3 Copyright 2002 Broadcom Corp. All Rights Reserved.
5 This program is free software; you can distribute it and/or modify it
6 under the terms of the GNU General Public License (Version 2) as
7 published by the Free Software Foundation.
9 This program is distributed in the hope it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
19 /***************************************************************************
22 * Description: This file contains Linux character device driver entry
23 * for the board related ioctl calls: flash, get free kernel
24 * page and dump kernel memory, etc.
26 * Created on : 2/20/2002 seanl: use cfiflash.c, cfliflash.h (AMD specific)
28 ***************************************************************************/
32 #include <linux/version.h>
33 #include <linux/init.h>
35 #include <linux/interrupt.h>
36 #include <linux/capability.h>
37 #include <linux/slab.h>
38 #include <linux/errno.h>
39 #include <linux/module.h>
40 #include <linux/pagemap.h>
41 #include <asm/uaccess.h>
42 #include <linux/wait.h>
43 #include <linux/poll.h>
44 #include <linux/sched.h>
45 #include <linux/list.h>
48 #include <bcm_map_part.h>
51 #include "boardparms.h"
52 #include "flash_api.h"
55 #include "bcm_map_part.h"
59 #if defined (WIRELESS)
60 #define SES_BTN_PRESSED 0x00000001
61 #define SES_EVENTS SES_BTN_PRESSED /*OR all values if any*/
64 #define SES_LED_BLINK 2
72 } MAC_ADDR_INFO, *PMAC_ADDR_INFO;
76 unsigned long ulSdramSize;
77 unsigned long ulPsiSize;
78 unsigned long ulNumMacAddrs;
79 unsigned char ucaBaseMacAddr[NVRAM_MAC_ADDRESS_LEN];
80 char chCountry[4]; // USR9108
81 MAC_ADDR_INFO MacAddrs[1];
82 } NVRAM_INFO, *PNVRAM_INFO;
86 unsigned long eventmask;
87 } BOARD_IOC, *PBOARD_IOC;
90 /*Dyinggasp callback*/
91 typedef void (*cb_dgasp_t)(void *arg);
92 typedef struct _CB_DGASP__LIST
94 struct list_head list;
96 cb_dgasp_t cb_dgasp_fn;
98 }CB_DGASP_LIST , *PCB_DGASP_LIST;
101 static LED_MAP_PAIR LedMapping[] =
102 { // led name Initial state physical pin (ledMask)
103 {kLedEnd, kLedStateOff, 0, 0, 0, 0},
104 {kLedEnd, kLedStateOff, 0, 0, 0, 0},
105 {kLedEnd, kLedStateOff, 0, 0, 0, 0},
106 {kLedEnd, kLedStateOff, 0, 0, 0, 0},
107 {kLedEnd, kLedStateOff, 0, 0, 0, 0},
108 {kLedEnd, kLedStateOff, 0, 0, 0, 0},
109 {kLedEnd, kLedStateOff, 0, 0, 0, 0},
110 {kLedEnd, kLedStateOff, 0, 0, 0, 0},
111 {kLedEnd, kLedStateOff, 0, 0, 0, 0} // NOTE: kLedEnd has to be at the end.
115 extern struct file fastcall *fget_light(unsigned int fd, int *fput_needed);
116 extern unsigned int nr_free_pages (void);
117 extern const char *get_system_type(void);
118 extern void kerSysFlashInit(void);
119 extern unsigned long get_nvram_start_addr(void);
120 extern unsigned long get_scratch_pad_start_addr(void);
121 extern unsigned long getMemorySize(void);
122 extern void __init boardLedInit(PLED_MAP_PAIR);
123 extern void boardLedCtrl(BOARD_LED_NAME, BOARD_LED_STATE);
124 extern void kerSysLedRegisterHandler( BOARD_LED_NAME ledName,
125 HANDLE_LED_FUNC ledHwFunc, int ledFailType );
126 extern UINT32 getCrc32(byte *pdata, UINT32 size, UINT32 crc);
129 void __init InitNvramInfo( void );
130 static int board_open( struct inode *inode, struct file *filp );
131 static int board_ioctl( struct inode *inode, struct file *flip, unsigned int command, unsigned long arg );
132 static ssize_t board_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos);
133 static unsigned int board_poll(struct file *filp, struct poll_table_struct *wait);
134 static int board_release(struct inode *inode, struct file *filp);
136 static BOARD_IOC* borad_ioc_alloc(void);
137 static void borad_ioc_free(BOARD_IOC* board_ioc);
139 /* DyingGasp function prototype */
140 static void __init kerSysDyingGaspMapIntr(void);
141 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
142 static irqreturn_t kerSysDyingGaspIsr(int irq, void * dev_id, struct pt_regs * regs);
144 static unsigned int kerSysDyingGaspIsr(void);
146 static void __init kerSysInitDyingGaspHandler( void );
147 static void __exit kerSysDeinitDyingGaspHandler( void );
148 /* -DyingGasp function prototype - */
151 #if defined (WIRELESS)
152 static irqreturn_t sesBtn_isr(int irq, void *dev_id, struct pt_regs *ptregs);
153 static void __init sesBtn_mapGpio(void);
154 static void __init sesBtn_mapIntr(int context);
155 static unsigned int sesBtn_poll(struct file *file, struct poll_table_struct *wait);
156 static ssize_t sesBtn_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos);
157 static void __init sesLed_mapGpio(void);
158 static void sesLed_ctrl(int action);
159 static void __init ses_board_init(void);
160 static void __exit ses_board_deinit(void);
163 static PNVRAM_INFO g_pNvramInfo = NULL;
164 static int g_ledInitialized = 0;
165 static wait_queue_head_t g_board_wait_queue;
166 static CB_DGASP_LIST *g_cb_dgasp_list_head = NULL;
168 static int g_wakeup_monitor = 0;
169 static struct file *g_monitor_file = NULL;
170 static struct task_struct *g_monitor_task = NULL;
171 static unsigned int (*g_orig_fop_poll)
172 (struct file *, struct poll_table_struct *) = NULL;
174 static struct file_operations board_fops =
180 release: board_release,
183 uint32 board_major = 0;
185 #if defined (WIRELESS)
186 static unsigned short sesBtn_irq = BP_NOT_DEFINED;
187 static unsigned short sesBtn_gpio = BP_NOT_DEFINED;
188 static unsigned short sesLed_gpio = BP_NOT_DEFINED;
192 int init_module(void)
194 return( brcm_board_init() );
197 void cleanup_module(void)
200 printk("brcm flash: cleanup_module failed because module is in use\n");
202 brcm_board_cleanup();
208 static int __init brcm_board_init( void )
210 typedef int (*BP_LED_FUNC) (unsigned short *);
211 static struct BpLedInformation
213 BOARD_LED_NAME ledName;
215 BP_LED_FUNC bpFuncFail;
217 {{kLedAdsl, BpGetAdslLedGpio, BpGetAdslFailLedGpio},
218 {kLedWireless, BpGetWirelessLedGpio, NULL},
219 {kLedUsb, BpGetUsbLedGpio, NULL},
220 {kLedHpna, BpGetHpnaLedGpio, NULL},
221 {kLedWanData, BpGetWanDataLedGpio, NULL},
222 {kLedPPP, BpGetPppLedGpio, BpGetPppFailLedGpio},
223 {kLedVoip, BpGetVoipLedGpio, NULL},
224 {kLedSes, BpGetWirelessSesLedGpio, NULL},
225 {kLedEnd, NULL, NULL}
230 ret = register_chrdev(BOARD_DRV_MAJOR, "bcrmboard", &board_fops );
232 printk( "brcm_board_init(major %d): fail to register device.\n",BOARD_DRV_MAJOR);
235 PLED_MAP_PAIR pLedMap = LedMapping;
237 struct BpLedInformation *pInfo;
239 printk("brcmboard: brcm_board_init entry\n");
240 board_major = BOARD_DRV_MAJOR;
243 for( pInfo = bpLedInfo; pInfo->ledName != kLedEnd; pInfo++ )
245 if( pInfo->bpFunc && (*pInfo->bpFunc) (&gpio) == BP_SUCCESS )
247 pLedMap->ledName = pInfo->ledName;
248 pLedMap->ledMask = GPIO_NUM_TO_MASK(gpio);
249 pLedMap->ledActiveLow = (gpio & BP_ACTIVE_LOW) ? 1 : 0;
251 if( pInfo->bpFuncFail && (*pInfo->bpFuncFail) (&gpio) == BP_SUCCESS )
253 pLedMap->ledName = pInfo->ledName;
254 pLedMap->ledMaskFail = GPIO_NUM_TO_MASK(gpio);
255 pLedMap->ledActiveLowFail = (gpio & BP_ACTIVE_LOW) ? 1 : 0;
257 if( pLedMap->ledName != kLedEnd )
261 init_waitqueue_head(&g_board_wait_queue);
262 #if defined (WIRELESS)
265 kerSysInitDyingGaspHandler();
266 kerSysDyingGaspMapIntr();
268 boardLedInit(LedMapping);
269 g_ledInitialized = 1;
275 void __init InitNvramInfo( void )
277 PNVRAM_DATA pNvramData = (PNVRAM_DATA) get_nvram_start_addr();
278 unsigned long ulNumMacAddrs = pNvramData->ulNumMacAddrs;
280 if( ulNumMacAddrs > 0 && ulNumMacAddrs <= NVRAM_MAC_COUNT_MAX )
282 unsigned long ulNvramInfoSize =
283 sizeof(NVRAM_INFO) + ((sizeof(MAC_ADDR_INFO) - 1) * ulNumMacAddrs);
285 g_pNvramInfo = (PNVRAM_INFO) kmalloc( ulNvramInfoSize, GFP_KERNEL );
289 unsigned long ulPsiSize;
290 if( BpGetPsiSize( &ulPsiSize ) != BP_SUCCESS )
291 ulPsiSize = NVRAM_PSI_DEFAULT;
292 memset( g_pNvramInfo, 0x00, ulNvramInfoSize );
293 g_pNvramInfo->ulPsiSize = ulPsiSize * 1024;
294 g_pNvramInfo->ulNumMacAddrs = pNvramData->ulNumMacAddrs;
295 memcpy( g_pNvramInfo->ucaBaseMacAddr, pNvramData->ucaBaseMacAddr,
296 NVRAM_MAC_ADDRESS_LEN );
297 g_pNvramInfo->ulSdramSize = getMemorySize();
298 strcpy(g_pNvramInfo->chCountry, pNvramData->chCountry); //USR9108
301 printk("ERROR - Could not allocate memory for NVRAM data\n");
304 printk("ERROR - Invalid number of MAC addresses (%ld) is configured.\n",
308 void __exit brcm_board_cleanup( void )
310 printk("brcm_board_cleanup()\n");
312 if (board_major != -1)
314 #if defined (WIRELESS)
317 kerSysDeinitDyingGaspHandler();
318 unregister_chrdev(board_major, "board_ioctl");
322 static BOARD_IOC* borad_ioc_alloc(void)
324 BOARD_IOC *board_ioc =NULL;
325 board_ioc = (BOARD_IOC*) kmalloc( sizeof(BOARD_IOC) , GFP_KERNEL );
328 memset(board_ioc, 0, sizeof(BOARD_IOC));
333 static void borad_ioc_free(BOARD_IOC* board_ioc)
342 static int board_open( struct inode *inode, struct file *filp )
344 filp->private_data = borad_ioc_alloc();
346 if (filp->private_data == NULL)
352 static int board_release(struct inode *inode, struct file *filp)
354 BOARD_IOC *board_ioc = filp->private_data;
356 wait_event_interruptible(g_board_wait_queue, 1);
357 borad_ioc_free(board_ioc);
363 static unsigned int board_poll(struct file *filp, struct poll_table_struct *wait)
365 unsigned int mask = 0;
366 #if defined (WIRELESS)
367 BOARD_IOC *board_ioc = filp->private_data;
370 poll_wait(filp, &g_board_wait_queue, wait);
371 #if defined (WIRELESS)
372 if(board_ioc->eventmask & SES_EVENTS){
373 mask |= sesBtn_poll(filp, wait);
381 static ssize_t board_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos)
383 #if defined (WIRELESS)
384 BOARD_IOC *board_ioc = filp->private_data;
385 if(board_ioc->eventmask & SES_EVENTS){
386 return sesBtn_read(filp, buffer, count, ppos);
392 //**************************************************************************************
393 // Utitlities for dump memory, free kernel pages, mips soft reset, etc.
394 //**************************************************************************************
396 /***********************************************************************
397 * Function Name: dumpaddr
398 * Description : Display a hex dump of the specified address.
399 ***********************************************************************/
400 void dumpaddr( unsigned char *pAddr, int nLen )
402 static char szHexChars[] = "0123456789abcdef";
405 unsigned char ch, *q;
411 sprintf( szLine, "%8.8lx: ", (unsigned long) pAddr );
412 p = szLine + strlen(szLine);
414 for(i = 0; i < 16 && nLen > 0; i += sizeof(long), nLen -= sizeof(long))
416 ul = *(unsigned long *) &pAddr[i];
417 q = (unsigned char *) &ul;
418 for( j = 0; j < sizeof(long); j++ )
420 *p++ = szHexChars[q[j] >> 4];
421 *p++ = szHexChars[q[j] & 0x0f];
426 for( j = 0; j < 16 - i; j++ )
427 *p++ = ' ', *p++ = ' ', *p++ = ' ';
429 *p++ = ' ', *p++ = ' ', *p++ = ' ';
431 for( j = 0; j < i; j++ )
434 *p++ = (ch > ' ' && ch < '~') ? ch : '.';
438 printk( "%s\r\n", szLine );
446 void kerSysMipsSoftReset(void)
448 #if defined(CONFIG_BCM96348)
449 if (PERF->RevID == 0x634800A1) {
450 typedef void (*FNPTR) (void);
451 FNPTR bootaddr = (FNPTR) FLASH_BASE;
454 /* Disable interrupts. */
457 /* Reset all blocks. */
458 PERF->BlockSoftReset &= ~BSR_ALL_BLOCKS;
459 for( i = 0; i < 1000000; i++ )
461 PERF->BlockSoftReset |= BSR_ALL_BLOCKS;
462 /* Jump to the power on address. */
466 PERF->pll_control |= SOFT_RESET; // soft reset mips
468 PERF->pll_control |= SOFT_RESET; // soft reset mips
473 int kerSysGetMacAddress( unsigned char *pucaMacAddr, unsigned long ulId )
475 const unsigned long constMacAddrIncIndex = 3;
477 PMAC_ADDR_INFO pMai = NULL;
478 PMAC_ADDR_INFO pMaiFreeNoId = NULL;
479 PMAC_ADDR_INFO pMaiFreeId = NULL;
480 unsigned long i = 0, ulIdxNoId = 0, ulIdxId = 0, baseMacAddr = 0;
482 /* baseMacAddr = last 3 bytes of the base MAC address treated as a 24 bit integer */
483 memcpy((unsigned char *) &baseMacAddr,
484 &g_pNvramInfo->ucaBaseMacAddr[constMacAddrIncIndex],
485 NVRAM_MAC_ADDRESS_LEN - constMacAddrIncIndex);
488 for( i = 0, pMai = g_pNvramInfo->MacAddrs; i < g_pNvramInfo->ulNumMacAddrs;
491 if( ulId == pMai->ulId || ulId == MAC_ADDRESS_ANY )
493 /* This MAC address has been used by the caller in the past. */
494 baseMacAddr = (baseMacAddr + i) << 8;
495 memcpy( pucaMacAddr, g_pNvramInfo->ucaBaseMacAddr,
496 constMacAddrIncIndex);
497 memcpy( pucaMacAddr + constMacAddrIncIndex, (unsigned char *)
498 &baseMacAddr, NVRAM_MAC_ADDRESS_LEN - constMacAddrIncIndex );
500 pMaiFreeNoId = pMaiFreeId = NULL;
504 if( pMai->chInUse == 0 )
506 if( pMai->ulId == 0 && pMaiFreeNoId == NULL )
508 /* This is an available MAC address that has never been
515 if( pMai->ulId != 0 && pMaiFreeId == NULL )
517 /* This is an available MAC address that has been used
518 * before. Use addresses that have never been used
519 * first, before using this one.
527 if( pMaiFreeNoId || pMaiFreeId )
529 /* An available MAC address was found. */
530 memcpy(pucaMacAddr, g_pNvramInfo->ucaBaseMacAddr,NVRAM_MAC_ADDRESS_LEN);
533 baseMacAddr = (baseMacAddr + ulIdxNoId) << 8;
534 memcpy( pucaMacAddr, g_pNvramInfo->ucaBaseMacAddr,
535 constMacAddrIncIndex);
536 memcpy( pucaMacAddr + constMacAddrIncIndex, (unsigned char *)
537 &baseMacAddr, NVRAM_MAC_ADDRESS_LEN - constMacAddrIncIndex );
538 pMaiFreeNoId->ulId = ulId;
539 pMaiFreeNoId->chInUse = 1;
543 baseMacAddr = (baseMacAddr + ulIdxId) << 8;
544 memcpy( pucaMacAddr, g_pNvramInfo->ucaBaseMacAddr,
545 constMacAddrIncIndex);
546 memcpy( pucaMacAddr + constMacAddrIncIndex, (unsigned char *)
547 &baseMacAddr, NVRAM_MAC_ADDRESS_LEN - constMacAddrIncIndex );
548 pMaiFreeId->ulId = ulId;
549 pMaiFreeId->chInUse = 1;
553 if( i == g_pNvramInfo->ulNumMacAddrs )
554 nRet = -EADDRNOTAVAIL;
557 } /* kerSysGetMacAddr */
559 int kerSysReleaseMacAddress( unsigned char *pucaMacAddr )
561 const unsigned long constMacAddrIncIndex = 3;
563 unsigned long ulIdx = 0;
564 unsigned long baseMacAddr = 0;
565 unsigned long relMacAddr = 0;
567 /* baseMacAddr = last 3 bytes of the base MAC address treated as a 24 bit integer */
568 memcpy((unsigned char *) &baseMacAddr,
569 &g_pNvramInfo->ucaBaseMacAddr[constMacAddrIncIndex],
570 NVRAM_MAC_ADDRESS_LEN - constMacAddrIncIndex);
573 /* Get last 3 bytes of MAC address to release. */
574 memcpy((unsigned char *) &relMacAddr, &pucaMacAddr[constMacAddrIncIndex],
575 NVRAM_MAC_ADDRESS_LEN - constMacAddrIncIndex);
578 ulIdx = relMacAddr - baseMacAddr;
580 if( ulIdx < g_pNvramInfo->ulNumMacAddrs )
582 PMAC_ADDR_INFO pMai = &g_pNvramInfo->MacAddrs[ulIdx];
583 if( pMai->chInUse == 1 )
591 } /* kerSysReleaseMacAddr */
593 int kerSysGetSdramSize( void )
595 return( (int) g_pNvramInfo->ulSdramSize );
596 } /* kerSysGetSdramSize */
599 void kerSysLedCtrl(BOARD_LED_NAME ledName, BOARD_LED_STATE ledState)
601 if (g_ledInitialized)
602 boardLedCtrl(ledName, ledState);
605 unsigned int kerSysMonitorPollHook( struct file *f, struct poll_table_struct *t)
607 int mask = (*g_orig_fop_poll) (f, t);
609 if( g_wakeup_monitor == 1 && g_monitor_file == f )
611 /* If g_wakeup_monitor is non-0, the user mode application needs to
612 * return from a blocking select function. Return POLLPRI which will
613 * cause the select to return with the exception descriptor set.
616 g_wakeup_monitor = 0;
622 /* Put the user mode application that monitors link state on a run queue. */
623 void kerSysWakeupMonitorTask( void )
625 g_wakeup_monitor = 1;
627 wake_up_process( g_monitor_task );
630 static PFILE_TAG getTagFromPartition(int imageNumber)
632 static unsigned char sectAddr1[sizeof(FILE_TAG)];
633 static unsigned char sectAddr2[sizeof(FILE_TAG)];
636 PFILE_TAG pTag = NULL;
637 unsigned char *pBase = flash_get_memptr(0);
638 unsigned char *pSectAddr = NULL;
640 /* The image tag for the first image is always after the boot loader.
641 * The image tag for the second image, if it exists, is at one half
644 if( imageNumber == 1 )
646 blk = flash_get_blk((int) (pBase + FLASH_LENGTH_BOOT_ROM));
647 pSectAddr = sectAddr1;
650 if( imageNumber == 2 )
652 blk = flash_get_blk((int) (pBase + (flash_get_total_size() / 2)));
653 pSectAddr = sectAddr2;
658 memset(pSectAddr, 0x00, sizeof(FILE_TAG));
659 flash_read_buf((unsigned short) blk, 0, pSectAddr, sizeof(FILE_TAG));
660 crc = CRC32_INIT_VALUE;
661 crc = getCrc32(pSectAddr, (UINT32)TAG_LEN-TOKEN_LEN, crc);
662 pTag = (PFILE_TAG) pSectAddr;
663 if (crc != (UINT32)(*(UINT32*)(pTag->tagValidationToken)))
670 static int getPartitionFromTag( PFILE_TAG pTag )
676 PFILE_TAG pTag1 = getTagFromPartition(1);
677 PFILE_TAG pTag2 = getTagFromPartition(2);
678 int sequence = simple_strtoul(pTag->imageSequence, NULL, 10);
679 int sequence1 = (pTag1) ? simple_strtoul(pTag1->imageSequence, NULL, 10)
681 int sequence2 = (pTag2) ? simple_strtoul(pTag2->imageSequence, NULL, 10)
684 if( pTag1 && sequence == sequence1 )
687 if( pTag2 && sequence == sequence2 )
694 static PFILE_TAG getBootImageTag(void)
696 PFILE_TAG pTag = NULL;
697 PFILE_TAG pTag1 = getTagFromPartition(1);
698 PFILE_TAG pTag2 = getTagFromPartition(2);
702 /* Two images are flashed. */
703 int sequence1 = simple_strtoul(pTag1->imageSequence, NULL, 10);
704 int sequence2 = simple_strtoul(pTag2->imageSequence, NULL, 10);
706 char bootPartition = BOOT_LATEST_IMAGE;
707 NVRAM_DATA nvramData;
709 memcpy((char *) &nvramData, (char *) get_nvram_start_addr(),
711 for( p = nvramData.szBootline; p[2] != '\0'; p++ )
712 if( p[0] == 'p' && p[1] == '=' )
714 bootPartition = p[2];
718 if( bootPartition == BOOT_LATEST_IMAGE )
719 pTag = (sequence2 > sequence1) ? pTag2 : pTag1;
720 else /* Boot from the image configured. */
721 pTag = (sequence2 < sequence1) ? pTag2 : pTag1;
724 /* One image is flashed. */
725 pTag = (pTag2) ? pTag2 : pTag1;
730 static void UpdateImageSequenceNumber( unsigned char *imageSequence )
732 int newImageSequence = 0;
733 PFILE_TAG pTag = getTagFromPartition(1);
736 newImageSequence = simple_strtoul(pTag->imageSequence, NULL, 10);
738 pTag = getTagFromPartition(2);
739 if(pTag && simple_strtoul(pTag->imageSequence, NULL, 10) > newImageSequence)
740 newImageSequence = simple_strtoul(pTag->imageSequence, NULL, 10);
743 sprintf(imageSequence, "%d", newImageSequence);
746 static int flashFsKernelImage( int destAddr, unsigned char *imagePtr,
750 PFILE_TAG pTag = (PFILE_TAG) imagePtr;
751 int rootfsAddr = simple_strtoul(pTag->rootfsAddress, NULL, 10) + BOOT_OFFSET;
752 int kernelAddr = simple_strtoul(pTag->kernelAddress, NULL, 10) + BOOT_OFFSET;
754 char *tagFs = imagePtr;
755 unsigned int baseAddr = (unsigned int) flash_get_memptr(0);
756 unsigned int totalSize = (unsigned int) flash_get_total_size();
757 unsigned int availableSizeOneImg = totalSize -
758 ((unsigned int) rootfsAddr - baseAddr) - FLASH_RESERVED_AT_END;
759 unsigned int reserveForTwoImages =
760 (FLASH_LENGTH_BOOT_ROM > FLASH_RESERVED_AT_END)
761 ? FLASH_LENGTH_BOOT_ROM : FLASH_RESERVED_AT_END;
762 unsigned int availableSizeTwoImgs =
763 (totalSize / 2) - reserveForTwoImages;
764 unsigned int newImgSize = simple_strtoul(pTag->rootfsLen, NULL, 10) +
765 simple_strtoul(pTag->kernelLen, NULL, 10);
766 PFILE_TAG pCurTag = getBootImageTag();
767 UINT32 crc = CRC32_INIT_VALUE;
768 unsigned int curImgSize = 0;
769 NVRAM_DATA nvramData;
771 memcpy((char *)&nvramData, (char *)get_nvram_start_addr(),sizeof(nvramData));
775 curImgSize = simple_strtoul(pCurTag->rootfsLen, NULL, 10) +
776 simple_strtoul(pCurTag->kernelLen, NULL, 10);
779 if( newImgSize > availableSizeOneImg)
781 printk("Illegal image size %d. Image size must not be greater "
782 "than %d.\n", newImgSize, availableSizeOneImg);
786 if( getTagFromPartition(1) != NULL && getTagFromPartition(2) != NULL &&
787 newImgSize > availableSizeTwoImgs )
789 printk("Illegal image size %d. Image size must not be greater "
790 "than %d.\n", newImgSize, availableSizeTwoImgs);
794 // If the current image fits in half the flash space and the new
795 // image to flash also fits in half the flash space, then flash it
796 // in the partition that is not currently being used to boot from.
797 if( curImgSize <= availableSizeTwoImgs &&
798 newImgSize <= availableSizeTwoImgs &&
799 getPartitionFromTag( pCurTag ) == 1 )
801 // Update rootfsAddr to point to the second boot partition.
802 int offset = (totalSize / 2) + TAG_LEN;
804 sprintf(((PFILE_TAG) tagFs)->kernelAddress, "%lu",
805 (unsigned long) IMAGE_BASE + offset + (kernelAddr - rootfsAddr));
806 kernelAddr = baseAddr + offset + (kernelAddr - rootfsAddr);
808 sprintf(((PFILE_TAG) tagFs)->rootfsAddress, "%lu",
809 (unsigned long) IMAGE_BASE + offset);
810 rootfsAddr = baseAddr + offset;
813 UpdateImageSequenceNumber( ((PFILE_TAG) tagFs)->imageSequence );
814 crc = getCrc32((unsigned char *)tagFs, (UINT32)TAG_LEN-TOKEN_LEN, crc);
815 *(unsigned long *) &((PFILE_TAG) tagFs)->tagValidationToken[0] = crc;
817 if( (status = kerSysBcmImageSet((rootfsAddr-TAG_LEN), tagFs,
818 TAG_LEN + newImgSize)) != 0 )
820 printk("Failed to flash root file system. Error: %d\n", status);
824 for( p = nvramData.szBootline; p[2] != '\0'; p++ )
825 if( p[0] == 'p' && p[1] == '=' && p[2] != BOOT_LATEST_IMAGE )
827 UINT32 crc = CRC32_INIT_VALUE;
829 // Change boot partition to boot from new image.
830 p[2] = BOOT_LATEST_IMAGE;
832 nvramData.ulCheckSum = 0;
833 crc = getCrc32((char *)&nvramData, (UINT32) sizeof(NVRAM_DATA), crc);
834 nvramData.ulCheckSum = crc;
835 kerSysNvRamSet( (char *) &nvramData, sizeof(nvramData), 0);
842 PFILE_TAG kerSysImageTagGet(void)
844 return( getBootImageTag() );
848 //********************************************************************************************
849 // misc. ioctl calls come to here. (flash, led, reset, kernel memory access, etc.)
850 //********************************************************************************************
851 static int board_ioctl( struct inode *inode, struct file *flip,
852 unsigned int command, unsigned long arg )
855 BOARD_IOCTL_PARMS ctrlParms;
856 unsigned char ucaMacAddr[NVRAM_MAC_ADDRESS_LEN];
860 case BOARD_IOCTL_FLASH_INIT:
861 // not used for now. kerSysBcmImageInit();
865 case BOARD_IOCTL_FLASH_WRITE:
866 if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0)
868 NVRAM_DATA SaveNvramData;
869 PNVRAM_DATA pNvramData = (PNVRAM_DATA) get_nvram_start_addr();
871 switch (ctrlParms.action)
874 ret = kerSysScratchPadSet(ctrlParms.string, ctrlParms.buf, ctrlParms.offset);
878 ret = kerSysPersistentSet(ctrlParms.string, ctrlParms.strLen, ctrlParms.offset);
882 ret = kerSysNvRamSet(ctrlParms.string, ctrlParms.strLen, ctrlParms.offset);
886 if( ctrlParms.strLen <= 0 || ctrlParms.strLen > FLASH_LENGTH_BOOT_ROM )
888 printk("Illegal CFE size [%d]. Size allowed: [%d]\n",
889 ctrlParms.strLen, FLASH_LENGTH_BOOT_ROM);
894 // save NVRAM data into a local structure
895 memcpy( &SaveNvramData, pNvramData, sizeof(NVRAM_DATA) );
897 // set memory type field
898 BpGetSdramSize( (unsigned long *) &ctrlParms.string[SDRAM_TYPE_ADDRESS_OFFSET] );
900 ret = kerSysBcmImageSet(ctrlParms.offset + BOOT_OFFSET, ctrlParms.string, ctrlParms.strLen);
902 // if nvram is not valid, restore the current nvram settings
903 if( BpSetBoardId( pNvramData->szBoardId ) != BP_SUCCESS &&
904 *(unsigned long *) pNvramData == NVRAM_DATA_ID )
906 kerSysNvRamSet((char *) &SaveNvramData, sizeof(SaveNvramData), 0);
911 if( (ret = flashFsKernelImage( ctrlParms.offset,
912 ctrlParms.string, ctrlParms.strLen)) == 0 )
914 kerSysMipsSoftReset();
918 case BCM_IMAGE_KERNEL: // not used for now.
920 case BCM_IMAGE_WHOLE:
921 if(ctrlParms.strLen <= 0)
923 printk("Illegal flash image size [%d].\n", ctrlParms.strLen);
928 // save NVRAM data into a local structure
929 memcpy( &SaveNvramData, pNvramData, sizeof(NVRAM_DATA) );
931 ret = kerSysBcmImageSet(ctrlParms.offset, ctrlParms.string, ctrlParms.strLen);
933 // if nvram is not valid, restore the current nvram settings
934 if( BpSetBoardId( pNvramData->szBoardId ) != BP_SUCCESS &&
935 *(unsigned long *) pNvramData == NVRAM_DATA_ID )
937 kerSysNvRamSet((char *) &SaveNvramData, sizeof(SaveNvramData), 0);
940 kerSysMipsSoftReset();
945 printk("flash_ioctl_command: invalid command %d\n", ctrlParms.action);
948 ctrlParms.result = ret;
949 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
955 case BOARD_IOCTL_FLASH_READ:
956 if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0)
958 switch (ctrlParms.action)
961 ret = kerSysScratchPadGet(ctrlParms.string, ctrlParms.buf, ctrlParms.offset);
965 ret = kerSysPersistentGet(ctrlParms.string, ctrlParms.strLen, ctrlParms.offset);
969 ret = kerSysNvRamGet(ctrlParms.string, ctrlParms.strLen, ctrlParms.offset);
973 ret = kerSysFlashSizeGet();
978 printk("Not supported. invalid command %d\n", ctrlParms.action);
981 ctrlParms.result = ret;
982 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
988 case BOARD_IOCTL_GET_NR_PAGES:
989 ctrlParms.result = nr_free_pages() + get_page_cache_size();
990 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
994 case BOARD_IOCTL_DUMP_ADDR:
995 if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0)
997 dumpaddr( (unsigned char *) ctrlParms.string, ctrlParms.strLen );
998 ctrlParms.result = 0;
999 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
1006 case BOARD_IOCTL_SET_MEMORY:
1007 if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0)
1009 unsigned long *pul = (unsigned long *) ctrlParms.string;
1010 unsigned short *pus = (unsigned short *) ctrlParms.string;
1011 unsigned char *puc = (unsigned char *) ctrlParms.string;
1012 switch( ctrlParms.strLen )
1015 *pul = (unsigned long) ctrlParms.offset;
1018 *pus = (unsigned short) ctrlParms.offset;
1021 *puc = (unsigned char) ctrlParms.offset;
1024 dumpaddr( (unsigned char *) ctrlParms.string, sizeof(long) );
1025 ctrlParms.result = 0;
1026 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
1033 case BOARD_IOCTL_MIPS_SOFT_RESET:
1034 kerSysMipsSoftReset();
1037 case BOARD_IOCTL_LED_CTRL:
1038 if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0)
1040 kerSysLedCtrl((BOARD_LED_NAME)ctrlParms.strLen, (BOARD_LED_STATE)ctrlParms.offset);
1045 case BOARD_IOCTL_GET_ID:
1046 if (copy_from_user((void*)&ctrlParms, (void*)arg,
1047 sizeof(ctrlParms)) == 0)
1049 if( ctrlParms.string )
1051 char *p = (char *) get_system_type();
1052 if( strlen(p) + 1 < ctrlParms.strLen )
1053 ctrlParms.strLen = strlen(p) + 1;
1054 __copy_to_user(ctrlParms.string, p, ctrlParms.strLen);
1057 ctrlParms.result = 0;
1058 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms,
1059 sizeof(BOARD_IOCTL_PARMS));
1063 case BOARD_IOCTL_GET_MAC_ADDRESS:
1064 if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0)
1066 ctrlParms.result = kerSysGetMacAddress( ucaMacAddr,
1069 if( ctrlParms.result == 0 )
1071 __copy_to_user(ctrlParms.string, ucaMacAddr,
1072 sizeof(ucaMacAddr));
1075 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms,
1076 sizeof(BOARD_IOCTL_PARMS));
1083 case BOARD_IOCTL_RELEASE_MAC_ADDRESS:
1084 if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0)
1086 if (copy_from_user((void*)ucaMacAddr, (void*)ctrlParms.string, \
1087 NVRAM_MAC_ADDRESS_LEN) == 0)
1089 ctrlParms.result = kerSysReleaseMacAddress( ucaMacAddr );
1093 ctrlParms.result = -EACCES;
1096 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms,
1097 sizeof(BOARD_IOCTL_PARMS));
1104 case BOARD_IOCTL_GET_PSI_SIZE:
1105 ctrlParms.result = (int) g_pNvramInfo->ulPsiSize;
1106 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
1110 case BOARD_IOCTL_GET_SDRAM_SIZE:
1111 ctrlParms.result = (int) g_pNvramInfo->ulSdramSize;
1112 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
1116 case BOARD_IOCTL_GET_BASE_MAC_ADDRESS:
1117 if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0)
1119 __copy_to_user(ctrlParms.string, g_pNvramInfo->ucaBaseMacAddr, NVRAM_MAC_ADDRESS_LEN);
1120 ctrlParms.result = 0;
1122 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms,
1123 sizeof(BOARD_IOCTL_PARMS));
1130 case BOARD_IOCTL_GET_CHIP_ID:
1131 ctrlParms.result = (int) (PERF->RevID & 0xFFFF0000) >> 16;
1132 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
1136 case BOARD_IOCTL_GET_NUM_ENET: {
1137 ETHERNET_MAC_INFO EnetInfos[BP_MAX_ENET_MACS];
1139 if (BpGetEthernetMacInfo(EnetInfos, BP_MAX_ENET_MACS) == BP_SUCCESS) {
1140 for( i = 0; i < BP_MAX_ENET_MACS; i++) {
1141 if (EnetInfos[i].ucPhyType != BP_ENET_NO_PHY) {
1145 ctrlParms.result = numeth;
1146 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
1155 case BOARD_IOCTL_GET_CFE_VER:
1156 if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
1157 char *vertag = (char *)(FLASH_BASE + CFE_VERSION_OFFSET);
1158 if (ctrlParms.strLen < CFE_VERSION_SIZE) {
1159 ctrlParms.result = 0;
1160 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
1163 else if (strncmp(vertag, "cfe-v", 5)) { // no tag info in flash
1164 ctrlParms.result = 0;
1165 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
1169 ctrlParms.result = 1;
1170 __copy_to_user(ctrlParms.string, vertag+CFE_VERSION_MARK_SIZE, CFE_VERSION_SIZE);
1171 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
1180 case BOARD_IOCTL_GET_ENET_CFG:
1181 if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
1182 ETHERNET_MAC_INFO EnetInfos[BP_MAX_ENET_MACS];
1183 if (BpGetEthernetMacInfo(EnetInfos, BP_MAX_ENET_MACS) == BP_SUCCESS) {
1184 if (ctrlParms.strLen == sizeof(EnetInfos)) {
1185 __copy_to_user(ctrlParms.string, EnetInfos, sizeof(EnetInfos));
1186 ctrlParms.result = 0;
1187 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
1202 #if defined (WIRELESS)
1203 case BOARD_IOCTL_GET_WLAN_ANT_INUSE:
1204 if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
1205 unsigned short antInUse = 0;
1206 if (BpGetWirelessAntInUse(&antInUse) == BP_SUCCESS) {
1207 if (ctrlParms.strLen == sizeof(antInUse)) {
1208 __copy_to_user(ctrlParms.string, &antInUse, sizeof(antInUse));
1209 ctrlParms.result = 0;
1210 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
1225 case BOARD_IOCTL_SET_TRIGGER_EVENT:
1226 if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
1227 BOARD_IOC *board_ioc = (BOARD_IOC *)flip->private_data;
1228 ctrlParms.result = -EFAULT;
1230 if (ctrlParms.strLen == sizeof(unsigned long)) {
1231 board_ioc->eventmask |= *((int*)ctrlParms.string);
1232 #if defined (WIRELESS)
1233 if((board_ioc->eventmask & SES_EVENTS)) {
1234 if(sesBtn_irq != BP_NOT_DEFINED) {
1235 BcmHalInterruptEnable(sesBtn_irq);
1236 ctrlParms.result = 0;
1241 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
1250 case BOARD_IOCTL_GET_TRIGGER_EVENT:
1251 if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
1252 BOARD_IOC *board_ioc = (BOARD_IOC *)flip->private_data;
1253 if (ctrlParms.strLen == sizeof(unsigned long)) {
1254 __copy_to_user(ctrlParms.string, &board_ioc->eventmask, sizeof(unsigned long));
1255 ctrlParms.result = 0;
1256 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
1268 case BOARD_IOCTL_UNSET_TRIGGER_EVENT:
1269 if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
1270 if (ctrlParms.strLen == sizeof(unsigned long)) {
1271 BOARD_IOC *board_ioc = (BOARD_IOC *)flip->private_data;
1272 board_ioc->eventmask &= (~(*((int*)ctrlParms.string)));
1273 ctrlParms.result = 0;
1274 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
1285 #if defined (WIRELESS)
1286 case BOARD_IOCTL_SET_SES_LED:
1287 if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
1288 if (ctrlParms.strLen == sizeof(int)) {
1289 sesLed_ctrl(*(int*)ctrlParms.string);
1290 ctrlParms.result = 0;
1291 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
1303 // USR9108 Wi-Fi Country selection
1304 case BOARD_IOCTL_GET_CNTRY_SEL:
1305 if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0)
1307 __copy_to_user(ctrlParms.string, g_pNvramInfo->chCountry, 4);
1308 ctrlParms.result = 0;
1310 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms,
1311 sizeof(BOARD_IOCTL_PARMS));
1318 case BOARD_IOCTL_SET_MONITOR_FD:
1319 if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
1320 int fput_needed = 0;
1322 g_monitor_file = fget_light( ctrlParms.offset, &fput_needed );
1323 if( g_monitor_file ) {
1324 /* Hook this file descriptor's poll function in order to set
1325 * the exception descriptor when there is a change in link
1328 g_monitor_task = current;
1329 g_orig_fop_poll = g_monitor_file->f_op->poll;
1330 g_monitor_file->f_op->poll = kerSysMonitorPollHook;
1335 case BOARD_IOCTL_WAKEUP_MONITOR_TASK:
1336 kerSysWakeupMonitorTask();
1341 ctrlParms.result = 0;
1342 printk("board_ioctl: invalid command %x, cmd %d .\n",command,_IOC_NR(command));
1351 /***************************************************************************
1352 * SES Button ISR/GPIO/LED functions.
1353 ***************************************************************************/
1354 #if defined (WIRELESS)
1355 static irqreturn_t sesBtn_isr(int irq, void *dev_id, struct pt_regs *ptregs)
1357 #if defined(_BCM96338_) || defined(CONFIG_BCM96338)
1358 unsigned long gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
1359 volatile unsigned long *gpio_reg = &GPIO->GPIOio;
1361 #if defined(_BCM96345_) || defined(CONFIG_BCM96345)
1362 unsigned short gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
1363 volatile unsigned short *gpio_reg = &GPIO->GPIOio;
1365 #if defined(_BCM96348_) || defined (CONFIG_BCM96348)
1366 unsigned long gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
1367 volatile unsigned long *gpio_reg = &GPIO->GPIOio;
1369 if( (sesBtn_gpio & ~BP_ACTIVE_MASK) >= 32 )
1371 gpio_mask = GPIO_NUM_TO_MASK_HIGH(sesBtn_gpio);
1372 gpio_reg = &GPIO->GPIOio_high;
1376 if (!(*gpio_reg & gpio_mask)){
1377 wake_up_interruptible(&g_board_wait_queue);
1378 return IRQ_RETVAL(1);
1380 return IRQ_RETVAL(0);
1384 static void __init sesBtn_mapGpio()
1386 if( BpGetWirelessSesBtnGpio(&sesBtn_gpio) == BP_SUCCESS )
1388 printk("SES: Button GPIO 0x%x is enabled\n", sesBtn_gpio);
1392 static void __init sesBtn_mapIntr(int context)
1394 if( BpGetWirelessSesExtIntr(&sesBtn_irq) == BP_SUCCESS )
1396 printk("SES: Button Interrupt 0x%x is enabled\n", sesBtn_irq);
1401 sesBtn_irq += INTERRUPT_ID_EXTERNAL_0;
1403 if (BcmHalMapInterrupt((FN_HANDLER)sesBtn_isr, context, sesBtn_irq)) {
1404 printk("SES: Interrupt mapping failed\n");
1406 BcmHalInterruptEnable(sesBtn_irq);
1410 static unsigned int sesBtn_poll(struct file *file, struct poll_table_struct *wait)
1412 #if defined(_BCM96338_) || defined(CONFIG_BCM96338)
1413 unsigned long gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
1414 volatile unsigned long *gpio_reg = &GPIO->GPIOio;
1416 #if defined(_BCM96345_) || defined(CONFIG_BCM96345)
1417 unsigned short gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
1418 volatile unsigned short *gpio_reg = &GPIO->GPIOio;
1420 #if defined(_BCM96348_) || defined (CONFIG_BCM96348)
1421 unsigned long gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
1422 volatile unsigned long *gpio_reg = &GPIO->GPIOio;
1424 if( (sesBtn_gpio & ~BP_ACTIVE_MASK) >= 32 )
1426 gpio_mask = GPIO_NUM_TO_MASK_HIGH(sesBtn_gpio);
1427 gpio_reg = &GPIO->GPIOio_high;
1431 if (!(*gpio_reg & gpio_mask)){
1437 static ssize_t sesBtn_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
1439 volatile unsigned int event=0;
1442 #if defined(_BCM96338_) || defined (CONFIG_BCM96338)
1443 unsigned long gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
1444 volatile unsigned long *gpio_reg = &GPIO->GPIOio;
1446 #if defined(_BCM96345_) || defined (CONFIG_BCM96345)
1447 unsigned short gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
1448 volatile unsigned short *gpio_reg = &GPIO->GPIOio;
1450 #if defined(_BCM96348_) || defined (CONFIG_BCM96348)
1451 unsigned long gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
1452 volatile unsigned long *gpio_reg = &GPIO->GPIOio;
1454 if( (sesBtn_gpio & ~BP_ACTIVE_MASK) >= 32 )
1456 gpio_mask = GPIO_NUM_TO_MASK_HIGH(sesBtn_gpio);
1457 gpio_reg = &GPIO->GPIOio_high;
1461 if(*gpio_reg & gpio_mask){
1462 BcmHalInterruptEnable(sesBtn_irq);
1466 __copy_to_user((char*)buffer, (char*)&event, sizeof(event));
1467 BcmHalInterruptEnable(sesBtn_irq);
1468 count -= sizeof(event);
1469 buffer += sizeof(event);
1470 ret += sizeof(event);
1474 static void __init sesLed_mapGpio()
1476 if( BpGetWirelessSesBtnGpio(&sesLed_gpio) == BP_SUCCESS )
1478 printk("SES: LED GPIO 0x%x is enabled\n", sesBtn_gpio);
1482 static void sesLed_ctrl(int action)
1485 //char status = ((action >> 8) & 0xff); /* extract status */
1486 //char event = ((action >> 16) & 0xff); /* extract event */
1487 //char blinktype = ((action >> 24) & 0xff); /* extract blink type for SES_LED_BLINK */
1489 BOARD_LED_STATE led;
1491 if(sesLed_gpio == BP_NOT_DEFINED)
1494 action &= 0xff; /* extract led */
1496 //printk("blinktype=%d, event=%d, status=%d\n",(int)blinktype, (int)event, (int)status);
1501 //printk("SES: led on\n");
1505 //printk("SES: led blink\n");
1506 led = kLedStateSlowBlinkContinues;
1510 //printk("SES: led off\n");
1514 kerSysLedCtrl(kLedSes, led);
1517 static void __init ses_board_init()
1523 static void __exit ses_board_deinit()
1526 BcmHalInterruptDisable(sesBtn_irq);
1530 /***************************************************************************
1531 * Dying gasp ISR and functions.
1532 ***************************************************************************/
1533 #define KERSYS_DBG printk
1535 #if defined(CONFIG_BCM96345)
1536 #define CYCLE_PER_US 70
1537 #elif defined(CONFIG_BCM96348) || defined(CONFIG_BCM96338)
1538 /* The BCM6348 cycles per microsecond is really variable since the BCM6348
1539 * MIPS speed can vary depending on the PLL settings. However, an appoximate
1540 * value of 120 will still work OK for the test being done.
1542 #define CYCLE_PER_US 120
1544 #define DG_GLITCH_TO (100*CYCLE_PER_US)
1546 static void __init kerSysDyingGaspMapIntr()
1548 unsigned long ulIntr;
1550 #if defined(CONFIG_BCM96348) || defined(_BCM96348_) || defined(CONFIG_BCM96338) || defined(_BCM96338_)
1551 if( BpGetAdslDyingGaspExtIntr( &ulIntr ) == BP_SUCCESS ) {
1552 BcmHalMapInterrupt((FN_HANDLER)kerSysDyingGaspIsr, 0, INTERRUPT_ID_DG);
1553 BcmHalInterruptEnable( INTERRUPT_ID_DG );
1555 #elif defined(CONFIG_BCM96345) || defined(_BCM96345_)
1556 if( BpGetAdslDyingGaspExtIntr( &ulIntr ) == BP_SUCCESS ) {
1557 ulIntr += INTERRUPT_ID_EXTERNAL_0;
1558 BcmHalMapInterrupt((FN_HANDLER)kerSysDyingGaspIsr, 0, ulIntr);
1559 BcmHalInterruptEnable( ulIntr );
1565 void kerSysSetWdTimer(ulong timeUs)
1567 TIMER->WatchDogDefCount = timeUs * (FPERIPH/1000000);
1568 TIMER->WatchDogCtl = 0xFF00;
1569 TIMER->WatchDogCtl = 0x00FF;
1572 ulong kerSysGetCycleCount(void)
1578 __asm volatile("mfc0 %0, $9":"=d"(cnt));
1583 static Bool kerSysDyingGaspCheckPowerLoss(void)
1589 clk0 = kerSysGetCycleCount();
1595 #if defined(CONFIG_BCM96345)
1596 BpGetAdslDyingGaspExtIntr( &ulIntr );
1601 clk1 = kerSysGetCycleCount(); /* time cleared */
1602 /* wait a little to get new reading */
1603 while ((kerSysGetCycleCount()-clk1) < CYCLE_PER_US*2)
1605 } while ((0 == (PERF->ExtIrqCfg & (1 << (ulIntr + EI_STATUS_SHFT)))) && ((kerSysGetCycleCount() - clk0) < DG_GLITCH_TO));
1607 if (PERF->ExtIrqCfg & (1 << (ulIntr + EI_STATUS_SHFT))) { /* power glitch */
1608 BcmHalInterruptEnable( ulIntr + INTERRUPT_ID_EXTERNAL_0);
1609 KERSYS_DBG(" - Power glitch detected. Duration: %ld us\n", (kerSysGetCycleCount() - clk0)/CYCLE_PER_US);
1612 #elif (defined(CONFIG_BCM96348) || defined(CONFIG_BCM96338)) && !defined(VXWORKS)
1616 clk1 = kerSysGetCycleCount(); /* time cleared */
1617 /* wait a little to get new reading */
1618 while ((kerSysGetCycleCount()-clk1) < CYCLE_PER_US*2)
1620 } while ((PERF->IrqStatus & (1 << (INTERRUPT_ID_DG - INTERNAL_ISR_TABLE_OFFSET))) && ((kerSysGetCycleCount() - clk0) < DG_GLITCH_TO));
1622 if (!(PERF->IrqStatus & (1 << (INTERRUPT_ID_DG - INTERNAL_ISR_TABLE_OFFSET)))) {
1623 BcmHalInterruptEnable( INTERRUPT_ID_DG );
1624 KERSYS_DBG(" - Power glitch detected. Duration: %ld us\n", (kerSysGetCycleCount() - clk0)/CYCLE_PER_US);
1631 static void kerSysDyingGaspShutdown( void )
1633 kerSysSetWdTimer(1000000);
1634 #if defined(CONFIG_BCM96345)
1635 PERF->blkEnables &= ~(EMAC_CLK_EN | USB_CLK_EN | CPU_CLK_EN);
1636 #elif defined(CONFIG_BCM96348)
1637 PERF->blkEnables &= ~(EMAC_CLK_EN | USBS_CLK_EN | USBH_CLK_EN | SAR_CLK_EN);
1641 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
1642 static irqreturn_t kerSysDyingGaspIsr(int irq, void * dev_id, struct pt_regs * regs)
1644 static unsigned int kerSysDyingGaspIsr(void)
1647 struct list_head *pos;
1648 CB_DGASP_LIST *tmp, *dsl = NULL;
1650 if (kerSysDyingGaspCheckPowerLoss()) {
1652 /* first to turn off everything other than dsl */
1653 list_for_each(pos, &g_cb_dgasp_list_head->list) {
1654 tmp = list_entry(pos, CB_DGASP_LIST, list);
1655 if(strncmp(tmp->name, "dsl", 3)) {
1656 (tmp->cb_dgasp_fn)(tmp->context);
1662 /* now send dgasp */
1664 (dsl->cb_dgasp_fn)(dsl->context);
1666 /* reset and shutdown system */
1667 kerSysDyingGaspShutdown();
1669 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
1670 return( IRQ_HANDLED );
1676 static void __init kerSysInitDyingGaspHandler( void )
1678 CB_DGASP_LIST *new_node;
1680 if( g_cb_dgasp_list_head != NULL) {
1681 printk("Error: kerSysInitDyingGaspHandler: list head is not null\n");
1684 new_node= (CB_DGASP_LIST *)kmalloc(sizeof(CB_DGASP_LIST), GFP_KERNEL);
1685 memset(new_node, 0x00, sizeof(CB_DGASP_LIST));
1686 INIT_LIST_HEAD(&new_node->list);
1687 g_cb_dgasp_list_head = new_node;
1689 } /* kerSysInitDyingGaspHandler */
1691 static void __exit kerSysDeinitDyingGaspHandler( void )
1693 struct list_head *pos;
1696 if(g_cb_dgasp_list_head == NULL)
1699 list_for_each(pos, &g_cb_dgasp_list_head->list) {
1700 tmp = list_entry(pos, CB_DGASP_LIST, list);
1705 kfree(g_cb_dgasp_list_head);
1706 g_cb_dgasp_list_head = NULL;
1708 } /* kerSysDeinitDyingGaspHandler */
1710 void kerSysRegisterDyingGaspHandler(char *devname, void *cbfn, void *context)
1712 CB_DGASP_LIST *new_node;
1714 if( g_cb_dgasp_list_head == NULL) {
1715 printk("Error: kerSysRegisterDyingGaspHandler: list head is null\n");
1719 if( devname == NULL || cbfn == NULL ) {
1720 printk("Error: kerSysRegisterDyingGaspHandler: register info not enough (%s,%x,%x)\n", devname, (unsigned int)cbfn, (unsigned int)context);
1724 new_node= (CB_DGASP_LIST *)kmalloc(sizeof(CB_DGASP_LIST), GFP_KERNEL);
1725 memset(new_node, 0x00, sizeof(CB_DGASP_LIST));
1726 INIT_LIST_HEAD(&new_node->list);
1727 strncpy(new_node->name, devname, IFNAMSIZ);
1728 new_node->cb_dgasp_fn = (cb_dgasp_t)cbfn;
1729 new_node->context = context;
1730 list_add(&new_node->list, &g_cb_dgasp_list_head->list);
1732 printk("dgasp: kerSysRegisterDyingGaspHandler: %s registered \n", devname);
1734 } /* kerSysRegisterDyingGaspHandler */
1736 void kerSysDeregisterDyingGaspHandler(char *devname)
1738 struct list_head *pos;
1741 if(g_cb_dgasp_list_head == NULL) {
1742 printk("Error: kerSysDeregisterDyingGaspHandler: list head is null\n");
1746 if(devname == NULL) {
1747 printk("Error: kerSysDeregisterDyingGaspHandler: devname is null\n");
1751 printk("kerSysDeregisterDyingGaspHandler: %s is deregistering\n", devname);
1753 list_for_each(pos, &g_cb_dgasp_list_head->list) {
1754 tmp = list_entry(pos, CB_DGASP_LIST, list);
1755 if(!strcmp(tmp->name, devname)) {
1758 printk("kerSysDeregisterDyingGaspHandler: %s is deregistered\n", devname);
1762 printk("kerSysDeregisterDyingGaspHandler: %s not (de)registered\n", devname);
1764 } /* kerSysDeregisterDyingGaspHandler */
1766 /***************************************************************************
1767 * MACRO to call driver initialization and cleanup functions.
1768 ***************************************************************************/
1769 module_init( brcm_board_init );
1770 module_exit( brcm_board_cleanup );
1772 EXPORT_SYMBOL(kerSysNvRamGet);
1773 EXPORT_SYMBOL(dumpaddr);
1774 EXPORT_SYMBOL(kerSysGetMacAddress);
1775 EXPORT_SYMBOL(kerSysReleaseMacAddress);
1776 EXPORT_SYMBOL(kerSysGetSdramSize);
1777 EXPORT_SYMBOL(kerSysLedCtrl);
1778 EXPORT_SYMBOL(kerSysLedRegisterHwHandler);
1779 EXPORT_SYMBOL(BpGetBoardIds);
1780 EXPORT_SYMBOL(BpGetSdramSize);
1781 EXPORT_SYMBOL(BpGetPsiSize);
1782 EXPORT_SYMBOL(BpGetEthernetMacInfo);
1783 EXPORT_SYMBOL(BpGetRj11InnerOuterPairGpios);
1784 EXPORT_SYMBOL(BpGetPressAndHoldResetGpio);
1785 EXPORT_SYMBOL(BpGetVoipResetGpio);
1786 EXPORT_SYMBOL(BpGetVoipIntrGpio);
1787 EXPORT_SYMBOL(BpGetPcmciaResetGpio);
1788 EXPORT_SYMBOL(BpGetRtsCtsUartGpios);
1789 EXPORT_SYMBOL(BpGetAdslLedGpio);
1790 EXPORT_SYMBOL(BpGetAdslFailLedGpio);
1791 EXPORT_SYMBOL(BpGetWirelessLedGpio);
1792 EXPORT_SYMBOL(BpGetUsbLedGpio);
1793 EXPORT_SYMBOL(BpGetHpnaLedGpio);
1794 EXPORT_SYMBOL(BpGetWanDataLedGpio);
1795 EXPORT_SYMBOL(BpGetPppLedGpio);
1796 EXPORT_SYMBOL(BpGetPppFailLedGpio);
1797 EXPORT_SYMBOL(BpGetVoipLedGpio);
1798 EXPORT_SYMBOL(BpGetWirelessExtIntr);
1799 EXPORT_SYMBOL(BpGetAdslDyingGaspExtIntr);
1800 EXPORT_SYMBOL(BpGetVoipExtIntr);
1801 EXPORT_SYMBOL(BpGetHpnaExtIntr);
1802 EXPORT_SYMBOL(BpGetHpnaChipSelect);
1803 EXPORT_SYMBOL(BpGetVoipChipSelect);
1804 EXPORT_SYMBOL(BpGetWirelessSesBtnGpio);
1805 EXPORT_SYMBOL(BpGetWirelessSesExtIntr);
1806 EXPORT_SYMBOL(BpGetWirelessSesLedGpio);
1807 EXPORT_SYMBOL(kerSysRegisterDyingGaspHandler);
1808 EXPORT_SYMBOL(kerSysDeregisterDyingGaspHandler);
1809 EXPORT_SYMBOL(kerSysGetCycleCount);
1810 EXPORT_SYMBOL(kerSysSetWdTimer);
1811 EXPORT_SYMBOL(kerSysWakeupMonitorTask);