⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vsc73xx.c

📁 linux下atheros的ag7100驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/* vsc73xx.c  * May 24, 2007 Tag before BSP resturcture */ #ifdef __BDI#include "bdi.h"#else#ifdef __ECOS#if defined(CYGNUM_USE_ENET_VERBOSE)#   undef  VERBOSE#   define VERBOSE CYGNUM_USE_ENET_VERBOSE#else#   define VERBOSE 0#endif #define printk             DEBUG_PRINTF#define udelay             A_UDELAY#else#include <linux/kernel.h>#include <asm/delay.h>#include "ar7100.h"#endif#endif#ifndef VERBOSE#define  VERBOSE           0#endif#include "generic_spi.h"#include "vsc73xx.h"#define MODULE_NAME "VSC73XX"/* ************************************************************** */#define VSC73XX_SYSTEM            0x7#define VSC73XX_ICPU_CTRL         0x10#define VSC73XX_ICPU_ADDR         0x11#define VSC73XX_ICPU_SRAM         0x12#define VSC73XX_ICPU_MAILBOX_VAL  0x15#define VSC73XX_ICPU_MAILBOX_SET  0x16#define VSC73XX_ICPU_MAILBOX_CLR  0x17#define VSC73XX_ICPU_CHIPID       0x18#define VSC73XX_ICPU_SIPAD        0x01#define VSC73XX_ICPU_GPIO         0x34#define VSC73XX_ICPU_CLOCK_DELAY  0x05#define VSC73XX_MAC               0x1#define VSC73XX_MAC_CFG           0x0#define VSC73XX_ADVPORTM          0x19#define VSC73XX_RXOCT             0x50#define VSC73XX_TXOCT             0x51#define VSC73XX_C_RX0             0x52#define VSC73XX_C_RX1             0x53#define VSC73XX_C_RX2             0x54#define VSC73XX_C_TX0             0x55#define VSC73XX_C_TX1             0x56#define VSC73XX_C_TX2             0x57#define VSC73XX_C_CFG             0x58#define VSC73XX_MII               0x3#define VSC73XX_MII_STAT          0x0#define VSC73XX_MII_CMD           0x1#define VSC73XX_MII_DATA          0x2static void inlinevsc73xx_force_reset(void){  ar7100_reg_rmw_set(AR7100_RESET, AR7100_RESET_GE1_PHY);  udelay(10);  ar7100_reg_rmw_clear(AR7100_RESET, AR7100_RESET_GE1_PHY);}#ifdef USE_TEST_CODEvoidvsc73xx_test_reset_line(void){  printk(MODULE_NAME": looping 10 uSec nRESET, 100Usec RESET\n");  generic_spi_init(GENERIC_SPI_VSC73XX_CS);  do {    vsc73xx_force_reset();    udelay(100);  } while (1);}#endifstatic intvsc73xx_check_block_sublock_ok(int block, int sublock) {  switch (block) {  case 1:    switch (sublock) {    case 0: case 1: case 2: case 3: case 4: case 6:      return (0==0);    }    break;  case 2: case 7:    switch (sublock) {    case 0:       return (0==0);    }    break;  case 3: case 4: case 5:    switch (sublock) {    case 0: case 1:       return (0==0);    }    break;  }  return 0;}intvsc73xx_rd(int block, int subblock, int reg, unsigned int  *value){  int rc;  rc=vsc73xx_check_block_sublock_ok(block, subblock);  if (rc<0) {    printk(MODULE_NAME": non-supported block/subblock %d %d\n", block, subblock);    return -1;  }  rc=generic_spi_access_enable(GENERIC_SPI_VSC73XX_CS);  if (rc<0) {    printk(MODULE_NAME": unable to CS %08x \n", GENERIC_SPI_VSC73XX_CS);    return -1;  }    /* Send address */  generic_spi_raw_output_u8((block<<5) | (0/*READ*/<<4) | (subblock<<0));  generic_spi_raw_output_u8(reg);    /* Pad based on SiPAD register ( default 2) */  generic_spi_raw_output_u8(0);  generic_spi_raw_output_u8(0);  /* Clock 32b data into serial shift register */  *value = generic_spi_raw_input_u32();     rc=generic_spi_access_done();  if (rc<0) {    printk(MODULE_NAME": unable to deassert CS %08x \n", GENERIC_SPI_VSC73XX_CS);    return -1;  }  return 0;}intvsc73xx_wr(int block, int subblock, int reg, unsigned int  value){  int rc;  rc=vsc73xx_check_block_sublock_ok(block, subblock);  if (rc<0) {    printk(MODULE_NAME": non-supported block/subblock %d %d\n", block, subblock);    return -1;  }    rc=generic_spi_access_enable(GENERIC_SPI_VSC73XX_CS);  if (rc<0) {    printk(MODULE_NAME": unable to CS %08x \n", GENERIC_SPI_VSC73XX_CS);    return -1;  }	  /* Address */  generic_spi_raw_output_u8((block<<5) | (1/*WRITE*/<<4) | (subblock<<0) );  generic_spi_raw_output_u8(reg);  /* Data */  generic_spi_raw_output_u8((value>>24) & 0xff);  generic_spi_raw_output_u8((value>>16) & 0xff);  generic_spi_raw_output_u8((value>>8 ) & 0xff);  generic_spi_raw_output_u8((value>>0 ) & 0xff);    rc=generic_spi_access_done();  if (rc<0) {    printk(MODULE_NAME": unable to deassert CS  %08x \n", GENERIC_SPI_VSC73XX_CS);    return -1;  }       return 0;}static intvsc73xx_get_and_verify_chipid(void){  int curVal;  int chip;  int ii=256;  do {    vsc73xx_rd(VSC73XX_SYSTEM, 0, VSC73XX_ICPU_CHIPID, &curVal);    chip = (curVal >> 12)  & 0x0ffff;  } while ((chip != 0x7385) && (chip != 0x7395) && (chip != 0x7396) && --ii);#ifdef VSC73XX_DEBUG  printk(MODULE_NAME": curval = 0x%08x\n", curVal);#endif  if (0==ii) {    printk(MODULE_NAME": unknown chip: %08x\n", chip);    return -1;  }#ifdef CONFIG_AR9100  /*   * Per Martin Olsen [martino@vitesse.com],   * VSC7385YV chips with 0x0 in bits 31:28 of "Block 7 Subblock 0   * Address 0x18" is the first revision and that have a problem   * with the reset. This can be the reason why this doesn't work.   */  if (!((curVal >> 28) & 0xf)) {    printk("\n==================================================\n"           "WARNING:\n"           "Using revision 0 of chip 0x%x. It might not work!\n"           "==================================================\n", chip);  }#endif  return chip;}static intvsc73xx_reset_and_verify_chipid(void){  vsc73xx_force_reset();  return vsc73xx_get_and_verify_chipid();}#ifdef USE_TEST_CODEvoidvsc73xx_test_reset_and_verify_chipid(void){  printk(MODULE_NAME": looping on reset & verify chipid\n");  generic_spi_init(GENERIC_SPI_VSC73XX_CS);  do {    vsc73xx_reset_and_verify_chipid();  } while (1);}#endifstatic inline intvsc73xx_mailbox_get(unsigned int *d){  return vsc73xx_rd(VSC73XX_SYSTEM, 0, VSC73XX_ICPU_MAILBOX_VAL, d);}static inline intvsc73xx_mailbox_clr(unsigned int value){  return vsc73xx_wr(VSC73XX_SYSTEM, 0, VSC73XX_ICPU_MAILBOX_CLR, value);}static inline intvsc73xx_mailbox_set(unsigned int value){  return vsc73xx_wr(VSC73XX_SYSTEM, 0, VSC73XX_ICPU_MAILBOX_SET, value);}static inline int vsc73xx_gpio_config_output(int value){  return vsc73xx_wr(VSC73XX_SYSTEM, 0, VSC73XX_ICPU_GPIO, ( value & VSC73XX_GPIO_MASK ) << 4);}static inline intvsc73xx_gpio_output(int value){    unsigned int d;  int rc;  value &=VSC73XX_GPIO_MASK;    /* 1 = high 0=low  */  rc=vsc73xx_rd(VSC73XX_SYSTEM, 0, VSC73XX_ICPU_GPIO, &d);  if (rc<0)    return rc;  d &=VSC73XX_GPIO_MASK;  d |=value;  return vsc73xx_wr(VSC73XX_SYSTEM, 0, VSC73XX_ICPU_GPIO, d);}static inline int vsc73xx_gpio_input(unsigned int *d){  int rc;  unsigned int e;  rc=vsc73xx_rd(VSC73XX_SYSTEM, 0, VSC73XX_ICPU_GPIO, &e);  if (rc<0)    return rc;  *d = e & VSC73XX_GPIO_MASK;  return rc;}#ifdef USE_TEST_CODEvoidvsc73xx_test_gpio(void){  printk(MODULE_NAME": looping on / off vsc73xx GPIO\n");  generic_spi_init(GENERIC_SPI_VSC73XX_CS);  vsc73xx_gpio_config_output(VSC73XX_GPIO_2);  do {    vsc73xx_gpio_output(VSC73XX_GPIO_2);    udelay(50);    vsc73xx_gpio_output(0);    udelay(50);  } while (1);}#endifstatic intvsc73xx_get_sVersion_resetNeeded(int *sVersion, int *resetNeeded){  unsigned int d;  int rc;  rc=vsc73xx_mailbox_get(&d);  if (rc<0)    return rc;  *sVersion    = d & 0xffff;  *resetNeeded = (d & 0xffff0000) == 0xffff0000;  return 0;}static inline int vsc73xx_restart_firmware(void){  int rc;  rc = vsc73xx_wr(		  VSC73XX_SYSTEM, 0, VSC73XX_ICPU_CTRL,		  (1<<7) |          /* SOFT_RST_HOLD = 1 */		  (1<<3) |          /* BOOT_EN       = 1 */		  (1<<2) |          /* EXT_ACC_EN    = 1 */		  (0<<0)            /* SOFT_RST      = 0 */		  );  if (rc<0)    return rc;    rc = vsc73xx_wr(				  VSC73XX_SYSTEM, 0,VSC73XX_ICPU_ADDR,		  0x0000		  );  if (rc<0)    return rc;    udelay(100);    rc = vsc73xx_wr(		  VSC73XX_SYSTEM, 0, VSC73XX_ICPU_CTRL,		  (1<<8) |          /* CLK_DIV  = 1 */		  (1<<3) |          /* BOOT_EN  = 1 */		  (1<<1) |          /* CLK_EN   = 1 */		  (1<<0)            /* SOFT_RST = 1 */		  );  return rc;}static intvsc73xx_load_firmware_raw(unsigned char *lutonuAddr, int lutonuSize) {  int            ii;  unsigned char  *dp;  unsigned int   curVal;  int            diffs;  int            rc;    rc = vsc73xx_wr(		  VSC73XX_SYSTEM, 0, VSC73XX_ICPU_CTRL,		  (1<<7) |          /* SOFT_RST_HOLD = 1 */		  (1<<3) |          /* BOOT_EN       = 1 */		  (1<<2) |          /* EXT_ACC_EN    = 1 */		  (0<<0)            /* SOFT_RST      = 0 */		  );  if (rc<0)    return rc;    rc = vsc73xx_wr(				  VSC73XX_SYSTEM, 0,VSC73XX_ICPU_ADDR,		  0x0000		  );  if (rc<0)    return rc;    dp = lutonuAddr;  for (ii=0; ii<lutonuSize; ii++) {    rc = vsc73xx_wr(		    VSC73XX_SYSTEM, 0, VSC73XX_ICPU_SRAM,		    *dp++ 		    );    if (rc<0) {      printk(MODULE_NAME": could not load microcode %d\n",rc);      return rc;    }  }  rc = vsc73xx_wr(				  VSC73XX_SYSTEM, 0, VSC73XX_ICPU_ADDR,		  0x0000		  );  if (rc<0) {    printk(MODULE_NAME": could not reset microcode %d\n",rc);    return rc;  }  printk(MODULE_NAME": microcode Loaded, verifying...\n");    dp = lutonuAddr;  diffs=0;  for (ii=0; ii<lutonuSize; ii++) {    rc = vsc73xx_rd(		    VSC73XX_SYSTEM, 0,VSC73XX_ICPU_SRAM, 		    &curVal		    );    if (rc<0) {      printk(MODULE_NAME": could not read microcode %d\n",rc);      return rc;    }        if (curVal > 0xff) {      printk(MODULE_NAME": bad val read: %04x : %02x  %02x  \n", ii, *dp, curVal);      return -1;    }         if ((curVal & 0xff) != *dp) {      diffs++;      printk(MODULE_NAME": verify error: %04x : %02x  %02x  \n", ii, *dp, curVal);            if (diffs > 4)	break;    }     dp++;  }    if (diffs) {    printk(MODULE_NAME": failed to verify\n");    return -1;  }  printk(MODULE_NAME": verify OK\n");    rc = vsc73xx_wr(		  VSC73XX_SYSTEM, 0, VSC73XX_ICPU_CTRL,		  (1<<8) |          /* CLK_DIV  = 1 */		  (1<<3) |          /* BOOT_EN  = 1 */		  (1<<1) |          /* CLK_EN   = 1 */		  (1<<0)            /* SOFT_RST = 1 */		  );  return rc;}#define VSC73XX_SFTW_VERSION            0x229#include "g5_Plus1_2_29b_unmanaged_Atheros_v5.c"#include "g5e_Plus1_2_29a_unmanaged_Atheros_v3.c"#include "g5_Plus1_2_29a_unmanaged_Atheros_v5.c"static intvsc73xx_load_firmware(void) {  int sVersion;  int resetNeeded;  int rc;  rc = vsc73xx_reset_and_verify_chipid();  if (rc < 0) {    printk(MODULE_NAME": could not identify chip, err %d\n", rc);    return rc;  }  printk(MODULE_NAME": found chip id: %04x\n", rc);#if defined(__BDI) && defined(VSC73XX_LOAD_FROM_RAM)  rc = vsc73xx_load_firmware_raw(get_scratch_uncached(8192), 8192);#else  switch (rc) {  case 0x00007385:  #ifndef CONFIG_AR9100    rc = vsc73xx_load_firmware_raw(g5_Plus1_2_29b_unmanaged_Atheros_v5, 				   sizeof(g5_Plus1_2_29b_unmanaged_Atheros_v5));#else    rc = vsc73xx_load_firmware_raw(g5_Plus1_2_29b_unmanaged_Atheros_v5,                                   sizeof(g5_Plus1_2_29b_unmanaged_Atheros_v5));#endif    break;  case 0x00007395:    /* source from vitesse uses symbol lutonu, later versions use the name of the file.  */    rc = vsc73xx_load_firmware_raw(lutonu,       /* g5e_Plus1_2_29a_unmanaged_Atheros_v3 */				   sizeof(lutonu /* g5e_Plus1_2_29a_unmanaged_Atheros_v3 */));    break;      default:    printk(MODULE_NAME": microcode not availale for chip id: %08x\n", rc);    rc = -1;  }#endif  if (rc<0)    return rc;  vsc73xx_get_sVersion_resetNeeded(&sVersion, &resetNeeded);  if (resetNeeded) {    printk(MODULE_NAME": failed to start\n");    return -1;  }  if (sVersion < VSC73XX_SFTW_VERSION) {    printk(MODULE_NAME": incorrect software version %04x\n", sVersion);    return -1;  }  printk(MODULE_NAME": software version %08x started OK\n",sVersion);  return 0;}#ifdef USE_TEST_CODEvoidvsc73xx_test_load_and_reset_firmware(void){  int rc;  printk(MODULE_NAME": looping on load firmware / reset firmware\n");  generic_spi_init(GENERIC_SPI_VSC73XX_CS);  do {    printk(MODULE_NAME": return from load firmware: %d\n", vsc73xx_load_firmware());

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -