i.MX drivers change for 5.2:

- A series from Aisheng to generalize the SCU powerdomain driver
    for easier adding new SCU based platforms like imx8qm.
  - Add a generic i.MX8 SoC driver for reporting SoC and platform
    information.
  - Replace explicit polling loop with a call to regmap_read_poll_timeout()
    for gpcv2 driver to avoid code repetition.
  - Use devm_platform_ioremap_resource() to simplify gpc/gpcv2 driver
    code a bit.
  - Add general IRQ support for imx-scu driver, so that interrupt of
    device like RTC, thermal and watchdog can be handled.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJcvWKIAAoJEFBXWFqHsHzOeCQH/j/lgujJU9RnyY2CFTelMyad
 uTKEUgk2vvbswBdFMaS7xAvbni24GOxUdKUYJul0oz5jBnK4wKmf6VY7TYMQ8Qht
 hsdp0dsHHgI1qysOiOSxidhIN/2aXFl/hSoF8FT/9m0qXqnmvoHGFQT0YoMGwznS
 +7tHuUt5cjUG/r5DMM6GOzI/w6K1of6RGGsLWvYeuy7OeoDhI2Gl5gtK+qxik98J
 qC9UM64jO93rmXebJuG+9ZNJ0FFATrBMboMB3a7rA3t9RvkAFKEuVRp3USPuj1ek
 TxNusTtkQwCeujy9QZu/eB/oUrScEbzJuw+sp0l69C9T2D44ucZLFbHixnwbigM=
 =1wlN
 -----END PGP SIGNATURE-----

Merge tag 'imx-drivers-5.2' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux into arm/drivers

i.MX drivers change for 5.2:
 - A series from Aisheng to generalize the SCU powerdomain driver
   for easier adding new SCU based platforms like imx8qm.
 - Add a generic i.MX8 SoC driver for reporting SoC and platform
   information.
 - Replace explicit polling loop with a call to regmap_read_poll_timeout()
   for gpcv2 driver to avoid code repetition.
 - Use devm_platform_ioremap_resource() to simplify gpc/gpcv2 driver
   code a bit.
 - Add general IRQ support for imx-scu driver, so that interrupt of
   device like RTC, thermal and watchdog can be handled.

* tag 'imx-drivers-5.2' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux:
  soc: imx: Add generic i.MX8 SoC driver
  firmware: imx: enable imx scu general irq function
  soc: imx: gpcv2: use devm_platform_ioremap_resource() to simplify code
  soc: imx: gpc: use devm_platform_ioremap_resource() to simplify code
  firmware: imx: scu-pd: decouple the SS information from domain names
  firmware: imx: scu-pd: add specifying the base of domain name index support
  firmware: imx: scu-pd: use bool to set postfix
  soc: imx: gpcv2: Make use of regmap_read_poll_timeout()

Signed-off-by: Olof Johansson <[email protected]>
This commit is contained in:
Olof Johansson 2019-04-29 09:25:21 -07:00
commit f99552d9eb
9 changed files with 376 additions and 89 deletions

View file

@ -1,2 +1,3 @@
obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o
obj-$(CONFIG_ARCH_MXC) += soc-imx8.o

View file

@ -406,7 +406,6 @@ static int imx_gpc_probe(struct platform_device *pdev)
const struct imx_gpc_dt_data *of_id_data = of_id->data;
struct device_node *pgc_node;
struct regmap *regmap;
struct resource *res;
void __iomem *base;
int ret;
@ -417,8 +416,7 @@ static int imx_gpc_probe(struct platform_device *pdev)
!pgc_node)
return 0;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);

View file

