X-Git-Url: http://git.rohieb.name/openwrt.git/blobdiff_plain/5febfb77522efc6ccfd1db6a93faa486ee50d653..90e9add59f05a5280f2517747029f44ddf4d2e32:/target/linux/danube/files/drivers/char/danube_led.c diff --git a/target/linux/danube/files/drivers/char/danube_led.c b/target/linux/danube/files/drivers/char/danube_led.c index 531c7ed0c..ba53abfbf 100644 --- a/target/linux/danube/files/drivers/char/danube_led.c +++ b/target/linux/danube/files/drivers/char/danube_led.c @@ -18,7 +18,6 @@ * */ -#include #include #include #include @@ -29,39 +28,57 @@ #include #include #include - -/* - * Chip Specific Head File - */ +#include #include - #include #include +#define LED_CONFIG 0x01 + +#define CONFIG_OPERATION_UPDATE_SOURCE 0x0001 +#define CONFIG_OPERATION_BLINK 0x0002 +#define CONFIG_OPERATION_UPDATE_CLOCK 0x0004 +#define CONFIG_OPERATION_STORE_MODE 0x0008 +#define CONFIG_OPERATION_SHIFT_CLOCK 0x0010 +#define CONFIG_OPERATION_DATA_OFFSET 0x0020 +#define CONFIG_OPERATION_NUMBER_OF_LED 0x0040 +#define CONFIG_OPERATION_DATA 0x0080 +#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 +}; -/* - * #################################### - * Definition - * #################################### - */ -#define DEBUG_ON_AMAZON 0 +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 BOARD_TYPE REFERENCE_BOARD - -#define DEBUG_WRITE_REGISTER 0 - #define RISING_EDGE 0 #define FALLING_EDGE 1 -#define EVALUATION_BOARD 0 -#define REFERENCE_BOARD 1 - -/* - * GPIO Driver Function Wrapping - */ #define port_reserve_pin danube_port_reserve_pin #define port_free_pin danube_port_free_pin #define port_set_altsel0 danube_port_set_altsel0 @@ -73,9 +90,6 @@ #define port_set_open_drain danube_port_set_open_drain #define port_clear_open_drain danube_port_clear_open_drain -/* - * GPIO Port Used By LED - */ #define LED_SH_PORT 0 #define LED_SH_PIN 4 #define LED_SH_DIR 1 @@ -119,9 +133,6 @@ #define ADSL_LED_IS_EXCLUSIVE 0 #endif -/* - * Define GPIO Functions - */ #if LED_SH_DIR #define LED_SH_DIR_SETUP port_set_dir_out #else @@ -227,188 +238,36 @@ #define LED_ADSL1_OPENDRAIN_SETUP port_clear_open_drain #endif -/* - * LED Device Minor Number - */ -#if !defined(LED_MINOR) - #define LED_MINOR 151 // This number is written in Linux kernel document "devices.txt" -#endif // !defined(LED_MINOR) - -/* - * Bits Operation - */ -#define GET_BITS(x, msb, lsb) (((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb)) #define SET_BITS(x, msb, lsb, value) (((x) & ~(((1 << ((msb) + 1)) - 1) ^ ((1 << (lsb)) - 1))) | (((value) & ((1 << (1 + (msb) - (lsb))) - 1)) << (lsb))) -/* - * LED Registers Mapping - */ -#define DANUBE_LED (KSEG1 + 0x1E100BB0) -#define DANUBE_LED_CON0 ((volatile u32*)(DANUBE_LED + 0x0000)) -#define DANUBE_LED_CON1 ((volatile u32*)(DANUBE_LED + 0x0004)) -#define DANUBE_LED_CPU0 ((volatile u32*)(DANUBE_LED + 0x0008)) -#define DANUBE_LED_CPU1 ((volatile u32*)(DANUBE_LED + 0x000C)) -#define DANUBE_LED_AR ((volatile u32*)(DANUBE_LED + 0x0010)) - -/* - * LED Control 0 Register - */ -#define LED_CON0_SWU (*DANUBE_LED_CON0 & (1 << 31)) -#define LED_CON0_FALLING_EDGE (*DANUBE_LED_CON0 & (1 << 26)) -#define LED_CON0_AD1 (*DANUBE_LED_CON0 & (1 << 25)) -#define LED_CON0_AD0 (*DANUBE_LED_CON0 & (1 << 24)) -#define LED_CON0_LBn(n) (*DANUBE_LED_CON0 & (1 << n)) -#define LED_CON0_DEFAULT_VALUE (0x80000000 | (DATA_CLOCKING_EDGE << 26)) - -/* - * LED Control 1 Register - */ -#define LED_CON1_US (*DANUBE_LED_CON1 >> 30) -#define LED_CON1_SCS (*DANUBE_LED_CON1 & (1 << 28)) -#define LED_CON1_FPID GET_BITS(*DANUBE_LED_CON1, 27, 23) -#define LED_CON1_FPIS GET_BITS(*DANUBE_LED_CON1, 21, 20) -#define LED_CON1_DO GET_BITS(*DANUBE_LED_CON1, 19, 18) -#define LED_CON1_G2 (*DANUBE_LED_CON1 & (1 << 2)) -#define LED_CON1_G1 (*DANUBE_LED_CON1 & (1 << 1)) -#define LED_CON1_G0 (*DANUBE_LED_CON1 & 0x01) -#define LED_CON1_G (*DANUBE_LED_CON1 & 0x07) -#define LED_CON1_DEFAULT_VALUE 0x00000000 - -/* - * LED Data Output CPU 0 Register - */ -#define LED_CPU0_Ln(n) (*DANUBE_LED_CPU0 & (1 << n)) -#define LED_LED_CPU0_DEFAULT_VALUE 0x00000000 - -/* - * LED Data Output CPU 1 Register - */ -#define LED_CPU1_Ln(n) (*DANUBE_LED_CPU1 & (1 << n)) -#define LED_LED_CPU1_DEFAULT_VALUE 0x00000000 - -/* - * LED Data Output Access Rights Register - */ -#define LED_AR_Ln(n) (*DANUBE_LED_AR & (1 << n)) -#define LED_AR_DEFAULT_VALUE 0x00000000 - - -/* - * #################################### - * Preparation of Debug on Amazon Chip - * #################################### - */ - -/* - * If try module on Amazon chip, prepare some tricks to prevent invalid memory write. - */ -#if defined(DEBUG_ON_AMAZON) && DEBUG_ON_AMAZON - char g_pFakeRegisters[0x50]; - - #undef DEBUG_WRITE_REGISTER - - #undef DANUBE_LED - #define DANUBE_LED g_pFakeRegisters - - #undef port_reserve_pin - #undef port_free_pin - #undef port_set_altsel0 - #undef port_clear_altsel0 - #undef port_set_altsel1 - #undef port_clear_altsel1 - #undef port_set_dir_out - - #define port_reserve_pin amazon_port_reserve_pin - #define port_free_pin amazon_port_free_pin - #define port_set_altsel0 amazon_port_set_altsel0 - #define port_clear_altsel0 amazon_port_clear_altsel0 - #define port_set_altsel1 amazon_port_set_altsel1 - #define port_clear_altsel1 amazon_port_clear_altsel1 - #define port_set_dir_out amazon_port_set_dir_out -#endif // defined(DEBUG_ON_AMAZON) && DEBUG_ON_AMAZON - - -/* - * #################################### - * Declaration - * #################################### - */ - -/* - * File Operations - */ -static int led_ioctl(struct inode *, struct file *, unsigned int, unsigned long); -static int led_open(struct inode *, struct file *); -static int led_release(struct inode *, struct file *); - -/* - * Software Update LED - */ static inline int update_led(void); -/* - * LED Configuration Functions - */ -static inline u32 set_update_source(u32, unsigned long, unsigned long); -static inline u32 set_blink_in_batch(u32, unsigned long, unsigned long); -static inline u32 set_data_clock_edge(u32, unsigned long); -static inline u32 set_update_clock(u32, unsigned long, unsigned long); -static inline u32 set_store_mode(u32, unsigned long); -static inline u32 set_shift_clock(u32, unsigned long); -static inline u32 set_data_offset(u32, unsigned long); -static inline u32 set_number_of_enabled_led(u32, unsigned long); -static inline u32 set_data_in_batch(u32, unsigned long, unsigned long); -static inline u32 set_access_right(u32, unsigned long, unsigned long); +static inline unsigned int set_update_source(unsigned int, unsigned long, unsigned long); +static inline unsigned int set_blink_in_batch(unsigned int, unsigned long, unsigned long); +static inline unsigned int set_data_clock_edge(unsigned int, unsigned long); +static inline unsigned int set_update_clock(unsigned int, unsigned long, unsigned long); +static inline unsigned int set_store_mode(unsigned int, unsigned long); +static inline unsigned int set_shift_clock(unsigned int, unsigned long); +static inline unsigned int set_data_offset(unsigned int, unsigned long); +static inline unsigned int set_number_of_enabled_led(unsigned int, unsigned long); +static inline unsigned int set_data_in_batch(unsigned int, unsigned long, unsigned long); +static inline unsigned int set_access_right(unsigned int, unsigned long, unsigned long); -/* - * PMU Operation - */ static inline void enable_led(void); static inline void disable_led(void); -/* - * GPIO Setup & Release - */ static inline int setup_gpio_port(unsigned long); static inline void release_gpio_port(unsigned long); -/* - * GPT Setup & Release - */ static inline int setup_gpt(int, unsigned long); static inline void release_gpt(int); -/* - * Turn On/Off LED - */ static inline int turn_on_led(unsigned long); static inline void turn_off_led(unsigned long); -/* - * #################################### - * Local Variable - * #################################### - */ - static struct semaphore led_sem; -static struct file_operations led_fops = { - owner: THIS_MODULE, - ioctl: led_ioctl, - open: led_open, - release: led_release -}; - -static struct miscdevice led_miscdev = { - LED_MINOR, - "led", - &led_fops, - NULL, - NULL, - NULL -}; - static unsigned long gpt_on = 0; static unsigned long gpt_freq = 0; @@ -418,62 +277,15 @@ static unsigned long f_led_on = 0; static int module_id; -/* - * #################################### - * Global Variable - * #################################### - */ - - -/* - * #################################### - * Local Function - * #################################### - */ - -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; -} - -static int led_release(struct inode *inode, struct file *file) -{ - return 0; -} - -/* - * Description: - * Update LEDs with data stored in register. - * Input: - * none - * Output: - * int --- 0: Success - * else: Error Code - */ -static inline int update_led(void) +static inline int +update_led (void) { int i, j; /* * GPT2 or FPID is the clock to update LEDs automatically. */ - if ( LED_CON1_US != 0 ) + if (readl(DANUBE_LED_CON1) >> 30) return 0; /* @@ -482,7 +294,7 @@ static inline int update_led(void) for ( i = 100000; i != 0; i -= j / 16 ) { down(&led_sem); - if ( !LED_CON0_SWU ) + if (!(readl(DANUBE_LED_CON0) & LED_CON0_SWU)) { *DANUBE_LED_CON0 |= 1 << 31; up(&led_sem); @@ -496,63 +308,26 @@ static inline int update_led(void) return -EBUSY; } -/* - * Description: - * Select update source for LED bit 0 and bit 1. - * Input: - * reg --- u32, the original register value going to be modified. - * led --- unsigned long, bit 0 stands for LED 0, and bit 1 stands for - * LED 1. If the bit is set, the source value is valid, else - * the source value is invalid. - * source --- unsigned long, bit 0 stands for LED 0, and bit 1 stands for - * LED 1. If the corresponding is cleared, LED is updated with - * value in data register, else LED is updated with ARC module. - * Output: - * u32 --- The updated register value. - */ -static inline u32 set_update_source(u32 reg, unsigned long led, unsigned long source) +static inline unsigned int +set_update_source (unsigned int reg, unsigned long led, unsigned long source) { return (reg & ~((led & 0x03) << 24)) | ((source & 0x03) << 24); } -/* - * Description: - * Define which of the LEDs should change their value based on the US pulse. - * Input: - * reg --- u32, the original register value going to be modified. - * mask --- unsigned long, if the corresponding bit is set, the blink value - * is valid, else the blink value is invalid. - * blink --- unsigned long, if the corresponding bit is set, the LED should - * change its value based on the US pulse. - * Output: - * u32 --- The updated register value. - */ -static inline u32 set_blink_in_batch(u32 reg, unsigned long mask, unsigned long blink) +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 u32 set_data_clock_edge(u32 reg, unsigned long f_on_rising_edge) +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)); } -/* - * Description: - * Select the clock source for US pulse. - * Input: - * reg --- u32, the original register value going to be modified. - * clock --- unsigned long, there 3 available values: - * 0x00 - use software update bit (SWU) as source. - * 0x01 - use GPT2 as clock source. - * 0x02 - use FPI as clock source. - * fpid --- unsigned long, if FPI is selected as clock source, this field - * specify the divider. Please refer to specification for detail - * description. - * Output: - * u32 --- The updated register value. - */ -static inline u32 set_update_clock(u32 reg, unsigned long clock, unsigned long fpid) +static inline unsigned int +set_update_clock (unsigned int reg, unsigned long clock, unsigned long fpid) { switch ( clock ) { @@ -563,105 +338,48 @@ static inline u32 set_update_clock(u32 reg, unsigned long clock, unsigned long f return reg; } -/* - * Description: - * Set the behavior of the LED_ST (shift register) signal. - * Input: - * reg --- u32, the original register value going to be modified. - * mode --- unsigned long, there 2 available values: - * zero - LED controller generate single pulse. - * non-zero - LED controller generate inverted shift clock. - * Output: - * u32 --- The updated register value. - */ -static inline u32 set_store_mode(u32 reg, unsigned long mode) +static inline unsigned int +set_store_mode (unsigned int reg, unsigned long mode) { return mode ? (reg | (1 << 28)) : (reg & ~(1 << 28)); } -/* - * Description: - * Select the clock source for shift clock LED_SH. - * Input: - * reg --- u32, the original register value going to be modified. - * fpis --- unsigned long, if FPI is selected as clock source, this field - * specify the divider. Please refer to specification for detail - * description. - * Output: - * u32 --- The updated register value. - */ -static inline u32 set_shift_clock(u32 reg, unsigned long fpis) +static inline +unsigned int set_shift_clock (unsigned int reg, unsigned long fpis) { return SET_BITS(reg, 21, 20, fpis); } -/* - * Description: - * Set the clock cycle offset before data is transmitted to LED_D pin. - * Input: - * reg --- u32, the original register value going to be modified. - * offset --- unsigned long, the number of clock cycles would be inserted - * before data is transmitted to LED_D pin. Zero means no cycle - * inserted. - * Output: - * u32 --- The updated register value. - */ -static inline u32 set_data_offset(u32 reg, unsigned long offset) +static inline +unsigned int set_data_offset (unsigned int reg, unsigned long offset) { return SET_BITS(reg, 19, 18, offset); } -/* - * Description: - * Enable or disable LEDs. - * Input: - * reg --- u32, the original register value going to be modified. - * number --- unsigned long, the number of LED to be enabled. This field - * could 0, 8, 16 or 24. Zero means disable all LEDs. - * Output: - * u32 --- The updated register value. - */ -static inline u32 set_number_of_enabled_led(u32 reg, unsigned long number) +static inline +unsigned int set_number_of_enabled_led (unsigned int reg, unsigned long number) { - u32 bit_mask; + unsigned int bit_mask; bit_mask = number > 16 ? 0x07 : (number > 8 ? 0x03 : (number ? 0x01 : 0x00)); return (reg & ~0x07) | bit_mask; } -/* - * Description: - * Turn on/off LEDs. - * Input: - * reg --- u32, the original register value going to be modified. - * mask --- unsigned long, if the corresponding bit is set, the data value - * is valid, else the data value is invalid. - * data --- unsigned long, if the corresponding bit is set, the LED should - * be on, else be off. - * Output: - * u32 --- The updated register value. - */ -static inline u32 set_data_in_batch(u32 reg, unsigned long mask, unsigned long data) +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 u32 set_access_right(u32 reg, unsigned long mask, unsigned long ar) +static inline unsigned int +set_access_right (unsigned int reg, unsigned long mask, unsigned long ar) { return (reg & ~(mask & 0x00FFFFFF)) | (~ar & mask); } -/* - * Description: - * Enable LED control module. - * Input: - * none - * Output: - * none - */ -static inline void enable_led(void) +static inline void +enable_led (void) { -#if !defined(DEBUG_ON_AMAZON) || !DEBUG_ON_AMAZON /* Activate LED module in PMU. */ int i = 1000000; @@ -669,57 +387,19 @@ static inline void enable_led(void) while ( --i && (*(unsigned long *)0xBF102020 & (1 << 11)) ); if ( !i ) panic("Activating LED in PMU failed!"); -#endif } -/* - * Description: - * Disable LED control module. - * Input: - * none - * Output: - * none - */ -static inline void disable_led(void) +static inline void +disable_led (void) { -#if !defined(DEBUG_ON_AMAZON) || !DEBUG_ON_AMAZON - /* Inactivating LED module in PMU. */ *(unsigned long *)0xBF10201C |= 1 << 11; -#endif } -/* - * Description: - * If LEDs are enabled, GPIO must be setup to enable LED pins. - * Input: - * none - * Output: - * int --- 0: Success - * else: Error Code - */ -static inline int setup_gpio_port(unsigned long adsl) +static inline int +setup_gpio_port (unsigned long adsl) { -#if !defined(DEBUG_ON_AMAZON) || !DEBUG_ON_AMAZON int ret = 0; - #if defined(DEBUG_WRITE_REGISTER) && DEBUG_WRITE_REGISTER - if ( adsl ) - { - *(unsigned long *)0xBE100B18 |= 0x30; - *(unsigned long *)0xBE100B1C |= 0x20; - *(unsigned long *)0xBE100B1C &= ~0x10; - *(unsigned long *)0xBE100B20 |= 0x30; - *(unsigned long *)0xBE100B24 |= 0x30; - } - else - { - *(unsigned long *)0xBE100B18 |= 0x70; - *(unsigned long *)0xBE100B1C |= 0x70; - *(unsigned long *)0xBE100B20 &= ~0x70; - *(unsigned long *)0xBE100B24 |= 0x70; - } - #else - /* * Reserve all pins before config them. */ @@ -780,25 +460,13 @@ static inline int setup_gpio_port(unsigned long adsl) LED_SH_DIR_SETUP(LED_SH_PORT, LED_SH_PIN, module_id); LED_SH_OPENDRAIN_SETUP(LED_SH_PORT, LED_SH_PIN, module_id); } - #endif -#endif return 0; } -/* - * Description: - * If LEDs are all disabled, GPIO must be released so that other application - * could reuse it. - * Input: - * none - * Output: - * none - */ -static inline void release_gpio_port(unsigned long adsl) +static inline void +release_gpio_port (unsigned long adsl) { -#if !defined(DEBUG_ON_AMAZON) || !DEBUG_ON_AMAZON - #if !defined(DEBUG_WRITE_REGISTER) || !DEBUG_WRITE_REGISTER if ( adsl ) { port_free_pin(LED_ADSL0_PORT, LED_ADSL0_PIN, module_id); @@ -810,37 +478,15 @@ static inline void release_gpio_port(unsigned long adsl) port_free_pin(LED_D_PORT, LED_D_PIN, module_id); port_free_pin(LED_SH_PORT, LED_SH_PIN, module_id); } - #endif -#endif } -/* - * Description: - * If shifter or update select GPT as clock source, this function would be - * invoked to setup corresponding GPT module. - * Attention please, this function is not working since the GPTU driver is - * not ready. - * Input: - * timer --- int, index of timer. - * freq --- unsigned long, frequency of timer (0.001Hz). This value will be - * rounded off to nearest possible value. - * Output: - * int --- 0: Success - * else: Error Code - */ -static inline int setup_gpt(int timer, unsigned long freq) +static inline int +setup_gpt (int timer, unsigned long freq) { int ret; -#if 0 - timer = TIMER(timer, 0); -#else - timer = TIMER(timer, 1); // 2B -#endif + timer = TIMER(timer, 1); -#if 0 - ret = set_timer(timer, freq, 1, 0, TIMER_FLAG_NO_HANDLE, 0, 0); -#else ret = request_timer(timer, TIMER_FLAG_SYNC | TIMER_FLAG_16BIT @@ -852,8 +498,6 @@ static inline int setup_gpt(int timer, unsigned long freq) 0, 0); -#endif -// printk("setup_gpt: timer = %d, freq = %d, return = %d\n", timer, freq, ret); if ( !ret ) { ret = start_timer(timer, 0); @@ -864,29 +508,16 @@ static inline int setup_gpt(int timer, unsigned long freq) return ret; } -/* - * Description: - * If shifter or update select other clock source, allocated GPT must be - * released so that other application can use it. - * Attention please, this function is not working since the GPTU driver is - * not ready. - * Input: - * none - * Output: - * none - */ -static inline void release_gpt(int timer) +static inline void +release_gpt (int timer) { -#if 0 - timer = TIMER(timer, 0); -#else timer = TIMER(timer, 1); -#endif stop_timer(timer); free_timer(timer); } -static inline int turn_on_led(unsigned long adsl) +static inline int +turn_on_led (unsigned long adsl) { int ret; @@ -899,33 +530,18 @@ static inline int turn_on_led(unsigned long adsl) return 0; } -static inline void turn_off_led(unsigned long adsl) +static inline void +turn_off_led (unsigned long adsl) { release_gpio_port(adsl); disable_led(); } -/* - * #################################### - * Global Function - * #################################### - */ - -/* - * Description: - * Define which of the LEDs should change its value based on the US pulse. - * Input: - * led --- unsigned int, index of the LED to be set. - * blink --- unsigned int, zero means normal mode, and non-zero means blink - * mode. - * Output: - * int --- 0: Success - * else: Error Code - */ -int danube_led_set_blink(unsigned int led, unsigned int blink) +int +danube_led_set_blink (unsigned int led, unsigned int blink) { - u32 bit_mask; + unsigned int bit_mask; if ( led > 23 ) return -EINVAL; @@ -938,23 +554,14 @@ int danube_led_set_blink(unsigned int led, unsigned int blink) *DANUBE_LED_CON0 &= ~bit_mask; up(&led_sem); - return (led == 0 && LED_CON0_AD0) || (led == 1 && LED_CON0_AD1) ? -EINVAL : 0; + return (led == 0 && (readl(DANUBE_LED_CON0) & LED_CON0_AD0)) || (led == 1 && (readl(DANUBE_LED_CON0) & LED_CON0_AD1)) ? -EINVAL : 0; } -/* - * Description: - * Turn on/off LED. - * Input: - * led --- unsigned int, index of the LED to be set. - * data --- unsigned int, zero means off, and non-zero means on. - * Output: - * int --- 0: Success - * else: Error Code - */ -int danube_led_set_data(unsigned int led, unsigned int data) +int +danube_led_set_data (unsigned int led, unsigned int data) { unsigned long f_update; - u32 bit_mask; + unsigned int bit_mask; if ( led > 23 ) return -EINVAL; @@ -971,39 +578,15 @@ int danube_led_set_data(unsigned int led, unsigned int data) return f_update ? update_led() : 0; } -/* - * Description: - * Config LED controller. - * Input: - * param --- struct led_config_param*, the members are listed below: - * operation_mask - Select operations to be performed - * led - LED to change update source - * source - Corresponding update source - * blink_mask - LEDs to set blink mode - * blink - Set to blink mode or normal mode - * update_clock - Select the source of update clock - * fpid - If FPI is the source of update clock, set the divider - * store_mode - Set clock mode or single pulse mode for store signal - * fpis - If FPI is the source of shift clock, set the divider - * data_offset - Set cycles to be inserted before data is transmitted - * number_of_enabled_led - Total number of LED to be enabled - * data_mask - LEDs to set value - * data - Corresponding value - * mips0_access_mask - LEDs to set access right - * mips0_access; - 1: the corresponding data is output from MIPS0, 0: MIPS1 - * f_data_clock_on_rising - 1: data clock on rising edge, 0: data clock on falling edge - * Output: - * int --- 0: Success - * else: Error Code - */ -int danube_led_config(struct led_config_param* param) +int +danube_led_config (struct led_config_param* param) { int ret; - u32 reg_con0, reg_con1, reg_cpu0, reg_ar; - u32 clean_reg_con0, clean_reg_con1, clean_reg_cpu0, clean_reg_ar; - u32 f_setup_gpt2; - u32 f_software_update; - u32 new_led_on, new_adsl_on; + 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; @@ -1022,7 +605,7 @@ int danube_led_config(struct led_config_param* param) f_setup_gpt2 = 0; - f_software_update = LED_CON0_SWU ? 0 : 1; + f_software_update = (readl(DANUBE_LED_CON0) & LED_CON0_SWU) ? 0 : 1; new_led_on = f_led_on; new_adsl_on = adsl_on; @@ -1183,20 +766,13 @@ int danube_led_config(struct led_config_param* param) ret = turn_on_led(new_adsl_on); if ( ret ) { -#if 1 printk("Setup GPIO error!\n"); -#endif goto SETUP_GPIO_ERROR; } adsl_on = new_adsl_on; f_led_on = 1; } -#if 0 - if ( (reg_con0 & 0x80000000) ) - printk("software update\n"); -#endif - /* Write Register */ if ( !f_led_on ) enable_led(); @@ -1211,25 +787,6 @@ int danube_led_config(struct led_config_param* param) if ( !f_led_on ) disable_led(); -#if defined(DEBUG_ON_AMAZON) && DEBUG_ON_AMAZON - *DANUBE_LED_CON0 &= 0x7FFFFFFF; -#endif - -#if 0 - #if !defined(DEBUG_ON_AMAZON) || !DEBUG_ON_AMAZON - printk("*0xBF10201C = 0x%08lX\n", *(unsigned long *)0xBF10201C); - printk("*0xBE100B18 = 0x%08lX\n", *(unsigned long *)0xBE100B18); - printk("*0xBE100B1C = 0x%08lX\n", *(unsigned long *)0xBE100B1C); - printk("*0xBE100B20 = 0x%08lX\n", *(unsigned long *)0xBE100B20); - printk("*0xBE100B24 = 0x%08lX\n", *(unsigned long *)0xBE100B24); - #endif - printk("*DANUBE_LED_CON0 = 0x%08X\n", *DANUBE_LED_CON0); - printk("*DANUBE_LED_CON1 = 0x%08X\n", *DANUBE_LED_CON1); - printk("*DANUBE_LED_CPU0 = 0x%08X\n", *DANUBE_LED_CPU0); - printk("*DANUBE_LED_CPU1 = 0x%08X\n", *DANUBE_LED_CPU1); - printk("*DANUBE_LED_AR = 0x%08X\n", *DANUBE_LED_AR); -#endif - up(&led_sem); return 0; @@ -1245,65 +802,88 @@ INVALID_PARAM: 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; -/* - * #################################### - * Init/Cleanup API - * #################################### - */ + switch ( cmd ) + { + case LED_CONFIG: + copy_from_user(¶m, (char*)arg, sizeof(param)); + ret = danube_led_config(¶m); + break; + } -/* - * Description: - * register device - * Input: - * none - * Output: - * 0 --- successful - * else --- failure, usually it is negative value of error code - */ -int __init danube_led_init(void) + return ret; +} + +static int +led_open (struct inode *inode, struct file *file) { - int ret; + return 0; +} + +static int +led_release (struct inode *inode, struct file *file) +{ + return 0; +} + +static struct file_operations led_fops = { + owner: THIS_MODULE, + ioctl: led_ioctl, + open: led_open, + release: led_release +}; + +static struct miscdevice led_miscdev = { + 151, + "led", + &led_fops, + NULL, + NULL, + NULL +}; + +int __init +danube_led_init (void) +{ + int ret = 0; struct led_config_param param = {0}; enable_led(); - /* - * Set default value to registers to turn off all LED light. - */ - *DANUBE_LED_AR = LED_AR_DEFAULT_VALUE; - *DANUBE_LED_CPU0 = LED_LED_CPU0_DEFAULT_VALUE; - *DANUBE_LED_CPU1 = LED_LED_CPU1_DEFAULT_VALUE; - *DANUBE_LED_CON1 = LED_CON1_DEFAULT_VALUE; - *DANUBE_LED_CON0 = LED_CON0_DEFAULT_VALUE; - -#if defined(DEBUG_ON_AMAZON) && DEBUG_ON_AMAZON - *DANUBE_LED_CON0 &= 0x7FFFFFFF; -#endif + 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 ) + if (ret == -EBUSY) { led_miscdev.minor = MISC_DYNAMIC_MINOR; ret = misc_register(&led_miscdev); } - if ( ret ) + + if (ret) { printk(KERN_ERR "led: can't misc_register\n"); - return ret; - } - else + goto out; + } else { printk(KERN_INFO "led: misc_register on minor = %d\n", led_miscdev.minor); + } module_id = THIS_MODULE ? (int)THIS_MODULE : ((MISC_MAJOR << 8) | led_miscdev.minor); up(&led_sem); -#if BOARD_TYPE == REFERENCE_BOARD /* Add to enable hardware relay */ /* Map for LED on reference board WLAN_READ LED11 OUT1 15 @@ -1327,7 +907,6 @@ int __init danube_led_init(void) param.data_mask = 1 << 4; param.data = 1 << 4; danube_led_config(¶m); -#endif // by default, update by FSC clock (FPID) param.operation_mask = CONFIG_OPERATION_UPDATE_CLOCK; @@ -1347,18 +926,12 @@ int __init danube_led_init(void) param.data = 1 << 5; danube_led_config(¶m); - return 0; +out: + return ret; } -/* - * Description: - * deregister device - * Input: - * none - * Output: - * none - */ -void __exit danube_led_exit(void) +void __exit +danube_led_exit (void) { int ret;