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; }
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); }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }