Linux Audio

Check our new training course

Loading...
v5.9
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * SCMI Generic power domain support.
  4 *
  5 * Copyright (C) 2018 ARM Ltd.
  6 */
  7
  8#include <linux/err.h>
  9#include <linux/io.h>
 10#include <linux/module.h>
 11#include <linux/pm_domain.h>
 12#include <linux/scmi_protocol.h>
 13
 14struct scmi_pm_domain {
 15	struct generic_pm_domain genpd;
 16	const struct scmi_handle *handle;
 17	const char *name;
 18	u32 domain;
 19};
 20
 21#define to_scmi_pd(gpd) container_of(gpd, struct scmi_pm_domain, genpd)
 22
 23static int scmi_pd_power(struct generic_pm_domain *domain, bool power_on)
 24{
 25	int ret;
 26	u32 state, ret_state;
 27	struct scmi_pm_domain *pd = to_scmi_pd(domain);
 28	const struct scmi_power_ops *ops = pd->handle->power_ops;
 29
 30	if (power_on)
 31		state = SCMI_POWER_STATE_GENERIC_ON;
 32	else
 33		state = SCMI_POWER_STATE_GENERIC_OFF;
 34
 35	ret = ops->state_set(pd->handle, pd->domain, state);
 36	if (!ret)
 37		ret = ops->state_get(pd->handle, pd->domain, &ret_state);
 38	if (!ret && state != ret_state)
 39		return -EIO;
 40
 41	return ret;
 42}
 43
 44static int scmi_pd_power_on(struct generic_pm_domain *domain)
 45{
 46	return scmi_pd_power(domain, true);
 47}
 48
 49static int scmi_pd_power_off(struct generic_pm_domain *domain)
 50{
 51	return scmi_pd_power(domain, false);
 52}
 53
 54static int scmi_pm_domain_probe(struct scmi_device *sdev)
 55{
 56	int num_domains, i;
 57	struct device *dev = &sdev->dev;
 58	struct device_node *np = dev->of_node;
 59	struct scmi_pm_domain *scmi_pd;
 60	struct genpd_onecell_data *scmi_pd_data;
 61	struct generic_pm_domain **domains;
 62	const struct scmi_handle *handle = sdev->handle;
 63
 64	if (!handle || !handle->power_ops)
 65		return -ENODEV;
 66
 67	num_domains = handle->power_ops->num_domains_get(handle);
 68	if (num_domains < 0) {
 69		dev_err(dev, "number of domains not found\n");
 70		return num_domains;
 71	}
 72
 73	scmi_pd = devm_kcalloc(dev, num_domains, sizeof(*scmi_pd), GFP_KERNEL);
 74	if (!scmi_pd)
 75		return -ENOMEM;
 76
 77	scmi_pd_data = devm_kzalloc(dev, sizeof(*scmi_pd_data), GFP_KERNEL);
 78	if (!scmi_pd_data)
 79		return -ENOMEM;
 80
 81	domains = devm_kcalloc(dev, num_domains, sizeof(*domains), GFP_KERNEL);
 82	if (!domains)
 83		return -ENOMEM;
 84
 85	for (i = 0; i < num_domains; i++, scmi_pd++) {
 86		u32 state;
 87
 88		if (handle->power_ops->state_get(handle, i, &state)) {
 89			dev_warn(dev, "failed to get state for domain %d\n", i);
 90			continue;
 91		}
 92
 93		scmi_pd->domain = i;
 94		scmi_pd->handle = handle;
 95		scmi_pd->name = handle->power_ops->name_get(handle, i);
 96		scmi_pd->genpd.name = scmi_pd->name;
 97		scmi_pd->genpd.power_off = scmi_pd_power_off;
 98		scmi_pd->genpd.power_on = scmi_pd_power_on;
 99
 
 
 
 
 
100		pm_genpd_init(&scmi_pd->genpd, NULL,
101			      state == SCMI_POWER_STATE_GENERIC_OFF);
102
103		domains[i] = &scmi_pd->genpd;
104	}
105
106	scmi_pd_data->domains = domains;
107	scmi_pd_data->num_domains = num_domains;
108
109	of_genpd_add_provider_onecell(np, scmi_pd_data);
110
111	return 0;
112}
113
114static const struct scmi_device_id scmi_id_table[] = {
115	{ SCMI_PROTOCOL_POWER, "genpd" },
116	{ },
117};
118MODULE_DEVICE_TABLE(scmi, scmi_id_table);
119
120static struct scmi_driver scmi_power_domain_driver = {
121	.name = "scmi-power-domain",
122	.probe = scmi_pm_domain_probe,
123	.id_table = scmi_id_table,
124};
125module_scmi_driver(scmi_power_domain_driver);
126
127MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
128MODULE_DESCRIPTION("ARM SCMI power domain driver");
129MODULE_LICENSE("GPL v2");
v4.17
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * SCMI Generic power domain support.
  4 *
  5 * Copyright (C) 2018 ARM Ltd.
  6 */
  7
  8#include <linux/err.h>
  9#include <linux/io.h>
 10#include <linux/module.h>
 11#include <linux/pm_domain.h>
 12#include <linux/scmi_protocol.h>
 13
 14struct scmi_pm_domain {
 15	struct generic_pm_domain genpd;
 16	const struct scmi_handle *handle;
 17	const char *name;
 18	u32 domain;
 19};
 20
 21#define to_scmi_pd(gpd) container_of(gpd, struct scmi_pm_domain, genpd)
 22
 23static int scmi_pd_power(struct generic_pm_domain *domain, bool power_on)
 24{
 25	int ret;
 26	u32 state, ret_state;
 27	struct scmi_pm_domain *pd = to_scmi_pd(domain);
 28	const struct scmi_power_ops *ops = pd->handle->power_ops;
 29
 30	if (power_on)
 31		state = SCMI_POWER_STATE_GENERIC_ON;
 32	else
 33		state = SCMI_POWER_STATE_GENERIC_OFF;
 34
 35	ret = ops->state_set(pd->handle, pd->domain, state);
 36	if (!ret)
 37		ret = ops->state_get(pd->handle, pd->domain, &ret_state);
 38	if (!ret && state != ret_state)
 39		return -EIO;
 40
 41	return ret;
 42}
 43
 44static int scmi_pd_power_on(struct generic_pm_domain *domain)
 45{
 46	return scmi_pd_power(domain, true);
 47}
 48
 49static int scmi_pd_power_off(struct generic_pm_domain *domain)
 50{
 51	return scmi_pd_power(domain, false);
 52}
 53
 54static int scmi_pm_domain_probe(struct scmi_device *sdev)
 55{
 56	int num_domains, i;
 57	struct device *dev = &sdev->dev;
 58	struct device_node *np = dev->of_node;
 59	struct scmi_pm_domain *scmi_pd;
 60	struct genpd_onecell_data *scmi_pd_data;
 61	struct generic_pm_domain **domains;
 62	const struct scmi_handle *handle = sdev->handle;
 63
 64	if (!handle || !handle->power_ops)
 65		return -ENODEV;
 66
 67	num_domains = handle->power_ops->num_domains_get(handle);
 68	if (num_domains < 0) {
 69		dev_err(dev, "number of domains not found\n");
 70		return num_domains;
 71	}
 72
 73	scmi_pd = devm_kcalloc(dev, num_domains, sizeof(*scmi_pd), GFP_KERNEL);
 74	if (!scmi_pd)
 75		return -ENOMEM;
 76
 77	scmi_pd_data = devm_kzalloc(dev, sizeof(*scmi_pd_data), GFP_KERNEL);
 78	if (!scmi_pd_data)
 79		return -ENOMEM;
 80
 81	domains = devm_kcalloc(dev, num_domains, sizeof(*domains), GFP_KERNEL);
 82	if (!domains)
 83		return -ENOMEM;
 84
 85	for (i = 0; i < num_domains; i++, scmi_pd++) {
 86		u32 state;
 87
 88		domains[i] = &scmi_pd->genpd;
 
 
 
 89
 90		scmi_pd->domain = i;
 91		scmi_pd->handle = handle;
 92		scmi_pd->name = handle->power_ops->name_get(handle, i);
 93		scmi_pd->genpd.name = scmi_pd->name;
 94		scmi_pd->genpd.power_off = scmi_pd_power_off;
 95		scmi_pd->genpd.power_on = scmi_pd_power_on;
 96
 97		if (handle->power_ops->state_get(handle, i, &state)) {
 98			dev_warn(dev, "failed to get state for domain %d\n", i);
 99			continue;
100		}
101
102		pm_genpd_init(&scmi_pd->genpd, NULL,
103			      state == SCMI_POWER_STATE_GENERIC_OFF);
 
 
104	}
105
106	scmi_pd_data->domains = domains;
107	scmi_pd_data->num_domains = num_domains;
108
109	of_genpd_add_provider_onecell(np, scmi_pd_data);
110
111	return 0;
112}
113
114static const struct scmi_device_id scmi_id_table[] = {
115	{ SCMI_PROTOCOL_POWER },
116	{ },
117};
118MODULE_DEVICE_TABLE(scmi, scmi_id_table);
119
120static struct scmi_driver scmi_power_domain_driver = {
121	.name = "scmi-power-domain",
122	.probe = scmi_pm_domain_probe,
123	.id_table = scmi_id_table,
124};
125module_scmi_driver(scmi_power_domain_driver);
126
127MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
128MODULE_DESCRIPTION("ARM SCMI power domain driver");
129MODULE_LICENSE("GPL v2");