MLK-15149-01 driver: soc: add gpc power domain support on i.mx8mq
Add generic power domain driver support on i.mx8mq. The power domain on/off operations need to use the SIP service call to trap into secure monitor to handle it. Signed-off-by: Bai Ping <ping.bai@nxp.com>pull/10/head
parent
7f5a18458a
commit
eda7bfe5f4
|
@ -20,50 +20,62 @@
|
|||
#include <linux/irq.h>
|
||||
#include <linux/irqchip.h>
|
||||
#include <linux/irqchip/arm-gic.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <soc/imx/fsl_sip.h>
|
||||
|
||||
#define GPC_MAX_IRQS (4 * 32)
|
||||
|
||||
struct imx_gpc_pm_domain {
|
||||
char name[30];
|
||||
struct generic_pm_domain pd;
|
||||
u32 gpc_domain_id;
|
||||
};
|
||||
|
||||
enum imx_gpc_pm_domain_state {
|
||||
GPC_PD_STATE_OFF,
|
||||
GPC_PD_STATE_ON,
|
||||
};
|
||||
|
||||
#define to_imx_gpc_pm_domain(_genpd) container_of(_genpd, struct imx_gpc_pm_domain, pd)
|
||||
|
||||
static DEFINE_SPINLOCK(gpc_psci_lock);
|
||||
|
||||
static void imx_gpc_psci_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct arm_smccc_res res;
|
||||
|
||||
spin_lock_irqsave(&gpc_psci_lock, flags);
|
||||
spin_lock(&gpc_psci_lock);
|
||||
arm_smccc_smc(FSL_SIP_GPC, FSL_SIP_CONFIG_GPC_UNMASK, d->hwirq,
|
||||
0, 0, 0, 0, 0, &res);
|
||||
spin_unlock_irqrestore(&gpc_psci_lock, flags);
|
||||
spin_unlock(&gpc_psci_lock);
|
||||
|
||||
irq_chip_unmask_parent(d);
|
||||
}
|
||||
|
||||
static void imx_gpc_psci_irq_mask(struct irq_data *d)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct arm_smccc_res res;
|
||||
|
||||
spin_lock_irqsave(&gpc_psci_lock, flags);
|
||||
spin_lock(&gpc_psci_lock);
|
||||
arm_smccc_smc(FSL_SIP_GPC, FSL_SIP_CONFIG_GPC_MASK, d->hwirq,
|
||||
0, 0, 0, 0, 0, &res);
|
||||
spin_unlock_irqrestore(&gpc_psci_lock, flags);
|
||||
spin_unlock(&gpc_psci_lock);
|
||||
|
||||
irq_chip_mask_parent(d);
|
||||
}
|
||||
static int imx_gpc_psci_irq_set_wake(struct irq_data *d, unsigned int on)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct arm_smccc_res res;
|
||||
|
||||
spin_lock_irqsave(&gpc_psci_lock, flags);
|
||||
spin_lock(&gpc_psci_lock);
|
||||
arm_smccc_smc(FSL_SIP_GPC, FSL_SIP_CONFIG_GPC_SET_WAKE, d->hwirq,
|
||||
on, 0, 0, 0, 0, &res);
|
||||
spin_unlock_irqrestore(&gpc_psci_lock, flags);
|
||||
spin_unlock(&gpc_psci_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -161,3 +173,102 @@ static int __init imx_gpc_psci_init(struct device_node *node,
|
|||
return 0;
|
||||
}
|
||||
IRQCHIP_DECLARE(imx_gpc_psci, "fsl,imx8mq-gpc", imx_gpc_psci_init);
|
||||
|
||||
static int imx_gpc_pd_power_on(struct generic_pm_domain *domain)
|
||||
{
|
||||
struct imx_gpc_pm_domain *pd = to_imx_gpc_pm_domain(domain);
|
||||
struct arm_smccc_res res;
|
||||
|
||||
spin_lock(&gpc_psci_lock);
|
||||
arm_smccc_smc(FSL_SIP_GPC, FSL_SIP_CONFIG_GPC_PM_DOMAIN, pd->gpc_domain_id,
|
||||
GPC_PD_STATE_ON, 0, 0, 0, 0, &res);
|
||||
spin_unlock(&gpc_psci_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx_gpc_pd_power_off(struct generic_pm_domain *domain)
|
||||
{
|
||||
struct imx_gpc_pm_domain *pd = to_imx_gpc_pm_domain(domain);
|
||||
struct arm_smccc_res res;
|
||||
|
||||
spin_lock(&gpc_psci_lock);
|
||||
arm_smccc_smc(FSL_SIP_GPC, FSL_SIP_CONFIG_GPC_PM_DOMAIN, pd->gpc_domain_id,
|
||||
GPC_PD_STATE_OFF, 0, 0, 0, 0, &res);
|
||||
spin_unlock(&gpc_psci_lock);
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
static int imx_gpc_pm_domain_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct imx_gpc_pm_domain *imx_pm_domain;
|
||||
struct genpd_onecell_data *imx_pd_data;
|
||||
struct generic_pm_domain **domains;
|
||||
int ret, num_domains, i;
|
||||
|
||||
pr_info("imx8mq pm domain init\n");
|
||||
if (!np) {
|
||||
dev_err(dev, "device tree node not found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(np, "num-domains", &num_domains);
|
||||
if (ret) {
|
||||
dev_err(dev, "number of domains not found\n");
|
||||
return -EINVAL;
|
||||
};
|
||||
|
||||
imx_pm_domain = devm_kcalloc(dev, num_domains, sizeof(*imx_pm_domain), GFP_KERNEL);
|
||||
if (!imx_pm_domain)
|
||||
return -ENOMEM;
|
||||
|
||||
imx_pd_data = devm_kzalloc(dev, sizeof(*imx_pd_data), GFP_KERNEL);
|
||||
if (!imx_pd_data)
|
||||
return -ENOMEM;
|
||||
|
||||
domains = devm_kcalloc(dev, num_domains, sizeof(*domains), GFP_KERNEL);
|
||||
if (!domains)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < num_domains; i++, imx_pm_domain++) {
|
||||
domains[i] = &imx_pm_domain->pd;
|
||||
imx_pm_domain->gpc_domain_id = i;
|
||||
sprintf(imx_pm_domain->name, "%s.%d", np->name, i);
|
||||
imx_pm_domain->pd.name = imx_pm_domain->name;
|
||||
imx_pm_domain->pd.power_off = imx_gpc_pd_power_off;
|
||||
imx_pm_domain->pd.power_on = imx_gpc_pd_power_on;
|
||||
|
||||
/* all power domains as off at boot */
|
||||
pm_genpd_init(&imx_pm_domain->pd, NULL, true);
|
||||
}
|
||||
|
||||
imx_pd_data->domains = domains;
|
||||
imx_pd_data->num_domains = num_domains;
|
||||
|
||||
of_genpd_add_provider_onecell(np, imx_pd_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id imx_gpc_pm_domain_ids[] = {
|
||||
{.compatible = "fsl,imx8mq-pm-domain"},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver imx_gpc_pm_domain_driver = {
|
||||
.driver = {
|
||||
.name = "imx8m_gpc_pm_domain",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = imx_gpc_pm_domain_ids,
|
||||
},
|
||||
.probe = imx_gpc_pm_domain_probe,
|
||||
};
|
||||
|
||||
module_platform_driver(imx_gpc_pm_domain_driver);
|
||||
|
||||
MODULE_AUTHOR("NXP");
|
||||
MODULE_DESCRIPTION("NXP i.MX8M GPC power domain driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
@ -14,5 +14,6 @@
|
|||
#define FSL_SIP_CONFIG_GPC_MASK 0x00
|
||||
#define FSL_SIP_CONFIG_GPC_UNMASK 0x01
|
||||
#define FSL_SIP_CONFIG_GPC_SET_WAKE 0x02
|
||||
#define FSL_SIP_CONFIG_GPC_PM_DOMAIN 0x03
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue