/** * @fn spi_flash_rdid * @brief Read SPI Flash ID * @return SPI FLash ID */ static uint32 spi_flash_rdid(void) { unsigned char cmd[1]; uint32 reg = 0; uint32 cnt = 0; sint8 ret = M2M_SUCCESS; cmd[0] = 0x9f; ret += nm_write_reg(SPI_FLASH_DATA_CNT, 4); ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]); ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x1); ret += nm_write_reg(SPI_FLASH_DMA_ADDR, DUMMY_REGISTER); ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1<<7)); do { ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)®); if(M2M_SUCCESS != ret) break; if(++cnt > 500) { ret = M2M_ERR_INIT; break; } } while(reg != 1); reg = (M2M_SUCCESS == ret)?(nm_read_reg(DUMMY_REGISTER)):(0); M2M_PRINT("Flash ID %x \n",(unsigned int)reg); return reg; }
sint8 hif_chip_sleep(void) { sint8 ret = M2M_SUCCESS; if(gu8ChipSleep >= 1) { gu8ChipSleep--; } if(gu8ChipSleep == 0) { if((gu8ChipMode == M2M_PS_DEEP_AUTOMATIC)||(gu8ChipMode == M2M_PS_MANUAL)) { uint32 reg = 0; ret = nm_write_reg(WAKE_REG, SLEEP_VALUE); if(ret != M2M_SUCCESS)goto ERR1; /* Clear bit 1 */ ret = nm_read_reg_with_ret(0x1, ®); if(ret != M2M_SUCCESS)goto ERR1; if(reg&0x2) { reg &=~(1 << 1); ret = nm_write_reg(0x1, reg); } } else { } } ERR1: return ret; }
static sint8 spi_flash_probe(uint32 * u32FlashId) { sint8 ret = M2M_SUCCESS; uint32 pin_mux_0; uint32 orig_pin_mux_0; uint32 flashid; pin_mux_0 = nm_read_reg(0x1408); orig_pin_mux_0 = pin_mux_0; if( (orig_pin_mux_0 & 0xffff000) != 0x1111000) { /* Select PINMUX to use SPI MASTER */ pin_mux_0 &= ~0xffff000; pin_mux_0 |= 0x1111000; nm_write_reg(0x1408, pin_mux_0); } flashid = spi_flash_rdid(); if( (orig_pin_mux_0 & 0xffff000) != 0x1111000) { nm_write_reg(0x1408, orig_pin_mux_0); } *u32FlashId = flashid; return ret; }
/** * @fn spi_flash_enable * @brief Enable spi flash operations */ sint8 spi_flash_enable(uint8 enable) { sint8 s8Ret = M2M_SUCCESS; if(REV(nmi_get_chipid()) >= REV_3A0) { uint32 u32Val; /* Enable pinmux to SPI flash. */ s8Ret = nm_read_reg_with_ret(0x1410, &u32Val); if(s8Ret != M2M_SUCCESS) { goto ERR1; } /* GPIO15/16/17/18 */ u32Val &= ~((0x7777ul) << 12); u32Val |= ((0x1111ul) << 12); nm_write_reg(0x1410, u32Val); if(enable) { spi_flash_leave_low_power_mode(); } else { spi_flash_enter_low_power_mode(); } /* Disable pinmux to SPI flash to minimize leakage. */ u32Val &= ~((0x7777ul) << 12); u32Val |= ((0x0010ul) << 12); nm_write_reg(0x1410, u32Val); } ERR1: return s8Ret; }
sint8 enable_interrupts(void) { uint32 reg; sint8 ret; /** interrupt pin mux select **/ ret = nm_read_reg_with_ret(NMI_PIN_MUX_0, ®); if (M2M_SUCCESS != ret) { return M2M_ERR_BUS_FAIL; } reg |= ((uint32) 1 << 8); ret = nm_write_reg(NMI_PIN_MUX_0, reg); if (M2M_SUCCESS != ret) { return M2M_ERR_BUS_FAIL; } /** interrupt enable **/ ret = nm_read_reg_with_ret(NMI_INTR_ENABLE, ®); if (M2M_SUCCESS != ret) { return M2M_ERR_BUS_FAIL; } reg |= ((uint32) 1 << 16); ret = nm_write_reg(NMI_INTR_ENABLE, reg); if (M2M_SUCCESS != ret) { return M2M_ERR_BUS_FAIL; } return M2M_SUCCESS; }
/** * @fn spi_flash_page_program * @brief Write data (less than page size) from cortus memory to SPI flash * @param[IN] u32MemAdr * Cortus data address. It must be set to its AHB access address * @param[IN] u32FlashAdr * Address to write to at the SPI flash * @param[IN] u32Sz * Data size */ static sint8 spi_flash_page_program(uint32 u32MemAdr, uint32 u32FlashAdr, uint32 u32Sz) { uint8 cmd[4]; uint32 val = 0; sint8 ret = M2M_SUCCESS; cmd[0] = 0x02; cmd[1] = (uint8)(u32FlashAdr >> 16); cmd[2] = (uint8)(u32FlashAdr >> 8); cmd[3] = (uint8)(u32FlashAdr); ret += nm_write_reg(SPI_FLASH_DATA_CNT, 0); ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]|(cmd[1]<<8)|(cmd[2]<<16)|(cmd[3]<<24)); ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x0f); ret += nm_write_reg(SPI_FLASH_DMA_ADDR, u32MemAdr); ret += nm_write_reg(SPI_FLASH_CMD_CNT, 4 | (1<<7) | ((u32Sz & 0xfffff) << 8)); do { ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val); if(M2M_SUCCESS != ret) break; } while(val != 1); return ret; }
sint8 wait_for_bootrom(uint8 arg) { sint8 ret = M2M_SUCCESS; uint32 reg = 0, cnt = 0; reg = 0; while(1) { reg = nm_read_reg(0x1014); /* wait for efuse loading done */ if (reg & 0x80000000) { break; } nm_bsp_sleep(1); /* TODO: Why bus error if this delay is not here. */ } reg = nm_read_reg(M2M_WAIT_FOR_HOST_REG); reg &= 0x1; /* check if waiting for the host will be skipped or not */ if(reg == 0) { reg = 0; while(reg != M2M_FINISH_BOOT_ROM) { nm_bsp_sleep(1); reg = nm_read_reg(BOOTROM_REG); if(++cnt > TIMEOUT) { M2M_DBG("failed to load firmware from flash.\n"); ret = M2M_ERR_INIT; goto ERR2; } } } if(2 == arg) { nm_write_reg(NMI_REV_REG, M2M_ATE_FW_START_VALUE); } else { /*bypass this step*/ } if(REV(nmi_get_chipid()) == REV_3A0) { chip_apply_conf(rHAVE_USE_PMU_BIT); } else { chip_apply_conf(0); } nm_write_reg(BOOTROM_REG,M2M_START_FIRMWARE); #ifdef __ROM_TEST__ rom_test(); #endif /* __ROM_TEST__ */ ERR2: return ret; }
void nmi_update_pll(void) { uint32 pll; pll = nm_read_reg(0x1428); pll &= ~0x1ul; nm_write_reg(0x1428, pll); pll |= 0x1ul; nm_write_reg(0x1428, pll); }
static void spi_flash_leave_low_power_mode(void) { volatile unsigned long tmp; unsigned char* cmd = (unsigned char*) &tmp; cmd[0] = 0xab; nm_write_reg(SPI_FLASH_DATA_CNT, 0); nm_write_reg(SPI_FLASH_BUF1, cmd[0]); nm_write_reg(SPI_FLASH_BUF_DIR, 0x1); nm_write_reg(SPI_FLASH_DMA_ADDR, 0); nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1 << 7)); while(nm_read_reg(SPI_FLASH_TR_DONE) != 1); }
static void chip_apply_conf(void) { sint8 ret = M2M_SUCCESS; uint32 val32; val32 = 0; #ifdef __ENABLE_PMU__ val32 |= rHAVE_USE_PMU_BIT; #endif #ifdef __ENABLE_SLEEP_CLK_SRC_RTC__ val32 |= rHAVE_SLEEP_CLK_SRC_RTC; #elif defined __ENABLE_SLEEP_CLK_SRC_XO__ val32 |= rHAVE_SLEEP_CLK_SRC_XO; #endif #ifdef __ENABLE_EXT_PA_INV_TX_RX__ val32 |= rHAVE_EXT_PA_INV_TX_RX; #endif #ifdef __ENABLE_LEGACY_RF_SETTINGS__ val32 |= rHAVE_LEGACY_RF_SETTINGS; #endif do { nm_write_reg(rNMI_GP_REG_1, val32); if(val32 != 0) { uint32 reg = 0; ret = nm_read_reg_with_ret(rNMI_GP_REG_1, ®); if(ret == M2M_SUCCESS) { if(reg == val32) break; } } else { break; } } while(1); }
sint8 wait_for_firmware_start(uint8 arg) { sint8 ret = M2M_SUCCESS; uint32 reg = 0, cnt = 0; volatile uint32 regAddress = NMI_STATE_REG; volatile uint32 checkValue = M2M_FINISH_INIT_STATE; if(2 == arg) { regAddress = NMI_REV_REG; checkValue = M2M_ATE_FW_IS_UP_VALUE; } else { /*bypass this step*/ } while (checkValue != reg) { nm_bsp_sleep(2); /* TODO: Why bus error if this delay is not here. */ M2M_DBG("%x %x %x\n",(unsigned int)nm_read_reg(0x108c),(unsigned int)nm_read_reg(0x108c),(unsigned int)nm_read_reg(0x14A0)); reg = nm_read_reg(regAddress); if(++cnt > TIMEOUT) { M2M_DBG("Time out for wait firmware Run\n"); ret = M2M_ERR_INIT; goto ERR; } } if(M2M_FINISH_INIT_STATE == checkValue) { nm_write_reg(NMI_STATE_REG, 0); } ERR: return ret; }
static uint32 spi_flash_rdid(void) { unsigned char cmd[1]; uint32 reg; cmd[0] = 0x9f; nm_write_reg(SPI_FLASH_DATA_CNT, 4); nm_write_reg(SPI_FLASH_BUF1, cmd[0]); nm_write_reg(SPI_FLASH_BUF_DIR, 0x1); nm_write_reg(SPI_FLASH_DMA_ADDR, DUMMY_REGISTER); nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1<<7)); while(nm_read_reg(SPI_FLASH_TR_DONE) != 1); reg = nm_read_reg(DUMMY_REGISTER); M2M_PRINT("Flash id %x \n",reg); return reg; }
sint8 cpu_start(void) { uint32 reg; sint8 ret; /** reset regs */ nm_write_reg(BOOTROM_REG,0); nm_write_reg(NMI_STATE_REG,0); nm_write_reg(NMI_REV_REG,0); /** Go... **/ ret = nm_read_reg_with_ret(0x1118, ®); if (M2M_SUCCESS != ret) { ret = M2M_ERR_BUS_FAIL; M2M_ERR("[nmi start]: fail read reg 0x1118 ...\n"); } reg |= (1 << 0); ret = nm_write_reg(0x1118, reg); ret = nm_write_reg(0x150014, 0x1); ret += nm_read_reg_with_ret(NMI_GLB_RESET_0, ®); if ((reg & (1ul << 10)) == (1ul << 10)) { reg &= ~(1ul << 10); ret += nm_write_reg(NMI_GLB_RESET_0, reg); } reg |= (1ul << 10); ret += nm_write_reg(NMI_GLB_RESET_0, reg); nm_bsp_sleep(1); /* TODO: Why bus error if this delay is not here. */ return ret; }
sint8 chip_reset_and_cpu_halt(void) { sint8 ret = M2M_SUCCESS; uint32 reg = 0; ret = chip_wake(); if(ret != M2M_SUCCESS) { return ret; } chip_reset(); ret = nm_read_reg_with_ret(0x1118, ®); if (M2M_SUCCESS != ret) { ret = M2M_ERR_BUS_FAIL; M2M_ERR("[nmi start]: fail read reg 0x1118 ...\n"); } reg |= (1 << 0); ret = nm_write_reg(0x1118, reg); ret += nm_read_reg_with_ret(NMI_GLB_RESET_0, ®); if ((reg & (1ul << 10)) == (1ul << 10)) { reg &= ~(1ul << 10); ret += nm_write_reg(NMI_GLB_RESET_0, reg); ret += nm_read_reg_with_ret(NMI_GLB_RESET_0, ®); } #if 0 reg |= (1ul << 10); ret += nm_write_reg(NMI_GLB_RESET_0, reg); ret += nm_read_reg_with_ret(NMI_GLB_RESET_0, ®); #endif nm_write_reg(BOOTROM_REG,0); nm_write_reg(NMI_STATE_REG,0); nm_write_reg(NMI_REV_REG,0); nm_write_reg(NMI_PIN_MUX_0, 0x11111000); return ret; }
void rom_test() { uint8 *pu8TextSec; FILE *fp; uint32 u32CodeSize = 0; nm_bsp_sleep(1000); /* Read text section. */ fp = fopen(ROM_FIRMWARE_FILE,"rb"); if(fp) { /* Get the code size. */ fseek(fp, 0L, SEEK_END); u32CodeSize = ftell(fp); fseek(fp, 0L, SEEK_SET); pu8TextSec = (uint8*)malloc(u32CodeSize); if(pu8TextSec != NULL) { M2M_INFO("Code Size %f\n",u32CodeSize / 1024.0); fread(pu8TextSec, u32CodeSize, 1, fp); nm_write_block(CODE_BASE, pu8TextSec, (uint16)u32CodeSize); //nm_read_block(CODE_BASE, tmpv, sz); fclose(fp); free(pu8TextSec); } } #if 0 uint8 *pu8DataSec; uint32 u32DataSize = 0; /* Read data section. */ fp = fopen(ROM_DATA_FILE,"rb"); if(fp) { /* Get the data size. */ fseek(fp, 0L, SEEK_END); u32DataSize = ftell(fp); fseek(fp, 0L, SEEK_SET); pu8DataSec = (uint8*)malloc(u32DataSize); if(pu8DataSec != NULL) { M2M_INFO("Data Size %f\n",u32DataSize / 1024.0); fread(pu8DataSec, u32DataSize, 1, fp); nm_write_block(DATA_BASE, pu8DataSec, (uint16)u32DataSize); fclose(fp); } free(pu8DataSec); } #endif nm_write_reg(0x108c, 0xdddd); }
void chip_idle(void) { uint32 reg =0; nm_read_reg_with_ret(0x1, ®); if(reg&0x2) { reg &=~(1 << 1); nm_write_reg(0x1, reg); } }
void restore_pmu_settings_after_global_reset(void) { /* * Must restore PMU register value after * global reset if PMU toggle is done at * least once since the last hard reset. */ if(REV(nmi_get_chipid()) >= REV_2B0) { nm_write_reg(0x1e48, 0xb78469ce); } }
sint8 chip_deinit(void) { uint32 reg = 0; sint8 ret; uint8 timeout = 10; /** stop the firmware, need a re-download **/ ret = nm_read_reg_with_ret(NMI_GLB_RESET_0, ®); if (ret != M2M_SUCCESS) { M2M_ERR("failed to de-initialize\n"); } reg &= ~(1 << 10); ret = nm_write_reg(NMI_GLB_RESET_0, reg); if (ret != M2M_SUCCESS) { M2M_ERR("Error while writing reg\n"); return ret; } do { ret = nm_read_reg_with_ret(NMI_GLB_RESET_0, ®); if (ret != M2M_SUCCESS) { M2M_ERR("Error while reading reg\n"); return ret; } /*Workaround to ensure that the chip is actually reset*/ if ((reg & (1 << 10))) { M2M_DBG("Bit 10 not reset retry %d\n", timeout); reg &= ~(1 << 10); ret = nm_write_reg(NMI_GLB_RESET_0, reg); timeout--; } else { break; } } while (timeout); return ret; }
void nmi_set_sys_clk_src_to_xo(void) { uint32 val32; /* Switch system clock source to XO. This will take effect after nmi_update_pll(). */ val32 = nm_read_reg(0x141c); val32 |= (1 << 2); nm_write_reg(0x141c, val32); /* Do PLL update */ nmi_update_pll(); }
/** * @fn spi_flash_write_disable * @brief Send write disable command to SPI flash */ static sint8 spi_flash_write_disable(void) { uint8 cmd[1]; uint32 val = 0; sint8 ret = M2M_SUCCESS; cmd[0] = 0x04; ret += nm_write_reg(SPI_FLASH_DATA_CNT, 0); ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]); ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x01); ret += nm_write_reg(SPI_FLASH_DMA_ADDR, 0); ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1<<7)); do { ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val); if(M2M_SUCCESS != ret) break; } while(val != 1); return ret; }
/** * @fn spi_flash_load_to_cortus_mem * @brief Load data from SPI flash into cortus memory * @param[IN] u32MemAdr * Cortus load address. It must be set to its AHB access address * @param[IN] u32FlashAdr * Address to read from at the SPI flash * @param[IN] u32Sz * Data size * @return Status of execution */ static sint8 spi_flash_load_to_cortus_mem(uint32 u32MemAdr, uint32 u32FlashAdr, uint32 u32Sz) { uint8 cmd[5]; uint32 val = 0; sint8 ret = M2M_SUCCESS; cmd[0] = 0x0b; cmd[1] = (uint8)(u32FlashAdr >> 16); cmd[2] = (uint8)(u32FlashAdr >> 8); cmd[3] = (uint8)(u32FlashAdr); cmd[4] = 0xA5; ret += nm_write_reg(SPI_FLASH_DATA_CNT, u32Sz); ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]|(cmd[1]<<8)|(cmd[2]<<16)|(cmd[3]<<24)); ret += nm_write_reg(SPI_FLASH_BUF2, cmd[4]); ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x1f); ret += nm_write_reg(SPI_FLASH_DMA_ADDR, u32MemAdr); ret += nm_write_reg(SPI_FLASH_CMD_CNT, 5 | (1<<7)); do { ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val); if(M2M_SUCCESS != ret) break; } while(val != 1); return ret; }
sint8 chip_reset(void) { sint8 ret = M2M_SUCCESS; #ifndef CONF_WINC_USE_UART nmi_set_sys_clk_src_to_xo(); #endif ret += nm_write_reg(NMI_GLB_RESET_0, 0); nm_bsp_sleep(50); #ifndef CONF_WINC_USE_UART restore_pmu_settings_after_global_reset(); #endif return ret; }
/** * @fn spi_flash_read_security_reg * @brief Read security register * @return Security register value */ static uint8 spi_flash_read_security_reg(void) { uint8 cmd[1]; uint32 reg; sint8 ret = M2M_SUCCESS; cmd[0] = 0x2b; ret += nm_write_reg(SPI_FLASH_DATA_CNT, 1); ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]); ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x01); ret += nm_write_reg(SPI_FLASH_DMA_ADDR, DUMMY_REGISTER); ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1<<7)); do { ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)®); if(M2M_SUCCESS != ret) break; } while(reg != 1); reg = (M2M_SUCCESS == ret)?(nm_read_reg(DUMMY_REGISTER)):(0); return (sint8)reg & 0xff; }
/** * @fn spi_flash_read_status_reg * @brief Read status register * @param[OUT] val value of status reg * @return Status of execution */ static sint8 spi_flash_read_status_reg(uint8 * val) { sint8 ret = M2M_SUCCESS; uint8 cmd[1]; uint32 reg; cmd[0] = 0x05; ret += nm_write_reg(SPI_FLASH_DATA_CNT, 4); ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]); ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x01); ret += nm_write_reg(SPI_FLASH_DMA_ADDR, DUMMY_REGISTER); ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1<<7)); do { ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)®); if(M2M_SUCCESS != ret) break; } while(reg != 1); reg = (M2M_SUCCESS == ret)?(nm_read_reg(DUMMY_REGISTER)):(0); *val = (uint8)(reg & 0xff); return ret; }
void enable_rf_blocks(void) { nm_write_reg(0x6, 0xdb); nm_write_reg(0x7, 0x6); nm_bsp_sleep(10); nm_write_reg(0x1480, 0); nm_write_reg(0x1484, 0); nm_bsp_sleep(10); nm_write_reg(0x6, 0x0); nm_write_reg(0x7, 0x0); }
sint8 chip_reset(void) { sint8 ret = M2M_SUCCESS; #if 0 // MERGEBUG: TODO: This causes serial trace from the chip to be garbled - investigate #ifndef CONF_WINC_USE_UART nmi_set_sys_clk_src_to_xo(); #endif #endif ret += nm_write_reg(NMI_GLB_RESET_0, 0); nm_bsp_sleep(50); #ifndef CONF_WINC_USE_UART restore_pmu_settings_after_global_reset(); #endif return ret; }
sint8 set_gpio_val(uint8 gpio, uint8 val) { uint32 val32; sint8 ret; ret = nm_read_reg_with_ret(0x20100, &val32); if(ret != M2M_SUCCESS) goto _EXIT; if(val) { val32 |= (1ul << gpio); } else { val32 &= ~(1ul << gpio); } ret = nm_write_reg(0x20100, val32); _EXIT: return ret; }
sint8 hif_chip_wake(void) { sint8 ret = M2M_SUCCESS; if(gu8ChipSleep == 0) { if((gu8ChipMode == M2M_PS_DEEP_AUTOMATIC)||(gu8ChipMode == M2M_PS_MANUAL)) { ret = nm_clkless_wake(); if(ret != M2M_SUCCESS)goto ERR1; ret = nm_write_reg(WAKE_REG, WAKE_VALUE); if(ret != M2M_SUCCESS)goto ERR1; } else { } } gu8ChipSleep++; ERR1: return ret; }
static sint8 hif_set_rx_done(void) { uint32 reg; sint8 ret = M2M_SUCCESS; gstrHifCxt.u8HifRXDone = 0; #ifdef NM_EDGE_INTERRUPT nm_bsp_interrupt_ctrl(1); #endif ret = nm_read_reg_with_ret(WIFI_HOST_RCV_CTRL_0,®); if(ret != M2M_SUCCESS)goto ERR1; /* Set RX Done */ reg |= NBIT1; ret = nm_write_reg(WIFI_HOST_RCV_CTRL_0,reg); if(ret != M2M_SUCCESS)goto ERR1; #ifdef NM_LEVEL_INTERRUPT nm_bsp_interrupt_ctrl(1); #endif ERR1: return ret; }
sint8 pullup_ctrl(uint32 pinmask, uint8 enable) { sint8 s8Ret; uint32 val32; s8Ret = nm_read_reg_with_ret(0x142c, &val32); if(s8Ret != M2M_SUCCESS) { M2M_ERR("[pullup_ctrl]: failed to read\n"); goto _EXIT; } if(enable) { val32 &= ~pinmask; } else { val32 |= pinmask; } s8Ret = nm_write_reg(0x142c, val32); if(s8Ret != M2M_SUCCESS) { M2M_ERR("[pullup_ctrl]: failed to write\n"); goto _EXIT; } _EXIT: return s8Ret; }