Ejemplo n.º 1
0
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);

}
Ejemplo n.º 2
0
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);
	}
}
Ejemplo n.º 3
0
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;

}
Ejemplo n.º 4
0
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;

}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
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);
}
Ejemplo n.º 10
0
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);
}
Ejemplo n.º 12
0
/*
 * 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;
}
Ejemplo n.º 13
0
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;
}
Ejemplo n.º 14
0
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, &reg);
	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;
}