Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/mips/alchemy/devboards/db1000.c
26481 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* DBAu1000/1500/1100 PBAu1100/1500 board support
4
*
5
* Copyright 2000, 2008 MontaVista Software Inc.
6
* Author: MontaVista Software, Inc. <[email protected]>
7
*/
8
9
#include <linux/clk.h>
10
#include <linux/dma-mapping.h>
11
#include <linux/gpio.h>
12
#include <linux/gpio/machine.h>
13
#include <linux/gpio/property.h>
14
#include <linux/init.h>
15
#include <linux/interrupt.h>
16
#include <linux/leds.h>
17
#include <linux/mmc/host.h>
18
#include <linux/platform_device.h>
19
#include <linux/property.h>
20
#include <linux/pm.h>
21
#include <linux/spi/spi.h>
22
#include <linux/spi/spi_gpio.h>
23
#include <asm/mach-au1x00/au1000.h>
24
#include <asm/mach-au1x00/gpio-au1000.h>
25
#include <asm/mach-au1x00/au1000_dma.h>
26
#include <asm/mach-au1x00/au1100_mmc.h>
27
#include <asm/mach-db1x00/bcsr.h>
28
#include <asm/reboot.h>
29
#include <prom.h>
30
#include "platform.h"
31
32
#define F_SWAPPED (bcsr_read(BCSR_STATUS) & BCSR_STATUS_DB1000_SWAPBOOT)
33
34
const char *get_system_type(void);
35
36
int __init db1000_board_setup(void)
37
{
38
/* initialize board register space */
39
bcsr_init(DB1000_BCSR_PHYS_ADDR,
40
DB1000_BCSR_PHYS_ADDR + DB1000_BCSR_HEXLED_OFS);
41
42
switch (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI))) {
43
case BCSR_WHOAMI_DB1000:
44
case BCSR_WHOAMI_DB1500:
45
case BCSR_WHOAMI_DB1100:
46
case BCSR_WHOAMI_PB1500:
47
case BCSR_WHOAMI_PB1500R2:
48
case BCSR_WHOAMI_PB1100:
49
pr_info("AMD Alchemy %s Board\n", get_system_type());
50
return 0;
51
}
52
return -ENODEV;
53
}
54
55
static int db1500_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
56
{
57
if ((slot < 12) || (slot > 13) || pin == 0)
58
return -1;
59
if (slot == 12)
60
return (pin == 1) ? AU1500_PCI_INTA : 0xff;
61
if (slot == 13) {
62
switch (pin) {
63
case 1: return AU1500_PCI_INTA;
64
case 2: return AU1500_PCI_INTB;
65
case 3: return AU1500_PCI_INTC;
66
case 4: return AU1500_PCI_INTD;
67
}
68
}
69
return -1;
70
}
71
72
static u64 au1xxx_all_dmamask = DMA_BIT_MASK(32);
73
74
static struct resource alchemy_pci_host_res[] = {
75
[0] = {
76
.start = AU1500_PCI_PHYS_ADDR,
77
.end = AU1500_PCI_PHYS_ADDR + 0xfff,
78
.flags = IORESOURCE_MEM,
79
},
80
};
81
82
static struct alchemy_pci_platdata db1500_pci_pd = {
83
.board_map_irq = db1500_map_pci_irq,
84
};
85
86
static struct platform_device db1500_pci_host_dev = {
87
.dev.platform_data = &db1500_pci_pd,
88
.name = "alchemy-pci",
89
.id = 0,
90
.num_resources = ARRAY_SIZE(alchemy_pci_host_res),
91
.resource = alchemy_pci_host_res,
92
};
93
94
int __init db1500_pci_setup(void)
95
{
96
return platform_device_register(&db1500_pci_host_dev);
97
}
98
99
static struct resource au1100_lcd_resources[] = {
100
[0] = {
101
.start = AU1100_LCD_PHYS_ADDR,
102
.end = AU1100_LCD_PHYS_ADDR + 0x800 - 1,
103
.flags = IORESOURCE_MEM,
104
},
105
[1] = {
106
.start = AU1100_LCD_INT,
107
.end = AU1100_LCD_INT,
108
.flags = IORESOURCE_IRQ,
109
}
110
};
111
112
static struct platform_device au1100_lcd_device = {
113
.name = "au1100-lcd",
114
.id = 0,
115
.dev = {
116
.dma_mask = &au1xxx_all_dmamask,
117
.coherent_dma_mask = DMA_BIT_MASK(32),
118
},
119
.num_resources = ARRAY_SIZE(au1100_lcd_resources),
120
.resource = au1100_lcd_resources,
121
};
122
123
static struct resource alchemy_ac97c_res[] = {
124
[0] = {
125
.start = AU1000_AC97_PHYS_ADDR,
126
.end = AU1000_AC97_PHYS_ADDR + 0xfff,
127
.flags = IORESOURCE_MEM,
128
},
129
[1] = {
130
.start = DMA_ID_AC97C_TX,
131
.end = DMA_ID_AC97C_TX,
132
.flags = IORESOURCE_DMA,
133
},
134
[2] = {
135
.start = DMA_ID_AC97C_RX,
136
.end = DMA_ID_AC97C_RX,
137
.flags = IORESOURCE_DMA,
138
},
139
};
140
141
static struct platform_device alchemy_ac97c_dev = {
142
.name = "alchemy-ac97c",
143
.id = -1,
144
.resource = alchemy_ac97c_res,
145
.num_resources = ARRAY_SIZE(alchemy_ac97c_res),
146
};
147
148
static struct platform_device alchemy_ac97c_dma_dev = {
149
.name = "alchemy-pcm-dma",
150
.id = 0,
151
};
152
153
static struct platform_device db1x00_codec_dev = {
154
.name = "ac97-codec",
155
.id = -1,
156
};
157
158
static struct platform_device db1x00_audio_dev = {
159
.name = "db1000-audio",
160
.dev = {
161
.dma_mask = &au1xxx_all_dmamask,
162
.coherent_dma_mask = DMA_BIT_MASK(32),
163
},
164
};
165
166
/******************************************************************************/
167
168
#ifdef CONFIG_MMC_AU1X
169
static irqreturn_t db1100_mmc_cd(int irq, void *ptr)
170
{
171
mmc_detect_change(ptr, msecs_to_jiffies(500));
172
return IRQ_HANDLED;
173
}
174
175
static int db1100_mmc_cd_setup(void *mmc_host, int en)
176
{
177
int ret = 0, irq;
178
179
if (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) == BCSR_WHOAMI_DB1100)
180
irq = AU1100_GPIO19_INT;
181
else
182
irq = AU1100_GPIO14_INT; /* PB1100 SD0 CD# */
183
184
if (en) {
185
irq_set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
186
ret = request_irq(irq, db1100_mmc_cd, 0,
187
"sd0_cd", mmc_host);
188
} else
189
free_irq(irq, mmc_host);
190
return ret;
191
}
192
193
static int db1100_mmc1_cd_setup(void *mmc_host, int en)
194
{
195
int ret = 0, irq;
196
197
if (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) == BCSR_WHOAMI_DB1100)
198
irq = AU1100_GPIO20_INT;
199
else
200
irq = AU1100_GPIO15_INT; /* PB1100 SD1 CD# */
201
202
if (en) {
203
irq_set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
204
ret = request_irq(irq, db1100_mmc_cd, 0,
205
"sd1_cd", mmc_host);
206
} else
207
free_irq(irq, mmc_host);
208
return ret;
209
}
210
211
static int db1100_mmc_card_readonly(void *mmc_host)
212
{
213
/* testing suggests that this bit is inverted */
214
return (bcsr_read(BCSR_STATUS) & BCSR_STATUS_SD0WP) ? 0 : 1;
215
}
216
217
static int db1100_mmc_card_inserted(void *mmc_host)
218
{
219
return !alchemy_gpio_get_value(19);
220
}
221
222
static void db1100_mmc_set_power(void *mmc_host, int state)
223
{
224
int bit;
225
226
if (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) == BCSR_WHOAMI_DB1100)
227
bit = BCSR_BOARD_SD0PWR;
228
else
229
bit = BCSR_BOARD_PB1100_SD0PWR;
230
231
if (state) {
232
bcsr_mod(BCSR_BOARD, 0, bit);
233
msleep(400); /* stabilization time */
234
} else
235
bcsr_mod(BCSR_BOARD, bit, 0);
236
}
237
238
static void db1100_mmcled_set(struct led_classdev *led, enum led_brightness b)
239
{
240
if (b != LED_OFF)
241
bcsr_mod(BCSR_LEDS, BCSR_LEDS_LED0, 0);
242
else
243
bcsr_mod(BCSR_LEDS, 0, BCSR_LEDS_LED0);
244
}
245
246
static struct led_classdev db1100_mmc_led = {
247
.brightness_set = db1100_mmcled_set,
248
};
249
250
static int db1100_mmc1_card_readonly(void *mmc_host)
251
{
252
return (bcsr_read(BCSR_BOARD) & BCSR_BOARD_SD1WP) ? 1 : 0;
253
}
254
255
static int db1100_mmc1_card_inserted(void *mmc_host)
256
{
257
return !alchemy_gpio_get_value(20);
258
}
259
260
static void db1100_mmc1_set_power(void *mmc_host, int state)
261
{
262
int bit;
263
264
if (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) == BCSR_WHOAMI_DB1100)
265
bit = BCSR_BOARD_SD1PWR;
266
else
267
bit = BCSR_BOARD_PB1100_SD1PWR;
268
269
if (state) {
270
bcsr_mod(BCSR_BOARD, 0, bit);
271
msleep(400); /* stabilization time */
272
} else
273
bcsr_mod(BCSR_BOARD, bit, 0);
274
}
275
276
static void db1100_mmc1led_set(struct led_classdev *led, enum led_brightness b)
277
{
278
if (b != LED_OFF)
279
bcsr_mod(BCSR_LEDS, BCSR_LEDS_LED1, 0);
280
else
281
bcsr_mod(BCSR_LEDS, 0, BCSR_LEDS_LED1);
282
}
283
284
static struct led_classdev db1100_mmc1_led = {
285
.brightness_set = db1100_mmc1led_set,
286
};
287
288
static struct au1xmmc_platform_data db1100_mmc_platdata[2] = {
289
[0] = {
290
.cd_setup = db1100_mmc_cd_setup,
291
.set_power = db1100_mmc_set_power,
292
.card_inserted = db1100_mmc_card_inserted,
293
.card_readonly = db1100_mmc_card_readonly,
294
.led = &db1100_mmc_led,
295
},
296
[1] = {
297
.cd_setup = db1100_mmc1_cd_setup,
298
.set_power = db1100_mmc1_set_power,
299
.card_inserted = db1100_mmc1_card_inserted,
300
.card_readonly = db1100_mmc1_card_readonly,
301
.led = &db1100_mmc1_led,
302
},
303
};
304
305
static struct resource au1100_mmc0_resources[] = {
306
[0] = {
307
.start = AU1100_SD0_PHYS_ADDR,
308
.end = AU1100_SD0_PHYS_ADDR + 0xfff,
309
.flags = IORESOURCE_MEM,
310
},
311
[1] = {
312
.start = AU1100_SD_INT,
313
.end = AU1100_SD_INT,
314
.flags = IORESOURCE_IRQ,
315
},
316
[2] = {
317
.start = DMA_ID_SD0_TX,
318
.end = DMA_ID_SD0_TX,
319
.flags = IORESOURCE_DMA,
320
},
321
[3] = {
322
.start = DMA_ID_SD0_RX,
323
.end = DMA_ID_SD0_RX,
324
.flags = IORESOURCE_DMA,
325
}
326
};
327
328
static struct platform_device db1100_mmc0_dev = {
329
.name = "au1xxx-mmc",
330
.id = 0,
331
.dev = {
332
.dma_mask = &au1xxx_all_dmamask,
333
.coherent_dma_mask = DMA_BIT_MASK(32),
334
.platform_data = &db1100_mmc_platdata[0],
335
},
336
.num_resources = ARRAY_SIZE(au1100_mmc0_resources),
337
.resource = au1100_mmc0_resources,
338
};
339
340
static struct resource au1100_mmc1_res[] = {
341
[0] = {
342
.start = AU1100_SD1_PHYS_ADDR,
343
.end = AU1100_SD1_PHYS_ADDR + 0xfff,
344
.flags = IORESOURCE_MEM,
345
},
346
[1] = {
347
.start = AU1100_SD_INT,
348
.end = AU1100_SD_INT,
349
.flags = IORESOURCE_IRQ,
350
},
351
[2] = {
352
.start = DMA_ID_SD1_TX,
353
.end = DMA_ID_SD1_TX,
354
.flags = IORESOURCE_DMA,
355
},
356
[3] = {
357
.start = DMA_ID_SD1_RX,
358
.end = DMA_ID_SD1_RX,
359
.flags = IORESOURCE_DMA,
360
}
361
};
362
363
static struct platform_device db1100_mmc1_dev = {
364
.name = "au1xxx-mmc",
365
.id = 1,
366
.dev = {
367
.dma_mask = &au1xxx_all_dmamask,
368
.coherent_dma_mask = DMA_BIT_MASK(32),
369
.platform_data = &db1100_mmc_platdata[1],
370
},
371
.num_resources = ARRAY_SIZE(au1100_mmc1_res),
372
.resource = au1100_mmc1_res,
373
};
374
#endif /* CONFIG_MMC_AU1X */
375
376
/******************************************************************************/
377
378
static const struct software_node db1100_alchemy2_gpiochip = {
379
.name = "alchemy-gpio2",
380
};
381
382
static const struct property_entry db1100_ads7846_properties[] = {
383
PROPERTY_ENTRY_U16("ti,vref_min", 3300),
384
PROPERTY_ENTRY_GPIO("pendown-gpios",
385
&db1100_alchemy2_gpiochip, 21, GPIO_ACTIVE_LOW),
386
{ }
387
};
388
389
static const struct software_node db1100_ads7846_swnode = {
390
.name = "ads7846",
391
.properties = db1100_ads7846_properties,
392
};
393
394
static struct spi_board_info db1100_spi_info[] __initdata = {
395
[0] = {
396
.modalias = "ads7846",
397
.max_speed_hz = 3250000,
398
.bus_num = 0,
399
.chip_select = 0,
400
.mode = 0,
401
.irq = AU1100_GPIO21_INT,
402
.swnode = &db1100_ads7846_swnode,
403
},
404
};
405
406
static const struct spi_gpio_platform_data db1100_spictl_pd __initconst = {
407
.num_chipselect = 1,
408
};
409
410
/*
411
* Alchemy GPIO 2 has its base at 200 so the GPIO lines
412
* 207 thru 210 are GPIOs at offset 7 thru 10 at this chip.
413
*/
414
static const struct property_entry db1100_spi_dev_properties[] __initconst = {
415
PROPERTY_ENTRY_GPIO("miso-gpios",
416
&db1100_alchemy2_gpiochip, 7, GPIO_ACTIVE_HIGH),
417
PROPERTY_ENTRY_GPIO("mosi-gpios",
418
&db1100_alchemy2_gpiochip, 8, GPIO_ACTIVE_HIGH),
419
PROPERTY_ENTRY_GPIO("sck-gpios",
420
&db1100_alchemy2_gpiochip, 9, GPIO_ACTIVE_HIGH),
421
PROPERTY_ENTRY_GPIO("cs-gpios",
422
&db1100_alchemy2_gpiochip, 10, GPIO_ACTIVE_HIGH),
423
{ }
424
};
425
426
static const struct platform_device_info db1100_spi_dev_info __initconst = {
427
.name = "spi_gpio",
428
.id = 0,
429
.data = &db1100_spictl_pd,
430
.size_data = sizeof(db1100_spictl_pd),
431
.dma_mask = DMA_BIT_MASK(32),
432
.properties = db1100_spi_dev_properties,
433
};
434
435
static struct platform_device *db1x00_devs[] = {
436
&db1x00_codec_dev,
437
&alchemy_ac97c_dma_dev,
438
&alchemy_ac97c_dev,
439
&db1x00_audio_dev,
440
};
441
442
static struct platform_device *db1100_devs[] = {
443
&au1100_lcd_device,
444
#ifdef CONFIG_MMC_AU1X
445
&db1100_mmc0_dev,
446
&db1100_mmc1_dev,
447
#endif
448
};
449
450
int __init db1000_dev_setup(void)
451
{
452
int board = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
453
int c0, c1, d0, d1, s0, s1, flashsize = 32, twosocks = 1;
454
int err;
455
unsigned long pfc;
456
struct clk *c, *p;
457
struct platform_device *spi_dev;
458
459
if (board == BCSR_WHOAMI_DB1500) {
460
c0 = AU1500_GPIO2_INT;
461
c1 = AU1500_GPIO5_INT;
462
d0 = 0; /* GPIO number, NOT irq! */
463
d1 = 3; /* GPIO number, NOT irq! */
464
s0 = AU1500_GPIO1_INT;
465
s1 = AU1500_GPIO4_INT;
466
} else if (board == BCSR_WHOAMI_DB1100) {
467
c0 = AU1100_GPIO2_INT;
468
c1 = AU1100_GPIO5_INT;
469
d0 = 0; /* GPIO number, NOT irq! */
470
d1 = 3; /* GPIO number, NOT irq! */
471
s0 = AU1100_GPIO1_INT;
472
s1 = AU1100_GPIO4_INT;
473
474
gpio_request(19, "sd0_cd");
475
gpio_request(20, "sd1_cd");
476
gpio_direction_input(19); /* sd0 cd# */
477
gpio_direction_input(20); /* sd1 cd# */
478
479
/* spi_gpio on SSI0 pins */
480
pfc = alchemy_rdsys(AU1000_SYS_PINFUNC);
481
pfc |= (1 << 0); /* SSI0 pins as GPIOs */
482
alchemy_wrsys(pfc, AU1000_SYS_PINFUNC);
483
484
software_node_register(&db1100_alchemy2_gpiochip);
485
spi_register_board_info(db1100_spi_info,
486
ARRAY_SIZE(db1100_spi_info));
487
488
/* link LCD clock to AUXPLL */
489
p = clk_get(NULL, "auxpll_clk");
490
c = clk_get(NULL, "lcd_intclk");
491
if (!IS_ERR(c) && !IS_ERR(p)) {
492
clk_set_parent(c, p);
493
clk_set_rate(c, clk_get_rate(p));
494
}
495
if (!IS_ERR(c))
496
clk_put(c);
497
if (!IS_ERR(p))
498
clk_put(p);
499
500
platform_add_devices(db1100_devs, ARRAY_SIZE(db1100_devs));
501
502
spi_dev = platform_device_register_full(&db1100_spi_dev_info);
503
err = PTR_ERR_OR_ZERO(spi_dev);
504
if (err)
505
pr_err("failed to register SPI controller: %d\n", err);
506
} else if (board == BCSR_WHOAMI_DB1000) {
507
c0 = AU1000_GPIO2_INT;
508
c1 = AU1000_GPIO5_INT;
509
d0 = 0; /* GPIO number, NOT irq! */
510
d1 = 3; /* GPIO number, NOT irq! */
511
s0 = AU1000_GPIO1_INT;
512
s1 = AU1000_GPIO4_INT;
513
} else if ((board == BCSR_WHOAMI_PB1500) ||
514
(board == BCSR_WHOAMI_PB1500R2)) {
515
c0 = AU1500_GPIO203_INT;
516
d0 = 1; /* GPIO number, NOT irq! */
517
s0 = AU1500_GPIO202_INT;
518
twosocks = 0;
519
flashsize = 64;
520
/* RTC and daughtercard irqs */
521
irq_set_irq_type(AU1500_GPIO204_INT, IRQ_TYPE_LEVEL_LOW);
522
irq_set_irq_type(AU1500_GPIO205_INT, IRQ_TYPE_LEVEL_LOW);
523
/* EPSON S1D13806 0x1b000000
524
* SRAM 1MB/2MB 0x1a000000
525
* DS1693 RTC 0x0c000000
526
*/
527
} else if (board == BCSR_WHOAMI_PB1100) {
528
c0 = AU1100_GPIO11_INT;
529
d0 = 9; /* GPIO number, NOT irq! */
530
s0 = AU1100_GPIO10_INT;
531
twosocks = 0;
532
flashsize = 64;
533
/* pendown, rtc, daughtercard irqs */
534
irq_set_irq_type(AU1100_GPIO8_INT, IRQ_TYPE_LEVEL_LOW);
535
irq_set_irq_type(AU1100_GPIO12_INT, IRQ_TYPE_LEVEL_LOW);
536
irq_set_irq_type(AU1100_GPIO13_INT, IRQ_TYPE_LEVEL_LOW);
537
/* EPSON S1D13806 0x1b000000
538
* SRAM 1MB/2MB 0x1a000000
539
* DiskOnChip 0x0d000000
540
* DS1693 RTC 0x0c000000
541
*/
542
platform_add_devices(db1100_devs, ARRAY_SIZE(db1100_devs));
543
} else
544
return 0; /* unknown board, no further dev setup to do */
545
546
irq_set_irq_type(c0, IRQ_TYPE_LEVEL_LOW);
547
irq_set_irq_type(s0, IRQ_TYPE_LEVEL_LOW);
548
549
db1x_register_pcmcia_socket(
550
AU1000_PCMCIA_ATTR_PHYS_ADDR,
551
AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
552
AU1000_PCMCIA_MEM_PHYS_ADDR,
553
AU1000_PCMCIA_MEM_PHYS_ADDR + 0x000400000 - 1,
554
AU1000_PCMCIA_IO_PHYS_ADDR,
555
AU1000_PCMCIA_IO_PHYS_ADDR + 0x000010000 - 1,
556
c0, d0, /*s0*/0, 0, 0);
557
558
if (twosocks) {
559
irq_set_irq_type(c1, IRQ_TYPE_LEVEL_LOW);
560
irq_set_irq_type(s1, IRQ_TYPE_LEVEL_LOW);
561
562
db1x_register_pcmcia_socket(
563
AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004000000,
564
AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004400000 - 1,
565
AU1000_PCMCIA_MEM_PHYS_ADDR + 0x004000000,
566
AU1000_PCMCIA_MEM_PHYS_ADDR + 0x004400000 - 1,
567
AU1000_PCMCIA_IO_PHYS_ADDR + 0x004000000,
568
AU1000_PCMCIA_IO_PHYS_ADDR + 0x004010000 - 1,
569
c1, d1, /*s1*/0, 0, 1);
570
}
571
572
platform_add_devices(db1x00_devs, ARRAY_SIZE(db1x00_devs));
573
db1x_register_norflash(flashsize << 20, 4 /* 32bit */, F_SWAPPED);
574
return 0;
575
}
576
577