/* * This module is basically like leds.c/leds-idp.c. * * But it can, in the timer, also do other stuff, e.g. toggle GPIO * Ant it's a loadable/unloadable module :-) * * (c) 2002 by M&N Logistik-Lösungen Online GmbH * GPLv2, see the COPYING from http://www.gnu.org/licenses/gpl.html */ #include #include #include #include #include #include #include // Frequency for toggling #define FREQ 10 // // The Hardware uses nCS[3] // // The 4 uarts are chip-selected directly by A8..A11, so all but // one have to high. That gives // // A11 A10 A8 A9 Address UART // ------------------------------------ // 1 1 1 0 0x2E00 UART A // 1 1 0 1 0x2D00 UART A // 1 0 1 1 0x2B00 UART A // 0 1 1 1 0x2700 UART A // #define MN_UART_A (PXA_CS3_PHYS+0x2E00) #ifdef WITH_IDP_LED #define CPLD_LED 0x17C00008 #endif // UART control registers, addresses are longword-aligned, A0 and A1 are always 0 #define RHR (0<<2) #define THR (0<<2) #define IER (1<<2) #define FCR (2<<2) #define IIR (2<<2) #define LCR (3<<2) #define MCR (4<<2) #define LSR (5<<2) #define MSR (6<<2) #define SPR (7<<2) static void *uart_a; // virtual mem cookie for UART A #ifdef WITH_IDP_LED static void *led; // virtual mem cookie for CPLD LED #endif static struct timer_list timer; // our timer static int state = 0; // current bit state static void toggler_timer(unsigned long nr) { #ifdef WITH_IDP_LED writel(state << 5, led); #else if (state) RAMSES_LED_BLUE_ON() else RAMSES_LED_BLUE_OFF(); #endif writel(state, uart_a+MCR); state = 1-state; mod_timer(&timer, jiffies + (HZ/FREQ)); } static int __init toggler_init(void) { unsigned int msc1; printk("%s\n", __FUNCTION__); #if 0 // setup MSC1 for nCS[5] msc1 = (1 // ROM type SRAM | (0 << 3) // 32 bits | (10 << 4) // delay first access | (12 << 8) // delay next access | (10 << 12) // recovery time | (0 << 15) // no streaming ); MSC1 = (MSC1 & 0xFFFF) | (msc1 << 16); msc1 = MSC1; // re-read because it's written in the spec #endif // setup virtual memory cookie if (!request_mem_region(MN_UART_A, 16*4, "uart_a")) { printk(KERN_ERR "unable to reserve uart region\n"); return -1; } else { uart_a = ioremap_nocache(MN_UART_A, 16*4); if (!uart_a) { printk(KERN_ERR "unable to map uart region\n"); return -1; } } printk("uart_a phys is: x\n", (unsigned int) MN_UART_A); printk("uart_a virt is: x\n", (unsigned int) uart_a); #ifdef WITH_IDP_LED if (!request_mem_region(CPLD_LED, 4, "led")) { printk(KERN_ERR "unable to reserve led region\n"); return -1; } else { led = ioremap_nocache(CPLD_LED, 4); if (!led) { printk(KERN_ERR "unable to map led region\n"); return -1; } } printk("led phys is: x\n", (unsigned int) CPLD_LED); printk("led cookie is: x\n", (unsigned int) led); #endif // setup timer init_timer(&timer); timer.function = toggler_timer; add_timer(&timer); return 0; } static void __exit toggler_exit(void) { del_timer_sync(&timer); #ifdef WITH_IDP_LED if (led) { iounmap(led); release_mem_region(CPLD_LED, 4); } #endif if (uart_a) { iounmap(uart_a); release_mem_region(MN_UART_A, 16*4); } } module_init(toggler_init); module_exit(toggler_exit); MODULE_DESCRIPTION("Toggles hardware signals"); MODULE_LICENSE("GPL");