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