X-Git-Url: http://git.rot13.org/?p=bcm963xx.git;a=blobdiff_plain;f=bcmdrivers%2Fopensource%2Fchar%2Fboard%2Fbcm963xx%2Fimpl1%2Fboard.c;h=3de06a4d15e6904713c26d07967175e417714e62;hp=916b7ed6a6cb3ce1becbea2d3a8b68e363ef3c7a;hb=a2d96664d0ef34bb8bed0eb7c011b47dff43c340;hpb=f76ebf3bd5a3980496d0305c613d4623a9b41680 diff --git a/bcmdrivers/opensource/char/board/bcm963xx/impl1/board.c b/bcmdrivers/opensource/char/board/bcm963xx/impl1/board.c index 916b7ed6..3de06a4d 100755 --- a/bcmdrivers/opensource/char/board/bcm963xx/impl1/board.c +++ b/bcmdrivers/opensource/char/board/bcm963xx/impl1/board.c @@ -38,12 +38,17 @@ #include #include #include +#include +#include +#include #include #include #include #include "boardparms.h" #include "cfiflash.h" +#include "bcm_intr.h" +#include "board.h" /* Typedefs. */ #if defined (NON_CONSECUTIVE_MAC) @@ -56,6 +61,14 @@ #define SHIFT_BITS 0 #endif +#if defined (WIRELESS) +#define SES_BTN_PRESSED 0x00000001 +#define SES_EVENTS SES_BTN_PRESSED /*OR all values if any*/ +#define SES_LED_OFF 0 +#define SES_LED_ON 1 +#define SES_LED_BLINK 2 +#endif + typedef struct { unsigned long ulId; @@ -69,9 +82,15 @@ typedef struct unsigned long ulPsiSize; unsigned long ulNumMacAddrs; unsigned long ucaBaseMacAddr[NVRAM_MAC_ADDRESS_LEN]; + char chCountry[4]; // USR9108 MAC_ADDR_INFO MacAddrs[1]; } NVRAM_INFO, *PNVRAM_INFO; +typedef struct +{ + unsigned long eventmask; +} BOARD_IOC, *PBOARD_IOC; + static LED_MAP_PAIR LedMapping[] = { // led name Initial state physical pin (ledMask) @@ -82,6 +101,7 @@ static LED_MAP_PAIR LedMapping[] = {kLedEnd, kLedStateOff, 0, 0, 0, 0}, {kLedEnd, kLedStateOff, 0, 0, 0, 0}, {kLedEnd, kLedStateOff, 0, 0, 0, 0}, + {kLedEnd, kLedStateOff, 0, 0, 0, 0}, {kLedEnd, kLedStateOff, 0, 0, 0, 0} // NOTE: kLedEnd has to be at the end. }; @@ -100,20 +120,46 @@ extern void kerSysLedRegisterHandler( BOARD_LED_NAME ledName, /* Prototypes. */ void __init InitNvramInfo( void ); static int board_open( struct inode *inode, struct file *filp ); -static int board_ioctl( struct inode *inode, struct file *flip, - unsigned int command, unsigned long arg ); +static int board_ioctl( struct inode *inode, struct file *flip, unsigned int command, unsigned long arg ); +static ssize_t board_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos); +static unsigned int board_poll(struct file *filp, struct poll_table_struct *wait); +static int board_release(struct inode *inode, struct file *filp); + +static BOARD_IOC* borad_ioc_alloc(void); +static void borad_ioc_free(BOARD_IOC* board_ioc); + +#if defined (WIRELESS) +static irqreturn_t sesBtn_isr(int irq, void *dev_id, struct pt_regs *ptregs); +static void __init sesBtn_mapGpio(void); +static void __init sesBtn_mapIntr(int context); +static unsigned int sesBtn_poll(struct file *file, struct poll_table_struct *wait); +static ssize_t sesBtn_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos); +static void __init sesLed_mapGpio(void); +static void sesLed_ctrl(int action); +static void __init ses_board_init(void); +static void __exit ses_board_deinit(void); +#endif static PNVRAM_INFO g_pNvramInfo = NULL; static int g_ledInitialized = 0; +static wait_queue_head_t g_board_wait_queue; static struct file_operations board_fops = { open: board_open, ioctl: board_ioctl, + poll: board_poll, + read: board_read, + release: board_release, }; uint32 board_major = 0; +#if defined (WIRELESS) +static unsigned short sesBtn_irq = BP_NOT_DEFINED; +static unsigned short sesBtn_gpio = BP_NOT_DEFINED; +static unsigned short sesLed_gpio = BP_NOT_DEFINED; +#endif #if defined(MODULE) int init_module(void) @@ -148,6 +194,7 @@ static int __init brcm_board_init( void ) {kLedWanData, BpGetWanDataLedGpio, NULL}, {kLedPPP, BpGetPppLedGpio, BpGetPppFailLedGpio}, {kLedVoip, BpGetVoipLedGpio, NULL}, + {kLedSes, BpGetWirelessSesLedGpio, NULL}, {kLedEnd, NULL, NULL} }; @@ -183,7 +230,11 @@ static int __init brcm_board_init( void ) if( pLedMap->ledName != kLedEnd ) pLedMap++; } - + + init_waitqueue_head(&g_board_wait_queue); +#if defined (WIRELESS) + ses_board_init(); +#endif boardLedInit(LedMapping); g_ledInitialized = 1; } @@ -214,6 +265,7 @@ void __init InitNvramInfo( void ) memcpy( g_pNvramInfo->ucaBaseMacAddr, pNvramData->ucaBaseMacAddr, NVRAM_MAC_ADDRESS_LEN ); g_pNvramInfo->ulSdramSize = getMemorySize(); + strcpy(g_pNvramInfo->chCountry, pNvramData->chCountry); //USR9108 } else printk("ERROR - Could not allocate memory for NVRAM data\n"); @@ -229,16 +281,80 @@ void __exit brcm_board_cleanup( void ) if (board_major != -1) { +#if defined (WIRELESS) + ses_board_deinit(); +#endif unregister_chrdev(board_major, "board_ioctl"); } } +static BOARD_IOC* borad_ioc_alloc(void) +{ + BOARD_IOC *board_ioc =NULL; + board_ioc = (BOARD_IOC*) kmalloc( sizeof(BOARD_IOC) , GFP_KERNEL ); + if(board_ioc) + { + memset(board_ioc, 0, sizeof(BOARD_IOC)); + } + return board_ioc; +} + +static void borad_ioc_free(BOARD_IOC* board_ioc) +{ + if(board_ioc) + { + kfree(board_ioc); + } +} + + static int board_open( struct inode *inode, struct file *filp ) { + filp->private_data = borad_ioc_alloc(); + + if (filp->private_data == NULL) + return -ENOMEM; + + return( 0 ); +} + +static int board_release(struct inode *inode, struct file *filp) +{ + BOARD_IOC *board_ioc = filp->private_data; + + wait_event_interruptible(g_board_wait_queue, 1); + borad_ioc_free(board_ioc); + return( 0 ); } +static unsigned int board_poll(struct file *filp, struct poll_table_struct *wait) +{ + unsigned int mask = 0; + BOARD_IOC *board_ioc = filp->private_data; + + poll_wait(filp, &g_board_wait_queue, wait); +#if defined (WIRELESS) + if(board_ioc->eventmask & SES_EVENTS){ + mask |= sesBtn_poll(filp, wait); + } +#endif + return mask; +} + + +static ssize_t board_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos) +{ + BOARD_IOC *board_ioc = filp->private_data; +#if defined (WIRELESS) + if(board_ioc->eventmask & SES_EVENTS){ + return sesBtn_read(filp, buffer, count, ppos); + } +#endif + return 0; +} + //************************************************************************************** // Utitlities for dump memory, free kernel pages, mips soft reset, etc. //************************************************************************************** @@ -507,20 +623,6 @@ static int board_ioctl( struct inode *inode, struct file *flip, kerSysMipsSoftReset(); break; - case BCM_IMAGE_TECOM: //tecom: to upload image by pieces - allowedSize = (int) flash_get_total_size() - \ - FLASH_RESERVED_AT_END - TAG_LEN - FLASH45_LENGTH_BOOT_ROM; - if( ctrlParms.strLen <= 0 || ctrlParms.strLen > allowedSize) - { - printk("Illegal root file system size [%d]. Size allowed: [%d]\n", - ctrlParms.strLen, allowedSize); - ret = -1; - break; - } - ret = kerSysBcmImageSet(ctrlParms.offset, ctrlParms.string, ctrlParms.strLen); - /*kerSysMipsSoftReset();*/ - break; - case BCM_IMAGE_KERNEL: // not used for now. break; case BCM_IMAGE_WHOLE: @@ -786,12 +888,11 @@ static int board_ioctl( struct inode *inode, struct file *flip, case BOARD_IOCTL_GET_ENET_CFG: if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) { ETHERNET_MAC_INFO EnetInfos[BP_MAX_ENET_MACS]; - int i; if (BpGetEthernetMacInfo(EnetInfos, BP_MAX_ENET_MACS) == BP_SUCCESS) { if (ctrlParms.strLen == sizeof(EnetInfos)) { __copy_to_user(ctrlParms.string, EnetInfos, sizeof(EnetInfos)); ctrlParms.result = 0; - __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS)); + __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS)); ret = 0; } else ret = -EFAULT; @@ -801,102 +902,127 @@ static int board_ioctl( struct inode *inode, struct file *flip, } break; } + else { + ret = -EFAULT; + } + break; - /* Tommy, add two functions */ - case BOARD_IOCTL_GET_GPIO: - if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) - { - int i; - uint32 j; - - //GPIO 32~36 - if (ctrlParms.strLen >= 32) - { - i = ctrlParms.strLen - 32; - j = GPIO->GPIOio_high; +#if defined (WIRELESS) + case BOARD_IOCTL_GET_WLAN_ANT_INUSE: + if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) { + unsigned short antInUse = 0; + if (BpGetWirelessAntInUse(&antInUse) == BP_SUCCESS) { + if (ctrlParms.strLen == sizeof(antInUse)) { + __copy_to_user(ctrlParms.string, &antInUse, sizeof(antInUse)); + ctrlParms.result = 0; + __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS)); + ret = 0; + } else + ret = -EFAULT; } - else - { - i = ctrlParms.strLen; - j = GPIO->GPIOio; + else { + ret = -EFAULT; + } + break; + } + else { + ret = -EFAULT; + } + break; +#endif + case BOARD_IOCTL_SET_TRIGGER_EVENT: + if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) { + BOARD_IOC *board_ioc = (BOARD_IOC *)flip->private_data; + ctrlParms.result = -EFAULT; + ret = -EFAULT; + if (ctrlParms.strLen == sizeof(unsigned long)) { + board_ioc->eventmask |= *((int*)ctrlParms.string); +#if defined (WIRELESS) + if((board_ioc->eventmask & SES_EVENTS)) { + if(sesBtn_irq != BP_NOT_DEFINED) { + BcmHalInterruptEnable(sesBtn_irq); + ctrlParms.result = 0; + ret = 0; + } + } +#endif + __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS)); } - j = (j >> i) & 1; - *ctrlParms.buf = (char) (j?1:0); - ctrlParms.result = 0; - __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS)); - ret = 0; + break; } - else + else { ret = -EFAULT; - break; + } + break; + + case BOARD_IOCTL_GET_TRIGGER_EVENT: + if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) { + BOARD_IOC *board_ioc = (BOARD_IOC *)flip->private_data; + if (ctrlParms.strLen == sizeof(unsigned long)) { + __copy_to_user(ctrlParms.string, &board_ioc->eventmask, sizeof(unsigned long)); + ctrlParms.result = 0; + __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS)); + ret = 0; + } else + ret = -EFAULT; + + break; + } + else { + ret = -EFAULT; + } + break; + + case BOARD_IOCTL_UNSET_TRIGGER_EVENT: + if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) { + if (ctrlParms.strLen == sizeof(unsigned long)) { + BOARD_IOC *board_ioc = (BOARD_IOC *)flip->private_data; + board_ioc->eventmask &= (~(*((int*)ctrlParms.string))); + ctrlParms.result = 0; + __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS)); + ret = 0; + } else + ret = -EFAULT; - case BOARD_IOCTL_SET_GPIO: + break; + } + else { + ret = -EFAULT; + } + break; +#if defined (WIRELESS) + case BOARD_IOCTL_SET_SES_LED: + if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) { + if (ctrlParms.strLen == sizeof(int)) { + sesLed_ctrl(*(int*)ctrlParms.string); + ctrlParms.result = 0; + __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS)); + ret = 0; + } else + ret = -EFAULT; + + break; + } + else { + ret = -EFAULT; + } + break; +#endif + // USR9108 Wi-Fi Country selection + case BOARD_IOCTL_GET_CNTRY_SEL: if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) { - int i; - uint32 j; - - //GPIO 32~36 - if (ctrlParms.strLen >= 32) - { - i = ctrlParms.strLen - 32; - j = 1; - GPIO->GPIODir_high |= (1 << i); //set to R/W pin - if (ctrlParms.offset) - GPIO->GPIOio_high |= (1 << i); - else - { - j = (1 << i) ^ 0xffffffff; - GPIO->GPIOio_high &= j; - } - } - else //GPIO 0~31 - { - i = ctrlParms.strLen; - j = 1; - GPIO->GPIODir |= (1 << i); //set to R/W pin - if (ctrlParms.offset) - GPIO->GPIOio |= (1 << i); - else - { - j = (1 << i) ^ 0xffffffff; - GPIO->GPIOio &= j; - } - } + __copy_to_user(ctrlParms.string, g_pNvramInfo->chCountry, 4); ctrlParms.result = 0; - __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS)); + + __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, + sizeof(BOARD_IOCTL_PARMS)); ret = 0; } else ret = -EFAULT; break; - - case BOARD_IOCTL_GET_RESET_STATUS: - { - unsigned short gpio; - unsigned long gpio_mask; - volatile unsigned long *gpio_reg; - if( BpGetPressAndHoldResetGpio( &gpio ) == BP_SUCCESS ) - { - gpio_mask = GPIO_NUM_TO_MASK(gpio); - gpio_reg = &GPIO->GPIOio; - - if( (gpio & ~BP_ACTIVE_MASK) >= 32 ) - { - gpio_mask = GPIO_NUM_TO_MASK_HIGH(gpio); - gpio_reg = &GPIO->GPIOio_high; - } - - ctrlParms.result = (int) *gpio_reg & gpio_mask; - __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS)); - ret = 0; - } - else - ret = -EFAULT; - } - break; - default: ret = -EINVAL; ctrlParms.result = 0; @@ -909,6 +1035,184 @@ static int board_ioctl( struct inode *inode, struct file *flip, } /* board_ioctl */ +/*************************************************************************** + * SES Button ISR/GPIO/LED functions. + ***************************************************************************/ +#if defined (WIRELESS) +static irqreturn_t sesBtn_isr(int irq, void *dev_id, struct pt_regs *ptregs) +{ +#if defined(_BCM96338_) || defined(CONFIG_BCM96338) + unsigned long gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio); + volatile unsigned long *gpio_reg = &GPIO->GPIOio; +#endif +#if defined(_BCM96345_) || defined(CONFIG_BCM96345) + unsigned short gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio); + volatile unsigned short *gpio_reg = &GPIO->GPIOio; +#endif +#if defined(_BCM96348_) || defined (CONFIG_BCM96348) + unsigned long gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio); + volatile unsigned long *gpio_reg = &GPIO->GPIOio; + + if( (sesBtn_gpio & ~BP_ACTIVE_MASK) >= 32 ) + { + gpio_mask = GPIO_NUM_TO_MASK_HIGH(sesBtn_gpio); + gpio_reg = &GPIO->GPIOio_high; + } +#endif + + if (!(*gpio_reg & gpio_mask)){ + wake_up_interruptible(&g_board_wait_queue); + return IRQ_RETVAL(1); + } else { + return IRQ_RETVAL(0); + } +} + +static void __init sesBtn_mapGpio() +{ + if( BpGetWirelessSesBtnGpio(&sesBtn_gpio) == BP_SUCCESS ) + { + printk("SES: Button GPIO 0x%x is enabled\n", sesBtn_gpio); + } +} + +static void __init sesBtn_mapIntr(int context) +{ + if( BpGetWirelessSesExtIntr(&sesBtn_irq) == BP_SUCCESS ) + { + printk("SES: Button Interrupt 0x%x is enabled\n", sesBtn_irq); + } + else + return; + + sesBtn_irq += INTERRUPT_ID_EXTERNAL_0; + + if (BcmHalMapInterrupt((FN_HANDLER)sesBtn_isr, context, sesBtn_irq)) { + printk("SES: Interrupt mapping failed\n"); + } + BcmHalInterruptEnable(sesBtn_irq); +} + + +static unsigned int sesBtn_poll(struct file *file, struct poll_table_struct *wait) +{ +#if defined(_BCM96338_) || defined(CONFIG_BCM96338) + unsigned long gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio); + volatile unsigned long *gpio_reg = &GPIO->GPIOio; +#endif +#if defined(_BCM96345_) || defined(CONFIG_BCM96345) + unsigned short gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio); + volatile unsigned short *gpio_reg = &GPIO->GPIOio; +#endif +#if defined(_BCM96348_) || defined (CONFIG_BCM96348) + unsigned long gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio); + volatile unsigned long *gpio_reg = &GPIO->GPIOio; + + if( (sesBtn_gpio & ~BP_ACTIVE_MASK) >= 32 ) + { + gpio_mask = GPIO_NUM_TO_MASK_HIGH(sesBtn_gpio); + gpio_reg = &GPIO->GPIOio_high; + } +#endif + + if (!(*gpio_reg & gpio_mask)){ + return POLLIN; + } + return 0; +} + +static ssize_t sesBtn_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) +{ + volatile unsigned int event=0; + ssize_t ret=0; + +#if defined(_BCM96338_) || defined (CONFIG_BCM96338) + unsigned long gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio); + volatile unsigned long *gpio_reg = &GPIO->GPIOio; +#endif +#if defined(_BCM96345_) || defined (CONFIG_BCM96345) + unsigned short gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio); + volatile unsigned short *gpio_reg = &GPIO->GPIOio; +#endif +#if defined(_BCM96348_) || defined (CONFIG_BCM96348) + unsigned long gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio); + volatile unsigned long *gpio_reg = &GPIO->GPIOio; + + if( (sesBtn_gpio & ~BP_ACTIVE_MASK) >= 32 ) + { + gpio_mask = GPIO_NUM_TO_MASK_HIGH(sesBtn_gpio); + gpio_reg = &GPIO->GPIOio_high; + } +#endif + + if(*gpio_reg & gpio_mask){ + BcmHalInterruptEnable(sesBtn_irq); + return ret; + } + event = SES_EVENTS; + __copy_to_user((char*)buffer, (char*)&event, sizeof(event)); + BcmHalInterruptEnable(sesBtn_irq); + count -= sizeof(event); + buffer += sizeof(event); + ret += sizeof(event); + return ret; +} + +static void __init sesLed_mapGpio() +{ + if( BpGetWirelessSesBtnGpio(&sesLed_gpio) == BP_SUCCESS ) + { + printk("SES: LED GPIO 0x%x is enabled\n", sesBtn_gpio); + } +} + +static void sesLed_ctrl(int action) +{ + + //char status = ((action >> 8) & 0xff); /* extract status */ + //char event = ((action >> 16) & 0xff); /* extract event */ + //char blinktype = ((action >> 24) & 0xff); /* extract blink type for SES_LED_BLINK */ + + BOARD_LED_STATE led; + + if(sesLed_gpio == BP_NOT_DEFINED) + return; + + action &= 0xff; /* extract led */ + + //printk("blinktype=%d, event=%d, status=%d\n",(int)blinktype, (int)event, (int)status); + + switch (action) + { + case SES_LED_ON: + //printk("SES: led on\n"); + led = kLedStateOn; + break; + case SES_LED_BLINK: + //printk("SES: led blink\n"); + led = kLedStateSlowBlinkContinues; + break; + case SES_LED_OFF: + default: + //printk("SES: led off\n"); + led = kLedStateOff; + } + + kerSysLedCtrl(kLedSes, led); +} + +static void __init ses_board_init() +{ + sesBtn_mapGpio(); + sesBtn_mapIntr(0); + sesLed_mapGpio(); +} +static void __exit ses_board_deinit() +{ + if(sesBtn_irq) + BcmHalInterruptDisable(sesBtn_irq); +} +#endif /*************************************************************************** * MACRO to call driver initialization and cleanup functions. @@ -948,4 +1252,6 @@ EXPORT_SYMBOL(BpGetVoipExtIntr); EXPORT_SYMBOL(BpGetHpnaExtIntr); EXPORT_SYMBOL(BpGetHpnaChipSelect); EXPORT_SYMBOL(BpGetVoipChipSelect); - +EXPORT_SYMBOL(BpGetWirelessSesBtnGpio); +EXPORT_SYMBOL(BpGetWirelessSesExtIntr); +EXPORT_SYMBOL(BpGetWirelessSesLedGpio);