1/*
2 * s6105 platform devices
3 *
4 * Copyright (c) 2009 emlix GmbH
5 */
6
7#include <linux/kernel.h>
8#include <linux/gpio.h>
9#include <linux/init.h>
10#include <linux/irq.h>
11#include <linux/phy.h>
12#include <linux/platform_device.h>
13#include <linux/serial.h>
14#include <linux/serial_8250.h>
15
16#include <variant/hardware.h>
17#include <variant/dmac.h>
18
19#include <platform/gpio.h>
20
21#define GPIO3_INTNUM		3
22#define UART_INTNUM		4
23#define GMAC_INTNUM		5
24
25static const signed char gpio3_irq_mappings[] = {
26	S6_INTC_GPIO(3),
27	-1
28};
29
30static const signed char uart_irq_mappings[] = {
31	S6_INTC_UART(0),
32	S6_INTC_UART(1),
33	-1,
34};
35
36static const signed char gmac_irq_mappings[] = {
37	S6_INTC_GMAC_STAT,
38	S6_INTC_GMAC_ERR,
39	S6_INTC_DMA_HOSTTERMCNT(0),
40	S6_INTC_DMA_HOSTTERMCNT(1),
41	-1
42};
43
44const signed char *platform_irq_mappings[NR_IRQS] = {
45	[GPIO3_INTNUM] = gpio3_irq_mappings,
46	[UART_INTNUM] = uart_irq_mappings,
47	[GMAC_INTNUM] = gmac_irq_mappings,
48};
49
50static struct plat_serial8250_port serial_platform_data[] = {
51	{
52		.membase = (void *)S6_REG_UART + 0x0000,
53		.mapbase = S6_REG_UART + 0x0000,
54		.irq = UART_INTNUM,
55		.uartclk = S6_SCLK,
56		.regshift = 2,
57		.iotype = SERIAL_IO_MEM,
58		.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST,
59	},
60	{
61		.membase = (void *)S6_REG_UART + 0x1000,
62		.mapbase = S6_REG_UART + 0x1000,
63		.irq = UART_INTNUM,
64		.uartclk = S6_SCLK,
65		.regshift = 2,
66		.iotype = SERIAL_IO_MEM,
67		.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST,
68	},
69	{ },
70};
71
72static struct resource s6_gmac_resource[] = {
73	{
74		.name   = "mem",
75		.start  = (resource_size_t)S6_REG_GMAC,
76		.end    = (resource_size_t)S6_REG_GMAC + 0x10000 - 1,
77		.flags  = IORESOURCE_MEM,
78	},
79	{
80		.name   = "dma",
81		.start  = (resource_size_t)
82			DMA_CHNL(S6_REG_HIFDMA, S6_HIFDMA_GMACTX),
83		.end    = (resource_size_t)
84			DMA_CHNL(S6_REG_HIFDMA, S6_HIFDMA_GMACTX) + 0x100 - 1,
85		.flags  = IORESOURCE_DMA,
86	},
87	{
88		.name   = "dma",
89		.start  = (resource_size_t)
90			DMA_CHNL(S6_REG_HIFDMA, S6_HIFDMA_GMACRX),
91		.end    = (resource_size_t)
92			DMA_CHNL(S6_REG_HIFDMA, S6_HIFDMA_GMACRX) + 0x100 - 1,
93		.flags  = IORESOURCE_DMA,
94	},
95	{
96		.name   = "io",
97		.start  = (resource_size_t)S6_MEM_GMAC,
98		.end    = (resource_size_t)S6_MEM_GMAC + 0x2000000 - 1,
99		.flags  = IORESOURCE_IO,
100	},
101	{
102		.name   = "irq",
103		.start  = (resource_size_t)GMAC_INTNUM,
104		.flags  = IORESOURCE_IRQ,
105	},
106	{
107		.name   = "irq",
108		.start  = (resource_size_t)PHY_POLL,
109		.flags  = IORESOURCE_IRQ,
110	},
111};
112
113static int __init prepare_phy_irq(int pin)
114{
115	int irq;
116	if (gpio_request(pin, "s6gmac_phy") < 0)
117		goto fail;
118	if (gpio_direction_input(pin) < 0)
119		goto free;
120	irq = gpio_to_irq(pin);
121	if (irq < 0)
122		goto free;
123	if (irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW) < 0)
124		goto free;
125	return irq;
126free:
127	gpio_free(pin);
128fail:
129	return PHY_POLL;
130}
131
132static struct platform_device platform_devices[] = {
133	{
134		.name = "serial8250",
135		.id = PLAT8250_DEV_PLATFORM,
136		.dev = {
137			.platform_data = serial_platform_data,
138		},
139	},
140	{
141		.name = "s6gmac",
142		.id = 0,
143		.resource = s6_gmac_resource,
144		.num_resources = ARRAY_SIZE(s6_gmac_resource),
145	},
146	{
147		I2C_BOARD_INFO("m41t62", S6I2C_ADDR_M41T62),
148	},
149};
150
151static int __init device_init(void)
152{
153	int i;
154
155	s6_gmac_resource[5].start = prepare_phy_irq(GPIO_PHY_IRQ);
156
157	for (i = 0; i < ARRAY_SIZE(platform_devices); i++)
158		platform_device_register(&platform_devices[i]);
159	return 0;
160}
161arch_initcall_sync(device_init);
162