@ -136,8 +136,8 @@ static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd,
GPC_PU_PGC_SW_PUP_REQ : GPC_PU_PGC_SW_PDN_REQ;
const bool enable_power_control = !on;
const bool has_regulator = !IS_ERR(domain->regulator);
unsigned long deadline;
int i, ret = 0;
u32 pxx_req;
regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
domain->bits.map, domain->bits.map);
@ -169,30 +169,19 @@ static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd,
* As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
* for PUP_REQ/PDN_REQ bit to be cleared
*/
deadline = jiffies + msecs_to_jiffies(1);
while (true) {
u32 pxx_req;
regmap_read(domain->regmap, offset, &pxx_req);
if (!(pxx_req & domain->bits.pxx))
break;
if (time_after(jiffies, deadline)) {
dev_err(domain->dev, "falied to command PGC\n");
ret = -ETIMEDOUT;
/*
* If we were in a process of enabling a
* domain and failed we might as well disable
* the regulator we just enabled. And if it
* was the opposite situation and we failed to
* power down -- keep the regulator on
*/
on = !on;
break;
}
cpu_relax();
ret = regmap_read_poll_timeout(domain->regmap, offset, pxx_req,
!(pxx_req & domain->bits.pxx),
0, USEC_PER_MSEC);
if (ret) {
dev_err(domain->dev, "failed to command PGC\n");
/*
* If we were in a process of enabling a
* domain and failed we might as well disable
* the regulator we just enabled. And if it
* was the opposite situation and we failed to
* power down -- keep the regulator on
*/
on = !on;
}
if (enable_power_control)
@ -574,7 +563,6 @@ static int imx_gpcv2_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *pgc_np, *np;
struct regmap *regmap;
struct resource *res;
void __iomem *base;
int ret;
@ -584,8 +572,7 @@ static int imx_gpcv2_probe(struct platform_device *pdev)
return -EINVAL;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(dev, res);
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);

115
drivers/soc/imx/soc-imx8.c Normal file
View file

@ -0,0 +1,115 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2019 NXP.
*/
#include <linux/init.h>
#include <linux/io.h>
#include <linux/of_address.h>
#include <linux/slab.h>
#include <linux/sys_soc.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#define REV_B1 0x21
#define IMX8MQ_SW_INFO_B1 0x40
#define IMX8MQ_SW_MAGIC_B1 0xff0055aa
struct imx8_soc_data {
char *name;
u32 (*soc_revision)(void);
};
static u32 __init imx8mq_soc_revision(void)
{
struct device_node *np;
void __iomem *ocotp_base;
u32 magic;
u32 rev = 0;
np = of_find_compatible_node(NULL, NULL, "fsl,imx8mq-ocotp");
if (!np)
goto out;
ocotp_base = of_iomap(np, 0);
WARN_ON(!ocotp_base);
magic = readl_relaxed(ocotp_base + IMX8MQ_SW_INFO_B1);
if (magic == IMX8MQ_SW_MAGIC_B1)
rev = REV_B1;
iounmap(ocotp_base);
out:
of_node_put(np);
return rev;
}
static const struct imx8_soc_data imx8mq_soc_data = {
.name = "i.MX8MQ",
.soc_revision = imx8mq_soc_revision,
};
static const struct of_device_id imx8_soc_match[] = {
{ .compatible = "fsl,imx8mq", .data = &imx8mq_soc_data, },
{ }
};
#define imx8_revision(soc_rev) \
soc_rev ? \
kasprintf(GFP_KERNEL, "%d.%d", (soc_rev >> 4) & 0xf, soc_rev & 0xf) : \
"unknown"
static int __init imx8_soc_init(void)
{
struct soc_device_attribute *soc_dev_attr;
struct soc_device *soc_dev;
struct device_node *root;
const struct of_device_id *id;
u32 soc_rev = 0;
const struct imx8_soc_data *data;
int ret;
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
if (!soc_dev_attr)
return -ENODEV;
soc_dev_attr->family = "Freescale i.MX";
root = of_find_node_by_path("/");
ret = of_property_read_string(root, "model", &soc_dev_attr->machine);
if (ret)
goto free_soc;
id = of_match_node(imx8_soc_match, root);
if (!id)
goto free_soc;
of_node_put(root);
data = id->data;
if (data) {
soc_dev_attr->soc_id = data->name;
if (data->soc_revision)
soc_rev = data->soc_revision();
}
soc_dev_attr->revision = imx8_revision(soc_rev);
if (!soc_dev_attr->revision)
goto free_soc;
soc_dev = soc_device_register(soc_dev_attr);
if (IS_ERR(soc_dev))
goto free_rev;
return 0;
free_rev:
kfree(soc_dev_attr->revision);
free_soc:
kfree(soc_dev_attr);
of_node_put(root);
return -ENODEV;
}
device_initcall(imx8_soc_init);