diff options
Diffstat (limited to 'arch/mips/sni')
| -rw-r--r-- | arch/mips/sni/Makefile | 4 | ||||
| -rw-r--r-- | arch/mips/sni/Platform | 11 | ||||
| -rw-r--r-- | arch/mips/sni/a20r.c | 126 | ||||
| -rw-r--r-- | arch/mips/sni/ds1216.c | 81 | ||||
| -rw-r--r-- | arch/mips/sni/eisa.c | 50 | ||||
| -rw-r--r-- | arch/mips/sni/irq.c | 22 | ||||
| -rw-r--r-- | arch/mips/sni/pcimt.c | 91 | ||||
| -rw-r--r-- | arch/mips/sni/pcimt_scache.c | 37 | ||||
| -rw-r--r-- | arch/mips/sni/pcit.c | 114 | ||||
| -rw-r--r-- | arch/mips/sni/reset.c | 7 | ||||
| -rw-r--r-- | arch/mips/sni/rm200.c | 408 | ||||
| -rw-r--r-- | arch/mips/sni/setup.c | 197 | ||||
| -rw-r--r-- | arch/mips/sni/sniprom.c | 247 | ||||
| -rw-r--r-- | arch/mips/sni/time.c | 140 |
14 files changed, 904 insertions, 631 deletions
diff --git a/arch/mips/sni/Makefile b/arch/mips/sni/Makefile index e5777b7e2bc..9d3bad3200c 100644 --- a/arch/mips/sni/Makefile +++ b/arch/mips/sni/Makefile @@ -2,5 +2,5 @@ # Makefile for the SNI specific part of the kernel # -obj-y += irq.o reset.o setup.o ds1216.o a20r.o rm200.o pcimt.o pcit.o time.o -obj-$(CONFIG_CPU_BIG_ENDIAN) += sniprom.o +obj-y += irq.o reset.o setup.o a20r.o rm200.o pcimt.o pcit.o time.o +obj-$(CONFIG_EISA) += eisa.o diff --git a/arch/mips/sni/Platform b/arch/mips/sni/Platform new file mode 100644 index 00000000000..2644a9d63c0 --- /dev/null +++ b/arch/mips/sni/Platform @@ -0,0 +1,11 @@ +# +# SNI RM +# +platform-$(CONFIG_SNI_RM) += sni/ +cflags-$(CONFIG_SNI_RM) += -I$(srctree)/arch/mips/include/asm/mach-rm +ifdef CONFIG_CPU_LITTLE_ENDIAN +load-$(CONFIG_SNI_RM) += 0xffffffff80600000 +else +load-$(CONFIG_SNI_RM) += 0xffffffff80030000 +endif +all-$(CONFIG_SNI_RM) := $(COMPRESSION_FNAME).ecoff diff --git a/arch/mips/sni/a20r.c b/arch/mips/sni/a20r.c index 31ab80f1bef..f9407e17047 100644 --- a/arch/mips/sni/a20r.c +++ b/arch/mips/sni/a20r.c @@ -10,12 +10,12 @@ #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/platform_device.h> #include <linux/serial_8250.h> #include <asm/sni.h> #include <asm/time.h> -#include <asm/ds1216.h> #define PORT(_base,_irq) \ { \ @@ -40,20 +40,34 @@ static struct platform_device a20r_serial8250_device = { }, }; +static struct resource a20r_ds1216_rsrc[] = { + { + .start = 0x1c081ffc, + .end = 0x1c081fff, + .flags = IORESOURCE_MEM + } +}; + +static struct platform_device a20r_ds1216_device = { + .name = "rtc-ds1216", + .num_resources = ARRAY_SIZE(a20r_ds1216_rsrc), + .resource = a20r_ds1216_rsrc +}; + static struct resource snirm_82596_rsrc[] = { { - .start = 0xb8000000, - .end = 0xb8000004, + .start = 0x18000000, + .end = 0x18000004, .flags = IORESOURCE_MEM }, { - .start = 0xb8010000, - .end = 0xb8010004, + .start = 0x18010000, + .end = 0x18010004, .flags = IORESOURCE_MEM }, { - .start = 0xbff00000, - .end = 0xbff00020, + .start = 0x1ff00000, + .end = 0x1ff00020, .flags = IORESOURCE_MEM }, { @@ -62,20 +76,20 @@ static struct resource snirm_82596_rsrc[] = { .flags = IORESOURCE_IRQ }, { - .flags = 0x01 /* 16bit mpu port access */ + .flags = 0x01 /* 16bit mpu port access */ } }; static struct platform_device snirm_82596_pdev = { - .name = "snirm_82596", - .num_resources = ARRAY_SIZE(snirm_82596_rsrc), - .resource = snirm_82596_rsrc + .name = "snirm_82596", + .num_resources = ARRAY_SIZE(snirm_82596_rsrc), + .resource = snirm_82596_rsrc }; static struct resource snirm_53c710_rsrc[] = { { - .start = 0xb9000000, - .end = 0xb90fffff, + .start = 0x19000000, + .end = 0x190fffff, .flags = IORESOURCE_MEM }, { @@ -86,15 +100,15 @@ static struct resource snirm_53c710_rsrc[] = { }; static struct platform_device snirm_53c710_pdev = { - .name = "snirm_53c710", - .num_resources = ARRAY_SIZE(snirm_53c710_rsrc), - .resource = snirm_53c710_rsrc + .name = "snirm_53c710", + .num_resources = ARRAY_SIZE(snirm_53c710_rsrc), + .resource = snirm_53c710_rsrc }; static struct resource sc26xx_rsrc[] = { { - .start = 0xbc070000, - .end = 0xbc0700ff, + .start = 0x1c070000, + .end = 0x1c0700ff, .flags = IORESOURCE_MEM }, { @@ -104,17 +118,36 @@ static struct resource sc26xx_rsrc[] = { } }; +#include <linux/platform_data/serial-sccnxp.h> + +static struct sccnxp_pdata sccnxp_data = { + .reg_shift = 2, + .mctrl_cfg[0] = MCTRL_SIG(DTR_OP, LINE_OP7) | + MCTRL_SIG(RTS_OP, LINE_OP3) | + MCTRL_SIG(DSR_IP, LINE_IP5) | + MCTRL_SIG(DCD_IP, LINE_IP6), + .mctrl_cfg[1] = MCTRL_SIG(DTR_OP, LINE_OP2) | + MCTRL_SIG(RTS_OP, LINE_OP1) | + MCTRL_SIG(DSR_IP, LINE_IP0) | + MCTRL_SIG(CTS_IP, LINE_IP1) | + MCTRL_SIG(DCD_IP, LINE_IP2) | + MCTRL_SIG(RNG_IP, LINE_IP3), +}; + static struct platform_device sc26xx_pdev = { - .name = "SC26xx", - .num_resources = ARRAY_SIZE(sc26xx_rsrc), - .resource = sc26xx_rsrc + .name = "sc2681", + .resource = sc26xx_rsrc, + .num_resources = ARRAY_SIZE(sc26xx_rsrc), + .dev = { + .platform_data = &sccnxp_data, + }, }; static u32 a20r_ack_hwint(void) { u32 status = read_c0_status(); - write_c0_status (status | 0x00010000); + write_c0_status(status | 0x00010000); asm volatile( " .set push \n" " .set noat \n" @@ -137,7 +170,7 @@ static u32 a20r_ack_hwint(void) " addiu %1, -1 \n" " sw $1, 0(%0) \n" " sync \n" - ".set pop \n" + ".set pop \n" : : "Jr" (PCIMT_UCONF), "Jr" (0xbc000000)); write_c0_status(status); @@ -145,33 +178,22 @@ static u32 a20r_ack_hwint(void) return status; } -static inline void unmask_a20r_irq(unsigned int irq) +static inline void unmask_a20r_irq(struct irq_data *d) { - set_c0_status(0x100 << (irq - SNI_A20R_IRQ_BASE)); + set_c0_status(0x100 << (d->irq - SNI_A20R_IRQ_BASE)); irq_enable_hazard(); } -static inline void mask_a20r_irq(unsigned int irq) +static inline void mask_a20r_irq(struct irq_data *d) { - clear_c0_status(0x100 << (irq - SNI_A20R_IRQ_BASE)); + clear_c0_status(0x100 << (d->irq - SNI_A20R_IRQ_BASE)); irq_disable_hazard(); } -static void end_a20r_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { - a20r_ack_hwint(); - unmask_a20r_irq(irq); - } -} - static struct irq_chip a20r_irq_type = { - .typename = "A20R", - .ack = mask_a20r_irq, - .mask = mask_a20r_irq, - .mask_ack = mask_a20r_irq, - .unmask = unmask_a20r_irq, - .end = end_a20r_irq, + .name = "A20R", + .irq_mask = mask_a20r_irq, + .irq_unmask = unmask_a20r_irq, }; /* @@ -182,7 +204,7 @@ static void a20r_hwint(void) u32 cause, status; int irq; - clear_c0_status (IE_IRQ0); + clear_c0_status(IE_IRQ0); status = a20r_ack_hwint(); cause = read_c0_cause(); @@ -197,16 +219,15 @@ void __init sni_a20r_irq_init(void) int i; for (i = SNI_A20R_IRQ_BASE + 2 ; i < SNI_A20R_IRQ_BASE + 8; i++) - set_irq_chip(i, &a20r_irq_type); + irq_set_chip_and_handler(i, &a20r_irq_type, handle_level_irq); sni_hwint = a20r_hwint; change_c0_status(ST0_IM, IE_IRQ0); - setup_irq (SNI_A20R_IRQ_BASE + 3, &sni_isa_irq); + setup_irq(SNI_A20R_IRQ_BASE + 3, &sni_isa_irq); } void sni_a20r_init(void) { - ds1216_base = (volatile unsigned char *) SNI_DS1216_A20R_BASE; - rtc_mips_get_time = ds1216_get_cmos_time; + /* FIXME, remove if not needed */ } static int __init snirm_a20r_setup_devinit(void) @@ -214,13 +235,14 @@ static int __init snirm_a20r_setup_devinit(void) switch (sni_brd_type) { case SNI_BRD_TOWER_OASIC: case SNI_BRD_MINITOWER: - platform_device_register(&snirm_82596_pdev); - platform_device_register(&snirm_53c710_pdev); - platform_device_register(&sc26xx_pdev); - platform_device_register(&a20r_serial8250_device); - break; + platform_device_register(&snirm_82596_pdev); + platform_device_register(&snirm_53c710_pdev); + platform_device_register(&sc26xx_pdev); + platform_device_register(&a20r_serial8250_device); + platform_device_register(&a20r_ds1216_device); + sni_eisa_root_init(); + break; } - return 0; } diff --git a/arch/mips/sni/ds1216.c b/arch/mips/sni/ds1216.c deleted file mode 100644 index 1d92732c14f..00000000000 --- a/arch/mips/sni/ds1216.c +++ /dev/null @@ -1,81 +0,0 @@ - -#include <linux/bcd.h> -#include <linux/time.h> - -#include <asm/ds1216.h> - -volatile unsigned char *ds1216_base; - -/* - * Read the 64 bit we'd like to have - It a series - * of 64 bits showing up in the LSB of the base register. - * - */ -static unsigned char *ds1216_read(void) -{ - static unsigned char rdbuf[8]; - unsigned char c; - int i, j; - - for (i = 0; i < 8; i++) { - c = 0x0; - for (j = 0; j < 8; j++) { - c |= (*ds1216_base & 0x1) << j; - } - rdbuf[i] = c; - } - - return rdbuf; -} - -static void ds1216_switch_ds_to_clock(void) -{ - unsigned char magic[] = { - 0xc5, 0x3a, 0xa3, 0x5c, 0xc5, 0x3a, 0xa3, 0x5c - }; - int i,j,c; - - /* Reset magic pointer */ - c = *ds1216_base; - - /* Write 64 bit magic to DS1216 */ - for (i = 0; i < 8; i++) { - c = magic[i]; - for (j = 0; j < 8; j++) { - *ds1216_base = c; - c = c >> 1; - } - } -} - -unsigned long ds1216_get_cmos_time(void) -{ - unsigned char *rdbuf; - unsigned int year, month, date, hour, min, sec; - - ds1216_switch_ds_to_clock(); - rdbuf = ds1216_read(); - - sec = BCD2BIN(DS1216_SEC(rdbuf)); - min = BCD2BIN(DS1216_MIN(rdbuf)); - hour = BCD2BIN(DS1216_HOUR(rdbuf)); - date = BCD2BIN(DS1216_DATE(rdbuf)); - month = BCD2BIN(DS1216_MONTH(rdbuf)); - year = BCD2BIN(DS1216_YEAR(rdbuf)); - - if (DS1216_1224(rdbuf) && DS1216_AMPM(rdbuf)) - hour+=12; - - if (year < 70) - year += 2000; - else - year += 1900; - - return mktime(year, month, date, hour, min, sec); -} - -int ds1216_set_rtc_mmss(unsigned long nowtime) -{ - printk("ds1216_set_rtc_mmss called but not implemented\n"); - return -1; -} diff --git a/arch/mips/sni/eisa.c b/arch/mips/sni/eisa.c new file mode 100644 index 00000000000..179b5d556ad --- /dev/null +++ b/arch/mips/sni/eisa.c @@ -0,0 +1,50 @@ +/* + * Virtual EISA root driver. + * Acts as a placeholder if we don't have a proper EISA bridge. + * + * (C) 2003 Marc Zyngier <maz@wild-wind.fr.eu.org> + * modified for SNI usage by Thomas Bogendoerfer + * + * This code is released under the GPL version 2. + */ + +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/eisa.h> +#include <linux/init.h> + +/* The default EISA device parent (virtual root device). + * Now use a platform device, since that's the obvious choice. */ + +static struct platform_device eisa_root_dev = { + .name = "eisa", + .id = 0, +}; + +static struct eisa_root_device eisa_bus_root = { + .dev = &eisa_root_dev.dev, + .bus_base_addr = 0, + .res = &ioport_resource, + .slots = EISA_MAX_SLOTS, + .dma_mask = 0xffffffff, + .force_probe = 1, +}; + +int __init sni_eisa_root_init(void) +{ + int r; + + r = platform_device_register(&eisa_root_dev); + if (!r) + return r; + + dev_set_drvdata(&eisa_root_dev.dev, &eisa_bus_root); + + if (eisa_root_register(&eisa_bus_root)) { + /* A real bridge may have been registered before + * us. So quietly unregister. */ + platform_device_unregister(&eisa_root_dev); + return -1; + } + return 0; +} diff --git a/arch/mips/sni/irq.c b/arch/mips/sni/irq.c index 9ccffdfb828..ac61b90bcc6 100644 --- a/arch/mips/sni/irq.c +++ b/arch/mips/sni/irq.c @@ -35,7 +35,7 @@ static irqreturn_t sni_isa_irq_handler(int dummy, void *p) if (unlikely(irq < 0)) return IRQ_NONE; - do_IRQ(irq); + generic_handle_irq(irq); return IRQ_HANDLED; } @@ -58,25 +58,25 @@ void __init arch_init_irq(void) case SNI_BRD_10NEW: case SNI_BRD_TOWER_OASIC: case SNI_BRD_MINITOWER: - sni_a20r_irq_init(); - break; + sni_a20r_irq_init(); + break; case SNI_BRD_PCI_TOWER: - sni_pcit_irq_init(); - break; + sni_pcit_irq_init(); + break; case SNI_BRD_PCI_TOWER_CPLUS: - sni_pcit_cplus_irq_init(); - break; + sni_pcit_cplus_irq_init(); + break; case SNI_BRD_RM200: - sni_rm200_irq_init(); - break; + sni_rm200_irq_init(); + break; case SNI_BRD_PCI_MTOWER: case SNI_BRD_PCI_DESKTOP: case SNI_BRD_PCI_MTOWER_CPLUS: - sni_pcimt_irq_init(); - break; + sni_pcimt_irq_init(); + break; } } diff --git a/arch/mips/sni/pcimt.c b/arch/mips/sni/pcimt.c index 9ee208daa8b..12336c2a649 100644 --- a/arch/mips/sni/pcimt.c +++ b/arch/mips/sni/pcimt.c @@ -6,15 +6,15 @@ * for more details. * * Copyright (C) 1996, 97, 98, 2000, 03, 04, 06 Ralf Baechle (ralf@linux-mips.org) - * Copyright (C) 2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de) + * Copyright (C) 2006,2007 Thomas Bogendoerfer (tsbogend@alpha.franken.de) */ #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/pci.h> #include <linux/serial_8250.h> -#include <asm/mc146818-time.h> #include <asm/sni.h> #include <asm/time.h> #include <asm/i8259.h> @@ -29,7 +29,7 @@ static void __init sni_pcimt_sc_init(void) scsiz = cacheconf & 7; if (scsiz == 0) { - printk("Second level cache is deactived.\n"); + printk("Second level cache is deactivated.\n"); return; } if (scsiz >= 6) { @@ -60,7 +60,7 @@ static inline void sni_pcimt_detect(void) p += sprintf(p, "%s PCI", (csmsr & 0x80) ? "RM200" : "RM300"); if ((csmsr & 0x80) == 0) p += sprintf(p, ", board revision %s", - (csmsr & 0x20) ? "D" : "C"); + (csmsr & 0x20) ? "D" : "C"); asic = csmsr & 0x80; asic = (csmsr & 0x08) ? asic : !asic; p += sprintf(p, ", ASIC PCI Rev %s", asic ? "1.0" : "1.1"); @@ -90,6 +90,26 @@ static struct platform_device pcimt_serial8250_device = { }, }; +static struct resource pcimt_cmos_rsrc[] = { + { + .start = 0x70, + .end = 0x71, + .flags = IORESOURCE_IO + }, + { + .start = 8, + .end = 8, + .flags = IORESOURCE_IRQ + } +}; + +static struct platform_device pcimt_cmos_device = { + .name = "rtc_cmos", + .num_resources = ARRAY_SIZE(pcimt_cmos_rsrc), + .resource = pcimt_cmos_rsrc +}; + + static struct resource sni_io_resource = { .start = 0x00000000UL, .end = 0x03bfffffUL, @@ -131,6 +151,19 @@ static struct resource pcimt_io_resources[] = { } }; +static struct resource pcimt_mem_resources[] = { + { + /* + * this region should only be 4 bytes long, + * but it's 16MB on all RM300C I've checked + */ + .start = 0x1a000000, + .end = 0x1affffff, + .name = "PCI INT ACK", + .flags = IORESOURCE_BUSY + } +}; + static struct resource sni_mem_resource = { .start = 0x18000000UL, .end = 0x1fbfffffUL, @@ -145,46 +178,42 @@ static void __init sni_pcimt_resource_init(void) /* request I/O space for devices used on all i[345]86 PCs */ for (i = 0; i < ARRAY_SIZE(pcimt_io_resources); i++) request_resource(&sni_io_resource, pcimt_io_resources + i); + /* request MEM space for devices used on all i[345]86 PCs */ + for (i = 0; i < ARRAY_SIZE(pcimt_mem_resources); i++) + request_resource(&sni_mem_resource, pcimt_mem_resources + i); } extern struct pci_ops sni_pcimt_ops; +#ifdef CONFIG_PCI static struct pci_controller sni_controller = { .pci_ops = &sni_pcimt_ops, .mem_resource = &sni_mem_resource, .mem_offset = 0x00000000UL, .io_resource = &sni_io_resource, .io_offset = 0x00000000UL, - .io_map_base = SNI_PORT_BASE + .io_map_base = SNI_PORT_BASE }; +#endif -static void enable_pcimt_irq(unsigned int irq) +static void enable_pcimt_irq(struct irq_data *d) { - unsigned int mask = 1 << (irq - PCIMT_IRQ_INT2); + unsigned int mask = 1 << (d->irq - PCIMT_IRQ_INT2); *(volatile u8 *) PCIMT_IRQSEL |= mask; } -void disable_pcimt_irq(unsigned int irq) +void disable_pcimt_irq(struct irq_data *d) { - unsigned int mask = ~(1 << (irq - PCIMT_IRQ_INT2)); + unsigned int mask = ~(1 << (d->irq - PCIMT_IRQ_INT2)); *(volatile u8 *) PCIMT_IRQSEL &= mask; } -static void end_pcimt_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_pcimt_irq(irq); -} - static struct irq_chip pcimt_irq_type = { - .typename = "PCIMT", - .ack = disable_pcimt_irq, - .mask = disable_pcimt_irq, - .mask_ack = disable_pcimt_irq, - .unmask = enable_pcimt_irq, - .end = end_pcimt_irq, + .name = "PCIMT", + .irq_mask = disable_pcimt_irq, + .irq_unmask = enable_pcimt_irq, }; /* @@ -209,9 +238,9 @@ static void pcimt_hwint1(void) if (pend & IT_EISA) { int irq; /* - * Note: ASIC PCI's builtin interrupt achknowledge feature is + * Note: ASIC PCI's builtin interrupt acknowledge feature is * broken. Using it may result in loss of some or all i8259 - * interupts, so don't use PCIMT_INT_ACKNOWLEDGE ... + * interrupts, so don't use PCIMT_INT_ACKNOWLEDGE ... */ irq = i8259_irq(); if (unlikely(irq < 0)) @@ -249,9 +278,9 @@ static void sni_pcimt_hwint(void) u32 pending = read_c0_cause() & read_c0_status(); if (pending & C_IRQ5) - do_IRQ (MIPS_CPU_IRQ_BASE + 7); + do_IRQ(MIPS_CPU_IRQ_BASE + 7); else if (pending & C_IRQ4) - do_IRQ (MIPS_CPU_IRQ_BASE + 6); + do_IRQ(MIPS_CPU_IRQ_BASE + 6); else if (pending & C_IRQ3) pcimt_hwint3(); else if (pending & C_IRQ1) @@ -269,18 +298,15 @@ void __init sni_pcimt_irq_init(void) mips_cpu_irq_init(); /* Actually we've got more interrupts to handle ... */ for (i = PCIMT_IRQ_INT2; i <= PCIMT_IRQ_SCSI; i++) - set_irq_chip(i, &pcimt_irq_type); + irq_set_chip_and_handler(i, &pcimt_irq_type, handle_level_irq); sni_hwint = sni_pcimt_hwint; change_c0_status(ST0_IM, IE_IRQ1|IE_IRQ3); } -void sni_pcimt_init(void) +void __init sni_pcimt_init(void) { sni_pcimt_detect(); sni_pcimt_sc_init(); - rtc_mips_get_time = mc146818_get_cmos_time; - rtc_mips_set_time = mc146818_set_rtc_mmss; - board_time_init = sni_cpu_time_init; ioport_resource.end = sni_io_resource.end; #ifdef CONFIG_PCI PCIBIOS_MIN_IO = 0x9000; @@ -295,8 +321,9 @@ static int __init snirm_pcimt_setup_devinit(void) case SNI_BRD_PCI_MTOWER: case SNI_BRD_PCI_DESKTOP: case SNI_BRD_PCI_MTOWER_CPLUS: - platform_device_register(&pcimt_serial8250_device); - break; + platform_device_register(&pcimt_serial8250_device); + platform_device_register(&pcimt_cmos_device); + break; } return 0; diff --git a/arch/mips/sni/pcimt_scache.c b/arch/mips/sni/pcimt_scache.c deleted file mode 100644 index a59d457fa8b..00000000000 --- a/arch/mips/sni/pcimt_scache.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * arch/mips/sni/pcimt_scache.c - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (c) 1997, 1998 by Ralf Baechle - */ -#include <linux/init.h> -#include <linux/kernel.h> -#include <asm/bcache.h> -#include <asm/sni.h> - -#define cacheconf (*(volatile unsigned int *)PCIMT_CACHECONF) -#define invspace (*(volatile unsigned int *)PCIMT_INVSPACE) - -void __init sni_pcimt_sc_init(void) -{ - unsigned int scsiz, sc_size; - - scsiz = cacheconf & 7; - if (scsiz == 0) { - printk("Second level cache is deactived.\n"); - return; - } - if (scsiz >= 6) { - printk("Invalid second level cache size configured, " - "deactivating second level cache.\n"); - cacheconf = 0; - return; - } - - sc_size = 128 << scsiz; - printk("%dkb second level cache detected, deactivating.\n", sc_size); - cacheconf = 0; -} diff --git a/arch/mips/sni/pcit.c b/arch/mips/sni/pcit.c index 00d151f4d12..05bb51676e8 100644 --- a/arch/mips/sni/pcit.c +++ b/arch/mips/sni/pcit.c @@ -10,10 +10,10 @@ #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/pci.h> #include <linux/serial_8250.h> -#include <asm/mc146818-time.h> #include <asm/sni.h> #include <asm/time.h> #include <asm/irq_cpu.h> @@ -58,6 +58,30 @@ static struct platform_device pcit_cplus_serial8250_device = { }, }; +static struct resource pcit_cmos_rsrc[] = { + { + .start = 0x70, + .end = 0x71, + .flags = IORESOURCE_IO + }, + { + .start = 8, + .end = 8, + .flags = IORESOURCE_IRQ + } +}; + +static struct platform_device pcit_cmos_device = { + .name = "rtc_cmos", + .num_resources = ARRAY_SIZE(pcit_cmos_rsrc), + .resource = pcit_cmos_rsrc +}; + +static struct platform_device pcit_pcspeaker_pdev = { + .name = "pcspkr", + .id = -1, +}; + static struct resource sni_io_resource = { .start = 0x00000000UL, .end = 0x03bfffffUL, @@ -104,13 +128,6 @@ static struct resource pcit_io_resources[] = { } }; -static struct resource sni_mem_resource = { - .start = 0x18000000UL, - .end = 0x1fbfffffUL, - .name = "PCIT PCI MEM", - .flags = IORESOURCE_MEM -}; - static void __init sni_pcit_resource_init(void) { int i; @@ -123,42 +140,42 @@ static void __init sni_pcit_resource_init(void) extern struct pci_ops sni_pcit_ops; +#ifdef CONFIG_PCI +static struct resource sni_mem_resource = { + .start = 0x18000000UL, + .end = 0x1fbfffffUL, + .name = "PCIT PCI MEM", + .flags = IORESOURCE_MEM +}; + static struct pci_controller sni_pcit_controller = { .pci_ops = &sni_pcit_ops, .mem_resource = &sni_mem_resource, .mem_offset = 0x00000000UL, .io_resource = &sni_io_resource, .io_offset = 0x00000000UL, - .io_map_base = SNI_PORT_BASE + .io_map_base = SNI_PORT_BASE }; +#endif /* CONFIG_PCI */ -static void enable_pcit_irq(unsigned int irq) +static void enable_pcit_irq(struct irq_data *d) { - u32 mask = 1 << (irq - SNI_PCIT_INT_START + 24); + u32 mask = 1 << (d->irq - SNI_PCIT_INT_START + 24); *(volatile u32 *)SNI_PCIT_INT_REG |= mask; } -void disable_pcit_irq(unsigned int irq) +void disable_pcit_irq(struct irq_data *d) { - u32 mask = 1 << (irq - SNI_PCIT_INT_START + 24); + u32 mask = 1 << (d->irq - SNI_PCIT_INT_START + 24); *(volatile u32 *)SNI_PCIT_INT_REG &= ~mask; } -void end_pcit_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_pcit_irq(irq); -} - static struct irq_chip pcit_irq_type = { - .typename = "PCIT", - .ack = disable_pcit_irq, - .mask = disable_pcit_irq, - .mask_ack = disable_pcit_irq, - .unmask = enable_pcit_irq, - .end = end_pcit_irq, + .name = "PCIT", + .irq_mask = disable_pcit_irq, + .irq_unmask = enable_pcit_irq, }; static void pcit_hwint1(void) @@ -170,8 +187,8 @@ static void pcit_hwint1(void) irq = ffs((pending >> 16) & 0x7f); if (likely(irq > 0)) - do_IRQ (irq + SNI_PCIT_INT_START - 1); - set_c0_status (IE_IRQ1); + do_IRQ(irq + SNI_PCIT_INT_START - 1); + set_c0_status(IE_IRQ1); } static void pcit_hwint0(void) @@ -183,8 +200,8 @@ static void pcit_hwint0(void) irq = ffs((pending >> 16) & 0x3f); if (likely(irq > 0)) - do_IRQ (irq + SNI_PCIT_INT_START - 1); - set_c0_status (IE_IRQ0); + do_IRQ(irq + SNI_PCIT_INT_START - 1); + set_c0_status(IE_IRQ0); } static void sni_pcit_hwint(void) @@ -194,11 +211,11 @@ static void sni_pcit_hwint(void) if (pending & C_IRQ1) pcit_hwint1(); else if (pending & C_IRQ2) - do_IRQ (MIPS_CPU_IRQ_BASE + 4); + do_IRQ(MIPS_CPU_IRQ_BASE + 4); else if (pending & C_IRQ3) - do_IRQ (MIPS_CPU_IRQ_BASE + 5); + do_IRQ(MIPS_CPU_IRQ_BASE + 5); else if (pending & C_IRQ5) - do_IRQ (MIPS_CPU_IRQ_BASE + 7); + do_IRQ(MIPS_CPU_IRQ_BASE + 7); } static void sni_pcit_hwint_cplus(void) @@ -208,13 +225,13 @@ static void sni_pcit_hwint_cplus(void) if (pending & C_IRQ0) pcit_hwint0(); else if (pending & C_IRQ1) - do_IRQ (MIPS_CPU_IRQ_BASE + 3); + do_IRQ(MIPS_CPU_IRQ_BASE + 3); else if (pending & C_IRQ2) - do_IRQ (MIPS_CPU_IRQ_BASE + 4); + do_IRQ(MIPS_CPU_IRQ_BASE + 4); else if (pending & C_IRQ3) - do_IRQ (MIPS_CPU_IRQ_BASE + 5); + do_IRQ(MIPS_CPU_IRQ_BASE + 5); else if (pending & C_IRQ5) - do_IRQ (MIPS_CPU_IRQ_BASE + 7); + do_IRQ(MIPS_CPU_IRQ_BASE + 7); } void __init sni_pcit_irq_init(void) @@ -223,11 +240,11 @@ void __init sni_pcit_irq_init(void) mips_cpu_irq_init(); for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++) - set_irq_chip(i, &pcit_irq_type); + irq_set_chip_and_handler(i, &pcit_irq_type, handle_level_irq); *(volatile u32 *)SNI_PCIT_INT_REG = 0; sni_hwint = sni_pcit_hwint; change_c0_status(ST0_IM, IE_IRQ1); - setup_irq (SNI_PCIT_INT_START + 6, &sni_isa_irq); + setup_irq(SNI_PCIT_INT_START + 6, &sni_isa_irq); } void __init sni_pcit_cplus_irq_init(void) @@ -236,18 +253,15 @@ void __init sni_pcit_cplus_irq_init(void) mips_cpu_irq_init(); for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++) - set_irq_chip(i, &pcit_irq_type); + irq_set_chip_and_handler(i, &pcit_irq_type, handle_level_irq); *(volatile u32 *)SNI_PCIT_INT_REG = 0x40000000; sni_hwint = sni_pcit_hwint_cplus; change_c0_status(ST0_IM, IE_IRQ0); - setup_irq (MIPS_CPU_IRQ_BASE + 3, &sni_isa_irq); + setup_irq(MIPS_CPU_IRQ_BASE + 3, &sni_isa_irq); } -void sni_pcit_init(void) +void __init sni_pcit_init(void) { - rtc_mips_get_time = mc146818_get_cmos_time; - rtc_mips_set_time = mc146818_set_rtc_mmss; - board_time_init = sni_cpu_time_init; ioport_resource.end = sni_io_resource.end; #ifdef CONFIG_PCI PCIBIOS_MIN_IO = 0x9000; @@ -260,12 +274,16 @@ static int __init snirm_pcit_setup_devinit(void) { switch (sni_brd_type) { case SNI_BRD_PCI_TOWER: - platform_device_register(&pcit_serial8250_device); - break; + platform_device_register(&pcit_serial8250_device); + platform_device_register(&pcit_cmos_device); + platform_device_register(&pcit_pcspeaker_pdev); + break; case SNI_BRD_PCI_TOWER_CPLUS: - platform_device_register(&pcit_cplus_serial8250_device); - break; + platform_device_register(&pcit_cplus_serial8250_device); + platform_device_register(&pcit_cmos_device); + platform_device_register(&pcit_pcspeaker_pdev); + break; } return 0; } diff --git a/arch/mips/sni/reset.c b/arch/mips/sni/reset.c index 2eada8aea68..244f9427625 100644 --- a/arch/mips/sni/reset.c +++ b/arch/mips/sni/reset.c @@ -5,7 +5,6 @@ */ #include <asm/io.h> #include <asm/reboot.h> -#include <asm/system.h> #include <asm/sni.h> /* @@ -35,15 +34,11 @@ void sni_machine_restart(char *command) kb_wait(); for (j = 0; j < 100000 ; j++) /* nothing */; - outb_p(0xfe,0x64); /* pulse reset low */ + outb_p(0xfe, 0x64); /* pulse reset low */ } } } -void sni_machine_halt(void) -{ -} - void sni_machine_power_off(void) { *(volatile unsigned char *)PCIMT_CSWCSM = 0xfd; diff --git a/arch/mips/sni/rm200.c b/arch/mips/sni/rm200.c index b82ff129f5e..a046b302623 100644 --- a/arch/mips/sni/rm200.c +++ b/arch/mips/sni/rm200.c @@ -5,31 +5,37 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de) + * Copyright (C) 2006,2007 Thomas Bogendoerfer (tsbogend@alpha.franken.de) + * + * i8259 parts ripped out of arch/mips/kernel/i8259.c */ +#include <linux/delay.h> #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/platform_device.h> #include <linux/serial_8250.h> +#include <linux/io.h> #include <asm/sni.h> #include <asm/time.h> -#include <asm/ds1216.h> #include <asm/irq_cpu.h> -#define PORT(_base,_irq) \ +#define RM200_I8259A_IRQ_BASE 32 + +#define MEMPORT(_base,_irq) \ { \ - .iobase = _base, \ + .mapbase = _base, \ .irq = _irq, \ .uartclk = 1843200, \ - .iotype = UPIO_PORT, \ - .flags = UPF_BOOT_AUTOCONF, \ + .iotype = UPIO_MEM, \ + .flags = UPF_BOOT_AUTOCONF|UPF_IOREMAP, \ } static struct plat_serial8250_port rm200_data[] = { - PORT(0x3f8, 4), - PORT(0x2f8, 3), + MEMPORT(0x160003f8, RM200_I8259A_IRQ_BASE + 4), + MEMPORT(0x160002f8, RM200_I8259A_IRQ_BASE + 3), { }, }; @@ -41,20 +47,34 @@ static struct platform_device rm200_serial8250_device = { }, }; +static struct resource rm200_ds1216_rsrc[] = { + { + .start = 0x1cd41ffc, + .end = 0x1cd41fff, + .flags = IORESOURCE_MEM + } +}; + +static struct platform_device rm200_ds1216_device = { + .name = "rtc-ds1216", + .num_resources = ARRAY_SIZE(rm200_ds1216_rsrc), + .resource = rm200_ds1216_rsrc +}; + static struct resource snirm_82596_rm200_rsrc[] = { { - .start = 0xb8000000, - .end = 0xb80fffff, + .start = 0x18000000, + .end = 0x180fffff, .flags = IORESOURCE_MEM }, { - .start = 0xbb000000, - .end = 0xbb000004, + .start = 0x1b000000, + .end = 0x1b000004, .flags = IORESOURCE_MEM }, { - .start = 0xbff00000, - .end = 0xbff00020, + .start = 0x1ff00000, + .end = 0x1ff00020, .flags = IORESOURCE_MEM }, { @@ -68,15 +88,15 @@ static struct resource snirm_82596_rm200_rsrc[] = { }; static struct platform_device snirm_82596_rm200_pdev = { - .name = "snirm_82596", - .num_resources = ARRAY_SIZE(snirm_82596_rm200_rsrc), - .resource = snirm_82596_rm200_rsrc + .name = "snirm_82596", + .num_resources = ARRAY_SIZE(snirm_82596_rm200_rsrc), + .resource = snirm_82596_rm200_rsrc }; static struct resource snirm_53c710_rm200_rsrc[] = { { - .start = 0xb9000000, - .end = 0xb90fffff, + .start = 0x19000000, + .end = 0x190fffff, .flags = IORESOURCE_MEM }, { @@ -87,57 +107,344 @@ static struct resource snirm_53c710_rm200_rsrc[] = { }; static struct platform_device snirm_53c710_rm200_pdev = { - .name = "snirm_53c710", - .num_resources = ARRAY_SIZE(snirm_53c710_rm200_rsrc), - .resource = snirm_53c710_rm200_rsrc + .name = "snirm_53c710", + .num_resources = ARRAY_SIZE(snirm_53c710_rm200_rsrc), + .resource = snirm_53c710_rm200_rsrc }; static int __init snirm_setup_devinit(void) { if (sni_brd_type == SNI_BRD_RM200) { platform_device_register(&rm200_serial8250_device); + platform_device_register(&rm200_ds1216_device); platform_device_register(&snirm_82596_rm200_pdev); platform_device_register(&snirm_53c710_rm200_pdev); + sni_eisa_root_init(); } return 0; } device_initcall(snirm_setup_devinit); +/* + * RM200 has an ISA and an EISA bus. The iSA bus is only used + * for onboard devices and also has twi i8259 PICs. Since these + * PICs are no accessible via inb/outb the following code uses + * readb/writeb to access them + */ + +static DEFINE_RAW_SPINLOCK(sni_rm200_i8259A_lock); +#define PIC_CMD 0x00 +#define PIC_IMR 0x01 +#define PIC_ISR PIC_CMD +#define PIC_POLL PIC_ISR +#define PIC_OCW3 PIC_ISR + +/* i8259A PIC related value */ +#define PIC_CASCADE_IR 2 +#define MASTER_ICW4_DEFAULT 0x01 +#define SLAVE_ICW4_DEFAULT 0x01 + +/* + * This contains the irq mask for both 8259A irq controllers, + */ +static unsigned int rm200_cached_irq_mask = 0xffff; +static __iomem u8 *rm200_pic_master; +static __iomem u8 *rm200_pic_slave; + +#define cached_master_mask (rm200_cached_irq_mask) +#define cached_slave_mask (rm200_cached_irq_mask >> 8) + +static void sni_rm200_disable_8259A_irq(struct irq_data *d) +{ + unsigned int mask, irq = d->irq - RM200_I8259A_IRQ_BASE; + unsigned long flags; + + mask = 1 << irq; + raw_spin_lock_irqsave(&sni_rm200_i8259A_lock, flags); + rm200_cached_irq_mask |= mask; + if (irq & 8) + writeb(cached_slave_mask, rm200_pic_slave + PIC_IMR); + else + writeb(cached_master_mask, rm200_pic_master + PIC_IMR); + raw_spin_unlock_irqrestore(&sni_rm200_i8259A_lock, flags); +} + +static void sni_rm200_enable_8259A_irq(struct irq_data *d) +{ + unsigned int mask, irq = d->irq - RM200_I8259A_IRQ_BASE; + unsigned long flags; + + mask = ~(1 << irq); + raw_spin_lock_irqsave(&sni_rm200_i8259A_lock, flags); + rm200_cached_irq_mask &= mask; + if (irq & 8) + writeb(cached_slave_mask, rm200_pic_slave + PIC_IMR); + else + writeb(cached_master_mask, rm200_pic_master + PIC_IMR); + raw_spin_unlock_irqrestore(&sni_rm200_i8259A_lock, flags); +} + +static inline int sni_rm200_i8259A_irq_real(unsigned int irq) +{ + int value; + int irqmask = 1 << irq; + + if (irq < 8) { + writeb(0x0B, rm200_pic_master + PIC_CMD); + value = readb(rm200_pic_master + PIC_CMD) & irqmask; + writeb(0x0A, rm200_pic_master + PIC_CMD); + return value; + } + writeb(0x0B, rm200_pic_slave + PIC_CMD); /* ISR register */ + value = readb(rm200_pic_slave + PIC_CMD) & (irqmask >> 8); + writeb(0x0A, rm200_pic_slave + PIC_CMD); + return value; +} + +/* + * Careful! The 8259A is a fragile beast, it pretty + * much _has_ to be done exactly like this (mask it + * first, _then_ send the EOI, and the order of EOI + * to the two 8259s is important! + */ +void sni_rm200_mask_and_ack_8259A(struct irq_data *d) +{ + unsigned int irqmask, irq = d->irq - RM200_I8259A_IRQ_BASE; + unsigned long flags; + + irqmask = 1 << irq; + raw_spin_lock_irqsave(&sni_rm200_i8259A_lock, flags); + /* + * Lightweight spurious IRQ detection. We do not want + * to overdo spurious IRQ handling - it's usually a sign + * of hardware problems, so we only do the checks we can + * do without slowing down good hardware unnecessarily. + * + * Note that IRQ7 and IRQ15 (the two spurious IRQs + * usually resulting from the 8259A-1|2 PICs) occur + * even if the IRQ is masked in the 8259A. Thus we + * can check spurious 8259A IRQs without doing the + * quite slow i8259A_irq_real() call for every IRQ. + * This does not cover 100% of spurious interrupts, + * but should be enough to warn the user that there + * is something bad going on ... + */ + if (rm200_cached_irq_mask & irqmask) + goto spurious_8259A_irq; + rm200_cached_irq_mask |= irqmask; + +handle_real_irq: + if (irq & 8) { + readb(rm200_pic_slave + PIC_IMR); + writeb(cached_slave_mask, rm200_pic_slave + PIC_IMR); + writeb(0x60+(irq & 7), rm200_pic_slave + PIC_CMD); + writeb(0x60+PIC_CASCADE_IR, rm200_pic_master + PIC_CMD); + } else { + readb(rm200_pic_master + PIC_IMR); + writeb(cached_master_mask, rm200_pic_master + PIC_IMR); + writeb(0x60+irq, rm200_pic_master + PIC_CMD); + } + raw_spin_unlock_irqrestore(&sni_rm200_i8259A_lock, flags); + return; + +spurious_8259A_irq: + /* + * this is the slow path - should happen rarely. + */ + if (sni_rm200_i8259A_irq_real(irq)) + /* + * oops, the IRQ _is_ in service according to the + * 8259A - not spurious, go handle it. + */ + goto handle_real_irq; + + { + static int spurious_irq_mask; + /* + * At this point we can be sure the IRQ is spurious, + * lets ACK and report it. [once per IRQ] + */ + if (!(spurious_irq_mask & irqmask)) { + printk(KERN_DEBUG + "spurious RM200 8259A interrupt: IRQ%d.\n", irq); + spurious_irq_mask |= irqmask; + } + atomic_inc(&irq_err_count); + /* + * Theoretically we do not have to handle this IRQ, + * but in Linux this does not cause problems and is + * simpler for us. + */ + goto handle_real_irq; + } +} -#define SNI_RM200_INT_STAT_REG 0xbc000000 -#define SNI_RM200_INT_ENA_REG 0xbc080000 +static struct irq_chip sni_rm200_i8259A_chip = { + .name = "RM200-XT-PIC", + .irq_mask = sni_rm200_disable_8259A_irq, + .irq_unmask = sni_rm200_enable_8259A_irq, + .irq_mask_ack = sni_rm200_mask_and_ack_8259A, +}; + +/* + * Do the traditional i8259 interrupt polling thing. This is for the few + * cases where no better interrupt acknowledge method is available and we + * absolutely must touch the i8259. + */ +static inline int sni_rm200_i8259_irq(void) +{ + int irq; + + raw_spin_lock(&sni_rm200_i8259A_lock); + + /* Perform an interrupt acknowledge cycle on controller 1. */ + writeb(0x0C, rm200_pic_master + PIC_CMD); /* prepare for poll */ + irq = readb(rm200_pic_master + PIC_CMD) & 7; + if (irq == PIC_CASCADE_IR) { + /* + * Interrupt is cascaded so perform interrupt + * acknowledge on controller 2. + */ + writeb(0x0C, rm200_pic_slave + PIC_CMD); /* prepare for poll */ + irq = (readb(rm200_pic_slave + PIC_CMD) & 7) + 8; + } + + if (unlikely(irq == 7)) { + /* + * This may be a spurious interrupt. + * + * Read the interrupt status register (ISR). If the most + * significant bit is not set then there is no valid + * interrupt. + */ + writeb(0x0B, rm200_pic_master + PIC_ISR); /* ISR register */ + if (~readb(rm200_pic_master + PIC_ISR) & 0x80) + irq = -1; + } + + raw_spin_unlock(&sni_rm200_i8259A_lock); + + return likely(irq >= 0) ? irq + RM200_I8259A_IRQ_BASE : irq; +} + +void sni_rm200_init_8259A(void) +{ + unsigned long flags; + + raw_spin_lock_irqsave(&sni_rm200_i8259A_lock, flags); + + writeb(0xff, rm200_pic_master + PIC_IMR); + writeb(0xff, rm200_pic_slave + PIC_IMR); + + writeb(0x11, rm200_pic_master + PIC_CMD); + writeb(0, rm200_pic_master + PIC_IMR); + writeb(1U << PIC_CASCADE_IR, rm200_pic_master + PIC_IMR); + writeb(MASTER_ICW4_DEFAULT, rm200_pic_master + PIC_IMR); + writeb(0x11, rm200_pic_slave + PIC_CMD); + writeb(8, rm200_pic_slave + PIC_IMR); + writeb(PIC_CASCADE_IR, rm200_pic_slave + PIC_IMR); + writeb(SLAVE_ICW4_DEFAULT, rm200_pic_slave + PIC_IMR); + udelay(100); /* wait for 8259A to initialize */ + + writeb(cached_master_mask, rm200_pic_master + PIC_IMR); + writeb(cached_slave_mask, rm200_pic_slave + PIC_IMR); + + raw_spin_unlock_irqrestore(&sni_rm200_i8259A_lock, flags); +} + +/* + * IRQ2 is cascade interrupt to second interrupt controller + */ +static struct irqaction sni_rm200_irq2 = { + .handler = no_action, + .name = "cascade", + .flags = IRQF_NO_THREAD, +}; + +static struct resource sni_rm200_pic1_resource = { + .name = "onboard ISA pic1", + .start = 0x16000020, + .end = 0x16000023, + .flags = IORESOURCE_BUSY +}; + +static struct resource sni_rm200_pic2_resource = { + .name = "onboard ISA pic2", + .start = 0x160000a0, + .end = 0x160000a3, + .flags = IORESOURCE_BUSY +}; + +/* ISA irq handler */ +static irqreturn_t sni_rm200_i8259A_irq_handler(int dummy, void *p) +{ + int irq; + + irq = sni_rm200_i8259_irq(); + if (unlikely(irq < 0)) + return IRQ_NONE; + + do_IRQ(irq); + return IRQ_HANDLED; +} + +struct irqaction sni_rm200_i8259A_irq = { + .handler = sni_rm200_i8259A_irq_handler, + .name = "onboard ISA", + .flags = IRQF_SHARED +}; + +void __init sni_rm200_i8259_irqs(void) +{ + int i; + + rm200_pic_master = ioremap_nocache(0x16000020, 4); + if (!rm200_pic_master) + return; + rm200_pic_slave = ioremap_nocache(0x160000a0, 4); + if (!rm200_pic_slave) { + iounmap(rm200_pic_master); + return; + } + + insert_resource(&iomem_resource, &sni_rm200_pic1_resource); + insert_resource(&iomem_resource, &sni_rm200_pic2_resource); + + sni_rm200_init_8259A(); + + for (i = RM200_I8259A_IRQ_BASE; i < RM200_I8259A_IRQ_BASE + 16; i++) + irq_set_chip_and_handler(i, &sni_rm200_i8259A_chip, + handle_level_irq); + + setup_irq(RM200_I8259A_IRQ_BASE + PIC_CASCADE_IR, &sni_rm200_irq2); +} + + +#define SNI_RM200_INT_STAT_REG CKSEG1ADDR(0xbc000000) +#define SNI_RM200_INT_ENA_REG CKSEG1ADDR(0xbc080000) #define SNI_RM200_INT_START 24 #define SNI_RM200_INT_END 28 -static void enable_rm200_irq(unsigned int irq) +static void enable_rm200_irq(struct irq_data *d) { - unsigned int mask = 1 << (irq - SNI_RM200_INT_START); + unsigned int mask = 1 << (d->irq - SNI_RM200_INT_START); *(volatile u8 *)SNI_RM200_INT_ENA_REG &= ~mask; } -void disable_rm200_irq(unsigned int irq) +void disable_rm200_irq(struct irq_data *d) { - unsigned int mask = 1 << (irq - SNI_RM200_INT_START); + unsigned int mask = 1 << (d->irq - SNI_RM200_INT_START); *(volatile u8 *)SNI_RM200_INT_ENA_REG |= mask; } -void end_rm200_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_rm200_irq(irq); -} - static struct irq_chip rm200_irq_type = { - .typename = "RM200", - .ack = disable_rm200_irq, - .mask = disable_rm200_irq, - .mask_ack = disable_rm200_irq, - .unmask = enable_rm200_irq, - .end = end_rm200_irq, + .name = "RM200", + .irq_mask = disable_rm200_irq, + .irq_unmask = enable_rm200_irq, }; static void sni_rm200_hwint(void) @@ -148,16 +455,16 @@ static void sni_rm200_hwint(void) int irq; if (pending & C_IRQ5) - do_IRQ (MIPS_CPU_IRQ_BASE + 7); + do_IRQ(MIPS_CPU_IRQ_BASE + 7); else if (pending & C_IRQ0) { - clear_c0_status (IE_IRQ0); + clear_c0_status(IE_IRQ0); mask = *(volatile u8 *)SNI_RM200_INT_ENA_REG ^ 0x1f; stat = *(volatile u8 *)SNI_RM200_INT_STAT_REG ^ 0x14; irq = ffs(stat & mask & 0x1f); if (likely(irq > 0)) - do_IRQ (irq + SNI_RM200_INT_START - 1); - set_c0_status (IE_IRQ0); + do_IRQ(irq + SNI_RM200_INT_START - 1); + set_c0_status(IE_IRQ0); } } @@ -167,20 +474,17 @@ void __init sni_rm200_irq_init(void) * (volatile u8 *)SNI_RM200_INT_ENA_REG = 0x1f; + sni_rm200_i8259_irqs(); mips_cpu_irq_init(); /* Actually we've got more interrupts to handle ... */ for (i = SNI_RM200_INT_START; i <= SNI_RM200_INT_END; i++) - set_irq_chip(i, &rm200_irq_type); + irq_set_chip_and_handler(i, &rm200_irq_type, handle_level_irq); sni_hwint = sni_rm200_hwint; change_c0_status(ST0_IM, IE_IRQ0); - setup_irq (SNI_RM200_INT_START + 0, &sni_isa_irq); + setup_irq(SNI_RM200_INT_START + 0, &sni_rm200_i8259A_irq); + setup_irq(SNI_RM200_INT_START + 1, &sni_isa_irq); } -void sni_rm200_init(void) +void __init sni_rm200_init(void) { - set_io_port_base(SNI_PORT_BASE + 0x02000000); - ioport_resource.end += 0x02000000; - ds1216_base = (volatile unsigned char *) SNI_DS1216_RM200_BASE; - rtc_mips_get_time = ds1216_get_cmos_time; - board_time_init = sni_cpu_time_init; } diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c index 68d7cf609b4..efad85c8c82 100644 --- a/arch/mips/sni/setup.c +++ b/arch/mips/sni/setup.c @@ -6,32 +6,39 @@ * for more details. * * Copyright (C) 1996, 97, 98, 2000, 03, 04, 06 Ralf Baechle (ralf@linux-mips.org) - * Copyright (C) 2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de) + * Copyright (C) 2006,2007 Thomas Bogendoerfer (tsbogend@alpha.franken.de) */ #include <linux/eisa.h> #include <linux/init.h> +#include <linux/export.h> #include <linux/console.h> #include <linux/fb.h> #include <linux/screen_info.h> -#ifdef CONFIG_ARC -#include <asm/arc/types.h> +#ifdef CONFIG_FW_ARC +#include <asm/fw/arc/types.h> #include <asm/sgialib.h> #endif +#ifdef CONFIG_FW_SNIPROM +#include <asm/mipsprom.h> +#endif + +#include <asm/bootinfo.h> +#include <asm/cpu.h> #include <asm/io.h> #include <asm/reboot.h> #include <asm/sni.h> unsigned int sni_brd_type; +EXPORT_SYMBOL(sni_brd_type); extern void sni_machine_restart(char *command); -extern void sni_machine_halt(void); extern void sni_machine_power_off(void); static void __init sni_display_setup(void) { -#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) && defined(CONFIG_ARC) +#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) && defined(CONFIG_FW_ARC) struct screen_info *si = &screen_info; DISPLAY_STATUS *di; @@ -48,47 +55,209 @@ static void __init sni_display_setup(void) #endif } +static void __init sni_console_setup(void) +{ +#ifndef CONFIG_FW_ARC + char *ctype; + char *cdev; + char *baud; + int port; + static char options[8] __initdata; + + cdev = prom_getenv("console_dev"); + if (strncmp(cdev, "tty", 3) == 0) { + ctype = prom_getenv("console"); + switch (*ctype) { + default: + case 'l': + port = 0; + baud = prom_getenv("lbaud"); + break; + case 'r': + port = 1; + baud = prom_getenv("rbaud"); + break; + } + if (baud) + strcpy(options, baud); + if (strncmp(cdev, "tty552", 6) == 0) + add_preferred_console("ttyS", port, + baud ? options : NULL); + else + add_preferred_console("ttySC", port, + baud ? options : NULL); + } +#endif +} + +#ifdef DEBUG +static void __init sni_idprom_dump(void) +{ + int i; + + pr_debug("SNI IDProm dump:\n"); + for (i = 0; i < 256; i++) { + if (i%16 == 0) + pr_debug("%04x ", i); + + printk("%02x ", *(unsigned char *) (SNI_IDPROM_BASE + i)); + + if (i % 16 == 15) + printk("\n"); + } +} +#endif void __init plat_mem_setup(void) { + int cputype; + set_io_port_base(SNI_PORT_BASE); // ioport_resource.end = sni_io_resource.end; /* * Setup (E)ISA I/O memory access stuff */ - isa_slot_offset = 0xb0000000; #ifdef CONFIG_EISA EISA_bus = 1; #endif + sni_brd_type = *(unsigned char *)SNI_IDPROM_BRDTYPE; + cputype = *(unsigned char *)SNI_IDPROM_CPUTYPE; + switch (sni_brd_type) { + case SNI_BRD_TOWER_OASIC: + switch (cputype) { + case SNI_CPU_M8030: + system_type = "RM400-330"; + break; + case SNI_CPU_M8031: + system_type = "RM400-430"; + break; + case SNI_CPU_M8037: + system_type = "RM400-530"; + break; + case SNI_CPU_M8034: + system_type = "RM400-730"; + break; + default: + system_type = "RM400-xxx"; + break; + } + break; + case SNI_BRD_MINITOWER: + switch (cputype) { + case SNI_CPU_M8021: + case SNI_CPU_M8043: + system_type = "RM400-120"; + break; + case SNI_CPU_M8040: + system_type = "RM400-220"; + break; + case SNI_CPU_M8053: + system_type = "RM400-225"; + break; + case SNI_CPU_M8050: + system_type = "RM400-420"; + break; + default: + system_type = "RM400-xxx"; + break; + } + break; + case SNI_BRD_PCI_TOWER: + system_type = "RM400-Cxx"; + break; + case SNI_BRD_RM200: + system_type = "RM200-xxx"; + break; + case SNI_BRD_PCI_MTOWER: + system_type = "RM300-Cxx"; + break; + case SNI_BRD_PCI_DESKTOP: + switch (read_c0_prid() & PRID_IMP_MASK) { + case PRID_IMP_R4600: + case PRID_IMP_R4700: + system_type = "RM200-C20"; + break; + case PRID_IMP_R5000: + system_type = "RM200-C40"; + break; + default: + system_type = "RM200-Cxx"; + break; + } + break; + case SNI_BRD_PCI_TOWER_CPLUS: + system_type = "RM400-Exx"; + break; + case SNI_BRD_PCI_MTOWER_CPLUS: + system_type = "RM300-Exx"; + break; + } + pr_debug("Found SNI brdtype %02x name %s\n", sni_brd_type, system_type); + +#ifdef DEBUG + sni_idprom_dump(); +#endif + switch (sni_brd_type) { case SNI_BRD_10: case SNI_BRD_10NEW: case SNI_BRD_TOWER_OASIC: case SNI_BRD_MINITOWER: - sni_a20r_init(); - break; + sni_a20r_init(); + break; case SNI_BRD_PCI_TOWER: case SNI_BRD_PCI_TOWER_CPLUS: - sni_pcit_init(); + sni_pcit_init(); break; case SNI_BRD_RM200: - sni_rm200_init(); - break; + sni_rm200_init(); + break; case SNI_BRD_PCI_MTOWER: case SNI_BRD_PCI_DESKTOP: case SNI_BRD_PCI_MTOWER_CPLUS: - sni_pcimt_init(); - break; + sni_pcimt_init(); + break; } _machine_restart = sni_machine_restart; - _machine_halt = sni_machine_halt; pm_power_off = sni_machine_power_off; sni_display_setup(); + sni_console_setup(); +} + +#ifdef CONFIG_PCI + +#include <linux/pci.h> +#include <video/vga.h> +#include <video/cirrus.h> + +static void quirk_cirrus_ram_size(struct pci_dev *dev) +{ + u16 cmd; + + /* + * firmware doesn't set the ram size correct, so we + * need to do it here, otherwise we get screen corruption + * on older Cirrus chips + */ + pci_read_config_word(dev, PCI_COMMAND, &cmd); + if ((cmd & (PCI_COMMAND_IO|PCI_COMMAND_MEMORY)) + == (PCI_COMMAND_IO|PCI_COMMAND_MEMORY)) { + vga_wseq(NULL, CL_SEQR6, 0x12); /* unlock all extension registers */ + vga_wseq(NULL, CL_SEQRF, 0x18); + } } + +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5434_8, + quirk_cirrus_ram_size); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5436, + quirk_cirrus_ram_size); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446, + quirk_cirrus_ram_size); +#endif diff --git a/arch/mips/sni/sniprom.c b/arch/mips/sni/sniprom.c deleted file mode 100644 index 643366eb854..00000000000 --- a/arch/mips/sni/sniprom.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Big Endian PROM code for SNI RM machines - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2005-2006 Florian Lohoff (flo@rfc822.org) - * Copyright (C) 2005-2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de) - */ - -#define DEBUG - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/string.h> -#include <linux/console.h> - -#include <asm/addrspace.h> -#include <asm/sni.h> -#include <asm/mipsprom.h> -#include <asm/bootinfo.h> - -/* special SNI prom calls */ -/* - * This does not exist in all proms - SINIX compares - * the prom env variable "version" against "2.0008" - * or greater. If lesser it tries to probe interesting - * registers - */ -#define PROM_GET_MEMCONF 58 - -#define PROM_VEC (u64 *)CKSEG1ADDR(0x1fc00000) -#define PROM_ENTRY(x) (PROM_VEC + (x)) - - -static int *(*__prom_putchar)(int) = (int *(*)(int))PROM_ENTRY(PROM_PUTCHAR); - -void prom_putchar(char c) -{ - __prom_putchar(c); -} - -static char *(*__prom_getenv)(char *) = (char *(*)(char *))PROM_ENTRY(PROM_GETENV); -static void (*__prom_get_memconf)(void *) = (void (*)(void *))PROM_ENTRY(PROM_GET_MEMCONF); - -char *prom_getenv (char *s) -{ - return __prom_getenv(s); -} - -void __init prom_free_prom_memory(void) -{ -} - -/* - * /proc/cpuinfo system type - * - */ -static const char *systype = "Unknown"; -const char *get_system_type(void) -{ - return systype; -} - -#define SNI_IDPROM_BASE 0xbff00000 -#define SNI_IDPROM_MEMSIZE (SNI_IDPROM_BASE+0x28) /* Memsize in 16MB quantities */ -#define SNI_IDPROM_BRDTYPE (SNI_IDPROM_BASE+0x29) /* Board Type */ -#define SNI_IDPROM_CPUTYPE (SNI_IDPROM_BASE+0x30) /* CPU Type */ - -#define SNI_IDPROM_SIZE 0x1000 - -#ifdef DEBUG -static void sni_idprom_dump(void) -{ - int i; - - pr_debug("SNI IDProm dump:\n"); - for (i = 0; i < 256; i++) { - if (i%16 == 0) - pr_debug("%04x ", i); - - printk("%02x ", *(unsigned char *) (SNI_IDPROM_BASE + i)); - - if (i % 16 == 15) - printk("\n"); - } -} -#endif - -static void sni_mem_init(void ) -{ - int i, memsize; - struct membank { - u32 size; - u32 base; - u32 size2; - u32 pad1; - u32 pad2; - } memconf[8]; - - /* MemSIZE from prom in 16MByte chunks */ - memsize = *((unsigned char *) SNI_IDPROM_MEMSIZE) * 16; - - pr_debug("IDProm memsize: %lu MByte\n", memsize); - - /* get memory bank layout from prom */ - __prom_get_memconf(&memconf); - - pr_debug("prom_get_mem_conf memory configuration:\n"); - for (i = 0;i < 8 && memconf[i].size; i++) { - if (sni_brd_type == SNI_BRD_PCI_TOWER || - sni_brd_type == SNI_BRD_PCI_TOWER_CPLUS) { - if (memconf[i].base >= 0x20000000 && - memconf[i].base < 0x30000000) { - memconf[i].base -= 0x20000000; - } - } - pr_debug("Bank%d: %08x @ %08x\n", i, - memconf[i].size, memconf[i].base); - add_memory_region(memconf[i].base, memconf[i].size, BOOT_MEM_RAM); - } -} - -static void __init sni_console_setup(void) -{ - char *ctype; - char *cdev; - char *baud; - int port; - static char options[8]; - - cdev = prom_getenv ("console_dev"); - if (strncmp (cdev, "tty", 3) == 0) { - ctype = prom_getenv ("console"); - switch (*ctype) { - default: - case 'l': - port = 0; - baud = prom_getenv("lbaud"); - break; - case 'r': - port = 1; - baud = prom_getenv("rbaud"); - break; - } - if (baud) - strcpy(options, baud); - add_preferred_console("ttyS", port, baud ? options : NULL); - } -} - -void __init prom_init(void) -{ - int argc = fw_arg0; - char **argv = (void *)fw_arg1; - int i; - int cputype; - - sni_brd_type = *(unsigned char *)SNI_IDPROM_BRDTYPE; - cputype = *(unsigned char *)SNI_IDPROM_CPUTYPE; - switch (sni_brd_type) { - case SNI_BRD_TOWER_OASIC: - switch (cputype) { - case SNI_CPU_M8030: - systype = "RM400-330"; - break; - case SNI_CPU_M8031: - systype = "RM400-430"; - break; - case SNI_CPU_M8037: - systype = "RM400-530"; - break; - case SNI_CPU_M8034: - systype = "RM400-730"; - break; - default: - systype = "RM400-xxx"; - break; - } - break; - case SNI_BRD_MINITOWER: - switch (cputype) { - case SNI_CPU_M8021: - case SNI_CPU_M8043: - systype = "RM400-120"; - break; - case SNI_CPU_M8040: - systype = "RM400-220"; - break; - case SNI_CPU_M8053: - systype = "RM400-225"; - break; - case SNI_CPU_M8050: - systype = "RM400-420"; - break; - default: - systype = "RM400-xxx"; - break; - } - break; - case SNI_BRD_PCI_TOWER: - systype = "RM400-Cxx"; - break; - case SNI_BRD_RM200: - systype = "RM200-xxx"; - break; - case SNI_BRD_PCI_MTOWER: - systype = "RM300-Cxx"; - break; - case SNI_BRD_PCI_DESKTOP: - switch (read_c0_prid() & 0xff00) { - case PRID_IMP_R4600: - case PRID_IMP_R4700: - systype = "RM200-C20"; - break; - case PRID_IMP_R5000: - systype = "RM200-C40"; - break; - default: - systype = "RM200-Cxx"; - break; - } - break; - case SNI_BRD_PCI_TOWER_CPLUS: - systype = "RM400-Exx"; - break; - case SNI_BRD_PCI_MTOWER_CPLUS: - systype = "RM300-Exx"; - break; - } - pr_debug("Found SNI brdtype %02x name %s\n", sni_brd_type,systype); - -#ifdef DEBUG - sni_idprom_dump(); -#endif - sni_mem_init(); - sni_console_setup(); - - /* copy prom cmdline parameters to kernel cmdline */ - for (i = 1; i < argc; i++) { - strcat(arcs_cmdline, argv[i]); - if (i < (argc - 1)) - strcat(arcs_cmdline, " "); - } -} - diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c index 20028fc7757..cf8ec568b9d 100644 --- a/arch/mips/sni/time.c +++ b/arch/mips/sni/time.c @@ -1,64 +1,120 @@ #include <linux/types.h> +#include <linux/i8253.h> #include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/smp.h> #include <linux/time.h> +#include <linux/clockchips.h> #include <asm/sni.h> #include <asm/time.h> +#include <asm-generic/rtc.h> -#define SNI_CLOCK_TICK_RATE 3686400 -#define SNI_COUNTER2_DIV 64 -#define SNI_COUNTER0_DIV ((SNI_CLOCK_TICK_RATE / SNI_COUNTER2_DIV) / HZ) +#define SNI_CLOCK_TICK_RATE 3686400 +#define SNI_COUNTER2_DIV 64 +#define SNI_COUNTER0_DIV ((SNI_CLOCK_TICK_RATE / SNI_COUNTER2_DIV) / HZ) -static void sni_a20r_timer_ack(void) +static void a20r_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) { - *(volatile u8 *)A20R_PT_TIM0_ACK = 0x0; wmb(); + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0x34; + wmb(); + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV; + wmb(); + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV >> 8; + wmb(); + + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0xb4; + wmb(); + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV; + wmb(); + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV >> 8; + wmb(); + + break; + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + break; + case CLOCK_EVT_MODE_RESUME: + break; + } +} + +static struct clock_event_device a20r_clockevent_device = { + .name = "a20r-timer", + .features = CLOCK_EVT_FEAT_PERIODIC, + + /* .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */ + + .rating = 300, + .irq = SNI_A20R_IRQ_TIMER, + .set_mode = a20r_set_mode, +}; + +static irqreturn_t a20r_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *cd = dev_id; + + *(volatile u8 *)A20R_PT_TIM0_ACK = 0; + wmb(); + + cd->event_handler(cd); + + return IRQ_HANDLED; } +static struct irqaction a20r_irqaction = { + .handler = a20r_interrupt, + .flags = IRQF_PERCPU | IRQF_TIMER, + .name = "a20r-timer", +}; + /* * a20r platform uses 2 counters to divide the input frequency. * Counter 2 output is connected to Counter 0 & 1 input. */ -static void __init sni_a20r_timer_setup(struct irqaction *irq) +static void __init sni_a20r_timer_setup(void) { - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0x34; wmb(); - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = (SNI_COUNTER0_DIV) & 0xff; wmb(); - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = (SNI_COUNTER0_DIV >> 8) & 0xff; wmb(); - - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0xb4; wmb(); - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = (SNI_COUNTER2_DIV) & 0xff; wmb(); - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = (SNI_COUNTER2_DIV >> 8) & 0xff; wmb(); - - setup_irq(SNI_A20R_IRQ_TIMER, irq); - mips_timer_ack = sni_a20r_timer_ack; + struct clock_event_device *cd = &a20r_clockevent_device; + struct irqaction *action = &a20r_irqaction; + unsigned int cpu = smp_processor_id(); + + cd->cpumask = cpumask_of(cpu); + clockevents_register_device(cd); + action->dev_id = cd; + setup_irq(SNI_A20R_IRQ_TIMER, &a20r_irqaction); } -#define SNI_8254_TICK_RATE 1193182UL +#define SNI_8254_TICK_RATE 1193182UL -#define SNI_8254_TCSAMP_COUNTER ((SNI_8254_TICK_RATE / HZ) + 255) +#define SNI_8254_TCSAMP_COUNTER ((SNI_8254_TICK_RATE / HZ) + 255) static __init unsigned long dosample(void) { u32 ct0, ct1; - volatile u8 msb, lsb; + volatile u8 msb; /* Start the counter. */ - outb_p (0x34, 0x43); + outb_p(0x34, 0x43); outb_p(SNI_8254_TCSAMP_COUNTER & 0xff, 0x40); - outb (SNI_8254_TCSAMP_COUNTER >> 8, 0x40); + outb(SNI_8254_TCSAMP_COUNTER >> 8, 0x40); /* Get initial counter invariant */ ct0 = read_c0_count(); /* Latch and spin until top byte of counter0 is zero */ do { - outb (0x00, 0x43); - lsb = inb (0x40); - msb = inb (0x40); + outb(0x00, 0x43); + (void) inb(0x40); + msb = inb(0x40); ct1 = read_c0_count(); } while (msb); /* Stop the counter. */ - outb (0x38, 0x43); + outb(0x38, 0x43); /* * Return the difference, this is how far the r4k counter increments * for every 1/HZ seconds. We round off the nearest 1 MHz of master @@ -71,7 +127,7 @@ static __init unsigned long dosample(void) /* * Here we need to calibrate the cycle counter to at least be close. */ -__init void sni_cpu_time_init(void) +void __init plat_time_init(void) { unsigned long r4k_ticks[3]; unsigned long r4k_tick; @@ -115,34 +171,20 @@ __init void sni_cpu_time_init(void) (int) (r4k_tick % (500000 / HZ))); mips_hpt_frequency = r4k_tick * HZ; -} -/* - * R4k counter based timer interrupt. Works on RM200-225 and possibly - * others but not on RM400 - */ -static void __init sni_cpu_timer_setup(struct irqaction *irq) -{ - setup_irq(SNI_MIPS_IRQ_CPU_TIMER, irq); -} - -void __init plat_timer_setup(struct irqaction *irq) -{ switch (sni_brd_type) { case SNI_BRD_10: case SNI_BRD_10NEW: case SNI_BRD_TOWER_OASIC: case SNI_BRD_MINITOWER: - sni_a20r_timer_setup (irq); - break; - - case SNI_BRD_PCI_TOWER: - case SNI_BRD_RM200: - case SNI_BRD_PCI_MTOWER: - case SNI_BRD_PCI_DESKTOP: - case SNI_BRD_PCI_TOWER_CPLUS: - case SNI_BRD_PCI_MTOWER_CPLUS: - sni_cpu_timer_setup (irq); - break; + sni_a20r_timer_setup(); + break; } + setup_pit_timer(); +} + +void read_persistent_clock(struct timespec *ts) +{ + ts->tv_sec = -1; + ts->tv_nsec = 0; } |
