Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

reset: mpfs: add non-auxiliary bus probing

While the auxiliary bus was a nice bandaid, and meant that re-writing
the representation of the clock regions in devicetree was not required,
it has run its course. The "mss_top_sysreg" region that contains the
clock and reset regions, also contains pinctrl and an interrupt
controller, so the time has come rewrite the devicetree and probe the
reset controller from an mfd devicetree node, rather than implement
those drivers using the auxiliary bus. Wanting to avoid propagating this
naive/incorrect description of the hardware to the new pic64gx SoC is a
major motivating factor here.

Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Conor Dooley <conor.dooley@microchip.com>

+60 -39
+2 -2
drivers/clk/microchip/clk-mpfs.c
··· 38 38 .reg_stride = 4, 39 39 .val_bits = 32, 40 40 .val_format_endian = REGMAP_ENDIAN_LITTLE, 41 - .max_register = REG_SUBBLK_CLOCK_CR, 41 + .max_register = REG_SUBBLK_RESET_CR, 42 42 }; 43 43 44 44 /* ··· 502 502 if (IS_ERR(clk_data->regmap)) 503 503 return PTR_ERR(clk_data->regmap); 504 504 505 - return mpfs_reset_controller_register(dev, clk_data->base + REG_SUBBLK_RESET_CR); 505 + return mpfs_reset_controller_register(dev, clk_data->regmap); 506 506 } 507 507 508 508 static int mpfs_clk_probe(struct platform_device *pdev)
+1
drivers/reset/Kconfig
··· 200 200 config RESET_POLARFIRE_SOC 201 201 bool "Microchip PolarFire SoC (MPFS) Reset Driver" 202 202 depends on MCHP_CLK_MPFS 203 + depends on MFD_SYSCON 203 204 select AUXILIARY_BUS 204 205 default MCHP_CLK_MPFS 205 206 help
+55 -36
drivers/reset/reset-mpfs.c
··· 9 9 #include <linux/auxiliary_bus.h> 10 10 #include <linux/delay.h> 11 11 #include <linux/io.h> 12 + #include <linux/mfd/syscon.h> 12 13 #include <linux/module.h> 13 14 #include <linux/of.h> 14 15 #include <linux/platform_device.h> 15 - #include <linux/slab.h> 16 + #include <linux/regmap.h> 16 17 #include <linux/reset-controller.h> 18 + #include <linux/slab.h> 17 19 #include <dt-bindings/clock/microchip,mpfs-clock.h> 18 20 #include <soc/microchip/mpfs.h> 19 21 ··· 29 27 #define MPFS_SLEEP_MIN_US 100 30 28 #define MPFS_SLEEP_MAX_US 200 31 29 32 - /* block concurrent access to the soft reset register */ 33 - static DEFINE_SPINLOCK(mpfs_reset_lock); 30 + #define REG_SUBBLK_RESET_CR 0x88u 34 31 35 32 struct mpfs_reset { 36 - void __iomem *base; 33 + struct regmap *regmap; 37 34 struct reset_controller_dev rcdev; 38 35 }; 39 36 ··· 47 46 static int mpfs_assert(struct reset_controller_dev *rcdev, unsigned long id) 48 47 { 49 48 struct mpfs_reset *rst = to_mpfs_reset(rcdev); 50 - unsigned long flags; 51 - u32 reg; 52 49 53 - spin_lock_irqsave(&mpfs_reset_lock, flags); 50 + return regmap_set_bits(rst->regmap, REG_SUBBLK_RESET_CR, BIT(id)); 54 51 55 - reg = readl(rst->base); 56 - reg |= BIT(id); 57 - writel(reg, rst->base); 58 - 59 - spin_unlock_irqrestore(&mpfs_reset_lock, flags); 60 - 61 - return 0; 62 52 } 63 53 64 54 static int mpfs_deassert(struct reset_controller_dev *rcdev, unsigned long id) 65 55 { 66 56 struct mpfs_reset *rst = to_mpfs_reset(rcdev); 67 - unsigned long flags; 68 - u32 reg; 69 57 70 - spin_lock_irqsave(&mpfs_reset_lock, flags); 58 + return regmap_clear_bits(rst->regmap, REG_SUBBLK_RESET_CR, BIT(id)); 71 59 72 - reg = readl(rst->base); 73 - reg &= ~BIT(id); 74 - writel(reg, rst->base); 75 - 76 - spin_unlock_irqrestore(&mpfs_reset_lock, flags); 77 - 78 - return 0; 79 60 } 80 61 81 62 static int mpfs_status(struct reset_controller_dev *rcdev, unsigned long id) 82 63 { 83 64 struct mpfs_reset *rst = to_mpfs_reset(rcdev); 84 - u32 reg = readl(rst->base); 65 + u32 reg; 66 + 67 + regmap_read(rst->regmap, REG_SUBBLK_RESET_CR, &reg); 85 68 86 69 /* 87 70 * It is safe to return here as MPFS_NUM_RESETS makes sure the sign bit ··· 115 130 return index - MPFS_PERIPH_OFFSET; 116 131 } 117 132 118 - static int mpfs_reset_probe(struct auxiliary_device *adev, 119 - const struct auxiliary_device_id *id) 133 + static int mpfs_reset_mfd_probe(struct platform_device *pdev) 120 134 { 121 - struct device *dev = &adev->dev; 122 135 struct reset_controller_dev *rcdev; 136 + struct device *dev = &pdev->dev; 123 137 struct mpfs_reset *rst; 124 138 125 139 rst = devm_kzalloc(dev, sizeof(*rst), GFP_KERNEL); 126 140 if (!rst) 127 141 return -ENOMEM; 128 142 129 - rst->base = (void __iomem *)adev->dev.platform_data; 143 + rcdev = &rst->rcdev; 144 + rcdev->dev = dev; 145 + rcdev->ops = &mpfs_reset_ops; 146 + 147 + rcdev->of_node = pdev->dev.parent->of_node; 148 + rcdev->of_reset_n_cells = 1; 149 + rcdev->of_xlate = mpfs_reset_xlate; 150 + rcdev->nr_resets = MPFS_NUM_RESETS; 151 + 152 + rst->regmap = device_node_to_regmap(pdev->dev.parent->of_node); 153 + if (IS_ERR(rst->regmap)) 154 + return dev_err_probe(dev, PTR_ERR(rst->regmap), 155 + "Failed to find syscon regmap\n"); 156 + 157 + return devm_reset_controller_register(dev, rcdev); 158 + } 159 + 160 + static struct platform_driver mpfs_reset_mfd_driver = { 161 + .probe = mpfs_reset_mfd_probe, 162 + .driver = { 163 + .name = "mpfs-reset", 164 + }, 165 + }; 166 + module_platform_driver(mpfs_reset_mfd_driver); 167 + 168 + static int mpfs_reset_adev_probe(struct auxiliary_device *adev, 169 + const struct auxiliary_device_id *id) 170 + { 171 + struct reset_controller_dev *rcdev; 172 + struct device *dev = &adev->dev; 173 + struct mpfs_reset *rst; 174 + 175 + rst = devm_kzalloc(dev, sizeof(*rst), GFP_KERNEL); 176 + if (!rst) 177 + return -ENOMEM; 178 + 179 + rst->regmap = (struct regmap *)adev->dev.platform_data; 130 180 131 181 rcdev = &rst->rcdev; 132 182 rcdev->dev = dev; 133 - rcdev->dev->parent = dev->parent; 134 183 rcdev->ops = &mpfs_reset_ops; 184 + 135 185 rcdev->of_node = dev->parent->of_node; 136 186 rcdev->of_reset_n_cells = 1; 137 187 rcdev->of_xlate = mpfs_reset_xlate; ··· 175 155 return devm_reset_controller_register(dev, rcdev); 176 156 } 177 157 178 - int mpfs_reset_controller_register(struct device *clk_dev, void __iomem *base) 158 + int mpfs_reset_controller_register(struct device *clk_dev, struct regmap *map) 179 159 { 180 160 struct auxiliary_device *adev; 181 161 182 - adev = devm_auxiliary_device_create(clk_dev, "reset-mpfs", 183 - (__force void *)base); 162 + adev = devm_auxiliary_device_create(clk_dev, "reset-mpfs", (void *)map); 184 163 if (!adev) 185 164 return -ENODEV; 186 165 ··· 195 176 }; 196 177 MODULE_DEVICE_TABLE(auxiliary, mpfs_reset_ids); 197 178 198 - static struct auxiliary_driver mpfs_reset_driver = { 199 - .probe = mpfs_reset_probe, 179 + static struct auxiliary_driver mpfs_reset_aux_driver = { 180 + .probe = mpfs_reset_adev_probe, 200 181 .id_table = mpfs_reset_ids, 201 182 }; 202 183 203 - module_auxiliary_driver(mpfs_reset_driver); 184 + module_auxiliary_driver(mpfs_reset_aux_driver); 204 185 205 186 MODULE_DESCRIPTION("Microchip PolarFire SoC Reset Driver"); 206 187 MODULE_AUTHOR("Conor Dooley <conor.dooley@microchip.com>");
+2 -1
include/soc/microchip/mpfs.h
··· 14 14 15 15 #include <linux/types.h> 16 16 #include <linux/of_device.h> 17 + #include <linux/regmap.h> 17 18 18 19 struct mpfs_sys_controller; 19 20 ··· 45 44 46 45 #if IS_ENABLED(CONFIG_MCHP_CLK_MPFS) 47 46 #if IS_ENABLED(CONFIG_RESET_POLARFIRE_SOC) 48 - int mpfs_reset_controller_register(struct device *clk_dev, void __iomem *base); 47 + int mpfs_reset_controller_register(struct device *clk_dev, struct regmap *map); 49 48 #else 50 49 static inline int mpfs_reset_controller_register(struct device *clk_dev, void __iomem *base) { return 0; } 51 50 #endif /* if IS_ENABLED(CONFIG_RESET_POLARFIRE_SOC) */