// SPDX-License-Identifier: GPL-2.0-only
/*
 * TI SCI Generic Power Domain Driver
 *
 * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/
 *	J Keerthy <j-keerthy@ti.com>
 *	Dave Gerlach <d-gerlach@ti.com>
 */

#include <linux/err.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/slab.h>
#include <linux/soc/ti/ti_sci_protocol.h>
#include <dt-bindings/soc/ti,sci_pm_domain.h>

/**
 * struct ti_sci_genpd_provider: holds common TI SCI genpd provider data
 * @ti_sci: handle to TI SCI protocol driver that provides ops to
 *	    communicate with system control processor.
 * @dev: pointer to dev for the driver for devm allocs
 * @pd_list: list of all the power domains on the device
 * @data: onecell data for genpd core
 */
struct ti_sci_genpd_provider {
	const struct ti_sci_handle *ti_sci;
	struct device *dev;
	struct list_head pd_list;
	struct genpd_onecell_data data;
};

/**
 * struct ti_sci_pm_domain: TI specific data needed for power domain
 * @idx: index of the device that identifies it with the system
 *	 control processor.
 * @exclusive: Permissions for exclusive request or shared request of the
 *	       device.
 * @pd: generic_pm_domain for use with the genpd framework
 * @node: link for the genpd list
 * @parent: link to the parent TI SCI genpd provider
 */
struct ti_sci_pm_domain {
	int idx;
	u8 exclusive;
	struct generic_pm_domain pd;
	struct list_head node;
	struct ti_sci_genpd_provider *parent;
};

#define genpd_to_ti_sci_pd(gpd) container_of(gpd, struct ti_sci_pm_domain, pd)

/*
 * ti_sci_pd_power_off(): genpd power down hook
 * @domain: pointer to the powerdomain to power off
 */
static int ti_sci_pd_power_off(struct generic_pm_domain *domain)
{
	struct ti_sci_pm_domain *pd = genpd_to_ti_sci_pd(domain);
	const struct ti_sci_handle *ti_sci = pd->parent->ti_sci;

	return ti_sci->ops.dev_ops.put_device(ti_sci, pd->idx);
}

/*
 * ti_sci_pd_power_on(): genpd power up hook
 * @domain: pointer to the powerdomain to power on
 */
static int ti_sci_pd_power_on(struct generic_pm_domain *domain)
{
	struct ti_sci_pm_domain *pd = genpd_to_ti_sci_pd(domain);
	const struct ti_sci_handle *ti_sci = pd->parent->ti_sci;

	if (pd->exclusive)
		return ti_sci->ops.dev_ops.get_device_exclusive(ti_sci,
								pd->idx);
	else
		return ti_sci->ops.dev_ops.get_device(ti_sci, pd->idx);
}

/*
 * ti_sci_pd_xlate(): translation service for TI SCI genpds
 * @genpdspec: DT identification data for the genpd
 * @data: genpd core data for all the powerdomains on the device
 */
static struct generic_pm_domain *ti_sci_pd_xlate(
					struct of_phandle_args *genpdspec,
					void *data)
{
	struct genpd_onecell_data *genpd_data = data;
	unsigned int idx = genpdspec->args[0];

	if (genpdspec->args_count < 2)
		return ERR_PTR(-EINVAL);

	if (idx >= genpd_data->num_domains) {
		pr_err("%s: invalid domain index %u\n", __func__, idx);
		return ERR_PTR(-EINVAL);
	}

	if (!genpd_data->domains[idx])
		return ERR_PTR(-ENOENT);

	genpd_to_ti_sci_pd(genpd_data->domains[idx])->exclusive =
		genpdspec->args[1];

	return genpd_data->domains[idx];
}

static const struct of_device_id ti_sci_pm_domain_matches[] = {
	{ .compatible = "ti,sci-pm-domain", },
	{ },
};
MODULE_DEVICE_TABLE(of, ti_sci_pm_domain_matches);

static int ti_sci_pm_domain_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct ti_sci_genpd_provider *pd_provider;
	struct ti_sci_pm_domain *pd;
	struct device_node *np = NULL;
	struct of_phandle_args args;
	int ret;
	u32 max_id = 0;
	int index;

	pd_provider = devm_kzalloc(dev, sizeof(*pd_provider), GFP_KERNEL);
	if (!pd_provider)
		return -ENOMEM;

	pd_provider->ti_sci = devm_ti_sci_get_handle(dev);
	if (IS_ERR(pd_provider->ti_sci))
		return PTR_ERR(pd_provider->ti_sci);

	pd_provider->dev = dev;

	INIT_LIST_HEAD(&pd_provider->pd_list);

	/* Find highest device ID used for power domains */
	while (1) {
		np = of_find_node_with_property(np, "power-domains");
		if (!np)
			break;

		index = 0;

		while (1) {
			ret = of_parse_phandle_with_args(np, "power-domains",
							 "#power-domain-cells",
							 index, &args);
			if (ret)
				break;

			if (args.args_count >= 1 && args.np == dev->of_node) {
				if (args.args[0] > max_id)
					max_id = args.args[0];

				pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
				if (!pd)
					return -ENOMEM;

				pd->pd.name = devm_kasprintf(dev, GFP_KERNEL,
							     "pd:%d",
							     args.args[0]);
				if (!pd->pd.name)
					return -ENOMEM;

				pd->pd.power_off = ti_sci_pd_power_off;
				pd->pd.power_on = ti_sci_pd_power_on;
				pd->idx = args.args[0];
				pd->parent = pd_provider;

				pm_genpd_init(&pd->pd, NULL, true);

				list_add(&pd->node, &pd_provider->pd_list);
			}
			index++;
		}
	}

	pd_provider->data.domains =
		devm_kcalloc(dev, max_id + 1,
			     sizeof(*pd_provider->data.domains),
			     GFP_KERNEL);

	pd_provider->data.num_domains = max_id + 1;
	pd_provider->data.xlate = ti_sci_pd_xlate;

	list_for_each_entry(pd, &pd_provider->pd_list, node)
		pd_provider->data.domains[pd->idx] = &pd->pd;

	return of_genpd_add_provider_onecell(dev->of_node, &pd_provider->data);
}

static struct platform_driver ti_sci_pm_domains_driver = {
	.probe = ti_sci_pm_domain_probe,
	.driver = {
		.name = "ti_sci_pm_domains",
		.of_match_table = ti_sci_pm_domain_matches,
	},
};
module_platform_driver(ti_sci_pm_domains_driver);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("TI System Control Interface (SCI) Power Domain driver");
MODULE_AUTHOR("Dave Gerlach");
