Merge branch 'misc.compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[sfrench/cifs-2.6.git] / arch / mips / loongson32 / common / platform.c
1 /*
2  * Copyright (c) 2011-2016 Zhang, Keguang <keguang.zhang@gmail.com>
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  */
9
10 #include <linux/clk.h>
11 #include <linux/dma-mapping.h>
12 #include <linux/err.h>
13 #include <linux/mtd/partitions.h>
14 #include <linux/sizes.h>
15 #include <linux/phy.h>
16 #include <linux/serial_8250.h>
17 #include <linux/stmmac.h>
18 #include <linux/usb/ehci_pdriver.h>
19
20 #include <platform.h>
21 #include <loongson1.h>
22 #include <cpufreq.h>
23 #include <dma.h>
24 #include <nand.h>
25
26 /* 8250/16550 compatible UART */
27 #define LS1X_UART(_id)                                          \
28         {                                                       \
29                 .mapbase        = LS1X_UART ## _id ## _BASE,    \
30                 .irq            = LS1X_UART ## _id ## _IRQ,     \
31                 .iotype         = UPIO_MEM,                     \
32                 .flags          = UPF_IOREMAP | UPF_FIXED_TYPE, \
33                 .type           = PORT_16550A,                  \
34         }
35
36 static struct plat_serial8250_port ls1x_serial8250_pdata[] = {
37         LS1X_UART(0),
38         LS1X_UART(1),
39         LS1X_UART(2),
40         LS1X_UART(3),
41         {},
42 };
43
44 struct platform_device ls1x_uart_pdev = {
45         .name           = "serial8250",
46         .id             = PLAT8250_DEV_PLATFORM,
47         .dev            = {
48                 .platform_data = ls1x_serial8250_pdata,
49         },
50 };
51
52 void __init ls1x_serial_set_uartclk(struct platform_device *pdev)
53 {
54         struct clk *clk;
55         struct plat_serial8250_port *p;
56
57         clk = clk_get(&pdev->dev, pdev->name);
58         if (IS_ERR(clk)) {
59                 pr_err("unable to get %s clock, err=%ld",
60                        pdev->name, PTR_ERR(clk));
61                 return;
62         }
63         clk_prepare_enable(clk);
64
65         for (p = pdev->dev.platform_data; p->flags != 0; ++p)
66                 p->uartclk = clk_get_rate(clk);
67 }
68
69 /* CPUFreq */
70 static struct plat_ls1x_cpufreq ls1x_cpufreq_pdata = {
71         .clk_name       = "cpu_clk",
72         .osc_clk_name   = "osc_clk",
73         .max_freq       = 266 * 1000,
74         .min_freq       = 33 * 1000,
75 };
76
77 struct platform_device ls1x_cpufreq_pdev = {
78         .name           = "ls1x-cpufreq",
79         .dev            = {
80                 .platform_data = &ls1x_cpufreq_pdata,
81         },
82 };
83
84 /* DMA */
85 static struct resource ls1x_dma_resources[] = {
86         [0] = {
87                 .start = LS1X_DMAC_BASE,
88                 .end = LS1X_DMAC_BASE + SZ_4 - 1,
89                 .flags = IORESOURCE_MEM,
90         },
91         [1] = {
92                 .start = LS1X_DMA0_IRQ,
93                 .end = LS1X_DMA0_IRQ,
94                 .flags = IORESOURCE_IRQ,
95         },
96         [2] = {
97                 .start = LS1X_DMA1_IRQ,
98                 .end = LS1X_DMA1_IRQ,
99                 .flags = IORESOURCE_IRQ,
100         },
101         [3] = {
102                 .start = LS1X_DMA2_IRQ,
103                 .end = LS1X_DMA2_IRQ,
104                 .flags = IORESOURCE_IRQ,
105         },
106 };
107
108 struct platform_device ls1x_dma_pdev = {
109         .name           = "ls1x-dma",
110         .id             = -1,
111         .num_resources  = ARRAY_SIZE(ls1x_dma_resources),
112         .resource       = ls1x_dma_resources,
113 };
114
115 void __init ls1x_dma_set_platdata(struct plat_ls1x_dma *pdata)
116 {
117         ls1x_dma_pdev.dev.platform_data = pdata;
118 }
119
120 /* Synopsys Ethernet GMAC */
121 static struct stmmac_mdio_bus_data ls1x_mdio_bus_data = {
122         .phy_mask       = 0,
123 };
124
125 static struct stmmac_dma_cfg ls1x_eth_dma_cfg = {
126         .pbl            = 1,
127 };
128
129 int ls1x_eth_mux_init(struct platform_device *pdev, void *priv)
130 {
131         struct plat_stmmacenet_data *plat_dat = NULL;
132         u32 val;
133
134         val = __raw_readl(LS1X_MUX_CTRL1);
135
136 #if defined(CONFIG_LOONGSON1_LS1B)
137         plat_dat = dev_get_platdata(&pdev->dev);
138         if (plat_dat->bus_id) {
139                 __raw_writel(__raw_readl(LS1X_MUX_CTRL0) | GMAC1_USE_UART1 |
140                              GMAC1_USE_UART0, LS1X_MUX_CTRL0);
141                 switch (plat_dat->interface) {
142                 case PHY_INTERFACE_MODE_RGMII:
143                         val &= ~(GMAC1_USE_TXCLK | GMAC1_USE_PWM23);
144                         break;
145                 case PHY_INTERFACE_MODE_MII:
146                         val |= (GMAC1_USE_TXCLK | GMAC1_USE_PWM23);
147                         break;
148                 default:
149                         pr_err("unsupported mii mode %d\n",
150                                plat_dat->interface);
151                         return -ENOTSUPP;
152                 }
153                 val &= ~GMAC1_SHUT;
154         } else {
155                 switch (plat_dat->interface) {
156                 case PHY_INTERFACE_MODE_RGMII:
157                         val &= ~(GMAC0_USE_TXCLK | GMAC0_USE_PWM01);
158                         break;
159                 case PHY_INTERFACE_MODE_MII:
160                         val |= (GMAC0_USE_TXCLK | GMAC0_USE_PWM01);
161                         break;
162                 default:
163                         pr_err("unsupported mii mode %d\n",
164                                plat_dat->interface);
165                         return -ENOTSUPP;
166                 }
167                 val &= ~GMAC0_SHUT;
168         }
169         __raw_writel(val, LS1X_MUX_CTRL1);
170 #elif defined(CONFIG_LOONGSON1_LS1C)
171         plat_dat = dev_get_platdata(&pdev->dev);
172
173         val &= ~PHY_INTF_SELI;
174         if (plat_dat->interface == PHY_INTERFACE_MODE_RMII)
175                 val |= 0x4 << PHY_INTF_SELI_SHIFT;
176         __raw_writel(val, LS1X_MUX_CTRL1);
177
178         val = __raw_readl(LS1X_MUX_CTRL0);
179         __raw_writel(val & (~GMAC_SHUT), LS1X_MUX_CTRL0);
180 #endif
181
182         return 0;
183 }
184
185 static struct plat_stmmacenet_data ls1x_eth0_pdata = {
186         .bus_id                 = 0,
187         .phy_addr               = -1,
188 #if defined(CONFIG_LOONGSON1_LS1B)
189         .interface              = PHY_INTERFACE_MODE_MII,
190 #elif defined(CONFIG_LOONGSON1_LS1C)
191         .interface              = PHY_INTERFACE_MODE_RMII,
192 #endif
193         .mdio_bus_data          = &ls1x_mdio_bus_data,
194         .dma_cfg                = &ls1x_eth_dma_cfg,
195         .has_gmac               = 1,
196         .tx_coe                 = 1,
197         .rx_queues_to_use       = 1,
198         .tx_queues_to_use       = 1,
199         .init                   = ls1x_eth_mux_init,
200 };
201
202 static struct resource ls1x_eth0_resources[] = {
203         [0] = {
204                 .start  = LS1X_GMAC0_BASE,
205                 .end    = LS1X_GMAC0_BASE + SZ_64K - 1,
206                 .flags  = IORESOURCE_MEM,
207         },
208         [1] = {
209                 .name   = "macirq",
210                 .start  = LS1X_GMAC0_IRQ,
211                 .flags  = IORESOURCE_IRQ,
212         },
213 };
214
215 struct platform_device ls1x_eth0_pdev = {
216         .name           = "stmmaceth",
217         .id             = 0,
218         .num_resources  = ARRAY_SIZE(ls1x_eth0_resources),
219         .resource       = ls1x_eth0_resources,
220         .dev            = {
221                 .platform_data = &ls1x_eth0_pdata,
222         },
223 };
224
225 #ifdef CONFIG_LOONGSON1_LS1B
226 static struct plat_stmmacenet_data ls1x_eth1_pdata = {
227         .bus_id                 = 1,
228         .phy_addr               = -1,
229         .interface              = PHY_INTERFACE_MODE_MII,
230         .mdio_bus_data          = &ls1x_mdio_bus_data,
231         .dma_cfg                = &ls1x_eth_dma_cfg,
232         .has_gmac               = 1,
233         .tx_coe                 = 1,
234         .rx_queues_to_use       = 1,
235         .tx_queues_to_use       = 1,
236         .init                   = ls1x_eth_mux_init,
237 };
238
239 static struct resource ls1x_eth1_resources[] = {
240         [0] = {
241                 .start  = LS1X_GMAC1_BASE,
242                 .end    = LS1X_GMAC1_BASE + SZ_64K - 1,
243                 .flags  = IORESOURCE_MEM,
244         },
245         [1] = {
246                 .name   = "macirq",
247                 .start  = LS1X_GMAC1_IRQ,
248                 .flags  = IORESOURCE_IRQ,
249         },
250 };
251
252 struct platform_device ls1x_eth1_pdev = {
253         .name           = "stmmaceth",
254         .id             = 1,
255         .num_resources  = ARRAY_SIZE(ls1x_eth1_resources),
256         .resource       = ls1x_eth1_resources,
257         .dev            = {
258                 .platform_data = &ls1x_eth1_pdata,
259         },
260 };
261 #endif  /* CONFIG_LOONGSON1_LS1B */
262
263 /* GPIO */
264 static struct resource ls1x_gpio0_resources[] = {
265         [0] = {
266                 .start  = LS1X_GPIO0_BASE,
267                 .end    = LS1X_GPIO0_BASE + SZ_4 - 1,
268                 .flags  = IORESOURCE_MEM,
269         },
270 };
271
272 struct platform_device ls1x_gpio0_pdev = {
273         .name           = "ls1x-gpio",
274         .id             = 0,
275         .num_resources  = ARRAY_SIZE(ls1x_gpio0_resources),
276         .resource       = ls1x_gpio0_resources,
277 };
278
279 static struct resource ls1x_gpio1_resources[] = {
280         [0] = {
281                 .start  = LS1X_GPIO1_BASE,
282                 .end    = LS1X_GPIO1_BASE + SZ_4 - 1,
283                 .flags  = IORESOURCE_MEM,
284         },
285 };
286
287 struct platform_device ls1x_gpio1_pdev = {
288         .name           = "ls1x-gpio",
289         .id             = 1,
290         .num_resources  = ARRAY_SIZE(ls1x_gpio1_resources),
291         .resource       = ls1x_gpio1_resources,
292 };
293
294 /* NAND Flash */
295 static struct resource ls1x_nand_resources[] = {
296         [0] = {
297                 .start  = LS1X_NAND_BASE,
298                 .end    = LS1X_NAND_BASE + SZ_32 - 1,
299                 .flags  = IORESOURCE_MEM,
300         },
301         [1] = {
302                 /* DMA channel 0 is dedicated to NAND */
303                 .start  = LS1X_DMA_CHANNEL0,
304                 .end    = LS1X_DMA_CHANNEL0,
305                 .flags  = IORESOURCE_DMA,
306         },
307 };
308
309 struct platform_device ls1x_nand_pdev = {
310         .name           = "ls1x-nand",
311         .id             = -1,
312         .num_resources  = ARRAY_SIZE(ls1x_nand_resources),
313         .resource       = ls1x_nand_resources,
314 };
315
316 void __init ls1x_nand_set_platdata(struct plat_ls1x_nand *pdata)
317 {
318         ls1x_nand_pdev.dev.platform_data = pdata;
319 }
320
321 /* USB EHCI */
322 static u64 ls1x_ehci_dmamask = DMA_BIT_MASK(32);
323
324 static struct resource ls1x_ehci_resources[] = {
325         [0] = {
326                 .start  = LS1X_EHCI_BASE,
327                 .end    = LS1X_EHCI_BASE + SZ_32K - 1,
328                 .flags  = IORESOURCE_MEM,
329         },
330         [1] = {
331                 .start  = LS1X_EHCI_IRQ,
332                 .flags  = IORESOURCE_IRQ,
333         },
334 };
335
336 static struct usb_ehci_pdata ls1x_ehci_pdata = {
337 };
338
339 struct platform_device ls1x_ehci_pdev = {
340         .name           = "ehci-platform",
341         .id             = -1,
342         .num_resources  = ARRAY_SIZE(ls1x_ehci_resources),
343         .resource       = ls1x_ehci_resources,
344         .dev            = {
345                 .dma_mask = &ls1x_ehci_dmamask,
346                 .platform_data = &ls1x_ehci_pdata,
347         },
348 };
349
350 /* Real Time Clock */
351 void __init ls1x_rtc_set_extclk(struct platform_device *pdev)
352 {
353         u32 val = __raw_readl(LS1X_RTC_CTRL);
354
355         if (!(val & RTC_EXTCLK_OK))
356                 __raw_writel(val | RTC_EXTCLK_EN, LS1X_RTC_CTRL);
357 }
358
359 struct platform_device ls1x_rtc_pdev = {
360         .name           = "ls1x-rtc",
361         .id             = -1,
362 };
363
364 /* Watchdog */
365 static struct resource ls1x_wdt_resources[] = {
366         {
367                 .start  = LS1X_WDT_BASE,
368                 .end    = LS1X_WDT_BASE + SZ_16 - 1,
369                 .flags  = IORESOURCE_MEM,
370         },
371 };
372
373 struct platform_device ls1x_wdt_pdev = {
374         .name           = "ls1x-wdt",
375         .id             = -1,
376         .num_resources  = ARRAY_SIZE(ls1x_wdt_resources),
377         .resource       = ls1x_wdt_resources,
378 };