xref: /linux/arch/mips/loongson32/common/platform.c (revision bd628c1bed7902ec1f24ba0fe70758949146abbe)
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 };
379