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