xref: /linux/arch/mips/loongson32/common/platform.c (revision e58e871becec2d3b04ed91c0c16fe8deac9c9dfa)
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 	.init		= ls1x_eth_mux_init,
198 };
199 
200 static struct resource ls1x_eth0_resources[] = {
201 	[0] = {
202 		.start	= LS1X_GMAC0_BASE,
203 		.end	= LS1X_GMAC0_BASE + SZ_64K - 1,
204 		.flags	= IORESOURCE_MEM,
205 	},
206 	[1] = {
207 		.name	= "macirq",
208 		.start	= LS1X_GMAC0_IRQ,
209 		.flags	= IORESOURCE_IRQ,
210 	},
211 };
212 
213 struct platform_device ls1x_eth0_pdev = {
214 	.name		= "stmmaceth",
215 	.id		= 0,
216 	.num_resources	= ARRAY_SIZE(ls1x_eth0_resources),
217 	.resource	= ls1x_eth0_resources,
218 	.dev		= {
219 		.platform_data = &ls1x_eth0_pdata,
220 	},
221 };
222 
223 #ifdef CONFIG_LOONGSON1_LS1B
224 static struct plat_stmmacenet_data ls1x_eth1_pdata = {
225 	.bus_id		= 1,
226 	.phy_addr	= -1,
227 	.interface	= PHY_INTERFACE_MODE_MII,
228 	.mdio_bus_data	= &ls1x_mdio_bus_data,
229 	.dma_cfg	= &ls1x_eth_dma_cfg,
230 	.has_gmac	= 1,
231 	.tx_coe		= 1,
232 	.init		= ls1x_eth_mux_init,
233 };
234 
235 static struct resource ls1x_eth1_resources[] = {
236 	[0] = {
237 		.start	= LS1X_GMAC1_BASE,
238 		.end	= LS1X_GMAC1_BASE + SZ_64K - 1,
239 		.flags	= IORESOURCE_MEM,
240 	},
241 	[1] = {
242 		.name	= "macirq",
243 		.start	= LS1X_GMAC1_IRQ,
244 		.flags	= IORESOURCE_IRQ,
245 	},
246 };
247 
248 struct platform_device ls1x_eth1_pdev = {
249 	.name		= "stmmaceth",
250 	.id		= 1,
251 	.num_resources	= ARRAY_SIZE(ls1x_eth1_resources),
252 	.resource	= ls1x_eth1_resources,
253 	.dev		= {
254 		.platform_data = &ls1x_eth1_pdata,
255 	},
256 };
257 #endif	/* CONFIG_LOONGSON1_LS1B */
258 
259 /* GPIO */
260 static struct resource ls1x_gpio0_resources[] = {
261 	[0] = {
262 		.start	= LS1X_GPIO0_BASE,
263 		.end	= LS1X_GPIO0_BASE + SZ_4 - 1,
264 		.flags	= IORESOURCE_MEM,
265 	},
266 };
267 
268 struct platform_device ls1x_gpio0_pdev = {
269 	.name		= "ls1x-gpio",
270 	.id		= 0,
271 	.num_resources	= ARRAY_SIZE(ls1x_gpio0_resources),
272 	.resource	= ls1x_gpio0_resources,
273 };
274 
275 static struct resource ls1x_gpio1_resources[] = {
276 	[0] = {
277 		.start	= LS1X_GPIO1_BASE,
278 		.end	= LS1X_GPIO1_BASE + SZ_4 - 1,
279 		.flags	= IORESOURCE_MEM,
280 	},
281 };
282 
283 struct platform_device ls1x_gpio1_pdev = {
284 	.name		= "ls1x-gpio",
285 	.id		= 1,
286 	.num_resources	= ARRAY_SIZE(ls1x_gpio1_resources),
287 	.resource	= ls1x_gpio1_resources,
288 };
289 
290 /* NAND Flash */
291 static struct resource ls1x_nand_resources[] = {
292 	[0] = {
293 		.start	= LS1X_NAND_BASE,
294 		.end	= LS1X_NAND_BASE + SZ_32 - 1,
295 		.flags	= IORESOURCE_MEM,
296 	},
297 	[1] = {
298 		/* DMA channel 0 is dedicated to NAND */
299 		.start	= LS1X_DMA_CHANNEL0,
300 		.end	= LS1X_DMA_CHANNEL0,
301 		.flags	= IORESOURCE_DMA,
302 	},
303 };
304 
305 struct platform_device ls1x_nand_pdev = {
306 	.name		= "ls1x-nand",
307 	.id		= -1,
308 	.num_resources	= ARRAY_SIZE(ls1x_nand_resources),
309 	.resource	= ls1x_nand_resources,
310 };
311 
312 void __init ls1x_nand_set_platdata(struct plat_ls1x_nand *pdata)
313 {
314 	ls1x_nand_pdev.dev.platform_data = pdata;
315 }
316 
317 /* USB EHCI */
318 static u64 ls1x_ehci_dmamask = DMA_BIT_MASK(32);
319 
320 static struct resource ls1x_ehci_resources[] = {
321 	[0] = {
322 		.start	= LS1X_EHCI_BASE,
323 		.end	= LS1X_EHCI_BASE + SZ_32K - 1,
324 		.flags	= IORESOURCE_MEM,
325 	},
326 	[1] = {
327 		.start	= LS1X_EHCI_IRQ,
328 		.flags	= IORESOURCE_IRQ,
329 	},
330 };
331 
332 static struct usb_ehci_pdata ls1x_ehci_pdata = {
333 };
334 
335 struct platform_device ls1x_ehci_pdev = {
336 	.name		= "ehci-platform",
337 	.id		= -1,
338 	.num_resources	= ARRAY_SIZE(ls1x_ehci_resources),
339 	.resource	= ls1x_ehci_resources,
340 	.dev		= {
341 		.dma_mask = &ls1x_ehci_dmamask,
342 		.platform_data = &ls1x_ehci_pdata,
343 	},
344 };
345 
346 /* Real Time Clock */
347 void __init ls1x_rtc_set_extclk(struct platform_device *pdev)
348 {
349 	u32 val = __raw_readl(LS1X_RTC_CTRL);
350 
351 	if (!(val & RTC_EXTCLK_OK))
352 		__raw_writel(val | RTC_EXTCLK_EN, LS1X_RTC_CTRL);
353 }
354 
355 struct platform_device ls1x_rtc_pdev = {
356 	.name		= "ls1x-rtc",
357 	.id		= -1,
358 };
359 
360 /* Watchdog */
361 static struct resource ls1x_wdt_resources[] = {
362 	{
363 		.start	= LS1X_WDT_BASE,
364 		.end	= LS1X_WDT_BASE + SZ_16 - 1,
365 		.flags	= IORESOURCE_MEM,
366 	},
367 };
368 
369 struct platform_device ls1x_wdt_pdev = {
370 	.name		= "ls1x-wdt",
371 	.id		= -1,
372 	.num_resources	= ARRAY_SIZE(ls1x_wdt_resources),
373 	.resource	= ls1x_wdt_resources,
374 };
375