|
From: Paul M. <le...@us...> - 2006-08-07 11:17:49
|
Update of /cvsroot/linuxsh/linux/arch/sh/boards/se/7343 In directory sc8-pr-cvs6.sourceforge.net:/tmp/cvs-serv25423/arch/sh/boards/se/7343 Added Files: Makefile io.c irq.c led.c setup.c Log Message: Add Solution Engine 7343 board support. --- NEW FILE: Makefile --- # # Makefile for the 7343 SolutionEngine specific parts of the kernel # obj-y := setup.o io.o irq.o obj-$(CONFIG_HEARTBEAT) += led.o --- NEW FILE: io.c --- /* * arch/sh/boards/se/7343/io.c * * I/O routine for SH-Mobile3AS 7343 SolutionEngine. * */ #include <linux/config.h> #include <linux/kernel.h> #include <asm/io.h> #include <asm/mach/se7343.h> #define badio(fn, a) panic("bad i/o operation %s for %08lx.", #fn, a) struct iop { unsigned long start, end; unsigned long base; struct iop *(*check) (struct iop * p, unsigned long port); unsigned char (*inb) (struct iop * p, unsigned long port); unsigned short (*inw) (struct iop * p, unsigned long port); void (*outb) (struct iop * p, unsigned char value, unsigned long port); void (*outw) (struct iop * p, unsigned short value, unsigned long port); }; struct iop * simple_check(struct iop *p, unsigned long port) { static int count; if (count < 100) count++; port &= 0xFFFF; if ((p->start <= port) && (port <= p->end)) return p; else badio(check, port); } struct iop * ide_check(struct iop *p, unsigned long port) { if (((0x1f0 <= port) && (port <= 0x1f7)) || (port == 0x3f7)) return p; return NULL; } unsigned char simple_inb(struct iop *p, unsigned long port) { return *(unsigned char *) (p->base + port); } unsigned short simple_inw(struct iop *p, unsigned long port) { return *(unsigned short *) (p->base + port); } void simple_outb(struct iop *p, unsigned char value, unsigned long port) { *(unsigned char *) (p->base + port) = value; } void simple_outw(struct iop *p, unsigned short value, unsigned long port) { *(unsigned short *) (p->base + port) = value; } unsigned char pcc_inb(struct iop *p, unsigned long port) { unsigned long addr = p->base + port + 0x40000; unsigned long v; if (port & 1) addr += 0x00400000; v = *(volatile unsigned char *) addr; return v; } void pcc_outb(struct iop *p, unsigned char value, unsigned long port) { unsigned long addr = p->base + port + 0x40000; if (port & 1) addr += 0x00400000; *(volatile unsigned char *) addr = value; } unsigned char bad_inb(struct iop *p, unsigned long port) { badio(inb, port); } void bad_outb(struct iop *p, unsigned char value, unsigned long port) { badio(inw, port); } #ifdef CONFIG_SMC91X /* MSTLANEX01 LAN at 0xb400:0000 */ static struct iop laniop = { .start = 0x00, .end = 0x0F, .base = 0x04000000, .check = simple_check, .inb = simple_inb, .inw = simple_inw, .outb = simple_outb, .outw = simple_outw, }; #endif #ifdef CONFIG_NE2000 /* NE2000 pc card NIC */ static struct iop neiop = { .start = 0x280, .end = 0x29f, .base = 0xb0600000 + 0x80, /* soft 0x280 -> hard 0x300 */ .check = simple_check, .inb = pcc_inb, .inw = simple_inw, .outb = pcc_outb, .outw = simple_outw, }; #endif #ifdef CONFIG_IDE /* CF in CF slot */ static struct iop cfiop = { .base = 0xb0600000, .check = ide_check, .inb = pcc_inb, .inw = simple_inw, .outb = pcc_outb, .outw = simple_outw, }; #endif static __inline__ struct iop * port2iop(unsigned long port) { if (0) ; #if defined(CONFIG_SMC91X) else if (laniop.check(&laniop, port)) return &laniop; #endif #if defined(CONFIG_NE2000) else if (neiop.check(&neiop, port)) return &neiop; #endif #if defined(CONFIG_IDE) else if (cfiop.check(&cfiop, port)) return &cfiop; #endif else return NULL; } static inline void delay(void) { ctrl_inw(0xac000000); ctrl_inw(0xac000000); } unsigned char sh7343se_inb(unsigned long port) { struct iop *p = port2iop(port); return (p->inb) (p, port); } unsigned char sh7343se_inb_p(unsigned long port) { unsigned char v = sh7343se_inb(port); delay(); return v; } unsigned short sh7343se_inw(unsigned long port) { struct iop *p = port2iop(port); return (p->inw) (p, port); } unsigned int sh7343se_inl(unsigned long port) { badio(inl, port); } void sh7343se_outb(unsigned char value, unsigned long port) { struct iop *p = port2iop(port); (p->outb) (p, value, port); } void sh7343se_outb_p(unsigned char value, unsigned long port) { sh7343se_outb(value, port); delay(); } void sh7343se_outw(unsigned short value, unsigned long port) { struct iop *p = port2iop(port); (p->outw) (p, value, port); } void sh7343se_outl(unsigned int value, unsigned long port) { badio(outl, port); } void sh7343se_insb(unsigned long port, void *addr, unsigned long count) { unsigned char *a = addr; struct iop *p = port2iop(port); while (count--) *a++ = (p->inb) (p, port); } void sh7343se_insw(unsigned long port, void *addr, unsigned long count) { unsigned short *a = addr; struct iop *p = port2iop(port); while (count--) *a++ = (p->inw) (p, port); } void sh7343se_insl(unsigned long port, void *addr, unsigned long count) { badio(insl, port); } void sh7343se_outsb(unsigned long port, const void *addr, unsigned long count) { unsigned char *a = (unsigned char *) addr; struct iop *p = port2iop(port); while (count--) (p->outb) (p, *a++, port); } void sh7343se_outsw(unsigned long port, const void *addr, unsigned long count) { unsigned short *a = (unsigned short *) addr; struct iop *p = port2iop(port); while (count--) (p->outw) (p, *a++, port); } void sh7343se_outsl(unsigned long port, const void *addr, unsigned long count) { badio(outsw, port); } --- NEW FILE: irq.c --- /* * arch/sh/boards/se/7343/irq.c * */ #include <linux/config.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <asm/irq.h> #include <asm/io.h> #include <asm/mach/se7343.h> static void disable_intreq_irq(unsigned int irq) { int bit = irq - OFFCHIP_IRQ_BASE; u16 val; val = ctrl_inw(PA_CPLD_IMSK); val |= 1 << bit; ctrl_outw(val, PA_CPLD_IMSK); } static void enable_intreq_irq(unsigned int irq) { int bit = irq - OFFCHIP_IRQ_BASE; u16 val; val = ctrl_inw(PA_CPLD_IMSK); val &= ~(1 << bit); ctrl_outw(val, PA_CPLD_IMSK); } static void mask_and_ack_intreq_irq(unsigned int irq) { disable_intreq_irq(irq); } static unsigned int startup_intreq_irq(unsigned int irq) { enable_intreq_irq(irq); return 0; } static void shutdown_intreq_irq(unsigned int irq) { disable_intreq_irq(irq); } static void end_intreq_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) enable_intreq_irq(irq); } static struct hw_interrupt_type intreq_irq_type = { .typename = "FPGA-IRQ", .startup = startup_intreq_irq, .shutdown = shutdown_intreq_irq, .enable = enable_intreq_irq, .disable = disable_intreq_irq, .ack = mask_and_ack_intreq_irq, .end = end_intreq_irq }; static void make_intreq_irq(unsigned int irq) { disable_irq_nosync(irq); irq_desc[irq].handler = &intreq_irq_type; disable_intreq_irq(irq); } int shmse_irq_demux(int irq) { int bit; volatile u16 val; if (irq == IRQ5_IRQ) { /* Read status Register */ val = ctrl_inw(PA_CPLD_ST); bit = ffs(val); if (bit != 0) return OFFCHIP_IRQ_BASE + bit - 1; } return irq; } /* IRQ5 is multiplexed between the following sources: * 1. PC Card socket * 2. Extension slot * 3. USB Controller * 4. Serial Controller * * We configure IRQ5 as a cascade IRQ. */ static struct irqaction irq5 = { no_action, 0, CPU_MASK_NONE, "IRQ5-cascade", NULL, NULL}; /* * Initialize IRQ setting */ void __init init_7343se_IRQ(void) { /* Setup Multiplexed interrupts */ ctrl_outw(8, PA_CPLD_MODESET); /* Set all CPLD interrupts to active * low. */ /* Mask all CPLD controller interrupts */ ctrl_outw(0x0fff, PA_CPLD_IMSK); /* PC Card interrupts */ make_intreq_irq(PC_IRQ0); make_intreq_irq(PC_IRQ1); make_intreq_irq(PC_IRQ2); make_intreq_irq(PC_IRQ3); /* Extension Slot Interrupts */ make_intreq_irq(EXT_IRQ0); make_intreq_irq(EXT_IRQ1); make_intreq_irq(EXT_IRQ2); make_intreq_irq(EXT_IRQ3); /* USB Controller interrupts */ make_intreq_irq(USB_IRQ0); make_intreq_irq(USB_IRQ1); /* Serial Controller interrupts */ make_intreq_irq(UART_IRQ0); make_intreq_irq(UART_IRQ1); /* Setup all external interrupts to be active low */ ctrl_outw(0xaaaa, INTC_ICR1); make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR+2, IRQ5_IPR_POS, IRQ5_PRIORITY); setup_irq(IRQ5_IRQ, &irq5); /* Set port control to use IRQ5 */ *(u16 *)0xA4050108 &= ~0xc; make_ipr_irq(SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY); make_ipr_irq(VPU_IRQ, VPU_IPR_ADDR, VPU_IPR_POS, 8); ctrl_outb(0x0f, INTC_IMCR5); /* enable SCIF IRQ */ make_ipr_irq(DMTE0_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY); make_ipr_irq(DMTE1_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY); make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY); make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY); make_ipr_irq(DMTE4_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY); make_ipr_irq(DMTE5_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY); /* I2C block */ make_ipr_irq(IIC0_ALI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY); make_ipr_irq(IIC0_TACKI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY); make_ipr_irq(IIC0_WAITI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY); make_ipr_irq(IIC0_DTEI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY); make_ipr_irq(IIC1_ALI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY); make_ipr_irq(IIC1_TACKI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY); make_ipr_irq(IIC1_WAITI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY); make_ipr_irq(IIC1_DTEI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY); /* SIOF */ make_ipr_irq(SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY); /* SIU */ make_ipr_irq(SIU_IRQ, SIU_IPR_ADDR, SIU_IPR_POS, SIU_PRIORITY); /* VIO interrupt */ make_ipr_irq(CEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY); make_ipr_irq(BEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY); make_ipr_irq(VEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY); /*MFI interrupt*/ make_ipr_irq(MFI_IRQ, MFI_IPR_ADDR, MFI_IPR_POS, MFI_PRIORITY); /* LCD controller */ make_ipr_irq(LCDC_IRQ, LCDC_IPR_ADDR, LCDC_IPR_POS, LCDC_PRIORITY); ctrl_outw(0x2000, PA_MRSHPC + 0x0c); /* mrshpc irq enable */ } --- NEW FILE: led.c --- /* * arch/sh/boards/se/7343/led.c * */ #include <linux/config.h> #include <linux/sched.h> #include <asm/mach/se7343.h> /* Cycle the LED's in the clasic Knightrider/Sun pattern */ void heartbeat_7343se(void) { static unsigned int cnt = 0, period = 0; volatile unsigned short *p = (volatile unsigned short *) PA_LED; static unsigned bit = 0, up = 1; cnt += 1; if (cnt < period) { return; } cnt = 0; /* Go through the points (roughly!): * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110 */ period = 110 - ((300 << FSHIFT) / ((avenrun[0] / 5) + (3 << FSHIFT))); if (up) { if (bit == 7) { bit--; up = 0; } else { bit++; } } else { if (bit == 0) { bit++; up = 1; } else { bit--; } } *p = 1 << (bit + LED_SHIFT); } --- NEW FILE: setup.c --- #include <linux/config.h> #include <linux/init.h> #include <linux/platform_device.h> #include <asm/machvec.h> #include <asm/mach/se7343.h> #include <asm/irq.h> void heartbeat_7343se(void); void init_7343se_IRQ(void); static struct resource smc91x_resources[] = { [0] = { .start = 0x10000000, .end = 0x1000000F, .flags = IORESOURCE_MEM, }, [1] = { /* * shared with other devices via externel * interrupt controller in FPGA... */ .start = EXT_IRQ2, .end = EXT_IRQ2, .flags = IORESOURCE_IRQ, }, }; static struct platform_device smc91x_device = { .name = "smc91x", .id = 0, .num_resources = ARRAY_SIZE(smc91x_resources), .resource = smc91x_resources, }; static struct platform_device *smc91x_platform_devices[] __initdata = { &smc91x_device, }; static int __init sh7343se_devices_setup(void) { return platform_add_devices(smc91x_platform_devices, ARRAY_SIZE(smc91x_platform_devices)); } static void __init sh7343se_setup(char **cmdline_p) { device_initcall(sh7343se_devices_setup); } /* * The Machine Vector */ struct sh_machine_vector mv_7343se __initmv = { .mv_name = "SolutionEngine 7343", .mv_setup = sh7343se_setup, .mv_nr_irqs = 108, .mv_inb = sh7343se_inb, .mv_inw = sh7343se_inw, .mv_inl = sh7343se_inl, .mv_outb = sh7343se_outb, .mv_outw = sh7343se_outw, .mv_outl = sh7343se_outl, .mv_inb_p = sh7343se_inb_p, .mv_inw_p = sh7343se_inw, .mv_inl_p = sh7343se_inl, .mv_outb_p = sh7343se_outb_p, .mv_outw_p = sh7343se_outw, .mv_outl_p = sh7343se_outl, .mv_insb = sh7343se_insb, .mv_insw = sh7343se_insw, .mv_insl = sh7343se_insl, .mv_outsb = sh7343se_outsb, .mv_outsw = sh7343se_outsw, .mv_outsl = sh7343se_outsl, .mv_init_irq = init_7343se_IRQ, .mv_irq_demux = shmse_irq_demux, #ifdef CONFIG_HEARTBEAT .mv_heartbeat = heartbeat_7343se, #endif }; ALIAS_MV(7343se) |