Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/mips/alchemy/board-mtx1.c
51706 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* MTX-1 platform devices registration (Au1500)
4
*
5
* Copyright (C) 2007-2009, Florian Fainelli <[email protected]>
6
*/
7
8
#include <linux/init.h>
9
#include <linux/interrupt.h>
10
#include <linux/kernel.h>
11
#include <linux/platform_device.h>
12
#include <linux/gpio/machine.h>
13
#include <linux/gpio/property.h>
14
#include <linux/input.h>
15
#include <linux/mtd/partitions.h>
16
#include <linux/mtd/physmap.h>
17
#include <mtd/mtd-abi.h>
18
#include <asm/bootinfo.h>
19
#include <asm/reboot.h>
20
#include <asm/setup.h>
21
#include <asm/mach-au1x00/au1000.h>
22
#include <asm/mach-au1x00/gpio-au1000.h>
23
#include <asm/mach-au1x00/au1xxx_eth.h>
24
#include <prom.h>
25
26
const char *get_system_type(void)
27
{
28
return "MTX-1";
29
}
30
31
void prom_putchar(char c)
32
{
33
alchemy_uart_putchar(AU1000_UART0_PHYS_ADDR, c);
34
}
35
36
static void mtx1_reset(char *c)
37
{
38
/* Jump to the reset vector */
39
__asm__ __volatile__("jr\t%0" : : "r"(0xbfc00000));
40
}
41
42
static void mtx1_power_off(void)
43
{
44
while (1)
45
asm volatile (
46
" .set mips32 \n"
47
" wait \n"
48
" .set mips0 \n");
49
}
50
51
void __init board_setup(void)
52
{
53
#if IS_ENABLED(CONFIG_USB_OHCI_HCD)
54
/* Enable USB power switch */
55
alchemy_gpio_direction_output(204, 0);
56
#endif /* IS_ENABLED(CONFIG_USB_OHCI_HCD) */
57
58
/* Initialize sys_pinfunc */
59
alchemy_wrsys(SYS_PF_NI2, AU1000_SYS_PINFUNC);
60
61
/* Initialize GPIO */
62
alchemy_wrsys(~0, AU1000_SYS_TRIOUTCLR);
63
alchemy_gpio_direction_output(0, 0); /* Disable M66EN (PCI 66MHz) */
64
alchemy_gpio_direction_output(3, 1); /* Disable PCI CLKRUN# */
65
alchemy_gpio_direction_output(1, 1); /* Enable EXT_IO3 */
66
alchemy_gpio_direction_output(5, 0); /* Disable eth PHY TX_ER */
67
68
/* Enable LED and set it to green */
69
alchemy_gpio_direction_output(211, 1); /* green on */
70
alchemy_gpio_direction_output(212, 0); /* red off */
71
72
pm_power_off = mtx1_power_off;
73
_machine_halt = mtx1_power_off;
74
_machine_restart = mtx1_reset;
75
76
printk(KERN_INFO "4G Systems MTX-1 Board\n");
77
}
78
79
/******************************************************************************/
80
81
static const struct software_node mtx1_gpiochip_node = {
82
.name = "alchemy-gpio2",
83
};
84
85
static const struct software_node mtx1_gpio_keys_node = {
86
.name = "mtx1-gpio-keys",
87
};
88
89
static const struct property_entry mtx1_button_props[] = {
90
PROPERTY_ENTRY_U32("linux,code", BTN_0),
91
PROPERTY_ENTRY_GPIO("gpios", &mtx1_gpiochip_node, 7, GPIO_ACTIVE_HIGH),
92
PROPERTY_ENTRY_STRING("label", "System button"),
93
{ }
94
};
95
96
static const struct software_node mtx1_button_node = {
97
.parent = &mtx1_gpio_keys_node,
98
.properties = mtx1_button_props,
99
};
100
101
static const struct software_node *mtx1_gpio_keys_swnodes[] __initconst = {
102
&mtx1_gpio_keys_node,
103
&mtx1_button_node,
104
NULL
105
};
106
107
static void __init mtx1_keys_init(void)
108
{
109
struct platform_device_info keys_info = {
110
.name = "gpio-keys",
111
.id = PLATFORM_DEVID_NONE,
112
};
113
struct platform_device *pd;
114
int err;
115
116
err = software_node_register_node_group(mtx1_gpio_keys_swnodes);
117
if (err) {
118
pr_err("failed to register gpio-keys software nodes: %d\n", err);
119
return;
120
}
121
122
keys_info.fwnode = software_node_fwnode(&mtx1_gpio_keys_node);
123
124
pd = platform_device_register_full(&keys_info);
125
err = PTR_ERR_OR_ZERO(pd);
126
if (err)
127
pr_err("failed to create gpio-keys device: %d\n", err);
128
}
129
130
/* Global number 215 is offset 15 on Alchemy GPIO 2 */
131
static const struct property_entry mtx1_wdt_props[] = {
132
PROPERTY_ENTRY_GPIO("gpios", &mtx1_gpiochip_node, 15, GPIO_ACTIVE_HIGH),
133
{ }
134
};
135
136
static struct platform_device_info mtx1_wdt_info __initconst = {
137
.name = "mtx1-wdt",
138
.id = 0,
139
.properties = mtx1_wdt_props,
140
};
141
142
static void __init mtx1_wdt_init(void)
143
{
144
struct platform_device *pd;
145
int err;
146
147
pd = platform_device_register_full(&mtx1_wdt_info);
148
err = PTR_ERR_OR_ZERO(pd);
149
if (err)
150
pr_err("failed to create gpio-keys device: %d\n", err);
151
}
152
153
static const struct software_node mtx1_gpio_leds_node = {
154
.name = "mtx1-leds",
155
};
156
157
static const struct property_entry mtx1_green_led_props[] = {
158
PROPERTY_ENTRY_GPIO("gpios", &mtx1_gpiochip_node, 11, GPIO_ACTIVE_HIGH),
159
{ }
160
};
161
162
static const struct software_node mtx1_green_led_node = {
163
.name = "mtx1:green",
164
.parent = &mtx1_gpio_leds_node,
165
.properties = mtx1_green_led_props,
166
};
167
168
static const struct property_entry mtx1_red_led_props[] = {
169
PROPERTY_ENTRY_GPIO("gpios", &mtx1_gpiochip_node, 12, GPIO_ACTIVE_HIGH),
170
{ }
171
};
172
173
static const struct software_node mtx1_red_led_node = {
174
.name = "mtx1:red",
175
.parent = &mtx1_gpio_leds_node,
176
.properties = mtx1_red_led_props,
177
};
178
179
static const struct software_node *mtx1_gpio_leds_swnodes[] = {
180
&mtx1_gpio_leds_node,
181
&mtx1_green_led_node,
182
&mtx1_red_led_node,
183
NULL
184
};
185
186
static void __init mtx1_leds_init(void)
187
{
188
struct platform_device_info led_info = {
189
.name = "leds-gpio",
190
.id = PLATFORM_DEVID_NONE,
191
};
192
struct platform_device *led_dev;
193
int err;
194
195
err = software_node_register_node_group(mtx1_gpio_leds_swnodes);
196
if (err) {
197
pr_err("failed to register LED software nodes: %d\n", err);
198
return;
199
}
200
201
led_info.fwnode = software_node_fwnode(&mtx1_gpio_leds_node);
202
203
led_dev = platform_device_register_full(&led_info);
204
err = PTR_ERR_OR_ZERO(led_dev);
205
if (err)
206
pr_err("failed to create LED device: %d\n", err);
207
}
208
209
static struct mtd_partition mtx1_mtd_partitions[] = {
210
{
211
.name = "filesystem",
212
.size = 0x01C00000,
213
.offset = 0,
214
},
215
{
216
.name = "yamon",
217
.size = 0x00100000,
218
.offset = MTDPART_OFS_APPEND,
219
.mask_flags = MTD_WRITEABLE,
220
},
221
{
222
.name = "kernel",
223
.size = 0x002c0000,
224
.offset = MTDPART_OFS_APPEND,
225
},
226
{
227
.name = "yamon env",
228
.size = 0x00040000,
229
.offset = MTDPART_OFS_APPEND,
230
},
231
};
232
233
static struct physmap_flash_data mtx1_flash_data = {
234
.width = 4,
235
.nr_parts = 4,
236
.parts = mtx1_mtd_partitions,
237
};
238
239
static struct resource mtx1_mtd_resource = {
240
.start = 0x1e000000,
241
.end = 0x1fffffff,
242
.flags = IORESOURCE_MEM,
243
};
244
245
static struct platform_device mtx1_mtd = {
246
.name = "physmap-flash",
247
.dev = {
248
.platform_data = &mtx1_flash_data,
249
},
250
.num_resources = 1,
251
.resource = &mtx1_mtd_resource,
252
};
253
254
static struct resource alchemy_pci_host_res[] = {
255
[0] = {
256
.start = AU1500_PCI_PHYS_ADDR,
257
.end = AU1500_PCI_PHYS_ADDR + 0xfff,
258
.flags = IORESOURCE_MEM,
259
},
260
};
261
262
static int mtx1_pci_idsel(unsigned int devsel, int assert)
263
{
264
/* This function is only necessary to support a proprietary Cardbus
265
* adapter on the mtx-1 "singleboard" variant. It triggers a custom
266
* logic chip connected to EXT_IO3 (GPIO1) to suppress IDSEL signals.
267
*/
268
udelay(1);
269
270
if (assert && devsel != 0)
271
/* Suppress signal to Cardbus */
272
alchemy_gpio_set_value(1, 0); /* set EXT_IO3 OFF */
273
else
274
alchemy_gpio_set_value(1, 1); /* set EXT_IO3 ON */
275
276
udelay(1);
277
return 1;
278
}
279
280
static const char mtx1_irqtab[][5] = {
281
[0] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTA, 0xff, 0xff }, /* IDSEL 00 - AdapterA-Slot0 (top) */
282
[1] = { -1, AU1500_PCI_INTB, AU1500_PCI_INTA, 0xff, 0xff }, /* IDSEL 01 - AdapterA-Slot1 (bottom) */
283
[2] = { -1, AU1500_PCI_INTC, AU1500_PCI_INTD, 0xff, 0xff }, /* IDSEL 02 - AdapterB-Slot0 (top) */
284
[3] = { -1, AU1500_PCI_INTD, AU1500_PCI_INTC, 0xff, 0xff }, /* IDSEL 03 - AdapterB-Slot1 (bottom) */
285
[4] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTB, 0xff, 0xff }, /* IDSEL 04 - AdapterC-Slot0 (top) */
286
[5] = { -1, AU1500_PCI_INTB, AU1500_PCI_INTA, 0xff, 0xff }, /* IDSEL 05 - AdapterC-Slot1 (bottom) */
287
[6] = { -1, AU1500_PCI_INTC, AU1500_PCI_INTD, 0xff, 0xff }, /* IDSEL 06 - AdapterD-Slot0 (top) */
288
[7] = { -1, AU1500_PCI_INTD, AU1500_PCI_INTC, 0xff, 0xff }, /* IDSEL 07 - AdapterD-Slot1 (bottom) */
289
};
290
291
static int mtx1_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
292
{
293
return mtx1_irqtab[slot][pin];
294
}
295
296
static struct alchemy_pci_platdata mtx1_pci_pd = {
297
.board_map_irq = mtx1_map_pci_irq,
298
.board_pci_idsel = mtx1_pci_idsel,
299
.pci_cfg_set = PCI_CONFIG_AEN | PCI_CONFIG_R2H | PCI_CONFIG_R1H |
300
PCI_CONFIG_CH |
301
#if defined(__MIPSEB__)
302
PCI_CONFIG_SIC_HWA_DAT | PCI_CONFIG_SM,
303
#else
304
0,
305
#endif
306
};
307
308
static struct platform_device mtx1_pci_host = {
309
.dev.platform_data = &mtx1_pci_pd,
310
.name = "alchemy-pci",
311
.id = 0,
312
.num_resources = ARRAY_SIZE(alchemy_pci_host_res),
313
.resource = alchemy_pci_host_res,
314
};
315
316
static struct platform_device *mtx1_devs[] __initdata = {
317
&mtx1_pci_host,
318
&mtx1_mtd,
319
};
320
321
static struct au1000_eth_platform_data mtx1_au1000_eth0_pdata = {
322
.phy_search_highest_addr = 1,
323
.phy1_search_mac0 = 1,
324
};
325
326
static int __init mtx1_register_devices(void)
327
{
328
int rc;
329
330
irq_set_irq_type(AU1500_GPIO204_INT, IRQ_TYPE_LEVEL_HIGH);
331
irq_set_irq_type(AU1500_GPIO201_INT, IRQ_TYPE_LEVEL_LOW);
332
irq_set_irq_type(AU1500_GPIO202_INT, IRQ_TYPE_LEVEL_LOW);
333
irq_set_irq_type(AU1500_GPIO203_INT, IRQ_TYPE_LEVEL_LOW);
334
irq_set_irq_type(AU1500_GPIO205_INT, IRQ_TYPE_LEVEL_LOW);
335
336
au1xxx_override_eth_cfg(0, &mtx1_au1000_eth0_pdata);
337
338
rc = software_node_register(&mtx1_gpiochip_node);
339
if (rc)
340
return rc;
341
342
rc = platform_add_devices(mtx1_devs, ARRAY_SIZE(mtx1_devs));
343
if (rc)
344
return rc;
345
346
mtx1_leds_init();
347
mtx1_wdt_init();
348
mtx1_keys_init();
349
350
return 0;
351
}
352
arch_initcall(mtx1_register_devices);
353
354