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 
25 static const signed char gpio3_irq_mappings[] = {
26 	S6_INTC_GPIO(3),
27 	-1
28 };
29 
30 static const signed char uart_irq_mappings[] = {
31 	S6_INTC_UART(0),
32 	S6_INTC_UART(1),
33 	-1,
34 };
35 
36 static 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 
44 const 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 
50 static 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 
72 static 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 
prepare_phy_irq(int pin)113 static 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;
126 free:
127 	gpio_free(pin);
128 fail:
129 	return PHY_POLL;
130 }
131 
132 static 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 
device_init(void)151 static 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 }
161 arch_initcall_sync(device_init);
162