Merge "clk: msm: clock-osm: Do not initialize ACD if the cluster isn't online"

This commit is contained in:
Linux Build Service Account 2017-06-18 09:47:24 -07:00 committed by Gerrit - the friendly Code Review server
commit fd2a5d6bd5

View file

@ -606,6 +606,83 @@ static int clk_osm_acd_auto_local_write_reg(struct clk_osm *c, u32 mask)
return 0;
}
static int clk_osm_acd_init(struct clk_osm *c)
{
int rc = 0;
u32 auto_xfer_mask = 0;
if (!c->acd_init)
return 0;
c->acd_debugfs_addr = ACD_HW_VERSION;
/* Program ACD tunable-length delay register */
clk_osm_acd_master_write_reg(c, c->acd_td, ACDTD);
auto_xfer_mask |= ACD_REG_RELATIVE_ADDR_BITMASK(ACDTD);
/* Program ACD control register */
clk_osm_acd_master_write_reg(c, c->acd_cr, ACDCR);
auto_xfer_mask |= ACD_REG_RELATIVE_ADDR_BITMASK(ACDCR);
/* Program ACD soft start control register */
clk_osm_acd_master_write_reg(c, c->acd_sscr, ACDSSCR);
auto_xfer_mask |= ACD_REG_RELATIVE_ADDR_BITMASK(ACDSSCR);
/* Program initial ACD external interface configuration register */
clk_osm_acd_master_write_reg(c, c->acd_extint0_cfg, ACD_EXTINT_CFG);
auto_xfer_mask |= ACD_REG_RELATIVE_ADDR_BITMASK(ACD_EXTINT_CFG);
/* Program ACD auto-register transfer control register */
clk_osm_acd_master_write_reg(c, c->acd_autoxfer_ctl, ACD_AUTOXFER_CTL);
/* Ensure writes complete before transfers to local copy */
clk_osm_acd_mb(c);
/* Transfer master copies */
rc = clk_osm_acd_auto_local_write_reg(c, auto_xfer_mask);
if (rc)
return rc;
/* Switch CPUSS clock source to ACD clock */
rc = clk_osm_acd_master_write_through_reg(c, ACD_GFMUX_CFG_SELECT,
ACD_GFMUX_CFG);
if (rc)
return rc;
/* Program ACD_DCVS_SW */
rc = clk_osm_acd_master_write_through_reg(c,
ACD_DCVS_SW_DCVS_IN_PRGR_SET,
ACD_DCVS_SW);
if (rc)
return rc;
rc = clk_osm_acd_master_write_through_reg(c,
ACD_DCVS_SW_DCVS_IN_PRGR_CLEAR,
ACD_DCVS_SW);
if (rc)
return rc;
udelay(1);
/* Program final ACD external interface configuration register */
rc = clk_osm_acd_master_write_through_reg(c, c->acd_extint1_cfg,
ACD_EXTINT_CFG);
if (rc)
return rc;
/*
* ACDCR, ACDTD, ACDSSCR, ACD_EXTINT_CFG, ACD_GFMUX_CFG
* must be copied from master to local copy on PC exit.
*/
auto_xfer_mask |= ACD_REG_RELATIVE_ADDR_BITMASK(ACD_GFMUX_CFG);
clk_osm_acd_master_write_reg(c, auto_xfer_mask, ACD_AUTOXFER_CFG);
/* ACD has been initialized and enabled for this cluster */
c->acd_init = false;
return 0;
}
static inline int clk_osm_count_ns(struct clk_osm *c, u64 nsec)
{
u64 temp;
@ -729,6 +806,17 @@ static int clk_osm_set_rate(struct clk *c, unsigned long rate)
static int clk_osm_enable(struct clk *c)
{
struct clk_osm *cpuclk = to_clk_osm(c);
int rc;
rc = clk_osm_acd_init(cpuclk);
if (rc) {
pr_err("Failed to initialize ACD for cluster %d, rc=%d\n",
cpuclk->cluster_num, rc);
return rc;
}
/* Wait for 5 usecs before enabling OSM */
udelay(5);
clk_osm_write_reg(cpuclk, 1, ENABLE_REG);
@ -3105,81 +3193,6 @@ static int clk_osm_panic_callback(struct notifier_block *nfb,
return NOTIFY_OK;
}
static int clk_osm_acd_init(struct clk_osm *c)
{
int rc = 0;
u32 auto_xfer_mask = 0;
if (!c->acd_init)
return 0;
c->acd_debugfs_addr = ACD_HW_VERSION;
/* Program ACD tunable-length delay register */
clk_osm_acd_master_write_reg(c, c->acd_td, ACDTD);
auto_xfer_mask |= ACD_REG_RELATIVE_ADDR_BITMASK(ACDTD);
/* Program ACD control register */
clk_osm_acd_master_write_reg(c, c->acd_cr, ACDCR);
auto_xfer_mask |= ACD_REG_RELATIVE_ADDR_BITMASK(ACDCR);
/* Program ACD soft start control register */
clk_osm_acd_master_write_reg(c, c->acd_sscr, ACDSSCR);
auto_xfer_mask |= ACD_REG_RELATIVE_ADDR_BITMASK(ACDSSCR);
/* Program initial ACD external interface configuration register */
clk_osm_acd_master_write_reg(c, c->acd_extint0_cfg, ACD_EXTINT_CFG);
auto_xfer_mask |= ACD_REG_RELATIVE_ADDR_BITMASK(ACD_EXTINT_CFG);
/* Program ACD auto-register transfer control register */
clk_osm_acd_master_write_reg(c, c->acd_autoxfer_ctl, ACD_AUTOXFER_CTL);
/* Ensure writes complete before transfers to local copy */
clk_osm_acd_mb(c);
/* Transfer master copies */
rc = clk_osm_acd_auto_local_write_reg(c, auto_xfer_mask);
if (rc)
return rc;
/* Switch CPUSS clock source to ACD clock */
rc = clk_osm_acd_master_write_through_reg(c, ACD_GFMUX_CFG_SELECT,
ACD_GFMUX_CFG);
if (rc)
return rc;
/* Program ACD_DCVS_SW */
rc = clk_osm_acd_master_write_through_reg(c,
ACD_DCVS_SW_DCVS_IN_PRGR_SET,
ACD_DCVS_SW);
if (rc)
return rc;
rc = clk_osm_acd_master_write_through_reg(c,
ACD_DCVS_SW_DCVS_IN_PRGR_CLEAR,
ACD_DCVS_SW);
if (rc)
return rc;
udelay(1);
/* Program final ACD external interface configuration register */
rc = clk_osm_acd_master_write_through_reg(c, c->acd_extint1_cfg,
ACD_EXTINT_CFG);
if (rc)
return rc;
/*
* ACDCR, ACDTD, ACDSSCR, ACD_EXTINT_CFG, ACD_GFMUX_CFG
* must be copied from master to local copy on PC exit.
*/
auto_xfer_mask |= ACD_REG_RELATIVE_ADDR_BITMASK(ACD_GFMUX_CFG);
clk_osm_acd_master_write_reg(c, auto_xfer_mask, ACD_AUTOXFER_CFG);
return 0;
}
static unsigned long init_rate = 300000000;
static unsigned long osm_clk_init_rate = 200000000;
@ -3362,17 +3375,6 @@ static int cpu_clock_osm_driver_probe(struct platform_device *pdev)
clk_osm_setup_cluster_pll(&perfcl_clk);
}
rc = clk_osm_acd_init(&pwrcl_clk);
if (rc) {
pr_err("failed to initialize ACD for pwrcl, rc=%d\n", rc);
return rc;
}
rc = clk_osm_acd_init(&perfcl_clk);
if (rc) {
pr_err("failed to initialize ACD for perfcl, rc=%d\n", rc);
return rc;
}
spin_lock_init(&pwrcl_clk.lock);
spin_lock_init(&perfcl_clk.lock);