]> git.itanic.dy.fi Git - linux-stable/blob - arch/mips/loongson32/common/platform.c
794c96c2a4cdd96cbaedb651b36a0421b09cbf37
[linux-stable] / arch / mips / loongson32 / common / platform.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2011-2016 Zhang, Keguang <keguang.zhang@gmail.com>
4  */
5
6 #include <linux/clk.h>
7 #include <linux/dma-mapping.h>
8 #include <linux/err.h>
9 #include <linux/mtd/partitions.h>
10 #include <linux/sizes.h>
11 #include <linux/phy.h>
12 #include <linux/serial_8250.h>
13 #include <linux/stmmac.h>
14 #include <linux/usb/ehci_pdriver.h>
15
16 #include <platform.h>
17 #include <loongson1.h>
18 #include <cpufreq.h>
19 #include <dma.h>
20 #include <nand.h>
21
22 /* 8250/16550 compatible UART */
23 #define LS1X_UART(_id)                                          \
24         {                                                       \
25                 .mapbase        = LS1X_UART ## _id ## _BASE,    \
26                 .irq            = LS1X_UART ## _id ## _IRQ,     \
27                 .iotype         = UPIO_MEM,                     \
28                 .flags          = UPF_IOREMAP | UPF_FIXED_TYPE, \
29                 .type           = PORT_16550A,                  \
30         }
31
32 static struct plat_serial8250_port ls1x_serial8250_pdata[] = {
33         LS1X_UART(0),
34         LS1X_UART(1),
35         LS1X_UART(2),
36         LS1X_UART(3),
37         {},
38 };
39
40 struct platform_device ls1x_uart_pdev = {
41         .name           = "serial8250",
42         .id             = PLAT8250_DEV_PLATFORM,
43         .dev            = {
44                 .platform_data = ls1x_serial8250_pdata,
45         },
46 };
47
48 void __init ls1x_serial_set_uartclk(struct platform_device *pdev)
49 {
50         struct clk *clk;
51         struct plat_serial8250_port *p;
52
53         clk = clk_get(&pdev->dev, pdev->name);
54         if (IS_ERR(clk)) {
55                 pr_err("unable to get %s clock, err=%ld",
56                        pdev->name, PTR_ERR(clk));
57                 return;
58         }
59         clk_prepare_enable(clk);
60
61         for (p = pdev->dev.platform_data; p->flags != 0; ++p)
62                 p->uartclk = clk_get_rate(clk);
63 }
64
65 /* CPUFreq */
66 static struct plat_ls1x_cpufreq ls1x_cpufreq_pdata = {
67         .clk_name       = "cpu_clk",
68         .osc_clk_name   = "osc_clk",
69         .max_freq       = 266 * 1000,
70         .min_freq       = 33 * 1000,
71 };
72
73 struct platform_device ls1x_cpufreq_pdev = {
74         .name           = "ls1x-cpufreq",
75         .dev            = {
76                 .platform_data = &ls1x_cpufreq_pdata,
77         },
78 };
79
80 /* Synopsys Ethernet GMAC */
81 static struct stmmac_mdio_bus_data ls1x_mdio_bus_data = {
82         .phy_mask       = 0,
83 };
84
85 static struct stmmac_dma_cfg ls1x_eth_dma_cfg = {
86         .pbl            = 1,
87 };
88
89 int ls1x_eth_mux_init(struct platform_device *pdev, void *priv)
90 {
91         struct plat_stmmacenet_data *plat_dat = NULL;
92         u32 val;
93
94         val = __raw_readl(LS1X_MUX_CTRL1);
95
96 #if defined(CONFIG_LOONGSON1_LS1B)
97         plat_dat = dev_get_platdata(&pdev->dev);
98         if (plat_dat->bus_id) {
99                 __raw_writel(__raw_readl(LS1X_MUX_CTRL0) | GMAC1_USE_UART1 |
100                              GMAC1_USE_UART0, LS1X_MUX_CTRL0);
101                 switch (plat_dat->interface) {
102                 case PHY_INTERFACE_MODE_RGMII:
103                         val &= ~(GMAC1_USE_TXCLK | GMAC1_USE_PWM23);
104                         break;
105                 case PHY_INTERFACE_MODE_MII:
106                         val |= (GMAC1_USE_TXCLK | GMAC1_USE_PWM23);
107                         break;
108                 default:
109                         pr_err("unsupported mii mode %d\n",
110                                plat_dat->interface);
111                         return -ENOTSUPP;
112                 }
113                 val &= ~GMAC1_SHUT;
114         } else {
115                 switch (plat_dat->interface) {
116                 case PHY_INTERFACE_MODE_RGMII:
117                         val &= ~(GMAC0_USE_TXCLK | GMAC0_USE_PWM01);
118                         break;
119                 case PHY_INTERFACE_MODE_MII:
120                         val |= (GMAC0_USE_TXCLK | GMAC0_USE_PWM01);
121                         break;
122                 default:
123                         pr_err("unsupported mii mode %d\n",
124                                plat_dat->interface);
125                         return -ENOTSUPP;
126                 }
127                 val &= ~GMAC0_SHUT;
128         }
129         __raw_writel(val, LS1X_MUX_CTRL1);
130 #elif defined(CONFIG_LOONGSON1_LS1C)
131         plat_dat = dev_get_platdata(&pdev->dev);
132
133         val &= ~PHY_INTF_SELI;
134         if (plat_dat->interface == PHY_INTERFACE_MODE_RMII)
135                 val |= 0x4 << PHY_INTF_SELI_SHIFT;
136         __raw_writel(val, LS1X_MUX_CTRL1);
137
138         val = __raw_readl(LS1X_MUX_CTRL0);
139         __raw_writel(val & (~GMAC_SHUT), LS1X_MUX_CTRL0);
140 #endif
141
142         return 0;
143 }
144
145 static struct plat_stmmacenet_data ls1x_eth0_pdata = {
146         .bus_id                 = 0,
147         .phy_addr               = -1,
148 #if defined(CONFIG_LOONGSON1_LS1B)
149         .interface              = PHY_INTERFACE_MODE_MII,
150 #elif defined(CONFIG_LOONGSON1_LS1C)
151         .interface              = PHY_INTERFACE_MODE_RMII,
152 #endif
153         .mdio_bus_data          = &ls1x_mdio_bus_data,
154         .dma_cfg                = &ls1x_eth_dma_cfg,
155         .has_gmac               = 1,
156         .tx_coe                 = 1,
157         .rx_queues_to_use       = 1,
158         .tx_queues_to_use       = 1,
159         .init                   = ls1x_eth_mux_init,
160 };
161
162 static struct resource ls1x_eth0_resources[] = {
163         [0] = {
164                 .start  = LS1X_GMAC0_BASE,
165                 .end    = LS1X_GMAC0_BASE + SZ_64K - 1,
166                 .flags  = IORESOURCE_MEM,
167         },
168         [1] = {
169                 .name   = "macirq",
170                 .start  = LS1X_GMAC0_IRQ,
171                 .flags  = IORESOURCE_IRQ,
172         },
173 };
174
175 struct platform_device ls1x_eth0_pdev = {
176         .name           = "stmmaceth",
177         .id             = 0,
178         .num_resources  = ARRAY_SIZE(ls1x_eth0_resources),
179         .resource       = ls1x_eth0_resources,
180         .dev            = {
181                 .platform_data = &ls1x_eth0_pdata,
182         },
183 };
184
185 #ifdef CONFIG_LOONGSON1_LS1B
186 static struct plat_stmmacenet_data ls1x_eth1_pdata = {
187         .bus_id                 = 1,
188         .phy_addr               = -1,
189         .interface              = PHY_INTERFACE_MODE_MII,
190         .mdio_bus_data          = &ls1x_mdio_bus_data,
191         .dma_cfg                = &ls1x_eth_dma_cfg,
192         .has_gmac               = 1,
193         .tx_coe                 = 1,
194         .rx_queues_to_use       = 1,
195         .tx_queues_to_use       = 1,
196         .init                   = ls1x_eth_mux_init,
197 };
198
199 static struct resource ls1x_eth1_resources[] = {
200         [0] = {
201                 .start  = LS1X_GMAC1_BASE,
202                 .end    = LS1X_GMAC1_BASE + SZ_64K - 1,
203                 .flags  = IORESOURCE_MEM,
204         },
205         [1] = {
206                 .name   = "macirq",
207                 .start  = LS1X_GMAC1_IRQ,
208                 .flags  = IORESOURCE_IRQ,
209         },
210 };
211
212 struct platform_device ls1x_eth1_pdev = {
213         .name           = "stmmaceth",
214         .id             = 1,
215         .num_resources  = ARRAY_SIZE(ls1x_eth1_resources),
216         .resource       = ls1x_eth1_resources,
217         .dev            = {
218                 .platform_data = &ls1x_eth1_pdata,
219         },
220 };
221 #endif  /* CONFIG_LOONGSON1_LS1B */
222
223 /* GPIO */
224 static struct resource ls1x_gpio0_resources[] = {
225         [0] = {
226                 .start  = LS1X_GPIO0_BASE,
227                 .end    = LS1X_GPIO0_BASE + SZ_4 - 1,
228                 .flags  = IORESOURCE_MEM,
229         },
230 };
231
232 struct platform_device ls1x_gpio0_pdev = {
233         .name           = "ls1x-gpio",
234         .id             = 0,
235         .num_resources  = ARRAY_SIZE(ls1x_gpio0_resources),
236         .resource       = ls1x_gpio0_resources,
237 };
238
239 static struct resource ls1x_gpio1_resources[] = {
240         [0] = {
241                 .start  = LS1X_GPIO1_BASE,
242                 .end    = LS1X_GPIO1_BASE + SZ_4 - 1,
243                 .flags  = IORESOURCE_MEM,
244         },
245 };
246
247 struct platform_device ls1x_gpio1_pdev = {
248         .name           = "ls1x-gpio",
249         .id             = 1,
250         .num_resources  = ARRAY_SIZE(ls1x_gpio1_resources),
251         .resource       = ls1x_gpio1_resources,
252 };
253
254 /* USB EHCI */
255 static u64 ls1x_ehci_dmamask = DMA_BIT_MASK(32);
256
257 static struct resource ls1x_ehci_resources[] = {
258         [0] = {
259                 .start  = LS1X_EHCI_BASE,
260                 .end    = LS1X_EHCI_BASE + SZ_32K - 1,
261                 .flags  = IORESOURCE_MEM,
262         },
263         [1] = {
264                 .start  = LS1X_EHCI_IRQ,
265                 .flags  = IORESOURCE_IRQ,
266         },
267 };
268
269 static struct usb_ehci_pdata ls1x_ehci_pdata = {
270 };
271
272 struct platform_device ls1x_ehci_pdev = {
273         .name           = "ehci-platform",
274         .id             = -1,
275         .num_resources  = ARRAY_SIZE(ls1x_ehci_resources),
276         .resource       = ls1x_ehci_resources,
277         .dev            = {
278                 .dma_mask = &ls1x_ehci_dmamask,
279                 .platform_data = &ls1x_ehci_pdata,
280         },
281 };
282
283 /* Real Time Clock */
284 void __init ls1x_rtc_set_extclk(struct platform_device *pdev)
285 {
286         u32 val = __raw_readl(LS1X_RTC_CTRL);
287
288         if (!(val & RTC_EXTCLK_OK))
289                 __raw_writel(val | RTC_EXTCLK_EN, LS1X_RTC_CTRL);
290 }
291
292 struct platform_device ls1x_rtc_pdev = {
293         .name           = "ls1x-rtc",
294         .id             = -1,
295 };
296
297 /* Watchdog */
298 static struct resource ls1x_wdt_resources[] = {
299         {
300                 .start  = LS1X_WDT_BASE,
301                 .end    = LS1X_WDT_BASE + SZ_16 - 1,
302                 .flags  = IORESOURCE_MEM,
303         },
304 };
305
306 struct platform_device ls1x_wdt_pdev = {
307         .name           = "ls1x-wdt",
308         .id             = -1,
309         .num_resources  = ARRAY_SIZE(ls1x_wdt_resources),
310         .resource       = ls1x_wdt_resources,
311 };