From fd362baad2e659ef0fb5652f023a606b248f1781 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 14 Aug 2022 23:12:40 -0500 Subject: [PATCH 1/8] soc: sunxi: sram: Actually claim SRAM regions sunxi_sram_claim() checks the sram_desc->claimed flag before updating the register, with the intent that only one device can claim a region. However, this was ineffective because the flag was never set. Fixes: 4af34b572a85 ("drivers: soc: sunxi: Introduce SoC driver to map SRAMs") Reviewed-by: Jernej Skrabec Signed-off-by: Samuel Holland Reviewed-by: Heiko Stuebner Tested-by: Heiko Stuebner Signed-off-by: Jernej Skrabec Link: https://lore.kernel.org/r/20220815041248.53268-4-samuel@sholland.org --- drivers/soc/sunxi/sunxi_sram.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index a8f3876963a0..f3d3f9259df9 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -254,6 +254,7 @@ int sunxi_sram_claim(struct device *dev) writel(val | ((device << sram_data->offset) & mask), base + sram_data->reg); + sram_desc->claimed = true; spin_unlock(&sram_lock); return 0; From 90e10a1fcd9b24b4ba8c0d35136127473dcd829e Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 14 Aug 2022 23:12:41 -0500 Subject: [PATCH 2/8] soc: sunxi: sram: Prevent the driver from being unbound This driver exports a regmap tied to the platform device (as opposed to a syscon, which exports a regmap tied to the OF node). Because of this, the driver can never be unbound, as that would destroy the regmap. Use builtin_platform_driver_probe() to enforce this limitation. Fixes: 5828729bebbb ("soc: sunxi: export a regmap for EMAC clock reg on A64") Reviewed-by: Jernej Skrabec Signed-off-by: Samuel Holland Reviewed-by: Heiko Stuebner Tested-by: Heiko Stuebner Signed-off-by: Jernej Skrabec Link: https://lore.kernel.org/r/20220815041248.53268-5-samuel@sholland.org --- drivers/soc/sunxi/sunxi_sram.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index f3d3f9259df9..a858a37fcdd4 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -330,7 +330,7 @@ static struct regmap_config sunxi_sram_emac_clock_regmap = { .writeable_reg = sunxi_sram_regmap_accessible_reg, }; -static int sunxi_sram_probe(struct platform_device *pdev) +static int __init sunxi_sram_probe(struct platform_device *pdev) { struct dentry *d; struct regmap *emac_clock; @@ -410,9 +410,8 @@ static struct platform_driver sunxi_sram_driver = { .name = "sunxi-sram", .of_match_table = sunxi_sram_dt_match, }, - .probe = sunxi_sram_probe, }; -module_platform_driver(sunxi_sram_driver); +builtin_platform_driver_probe(sunxi_sram_driver, sunxi_sram_probe); MODULE_AUTHOR("Maxime Ripard "); MODULE_DESCRIPTION("Allwinner sunXi SRAM Controller Driver"); From 49fad91a7b8941979c3e9a35f9894ac45bc5d3d6 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 14 Aug 2022 23:12:42 -0500 Subject: [PATCH 3/8] soc: sunxi: sram: Fix probe function ordering issues Errors from debugfs are intended to be non-fatal, and should not prevent the driver from probing. Since debugfs file creation is treated as infallible, move it below the parts of the probe function that can fail. This prevents an error elsewhere in the probe function from causing the file to leak. Do the same for the call to of_platform_populate(). Finally, checkpatch suggests an octal literal for the file permissions. Fixes: 4af34b572a85 ("drivers: soc: sunxi: Introduce SoC driver to map SRAMs") Fixes: 5828729bebbb ("soc: sunxi: export a regmap for EMAC clock reg on A64") Reviewed-by: Jernej Skrabec Signed-off-by: Samuel Holland Tested-by: Heiko Stuebner Signed-off-by: Jernej Skrabec Link: https://lore.kernel.org/r/20220815041248.53268-6-samuel@sholland.org --- drivers/soc/sunxi/sunxi_sram.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index a858a37fcdd4..52d07bed7664 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -332,9 +332,9 @@ static struct regmap_config sunxi_sram_emac_clock_regmap = { static int __init sunxi_sram_probe(struct platform_device *pdev) { - struct dentry *d; struct regmap *emac_clock; const struct sunxi_sramc_variant *variant; + struct device *dev = &pdev->dev; sram_dev = &pdev->dev; @@ -346,13 +346,6 @@ static int __init sunxi_sram_probe(struct platform_device *pdev) if (IS_ERR(base)) return PTR_ERR(base); - of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); - - d = debugfs_create_file("sram", S_IRUGO, NULL, NULL, - &sunxi_sram_fops); - if (!d) - return -ENOMEM; - if (variant->num_emac_clocks > 0) { emac_clock = devm_regmap_init_mmio(&pdev->dev, base, &sunxi_sram_emac_clock_regmap); @@ -361,6 +354,10 @@ static int __init sunxi_sram_probe(struct platform_device *pdev) return PTR_ERR(emac_clock); } + of_platform_populate(dev->of_node, NULL, NULL, dev); + + debugfs_create_file("sram", 0444, NULL, NULL, &sunxi_sram_fops); + return 0; } From e3c95edb1bd8b9c2cb0caa6ae382fc8080f6a0ed Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 14 Aug 2022 23:12:43 -0500 Subject: [PATCH 4/8] soc: sunxi: sram: Fix debugfs info for A64 SRAM C The labels were backward with respect to the register values. The SRAM is mapped to the CPU when the register value is 1. Fixes: 5e4fb6429761 ("drivers: soc: sunxi: add support for A64 and its SRAM C") Acked-by: Jernej Skrabec Signed-off-by: Samuel Holland Signed-off-by: Jernej Skrabec Link: https://lore.kernel.org/r/20220815041248.53268-7-samuel@sholland.org --- drivers/soc/sunxi/sunxi_sram.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index 52d07bed7664..09754cd1d57d 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -78,8 +78,8 @@ static struct sunxi_sram_desc sun4i_a10_sram_d = { static struct sunxi_sram_desc sun50i_a64_sram_c = { .data = SUNXI_SRAM_DATA("C", 0x4, 24, 1, - SUNXI_SRAM_MAP(0, 1, "cpu"), - SUNXI_SRAM_MAP(1, 0, "de2")), + SUNXI_SRAM_MAP(1, 0, "cpu"), + SUNXI_SRAM_MAP(0, 1, "de2")), }; static const struct of_device_id sunxi_sram_dt_ids[] = { From 460d9cb62f7fe82cc835d6b3924a8d06fd2d510a Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 14 Aug 2022 23:12:44 -0500 Subject: [PATCH 5/8] soc: sunxi: sram: Return void from the release function There is no point in returning an error here, as the caller can do nothing about it. In fact, all callers already ignore the return value. Acked-by: Jernej Skrabec Signed-off-by: Samuel Holland Reviewed-by: Heiko Stuebner Tested-by: Heiko Stuebner Link: https://lore.kernel.org/r/20220815041248.53268-8-samuel@sholland.org Signed-off-by: Jernej Skrabec --- drivers/soc/sunxi/sunxi_sram.c | 8 +++----- include/linux/soc/sunxi/sunxi_sram.h | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index 09754cd1d57d..9622fd45f5e5 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -261,25 +261,23 @@ int sunxi_sram_claim(struct device *dev) } EXPORT_SYMBOL(sunxi_sram_claim); -int sunxi_sram_release(struct device *dev) +void sunxi_sram_release(struct device *dev) { const struct sunxi_sram_data *sram_data; struct sunxi_sram_desc *sram_desc; if (!dev || !dev->of_node) - return -EINVAL; + return; sram_data = sunxi_sram_of_parse(dev->of_node, NULL); if (IS_ERR(sram_data)) - return -EINVAL; + return; sram_desc = to_sram_desc(sram_data); spin_lock(&sram_lock); sram_desc->claimed = false; spin_unlock(&sram_lock); - - return 0; } EXPORT_SYMBOL(sunxi_sram_release); diff --git a/include/linux/soc/sunxi/sunxi_sram.h b/include/linux/soc/sunxi/sunxi_sram.h index c5f663bba9c2..60e274d1b821 100644 --- a/include/linux/soc/sunxi/sunxi_sram.h +++ b/include/linux/soc/sunxi/sunxi_sram.h @@ -14,6 +14,6 @@ #define _SUNXI_SRAM_H_ int sunxi_sram_claim(struct device *dev); -int sunxi_sram_release(struct device *dev); +void sunxi_sram_release(struct device *dev); #endif /* _SUNXI_SRAM_H_ */ From ee07b9056e3e7cac6d13e0177b6c8cd9ce8a9c5f Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 14 Aug 2022 23:12:45 -0500 Subject: [PATCH 6/8] soc: sunxi: sram: Save a pointer to the OF match data It is inefficient to match the compatible string every time the regmap is accessed. Acked-by: Jernej Skrabec Signed-off-by: Samuel Holland Reviewed-by: Heiko Stuebner Tested-by: Heiko Stuebner Link: https://lore.kernel.org/r/20220815041248.53268-9-samuel@sholland.org Signed-off-by: Jernej Skrabec --- drivers/soc/sunxi/sunxi_sram.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index 9622fd45f5e5..7c6fb17cfe7f 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -305,9 +305,7 @@ static const struct sunxi_sramc_variant sun50i_h616_sramc_variant = { static bool sunxi_sram_regmap_accessible_reg(struct device *dev, unsigned int reg) { - const struct sunxi_sramc_variant *variant; - - variant = of_device_get_match_data(dev); + const struct sunxi_sramc_variant *variant = dev_get_drvdata(dev); if (reg < SUNXI_SRAM_EMAC_CLOCK_REG) return false; @@ -340,6 +338,8 @@ static int __init sunxi_sram_probe(struct platform_device *pdev) if (!variant) return -EINVAL; + dev_set_drvdata(dev, (struct sunxi_sramc_variant *)variant); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); From dd2ae2ecb0b98c7b196fc44ad07010093b7cd3cc Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 14 Aug 2022 23:12:46 -0500 Subject: [PATCH 7/8] soc: sunxi: sram: Export the LDO control register Some newer Allwinner SoCs contain internal LDOs managed by a register in the system control MMIO space. Export this from the regmap in addtion to the EMAC register. Use generic names now that the regmap is no longer EMAC-specific. Acked-by: Jernej Skrabec Signed-off-by: Samuel Holland Reviewed-by: Heiko Stuebner Tested-by: Heiko Stuebner Link: https://lore.kernel.org/r/20220815041248.53268-10-samuel@sholland.org Signed-off-by: Jernej Skrabec --- drivers/soc/sunxi/sunxi_sram.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index 7c6fb17cfe7f..7e8dab0f0ec4 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -283,6 +283,7 @@ EXPORT_SYMBOL(sunxi_sram_release); struct sunxi_sramc_variant { int num_emac_clocks; + bool has_ldo_ctrl; }; static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = { @@ -302,25 +303,28 @@ static const struct sunxi_sramc_variant sun50i_h616_sramc_variant = { }; #define SUNXI_SRAM_EMAC_CLOCK_REG 0x30 +#define SUNXI_SYS_LDO_CTRL_REG 0x150 + static bool sunxi_sram_regmap_accessible_reg(struct device *dev, unsigned int reg) { const struct sunxi_sramc_variant *variant = dev_get_drvdata(dev); - if (reg < SUNXI_SRAM_EMAC_CLOCK_REG) - return false; - if (reg > SUNXI_SRAM_EMAC_CLOCK_REG + variant->num_emac_clocks * 4) - return false; + if (reg >= SUNXI_SRAM_EMAC_CLOCK_REG && + reg < SUNXI_SRAM_EMAC_CLOCK_REG + variant->num_emac_clocks * 4) + return true; + if (reg == SUNXI_SYS_LDO_CTRL_REG && variant->has_ldo_ctrl) + return true; - return true; + return false; } -static struct regmap_config sunxi_sram_emac_clock_regmap = { +static struct regmap_config sunxi_sram_regmap_config = { .reg_bits = 32, .val_bits = 32, .reg_stride = 4, /* last defined register */ - .max_register = SUNXI_SRAM_EMAC_CLOCK_REG + 4, + .max_register = SUNXI_SYS_LDO_CTRL_REG, /* other devices have no business accessing other registers */ .readable_reg = sunxi_sram_regmap_accessible_reg, .writeable_reg = sunxi_sram_regmap_accessible_reg, @@ -328,9 +332,9 @@ static struct regmap_config sunxi_sram_emac_clock_regmap = { static int __init sunxi_sram_probe(struct platform_device *pdev) { - struct regmap *emac_clock; const struct sunxi_sramc_variant *variant; struct device *dev = &pdev->dev; + struct regmap *regmap; sram_dev = &pdev->dev; @@ -344,12 +348,10 @@ static int __init sunxi_sram_probe(struct platform_device *pdev) if (IS_ERR(base)) return PTR_ERR(base); - if (variant->num_emac_clocks > 0) { - emac_clock = devm_regmap_init_mmio(&pdev->dev, base, - &sunxi_sram_emac_clock_regmap); - - if (IS_ERR(emac_clock)) - return PTR_ERR(emac_clock); + if (variant->num_emac_clocks || variant->has_ldo_ctrl) { + regmap = devm_regmap_init_mmio(dev, base, &sunxi_sram_regmap_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); } of_platform_populate(dev->of_node, NULL, NULL, dev); From 1f698cb11dd48ec5c430886f794953878e1ff016 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 14 Aug 2022 23:12:47 -0500 Subject: [PATCH 8/8] soc: sunxi: sram: Add support for the D1 system control D1 has a single EMAC and some LDOs that need to be exported. Acked-by: Jernej Skrabec Signed-off-by: Samuel Holland Reviewed-by: Heiko Stuebner Tested-by: Heiko Stuebner Link: https://lore.kernel.org/r/20220815041248.53268-11-samuel@sholland.org Signed-off-by: Jernej Skrabec --- drivers/soc/sunxi/sunxi_sram.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index 7e8dab0f0ec4..92f9186c1c42 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -294,6 +294,11 @@ static const struct sunxi_sramc_variant sun8i_h3_sramc_variant = { .num_emac_clocks = 1, }; +static const struct sunxi_sramc_variant sun20i_d1_sramc_variant = { + .num_emac_clocks = 1, + .has_ldo_ctrl = true, +}; + static const struct sunxi_sramc_variant sun50i_a64_sramc_variant = { .num_emac_clocks = 1, }; @@ -382,6 +387,10 @@ static const struct of_device_id sunxi_sram_dt_match[] = { .compatible = "allwinner,sun8i-h3-system-control", .data = &sun8i_h3_sramc_variant, }, + { + .compatible = "allwinner,sun20i-d1-system-control", + .data = &sun20i_d1_sramc_variant, + }, { .compatible = "allwinner,sun50i-a64-sram-controller", .data = &sun50i_a64_sramc_variant,