#include <linux/module.h>
#include <linux/pagemap.h>
#include <asm/uaccess.h>
+#include <linux/wait.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
#include <bcm_map_part.h>
#include <board.h>
#include <bcmTag.h>
#include "boardparms.h"
#include "cfiflash.h"
+#include "bcm_intr.h"
+#include "board.h"
/* Typedefs. */
#if defined (NON_CONSECUTIVE_MAC)
#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;
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)
{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.
};
/* 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)
{kLedWanData, BpGetWanDataLedGpio, NULL},
{kLedPPP, BpGetPppLedGpio, BpGetPppFailLedGpio},
{kLedVoip, BpGetVoipLedGpio, NULL},
+ {kLedSes, BpGetWirelessSesLedGpio, NULL},
{kLedEnd, NULL, NULL}
};
if( pLedMap->ledName != kLedEnd )
pLedMap++;
}
-
+
+ init_waitqueue_head(&g_board_wait_queue);
+#if defined (WIRELESS)
+ ses_board_init();
+#endif
boardLedInit(LedMapping);
g_ledInitialized = 1;
}
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");
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.
//**************************************************************************************
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:
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;
}
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;
} /* 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.
EXPORT_SYMBOL(BpGetHpnaExtIntr);
EXPORT_SYMBOL(BpGetHpnaChipSelect);
EXPORT_SYMBOL(BpGetVoipChipSelect);
-
+EXPORT_SYMBOL(BpGetWirelessSesBtnGpio);
+EXPORT_SYMBOL(BpGetWirelessSesExtIntr);
+EXPORT_SYMBOL(BpGetWirelessSesLedGpio);