/*
* 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");