scpsys
scpsys->bus_prot = devm_kmalloc_array(dev, num_regmaps,
sizeof(*scpsys->bus_prot), GFP_KERNEL);
if (!scpsys->bus_prot)
scpsys->bus_prot_index[bp_type] = j;
scpsys->bus_prot[j] = regmap[i];
static int scpsys_get_bus_protection(struct device *dev, struct scpsys *scpsys)
const struct scpsys_soc_data *soc = scpsys->soc_data;
regmap_multi_reg_read(pd->scpsys->base, regs, val, 2);
scpsys->bus_prot = devm_kmalloc_array(dev, soc->num_bus_prot_blocks,
sizeof(*scpsys->bus_prot), GFP_KERNEL);
if (!scpsys->bus_prot)
scpsys->bus_prot_index[bp_type] = i;
scpsys->bus_prot[i] = device_node_to_regmap(node);
if (IS_ERR_OR_NULL(scpsys->bus_prot[i]))
return dev_err_probe(dev, scpsys->bus_prot[i] ?
PTR_ERR(scpsys->bus_prot[i]) : -ENXIO,
struct scpsys *scpsys;
scpsys = devm_kzalloc(dev, struct_size(scpsys, domains, num_domains), GFP_KERNEL);
if (!scpsys)
scpsys->dev = dev;
scpsys->soc_data = soc;
scpsys->pd_data.domains = scpsys->domains;
scpsys->pd_data.num_domains = num_domains;
regmap_multi_reg_read(pd->scpsys->base, regs, val, 3);
scpsys->base = syscon_node_to_regmap(parent->of_node);
if (IS_ERR(scpsys->base)) {
return PTR_ERR(scpsys->base);
ret = scpsys_get_bus_protection(dev, scpsys);
ret = scpsys_get_bus_protection_legacy(dev, scpsys);
domain = scpsys_add_one_domain(scpsys, node);
ret = scpsys_add_subdomain(scpsys, node);
ret = of_genpd_add_provider_onecell(np, &scpsys->pd_data);
scpsys_domain_cleanup(scpsys);
struct scpsys *scpsys = pd->scpsys;
regmap_set_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
ret = regmap_read_poll_timeout(scpsys->base, pd->data->ctl_offs, tmp,
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_ISOINT_B_BIT);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_CLKISO_BIT);
struct scpsys *scpsys = pd->scpsys;
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_CLKISO_BIT);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_ISOINT_B_BIT);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
return regmap_read_poll_timeout(scpsys->base, pd->data->ctl_offs, tmp,
struct scpsys *scpsys = pd->scpsys;
unsigned short block_idx = scpsys->bus_prot_index[bpd->bus_prot_block];
return scpsys->bus_prot[block_idx];
struct scpsys *scpsys = pd->scpsys;
int block_idx = scpsys->bus_prot_index[bpd->bus_prot_sta_block];
return scpsys->bus_prot[block_idx];
struct scpsys *scpsys = pd->scpsys;
ret = regmap_read_poll_timeout_atomic(scpsys->base, hwv->done, val,
dev_err(scpsys->dev, "Failed to power on: HW Voter busy.\n");
regmap_write(scpsys->base, hwv->set, BIT(hwv->setclr_bit));
ret = regmap_read_poll_timeout_atomic(scpsys->base, hwv->set, val,
dev_err(scpsys->dev, "Failed to power on: HW Voter not starting.\n");
dev_err(scpsys->dev, "Failed to power on: HW Voter ACK timeout.\n");
struct scpsys *scpsys = pd->scpsys;
ret = regmap_read_poll_timeout_atomic(scpsys->base, hwv->done, val,
regmap_write(scpsys->base, hwv->clr, BIT(hwv->setclr_bit));
ret = regmap_read_poll_timeout_atomic(scpsys->base, hwv->clr, val,
struct scpsys *scpsys = pd->scpsys;
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
regmap_read(scpsys->base, pd->data->ctl_offs, &ctl_status);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE_FLAG);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_NRESTORE);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_NRESTORE);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE_FLAG);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_NRESTORE);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_NRESTORE);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_UFS_CLK_DIS);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_NRESTORE);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_NRESTORE);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_UFS_CLK_DIS);
struct scpsys *scpsys = pd->scpsys;
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE_FLAG);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_UFS_CLK_DIS);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_SAVE);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_UFS_CLK_DIS);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
struct scpsys *scpsys = pd->scpsys;
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
struct scpsys *scpsys = pd->scpsys;
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
struct scpsys *scpsys = pd->scpsys;
regmap_clear_bits(scpsys->base, pd->data->ext_buck_iso_offs,
struct scpsys *scpsys;
struct scpsys *scpsys = pd->scpsys;
regmap_set_bits(scpsys->base, pd->data->ext_buck_iso_offs,
generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_node *node)
dev_err(scpsys->dev, "%pOF: failed to retrieve domain id from reg: %d\n",
switch (scpsys->soc_data->type) {
if (id >= scpsys->soc_data->num_domains) {
dev_err(scpsys->dev, "%pOF: invalid domain id %d\n", node, id);
domain_data = &scpsys->soc_data->domains_data[id];
dev_err(scpsys->dev, "%pOF: undefined domain id %d\n", node, id);
if (id >= scpsys->soc_data->num_hwv_domains) {
dev_err(scpsys->dev, "%pOF: invalid HWV domain id %d\n", node, id);
hwv_domain_data = &scpsys->soc_data->hwv_domains_data[id];
pd = devm_kzalloc(scpsys->dev, sizeof(*pd), GFP_KERNEL);
pd->scpsys = scpsys;
pd->supply = devm_of_regulator_get_optional(scpsys->dev, node, "domain");
return dev_err_cast_probe(scpsys->dev, pd->supply,
pd->clks = devm_kcalloc(scpsys->dev, pd->num_clks, sizeof(*pd->clks), GFP_KERNEL);
pd->subsys_clks = devm_kcalloc(scpsys->dev, pd->num_subsys_clks,
dev_err_probe(scpsys->dev, ret,
dev_err_probe(scpsys->dev, ret,
if (scpsys->domains[id]) {
dev_err(scpsys->dev,
if (scpsys->soc_data->type == SCPSYS_MTCMOS_TYPE_DIRECT_CTL) {
struct scpsys *scpsys = pd->scpsys;
dev_warn(scpsys->dev,
dev_err(scpsys->dev, "%pOF: failed to power on domain: %d\n", node, ret);
scpsys->domains[id] = &pd->genpd;
return scpsys->pd_data.domains[id];
static int scpsys_add_subdomain(struct scpsys *scpsys, struct device_node *parent)
dev_err(scpsys->dev, "%pOF: failed to get parent domain id\n", child);
regmap_read(scpsys->base, pd->data->pwr_sta_offs, &status);
if (!scpsys->pd_data.domains[id]) {
dev_err(scpsys->dev, "power domain with id %d does not exist\n", id);
parent_pd = scpsys->pd_data.domains[id];
child_pd = scpsys_add_one_domain(scpsys, child);
dev_err_probe(scpsys->dev, ret, "%pOF: failed to get child domain id\n",
ret = scpsys_add_subdomain(scpsys, child);
dev_err(scpsys->dev, "failed to add %s subdomain to parent %s\n",
regmap_read(scpsys->base, pd->data->pwr_sta2nd_offs, &status2);
dev_dbg(scpsys->dev, "%s add subdomain: %s\n", parent_pd->name,
dev_err(pd->scpsys->dev,
static void scpsys_domain_cleanup(struct scpsys *scpsys)
for (i = scpsys->pd_data.num_domains - 1; i >= 0; i--) {
genpd = scpsys->pd_data.domains[i];
static int scpsys_get_bus_protection_legacy(struct device *dev, struct scpsys *scpsys)