Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/mips/loongson32/common/platform.c
26481 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Copyright (c) 2011-2016 Zhang, Keguang <[email protected]>
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
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
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
287