コード例 #1
0
static int footswitch_disable(struct regulator_dev *rdev)
{
	struct footswitch *fs = rdev_get_drvdata(rdev);
	uint32_t regval, rc = 0;

	/* Make sure required clocks are on at the correct rates. */
	rc = setup_clocks(fs);
	if (rc)
		goto out;

	/* Halt all bus ports in the power domain. */
	if (fs->bus_port1) {
		rc = msm_bus_axi_porthalt(fs->bus_port1);
		if (rc) {
			pr_err("%s: Port 1 halt failed.\n", __func__);
			goto out;
		}
	}
	if (fs->bus_port2) {
		rc = msm_bus_axi_porthalt(fs->bus_port2);
		if (rc) {
			pr_err("%s: Port 1 halt failed.\n", __func__);
			goto err_port2_halt;
		}
	}

	/* Assert resets for all clocks in the clock domain so that
	 * outputs settle prior to clamping. */
	if (fs->axi_clk)
		clk_reset(fs->axi_clk, CLK_RESET_ASSERT);
	clk_reset(fs->ahb_clk, CLK_RESET_ASSERT);
	clk_reset(fs->core_clk, CLK_RESET_ASSERT);
	/* Wait for synchronous resets to propagate. */
	udelay(RESET_DELAY_US);

	/* Clamp the I/O ports of the core to ensure the values
	 * remain fixed while the core is collapsed. */
	regval = readl(fs->gfs_ctl_reg);
	regval |= CLAMP_BIT;
	writel(regval, fs->gfs_ctl_reg);

	/* Collapse the power rail at the footswitch. */
	regval &= ~ENABLE_BIT;
	writel(regval, fs->gfs_ctl_reg);

	/* Return clocks to their state before this function. */
	restore_clocks(fs);

	fs->is_enabled = 0;

	return rc;

err_port2_halt:
	msm_bus_axi_portunhalt(fs->bus_port1);
out:
	return rc;
}
コード例 #2
0
ファイル: pil-q6v4.c プロジェクト: 0987363/BMW-OpenSource
static int pil_q6v4_reset_trusted(struct pil_desc *pil)
{
	const struct pil_q6v4_pdata *pdata = pil->dev->platform_data;
	int err;

	err = pil_q6v4_power_up(pil->dev);
	if (err)
		return err;

	/* Unhalt bus port */
	err = msm_bus_axi_portunhalt(pdata->bus_port);
	if (err)
		dev_err(pil->dev, "Failed to unhalt bus port\n");
	return pas_auth_and_reset(pdata->pas_id);
}
コード例 #3
0
int mercury_core_reset(void)
{
	struct clk *clk = NULL;

	/*Resettting MMSS Fabric*/

	clk = clk_get(NULL, "jpegd_clk");

	if (!IS_ERR(clk))
		clk_enable(clk);

	msm_bus_axi_porthalt(MSM_BUS_MASTER_JPEG_DEC);
	clk_reset(clk, CLK_RESET_ASSERT);

	/*need to have some delay here, there is no
	 other way to know if hardware reset is complete*/
	usleep_range(1000, 1200);

	msm_bus_axi_portunhalt(MSM_BUS_MASTER_JPEG_DEC);
	clk_reset(clk, CLK_RESET_DEASSERT);

	return 0;
}
コード例 #4
0
static int gfx2d_footswitch_enable(struct regulator_dev *rdev)
{
	struct footswitch *fs = rdev_get_drvdata(rdev);
	struct fs_clk_data *clock;
	uint32_t regval, rc = 0;

	mutex_lock(&claim_lock);
	fs->is_claimed = true;
	mutex_unlock(&claim_lock);

	/* Return early if already enabled. */
	regval = readl_relaxed(fs->gfs_ctl_reg);
	if ((regval & (ENABLE_BIT | CLAMP_BIT)) == ENABLE_BIT)
		return 0;

	/* Make sure required clocks are on at the correct rates. */
	rc = setup_clocks(fs);
	if (rc)
		return rc;

	/* Un-halt all bus ports in the power domain. */
	if (fs->bus_port0) {
		rc = msm_bus_axi_portunhalt(fs->bus_port0);
		if (rc) {
			pr_err("%s port 0 unhalt failed.\n", fs->desc.name);
			goto err;
		}
	}

	/* Disable core clock. */
	clk_disable_unprepare(fs->core_clk);

	/*
	 * (Re-)Assert resets for all clocks in the clock domain, since
	 * footswitch_enable() is first called before footswitch_disable()
	 * and resets should be asserted before power is restored.
	 */
	for (clock = fs->clk_data; clock->clk; clock++)
		; /* Do nothing */
	for (clock--; clock >= fs->clk_data; clock--)
		clk_reset(clock->clk, CLK_RESET_ASSERT);
	/* Wait for synchronous resets to propagate. */
	udelay(RESET_DELAY_US);

	/* Enable the power rail at the footswitch. */
	regval |= ENABLE_BIT;
	writel_relaxed(regval, fs->gfs_ctl_reg);
	mb();
	udelay(1);

	/* Un-clamp the I/O ports. */
	regval &= ~CLAMP_BIT;
	writel_relaxed(regval, fs->gfs_ctl_reg);

	/* Deassert resets for all clocks in the power domain. */
	for (clock = fs->clk_data; clock->clk; clock++)
		clk_reset(clock->clk, CLK_RESET_DEASSERT);
	udelay(RESET_DELAY_US);

	/* Re-enable core clock. */
	clk_prepare_enable(fs->core_clk);

	/* Prevent core memory from collapsing when its clock is gated. */
	clk_set_flags(fs->core_clk, CLKFLAG_RETAIN);

	/* Return clocks to their state before this function. */
	restore_clocks(fs);

	fs->is_enabled = true;
	return 0;

err:
	restore_clocks(fs);
	return rc;
}
コード例 #5
0
static int footswitch_disable(struct regulator_dev *rdev)
{
	struct footswitch *fs = rdev_get_drvdata(rdev);
	struct fs_clk_data *clock;
	uint32_t regval, rc = 0;

	/* Return early if already disabled. */
	regval = readl_relaxed(fs->gfs_ctl_reg);
	if ((regval & ENABLE_BIT) == 0)
		return 0;

	/* Make sure required clocks are on at the correct rates. */
	rc = setup_clocks(fs);
	if (rc)
		return rc;

	/* Allow core memory to collapse when its clock is gated. */
	clk_set_flags(fs->core_clk, CLKFLAG_NORETAIN);

	/* Halt all bus ports in the power domain. */
	if (fs->bus_port0) {
		rc = msm_bus_axi_porthalt(fs->bus_port0);
		if (rc) {
			pr_err("%s port 0 halt failed.\n", fs->desc.name);
			goto err;
		}
	}
	if (fs->bus_port1) {
		rc = msm_bus_axi_porthalt(fs->bus_port1);
		if (rc) {
			pr_err("%s port 1 halt failed.\n", fs->desc.name);
			goto err_port2_halt;
		}
	}

	/*
	 * Assert resets for all clocks in the clock domain so that
	 * outputs settle prior to clamping.
	 */
	for (clock = fs->clk_data; clock->clk; clock++)
		; /* Do nothing */
	for (clock--; clock >= fs->clk_data; clock--)
		clk_reset(clock->clk, CLK_RESET_ASSERT);
	/* Wait for synchronous resets to propagate. */
	udelay(RESET_DELAY_US);

	/*
	 * Return clocks to their state before this function. For robustness
	 * if memory-retention across collapses is required, clocks should
	 * be disabled before asserting the clamps. Assuming clocks were off
	 * before entering footswitch_disable(), this will be true.
	 */
	restore_clocks(fs);

	/*
	 * Clamp the I/O ports of the core to ensure the values
	 * remain fixed while the core is collapsed.
	 */
	regval |= CLAMP_BIT;
	writel_relaxed(regval, fs->gfs_ctl_reg);

	/* Collapse the power rail at the footswitch. */
	regval &= ~ENABLE_BIT;
	writel_relaxed(regval, fs->gfs_ctl_reg);

	fs->is_enabled = false;
	return 0;

err_port2_halt:
	msm_bus_axi_portunhalt(fs->bus_port0);
err:
	clk_set_flags(fs->core_clk, CLKFLAG_RETAIN);
	restore_clocks(fs);
	return rc;
}
コード例 #6
0
ファイル: pil-q6v4.c プロジェクト: 0987363/BMW-OpenSource
static int pil_q6v4_reset(struct pil_desc *pil)
{
	u32 reg, err;
	const struct q6v4_data *drv = dev_get_drvdata(pil->dev);
	const struct pil_q6v4_pdata *pdata = pil->dev->platform_data;

	err = pil_q6v4_power_up(pil->dev);
	if (err)
		return err;
	/* Enable Q6 ACLK */
	writel_relaxed(0x10, pdata->aclk_reg);

	if (drv->modem_base)
		pil_q6v4_init_modem(drv->modem_base, pdata->jtag_clk_reg);

	/* Unhalt bus port */
	err = msm_bus_axi_portunhalt(pdata->bus_port);
	if (err)
		dev_err(pil->dev, "Failed to unhalt bus port\n");

	/* Deassert Q6SS_SS_ARES */
	reg = readl_relaxed(drv->base + QDSP6SS_RESET);
	reg &= ~(Q6SS_SS_ARES);
	writel_relaxed(reg, drv->base + QDSP6SS_RESET);

	/* Program boot address */
	writel_relaxed((drv->start_addr >> 8) & 0xFFFFFF,
			drv->base + QDSP6SS_RST_EVB);

	/* Program TCM and AHB address ranges */
	writel_relaxed(pdata->strap_tcm_base, drv->base + QDSP6SS_STRAP_TCM);
	writel_relaxed(pdata->strap_ahb_upper | pdata->strap_ahb_lower,
		       drv->base + QDSP6SS_STRAP_AHB);

	/* Turn off Q6 core clock */
	writel_relaxed(Q6SS_SRC_SWITCH_CLK_OVR,
		       drv->base + QDSP6SS_GFMUX_CTL);

	/* Put memories to sleep */
	writel_relaxed(Q6SS_CLAMP_IO, drv->base + QDSP6SS_PWR_CTL);

	/* Assert resets */
	reg = readl_relaxed(drv->base + QDSP6SS_RESET);
	reg |= (Q6SS_CORE_ARES | Q6SS_ISDB_ARES | Q6SS_ETM_ARES
	    | Q6SS_STOP_CORE_ARES);
	writel_relaxed(reg, drv->base + QDSP6SS_RESET);

	/* Wait 8 AHB cycles for Q6 to be fully reset (AHB = 1.5Mhz) */
	mb();
	usleep_range(20, 30);

	/* Turn on Q6 memories */
	reg = Q6SS_L2DATA_SLP_NRET_N | Q6SS_SLP_RET_N | Q6SS_L1TCM_SLP_NRET_N
	    | Q6SS_L2TAG_SLP_NRET_N | Q6SS_ETB_SLEEP_NRET_N | Q6SS_ARR_STBY_N
	    | Q6SS_CLAMP_IO;
	writel_relaxed(reg, drv->base + QDSP6SS_PWR_CTL);

	/* Turn on Q6 core clock */
	reg = Q6SS_CLK_ENA | Q6SS_SRC_SWITCH_CLK_OVR;
	writel_relaxed(reg, drv->base + QDSP6SS_GFMUX_CTL);

	/* Remove Q6SS_CLAMP_IO */
	reg = readl_relaxed(drv->base + QDSP6SS_PWR_CTL);
	reg &= ~Q6SS_CLAMP_IO;
	writel_relaxed(reg, drv->base + QDSP6SS_PWR_CTL);

	/* Bring Q6 core out of reset and start execution. */
	writel_relaxed(0x0, drv->base + QDSP6SS_RESET);

	return 0;
}
コード例 #7
0
static int pil_q6v4_reset(struct pil_desc *pil)
{
	u32 reg, err;
	const struct q6v4_data *drv = dev_get_drvdata(pil->dev);
	const struct pil_q6v4_pdata *pdata = pil->dev->platform_data;

	err = pil_q6v4_power_up(pil->dev);
	if (err)
		return err;
	
	writel_relaxed(0x10, pdata->aclk_reg);

	if (drv->modem_base)
		pil_q6v4_init_modem(drv->modem_base, pdata->jtag_clk_reg);

	
	err = msm_bus_axi_portunhalt(pdata->bus_port);
	if (err)
		dev_err(pil->dev, "Failed to unhalt bus port\n");

	
	reg = readl_relaxed(drv->base + QDSP6SS_RESET);
	reg &= ~(Q6SS_SS_ARES);
	writel_relaxed(reg, drv->base + QDSP6SS_RESET);

	
	writel_relaxed((drv->start_addr >> 8) & 0xFFFFFF,
			drv->base + QDSP6SS_RST_EVB);

	
	writel_relaxed(pdata->strap_tcm_base, drv->base + QDSP6SS_STRAP_TCM);
	writel_relaxed(pdata->strap_ahb_upper | pdata->strap_ahb_lower,
		       drv->base + QDSP6SS_STRAP_AHB);

	
	writel_relaxed(Q6SS_SRC_SWITCH_CLK_OVR,
		       drv->base + QDSP6SS_GFMUX_CTL);

	
	writel_relaxed(Q6SS_CLAMP_IO, drv->base + QDSP6SS_PWR_CTL);

	
	reg = readl_relaxed(drv->base + QDSP6SS_RESET);
	reg |= (Q6SS_CORE_ARES | Q6SS_ISDB_ARES | Q6SS_ETM_ARES
	    | Q6SS_STOP_CORE_ARES);
	writel_relaxed(reg, drv->base + QDSP6SS_RESET);

	
	mb();
	usleep_range(20, 30);

	
	reg = Q6SS_L2DATA_SLP_NRET_N | Q6SS_SLP_RET_N | Q6SS_L1TCM_SLP_NRET_N
	    | Q6SS_L2TAG_SLP_NRET_N | Q6SS_ETB_SLEEP_NRET_N | Q6SS_ARR_STBY_N
	    | Q6SS_CLAMP_IO;
	writel_relaxed(reg, drv->base + QDSP6SS_PWR_CTL);

	
	reg = Q6SS_CLK_ENA | Q6SS_SRC_SWITCH_CLK_OVR;
	writel_relaxed(reg, drv->base + QDSP6SS_GFMUX_CTL);

	
	reg = readl_relaxed(drv->base + QDSP6SS_PWR_CTL);
	reg &= ~Q6SS_CLAMP_IO;
	writel_relaxed(reg, drv->base + QDSP6SS_PWR_CTL);

	
	writel_relaxed(0x0, drv->base + QDSP6SS_RESET);

	return 0;
}
コード例 #8
0
ファイル: pil-q6v4.c プロジェクト: DESHONOR/kernel_huawei
static int pil_q6v4_reset(struct pil_desc *pil)
{
	u32 reg, err = 0;
	const struct q6v4_data *drv = dev_get_drvdata(pil->dev);
	const struct pil_q6v4_pdata *pdata = pil->dev->platform_data;

	pil_q6v4_make_xo_proxy_votes(pil->dev);

	err = pil_q6v4_power_up(pil->dev);
	if (err)
		return err;
	/* Enable Q6 ACLK */
	writel_relaxed(0x10, pdata->aclk_reg);

	if (drv->modem_base)
		pil_q6v4_init_modem(drv->modem_base, pdata->jtag_clk_reg);

	/* Unhalt bus port */
	err = msm_bus_axi_portunhalt(pdata->bus_port);
	if (err)
		dev_err(pil->dev, "Failed to unhalt bus port\n");

	/*
	 * Assert AXIS_ACLK_EN override to allow for correct updating of the
	 * QDSP6_CORE_STATE status bit. This is mandatory only for the SW Q6
	 * in 8960v1 and optional elsewhere.
	 */
	reg = readl_relaxed(drv->base + QDSP6SS_CGC_OVERRIDE);
	reg |= Q6SS_AXIS_ACLK_EN;
	writel_relaxed(reg, drv->base + QDSP6SS_CGC_OVERRIDE);

	/* Deassert Q6SS_SS_ARES */
	reg = readl_relaxed(drv->base + QDSP6SS_RESET);
	reg &= ~(Q6SS_SS_ARES);
	writel_relaxed(reg, drv->base + QDSP6SS_RESET);

	/* Program boot address */
	writel_relaxed((drv->start_addr >> 8) & 0xFFFFFF,
			drv->base + QDSP6SS_RST_EVB);

	/* Program TCM and AHB address ranges */
	writel_relaxed(pdata->strap_tcm_base, drv->base + QDSP6SS_STRAP_TCM);
	writel_relaxed(pdata->strap_ahb_upper | pdata->strap_ahb_lower,
		       drv->base + QDSP6SS_STRAP_AHB);

	/* Turn off Q6 core clock */
	writel_relaxed(Q6SS_SRC_SWITCH_CLK_OVR,
		       drv->base + QDSP6SS_GFMUX_CTL);

	/* Put memories to sleep */
	writel_relaxed(Q6SS_CLAMP_IO, drv->base + QDSP6SS_PWR_CTL);

	/* Assert resets */
	reg = readl_relaxed(drv->base + QDSP6SS_RESET);
	reg |= (Q6SS_CORE_ARES | Q6SS_ISDB_ARES | Q6SS_ETM_ARES
	    | Q6SS_STOP_CORE_ARES);
	writel_relaxed(reg, drv->base + QDSP6SS_RESET);

	/* Wait 8 AHB cycles for Q6 to be fully reset (AHB = 1.5Mhz) */
	mb();
	usleep_range(20, 30);

	/* Turn on Q6 memories */
	reg = Q6SS_L2DATA_SLP_NRET_N | Q6SS_SLP_RET_N | Q6SS_L1TCM_SLP_NRET_N
	    | Q6SS_L2TAG_SLP_NRET_N | Q6SS_ETB_SLEEP_NRET_N | Q6SS_ARR_STBY_N
	    | Q6SS_CLAMP_IO;
	writel_relaxed(reg, drv->base + QDSP6SS_PWR_CTL);

	/* Turn on Q6 core clock */
	reg = Q6SS_CLK_ENA | Q6SS_SRC_SWITCH_CLK_OVR;
	writel_relaxed(reg, drv->base + QDSP6SS_GFMUX_CTL);

	/* Remove Q6SS_CLAMP_IO */
	reg = readl_relaxed(drv->base + QDSP6SS_PWR_CTL);
	reg &= ~Q6SS_CLAMP_IO;
	writel_relaxed(reg, drv->base + QDSP6SS_PWR_CTL);

	/* Bring Q6 core out of reset and start execution. */
	writel_relaxed(0x0, drv->base + QDSP6SS_RESET);

	/*
	 * Re-enable auto-gating of AXIS_ACLK at lease one AXI clock cycle
	 * after resets are de-asserted.
	 */
	mb();
	usleep_range(1, 10);
	reg = readl_relaxed(drv->base + QDSP6SS_CGC_OVERRIDE);
	reg &= ~Q6SS_AXIS_ACLK_EN;
	writel_relaxed(reg, drv->base + QDSP6SS_CGC_OVERRIDE);

	return 0;
}
コード例 #9
0
ファイル: footswitch-8x60.c プロジェクト: robcore/machinex
static int footswitch_enable(struct regulator_dev *rdev)
{
	struct footswitch *fs = rdev_get_drvdata(rdev);
	struct fs_clk_data *clock;
	uint32_t regval, rc = 0;

	mutex_lock(&claim_lock);
	fs->is_claimed = true;
	mutex_unlock(&claim_lock);

	/* Return early if already enabled. */
	regval = readl_relaxed(fs->gfs_ctl_reg);
	if ((regval & (ENABLE_BIT | CLAMP_BIT)) == ENABLE_BIT)
		return 0;

	/* Make sure required clocks are on at the correct rates. */
	rc = setup_clocks(fs);
	if (rc)
		return rc;

	/* Un-halt all bus ports in the power domain. */
	if (fs->bus_port0) {
		rc = msm_bus_axi_portunhalt(fs->bus_port0);
		if (rc) {
			pr_err("%s port 0 unhalt failed.\n", fs->desc.name);
			goto err;
		}
	}
	if (fs->bus_port1) {
		rc = msm_bus_axi_portunhalt(fs->bus_port1);
		if (rc) {
			pr_err("%s port 1 unhalt failed.\n", fs->desc.name);
			goto err_port2_halt;
		}
	}

	/*
	 * (Re-)Assert resets for all clocks in the clock domain, since
	 * footswitch_enable() is first called before footswitch_disable()
	 * and resets should be asserted before power is restored.
	 */
	for (clock = fs->clk_data; clock->clk; clock++)
		; /* Do nothing */
	for (clock--; clock >= fs->clk_data; clock--)
		clk_reset(clock->clk, CLK_RESET_ASSERT);
	/* Wait for synchronous resets to propagate. */
	udelay(fs->reset_delay_us);

	/* Enable the power rail at the footswitch. */
	regval |= ENABLE_BIT;

#if defined(CONFIG_ARCH_MSM8930)
	writel_relaxed(regval, fs->gfs_ctl_reg);
#else
	if (fs->desc.id != FS_GFX3D)
		writel_relaxed(regval, fs->gfs_ctl_reg);
#endif

	/* Wait for the rail to fully charge. */
	mb();
	udelay(1);

	/* Un-clamp the I/O ports. */
	regval &= ~CLAMP_BIT;
	writel_relaxed(regval, fs->gfs_ctl_reg);

	/* Deassert resets for all clocks in the power domain. */
	for (clock = fs->clk_data; clock->clk; clock++)
		clk_reset(clock->clk, CLK_RESET_DEASSERT);
	/* Toggle core reset again after first power-on (required for GFX3D). */
	if (fs->desc.id == FS_GFX3D) {
		clk_reset(fs->core_clk, CLK_RESET_ASSERT);
		udelay(fs->reset_delay_us);
		clk_reset(fs->core_clk, CLK_RESET_DEASSERT);
		udelay(fs->reset_delay_us);
	}

	/* Prevent core memory from collapsing when its clock is gated. */
	clk_set_flags(fs->core_clk, CLKFLAG_RETAIN_MEM);

	/* Return clocks to their state before this function. */
	restore_clocks(fs);

	fs->is_enabled = true;
	return 0;

err_port2_halt:
	msm_bus_axi_porthalt(fs->bus_port0);
err:
	restore_clocks(fs);
	return rc;
}
コード例 #10
0
static int gfx2d_footswitch_enable(struct regulator_dev *rdev)
{
	struct footswitch *fs = rdev_get_drvdata(rdev);
	uint32_t regval, rc = 0;

	mutex_lock(&claim_lock);
	fs->is_claimed = true;
	mutex_unlock(&claim_lock);

	/* Return early if already enabled. */
	regval = readl_relaxed(fs->gfs_ctl_reg);
	if ((regval & (ENABLE_BIT | CLAMP_BIT)) == ENABLE_BIT)
		return 0;

	/* Make sure required clocks are on at the correct rates. */
	rc = setup_clocks(fs);
	if (rc)
		goto out;

	/* Un-halt all bus ports in the power domain. */
	if (fs->bus_port1) {
		rc = msm_bus_axi_portunhalt(fs->bus_port1);
		if (rc) {
			pr_err("%s: Port 1 unhalt failed.\n", __func__);
			goto out;
		}
	}

	/* Disable core clock. */
	clk_disable(fs->core_clk);

	/*
	 * (Re-)Assert resets for all clocks in the clock domain, since
	 * footswitch_enable() is first called before footswitch_disable()
	 * and resets should be asserted before power is restored.
	 */
	if (fs->axi_clk)
		clk_reset(fs->axi_clk, CLK_RESET_ASSERT);
	clk_reset(fs->ahb_clk, CLK_RESET_ASSERT);
	clk_reset(fs->core_clk, CLK_RESET_ASSERT);
	/* Wait for synchronous resets to propagate. */
	udelay(20);

	/* Enable the power rail at the footswitch. */
	regval |= ENABLE_BIT;
	writel_relaxed(regval, fs->gfs_ctl_reg);
	mb();
	udelay(1);

	/* Un-clamp the I/O ports. */
	regval &= ~CLAMP_BIT;
	writel_relaxed(regval, fs->gfs_ctl_reg);

	/* Deassert resets for all clocks in the power domain. */
	if (fs->axi_clk)
		clk_reset(fs->axi_clk, CLK_RESET_DEASSERT);
	clk_reset(fs->ahb_clk, CLK_RESET_DEASSERT);
	clk_reset(fs->core_clk, CLK_RESET_DEASSERT);
	udelay(20);

	/* Re-enable core clock. */
	clk_enable(fs->core_clk);

	/* Return clocks to their state before this function. */
	restore_clocks(fs);

	fs->is_enabled = true;
out:
	return rc;
}
コード例 #11
0
ファイル: footswitch-8x60.c プロジェクト: AKToronto/IronBorn2
static int gfx2d_footswitch_enable(struct regulator_dev *rdev)
{
	struct footswitch *fs = rdev_get_drvdata(rdev);
	struct fs_clk_data *clock;
	uint32_t regval, rc = 0;

	mutex_lock(&claim_lock);
	fs->is_claimed = true;
	mutex_unlock(&claim_lock);

	
	regval = readl_relaxed(fs->gfs_ctl_reg);
	if ((regval & (ENABLE_BIT | CLAMP_BIT)) == ENABLE_BIT)
		return 0;

	
	rc = setup_clocks(fs);
	if (rc)
		return rc;

	
	if (fs->bus_port0) {
		rc = msm_bus_axi_portunhalt(fs->bus_port0);
		if (rc) {
			pr_err("%s port 0 unhalt failed.\n", fs->desc.name);
			goto err;
		}
	}

	
	clk_disable_unprepare(fs->core_clk);

	for (clock = fs->clk_data; clock->clk; clock++)
		; 
	for (clock--; clock >= fs->clk_data; clock--)
		clk_reset(clock->clk, CLK_RESET_ASSERT);
	
	udelay(RESET_DELAY_US);

	
	regval |= ENABLE_BIT;
	writel_relaxed(regval, fs->gfs_ctl_reg);
	mb();
	udelay(1);

	
	regval &= ~CLAMP_BIT;
	writel_relaxed(regval, fs->gfs_ctl_reg);

	
	for (clock = fs->clk_data; clock->clk; clock++)
		clk_reset(clock->clk, CLK_RESET_DEASSERT);
	udelay(RESET_DELAY_US);

	
	clk_prepare_enable(fs->core_clk);

	
	clk_set_flags(fs->core_clk, CLKFLAG_RETAIN);

	
	restore_clocks(fs);

	fs->is_enabled = true;
	return 0;

err:
	restore_clocks(fs);
	return rc;
}
コード例 #12
0
ファイル: footswitch-8x60.c プロジェクト: AKToronto/IronBorn2
static int footswitch_disable(struct regulator_dev *rdev)
{
	struct footswitch *fs = rdev_get_drvdata(rdev);
	struct fs_clk_data *clock;
	uint32_t regval, rc = 0;

	
	regval = readl_relaxed(fs->gfs_ctl_reg);
	if ((regval & ENABLE_BIT) == 0)
		return 0;

	
	rc = setup_clocks(fs);
	if (rc)
		return rc;

	
	clk_set_flags(fs->core_clk, CLKFLAG_NORETAIN);

	
	if (fs->bus_port0) {
		rc = msm_bus_axi_porthalt(fs->bus_port0);
		if (rc) {
			pr_err("%s port 0 halt failed.\n", fs->desc.name);
			goto err;
		}
	}
	if (fs->bus_port1) {
		rc = msm_bus_axi_porthalt(fs->bus_port1);
		if (rc) {
			pr_err("%s port 1 halt failed.\n", fs->desc.name);
			goto err_port2_halt;
		}
	}

	for (clock = fs->clk_data; clock->clk; clock++)
		; 
	for (clock--; clock >= fs->clk_data; clock--)
		clk_reset(clock->clk, CLK_RESET_ASSERT);
	
	udelay(RESET_DELAY_US);

	restore_clocks(fs);

	regval |= CLAMP_BIT;
	writel_relaxed(regval, fs->gfs_ctl_reg);

	
	regval &= ~ENABLE_BIT;
	writel_relaxed(regval, fs->gfs_ctl_reg);

	fs->is_enabled = false;
	return 0;

err_port2_halt:
	msm_bus_axi_portunhalt(fs->bus_port0);
err:
	clk_set_flags(fs->core_clk, CLKFLAG_RETAIN);
	restore_clocks(fs);
	return rc;
}
コード例 #13
0
static int footswitch_enable(struct regulator_dev *rdev)
{
	struct footswitch *fs = rdev_get_drvdata(rdev);
	uint32_t regval, rc = 0;

	mutex_lock(&claim_lock);
	fs->is_claimed = 1;
	mutex_unlock(&claim_lock);

	/* Make sure required clocks are on at the correct rates. */
	rc = setup_clocks(fs);
	if (rc)
		goto out;

	/* (Re-)Assert resets for all clocks in the clock domain, since
	 * footswitch_enable() is first called before footswitch_disable()
	 * and resets should be asserted before power is restored. */
	if (fs->axi_clk)
		clk_reset(fs->axi_clk, CLK_RESET_ASSERT);
	clk_reset(fs->ahb_clk, CLK_RESET_ASSERT);
	clk_reset(fs->core_clk, CLK_RESET_ASSERT);
	/* Wait for synchronous resets to propagate. */
	udelay(RESET_DELAY_US);

	/* Un-halt all bus ports in the power domain. */
	if (fs->bus_port1) {
		rc = msm_bus_axi_portunhalt(fs->bus_port1);
		if (rc) {
			pr_err("%s: Port 1 unhalt failed.\n", __func__);
			goto out;
		}
	}
	if (fs->bus_port2) {
		rc = msm_bus_axi_portunhalt(fs->bus_port2);
		if (rc) {
			pr_err("%s: Port 2 unhalt failed.\n", __func__);
			goto out;
		}
	}

	/* Enable the power rail at the footswitch. */
	regval = readl(fs->gfs_ctl_reg);
	regval |= ENABLE_BIT;
	writel(regval, fs->gfs_ctl_reg);
	/* Wait 2us for the rail to fully charge. */
	udelay(2);

	/* Deassert resets for all clocks in the power domain. */
	clk_reset(fs->core_clk, CLK_RESET_DEASSERT);
	clk_reset(fs->ahb_clk, CLK_RESET_DEASSERT);
	if (fs->axi_clk)
		clk_reset(fs->axi_clk, CLK_RESET_DEASSERT);
	/* Toggle core reset now that power is on (required for some cores). */
	clk_reset(fs->core_clk, CLK_RESET_ASSERT);
	udelay(RESET_DELAY_US);
	clk_reset(fs->core_clk, CLK_RESET_DEASSERT);
	udelay(RESET_DELAY_US);

	/* Un-clamp the I/O ports. */
	regval &= ~CLAMP_BIT;
	writel(regval, fs->gfs_ctl_reg);

	/* Wait for the clamps to clear and signals to settle. */
	udelay(5);

	/* Return clocks to their state before this function. */
	restore_clocks(fs);

	fs->is_enabled = 1;
out:
	return rc;
}