/* * linux/arch/arm/mach-sa1100/neponset.c * */ #include #include #include #include #include #include #include #include #include #include #include #include #include "sa1111.h" /* * Install handler for Neponset IRQ. Yes, yes... we are way down the IRQ * cascade which is not good for IRQ latency, but the hardware has been * designed that way... */ static void neponset_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs ) { int irr; for(;;){ irr = IRR & (IRR_ETHERNET | IRR_USAR | IRR_SA1111); /* Let's have all active IRQ bits high. * Note: there is a typo in the Neponset user's guide * for the SA1111 IRR level. */ irr ^= (IRR_ETHERNET | IRR_USAR); if (!irr) break; if( irr & IRR_ETHERNET ) do_IRQ(NEPONSET_ETHERNET_IRQ, regs); if( irr & IRR_USAR ) do_IRQ(NEPONSET_USAR_IRQ, regs); if( irr & IRR_SA1111 ) sa1111_IRQ_demux(irq, dev_id, regs); } } static struct irqaction neponset_irq = { name: "Neponset", handler: neponset_IRQ_demux, flags: SA_INTERRUPT }; static void __init neponset_init_irq(void) { int irq; sa1111_init_irq(-1); /* SA1111 IRQ not routed to a GPIO */ /* setup extra Neponset IRQs */ irq = NEPONSET_ETHERNET_IRQ; irq_desc[irq].valid = 1; irq_desc[irq].probe_ok = 1; irq = NEPONSET_USAR_IRQ; irq_desc[irq].valid = 1; irq_desc[irq].probe_ok = 1; set_GPIO_IRQ_edge(ASSABET_GPIO_NEP_IRQ, GPIO_RISING_EDGE); setup_arm_irq(ASSABET_IRQ_GPIO_NEP_IRQ, &neponset_irq); } static int __init neponset_init(void) { int ret; /* * The Neponset is only present on the Assabet machine type. */ if (!machine_is_assabet()) return -ENODEV; /* * Ensure that the memory bus request/grant signals are setup, * and the grant is held in its inactive state, whether or not * we actually have a Neponset attached. */ sa1110_mb_disable(); if (!machine_has_neponset()) { printk(KERN_DEBUG "Neponset expansion board not present\n"); return -ENODEV; } if (WHOAMI != 0x11) { printk(KERN_WARNING "Neponset board detected, but " "wrong ID: %02x\n", WHOAMI); return -ENODEV; } /* * Neponset has SA1111 connected to CS4. We know that after * reset the chip will be configured for variable latency IO. */ /* FIXME: setup MSC2 */ /* * Probe for a SA1111. */ ret = sa1111_probe(); if (ret < 0) return ret; /* * We found it. Wake the chip up. */ sa1111_wake(); /* * The SDRAM configuration of the SA1110 and the SA1111 must * match. This is very important to ensure that SA1111 accesses * don't corrupt the SDRAM. Note that this ungates the SA1111's * MBGNT signal, so we must have called sa1110_mb_disable() * beforehand. */ sa1111_configure_smc(1, FExtr(MDCNFG, MDCNFG_SA1110_DRAC0), FExtr(MDCNFG, MDCNFG_SA1110_TDL0)); /* * We only need to turn on DCLK whenever we want to use the * DMA. It can otherwise be held firmly in the off position. */ SKPCR |= SKPCR_DCLKEN; /* * Enable the SA1110 memory bus request and grant signals. */ sa1110_mb_enable(); neponset_init_irq(); return 0; } __initcall(neponset_init); static struct map_desc neponset_io_desc[] __initdata = { /* virtual physical length domain r w c b */ { 0xf3000000, 0x10000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* System Registers */ { 0xf4000000, 0x40000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA-1111 */ LAST_DESC }; static void neponset_set_mctrl(struct uart_port *port, u_int mctrl) { u_int mdm_ctl0 = MDM_CTL_0; if (port->mapbase == _Ser1UTCR0) { if (mctrl & TIOCM_RTS) mdm_ctl0 &= ~MDM_CTL0_RTS2; else mdm_ctl0 |= MDM_CTL0_RTS2; if (mctrl & TIOCM_DTR) mdm_ctl0 &= ~MDM_CTL0_DTR2; else mdm_ctl0 |= MDM_CTL0_DTR2; } else if (port->mapbase == _Ser3UTCR0) { if (mctrl & TIOCM_RTS) mdm_ctl0 &= ~MDM_CTL0_RTS1; else mdm_ctl0 |= MDM_CTL0_RTS1; if (mctrl & TIOCM_DTR) mdm_ctl0 &= ~MDM_CTL0_DTR1; else mdm_ctl0 |= MDM_CTL0_DTR1; } MDM_CTL_0 = mdm_ctl0; } static int neponset_get_mctrl(struct uart_port *port) { u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR; u_int mdm_ctl1 = MDM_CTL_1; if (port->mapbase == _Ser1UTCR0) { if (mdm_ctl1 & MDM_CTL1_DCD2) ret &= ~TIOCM_CD; if (mdm_ctl1 & MDM_CTL1_CTS2) ret &= ~TIOCM_CTS; if (mdm_ctl1 & MDM_CTL1_DSR2) ret &= ~TIOCM_DSR; } else if (port->mapbase == _Ser3UTCR0) { if (mdm_ctl1 & MDM_CTL1_DCD1) ret &= ~TIOCM_CD; if (mdm_ctl1 & MDM_CTL1_CTS1) ret &= ~TIOCM_CTS; if (mdm_ctl1 & MDM_CTL1_DSR1) ret &= ~TIOCM_DSR; } return ret; } static struct sa1100_port_fns neponset_port_fns __initdata = { set_mctrl: neponset_set_mctrl, get_mctrl: neponset_get_mctrl, }; void __init neponset_map_io(void) { iotable_init(neponset_io_desc); if (machine_has_neponset()) sa1100_register_uart_fns(&neponset_port_fns); }