void program_prevent_C3Exit(mic_ctx_t *mic_ctx, bool set) { sbox_pcu_ctrl_t ctrl_regval; ctrl_regval.value = pm_reg_read(mic_ctx,SBOX_PCU_CONTROL); ctrl_regval.bits.prevent_auto_c3_exit = (set ? 1: 0); pm_reg_write(ctrl_regval.value, mic_ctx, SBOX_PCU_CONTROL); }
void program_mclk_shutdown(mic_ctx_t *mic_ctx, bool set) { sbox_uos_pcu_ctrl_t uos_ctrl_regval; sbox_pcu_ctrl_t ctrl_regval; if(KNC_A_STEP == mic_ctx->bi_stepping) { ctrl_regval.value = pm_reg_read(mic_ctx,SBOX_PCU_CONTROL); ctrl_regval.bits.enable_mclk_pl_shutdown = (set ? 1: 0); pm_reg_write(ctrl_regval.value, mic_ctx, SBOX_PCU_CONTROL); } else { uos_ctrl_regval.value = pm_reg_read(mic_ctx, SBOX_UOS_PCUCONTROL); uos_ctrl_regval.bits.enable_mclk_pll_shutdown = (set ? 1: 0); pm_reg_write(uos_ctrl_regval.value, mic_ctx, SBOX_UOS_PCUCONTROL); } }
PM_IDLE_STATE get_card_state(mic_ctx_t *mic_ctx) { PM_IDLE_STATE state; sbox_uos_pm_state_t upmstate_regval = {0}; upmstate_regval.value = pm_reg_read(mic_ctx, SBOX_UOS_PMSTATE); state = (PM_IDLE_STATE)(upmstate_regval.bits.uos_pm_state); return state; }
PM_IDLE_STATE get_host_state(mic_ctx_t *mic_ctx) { PM_IDLE_STATE state; sbox_host_pm_state_t hpmstate_regval = {0}; hpmstate_regval.value = pm_reg_read(mic_ctx, SBOX_HOST_PMSTATE); state = (PM_IDLE_STATE)(hpmstate_regval.bits.host_pm_state); return state; }
int set_host_state(mic_ctx_t *mic_ctx, PM_IDLE_STATE state) { int err = 0; sbox_host_pm_state_t hpmstate_regval = {0}; hpmstate_regval.value = pm_reg_read(mic_ctx, SBOX_HOST_PMSTATE); hpmstate_regval.bits.host_pm_state = 0; hpmstate_regval.bits.host_pm_state = state; pm_reg_write(hpmstate_regval.value, mic_ctx, SBOX_HOST_PMSTATE); return err; }
void restore_pc6_registers(mic_ctx_t *mic_ctx, bool from_dpc3) { sbox_pcu_ctrl_t ctrl_regval = {0}; sbox_uos_pcu_ctrl_t uos_ctrl_regval = {0}; gbox_pm_control pmctrl_reg = {0}; sbox_core_freq_t core_freq_reg = {0}; if (!from_dpc3) { if(KNC_A_STEP == mic_ctx->bi_stepping) { ctrl_regval.value = pm_reg_read(mic_ctx, SBOX_PCU_CONTROL); ctrl_regval.bits.enable_mclk_pl_shutdown = 0; pm_reg_write(ctrl_regval.value, mic_ctx, SBOX_PCU_CONTROL); } else { uos_ctrl_regval.value = pm_reg_read(mic_ctx,SBOX_UOS_PCUCONTROL); uos_ctrl_regval.bits.enable_mclk_pll_shutdown = 0; pm_reg_write(uos_ctrl_regval.value, mic_ctx, SBOX_UOS_PCUCONTROL); } ctrl_regval.value = pm_reg_read(mic_ctx, SBOX_PCU_CONTROL); ctrl_regval.bits.prevent_auto_c3_exit = 0; pm_reg_write(ctrl_regval.value, mic_ctx, SBOX_PCU_CONTROL); } pmctrl_reg.value = pm_reg_read(mic_ctx, GBOX_PM_CTRL); pmctrl_reg.bits.in_pckgc6 = 0; pm_reg_write(pmctrl_reg.value, mic_ctx, GBOX_PM_CTRL); ctrl_regval.value = pm_reg_read(mic_ctx, SBOX_PCU_CONTROL); ctrl_regval.bits.grpB_pwrgood_mask = 0; pm_reg_write(ctrl_regval.value, mic_ctx, SBOX_PCU_CONTROL); core_freq_reg.value = pm_reg_read(mic_ctx, SBOX_COREFREQ); core_freq_reg.bits.booted = 1; pm_reg_write(core_freq_reg.value, mic_ctx, SBOX_COREFREQ); }
static bool is_hw_strobe(struct pm8941_flash_data *data) { u8 val; int rc; rc = pm_reg_read(data, STROBE_CONTROL, &val); if (rc) { pm8941_dev_err(data, "reg read failed(%d)\n", rc); return false; } val &= STROBE_SELECT_HW; return val ? true : false; }
static ssize_t pm8941_get_reg_common(struct device *ldev, u16 offset, struct device_attribute *attr, char *buf) { struct pm8941_flash_data *data = dev_get_drvdata(ldev); u8 val; int rc; rc = pm_reg_read(data, offset, &val); if (rc) { pm8941_dev_err(data, "reg read failed(%d)\n", rc); return rc; } return scnprintf(buf, PAGE_SIZE, "%d\n", val); }
static ssize_t pm8941_get_strobe(struct device *ldev, struct device_attribute *attr, char *buf) { struct pm8941_flash_data *data = dev_get_drvdata(ldev); u8 val; int rc; rc = pm_reg_read(data, STROBE_CONTROL, &val); if (rc) { pm8941_dev_err(data, "reg read failed(%d)\n", rc); return rc; } val &= STROBE_SELECT_HW; val >>= 2; return scnprintf(buf, PAGE_SIZE, "%d\n", val); }
int hw_active(mic_ctx_t *mic_ctx) { uint8_t is_ring_active; sbox_pcu_ctrl_t ctrl_regval; uint32_t idle_wait_cnt; for(idle_wait_cnt = 0; idle_wait_cnt <= MAX_HW_IDLE_WAIT_COUNT; idle_wait_cnt++) { ctrl_regval.value = pm_reg_read(mic_ctx,SBOX_PCU_CONTROL); is_ring_active = ctrl_regval.bits.mclk_enabled; if (likely(is_ring_active)) return is_ring_active; msleep(10); } PM_DEBUG("Timing out waiting for HW to become active\n"); return is_ring_active; }
static ssize_t pm8941_get_mode(struct device *ldev, struct device_attribute *attr, char *buf) { struct pm8941_flash_data *data = dev_get_drvdata(ldev); unsigned long mode; u8 val; int rc; rc = pm_reg_read(data, ENABLE_CONTROL, &val); if (rc) { pm8941_dev_err(data, "reg read failed(%d)\n", rc); return rc; } if (val & MODULE_ENABLE) mode = (val & CURR_MAX_1A) ? FLASH_MODE_FLASH : FLASH_MODE_TORCH; else mode = FLASH_MODE_NONE; return scnprintf(buf, PAGE_SIZE, "%lu\n", mode); }
/* * pm_pc6_exit: * * Execute pc6 exit for a node. * mic_ctx: The driver context of the node. */ int pm_pc6_exit(mic_ctx_t *mic_ctx) { int err = 0; sbox_host_pm_state_t hpmstate_regval; sbox_pcu_ctrl_t ctrl_regval; uint8_t tdp_vid = 0; uint8_t is_pll_locked; uint32_t wait_cnt; int i; if (!check_host_state(mic_ctx, PM_IDLE_STATE_PC6)) { PM_DEBUG("Wrong Host PM state. State = %d\n", get_host_state(mic_ctx)); err = -EINVAL; goto restore_registers; } hpmstate_regval.value = pm_reg_read(mic_ctx, SBOX_HOST_PMSTATE); tdp_vid = hpmstate_regval.bits.tdp_vid; PM_DEBUG("TDP_VID value obtained from Host PM Register = %d",tdp_vid); PM_DEBUG("Setting voltage to %dV using SVID Control\n",tdp_vid); err = set_vid_knc(mic_ctx, tdp_vid); if (err != 0) { printk(KERN_ERR "%s Failed PC6 entry...error in setting VID\n", __func__); goto restore_registers; } ctrl_regval.value = pm_reg_read(mic_ctx, SBOX_PCU_CONTROL); program_mclk_shutdown(mic_ctx, false); program_prevent_C3Exit(mic_ctx, false); for(wait_cnt = 0; wait_cnt < 200; wait_cnt++) { ctrl_regval.value = pm_reg_read(mic_ctx,SBOX_PCU_CONTROL); is_pll_locked = ctrl_regval.bits.mclk_pll_lock; if(likely(is_pll_locked)) break; msleep(10); } if(wait_cnt >= 200) { PM_DEBUG("mclk_pll_locked bit is not set.\n"); err = -EAGAIN; goto restore_registers; } ctrl_regval.bits.grpB_pwrgood_mask = 0; pm_reg_write(ctrl_regval.value, mic_ctx, SBOX_PCU_CONTROL); if (!hw_active(mic_ctx)) { PM_DEBUG("Timing out waiting for hw to become active"); goto restore_registers; } for(wait_cnt = 0; wait_cnt < 200; wait_cnt++) { if ((get_card_state(mic_ctx)) == PM_IDLE_STATE_PC0) break; msleep(10); } if(wait_cnt >= 200) { PM_DEBUG("PC6 Exit not complete.\n"); err = -EFAULT; goto restore_registers; } mic_ctx->micpm_ctx.idle_state = PM_IDLE_STATE_PC0; for (i = 0; i <= mic_data.dd_numdevs; i++) { if (micscif_get_nodedep(mic_get_scifnode_id(mic_ctx), i) == DEP_STATE_DISCONNECTED) { micscif_set_nodedep(mic_get_scifnode_id(mic_ctx), i, DEP_STATE_DEPENDENT); } } PM_PRINT("Node %d exited PC6\n", mic_get_scifnode_id(mic_ctx)); goto exit; restore_registers: restore_pc6_registers(mic_ctx, false); exit: atomic_set(&mic_ctx->gate_interrupt, 0); tasklet_schedule(&mic_ctx->bi_dpc); return err; }
int pm_pc3_to_pc6_entry(mic_ctx_t *mic_ctx) { int err; sbox_pcu_ctrl_t ctrl_regval; gbox_pm_control pmctrl_reg; sbox_core_freq_t core_freq_reg; if ((get_card_state(mic_ctx)) != PM_IDLE_STATE_PC3) { PM_DEBUG("Card not ready to go to PC6. \n"); err = -EAGAIN; goto exit; } if (atomic_cmpxchg(&mic_ctx->gate_interrupt, 0, 1) == 1) { PM_DEBUG("Cannot gate interrupt handler while it is in use\n"); err = -EFAULT; goto exit; } program_prevent_C3Exit(mic_ctx, true); program_mclk_shutdown(mic_ctx, true); /* Wait for uos to become idle. */ if (!hw_idle(mic_ctx)) { program_mclk_shutdown(mic_ctx, false); if (!hw_idle(mic_ctx)) { program_prevent_C3Exit(mic_ctx, false); PM_DEBUG("Card not ready to go to PC6. \n"); err = -EAGAIN; goto intr_ungate; } else { program_mclk_shutdown(mic_ctx, true); } } pmctrl_reg.value = pm_reg_read(mic_ctx, GBOX_PM_CTRL); pmctrl_reg.bits.in_pckgc6 = 1; pm_reg_write(pmctrl_reg.value, mic_ctx, GBOX_PM_CTRL); core_freq_reg.value = pm_reg_read(mic_ctx, SBOX_COREFREQ); core_freq_reg.bits.booted = 0; pm_reg_write(core_freq_reg.value, mic_ctx, SBOX_COREFREQ); udelay(500); ctrl_regval.value = pm_reg_read(mic_ctx, SBOX_PCU_CONTROL); ctrl_regval.bits.grpB_pwrgood_mask = 1; pm_reg_write(ctrl_regval.value, mic_ctx, SBOX_PCU_CONTROL); err = set_vid_knc(mic_ctx, 0); if (err != 0) { PM_DEBUG("Aborting PC6 entry...Failed to set VID\n"); restore_pc6_registers(mic_ctx, true); goto intr_ungate; } mic_ctx->micpm_ctx.idle_state = PM_IDLE_STATE_PC6; set_host_state(mic_ctx, PM_IDLE_STATE_PC6); dma_prep_suspend(mic_ctx->dma_handle); PM_PRINT("Node %d entered PC6\n", mic_get_scifnode_id(mic_ctx)); return err; intr_ungate: atomic_set(&mic_ctx->gate_interrupt, 0); tasklet_schedule(&mic_ctx->bi_dpc); exit: return err; }
int set_vid_knc(mic_ctx_t *mic_ctx, unsigned int vidcode) { uint32_t status = 0; sbox_svid_control svidctrl_regval = {0}; uint32_t svid_idle = 0; uint32_t svid_error = 0; int i = 0; uint32_t wait_cnt = 0; sbox_core_volt_t core_volt_regval = {0}; int retry = 0; if (mic_ctx->bi_stepping >= KNC_B0_STEP) { for (retry = 0; retry < SET_VID_RETRY_COUNT; retry++) { status = 0; for (i = 0; i < KNC_SETVID_ATTEMPTS; i++) { svidctrl_regval.value = pm_reg_read(mic_ctx,SBOX_SVID_CONTROL); svid_idle = svidctrl_regval.bits.svid_idle; if (svid_idle) { set_vid(mic_ctx, svidctrl_regval, vidcode); svidctrl_regval.value = pm_reg_read(mic_ctx,SBOX_SVID_CONTROL); svid_idle = svidctrl_regval.bits.svid_idle; svid_error = svidctrl_regval.bits.svid_error; if (!svid_idle) { printk(KERN_ERR "%s SVID command failed - Idle not set\n", __func__); msleep(10); continue; } if (svid_error) { if (SBOX_SVIDCTRL_ACK1ACK0(svidctrl_regval.value) == 0x2) { printk(KERN_ERR "%s SVID command failed - rx parity error\n", __func__); } else { printk(KERN_ERR "%s SVID command failed - tx parity error\n", __func__); } status = -EINVAL; goto exit; } else { PM_DEBUG("SVID Command Successful - VID set to %d\n",vidcode); break; } } } if (i == KNC_SETVID_ATTEMPTS) { printk(KERN_ERR "%s Timed out waiting for SVID idle\n", __func__); status = -EINVAL; goto exit; } /* Verify that the voltage is set */ for(wait_cnt = 0; wait_cnt <= 100; wait_cnt++) { core_volt_regval.value = pm_reg_read(mic_ctx, SBOX_COREVOLT); if(vidcode == core_volt_regval.bits.vid) { return status; } msleep(10); PM_DEBUG("Retry: %d Voltage not set yet. vidcode = 0x%x Current vid = 0x%x\n", retry, vidcode, core_volt_regval.bits.vid); } PM_PRINT("Retry: %d Failed to set vid for node %d. vid code = 0x%x Current vid = 0x%x.\n", retry, mic_get_scifnode_id(mic_ctx), vidcode, core_volt_regval.bits.vid); status = -ENODEV; } } else { set_vid(mic_ctx, svidctrl_regval, vidcode); /* SBOX_COREVOLT does not reflect the correct vid * value on A0. Just wait here for sometime to * allow for the vid to be set. */ msleep(20); } exit: return status; }
static int __devinit pm8941_flash_initialize(struct pm8941_flash_data *data) { int rc; u8 reg; /* Set strobe */ reg = DISABLE_CURRENT_OUT | data->flash_cfg.hw_strobe_config; rc = pm_reg_write(data, STROBE_CONTROL, reg); if (rc) { pm8941_dev_err(data, "Strobe write failed(%d)\n", rc); return rc; } /* Safety timer */ rc = pm_reg_read(data, SAFETY_TIMER, ®); if (rc) { pm8941_dev_err(data, "Safety timer read failed(%d)\n", rc); return rc; } data->turn_off_delay_ms = ++reg * 10; /* Set clamp current */ rc = pm_reg_write(data, CLAMP_CURRENT, data->flash_cfg.clamp_curr); if (rc) { pm8941_dev_err(data, "Clamp reg write failed(%d)\n", rc); return rc; } /* Set headroom */ rc = pm_reg_write(data, HEADROOM, data->flash_cfg.headroom); if (rc) { pm8941_dev_err(data, "Headroom reg write failed(%d)\n", rc); return rc; } /* Set mask enable */ rc = pm_reg_write(data, MASK_ENABLE, data->flash_cfg.mask_enable << 5); if (rc) { pm8941_dev_err(data, "Mask enable reg write failed(%d)\n", rc); return rc; } /* Set startup delay */ rc = pm_reg_write(data, STARTUP_DELAY, data->flash_cfg.startup_dly); if (rc) { pm8941_dev_err(data, "Start delay reg write failed(%d)\n", rc); return rc; } /* Set VPH_PWR_DROOP */ reg = data->flash_cfg.vph_pwr_droop.enable << 7 | data->flash_cfg.vph_pwr_droop.threshold << 4 | data->flash_cfg.vph_pwr_droop.debounce_time; rc = pm_reg_write(data, VPH_PWR_DROOP, reg); if (rc) { pm8941_dev_err(data, "Start delay reg write failed(%d)\n", rc); return rc; } /* Set current */ rc = rc ? rc : pm_reg_write(data, LED1_CURRENT, 0xA); if (rc) { pm8941_dev_err(data, "current1 reg write failed(%d)\n", rc); return rc; } rc = rc ? rc : pm_reg_write(data, LED2_CURRENT, 0xA); if (rc) { pm8941_dev_err(data, "current2 reg write failed(%d)\n", rc); return rc; } /* Set enable module */ rc = pm_reg_write(data, ENABLE_CONTROL, MODULE_DISABLE | CURR_MAX_200mA); if (rc) { pm8941_dev_err(data, "Enable module failed(%d)\n", rc); return rc; } /* Disable watchdog timer */ rc = rc ? rc : pm_reg_write(data, SEC_ACCESS, ENABLE_SEC_ACCESS); rc = rc ? rc : pm_reg_write(data, TEST3_TIMER, TEST3_ENABLE_FLASH_TIMER | TEST3_DISABLE_WATCHDOG_TIMER); rc = rc ? rc : pm_reg_write(data, SEC_ACCESS, DISABLE_SEC_ACCESS); if (rc) { pm8941_dev_err(data, "Disable watchdog failed(%d)\n", rc); return rc; } return 0; }