Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/mips/rb532/devices.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* RouterBoard 500 Platform devices
4
*
5
* Copyright (C) 2006 Felix Fietkau <[email protected]>
6
* Copyright (C) 2007 Florian Fainelli <[email protected]>
7
*/
8
#include <linux/kernel.h>
9
#include <linux/export.h>
10
#include <linux/init.h>
11
#include <linux/ctype.h>
12
#include <linux/string.h>
13
#include <linux/platform_device.h>
14
#include <linux/mtd/platnand.h>
15
#include <linux/mtd/mtd.h>
16
#include <linux/gpio.h>
17
#include <linux/gpio/machine.h>
18
#include <linux/gpio_keys.h>
19
#include <linux/input.h>
20
#include <linux/serial_8250.h>
21
22
#include <asm/bootinfo.h>
23
24
#include <asm/mach-rc32434/rc32434.h>
25
#include <asm/mach-rc32434/dma.h>
26
#include <asm/mach-rc32434/dma_v.h>
27
#include <asm/mach-rc32434/eth.h>
28
#include <asm/mach-rc32434/rb.h>
29
#include <asm/mach-rc32434/integ.h>
30
#include <asm/mach-rc32434/gpio.h>
31
#include <asm/mach-rc32434/irq.h>
32
33
#define ETH0_RX_DMA_ADDR (DMA0_BASE_ADDR + 0 * DMA_CHAN_OFFSET)
34
#define ETH0_TX_DMA_ADDR (DMA0_BASE_ADDR + 1 * DMA_CHAN_OFFSET)
35
36
extern unsigned int idt_cpu_freq;
37
38
static struct mpmc_device dev3;
39
40
void set_latch_u5(unsigned char or_mask, unsigned char nand_mask)
41
{
42
unsigned long flags;
43
44
spin_lock_irqsave(&dev3.lock, flags);
45
46
dev3.state = (dev3.state | or_mask) & ~nand_mask;
47
writeb(dev3.state, dev3.base);
48
49
spin_unlock_irqrestore(&dev3.lock, flags);
50
}
51
EXPORT_SYMBOL(set_latch_u5);
52
53
unsigned char get_latch_u5(void)
54
{
55
return dev3.state;
56
}
57
EXPORT_SYMBOL(get_latch_u5);
58
59
static struct resource korina_dev0_res[] = {
60
{
61
.name = "emac",
62
.start = ETH0_BASE_ADDR,
63
.end = ETH0_BASE_ADDR + sizeof(struct eth_regs),
64
.flags = IORESOURCE_MEM,
65
}, {
66
.name = "rx",
67
.start = ETH0_DMA_RX_IRQ,
68
.end = ETH0_DMA_RX_IRQ,
69
.flags = IORESOURCE_IRQ
70
}, {
71
.name = "tx",
72
.start = ETH0_DMA_TX_IRQ,
73
.end = ETH0_DMA_TX_IRQ,
74
.flags = IORESOURCE_IRQ
75
}, {
76
.name = "dma_rx",
77
.start = ETH0_RX_DMA_ADDR,
78
.end = ETH0_RX_DMA_ADDR + DMA_CHAN_OFFSET - 1,
79
.flags = IORESOURCE_MEM,
80
}, {
81
.name = "dma_tx",
82
.start = ETH0_TX_DMA_ADDR,
83
.end = ETH0_TX_DMA_ADDR + DMA_CHAN_OFFSET - 1,
84
.flags = IORESOURCE_MEM,
85
}
86
};
87
88
static struct korina_device korina_dev0_data = {
89
.name = "korina0",
90
.mac = {0xde, 0xca, 0xff, 0xc0, 0xff, 0xee}
91
};
92
93
static struct platform_device korina_dev0 = {
94
.id = -1,
95
.name = "korina",
96
.resource = korina_dev0_res,
97
.num_resources = ARRAY_SIZE(korina_dev0_res),
98
.dev = {
99
.platform_data = &korina_dev0_data.mac,
100
}
101
};
102
103
static struct resource cf_slot0_res[] = {
104
{
105
.name = "cf_membase",
106
.flags = IORESOURCE_MEM
107
}, {
108
.name = "cf_irq",
109
.start = (8 + 4 * 32 + CF_GPIO_NUM), /* 149 */
110
.end = (8 + 4 * 32 + CF_GPIO_NUM),
111
.flags = IORESOURCE_IRQ
112
}
113
};
114
115
static struct gpiod_lookup_table cf_slot0_gpio_table = {
116
.dev_id = "pata-rb532-cf",
117
.table = {
118
GPIO_LOOKUP("gpio0", CF_GPIO_NUM,
119
NULL, GPIO_ACTIVE_HIGH),
120
{ },
121
},
122
};
123
124
static struct platform_device cf_slot0 = {
125
.id = -1,
126
.name = "pata-rb532-cf",
127
.resource = cf_slot0_res,
128
.num_resources = ARRAY_SIZE(cf_slot0_res),
129
};
130
131
/* Resources and device for NAND */
132
static int rb532_dev_ready(struct nand_chip *chip)
133
{
134
return gpio_get_value(GPIO_RDY);
135
}
136
137
static void rb532_cmd_ctrl(struct nand_chip *chip, int cmd, unsigned int ctrl)
138
{
139
unsigned char orbits, nandbits;
140
141
if (ctrl & NAND_CTRL_CHANGE) {
142
orbits = (ctrl & NAND_CLE) << 1;
143
orbits |= (ctrl & NAND_ALE) >> 1;
144
145
nandbits = (~ctrl & NAND_CLE) << 1;
146
nandbits |= (~ctrl & NAND_ALE) >> 1;
147
148
set_latch_u5(orbits, nandbits);
149
}
150
if (cmd != NAND_CMD_NONE)
151
writeb(cmd, chip->legacy.IO_ADDR_W);
152
}
153
154
static struct resource nand_slot0_res[] = {
155
[0] = {
156
.name = "nand_membase",
157
.flags = IORESOURCE_MEM
158
}
159
};
160
161
static struct platform_nand_data rb532_nand_data = {
162
.ctrl.dev_ready = rb532_dev_ready,
163
.ctrl.cmd_ctrl = rb532_cmd_ctrl,
164
};
165
166
static struct platform_device nand_slot0 = {
167
.name = "gen_nand",
168
.id = -1,
169
.resource = nand_slot0_res,
170
.num_resources = ARRAY_SIZE(nand_slot0_res),
171
.dev.platform_data = &rb532_nand_data,
172
};
173
174
static struct mtd_partition rb532_partition_info[] = {
175
{
176
.name = "Routerboard NAND boot",
177
.offset = 0,
178
.size = 4 * 1024 * 1024,
179
}, {
180
.name = "rootfs",
181
.offset = MTDPART_OFS_NXTBLK,
182
.size = MTDPART_SIZ_FULL,
183
}
184
};
185
186
static struct platform_device rb532_led = {
187
.name = "rb532-led",
188
.id = -1,
189
};
190
191
static struct platform_device rb532_button = {
192
.name = "rb532-button",
193
.id = -1,
194
};
195
196
static struct resource rb532_wdt_res[] = {
197
{
198
.name = "rb532_wdt_res",
199
.start = INTEG0_BASE_ADDR,
200
.end = INTEG0_BASE_ADDR + sizeof(struct integ),
201
.flags = IORESOURCE_MEM,
202
}
203
};
204
205
static struct platform_device rb532_wdt = {
206
.name = "rc32434_wdt",
207
.id = -1,
208
.resource = rb532_wdt_res,
209
.num_resources = ARRAY_SIZE(rb532_wdt_res),
210
};
211
212
static struct plat_serial8250_port rb532_uart_res[] = {
213
{
214
.type = PORT_16550A,
215
.membase = (char *)KSEG1ADDR(REGBASE + UART0BASE),
216
.irq = UART0_IRQ,
217
.regshift = 2,
218
.iotype = UPIO_MEM,
219
.flags = UPF_BOOT_AUTOCONF,
220
},
221
{
222
.flags = 0,
223
}
224
};
225
226
static struct platform_device rb532_uart = {
227
.name = "serial8250",
228
.id = PLAT8250_DEV_PLATFORM,
229
.dev.platform_data = &rb532_uart_res,
230
};
231
232
static struct platform_device *rb532_devs[] = {
233
&korina_dev0,
234
&nand_slot0,
235
&cf_slot0,
236
&rb532_led,
237
&rb532_button,
238
&rb532_uart,
239
&rb532_wdt
240
};
241
242
/* NAND definitions */
243
#define NAND_CHIP_DELAY 25
244
245
static void __init rb532_nand_setup(void)
246
{
247
switch (mips_machtype) {
248
case MACH_MIKROTIK_RB532A:
249
set_latch_u5(LO_FOFF | LO_CEX,
250
LO_ULED | LO_ALE | LO_CLE | LO_WPX);
251
break;
252
default:
253
set_latch_u5(LO_WPX | LO_FOFF | LO_CEX,
254
LO_ULED | LO_ALE | LO_CLE);
255
break;
256
}
257
258
/* Setup NAND specific settings */
259
rb532_nand_data.chip.nr_chips = 1;
260
rb532_nand_data.chip.nr_partitions = ARRAY_SIZE(rb532_partition_info);
261
rb532_nand_data.chip.partitions = rb532_partition_info;
262
rb532_nand_data.chip.chip_delay = NAND_CHIP_DELAY;
263
}
264
265
266
static int __init plat_setup_devices(void)
267
{
268
/* Look for the CF card reader */
269
if (!readl(IDT434_REG_BASE + DEV1MASK))
270
rb532_devs[2] = NULL; /* disable cf_slot0 at index 2 */
271
else {
272
cf_slot0_res[0].start =
273
readl(IDT434_REG_BASE + DEV1BASE);
274
cf_slot0_res[0].end = cf_slot0_res[0].start + 0x1000;
275
}
276
277
/* Read the NAND resources from the device controller */
278
nand_slot0_res[0].start = readl(IDT434_REG_BASE + DEV2BASE);
279
nand_slot0_res[0].end = nand_slot0_res[0].start + 0x1000;
280
281
/* Read and map device controller 3 */
282
dev3.base = ioremap(readl(IDT434_REG_BASE + DEV3BASE), 1);
283
284
if (!dev3.base) {
285
printk(KERN_ERR "rb532: cannot remap device controller 3\n");
286
return -ENXIO;
287
}
288
289
/* Initialise the NAND device */
290
rb532_nand_setup();
291
292
/* set the uart clock to the current cpu frequency */
293
rb532_uart_res[0].uartclk = idt_cpu_freq;
294
295
gpiod_add_lookup_table(&cf_slot0_gpio_table);
296
return platform_add_devices(rb532_devs, ARRAY_SIZE(rb532_devs));
297
}
298
299
#ifdef CONFIG_NET
300
301
static int __init setup_kmac(char *s)
302
{
303
printk(KERN_INFO "korina mac = %s\n", s);
304
if (!mac_pton(s, korina_dev0_data.mac))
305
printk(KERN_ERR "Invalid mac\n");
306
return 1;
307
}
308
309
__setup("kmac=", setup_kmac);
310
311
#endif /* CONFIG_NET */
312
313
arch_initcall(plat_setup_devices);
314
315