2 * linux/arch/mips/txx9/generic/setup.c
4 * Based on linux/arch/mips/txx9/rbtx4938/setup.c,
5 * and RBTX49xx patch from CELF patch archive.
7 * 2003-2005 (c) MontaVista Software, Inc.
8 * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007
10 * This file is subject to the terms and conditions of the GNU General Public
11 * License. See the file "COPYING" in the main directory of this archive
14 #include <linux/init.h>
15 #include <linux/kernel.h>
16 #include <linux/types.h>
17 #include <linux/interrupt.h>
18 #include <linux/string.h>
19 #include <linux/module.h>
20 #include <linux/clk.h>
21 #include <linux/err.h>
22 #include <linux/gpio.h>
23 #include <linux/platform_device.h>
24 #include <linux/serial_core.h>
25 #include <linux/mtd/physmap.h>
26 #include <linux/leds.h>
27 #include <asm/bootinfo.h>
29 #include <asm/reboot.h>
30 #include <asm/r4kcache.h>
31 #include <asm/txx9/generic.h>
32 #include <asm/txx9/pci.h>
33 #include <asm/txx9tmr.h>
34 #ifdef CONFIG_CPU_TX49XX
35 #include <asm/txx9/tx4938.h>
38 /* EBUSC settings of TX4927, etc. */
39 struct resource txx9_ce_res
[8];
40 static char txx9_ce_res_name
[8][4]; /* "CEn" */
42 /* pcode, internal register */
43 unsigned int txx9_pcode
;
44 char txx9_pcode_str
[8];
45 static struct resource txx9_reg_res
= {
46 .name
= txx9_pcode_str
,
47 .flags
= IORESOURCE_MEM
,
50 txx9_reg_res_init(unsigned int pcode
, unsigned long base
, unsigned long size
)
54 for (i
= 0; i
< ARRAY_SIZE(txx9_ce_res
); i
++) {
55 sprintf(txx9_ce_res_name
[i
], "CE%d", i
);
56 txx9_ce_res
[i
].flags
= IORESOURCE_MEM
;
57 txx9_ce_res
[i
].name
= txx9_ce_res_name
[i
];
61 sprintf(txx9_pcode_str
, "TX%x", pcode
);
63 txx9_reg_res
.start
= base
& 0xfffffffffULL
;
64 txx9_reg_res
.end
= (base
& 0xfffffffffULL
) + (size
- 1);
65 request_resource(&iomem_resource
, &txx9_reg_res
);
70 unsigned int txx9_master_clock
;
71 unsigned int txx9_cpu_clock
;
72 unsigned int txx9_gbus_clock
;
74 #ifdef CONFIG_CPU_TX39XX
75 /* don't enable by default - see errata */
76 int txx9_ccfg_toeon __initdata
;
78 int txx9_ccfg_toeon __initdata
= 1;
81 /* Minimum CLK support */
83 struct clk
*clk_get(struct device
*dev
, const char *id
)
85 if (!strcmp(id
, "spi-baseclk"))
86 return (struct clk
*)((unsigned long)txx9_gbus_clock
/ 2 / 4);
87 if (!strcmp(id
, "imbus_clk"))
88 return (struct clk
*)((unsigned long)txx9_gbus_clock
/ 2);
89 return ERR_PTR(-ENOENT
);
91 EXPORT_SYMBOL(clk_get
);
93 int clk_enable(struct clk
*clk
)
97 EXPORT_SYMBOL(clk_enable
);
99 void clk_disable(struct clk
*clk
)
102 EXPORT_SYMBOL(clk_disable
);
104 unsigned long clk_get_rate(struct clk
*clk
)
106 return (unsigned long)clk
;
108 EXPORT_SYMBOL(clk_get_rate
);
110 void clk_put(struct clk
*clk
)
113 EXPORT_SYMBOL(clk_put
);
117 #ifdef CONFIG_GENERIC_GPIO
118 int gpio_to_irq(unsigned gpio
)
122 EXPORT_SYMBOL(gpio_to_irq
);
124 int irq_to_gpio(unsigned irq
)
128 EXPORT_SYMBOL(irq_to_gpio
);
131 #define BOARD_VEC(board) extern struct txx9_board_vec board;
132 #include <asm/txx9/boards.h>
135 struct txx9_board_vec
*txx9_board_vec __initdata
;
136 static char txx9_system_type
[32];
138 static struct txx9_board_vec
*board_vecs
[] __initdata
= {
139 #define BOARD_VEC(board) &board,
140 #include <asm/txx9/boards.h>
144 static struct txx9_board_vec
*__init
find_board_byname(const char *name
)
148 /* search board_vecs table */
149 for (i
= 0; i
< ARRAY_SIZE(board_vecs
); i
++) {
150 if (strstr(board_vecs
[i
]->system
, name
))
151 return board_vecs
[i
];
156 static void __init
prom_init_cmdline(void)
158 int argc
= (int)fw_arg0
;
159 int *argv32
= (int *)fw_arg1
;
160 int i
; /* Always ignore the "-c" at argv[0] */
161 char builtin
[CL_SIZE
];
163 /* ignore all built-in args if any f/w args given */
165 * But if built-in strings was started with '+', append them
166 * to command line args. If built-in was started with '-',
167 * ignore all f/w args.
170 if (arcs_cmdline
[0] == '+')
171 strcpy(builtin
, arcs_cmdline
+ 1);
172 else if (arcs_cmdline
[0] == '-') {
173 strcpy(builtin
, arcs_cmdline
+ 1);
175 } else if (argc
<= 1)
176 strcpy(builtin
, arcs_cmdline
);
177 arcs_cmdline
[0] = '\0';
179 for (i
= 1; i
< argc
; i
++) {
180 char *str
= (char *)(long)argv32
[i
];
182 strcat(arcs_cmdline
, " ");
183 if (strchr(str
, ' ')) {
184 strcat(arcs_cmdline
, "\"");
185 strcat(arcs_cmdline
, str
);
186 strcat(arcs_cmdline
, "\"");
188 strcat(arcs_cmdline
, str
);
190 /* append saved builtin args */
193 strcat(arcs_cmdline
, " ");
194 strcat(arcs_cmdline
, builtin
);
198 static int txx9_ic_disable __initdata
;
199 static int txx9_dc_disable __initdata
;
201 #if defined(CONFIG_CPU_TX49XX)
202 /* flush all cache on very early stage (before 4k_cache_init) */
203 static void __init
early_flush_dcache(void)
205 unsigned int conf
= read_c0_config();
206 unsigned int dc_size
= 1 << (12 + ((conf
& CONF_DC
) >> 6));
207 unsigned int linesz
= 32;
208 unsigned long addr
, end
;
210 end
= INDEX_BASE
+ dc_size
/ 4;
212 for (addr
= INDEX_BASE
; addr
< end
; addr
+= linesz
) {
213 cache_op(Index_Writeback_Inv_D
, addr
| 0);
214 cache_op(Index_Writeback_Inv_D
, addr
| 1);
215 cache_op(Index_Writeback_Inv_D
, addr
| 2);
216 cache_op(Index_Writeback_Inv_D
, addr
| 3);
220 static void __init
txx9_cache_fixup(void)
224 conf
= read_c0_config();
225 /* flush and disable */
226 if (txx9_ic_disable
) {
227 conf
|= TX49_CONF_IC
;
228 write_c0_config(conf
);
230 if (txx9_dc_disable
) {
231 early_flush_dcache();
232 conf
|= TX49_CONF_DC
;
233 write_c0_config(conf
);
237 conf
= read_c0_config();
238 if (!txx9_ic_disable
)
239 conf
&= ~TX49_CONF_IC
;
240 if (!txx9_dc_disable
)
241 conf
&= ~TX49_CONF_DC
;
242 write_c0_config(conf
);
244 if (conf
& TX49_CONF_IC
)
245 pr_info("TX49XX I-Cache disabled.\n");
246 if (conf
& TX49_CONF_DC
)
247 pr_info("TX49XX D-Cache disabled.\n");
249 #elif defined(CONFIG_CPU_TX39XX)
250 /* flush all cache on very early stage (before tx39_cache_init) */
251 static void __init
early_flush_dcache(void)
253 unsigned int conf
= read_c0_config();
254 unsigned int dc_size
= 1 << (10 + ((conf
& TX39_CONF_DCS_MASK
) >>
255 TX39_CONF_DCS_SHIFT
));
256 unsigned int linesz
= 16;
257 unsigned long addr
, end
;
259 end
= INDEX_BASE
+ dc_size
/ 2;
261 for (addr
= INDEX_BASE
; addr
< end
; addr
+= linesz
) {
262 cache_op(Index_Writeback_Inv_D
, addr
| 0);
263 cache_op(Index_Writeback_Inv_D
, addr
| 1);
267 static void __init
txx9_cache_fixup(void)
271 conf
= read_c0_config();
272 /* flush and disable */
273 if (txx9_ic_disable
) {
274 conf
&= ~TX39_CONF_ICE
;
275 write_c0_config(conf
);
277 if (txx9_dc_disable
) {
278 early_flush_dcache();
279 conf
&= ~TX39_CONF_DCE
;
280 write_c0_config(conf
);
284 conf
= read_c0_config();
285 if (!txx9_ic_disable
)
286 conf
|= TX39_CONF_ICE
;
287 if (!txx9_dc_disable
)
288 conf
|= TX39_CONF_DCE
;
289 write_c0_config(conf
);
291 if (!(conf
& TX39_CONF_ICE
))
292 pr_info("TX39XX I-Cache disabled.\n");
293 if (!(conf
& TX39_CONF_DCE
))
294 pr_info("TX39XX D-Cache disabled.\n");
297 static inline void txx9_cache_fixup(void)
302 static void __init
preprocess_cmdline(void)
304 char cmdline
[CL_SIZE
];
307 strcpy(cmdline
, arcs_cmdline
);
309 arcs_cmdline
[0] = '\0';
311 char *str
= strsep(&s
, " ");
312 if (strncmp(str
, "board=", 6) == 0) {
313 txx9_board_vec
= find_board_byname(str
+ 6);
315 } else if (strncmp(str
, "masterclk=", 10) == 0) {
317 if (strict_strtoul(str
+ 10, 10, &val
) == 0)
318 txx9_master_clock
= val
;
320 } else if (strcmp(str
, "icdisable") == 0) {
323 } else if (strcmp(str
, "dcdisable") == 0) {
326 } else if (strcmp(str
, "toeoff") == 0) {
329 } else if (strcmp(str
, "toeon") == 0) {
334 strcat(arcs_cmdline
, " ");
335 strcat(arcs_cmdline
, str
);
341 static void __init
select_board(void)
345 /* first, determine by "board=" argument in preprocess_cmdline() */
348 /* next, determine by "board" envvar */
349 envstr
= prom_getenv("board");
351 txx9_board_vec
= find_board_byname(envstr
);
356 /* select "default" board */
357 #ifdef CONFIG_CPU_TX39XX
358 txx9_board_vec
= &jmr3927_vec
;
360 #ifdef CONFIG_CPU_TX49XX
361 switch (TX4938_REV_PCODE()) {
362 #ifdef CONFIG_TOSHIBA_RBTX4927
364 txx9_board_vec
= &rbtx4927_vec
;
367 txx9_board_vec
= &rbtx4937_vec
;
370 #ifdef CONFIG_TOSHIBA_RBTX4938
372 txx9_board_vec
= &rbtx4938_vec
;
379 void __init
prom_init(void)
382 preprocess_cmdline();
385 strcpy(txx9_system_type
, txx9_board_vec
->system
);
387 txx9_board_vec
->prom_init();
390 void __init
prom_free_prom_memory(void)
394 const char *get_system_type(void)
396 return txx9_system_type
;
399 char * __init
prom_getcmdline(void)
401 return &(arcs_cmdline
[0]);
404 const char *__init
prom_getenv(const char *name
)
406 const s32
*str
= (const s32
*)fw_arg2
;
410 /* YAMON style ("name", "value" pairs) */
411 while (str
[0] && str
[1]) {
412 if (!strcmp((const char *)(unsigned long)str
[0], name
))
413 return (const char *)(unsigned long)str
[1];
419 static void __noreturn
txx9_machine_halt(void)
422 clear_c0_status(ST0_IM
);
426 if (cpu_has_counter
) {
428 * Clear counter interrupt while it
429 * breaks WAIT instruction even if
438 /* Watchdog support */
439 void __init
txx9_wdt_init(unsigned long base
)
441 struct resource res
= {
443 .end
= base
+ 0x100 - 1,
444 .flags
= IORESOURCE_MEM
,
446 platform_device_register_simple("txx9wdt", -1, &res
, 1);
449 void txx9_wdt_now(unsigned long base
)
451 struct txx9_tmr_reg __iomem
*tmrptr
=
452 ioremap(base
, sizeof(struct txx9_tmr_reg
));
453 /* disable watch dog timer */
454 __raw_writel(TXx9_TMWTMR_WDIS
| TXx9_TMWTMR_TWC
, &tmrptr
->wtmr
);
455 __raw_writel(0, &tmrptr
->tcr
);
457 __raw_writel(TXx9_TMWTMR_TWIE
, &tmrptr
->wtmr
);
458 __raw_writel(1, &tmrptr
->cpra
); /* immediate */
459 __raw_writel(TXx9_TMTCR_TCE
| TXx9_TMTCR_CCDE
| TXx9_TMTCR_TMODE_WDOG
,
464 void __init
txx9_spi_init(int busid
, unsigned long base
, int irq
)
466 struct resource res
[] = {
469 .end
= base
+ 0x20 - 1,
470 .flags
= IORESOURCE_MEM
,
473 .flags
= IORESOURCE_IRQ
,
476 platform_device_register_simple("spi_txx9", busid
,
477 res
, ARRAY_SIZE(res
));
480 void __init
txx9_ethaddr_init(unsigned int id
, unsigned char *ethaddr
)
482 struct platform_device
*pdev
=
483 platform_device_alloc("tc35815-mac", id
);
485 platform_device_add_data(pdev
, ethaddr
, 6) ||
486 platform_device_add(pdev
))
487 platform_device_put(pdev
);
490 void __init
txx9_sio_init(unsigned long baseaddr
, int irq
,
491 unsigned int line
, unsigned int sclk
, int nocts
)
493 #ifdef CONFIG_SERIAL_TXX9
494 struct uart_port req
;
496 memset(&req
, 0, sizeof(req
));
498 req
.iotype
= UPIO_MEM
;
499 req
.membase
= ioremap(baseaddr
, 0x24);
500 req
.mapbase
= baseaddr
;
503 req
.flags
|= UPF_BUGGY_UART
/*HAVE_CTS_LINE*/;
505 req
.flags
|= UPF_MAGIC_MULTIPLIER
/*USE_SCLK*/;
508 req
.uartclk
= TXX9_IMCLK
;
509 early_serial_txx9_setup(&req
);
510 #endif /* CONFIG_SERIAL_TXX9 */
513 #ifdef CONFIG_EARLY_PRINTK
514 static void __init
null_prom_putchar(char c
)
517 void (*txx9_prom_putchar
)(char c
) __initdata
= null_prom_putchar
;
519 void __init
prom_putchar(char c
)
521 txx9_prom_putchar(c
);
524 static void __iomem
*early_txx9_sio_port
;
526 static void __init
early_txx9_sio_putchar(char c
)
528 #define TXX9_SICISR 0x0c
529 #define TXX9_SITFIFO 0x1c
530 #define TXX9_SICISR_TXALS 0x00000002
531 while (!(__raw_readl(early_txx9_sio_port
+ TXX9_SICISR
) &
534 __raw_writel(c
, early_txx9_sio_port
+ TXX9_SITFIFO
);
537 void __init
txx9_sio_putchar_init(unsigned long baseaddr
)
539 early_txx9_sio_port
= ioremap(baseaddr
, 0x24);
540 txx9_prom_putchar
= early_txx9_sio_putchar
;
542 #endif /* CONFIG_EARLY_PRINTK */
545 void __init
plat_mem_setup(void)
547 ioport_resource
.start
= 0;
548 ioport_resource
.end
= ~0UL; /* no limit */
549 iomem_resource
.start
= 0;
550 iomem_resource
.end
= ~0UL; /* no limit */
552 /* fallback restart/halt routines */
553 _machine_restart
= (void (*)(char *))txx9_machine_halt
;
554 _machine_halt
= txx9_machine_halt
;
555 pm_power_off
= txx9_machine_halt
;
558 pcibios_plat_setup
= txx9_pcibios_setup
;
560 txx9_board_vec
->mem_setup();
563 void __init
arch_init_irq(void)
565 txx9_board_vec
->irq_setup();
568 void __init
plat_time_init(void)
570 #ifdef CONFIG_CPU_TX49XX
571 mips_hpt_frequency
= txx9_cpu_clock
/ 2;
573 txx9_board_vec
->time_init();
576 static int __init
_txx9_arch_init(void)
578 if (txx9_board_vec
->arch_init
)
579 txx9_board_vec
->arch_init();
582 arch_initcall(_txx9_arch_init
);
584 static int __init
_txx9_device_init(void)
586 if (txx9_board_vec
->device_init
)
587 txx9_board_vec
->device_init();
590 device_initcall(_txx9_device_init
);
592 int (*txx9_irq_dispatch
)(int pending
);
593 asmlinkage
void plat_irq_dispatch(void)
595 int pending
= read_c0_status() & read_c0_cause() & ST0_IM
;
596 int irq
= txx9_irq_dispatch(pending
);
598 if (likely(irq
>= 0))
601 spurious_interrupt();
604 /* see include/asm-mips/mach-tx39xx/mangle-port.h, for example. */
605 #ifdef NEEDS_TXX9_SWIZZLE_ADDR_B
606 static unsigned long __swizzle_addr_none(unsigned long port
)
610 unsigned long (*__swizzle_addr_b
)(unsigned long port
) = __swizzle_addr_none
;
611 EXPORT_SYMBOL(__swizzle_addr_b
);
614 void __init
txx9_physmap_flash_init(int no
, unsigned long addr
,
616 const struct physmap_flash_data
*pdata
)
618 #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
619 struct resource res
= {
621 .end
= addr
+ size
- 1,
622 .flags
= IORESOURCE_MEM
,
624 struct platform_device
*pdev
;
625 #ifdef CONFIG_MTD_PARTITIONS
626 static struct mtd_partition parts
[2];
627 struct physmap_flash_data pdata_part
;
629 /* If this area contained boot area, make separate partition */
630 if (pdata
->nr_parts
== 0 && !pdata
->parts
&&
631 addr
< 0x1fc00000 && addr
+ size
> 0x1fc00000 &&
633 parts
[0].name
= "boot";
634 parts
[0].offset
= 0x1fc00000 - addr
;
635 parts
[0].size
= addr
+ size
- 0x1fc00000;
636 parts
[1].name
= "user";
638 parts
[1].size
= 0x1fc00000 - addr
;
640 pdata_part
.nr_parts
= ARRAY_SIZE(parts
);
641 pdata_part
.parts
= parts
;
645 pdev
= platform_device_alloc("physmap-flash", no
);
647 platform_device_add_resources(pdev
, &res
, 1) ||
648 platform_device_add_data(pdev
, pdata
, sizeof(*pdata
)) ||
649 platform_device_add(pdev
))
650 platform_device_put(pdev
);
654 #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
655 static DEFINE_SPINLOCK(txx9_iocled_lock
);
657 #define TXX9_IOCLED_MAXLEDS 8
659 struct txx9_iocled_data
{
660 struct gpio_chip chip
;
662 void __iomem
*mmioaddr
;
663 struct gpio_led_platform_data pdata
;
664 struct gpio_led leds
[TXX9_IOCLED_MAXLEDS
];
665 char names
[TXX9_IOCLED_MAXLEDS
][32];
668 static int txx9_iocled_get(struct gpio_chip
*chip
, unsigned int offset
)
670 struct txx9_iocled_data
*data
=
671 container_of(chip
, struct txx9_iocled_data
, chip
);
672 return data
->cur_val
& (1 << offset
);
675 static void txx9_iocled_set(struct gpio_chip
*chip
, unsigned int offset
,
678 struct txx9_iocled_data
*data
=
679 container_of(chip
, struct txx9_iocled_data
, chip
);
681 spin_lock_irqsave(&txx9_iocled_lock
, flags
);
683 data
->cur_val
|= 1 << offset
;
685 data
->cur_val
&= ~(1 << offset
);
686 writeb(data
->cur_val
, data
->mmioaddr
);
688 spin_unlock_irqrestore(&txx9_iocled_lock
, flags
);
691 static int txx9_iocled_dir_in(struct gpio_chip
*chip
, unsigned int offset
)
696 static int txx9_iocled_dir_out(struct gpio_chip
*chip
, unsigned int offset
,
699 txx9_iocled_set(chip
, offset
, value
);
703 void __init
txx9_iocled_init(unsigned long baseaddr
,
704 int basenum
, unsigned int num
, int lowactive
,
705 const char *color
, char **deftriggers
)
707 struct txx9_iocled_data
*iocled
;
708 struct platform_device
*pdev
;
710 static char *default_triggers
[] __initdata
= {
718 deftriggers
= default_triggers
;
719 iocled
= kzalloc(sizeof(*iocled
), GFP_KERNEL
);
722 iocled
->mmioaddr
= ioremap(baseaddr
, 1);
723 if (!iocled
->mmioaddr
)
725 iocled
->chip
.get
= txx9_iocled_get
;
726 iocled
->chip
.set
= txx9_iocled_set
;
727 iocled
->chip
.direction_input
= txx9_iocled_dir_in
;
728 iocled
->chip
.direction_output
= txx9_iocled_dir_out
;
729 iocled
->chip
.label
= "iocled";
730 iocled
->chip
.base
= basenum
;
731 iocled
->chip
.ngpio
= num
;
732 if (gpiochip_add(&iocled
->chip
))
735 basenum
= iocled
->chip
.base
;
737 pdev
= platform_device_alloc("leds-gpio", basenum
);
740 iocled
->pdata
.num_leds
= num
;
741 iocled
->pdata
.leds
= iocled
->leds
;
742 for (i
= 0; i
< num
; i
++) {
743 struct gpio_led
*led
= &iocled
->leds
[i
];
744 snprintf(iocled
->names
[i
], sizeof(iocled
->names
[i
]),
745 "iocled:%s:%u", color
, i
);
746 led
->name
= iocled
->names
[i
];
747 led
->gpio
= basenum
+ i
;
748 led
->active_low
= lowactive
;
749 if (deftriggers
&& *deftriggers
)
750 led
->default_trigger
= *deftriggers
++;
752 pdev
->dev
.platform_data
= &iocled
->pdata
;
753 if (platform_device_add(pdev
))
754 platform_device_put(pdev
);
756 #else /* CONFIG_LEDS_GPIO */
757 void __init
txx9_iocled_init(unsigned long baseaddr
,
758 int basenum
, unsigned int num
, int lowactive
,
759 const char *color
, char **deftriggers
)
762 #endif /* CONFIG_LEDS_GPIO */