diff options
Diffstat (limited to 'drivers/clk/microchip')
-rw-r--r-- | drivers/clk/microchip/Kconfig | 2 | ||||
-rw-r--r-- | drivers/clk/microchip/mpfs_clk.c | 63 | ||||
-rw-r--r-- | drivers/clk/microchip/mpfs_clk.h | 5 | ||||
-rw-r--r-- | drivers/clk/microchip/mpfs_clk_cfg.c | 16 | ||||
-rw-r--r-- | drivers/clk/microchip/mpfs_clk_periph.c | 37 |
5 files changed, 81 insertions, 42 deletions
diff --git a/drivers/clk/microchip/Kconfig b/drivers/clk/microchip/Kconfig index b70241559db..62072e100b1 100644 --- a/drivers/clk/microchip/Kconfig +++ b/drivers/clk/microchip/Kconfig @@ -1,5 +1,7 @@ config CLK_MPFS bool "Clock support for Microchip PolarFire SoC" depends on CLK && CLK_CCF + depends on SYSCON + depends on REGMAP help This enables support clock driver for Microchip PolarFire SoC platform. diff --git a/drivers/clk/microchip/mpfs_clk.c b/drivers/clk/microchip/mpfs_clk.c index 0a82777ff74..2c6694f0035 100644 --- a/drivers/clk/microchip/mpfs_clk.c +++ b/drivers/clk/microchip/mpfs_clk.c @@ -9,25 +9,39 @@ #include <log.h> #include <dm/device.h> #include <dm/devres.h> +#include <dm/ofnode.h> #include <dm/uclass.h> +#include <regmap.h> +#include <syscon.h> #include <dt-bindings/clock/microchip-mpfs-clock.h> #include <linux/err.h> #include "mpfs_clk.h" -static int mpfs_clk_probe(struct udevice *dev) +static int mpfs_clk_syscon_probe(struct udevice *dev, void __iomem **msspll_base, + struct regmap **regmap) { - struct clk *parent_clk = dev_get_priv(dev); - struct clk clk_msspll = { .id = CLK_MSSPLL }; - void __iomem *base; - void __iomem *msspll_base; - int ret; + ofnode node; - base = dev_read_addr_index_ptr(dev, 0); - if (!base) - return -EINVAL; + node = ofnode_by_compatible(ofnode_null(), "microchip,mpfs-mss-top-sysreg"); + if (!ofnode_valid(node)) + return -ENODEV; - ret = clk_get_by_index(dev, 0, parent_clk); + *regmap = syscon_node_to_regmap(node); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + *msspll_base = dev_read_addr_index_ptr(dev, 0); + + return 0; +} + +static int mpfs_clk_old_format_probe(struct udevice *dev, void __iomem **msspll_base, + struct regmap **regmap) +{ + int ret; + + ret = regmap_init_mem_index(dev_ofnode(dev), regmap, 0); if (ret) return ret; @@ -40,7 +54,30 @@ static int mpfs_clk_probe(struct udevice *dev) * Otherwise, skip registering it & pass the reference clock directly * to the cfg clock registration function. */ - msspll_base = dev_read_addr_index_ptr(dev, 1); + *msspll_base = dev_read_addr_index_ptr(dev, 1); + + return 0; +} + +static int mpfs_clk_probe(struct udevice *dev) +{ + struct clk *parent_clk = dev_get_priv(dev); + struct clk clk_msspll = { .id = CLK_MSSPLL }; + struct regmap *regmap; + void __iomem *msspll_base; + int ret; + + ret = clk_get_by_index(dev, 0, parent_clk); + if (ret) + return ret; + + ret = mpfs_clk_syscon_probe(dev, &msspll_base, ®map); + if (ret) { + ret = mpfs_clk_old_format_probe(dev, &msspll_base, ®map); + if (ret) + return ret; + } + if (msspll_base) { ret = mpfs_clk_register_msspll(msspll_base, parent_clk); if (ret) @@ -50,11 +87,11 @@ static int mpfs_clk_probe(struct udevice *dev) parent_clk = &clk_msspll; } - ret = mpfs_clk_register_cfgs(base, parent_clk); + ret = mpfs_clk_register_cfgs(parent_clk, regmap); if (ret) return ret; - ret = mpfs_clk_register_periphs(base, dev); + ret = mpfs_clk_register_periphs(dev, regmap); return ret; } diff --git a/drivers/clk/microchip/mpfs_clk.h b/drivers/clk/microchip/mpfs_clk.h index 72288cc971b..b8ad3ea7616 100644 --- a/drivers/clk/microchip/mpfs_clk.h +++ b/drivers/clk/microchip/mpfs_clk.h @@ -7,6 +7,7 @@ #define __MICROCHIP_MPFS_CLK_H #include <linux/clk-provider.h> +#include <regmap.h> /** * mpfs_clk_register_cfgs() - register configuration clocks * @@ -14,7 +15,7 @@ * @parent: a pointer to parent clock. * Return: zero on success, or a negative error code. */ -int mpfs_clk_register_cfgs(void __iomem *base, struct clk *parent); +int mpfs_clk_register_cfgs(struct clk *parent, struct regmap *regmap); /** * mpfs_clk_register_msspll() - register the mss pll * @@ -30,7 +31,7 @@ int mpfs_clk_register_msspll(void __iomem *base, struct clk *parent); * @dev: udevice representing the clock controller. * Return: zero on success, or a negative error code. */ -int mpfs_clk_register_periphs(void __iomem *base, struct udevice *dev); +int mpfs_clk_register_periphs(struct udevice *dev, struct regmap *regmap); /** * divider_get_val() - get the clock divider value * diff --git a/drivers/clk/microchip/mpfs_clk_cfg.c b/drivers/clk/microchip/mpfs_clk_cfg.c index 5e8fb995289..7da1fc77120 100644 --- a/drivers/clk/microchip/mpfs_clk_cfg.c +++ b/drivers/clk/microchip/mpfs_clk_cfg.c @@ -9,6 +9,7 @@ #include <dm/device.h> #include <dm/devres.h> #include <dm/uclass.h> +#include <regmap.h> #include <dt-bindings/clock/microchip-mpfs-clock.h> #include <linux/err.h> @@ -57,7 +58,7 @@ struct mpfs_cfg_clock { */ struct mpfs_cfg_hw_clock { struct mpfs_cfg_clock cfg; - void __iomem *sys_base; + struct regmap *regmap; u32 prate; struct clk hw; }; @@ -68,11 +69,11 @@ static ulong mpfs_cfg_clk_recalc_rate(struct clk *hw) { struct mpfs_cfg_hw_clock *cfg_hw = to_mpfs_cfg_clk(hw); struct mpfs_cfg_clock *cfg = &cfg_hw->cfg; - void __iomem *base_addr = cfg_hw->sys_base; unsigned long rate; u32 val; - val = readl(base_addr + REG_CLOCK_CONFIG_CR) >> cfg->shift; + regmap_read(cfg_hw->regmap, REG_CLOCK_CONFIG_CR, &val); + val >>= cfg->shift; val &= clk_div_mask(cfg->width); rate = cfg_hw->prate / (1u << val); hw->rate = rate; @@ -84,7 +85,6 @@ static ulong mpfs_cfg_clk_set_rate(struct clk *hw, ulong rate) { struct mpfs_cfg_hw_clock *cfg_hw = to_mpfs_cfg_clk(hw); struct mpfs_cfg_clock *cfg = &cfg_hw->cfg; - void __iomem *base_addr = cfg_hw->sys_base; u32 val; int divider_setting; @@ -93,10 +93,10 @@ static ulong mpfs_cfg_clk_set_rate(struct clk *hw, ulong rate) if (divider_setting < 0) return divider_setting; - val = readl(base_addr + REG_CLOCK_CONFIG_CR); + regmap_read(cfg_hw->regmap, REG_CLOCK_CONFIG_CR, &val); val &= ~(clk_div_mask(cfg->width) << cfg_hw->cfg.shift); val |= divider_setting << cfg->shift; - writel(val, base_addr + REG_CLOCK_CONFIG_CR); + regmap_write(cfg_hw->regmap, REG_CLOCK_CONFIG_CR, val); return clk_get_rate(hw); } @@ -116,7 +116,7 @@ static struct mpfs_cfg_hw_clock mpfs_cfg_clks[] = { CLK_CFG(CLK_AHB, "clk_ahb", 4, 2, mpfs_div_ahb_table, 0), }; -int mpfs_clk_register_cfgs(void __iomem *base, struct clk *parent) +int mpfs_clk_register_cfgs(struct clk *parent, struct regmap *regmap) { int ret; int i, id, num_clks; @@ -126,7 +126,7 @@ int mpfs_clk_register_cfgs(void __iomem *base, struct clk *parent) num_clks = ARRAY_SIZE(mpfs_cfg_clks); for (i = 0; i < num_clks; i++) { hw = &mpfs_cfg_clks[i].hw; - mpfs_cfg_clks[i].sys_base = base; + mpfs_cfg_clks[i].regmap = regmap; mpfs_cfg_clks[i].prate = clk_get_rate(parent); name = mpfs_cfg_clks[i].cfg.name; ret = clk_register(hw, MPFS_CFG_CLOCK, name, parent->dev->name); diff --git a/drivers/clk/microchip/mpfs_clk_periph.c b/drivers/clk/microchip/mpfs_clk_periph.c index 41c6df4fb97..b734f49d81a 100644 --- a/drivers/clk/microchip/mpfs_clk_periph.c +++ b/drivers/clk/microchip/mpfs_clk_periph.c @@ -9,6 +9,7 @@ #include <dm/device.h> #include <dm/devres.h> #include <dm/uclass.h> +#include <regmap.h> #include <dt-bindings/clock/microchip-mpfs-clock.h> #include <linux/err.h> @@ -50,7 +51,7 @@ struct mpfs_periph_clock { */ struct mpfs_periph_hw_clock { struct mpfs_periph_clock periph; - void __iomem *sys_base; + struct regmap *regmap; u32 prate; struct clk hw; }; @@ -61,17 +62,16 @@ static int mpfs_periph_clk_enable(struct clk *hw) { struct mpfs_periph_hw_clock *periph_hw = to_mpfs_periph_clk(hw); struct mpfs_periph_clock *periph = &periph_hw->periph; - void __iomem *base_addr = periph_hw->sys_base; - u32 reg, val; + u32 reg; if (periph->flags != CLK_IS_CRITICAL) { - reg = readl(base_addr + REG_SUBBLK_RESET_CR); - val = reg & ~(1u << periph->shift); - writel(val, base_addr + REG_SUBBLK_RESET_CR); + regmap_read(periph_hw->regmap, REG_SUBBLK_RESET_CR, ®); + reg &= ~(1u << periph->shift); + regmap_write(periph_hw->regmap, REG_SUBBLK_RESET_CR, reg); - reg = readl(base_addr + REG_SUBBLK_CLOCK_CR); - val = reg | (1u << periph->shift); - writel(val, base_addr + REG_SUBBLK_CLOCK_CR); + regmap_read(periph_hw->regmap, REG_SUBBLK_CLOCK_CR, ®); + reg |= (1u << periph->shift); + regmap_write(periph_hw->regmap, REG_SUBBLK_CLOCK_CR, reg); } return 0; @@ -81,17 +81,16 @@ static int mpfs_periph_clk_disable(struct clk *hw) { struct mpfs_periph_hw_clock *periph_hw = to_mpfs_periph_clk(hw); struct mpfs_periph_clock *periph = &periph_hw->periph; - void __iomem *base_addr = periph_hw->sys_base; - u32 reg, val; + u32 reg; if (periph->flags != CLK_IS_CRITICAL) { - reg = readl(base_addr + REG_SUBBLK_RESET_CR); - val = reg | (1u << periph->shift); - writel(val, base_addr + REG_SUBBLK_RESET_CR); + regmap_read(periph_hw->regmap, REG_SUBBLK_RESET_CR, ®); + reg |= (1u << periph->shift); + regmap_write(periph_hw->regmap, REG_SUBBLK_RESET_CR, reg); - reg = readl(base_addr + REG_SUBBLK_CLOCK_CR); - val = reg & ~(1u << periph->shift); - writel(val, base_addr + REG_SUBBLK_CLOCK_CR); + regmap_read(periph_hw->regmap, REG_SUBBLK_CLOCK_CR, ®); + reg &= ~(1u << periph->shift); + regmap_write(periph_hw->regmap, REG_SUBBLK_CLOCK_CR, reg); } return 0; @@ -159,7 +158,7 @@ static struct mpfs_periph_hw_clock mpfs_periph_clks[] = { CLK_PERIPH(CLK_CFM, "clk_periph_cfm", CLK_AHB, 29, 0), }; -int mpfs_clk_register_periphs(void __iomem *base, struct udevice *dev) +int mpfs_clk_register_periphs(struct udevice *dev, struct regmap *regmap) { int ret; int i, id, num_clks; @@ -172,7 +171,7 @@ int mpfs_clk_register_periphs(void __iomem *base, struct udevice *dev) clk_request(dev, &parent); hw = &mpfs_periph_clks[i].hw; - mpfs_periph_clks[i].sys_base = base; + mpfs_periph_clks[i].regmap = regmap; mpfs_periph_clks[i].prate = clk_get_rate(&parent); name = mpfs_periph_clks[i].periph.name; ret = clk_register(hw, MPFS_PERIPH_CLOCK, name, parent.dev->name); |