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