From d9cf9b68524d88692f9fefb323d19050ca67dffc Mon Sep 17 00:00:00 2001 From: blogic Date: Fri, 14 Dec 2007 20:43:53 +0000 Subject: [PATCH 1/1] danube_led cleanup git-svn-id: svn://svn.openwrt.org/openwrt/trunk@9757 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- target/linux/danube/config-2.6.23 | 2 +- .../danube/files/drivers/char/danube_led.c | 778 +++--------------- .../files/include/asm-mips/danube/danube.h | 19 + 3 files changed, 130 insertions(+), 669 deletions(-) diff --git a/target/linux/danube/config-2.6.23 b/target/linux/danube/config-2.6.23 index 9a4be73d6d..286035a474 100644 --- a/target/linux/danube/config-2.6.23 +++ b/target/linux/danube/config-2.6.23 @@ -42,7 +42,7 @@ CONFIG_CPU_SUPPORTS_HIGHMEM=y CONFIG_DANUBE=y CONFIG_DANUBE_ASC_UART=y CONFIG_DANUBE_GPIO=y -# CONFIG_DANUBE_LED is not set +CONFIG_DANUBE_LED=y CONFIG_DANUBE_MII0=y CONFIG_DANUBE_MII1=y CONFIG_DANUBE_WDT=y diff --git a/target/linux/danube/files/drivers/char/danube_led.c b/target/linux/danube/files/drivers/char/danube_led.c index 9cefe8e94b..8f5758933f 100644 --- a/target/linux/danube/files/drivers/char/danube_led.c +++ b/target/linux/danube/files/drivers/char/danube_led.c @@ -30,7 +30,6 @@ #include #include #include -#include #define LED_CONFIG 0x01 @@ -45,38 +44,8 @@ #define CONFIG_OPERATION_MIPS0_ACCESS 0x0100 #define CONFIG_DATA_CLOCK_EDGE 0x0200 - -/* -* Data Type Used to Call ioctl -*/ -struct led_config_param { - unsigned long operation_mask; // Select operations to be performed - unsigned long led; // LED to change update source (LED or ADSL) - unsigned long source; // Corresponding update source (LED or ADSL) - unsigned long blink_mask; // LEDs to set blink mode - unsigned long blink; // Set to blink mode or normal mode - unsigned long update_clock; // Select the source of update clock - unsigned long fpid; // If FPI is the source of update clock, set the divider - // else if GPT is the source, set the frequency - unsigned long store_mode; // Set clock mode or single pulse mode for store signal - unsigned long fpis; // FPI is the source of shift clock, set the divider - unsigned long data_offset; // Set cycles to be inserted before data is transmitted - unsigned long number_of_enabled_led; // Total number of LED to be enabled - unsigned long data_mask; // LEDs to set value - unsigned long data; // Corresponding value - unsigned long mips0_access_mask; // LEDs to set access right - unsigned long mips0_access; // 1: the corresponding data is output from MIPS0, 0: MIPS1 - unsigned long f_data_clock_on_rising; // 1: data clock on rising edge, 0: data clock on falling edge -}; - - -extern int danube_led_set_blink(unsigned int, unsigned int); -extern int danube_led_set_data(unsigned int, unsigned int); -extern int danube_led_config(struct led_config_param *); - -#define DATA_CLOCKING_EDGE FALLING_EDGE -#define RISING_EDGE 0 -#define FALLING_EDGE 1 +#define DANUBE_LED_CLK_EDGE DANUBE_LED_FALLING +//#define DANUBE_LED_CLK_EDGE DANUBE_LED_RISING #define LED_SH_PORT 0 #define LED_SH_PIN 4 @@ -228,691 +197,164 @@ extern int danube_led_config(struct led_config_param *); #define SET_BITS(x, msb, lsb, value) (((x) & ~(((1 << ((msb) + 1)) - 1) ^ ((1 << (lsb)) - 1))) | (((value) & ((1 << (1 + (msb) - (lsb))) - 1)) << (lsb))) -static struct semaphore led_sem; - -static unsigned long gpt_on = 0; -static unsigned long gpt_freq = 0; - -static unsigned long adsl_on = 0; -static unsigned long f_led_on = 0; - -static inline int -update_led (void) -{ - int i, j; - - /* - * GPT2 or FPID is the clock to update LEDs automatically. - */ - if (readl(DANUBE_LED_CON1) >> 30) - return 0; - - /* - * Check the status to prevent conflict of two consecutive update - */ - for ( i = 100000; i != 0; i -= j / 16 ) - { - down(&led_sem); - if (!(readl(DANUBE_LED_CON0) & LED_CON0_SWU)) - { - *DANUBE_LED_CON0 |= 1 << 31; - up(&led_sem); - return 0; - } - else - up(&led_sem); - for ( j = 0; j < 1000 * 16; j++ ); - } - - return -EBUSY; -} - -static inline unsigned int -set_update_source (unsigned int reg, unsigned long led, unsigned long source) -{ - return (reg & ~((led & 0x03) << 24)) | ((source & 0x03) << 24); -} - -static inline unsigned int -set_blink_in_batch (unsigned int reg, unsigned long mask, unsigned long blink) -{ - return (reg & (~(mask & 0x00FFFFFF) & 0x87FFFFFF)) | (blink & 0x00FFFFFF); -} - -static inline unsigned int -set_data_clock_edge (unsigned int reg, unsigned long f_on_rising_edge) -{ - return f_on_rising_edge ? (reg & ~(1 << 26)) : (reg | (1 << 26)); -} - -static inline unsigned int -set_update_clock (unsigned int reg, unsigned long clock, unsigned long fpid) -{ - switch ( clock ) - { - case 0: - reg &= ~0xC0000000; - break; - - case 1: - reg = (reg & ~0xC0000000) | 0x40000000; - break; - - case 2: - reg = (reg & ~0xCF800000) | 0x80000000 | ((fpid & 0x1F) << 23); - break; - } +static int danube_led_major; - return reg; -} - -static inline unsigned int -set_store_mode (unsigned int reg, unsigned long mode) -{ - return mode ? (reg | (1 << 28)) : (reg & ~(1 << 28)); -} - -static inline -unsigned int set_shift_clock (unsigned int reg, unsigned long fpis) +static int +danube_led_setup_gpio (void) { - return SET_BITS(reg, 21, 20, fpis); + /* + * Set LED_ST + * I don't check the return value, because I'm sure the value is valid + * and the pins are reserved already. + */ + LED_ST_ALTSEL0_SETUP(LED_ST_PORT, LED_ST_PIN); + LED_ST_ALTSEL1_SETUP(LED_ST_PORT, LED_ST_PIN); + LED_ST_DIR_SETUP(LED_ST_PORT, LED_ST_PIN); + LED_ST_OPENDRAIN_SETUP(LED_ST_PORT, LED_ST_PIN); + + /* + * Set LED_D + */ + LED_D_ALTSEL0_SETUP(LED_D_PORT, LED_D_PIN); + LED_D_ALTSEL1_SETUP(LED_D_PORT, LED_D_PIN); + LED_D_DIR_SETUP(LED_D_PORT, LED_D_PIN); + LED_D_OPENDRAIN_SETUP(LED_D_PORT, LED_D_PIN); + + /* + * Set LED_SH + */ + LED_SH_ALTSEL0_SETUP(LED_SH_PORT, LED_SH_PIN); + LED_SH_ALTSEL1_SETUP(LED_SH_PORT, LED_SH_PIN); + LED_SH_DIR_SETUP(LED_SH_PORT, LED_SH_PIN); + LED_SH_OPENDRAIN_SETUP(LED_SH_PORT, LED_SH_PIN); + + return 0; } -static inline -unsigned int set_data_offset (unsigned int reg, unsigned long offset) +static void +danube_led_enable (void) { - return SET_BITS(reg, 19, 18, offset); -} + int err = 1000000; -static inline -unsigned int set_number_of_enabled_led (unsigned int reg, unsigned long number) -{ - unsigned int bit_mask; + writel(readl(DANUBE_PMU_PWDCR) & ~DANUBE_PMU_PWDCR_LED, DANUBE_PMU_PWDCR); + while (--err && (readl(DANUBE_PMU_PWDSR) & DANUBE_PMU_PWDCR_LED)) {} - bit_mask = number > 16 ? 0x07 : (number > 8 ? 0x03 : (number ? 0x01 : 0x00)); - return (reg & ~0x07) | bit_mask; -} - -static inline unsigned int -set_data_in_batch (unsigned int reg, unsigned long mask, unsigned long data) -{ - return (reg & ~(mask & 0x00FFFFFF)) | (data & 0x00FFFFFF); -} - -static inline unsigned int -set_access_right (unsigned int reg, unsigned long mask, unsigned long ar) -{ - return (reg & ~(mask & 0x00FFFFFF)) | (~ar & mask); + if (!err) + panic("Activating LED in PMU failed!"); } static inline void -enable_led (void) +danube_led_disable (void) { - /* Activate LED module in PMU. */ - int i = 1000000; - - writel(readl(DANUBE_PMU_PWDCR) & ~DANUBE_PMU_PWDCR_LED, DANUBE_PMU_PWDCR); - while (--i && (readl(DANUBE_PMU_PWDSR) & DANUBE_PMU_PWDCR_LED)) {} - - if (!i) - panic("Activating LED in PMU failed!"); + writel(readl(DANUBE_PMU_PWDCR) | DANUBE_PMU_PWDCR_LED, DANUBE_PMU_PWDCR); } -static inline void -disable_led (void) +static int +led_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - writel(readl(DANUBE_PMU_PWDCR) | DANUBE_PMU_PWDCR_LED, DANUBE_PMU_PWDCR); -} + int ret = -EINVAL; -static inline void -release_gpio_port (unsigned long adsl) -{ - if ( adsl ) - { - danube_port_free_pin(LED_ADSL0_PORT, LED_ADSL0_PIN); - danube_port_free_pin(LED_ADSL1_PORT, LED_ADSL1_PIN); - } - else - { - danube_port_free_pin(LED_ST_PORT, LED_ST_PIN); - danube_port_free_pin(LED_D_PORT, LED_D_PIN); - danube_port_free_pin(LED_SH_PORT, LED_SH_PIN); - } -} + switch ( cmd ) + { + case LED_CONFIG: + break; + } -static inline int -setup_gpio_port (unsigned long adsl) -{ - int ret = 0; - - /* - * Reserve all pins before config them. - */ - if ( adsl ) - { - ret |= danube_port_reserve_pin(LED_ADSL0_PORT, LED_ADSL0_PIN); - ret |= danube_port_reserve_pin(LED_ADSL1_PORT, LED_ADSL1_PIN); - } - else - { - ret |= danube_port_reserve_pin(LED_ST_PORT, LED_ST_PIN); - ret |= danube_port_reserve_pin(LED_D_PORT, LED_D_PIN); - ret |= danube_port_reserve_pin(LED_SH_PORT, LED_SH_PIN); - } - if ( ret ) - { - release_gpio_port(adsl); - return ret; // Should be -EBUSY - } - - if ( adsl ) - { - LED_ADSL0_ALTSEL0_SETUP(LED_ADSL0_PORT, LED_ADSL0_PIN); - LED_ADSL0_ALTSEL1_SETUP(LED_ADSL0_PORT, LED_ADSL0_PIN); - LED_ADSL0_DIR_SETUP(LED_ADSL0_PORT, LED_ADSL0_PIN); - LED_ADSL0_OPENDRAIN_SETUP(LED_ADSL0_PORT, LED_ADSL0_PIN); - - LED_ADSL1_ALTSEL0_SETUP(LED_ADSL1_PORT, LED_ADSL1_PIN); - LED_ADSL1_ALTSEL1_SETUP(LED_ADSL1_PORT, LED_ADSL1_PIN); - LED_ADSL1_DIR_SETUP(LED_ADSL1_PORT, LED_ADSL1_PIN); - LED_ADSL1_OPENDRAIN_SETUP(LED_ADSL1_PORT, LED_ADSL1_PIN); - } - else - { - /* - * Set LED_ST - * I don't check the return value, because I'm sure the value is valid - * and the pins are reserved already. - */ - LED_ST_ALTSEL0_SETUP(LED_ST_PORT, LED_ST_PIN); - LED_ST_ALTSEL1_SETUP(LED_ST_PORT, LED_ST_PIN); - LED_ST_DIR_SETUP(LED_ST_PORT, LED_ST_PIN); - LED_ST_OPENDRAIN_SETUP(LED_ST_PORT, LED_ST_PIN); - - /* - * Set LED_D - */ - LED_D_ALTSEL0_SETUP(LED_D_PORT, LED_D_PIN); - LED_D_ALTSEL1_SETUP(LED_D_PORT, LED_D_PIN); - LED_D_DIR_SETUP(LED_D_PORT, LED_D_PIN); - LED_D_OPENDRAIN_SETUP(LED_D_PORT, LED_D_PIN); - - /* - * Set LED_SH - */ - LED_SH_ALTSEL0_SETUP(LED_SH_PORT, LED_SH_PIN); - LED_SH_ALTSEL1_SETUP(LED_SH_PORT, LED_SH_PIN); - LED_SH_DIR_SETUP(LED_SH_PORT, LED_SH_PIN); - LED_SH_OPENDRAIN_SETUP(LED_SH_PORT, LED_SH_PIN); - } - - return 0; + return ret; } -static inline int -setup_gpt (int timer, unsigned long freq) +static int +led_open (struct inode *inode, struct file *file) { - int ret; - - timer = TIMER(timer, 1); - - ret = request_timer(timer, - TIMER_FLAG_SYNC - | TIMER_FLAG_16BIT - | TIMER_FLAG_INT_SRC - | TIMER_FLAG_CYCLIC | TIMER_FLAG_COUNTER | TIMER_FLAG_DOWN - | TIMER_FLAG_ANY_EDGE - | TIMER_FLAG_NO_HANDLE, - 8000000 / freq, - 0, - 0); - - if ( !ret ) - { - ret = start_timer(timer, 0); - if ( ret ) - free_timer(timer); - } - - return ret; + return 0; } -static inline void -release_gpt (int timer) +static int +led_release (struct inode *inode, struct file *file) { - timer = TIMER(timer, 1); - stop_timer(timer); - free_timer(timer); + return 0; } -static inline int -turn_on_led (unsigned long adsl) -{ - int ret; +static struct file_operations danube_led_fops = { + .owner = THIS_MODULE, + .ioctl = led_ioctl, + .open = led_open, + .release = led_release +}; - ret = setup_gpio_port(adsl); - if ( ret ) - return ret; - enable_led(); +/* +Map for LED on reference board + WLAN_READ LED11 OUT1 15 + WARNING LED12 OUT2 14 + FXS1_LINK LED13 OUT3 13 + FXS2_LINK LED14 OUT4 12 + FXO_ACT LED15 OUT5 11 + USB_LINK LED16 OUT6 10 + ADSL2_LINK LED19 OUT7 9 + BT_LINK LED17 OUT8 8 + SD_LINK LED20 OUT9 7 + ADSL2_TRAFFIC LED31 OUT16 0 +Map for hardware relay on reference board + USB Power On OUT11 5 + RELAY OUT12 4 +*/ - return 0; -} -static inline void -turn_off_led (unsigned long adsl) +int __init +danube_led_init (void) { - release_gpio_port(adsl); - disable_led(); -} + int ret = 0; + danube_led_setup_gpio(); -int -danube_led_set_blink (unsigned int led, unsigned int blink) -{ - unsigned int bit_mask; + writel(0, DANUBE_LED_AR); + writel(0xff00, DANUBE_LED_CPU0); + writel(0, DANUBE_LED_CPU1); + writel(0x8000ffff, DANUBE_LED_CON0); - if ( led > 23 ) - return -EINVAL; + /* setup the clock edge that the shift register is triggered on */ + writel(readl(DANUBE_LED_CON0) & ~DANUBE_LED_EDGE_MASK, DANUBE_LED_CON0); + writel(readl(DANUBE_LED_CON0) | DANUBE_LED_CLK_EDGE, DANUBE_LED_CON0); - bit_mask = 1 << led; - down(&led_sem); - if ( blink ) - *DANUBE_LED_CON0 |= bit_mask; - else - *DANUBE_LED_CON0 &= ~bit_mask; - up(&led_sem); + /* per default leds 15-0 are set */ + writel(DANUBE_LED_GROUP1 | DANUBE_LED_GROUP0, DANUBE_LED_CON1); - return (led == 0 && (readl(DANUBE_LED_CON0) & LED_CON0_AD0)) || (led == 1 && (readl(DANUBE_LED_CON0) & LED_CON0_AD1)) ? -EINVAL : 0; -} + /* leds are update periodically by the FPID */ + writel(readl(DANUBE_LED_CON1) & ~DANUBE_LED_UPD_MASK, DANUBE_LED_CON1); + writel(readl(DANUBE_LED_CON1) | DANUBE_LED_UPD_SRC_FPI, DANUBE_LED_CON1); -int -danube_led_set_data (unsigned int led, unsigned int data) -{ - unsigned long f_update; - unsigned int bit_mask; - - if ( led > 23 ) - return -EINVAL; - - bit_mask = 1 << led; - down(&led_sem); - if ( data ) - *DANUBE_LED_CPU0 |= bit_mask; - else - *DANUBE_LED_CPU0 &= ~bit_mask; - f_update = !(*DANUBE_LED_AR & bit_mask); - up(&led_sem); - - return f_update ? update_led() : 0; -} + /* set led update speed */ + writel(readl(DANUBE_LED_CON1) & ~DANUBE_LED_MASK, DANUBE_LED_CON1); + writel(readl(DANUBE_LED_CON1) | DANUBE_LED_8HZ, DANUBE_LED_CON1); -int -danube_led_config (struct led_config_param* param) -{ - int ret; - unsigned int reg_con0, reg_con1, reg_cpu0, reg_ar; - unsigned int clean_reg_con0, clean_reg_con1, clean_reg_cpu0, clean_reg_ar; - unsigned int f_setup_gpt2; - unsigned int f_software_update; - unsigned int new_led_on, new_adsl_on; - - if ( !param ) - return -EINVAL; - - down(&led_sem); - - reg_con0 = *DANUBE_LED_CON0; - reg_con1 = *DANUBE_LED_CON1; - reg_cpu0 = *DANUBE_LED_CPU0; - reg_ar = *DANUBE_LED_AR; - - clean_reg_con0 = 1; - clean_reg_con1 = 1; - clean_reg_cpu0 = 1; - clean_reg_ar = 1; - - f_setup_gpt2 = 0; - - f_software_update = (readl(DANUBE_LED_CON0) & LED_CON0_SWU) ? 0 : 1; - - new_led_on = f_led_on; - new_adsl_on = adsl_on; - - /* ADSL or LED */ - if ( (param->operation_mask & CONFIG_OPERATION_UPDATE_SOURCE) ) - { - if ( param->led > 0x03 || param->source > 0x03 ) - goto INVALID_PARAM; - clean_reg_con0 = 0; - reg_con0 = set_update_source(reg_con0, param->led, param->source); -#if 0 // ADSL0,1 is source for bit 0, 1 in shift register - new_adsl_on = param->source; -#endif - } - - /* Blink */ - if ( (param->operation_mask & CONFIG_OPERATION_BLINK) ) - { - if ( (param->blink_mask & 0xFF000000) || (param->blink & 0xFF000000) ) - goto INVALID_PARAM; - clean_reg_con0 = 0; - reg_con0 = set_blink_in_batch(reg_con0, param->blink_mask, param->blink); - } - - /* Edge */ - if ( (param->operation_mask & CONFIG_DATA_CLOCK_EDGE) ) - { - clean_reg_con0 = 0; - reg_con0 = set_data_clock_edge(reg_con0, param->f_data_clock_on_rising); - } - - /* Update Clock */ - if ( (param->operation_mask & CONFIG_OPERATION_UPDATE_CLOCK) ) - { - if ( param->update_clock > 0x02 || (param->update_clock == 0x02 && param->fpid > 0x3) ) - goto INVALID_PARAM; - clean_reg_con1 = 0; - f_software_update = param->update_clock == 0 ? 1 : 0; - if ( param->update_clock == 0x01 ) - f_setup_gpt2 = 1; - reg_con1 = set_update_clock(reg_con1, param->update_clock, param->fpid); - } - - /* Store Mode */ - if ( (param->operation_mask & CONFIG_OPERATION_STORE_MODE) ) - { - clean_reg_con1 = 0; - reg_con1 = set_store_mode(reg_con1, param->store_mode); - } - - /* Shift Clock */ - if ( (param->operation_mask & CONFIG_OPERATION_SHIFT_CLOCK) ) - { - if ( param->fpis > 0x03 ) - goto INVALID_PARAM; - clean_reg_con1 = 0; - reg_con1 = set_shift_clock(reg_con1, param->fpis); - } - - /* Data Offset */ - if ( (param->operation_mask & CONFIG_OPERATION_DATA_OFFSET) ) - { - if ( param->data_offset > 0x03 ) - goto INVALID_PARAM; - clean_reg_con1 = 0; - reg_con1 = set_data_offset(reg_con1, param->data_offset); - } - - /* Number of LED */ - if ( (param->operation_mask & CONFIG_OPERATION_NUMBER_OF_LED) ) - { - if ( param->number_of_enabled_led > 0x24 ) - goto INVALID_PARAM; - - /* - * If there is at lease one LED enabled, the GPIO pin must be setup. - */ - new_led_on = param->number_of_enabled_led ? 1 : 0; - - clean_reg_con1 = 0; - reg_con1 = set_number_of_enabled_led(reg_con1, param->number_of_enabled_led); - } - - /* LED Data */ - if ( (param->operation_mask & CONFIG_OPERATION_DATA) ) - { - if ( (param->data_mask & 0xFF000000) || (param->data & 0xFF000000) ) - goto INVALID_PARAM; - clean_reg_cpu0 = 0; - reg_cpu0 = set_data_in_batch(reg_cpu0, param->data_mask, param->data); - if ( f_software_update ) - { - clean_reg_con0 = 0; - reg_con0 |= 0x80000000; - } - } - - /* Access Right */ - if ( (param->operation_mask & CONFIG_OPERATION_MIPS0_ACCESS) ) - { - if ( (param->mips0_access_mask & 0xFF000000) || (param->mips0_access & 0xFF000000) ) - goto INVALID_PARAM; - clean_reg_ar = 0; - reg_ar = set_access_right(reg_ar, param->mips0_access_mask, param->mips0_access); - } - - /* Setup GPT */ - if ( f_setup_gpt2 && !new_adsl_on ) // If ADSL led is on, GPT is disabled. - { - ret = 0; - - if ( gpt_on ) - { - if ( gpt_freq != param->fpid ) - { - release_gpt(2); - gpt_on = 0; - ret = setup_gpt(2, param->fpid); - } - } - else - ret = setup_gpt(2, param->fpid); - - if ( ret ) - { -#if 1 - printk("Setup GPT error!\n"); -#endif - goto SETUP_GPT_ERROR; - } - else - { -#if 0 - printk("Setup GPT successfully!\n"); -#endif - gpt_on = 1; - } - } - else - if ( gpt_on ) - { - release_gpt(2); - gpt_on = 0; - } - - /* Turn on LED */ - if ( new_adsl_on ) - new_led_on = 1; - if ( !new_led_on || adsl_on != new_adsl_on ) - { - turn_off_led(adsl_on); - f_led_on = 0; - adsl_on = 0; - } - if ( !f_led_on && new_led_on ) - { - ret = turn_on_led(new_adsl_on); - if ( ret ) - { - printk("Setup GPIO error!\n"); - goto SETUP_GPIO_ERROR; - } - adsl_on = new_adsl_on; - f_led_on = 1; - } - - /* Write Register */ - if ( !f_led_on ) - enable_led(); - if ( !clean_reg_ar ) - *DANUBE_LED_AR = reg_ar; - if ( !clean_reg_cpu0 ) - *DANUBE_LED_CPU0 = reg_cpu0; - if ( !clean_reg_con1 ) - *DANUBE_LED_CON1 = reg_con1; - if ( !clean_reg_con0 ) - *DANUBE_LED_CON0 = reg_con0; - if ( !f_led_on ) - disable_led(); - - up(&led_sem); - return 0; - -SETUP_GPIO_ERROR: - release_gpt(2); - gpt_on = 0; -SETUP_GPT_ERROR: - up(&led_sem); - return ret; - -INVALID_PARAM: - up(&led_sem); - return -EINVAL; -} - -static int -led_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - int ret = -EINVAL; - struct led_config_param param; - - switch ( cmd ) - { - case LED_CONFIG: - copy_from_user(¶m, (char*)arg, sizeof(param)); - ret = danube_led_config(¶m); - break; - } - - return ret; -} - -static int -led_open (struct inode *inode, struct file *file) -{ - return 0; -} + /* adsl 0 and 1 leds are updated by the arc */ + writel(readl(DANUBE_LED_CON0) | DANUBE_LED_ADSL_SRC, DANUBE_LED_CON0); -static int -led_release (struct inode *inode, struct file *file) -{ - return 0; -} + /* per default, the leds are turned on */ + danube_led_enable(); -static struct file_operations led_fops = { - owner: THIS_MODULE, - ioctl: led_ioctl, - open: led_open, - release: led_release -}; + danube_led_major = register_chrdev(0, "danube_led", &danube_led_fops); -static struct miscdevice led_miscdev = { - 151, - "led", - &led_fops, - NULL, - NULL, - NULL -}; + if (!danube_led_major) + { + printk("danube_led: Error! Could not register device. %d\n", danube_led_major); + ret = -EINVAL; -int __init -danube_led_init (void) -{ - int ret = 0; - struct led_config_param param = {0}; - - enable_led(); - - writel(0, DANUBE_LED_AR); - writel(0, DANUBE_LED_CPU0); - writel(0, DANUBE_LED_CPU1); - writel(0, DANUBE_LED_CON1); - writel((0x80000000 | (DATA_CLOCKING_EDGE << 26)), DANUBE_LED_CON0); - - disable_led(); - - sema_init(&led_sem, 0); - - ret = misc_register(&led_miscdev); - if (ret == -EBUSY) - { - led_miscdev.minor = MISC_DYNAMIC_MINOR; - ret = misc_register(&led_miscdev); - } - - if (ret) - { - printk(KERN_ERR "led: can't misc_register\n"); - goto out; - } else { - printk(KERN_INFO "led: misc_register on minor = %d\n", led_miscdev.minor); + goto out; } - up(&led_sem); - - /* Add to enable hardware relay */ - /* Map for LED on reference board - WLAN_READ LED11 OUT1 15 - WARNING LED12 OUT2 14 - FXS1_LINK LED13 OUT3 13 - FXS2_LINK LED14 OUT4 12 - FXO_ACT LED15 OUT5 11 - USB_LINK LED16 OUT6 10 - ADSL2_LINK LED19 OUT7 9 - BT_LINK LED17 OUT8 8 - SD_LINK LED20 OUT9 7 - ADSL2_TRAFFIC LED31 OUT16 0 - Map for hardware relay on reference board - USB Power On OUT11 5 - RELAY OUT12 4 - */ - param.operation_mask = CONFIG_OPERATION_NUMBER_OF_LED; - param.number_of_enabled_led = 16; - danube_led_config(¶m); - param.operation_mask = CONFIG_OPERATION_DATA; - param.data_mask = 1 << 4; - param.data = 1 << 4; - danube_led_config(¶m); - - // by default, update by FSC clock (FPID) - param.operation_mask = CONFIG_OPERATION_UPDATE_CLOCK; - param.update_clock = 2; // FPID - param.fpid = 3; // 10Hz - danube_led_config(¶m); - - // source of LED 0, 1 is ADSL - param.operation_mask = CONFIG_OPERATION_UPDATE_SOURCE; - param.led = 3; // LED 0, 1 - param.source = 3; // ADSL - danube_led_config(¶m); - - // turn on USB - param.operation_mask = CONFIG_OPERATION_DATA; - param.data_mask = 1 << 5; - param.data = 1 << 5; - danube_led_config(¶m); + printk(KERN_INFO "danube_led : device registered on major %d\n", danube_led_major); out: - return ret; + return ret; } void __exit danube_led_exit (void) { - int ret; - - ret = misc_deregister(&led_miscdev); - if ( ret ) - printk(KERN_ERR "led: can't misc_deregister, get error number %d\n", -ret); - else - printk(KERN_INFO "led: misc_deregister successfully\n"); + unregister_chrdev(danube_led_major, "danube_led"); } -EXPORT_SYMBOL(danube_led_set_blink); -EXPORT_SYMBOL(danube_led_set_data); -EXPORT_SYMBOL(danube_led_config); - module_init(danube_led_init); module_exit(danube_led_exit); - diff --git a/target/linux/danube/files/include/asm-mips/danube/danube.h b/target/linux/danube/files/include/asm-mips/danube/danube.h index deb0618ea0..6329b2a826 100644 --- a/target/linux/danube/files/include/asm-mips/danube/danube.h +++ b/target/linux/danube/files/include/asm-mips/danube/danube.h @@ -309,6 +309,25 @@ #define LED_CON0_AD1 (1 << 25) #define LED_CON0_AD0 (1 << 24) +#define DANUBE_LED_2HZ (0) +#define DANUBE_LED_4HZ (1 << 23) +#define DANUBE_LED_8HZ (2 << 23) +#define DANUBE_LED_10HZ (3 << 23) +#define DANUBE_LED_MASK (0xf << 23) + +#define DANUBE_LED_UPD_SRC_FPI (1 << 31) +#define DANUBE_LED_UPD_MASK (3 << 30) +#define DANUBE_LED_ADSL_SRC (3 << 24) + +#define DANUBE_LED_GROUP0 (1 << 0) +#define DANUBE_LED_GROUP1 (1 << 1) +#define DANUBE_LED_GROUP2 (1 << 2) + +#define DANUBE_LED_RISING 0 +#define DANUBE_LED_FALLING (1 << 26) +#define DANUBE_LED_EDGE_MASK (1 << 26) + + /*------------ GPIO */ -- 2.30.2