Lines Matching +full:sci +full:- +full:dev +full:- +full:id

1 // SPDX-License-Identifier: GPL-2.0-only
3 * TI SCI Generic Power Domain Driver
5 * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/
6 * J Keerthy <j-keerthy@ti.com>
7 * Dave Gerlach <d-gerlach@ti.com>
19 #include <dt-bindings/soc/ti,sci_pm_domain.h>
22 * struct ti_sci_genpd_provider: holds common TI SCI genpd provider data
23 * @ti_sci: handle to TI SCI protocol driver that provides ops to
25 * @dev: pointer to dev for the driver for devm allocs
31 struct device *dev; member
44 * @parent: link to the parent TI SCI genpd provider
62 static void ti_sci_pd_set_lat_constraint(struct device *dev, s32 val) in ti_sci_pd_set_lat_constraint() argument
64 struct generic_pm_domain *genpd = pd_to_genpd(dev->pm_domain); in ti_sci_pd_set_lat_constraint()
66 const struct ti_sci_handle *ti_sci = pd->parent->ti_sci; in ti_sci_pd_set_lat_constraint()
70 /* PM QoS latency unit is usecs, TI SCI uses msecs */ in ti_sci_pd_set_lat_constraint()
72 ret = ti_sci->ops.pm_ops.set_latency_constraint(ti_sci, val_ms, TISCI_MSG_CONSTRAINT_SET); in ti_sci_pd_set_lat_constraint()
74 dev_err(dev, "ti_sci_pd: set latency constraint failed: ret=%d\n", in ti_sci_pd_set_lat_constraint()
77 dev_dbg(dev, "ti_sci_pd: ID:%d set latency constraint %d\n", in ti_sci_pd_set_lat_constraint()
78 pd->idx, val); in ti_sci_pd_set_lat_constraint()
82 static inline void ti_sci_pd_set_wkup_constraint(struct device *dev) in ti_sci_pd_set_wkup_constraint() argument
84 struct generic_pm_domain *genpd = pd_to_genpd(dev->pm_domain); in ti_sci_pd_set_wkup_constraint()
86 const struct ti_sci_handle *ti_sci = pd->parent->ti_sci; in ti_sci_pd_set_wkup_constraint()
89 if (device_may_wakeup(dev)) { in ti_sci_pd_set_wkup_constraint()
94 if (dev->power.wakeirq) { in ti_sci_pd_set_wkup_constraint()
95 dev_dbg(dev, "%s: has wake IRQ, not setting constraints\n", __func__); in ti_sci_pd_set_wkup_constraint()
99 ret = ti_sci->ops.pm_ops.set_device_constraint(ti_sci, pd->idx, in ti_sci_pd_set_wkup_constraint()
102 dev_dbg(dev, "ti_sci_pd: ID:%d set device constraint.\n", pd->idx); in ti_sci_pd_set_wkup_constraint()
113 const struct ti_sci_handle *ti_sci = pd->parent->ti_sci; in ti_sci_pd_power_off()
115 return ti_sci->ops.dev_ops.put_device(ti_sci, pd->idx); in ti_sci_pd_power_off()
125 const struct ti_sci_handle *ti_sci = pd->parent->ti_sci; in ti_sci_pd_power_on()
127 if (pd->exclusive) in ti_sci_pd_power_on()
128 return ti_sci->ops.dev_ops.get_device_exclusive(ti_sci, in ti_sci_pd_power_on()
129 pd->idx); in ti_sci_pd_power_on()
131 return ti_sci->ops.dev_ops.get_device(ti_sci, pd->idx); in ti_sci_pd_power_on()
135 static int ti_sci_pd_suspend(struct device *dev) in ti_sci_pd_suspend() argument
140 ret = pm_generic_suspend(dev); in ti_sci_pd_suspend()
144 val = dev_pm_qos_read_value(dev, DEV_PM_QOS_RESUME_LATENCY); in ti_sci_pd_suspend()
146 ti_sci_pd_set_lat_constraint(dev, val); in ti_sci_pd_suspend()
148 ti_sci_pd_set_wkup_constraint(dev); in ti_sci_pd_suspend()
157 * ti_sci_pd_xlate(): translation service for TI SCI genpds
166 unsigned int idx = genpdspec->args[0]; in ti_sci_pd_xlate()
168 if (genpdspec->args_count != 1 && genpdspec->args_count != 2) in ti_sci_pd_xlate()
169 return ERR_PTR(-EINVAL); in ti_sci_pd_xlate()
171 if (idx >= genpd_data->num_domains) { in ti_sci_pd_xlate()
173 return ERR_PTR(-EINVAL); in ti_sci_pd_xlate()
176 if (!genpd_data->domains[idx]) in ti_sci_pd_xlate()
177 return ERR_PTR(-ENOENT); in ti_sci_pd_xlate()
179 genpd_to_ti_sci_pd(genpd_data->domains[idx])->exclusive = in ti_sci_pd_xlate()
180 genpdspec->args[1]; in ti_sci_pd_xlate()
182 return genpd_data->domains[idx]; in ti_sci_pd_xlate()
186 { .compatible = "ti,sci-pm-domain", },
195 list_for_each_entry(pd, &pd_provider->pd_list, node) { in ti_sci_pm_idx_exists()
196 if (pd->idx == idx) in ti_sci_pm_idx_exists()
205 struct device *dev = &pdev->dev; in ti_sci_pm_domain_probe() local
213 pd_provider = devm_kzalloc(dev, sizeof(*pd_provider), GFP_KERNEL); in ti_sci_pm_domain_probe()
215 return -ENOMEM; in ti_sci_pm_domain_probe()
217 pd_provider->ti_sci = devm_ti_sci_get_handle(dev); in ti_sci_pm_domain_probe()
218 if (IS_ERR(pd_provider->ti_sci)) in ti_sci_pm_domain_probe()
219 return PTR_ERR(pd_provider->ti_sci); in ti_sci_pm_domain_probe()
221 pd_provider->dev = dev; in ti_sci_pm_domain_probe()
223 INIT_LIST_HEAD(&pd_provider->pd_list); in ti_sci_pm_domain_probe()
225 /* Find highest device ID used for power domains */ in ti_sci_pm_domain_probe()
226 for_each_node_with_property(np, "power-domains") { in ti_sci_pm_domain_probe()
229 while (!of_parse_phandle_with_args(np, "power-domains", in ti_sci_pm_domain_probe()
230 "#power-domain-cells", in ti_sci_pm_domain_probe()
233 if (args.args_count >= 1 && args.np == dev->of_node) { in ti_sci_pm_domain_probe()
244 pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); in ti_sci_pm_domain_probe()
246 return -ENOMEM; in ti_sci_pm_domain_probe()
248 pd->pd.name = devm_kasprintf(dev, GFP_KERNEL, in ti_sci_pm_domain_probe()
251 if (!pd->pd.name) in ti_sci_pm_domain_probe()
252 return -ENOMEM; in ti_sci_pm_domain_probe()
254 pd->pd.power_off = ti_sci_pd_power_off; in ti_sci_pm_domain_probe()
255 pd->pd.power_on = ti_sci_pd_power_on; in ti_sci_pm_domain_probe()
256 pd->pd.flags |= GENPD_FLAG_ACTIVE_WAKEUP; in ti_sci_pm_domain_probe()
257 pd->idx = args.args[0]; in ti_sci_pm_domain_probe()
258 pd->parent = pd_provider; in ti_sci_pm_domain_probe()
260 * If SCI constraint functions are present, then firmware in ti_sci_pm_domain_probe()
263 if (pd_provider->ti_sci->ops.pm_ops.set_device_constraint && in ti_sci_pm_domain_probe()
264 pd_provider->ti_sci->ops.pm_ops.set_latency_constraint) in ti_sci_pm_domain_probe()
265 pd->pd.domain.ops.suspend = ti_sci_pd_suspend; in ti_sci_pm_domain_probe()
267 pm_genpd_init(&pd->pd, NULL, true); in ti_sci_pm_domain_probe()
269 list_add(&pd->node, &pd_provider->pd_list); in ti_sci_pm_domain_probe()
278 pd_provider->data.domains = in ti_sci_pm_domain_probe()
279 devm_kcalloc(dev, max_id + 1, in ti_sci_pm_domain_probe()
280 sizeof(*pd_provider->data.domains), in ti_sci_pm_domain_probe()
282 if (!pd_provider->data.domains) in ti_sci_pm_domain_probe()
283 return -ENOMEM; in ti_sci_pm_domain_probe()
285 pd_provider->data.num_domains = max_id + 1; in ti_sci_pm_domain_probe()
286 pd_provider->data.xlate = ti_sci_pd_xlate; in ti_sci_pm_domain_probe()
288 list_for_each_entry(pd, &pd_provider->pd_list, node) in ti_sci_pm_domain_probe()
289 pd_provider->data.domains[pd->idx] = &pd->pd; in ti_sci_pm_domain_probe()
291 return of_genpd_add_provider_onecell(dev->of_node, &pd_provider->data); in ti_sci_pm_domain_probe()
303 MODULE_DESCRIPTION("TI System Control Interface (SCI) Power Domain driver");