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