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