]> git.karo-electronics.de Git - karo-tx-linux.git/blob - arch/mips/mti-sead3/sead3-platform.c
d6be0298056a3341f8a5fc95d7a7df6934b57317
[karo-tx-linux.git] / arch / mips / mti-sead3 / sead3-platform.c
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (C) 2012 MIPS Technologies, Inc.  All rights reserved.
7  */
8 #include <linux/dma-mapping.h>
9 #include <linux/init.h>
10 #include <linux/irq.h>
11 #include <linux/irqchip/mips-gic.h>
12 #include <linux/irqdomain.h>
13 #include <linux/leds.h>
14 #include <linux/mtd/physmap.h>
15 #include <linux/of.h>
16 #include <linux/platform_device.h>
17 #include <linux/serial_8250.h>
18 #include <linux/smsc911x.h>
19
20 #include <asm/mips-boards/sead3int.h>
21
22 #define UART(base)                                                      \
23 {                                                                       \
24         .mapbase        = base,                                         \
25         .irq            = -1,                                           \
26         .uartclk        = 14745600,                                     \
27         .iotype         = UPIO_MEM32,                                   \
28         .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, \
29         .regshift       = 2,                                            \
30 }
31
32 static struct plat_serial8250_port uart8250_data[] = {
33         UART(0x1f000900),   /* ttyS0 = USB   */
34         UART(0x1f000800),   /* ttyS1 = RS232 */
35         { },
36 };
37
38 static struct platform_device uart8250_device = {
39         .name                   = "serial8250",
40         .id                     = PLAT8250_DEV_PLATFORM2,
41         .dev                    = {
42                 .platform_data  = uart8250_data,
43         },
44 };
45
46 static struct smsc911x_platform_config sead3_smsc911x_data = {
47         .irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
48         .irq_type       = SMSC911X_IRQ_TYPE_PUSH_PULL,
49         .flags          = SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS,
50         .phy_interface  = PHY_INTERFACE_MODE_MII,
51 };
52
53 static struct resource sead3_net_resources[] = {
54         {
55                 .start                  = 0x1f010000,
56                 .end                    = 0x1f01ffff,
57                 .flags                  = IORESOURCE_MEM
58         }, {
59                 .flags                  = IORESOURCE_IRQ
60         }
61 };
62
63 static struct platform_device sead3_net_device = {
64         .name                   = "smsc911x",
65         .id                     = 0,
66         .dev                    = {
67                 .platform_data  = &sead3_smsc911x_data,
68         },
69         .num_resources          = ARRAY_SIZE(sead3_net_resources),
70         .resource               = sead3_net_resources
71 };
72
73 static struct mtd_partition sead3_mtd_partitions[] = {
74         {
75                 .name =         "User FS",
76                 .offset =       0x00000000,
77                 .size =         0x01fc0000,
78         }, {
79                 .name =         "Board Config",
80                 .offset =       0x01fc0000,
81                 .size =         0x00040000,
82                 .mask_flags =   MTD_WRITEABLE
83         },
84 };
85
86 static struct physmap_flash_data sead3_flash_data = {
87         .width          = 4,
88         .nr_parts       = ARRAY_SIZE(sead3_mtd_partitions),
89         .parts          = sead3_mtd_partitions
90 };
91
92 static struct resource sead3_flash_resource = {
93         .start          = 0x1c000000,
94         .end            = 0x1dffffff,
95         .flags          = IORESOURCE_MEM
96 };
97
98 static struct platform_device sead3_flash = {
99         .name           = "physmap-flash",
100         .id             = 0,
101         .dev            = {
102                 .platform_data  = &sead3_flash_data,
103         },
104         .num_resources  = 1,
105         .resource       = &sead3_flash_resource,
106 };
107
108 #define LEDFLAGS(bits, shift)           \
109         ((bits << 8) | (shift << 8))
110
111 #define LEDBITS(id, shift, bits)        \
112         .name = id #shift,              \
113         .flags = LEDFLAGS(bits, shift)
114
115 static struct led_info led_data_info[] = {
116         { LEDBITS("bit", 0, 1) },
117         { LEDBITS("bit", 1, 1) },
118         { LEDBITS("bit", 2, 1) },
119         { LEDBITS("bit", 3, 1) },
120         { LEDBITS("bit", 4, 1) },
121         { LEDBITS("bit", 5, 1) },
122         { LEDBITS("bit", 6, 1) },
123         { LEDBITS("bit", 7, 1) },
124         { LEDBITS("all", 0, 8) },
125 };
126
127 static struct led_platform_data led_data = {
128         .num_leds       = ARRAY_SIZE(led_data_info),
129         .leds           = led_data_info
130 };
131
132 static struct resource pled_resources[] = {
133         {
134                 .start  = 0x1f000210,
135                 .end    = 0x1f000217,
136                 .flags  = IORESOURCE_MEM
137         }
138 };
139
140 static struct platform_device pled_device = {
141         .name                   = "sead3::pled",
142         .id                     = 0,
143         .dev                    = {
144                 .platform_data  = &led_data,
145         },
146         .num_resources          = ARRAY_SIZE(pled_resources),
147         .resource               = pled_resources
148 };
149
150
151 static struct resource fled_resources[] = {
152         {
153                 .start                  = 0x1f000218,
154                 .end                    = 0x1f00021f,
155                 .flags                  = IORESOURCE_MEM
156         }
157 };
158
159 static struct platform_device fled_device = {
160         .name                   = "sead3::fled",
161         .id                     = 0,
162         .dev                    = {
163                 .platform_data  = &led_data,
164         },
165         .num_resources          = ARRAY_SIZE(fled_resources),
166         .resource               = fled_resources
167 };
168
169 static struct platform_device sead3_led_device = {
170         .name   = "sead3-led",
171         .id     = -1,
172 };
173
174 static struct resource ehci_resources[] = {
175         {
176                 .start                  = 0x1b200000,
177                 .end                    = 0x1b200fff,
178                 .flags                  = IORESOURCE_MEM
179         }, {
180                 .flags                  = IORESOURCE_IRQ
181         }
182 };
183
184 static u64 sead3_usbdev_dma_mask = DMA_BIT_MASK(32);
185
186 static struct platform_device ehci_device = {
187         .name           = "sead3-ehci",
188         .id             = 0,
189         .dev            = {
190                 .dma_mask               = &sead3_usbdev_dma_mask,
191                 .coherent_dma_mask      = DMA_BIT_MASK(32)
192         },
193         .num_resources  = ARRAY_SIZE(ehci_resources),
194         .resource       = ehci_resources
195 };
196
197 static struct platform_device *sead3_platform_devices[] __initdata = {
198         &uart8250_device,
199         &sead3_flash,
200         &pled_device,
201         &fled_device,
202         &sead3_led_device,
203         &ehci_device,
204         &sead3_net_device,
205 };
206
207 static int __init sead3_platforms_device_init(void)
208 {
209         const char *intc_compat;
210         struct device_node *node;
211         struct irq_domain *irqd;
212
213         if (gic_present)
214                 intc_compat = "mti,gic";
215         else
216                 intc_compat = "mti,cpu-interrupt-controller";
217
218         node = of_find_compatible_node(NULL, NULL, intc_compat);
219         if (!node) {
220                 pr_err("unable to find interrupt controller DT node\n");
221                 return -ENODEV;
222         }
223
224         irqd = irq_find_host(node);
225         if (!irqd) {
226                 pr_err("unable to find interrupt controller IRQ domain\n");
227                 return -ENODEV;
228         }
229
230         if (gic_present) {
231                 uart8250_data[0].irq = irq_create_mapping(irqd, GIC_INT_UART0);
232                 uart8250_data[1].irq = irq_create_mapping(irqd, GIC_INT_UART1);
233                 ehci_resources[1].start =
234                         irq_create_mapping(irqd, GIC_INT_EHCI);
235                 sead3_net_resources[1].start =
236                         irq_create_mapping(irqd, GIC_INT_NET);
237         } else {
238                 uart8250_data[0].irq = irq_create_mapping(irqd, CPU_INT_UART0);
239                 uart8250_data[1].irq = irq_create_mapping(irqd, CPU_INT_UART1);
240                 ehci_resources[1].start =
241                         irq_create_mapping(irqd, CPU_INT_EHCI);
242                 sead3_net_resources[1].start =
243                         irq_create_mapping(irqd, CPU_INT_NET);
244         }
245
246         return platform_add_devices(sead3_platform_devices,
247                                     ARRAY_SIZE(sead3_platform_devices));
248 }
249
250 device_initcall(sead3_platforms_device_init);