static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl) { u16 spare_reg; int ret; /* Mask bits [2] & [8:4] in the sys_clk_cfg register */ ret = wl1271_top_reg_read(wl, WL_SPARE_REG, &spare_reg); if (ret < 0) return ret; if (spare_reg == 0xFFFF) return -EFAULT; spare_reg |= (BIT(3) | BIT(5) | BIT(6)); ret = wl1271_top_reg_write(wl, WL_SPARE_REG, spare_reg); if (ret < 0) return ret; /* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */ ret = wl1271_top_reg_write(wl, SYS_CLK_CFG_REG, WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF); if (ret < 0) return ret; /* Delay execution for 15msec, to let the HW settle */ mdelay(15); return 0; }
static int wl128x_manually_configure_mcs_pll(struct wl1271 *wl) { int ret; ret = wl1271_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL); if (ret < 0) goto out; ret = wl1271_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL); if (ret < 0) goto out; ret = wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG, MCS_PLL_CONFIG_REG_VAL); out: return ret; }
static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) { u16 spare_reg; u16 pll_config; u8 input_freq; int ret; /* Mask bits [3:1] in the sys_clk_cfg register */ ret = wl1271_top_reg_read(wl, WL_SPARE_REG, &spare_reg); if (ret < 0) return ret; if (spare_reg == 0xFFFF) return -EFAULT; spare_reg |= BIT(2); ret = wl1271_top_reg_write(wl, WL_SPARE_REG, spare_reg); if (ret < 0) return ret; /* Handle special cases of the TCXO clock */ if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_8 || wl->tcxo_clock == WL12XX_TCXOCLOCK_33_6) return wl128x_manually_configure_mcs_pll(wl); /* Set the input frequency according to the selected clock source */ input_freq = (clk & 1) + 1; ret = wl1271_top_reg_read(wl, MCS_PLL_CONFIG_REG, &pll_config); if (ret < 0) return ret; if (pll_config == 0xFFFF) return -EFAULT; pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT); pll_config |= MCS_PLL_ENABLE_HP; ret = wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG, pll_config); return ret; }
static int wl1271_boot_write_irq_polarity(struct wl1271 *wl) { u32 polarity; polarity = wl1271_top_reg_read(wl, OCP_REG_POLARITY); /* We use HIGH polarity, so unset the LOW bit */ polarity &= ~POLARITY_LOW; wl1271_top_reg_write(wl, OCP_REG_POLARITY, polarity); return 0; }
static int wl1271_boot_write_irq_polarity(struct wl1271 *wl) { u16 polarity; int ret; ret = wl1271_top_reg_read(wl, OCP_REG_POLARITY, &polarity); if (ret < 0) return ret; /* We use HIGH polarity, so unset the LOW bit */ polarity &= ~POLARITY_LOW; ret = wl1271_top_reg_write(wl, OCP_REG_POLARITY, polarity); return ret; }
/* uploads NVS and firmware */ int wl1271_load_firmware(struct wl1271 *wl) { int ret = 0; u32 tmp, clk; int selected_clock = -1; ret = wl12xx_init_pll_clock(wl, &selected_clock); if (ret < 0) goto out; ret = wl1271_set_partition(wl, &wl12xx_part_table[PART_DRPW]); if (ret < 0) goto out; /* Read-modify-write DRPW_SCRATCH_START register (see next state) to be used by DRPw FW. The RTRIM value will be added by the FW before taking DRPw out of reset */ wl1271_debug(DEBUG_BOOT, "DRPW_SCRATCH_START %08x", DRPW_SCRATCH_START); ret = wl1271_read32(wl, DRPW_SCRATCH_START, &clk); if (ret < 0) goto out; wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); if (wl->chip.id == CHIP_ID_1283_PG20) { clk |= ((selected_clock & 0x3) << 1) << 4; } else { clk |= (wl->ref_clock << 1) << 4; } ret = wl1271_write32(wl, DRPW_SCRATCH_START, clk); if (ret < 0) goto out; ret = wl1271_set_partition(wl, &wl12xx_part_table[PART_WORK]); if (ret < 0) goto out; /* Disable interrupts */ ret = wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); if (ret < 0) goto out; ret = wl1271_boot_soft_reset(wl); if (ret < 0) goto out; /* 2. start processing NVS file */ ret = wl1271_boot_upload_nvs(wl); if (ret < 0) goto out; /* write firmware's last address (ie. it's length) to * ACX_EEPROMLESS_IND_REG */ wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG"); ret = wl1271_write32(wl, ACX_EEPROMLESS_IND_REG, ACX_EEPROMLESS_IND_REG); if (ret < 0) goto out; ret = wl1271_read32(wl, CHIP_ID_B, &tmp); if (ret < 0) goto out; wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); /* 6. read the EEPROM parameters */ ret = wl1271_read32(wl, SCR_PAD2, &tmp); if (ret < 0) goto out; /* WL1271: The reference driver skips steps 7 to 10 (jumps directly * to upload_fw) */ if (wl->chip.id == CHIP_ID_1283_PG20) { ret = wl1271_top_reg_write(wl, SDIO_IO_DS, wl->conf.hci_io_ds); if (ret < 0) goto out; } ret = wl1271_boot_upload_firmware(wl); if (ret < 0) goto out; /* update loaded fw type */ wl->fw_type = wl->saved_fw_type; out: return ret; }
int wl127x_boot_clk(struct wl1271 *wl) { u32 pause; u32 clk; int ret; if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3) wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION; if (wl->ref_clock == CONF_REF_CLK_19_2_E || wl->ref_clock == CONF_REF_CLK_38_4_E || wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL) /* ref clk: 19.2/38.4/38.4-XTAL */ clk = 0x3; else if (wl->ref_clock == CONF_REF_CLK_26_E || wl->ref_clock == CONF_REF_CLK_52_E) /* ref clk: 26/52 */ clk = 0x5; else return -EINVAL; if (wl->ref_clock != CONF_REF_CLK_19_2_E) { u16 val; /* Set clock type (open drain) */ ret = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE, &val); if (ret < 0) return ret; val &= FREF_CLK_TYPE_BITS; ret = wl1271_top_reg_write(wl, OCP_REG_CLK_TYPE, val); if (ret < 0) return ret; /* Set clock pull mode (no pull) */ ret = wl1271_top_reg_read(wl, OCP_REG_CLK_PULL, &val); if (ret < 0) return ret; val |= NO_PULL; ret = wl1271_top_reg_write(wl, OCP_REG_CLK_PULL, val); if (ret < 0) return ret; } else { u16 val; /* Set clock polarity */ ret = wl1271_top_reg_read(wl, OCP_REG_CLK_POLARITY, &val); if (ret < 0) return ret; val &= FREF_CLK_POLARITY_BITS; val |= CLK_REQ_OUTN_SEL; ret = wl1271_top_reg_write(wl, OCP_REG_CLK_POLARITY, val); if (ret < 0) return ret; } ret = wl1271_write32(wl, PLL_PARAMETERS, clk); if (ret < 0) goto out; ret = wl1271_read32(wl, PLL_PARAMETERS, &pause); if (ret < 0) goto out; wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); pause &= ~(WU_COUNTER_PAUSE_VAL); pause |= WU_COUNTER_PAUSE_VAL; ret = wl1271_write32(wl, WU_COUNTER_PAUSE, pause); out: return ret; }
int wl1271_boot(struct wl1271 *wl) { int ret = 0; u32 tmp, clk, pause; if (REF_CLOCK == 0 || REF_CLOCK == 2 || REF_CLOCK == 4) /* ref clk: 19.2/38.4/38.4-XTAL */ clk = 0x3; else if (REF_CLOCK == 1 || REF_CLOCK == 3) /* ref clk: 26/52 */ clk = 0x5; if (REF_CLOCK != 0) { u16 val; /* Set clock type */ val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); val &= FREF_CLK_TYPE_BITS; val |= CLK_REQ_PRCM; wl1271_top_reg_write(wl, OCP_REG_CLK_TYPE, val); } else { u16 val; /* Set clock polarity */ val = wl1271_top_reg_read(wl, OCP_REG_CLK_POLARITY); val &= FREF_CLK_POLARITY_BITS; val |= CLK_REQ_OUTN_SEL; wl1271_top_reg_write(wl, OCP_REG_CLK_POLARITY, val); } wl1271_spi_write32(wl, PLL_PARAMETERS, clk); pause = wl1271_spi_read32(wl, PLL_PARAMETERS); wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); pause &= ~(WU_COUNTER_PAUSE_VAL); /* FIXME: This should probably be * WU_COUNTER_PAUSE_VAL instead of * 0x3ff (magic number ). How does * this work?! */ pause |= WU_COUNTER_PAUSE_VAL; wl1271_spi_write32(wl, WU_COUNTER_PAUSE, pause); /* Continue the ELP wake up sequence */ wl1271_spi_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); udelay(500); wl1271_set_partition(wl, &part_table[PART_DRPW]); /* Read-modify-write DRPW_SCRATCH_START register (see next state) to be used by DRPw FW. The RTRIM value will be added by the FW before taking DRPw out of reset */ wl1271_debug(DEBUG_BOOT, "DRPW_SCRATCH_START %08x", DRPW_SCRATCH_START); clk = wl1271_spi_read32(wl, DRPW_SCRATCH_START); wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); /* 2 */ clk |= (REF_CLOCK << 1) << 4; wl1271_spi_write32(wl, DRPW_SCRATCH_START, clk); wl1271_set_partition(wl, &part_table[PART_WORK]); /* Disable interrupts */ wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); ret = wl1271_boot_soft_reset(wl); if (ret < 0) goto out; /* 2. start processing NVS file */ ret = wl1271_boot_upload_nvs(wl); if (ret < 0) goto out; /* write firmware's last address (ie. it's length) to * ACX_EEPROMLESS_IND_REG */ wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG"); wl1271_spi_write32(wl, ACX_EEPROMLESS_IND_REG, ACX_EEPROMLESS_IND_REG); tmp = wl1271_spi_read32(wl, CHIP_ID_B); wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); /* 6. read the EEPROM parameters */ tmp = wl1271_spi_read32(wl, SCR_PAD2); ret = wl1271_boot_write_irq_polarity(wl); if (ret < 0) goto out; /* FIXME: Need to check whether this is really what we want */ wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_ALL_EVENTS_VECTOR); /* WL1271: The reference driver skips steps 7 to 10 (jumps directly * to upload_fw) */ ret = wl1271_boot_upload_firmware(wl); if (ret < 0) goto out; /* 10.5 start firmware */ ret = wl1271_boot_run_firmware(wl); if (ret < 0) goto out; /* Enable firmware interrupts now */ wl1271_boot_enable_interrupts(wl); /* set the wl1271 default filters */ wl->rx_config = WL1271_DEFAULT_RX_CONFIG; wl->rx_filter = WL1271_DEFAULT_RX_FILTER; wl1271_event_mbox_config(wl); out: return ret; }