From ca7294b98645f0d2345178e249c17f8be342859b Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 6 Aug 2007 14:15:57 +0000 Subject: Add generic gpio support to rdc, convert the led driver to be a platform driver, need to convert the flash driver as well SVN-Revision: 8348 --- .../linux/rdc-2.6/files/arch/i386/mach-rdc/gpio.c | 81 +++ .../rdc-2.6/files/arch/i386/mach-rdc/platform.c | 73 ++ .../rdc-2.6/files/drivers/leds/leds-rdc3211.c | 87 +-- target/linux/rdc-2.6/files/include/asm-i386/gpio.h | 6 + .../files/include/asm-i386/mach-generic/gpio.h | 15 + .../rdc-2.6/files/include/asm-i386/mach-rdc/gpio.h | 56 ++ .../files/include/asm-i386/mach-rdc/rdc321x_defs.h | 1 + target/linux/rdc-2.6/patches/000-rdc_fixes.patch | 787 +-------------------- 8 files changed, 261 insertions(+), 845 deletions(-) create mode 100644 target/linux/rdc-2.6/files/arch/i386/mach-rdc/gpio.c create mode 100644 target/linux/rdc-2.6/files/arch/i386/mach-rdc/platform.c create mode 100644 target/linux/rdc-2.6/files/include/asm-i386/gpio.h create mode 100644 target/linux/rdc-2.6/files/include/asm-i386/mach-generic/gpio.h create mode 100644 target/linux/rdc-2.6/files/include/asm-i386/mach-rdc/gpio.h create mode 100644 target/linux/rdc-2.6/files/include/asm-i386/mach-rdc/rdc321x_defs.h (limited to 'target') diff --git a/target/linux/rdc-2.6/files/arch/i386/mach-rdc/gpio.c b/target/linux/rdc-2.6/files/arch/i386/mach-rdc/gpio.c new file mode 100644 index 0000000000..eadb15235e --- /dev/null +++ b/target/linux/rdc-2.6/files/arch/i386/mach-rdc/gpio.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2007, OpenWrt.org, Florian Fainelli + * RDC321x architecture specific GPIO support + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +#define RDC3210_CFGREG_ADDR 0x0CF8 +#define RDC3210_CFGREG_DATA 0x0CFC + +static unsigned int rdc_gpio_read(unsigned gpio) +{ + unsigned int val; + + val = 0x80000000 | (7 << 11) | ((0x48)); + outl(val, RDC3210_CFGREG_ADDR); + udelay(10); + val = inl(RDC3210_CFGREG_DATA); + val |= (0x1 << gpio); + outl(val, RDC3210_CFGREG_DATA); + udelay(10); + val = 0x80000000 | (7 << 11) | ((0x4C)); + outl(val, RDC3210_CFGREG_ADDR); + udelay(10); + val = inl(RDC3210_CFGREG_DATA); + + return val; +} + +void rdc_gpio_write(unsigned int val) +{ + if (val) { + outl(val, RDC3210_CFGREG_DATA); + udelay(10); + } +} + +int rdc_gpio_get_value(unsigned gpio) +{ + return ((int)rdc_gpio_read(gpio)); +} +EXPORT_SYMBOL(rdc_gpio_get_value); + +void rdc_gpio_set_value(unsigned gpio, int value) +{ + unsigned int val; + + val = rdc_gpio_read(gpio); + + if (value) + val &= ~(0x1 << gpio); + else + val |= (0x1 << gpio); + + rdc_gpio_write(val); +} +EXPORT_SYMBOL(rdc_gpio_set_value); + +int rdc_gpio_direction_input(unsigned gpio) +{ + return 0; +} +EXPORT_SYMBOL(rdc_gpio_direction_input); + +int rdc_gpio_direction_output(unsigned gpio, int value) +{ + return 0; +} +EXPORT_SYMBOL(rdc_gpio_direction_output); + + diff --git a/target/linux/rdc-2.6/files/arch/i386/mach-rdc/platform.c b/target/linux/rdc-2.6/files/arch/i386/mach-rdc/platform.c new file mode 100644 index 0000000000..aa245a052b --- /dev/null +++ b/target/linux/rdc-2.6/files/arch/i386/mach-rdc/platform.c @@ -0,0 +1,73 @@ +/* + * $Id: platform.c 8331 2007-08-03 15:59:23Z florian $ + * + * Generic RDC321x platform devices + * + * Copyright (C) 2007 OpenWrt.org + * Copyright (C) 2007 Florian Fainelli + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include +#include +#include + +#include +#include + +/* FIXME : Flash */ +static struct resource rdc_flash_resource[] = { + [0] = { + .start = RDC_FLASH_BASE, + .end = RDC_FLASH_BASE+CONFIG_MTD_RDC3210_SIZE-1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device rdc_flash_device = { + .name = "rdc321x-flash", + .id = -1, + .num_resources = ARRAY_SIZE(rdc_flash_resource), + .resource = rdc_flash_resource, +}; + +/* LEDS */ +static struct platform_device rdc321x_leds = { + .name = "rdc321x-leds", + .id = -1, + .num_resources = 0, +}; + +static int __init rdc_board_setup(void) +{ + int err; + + err = platform_device_register(&rdc_flash_device); + if (err) + printk(KERN_ALERT "rdc321x: failed to register flash\n"); + + err = platform_device_register(&rdc321x_leds); + if (err) + printk(KERN_ALERT "rdc321x: failed to register LEDS\n"); + + return err; +} + +arch_initcall(rdc_board_setup); diff --git a/target/linux/rdc-2.6/files/drivers/leds/leds-rdc3211.c b/target/linux/rdc-2.6/files/drivers/leds/leds-rdc3211.c index b98b43a5b5..b45a10e0a6 100644 --- a/target/linux/rdc-2.6/files/drivers/leds/leds-rdc3211.c +++ b/target/linux/rdc-2.6/files/drivers/leds/leds-rdc3211.c @@ -10,100 +10,67 @@ */ #include +#include #include #include #include #include +#include #include +#include -#define LED_VAL 0x8000384C // the data ofset of gpio 0~30 +int gpio; +module_param(gpio, int, 0444); +MODULE_PARM_DESC(gpio, " GPIO line"); -static struct platform_device *pdev; - -static void rdc3211_led_set(struct led_classdev *led_cdev, enum led_brightness brightness) +static void rdc321x_led_set(struct led_classdev *led_cdev, enum led_brightness brightness) { - unsigned long ul_ledstat = 0xffffffff; - unsigned long led_bit = 1 << (led_cdev->flags); - - if (brightness) - ul_ledstat &= ~led_bit; - else - ul_ledstat|= led_bit; - - outl(LED_VAL, 0xcf8); - outl(ul_ledstat, 0xcfc); + gpio_set_value(gpio, brightness ? 1 : 0); } -static struct led_classdev rdc3211_power_led = { - .name = "rdc3211:power", - .flags = 15, - .brightness_set = rdc3211_led_set, +static struct led_classdev rdc321x_dmz_led = { + .name = "rdc321x:dmz", + .brightness_set = rdc321x_led_set, }; -static struct led_classdev rdc3211_dmz_led = { - .name = "rdc3211:dmz", - .flags = 16, - .brightness_set = rdc3211_led_set, -}; - -static int rdc3211_leds_probe(struct platform_device *pdev) +static int rdc321x_leds_probe(struct platform_device *pdev) { - int ret; - - ret = led_classdev_register(&pdev->dev, &rdc3211_power_led); - if (ret < 0) - return ret; - - ret = led_classdev_register(&pdev->dev, &rdc3211_dmz_led); - if (ret < 0) - led_classdev_unregister(&rdc3211_power_led); - - return ret; + return led_classdev_register(&pdev->dev, &rdc321x_dmz_led); } -static int rdc3211_leds_remove(struct platform_device *pdev) +static int rdc321x_leds_remove(struct platform_device *pdev) { - led_classdev_unregister(&rdc3211_power_led); - led_classdev_unregister(&rdc3211_dmz_led); + led_classdev_unregister(&rdc321x_dmz_led); return 0; } -static struct platform_driver rdc3211_leds_driver = { - .probe = rdc3211_leds_probe, - .remove = rdc3211_leds_remove, +static struct platform_driver rdc321x_leds_driver = { + .probe = rdc321x_leds_probe, + .remove = rdc321x_leds_remove, .driver = { - .name = "rdc3211-leds", + .name = "rdc321x-leds", + .owner = THIS_MODULE, } }; -static int __init rdc3211_leds_init(void) +static int __init rdc321x_leds_init(void) { int ret; - ret = platform_driver_register(&rdc3211_leds_driver); - if (ret < 0) - goto out; - - pdev = platform_device_register_simple("rdc3211-leds", -1, NULL, 0); - if (IS_ERR(pdev)) { - ret = PTR_ERR(pdev); - platform_driver_unregister(&rdc3211_leds_driver); - goto out; - } + ret = platform_driver_register(&rdc321x_leds_driver); -out: return ret; } -static void __exit rdc3211_leds_exit(void) +static void __exit rdc321x_leds_exit(void) { - platform_driver_unregister(&rdc3211_leds_driver); + platform_driver_unregister(&rdc321x_leds_driver); } -module_init(rdc3211_leds_init); -module_exit(rdc3211_leds_exit); +module_init(rdc321x_leds_init); +module_exit(rdc321x_leds_exit); MODULE_AUTHOR("Florian Fainelli "); -MODULE_DESCRIPTION("RDC3211 LED driver"); +MODULE_DESCRIPTION("RDC321x LED driver"); MODULE_LICENSE("GPL"); diff --git a/target/linux/rdc-2.6/files/include/asm-i386/gpio.h b/target/linux/rdc-2.6/files/include/asm-i386/gpio.h new file mode 100644 index 0000000000..ff87fca0ca --- /dev/null +++ b/target/linux/rdc-2.6/files/include/asm-i386/gpio.h @@ -0,0 +1,6 @@ +#ifndef _ASM_I386_GPIO_H +#define _ASM_I386_GPIO_H + +#include + +#endif /* _ASM_I386_GPIO_H */ diff --git a/target/linux/rdc-2.6/files/include/asm-i386/mach-generic/gpio.h b/target/linux/rdc-2.6/files/include/asm-i386/mach-generic/gpio.h new file mode 100644 index 0000000000..5305dcb96d --- /dev/null +++ b/target/linux/rdc-2.6/files/include/asm-i386/mach-generic/gpio.h @@ -0,0 +1,15 @@ +#ifndef __ASM_MACH_GENERIC_GPIO_H +#define __ASM_MACH_GENERIC_GPIO_H + +int gpio_request(unsigned gpio, const char *label); +void gpio_free(unsigned gpio); +int gpio_direction_input(unsigned gpio); +int gpio_direction_output(unsigned gpio, int value); +int gpio_get_value(unsigned gpio); +void gpio_set_value(unsigned gpio, int value); +int gpio_to_irq(unsigned gpio); +int irq_to_gpio(unsigned irq); + +#include /* cansleep wrappers */ + +#endif /* __ASM_MACH_GENERIC_GPIO_H */ diff --git a/target/linux/rdc-2.6/files/include/asm-i386/mach-rdc/gpio.h b/target/linux/rdc-2.6/files/include/asm-i386/mach-rdc/gpio.h new file mode 100644 index 0000000000..2368bd7583 --- /dev/null +++ b/target/linux/rdc-2.6/files/include/asm-i386/mach-rdc/gpio.h @@ -0,0 +1,56 @@ +#ifndef _RDC_GPIO_H +#define _RDC_GPIO_H + +extern int rdc_gpio_get_value(unsigned gpio); +extern void rdc_gpio_set_value(unsigned gpio, int value); +extern int rdc_gpio_direction_input(unsigned gpio); +extern int rdc_gpio_direction_output(unsigned gpio, int value); + + +/* Wrappers for the arch-neutral GPIO API */ + +static inline int gpio_request(unsigned gpio, const char *label) +{ + /* Not yet implemented */ + return 0; +} + +static inline void gpio_free(unsigned gpio) +{ + /* Not yet implemented */ +} + +static inline int gpio_direction_input(unsigned gpio) +{ + return rdc_gpio_direction_input(gpio); +} + +static inline int gpio_direction_output(unsigned gpio, int value) +{ + return rdc_gpio_direction_output(gpio, value); +} + +static inline int gpio_get_value(unsigned gpio) +{ + return rdc_gpio_get_value(gpio); +} + +static inline void gpio_set_value(unsigned gpio, int value) +{ + rdc_gpio_set_value(gpio, value); +} + +static inline int gpio_to_irq(unsigned gpio) +{ + return gpio; +} + +static inline int irq_to_gpio(unsigned irq) +{ + return irq; +} + +/* For cansleep */ +#include + +#endif /* _RDC_GPIO_H_ */ diff --git a/target/linux/rdc-2.6/files/include/asm-i386/mach-rdc/rdc321x_defs.h b/target/linux/rdc-2.6/files/include/asm-i386/mach-rdc/rdc321x_defs.h new file mode 100644 index 0000000000..c8e6355bce --- /dev/null +++ b/target/linux/rdc-2.6/files/include/asm-i386/mach-rdc/rdc321x_defs.h @@ -0,0 +1 @@ +#define RDC_FLASH_BASE 0xffc00000 diff --git a/target/linux/rdc-2.6/patches/000-rdc_fixes.patch b/target/linux/rdc-2.6/patches/000-rdc_fixes.patch index 148fc482b4..1f0ac2144a 100644 --- a/target/linux/rdc-2.6/patches/000-rdc_fixes.patch +++ b/target/linux/rdc-2.6/patches/000-rdc_fixes.patch @@ -24,7 +24,7 @@ diff -urN linux-2.6.19/arch/i386/Makefile linux-2.6.19.new/arch/i386/Makefile mcore-$(CONFIG_X86_ES7000) := mach-default core-$(CONFIG_X86_ES7000) := arch/i386/mach-es7000/ +# RDC subarch support -+mflags-$(CONFIG_X86_RDC) := -Iinclude/asm-i386/mach-generic ++mflags-$(CONFIG_X86_RDC) := -Iinclude/asm-i386/mach-rdc +mcore-$(CONFIG_X86_RDC) := mach-default +core-$(CONFIG_X86_RDC) += arch/i386/mach-rdc/ @@ -38,787 +38,4 @@ diff -urN linux-2.6.19/arch/i386/mach-rdc/Makefile linux-2.6.19.new/arch/i386/ma +# Makefile for the linux kernel. +# + -+obj-$(CONFIG_X86_RDC) := led.o -diff -urN linux-2.6.19/arch/i386/mach-rdc/led.c linux-2.6.19.new/arch/i386/mach-rdc/led.c ---- linux-2.6.19/arch/i386/mach-rdc/led.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.19.new/arch/i386/mach-rdc/led.c 2006-12-17 17:13:33.000000000 +0100 -@@ -0,0 +1,743 @@ -+/* -+ * LED interface for WP3200 -+ * -+ * Copyright (C) 2002, by Allen Hung -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "led.h" -+ -+#define BUF_LEN 30 -+ -+struct LED_DATA { -+ char sts_buf[BUF_LEN+1]; -+ unsigned long sts; -+}; -+ -+struct LED_DATA led_data[LED_DEV_NUM]; -+// sam -+unsigned long ul_ledstat = 0xffffffff; -+ -+ -+static struct timer_list blink_timer[LED_DEV_NUM]; -+// sam 01-30-2004 for watchdog -+static struct timer_list watchdog; -+// end sam -+static char cmd_buf[BUF_LEN+1]; -+ -+//------------------------------------------------------------ -+static long atoh(char *p) -+{ -+ long v = 0, c; -+ while ( (c = *p++) ) { -+ if ( c >= '0' && c <= '9' ) v = (v << 4) + c - '0'; -+ else if ( c >= 'a' && c <= 'f' ) v = (v << 4) + c - 'a' + 0xA; -+ else if ( c >= 'A' && c <= 'F' ) v = (v << 4) + c - 'A' + 0xA; -+ else break; -+ } -+ return v; -+} -+ -+static int reset_flash_default(void *data) -+{ -+ char *argv[3], *envp[1] = {NULL}; -+ int i = 0; -+ -+ int reset_default=(int) data; -+ -+ argv[i++] = "/bin/flash"; -+ argv[i++] = "default"; -+ argv[i] = NULL; -+ if(reset_default) -+ if (call_usermodehelper(argv[0], argv, envp, 1)) -+ printk("failed to Reset to default\n"); -+ machine_restart(0); -+ return 0; -+} -+ -+// sam for ps 3205U -- using CSx1 (0xb0e00000) -+// bit map as following -+// BIT 1 2 3 4 5 -+// POWER WLEN PORT1 PORT2 PORT3 -+// -+// value 0 --> led on -+// value 1 --> led off -+ -+#define _ROUTER_ -+ -+#ifdef _ROUTER_ -+ #define LED_VAL 0x8000384C // the data ofset of gpio 0~30 -+#else -+ #define LED_VAL 0x80003888 // the ofset of gpio 31~58 -+#endif -+#define GPIO_VAL 0x8000384C // the offset of gpio 0-30 -+ -+ -+ -+// sam 1-30-2004 LED status -+// bit map as following -+// BIT 4:0 Link status -->PHY Link ->1 = up, 0 = down -+#define LINK_STATUS (*(unsigned long *)0xb2000014) -+#define WATCHDOG_VAL (*(unsigned long *)0xb20000c0) -+#define WATCHDOG_PERIOD 500 // unit ms -+#define EXPIRE_TIME 300 // unit 10 ms -+#define CLEAR_TIMEER 0xffffa000l // bit 14:0 -> count up timer, write 0 to clear -+#define ENABLE_WATCHDOG 0x80000000l // bit 31 -> 1 enable , 0 disable watchdog -+#define WATCHDOG_SET_TMR_SHIFT 16 // bit 16:30 -> watchdog timer set -+// end sam -+ -+ -+//------------------------------------------------------------ -+static void turn_led(int id, int on) -+{ -+ unsigned long led_bit = 1 << (id); -+ unsigned long led_bit_val; -+ -+ // since we define we have 8 led devices and use gpio 53, 55, 57, 58 -+ // which locate at bit21~26, so we rotate left 20bit -+ -+#ifdef _ROUTER_ -+ led_bit_val = led_bit; -+#else -+ led_bit_val = led_bit << 20; -+#endif -+ -+ switch ( on ) { -+ case 0: -+ ul_ledstat|= led_bit_val; -+ outl(LED_VAL, 0xcf8); -+ outl(ul_ledstat, 0xcfc); -+ break; // LED OFF -+ case 1: -+ ul_ledstat &= ~led_bit_val; -+ outl(LED_VAL, 0xcf8); -+ outl(ul_ledstat, 0xcfc); -+ break; // LED ON -+ case 2: -+ ul_ledstat ^= led_bit_val; -+ outl(LED_VAL, 0xcf8); -+ outl(ul_ledstat, 0xcfc); -+ break; // LED inverse -+ } -+} -+ -+ -+static int led_flash[30]={20,10,100,5,5,150,100,5,5,50,20,50,50,20,60,5,20,10,30,10,5,10,50,2,5,5,5,70,10,50};//Erwin -+static unsigned int wlan_counter; //Erwin -+static void blink_wrapper(u_long id) -+{ -+ u_long sts = led_data[id].sts; -+ -+ if ( (sts & LED_BLINK_CMD) == LED_BLINK_CMD ) { -+ unsigned long period = sts & LED_BLINK_PERIOD; -+ if(period == 0xffff) // BLINK random -+ { -+ blink_timer[id].expires = jiffies + 3*led_flash[wlan_counter%30]*HZ/1000; -+ wlan_counter++; -+ } -+ else -+ blink_timer[id].expires = jiffies + (period * HZ / 1000); -+ turn_led(id, 2); -+ add_timer(&blink_timer[id]); -+ } -+ else if ( sts == LED_ON || sts == LED_OFF ) -+ turn_led(id, sts==LED_ON ? 1 : 0); -+} -+//------------------------------------------------------------ -+static void get_token_str(char *str, char token[][21], int token_num) -+{ -+ int t, i; -+ -+ for ( t = 0 ; t < token_num ; t++ ) { -+ memset(token[t], 0, 21); -+ while ( *str == ' ' ) str++; -+ for ( i = 0 ; str[i] ; i++ ) { -+ if ( str[i] == '\t' || str[i] == ' ' || str[i] == '\n' ) break; -+ if ( i < 20 ) token[t][i] = str[i]; -+ } -+ str += i; -+ } -+} -+ -+//------------------------------------------------------------ -+static void set_led_status_by_str(int id) -+{ -+ char token[3][21], *p; -+ -+ -+ get_token_str(led_data[id].sts_buf, token, 3); -+ -+ if ( strcmp(token[0], "LED") ) -+ { -+ goto set_led_off; -+ } -+ if ( !strcmp(token[1], "ON") ) -+ { -+ -+ turn_led(id, 1); -+ led_data[id].sts = LED_ON; -+ } -+ else if ( !strcmp(token[1], "OFF") ) -+ { -+ -+ goto set_led_off; -+ } -+ else if ( !strcmp(token[1], "BLINK") ) -+ { -+ unsigned int period = 0; -+ p = token[2]; -+ if ( !strcmp(p, "FAST") ) -+ period = LED_BLINK_FAST & LED_BLINK_PERIOD; -+ else if ( !strcmp(p, "SLOW") ) -+ period = LED_BLINK_SLOW & LED_BLINK_PERIOD; -+ else if ( !strcmp(p, "EXTRA_SLOW") ) -+ period = LED_BLINK_EXTRA_SLOW & LED_BLINK_PERIOD; -+ else if ( !strcmp(p, "RANDOM") ) -+ period = LED_BLINK_RANDOM & LED_BLINK_PERIOD; -+ else if ( !strcmp(p, "OFF") ) -+ goto set_led_off; -+ else if ( *p >= '0' && *p <= '9' ) -+ { -+ while ( *p >= '0' && *p <= '9' ) -+ period = period * 10 + (*p++) - '0'; -+// if ( period > 10000 ) -+// period = 10000; -+ } -+ else -+ period = LED_BLINK & LED_BLINK_PERIOD; -+ -+ if ( period == 0 ) -+ goto set_led_off; -+ -+ sprintf(led_data[id].sts_buf, "LED BLINK %d\n", period); -+ led_data[id].sts = LED_BLINK_CMD + period; -+ turn_led(id, 2); -+ // Set timer for next blink -+ del_timer(&blink_timer[id]); -+ blink_timer[id].function = blink_wrapper; -+ blink_timer[id].data = id; -+ init_timer(&blink_timer[id]); -+ -+ blink_timer[id].expires = jiffies + (1000 * HZ / 1000); -+ -+ add_timer(&blink_timer[id]); -+ } -+ else -+ { -+ goto set_led_off; -+ } -+ return; -+ set_led_off: -+ strcpy(led_data[id].sts_buf, "LED OFF\n"); -+ led_data[id].sts = LED_OFF; -+ turn_led(id, 0); -+} -+ -+//---------------------------------------------------------------------- -+static int led_read_proc(char *buf, char **start, off_t fpos, int length, int *eof, void *data) -+{ -+ int len, dev; -+ -+ for ( len = dev = 0 ; dev < LED_DEV_NUM ; dev++ ) { -+ len += sprintf(buf+len, "%d: %s", dev, led_data[dev].sts_buf); -+ } -+ len = strlen(buf) - fpos; -+ if ( len <= 0 ) { -+ *start = buf; -+ *eof = 1; -+ return 0; -+ } -+ *start = buf + fpos; -+ if ( len <= length ) *eof = 1; -+ return len < length ? len : length; -+} -+ -+//---------------------------------------------------------------------- -+static int led_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ int id = (int)file->private_data; -+ -+ switch ( cmd ) { -+ case LED_ON: -+ strcpy(led_data[id].sts_buf, "LED ON\n"); -+ set_led_status_by_str(id); -+ break; -+ case LED_OFF: -+ strcpy(led_data[id].sts_buf, "LED OFF\n"); -+ set_led_status_by_str(id); -+ break; -+ default: -+ if ( (cmd & LED_BLINK_CMD) != LED_BLINK_CMD ) -+ { -+ break; -+ } -+ case LED_BLINK: -+ case LED_BLINK_FAST: -+ case LED_BLINK_SLOW: -+ case LED_BLINK_EXTRA_SLOW: -+ case LED_BLINK_RANDOM: -+ sprintf(led_data[id].sts_buf, "LED BLINK %d\n", (int)(cmd & LED_BLINK_PERIOD)); -+ set_led_status_by_str(id); -+ break; -+ } -+ return 0; -+} -+ -+static int led_open(struct inode *inode, struct file *file) -+{ -+ int led_id = MINOR(inode->i_rdev); -+// unsigned long led_bit = 1 << (led_id); -+ -+ if ( led_id >= LED_DEV_NUM ) -+ return -ENODEV; -+/* sam 12/02/2003 -+ GPIO_SEL_I_O &= ~led_bit; // 0 to GPIO -+ GPIO_O_EN |= (led_bit << 16); // 0 to Output -+*/ -+ -+ file->private_data = (void*)led_id; -+ return 0; -+} -+ -+static long led_read(struct file *file, char *buf, size_t count, loff_t *fpos) -+{ -+ int rem, len; -+ int id = (int)file->private_data; -+ char *p = led_data[id].sts_buf; -+ -+ len = strlen(p); -+ rem = len - *fpos; -+ if ( rem <= 0 ) { -+ *fpos = len; -+ return 0; -+ } -+ if ( rem > count ) rem = count; -+ memcpy(buf, p+(*fpos), rem); -+ *fpos += rem; -+ return rem; -+} -+ -+static long led_write(struct file *file, char *buf, size_t count, loff_t *fpos) -+{ -+ int len; -+ int id = (int)file->private_data; -+ char *p = id == REG_MINOR ? cmd_buf : led_data[id].sts_buf; -+ memset(p, 0, BUF_LEN); -+ -+ p += *fpos; -+ len = 0; -+ -+ -+ while ( count > 0 ) -+ { -+ -+ if ( *fpos < BUF_LEN ) -+ { -+ int c = *buf++; -+ p[len] = c>='a' && c<='z' ? c-'a'+'A' : c; -+ } -+ (*fpos)++; -+ len++; -+ count--; -+ } -+ // sam -+ set_led_status_by_str(id); -+ (*fpos) = 0; -+ // -+ -+ return len; -+} -+ -+static int led_flush(struct file *file) -+{ -+ int id = (int)file->private_data; -+ -+ if ( file->f_mode & FMODE_WRITE ) -+ { -+ set_led_status_by_str(id); -+ } -+ return 0; -+} -+ -+static struct file_operations led_fops = { -+ read: led_read, -+ write: led_write, -+ flush: led_flush, -+ ioctl: led_ioctl, -+ open: led_open, -+}; -+ -+//---------------------------------------------- -+static unsigned long *reg_addr; -+static int dump_len; -+ -+static int dump_content(char *buf) -+{ -+ return 0; -+} -+ -+static long gpio_read(struct file *file, char *buf, size_t count, loff_t *fpos) -+{ -+ int rem, len; -+ int id = (int)file->private_data; -+ char temp[80*10]; -+ unsigned long gpio_regval =0; -+ -+ outl(GPIO_VAL, 0xcf8); -+ gpio_regval = inl(0xcfc); -+ gpio_regval |= 0x40; -+ outl(gpio_regval, 0xcfc); // each in, need out 1 first -+ gpio_regval = inl(0xcfc); -+ -+ -+ // sam debug -+ //printk(KERN_ERR "gpio_id:%d, gpio_regval:%08X\n", id, gpio_regval); -+ //end sam -+ -+ if ( id < GPIO_DEV_NUM ) { -+ int gpio_bit = 1 << id; -+ -+ len = sprintf(temp, "%d\n", (gpio_regval & gpio_bit) ? 1 : 0); -+ } -+ else // REG device -+ len = dump_content(temp); -+ rem = len - *fpos; -+ if ( rem <= 0 ) { -+ *fpos = len; -+ return 0; -+ } -+ if ( rem > count ) rem = count; -+ memcpy(buf, temp+(*fpos), rem); -+ *fpos += rem; -+ return rem; -+} -+ -+static int gpio_flush(struct file *file) -+{ -+ return 0; -+} -+ -+static int gpio_open(struct inode *inode, struct file *file) -+{ -+ int id = MINOR(inode->i_rdev); -+ if ( id >= GPIO_DEV_NUM && id != REG_MINOR ) -+ return -ENODEV; -+ file->private_data = (void*)id; -+ return 0; -+} -+ -+static struct file_operations gpio_fops = { -+ read: gpio_read, -+ open: gpio_open, -+ flush: gpio_flush, -+ write: led_write, -+}; -+ -+// --------------------------------------------- -+// sam 1-30-2004 LAN_STATUS Device -+ -+//static unsigned long *reg_addr; -+//static int dump_len; -+ -+//static int lanSt_content(char *buf) -+//{ -+// int i, j, len; -+// unsigned long *p = (unsigned long *)0xb2000014; // PHY_ST -+// // j = dump_len/4 + ((dump_len&3) ? 1 : 0); -+// len = sprintf(buf, "Reg Addr = %08lX, Value = \n", (unsigned long)p); -+// // for ( i = 0 ; i < j ; i++, p++ ) -+// len += sprintf(buf+len,"%08lX\n", *p); -+ -+// return len; -+//} -+ -+#define MAC_IOBASE 0xe800 // Eth0 -+#define PHY_ADDR 1 // For Eth0 -+#define MII_STATUS_ADDR 1 -+// where "id" value means which bit of PHY reg 1 we want to check -+static long lanSt_read(struct file *file, char *buf, size_t count, loff_t *fpos) -+{ -+ int rem, len; -+// unsigned long *p = (unsigned long *)0xb2000014; // PHY_ST -+ unsigned short status; -+ unsigned int i = 0; -+ int id = (int)file->private_data; -+ char temp[80*10]; -+ -+ outw(0x2000 + MII_STATUS_ADDR + (PHY_ADDR << 8), MAC_IOBASE + 0x20); -+ do{}while( (i++ < 2048) && (inw(MAC_IOBASE+0x20) & 0x2000) ); -+ -+ status = inw(MAC_IOBASE + 0x24); -+ -+ // sam debug -+ //printk(KERN_ERR "PHY REG1 Status:%04x\n", status ); -+ // end sam -+ -+ if ( id < LAN_DEV_NUM ) { -+ unsigned long lanSt_bit = 1 << id; -+// len = lanSt_content(temp); -+ len = sprintf(temp, "%d\n",(status & lanSt_bit) ? 1 : 0); -+ } -+ else // REG device -+ { -+ len = sprintf(temp, "-1\n"); -+ } -+ rem = len - *fpos; -+ if ( rem <= 0 ) { -+ *fpos = len; -+ return 0; -+ } -+ if ( rem > count ) rem = count; -+ memcpy(buf, temp+(*fpos), rem); -+ *fpos += rem; -+ return rem; -+} -+ -+static int lanSt_flush(struct file *file) -+{ -+ return 0; -+} -+ -+static int lanSt_open(struct inode *inode, struct file *file) -+{ -+ int id = MINOR(inode->i_rdev); -+ if ( id >= LAN_DEV_NUM && id != REG_MINOR ) -+ return -ENODEV; -+ file->private_data = (void*)id; -+ return 0; -+} -+ -+static struct file_operations lanSt_fops = { -+ read: lanSt_read, -+ open: lanSt_open, -+ flush: lanSt_flush, -+ write: led_write, -+}; -+ -+//---------------------------------------------- -+static int SwResetPress = 0; -+static int SwResetCounter = 0; -+static int RebootFlag = 0; -+static void watchdog_wrapper(unsigned int period) -+{ -+ // { RexHua add for restore default, by press SwReset 5 second, 2 sec to restart -+#if 0 // -+ u_long reg; -+ -+ outl(GPIO_VAL, 0xcf8); -+ reg = inl(0xcfc); -+ reg |= 0x40; -+ outl(reg, 0xcfc); // each in, need out 1 first -+ reg = inl(0xcfc); -+ -+ if( (reg & 0x40) == 0) -+ { -+ if(SwResetPress == 0) -+ { -+ SwResetCounter=0; -+ strcpy(led_data[15].sts_buf, "LED BLINK 500\n" ); -+ set_led_status_by_str(15); -+ } -+ SwResetPress=1; -+ printk("SwReset press!\n"); -+ -+ } -+ else -+ { -+ if(SwResetPress=1) -+ { -+ strcpy(led_data[15].sts_buf, "LED ON\n" ); -+ set_led_status_by_str(15); -+ } -+ -+ SwResetPress=0; -+ if(RebootFlag == 1) -+ machine_restart(0); -+ } -+ -+ if(SwResetPress == 1) -+ { -+ if(SwResetCounter > 10) -+ { -+ turn_led(15, 0); -+// kernel_thread(reset_flash_default, 1, SIGCHLD); -+ reset_flash_default(1); -+ turn_led(15, 1); -+ } -+ else if(SwResetCounter == 3) -+ { -+ RebootFlag=1; -+ strcpy(led_data[15].sts_buf, "LED BLINK 100\n" ); -+ set_led_status_by_str(15); -+ } -+ } -+ -+ SwResetCounter++; -+#endif -+ -+ // clear timer count -+ outl(0x80003844, 0xcf8); -+ outl(0x00800080, 0xcfc); // enable watchdog and set the timeout = 1.34s -+ //printk(KERN_ERR "wdt\n" ); -+ watchdog.expires = jiffies + (period * HZ / 1000); -+ add_timer(&watchdog); -+} -+ -+//---------------------------------------------- -+static int init_status; -+ -+#define INIT_REGION 0x01 -+#define INIT_LED_REGISTER 0x02 -+#define INIT_LED_PROC_READ 0x04 -+#define INIT_GPIO_REGISTER 0x08 -+// sam 1-30-2004 LAN_STATUS -+#define INIT_LAN_STATUS_REGISTER 0x10 -+#define INIT_WATCHDOG_REGISTER 0x20 -+ -+static void led_exit(void) -+{ -+ int id; -+ for ( id = 0 ; id < LED_DEV_NUM ; id++ ) { -+ del_timer(&blink_timer[id]); -+ turn_led(id, 0); -+ } -+ if ( init_status & INIT_LED_PROC_READ ) -+ remove_proc_entry("driver/led", NULL); -+ -+ if ( init_status & INIT_LED_REGISTER ) -+ unregister_chrdev(LED_MAJOR, "led"); -+ -+ if ( init_status & INIT_GPIO_REGISTER ) -+ unregister_chrdev(GPIO_MAJOR, "gpio"); -+ // sam 1-30-2004 -+ -+ if( init_status & INIT_LAN_STATUS_REGISTER ) -+ unregister_chrdev(LAN_STATUS_MAJOR, "lanSt"); -+ -+ if( init_status & INIT_WATCHDOG_REGISTER) -+ del_timer(&watchdog); -+ -+ -+ // end sam -+ -+} -+ -+static int __init led_init(void) -+{ -+ int result, id, i, j; -+ unsigned long reg; -+ init_status = 0; -+ -+ //----- register device (LED)------------------------- -+ -+ -+ result = register_chrdev(LED_MAJOR, "led", &led_fops); -+ if ( result < 0 ) { -+ printk(KERN_ERR "led: can't register char device\n" ); -+ led_exit(); -+ return result; -+ } -+ init_status |= INIT_LED_REGISTER; -+ //----- register device (GPIO)------------------------- -+ result = register_chrdev(GPIO_MAJOR, "gpio", &gpio_fops); -+ if ( result < 0 ) { -+ printk(KERN_ERR "gpio: can't register char device\n" ); -+ led_exit(); -+ return result; -+ } -+ init_status |= INIT_GPIO_REGISTER; -+ -+ // sam 1-30-2004 LAN Status -+ // ----- register device (LAN_STATUS)------------------- -+ -+ //--> sam 5-1802995 -+ -+ result = register_chrdev(LAN_STATUS_MAJOR, "lanSt", &lanSt_fops); -+ if ( result < 0 ) { -+ printk(KERN_ERR "lanSt: can't register char device\n" ); -+ led_exit(); -+ return result; -+ } -+ init_status |= INIT_LAN_STATUS_REGISTER; -+ -+ // <-- end sam -+ -+ // -----------init watchdog timer------------------------- -+ //del_timer(&blink_timer[id]); -+ -+ outl(0x80003840, 0xcf8); -+ reg = inl(0xcfc); -+ reg |= 0x1600; // ensable SRC bit -+ outl(reg, 0xcfc); -+#ifdef _ROUTER_ -+ outl(0x80003848, 0xcf8); -+ reg = inl(0xcfc); -+ reg |= 0x18040; // enable GPIO, PowerLED:15, WLAN_LED0:16, SwReset:6 -+ outl(reg, 0xcfc); -+ -+ outl(0x8000384c, 0xcf8); -+ reg = inl(0xcfc); -+ reg |= 0x40; // output SwReset:6 1, Set SwReset as Input -+ outl(reg, 0xcfc); -+#endif -+ // sam debug -+ //reg = inl(0xcfc); -+ //printk(KERN_ERR "REG40:%08X\n", reg); -+ // end sam -+ outl(0x80003844, 0xcf8); -+ outl(0x00800080, 0xcfc); // enable watchdog and set the timeout = 1.34s -+ -+ watchdog.function = watchdog_wrapper; -+ watchdog.data = WATCHDOG_PERIOD; -+ init_timer(&watchdog); -+ watchdog.expires = jiffies + (WATCHDOG_PERIOD * HZ / 1000); -+ add_timer(&watchdog); -+ init_status |= INIT_WATCHDOG_REGISTER; -+ -+ // end sam -+ //------ read proc ------------------- -+ if ( !create_proc_read_entry("driver/led", 0, 0, led_read_proc, NULL) ) { -+ printk(KERN_ERR "led: can't create /proc/driver/led\n"); -+ led_exit(); -+ return -ENOMEM; -+ } -+ init_status |= INIT_LED_PROC_READ; -+ //------------------------------ -+// reg_addr = (unsigned long *)0xB4000000; -+// dump_len = 4; -+ -+ for ( id = 0 ; id < LED_DEV_NUM ; id++ ) { -+ strcpy(led_data[id].sts_buf, "LED ON\n" ); -+ set_led_status_by_str(id); -+ } -+ -+// for (i = 0; i < 0xffff; i++) -+// for (j = 0; j < 0x6000; j++); -+ -+/* sam 5-18-2005 remark -+ for ( id = 0 ; id < LED_DEV_NUM ; id++ ) { -+ strcpy(led_data[id].sts_buf, "LED ON\n" ); -+ set_led_status_by_str(id); -+ } -+*/ -+ printk(KERN_INFO "LED & GPIO & LAN Status Driver LED_VERSION \n"); -+ return 0; -+} -+ -+module_init(led_init); -+module_exit(led_exit); -+EXPORT_NO_SYMBOLS; -diff -urN linux-2.6.19/arch/i386/mach-rdc/led.h linux-2.6.19.new/arch/i386/mach-rdc/led.h ---- linux-2.6.19/arch/i386/mach-rdc/led.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.19.new/arch/i386/mach-rdc/led.h 2006-12-17 17:13:33.000000000 +0100 -@@ -0,0 +1,32 @@ -+#ifndef _LED_H_INCLUDED -+#define _LED_H_INCLUDED -+ -+#include -+ -+#define LED_VERSION "v1.0" -+#define LED_MAJOR 166 -+#define LED_DEV_NUM 32 -+#define LED_GPIO_START 1 -+#define GPIO_MAJOR 167 -+#define GPIO_DEV_NUM 32 -+#define REG_MINOR 128 -+// sam 1-30-2004 for LAN_STATUS -+#define LAN_STATUS_MAJOR 168 -+#define LAN_DEV_NUM 5 -+// end sam -+ -+//#define GPIO_IO_BASE 0xB4002480 -+//#define GPIO_IO_BASE ((unsigned long)0xb20000b8) -+//#define GPIO_IO_EXTENT 0x40 -+ -+#define LED_ON 0x010000 -+#define LED_OFF 0x020000 -+#define LED_BLINK_CMD 0x030000 -+#define LED_BLINK_PERIOD 0x00FFFF -+#define LED_BLINK (LED_BLINK_CMD|1000) -+#define LED_BLINK_FAST (LED_BLINK_CMD|250) -+#define LED_BLINK_SLOW (LED_BLINK_CMD|500) -+#define LED_BLINK_EXTRA_SLOW (LED_BLINK_CMD|2000) -+#define LED_BLINK_RANDOM (LED_BLINK_CMD|0xffff) -+ -+#endif ++obj-$(CONFIG_X86_RDC) := gpio.o platform.o -- cgit v1.2.3