From: Conor Dooley <[email protected]>
While reviewing a CAN driver internally for MPFS [1], I realised
that the modeling of the MSSPLL such that only one of its outputs could
be used was not correct. The CAN controllers on MPFS take 2 input
clocks - one that is the bus clock, acquired from the main MSSPLL and
a second clock for the AHB interface to the result of the SoC.
Currently the binding for the CAN controllers and the represetnation
of the MSSPLL only allows for one of these clocks.
Modify the binding and devicetree to expect two clocks and rework the
main clock controller driver for MPFS such that it is capable of
providing multiple outputs from the MSSPLL.
Cheers,
Conor.
1 - Hopefully that'll show up on the lists soon, once we are happy with
it ourselves. (As of v2, that's not happened yet, Christmas etc gettin
in the way, soonTM).
Changes in v2:
- Swap MSSPLL out for MSSPLL0 in the driver, there's no functional
change there.
- drop the unneeded maxItems from clocks.
CC: Conor Dooley <[email protected]>
CC: Daire McNamara <[email protected]>
CC: Wolfgang Grandegger <[email protected]>
CC: Marc Kleine-Budde <[email protected]>
CC: "David S. Miller" <[email protected]>
CC: Eric Dumazet <[email protected]>
CC: Jakub Kicinski <[email protected]>
CC: Paolo Abeni <[email protected]>
CC: Rob Herring <[email protected]>
CC: Krzysztof Kozlowski <[email protected]>
CC: Paul Walmsley <[email protected]>
CC: Palmer Dabbelt <[email protected]>
CC: Albert Ou <[email protected]>
CC: Michael Turquette <[email protected]>
CC: Stephen Boyd <[email protected]>
CC: [email protected]
CC: [email protected]
CC: [email protected]
CC: [email protected]
CC: [email protected]
CC: [email protected]
Conor Dooley (7):
dt-bindings: clock: mpfs: add more MSSPLL output definitions
dt-bindings: can: mpfs: add missing required clock
clk: microchip: mpfs: split MSSPLL in two
clk: microchip: mpfs: setup for using other mss pll outputs
clk: microchip: mpfs: add missing MSSPLL outputs
clk: microchip: mpfs: convert MSSPLL outputs to clk_divider
riscv: dts: microchip: add missing CAN bus clocks
.../bindings/net/can/microchip,mpfs-can.yaml | 6 +-
arch/riscv/boot/dts/microchip/mpfs.dtsi | 4 +-
drivers/clk/microchip/clk-mpfs.c | 154 ++++++++++--------
.../dt-bindings/clock/microchip,mpfs-clock.h | 5 +
4 files changed, 98 insertions(+), 71 deletions(-)
--
2.43.0
From: Conor Dooley <[email protected]>
There are 3 undocumented outputs of the MSSPLL that are used for the CAN
bus, "user crypto" module and eMMC. Add their clock IDs so that they can
be hooked up in DT.
Acked-by: Krzysztof Kozlowski <[email protected]>
Signed-off-by: Conor Dooley <[email protected]>
---
include/dt-bindings/clock/microchip,mpfs-clock.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/include/dt-bindings/clock/microchip,mpfs-clock.h b/include/dt-bindings/clock/microchip,mpfs-clock.h
index 79775a5134ca..b52f19a2b480 100644
--- a/include/dt-bindings/clock/microchip,mpfs-clock.h
+++ b/include/dt-bindings/clock/microchip,mpfs-clock.h
@@ -44,6 +44,11 @@
#define CLK_RTCREF 33
#define CLK_MSSPLL 34
+#define CLK_MSSPLL0 34
+#define CLK_MSSPLL1 35
+#define CLK_MSSPLL2 36
+#define CLK_MSSPLL3 37
+/* 38 is reserved for MSS PLL internals */
/* Clock Conditioning Circuitry Clock IDs */
--
2.43.0
From: Conor Dooley <[email protected]>
The MSSPLL is really two stages - there's the PLL itself and 4 outputs,
each with their own divider. The current driver models this as a single
entity, outputting a single clock, used for both the CPU and AHB/AXI
buses. The other 3 outputs are used for the eMMC, "user crypto" and CAN
controller. Split the MSSPLL in two, as a precursor to adding support
for the other 3 outputs, with the PLL itself as one "hw" clock and the
output divider stage as another.
Signed-off-by: Conor Dooley <[email protected]>
---
drivers/clk/microchip/clk-mpfs.c | 188 ++++++++++++++++++++-----------
1 file changed, 123 insertions(+), 65 deletions(-)
diff --git a/drivers/clk/microchip/clk-mpfs.c b/drivers/clk/microchip/clk-mpfs.c
index c8ffa755b58d..acf598a32ce0 100644
--- a/drivers/clk/microchip/clk-mpfs.c
+++ b/drivers/clk/microchip/clk-mpfs.c
@@ -30,6 +30,13 @@
#define MSSPLL_POSTDIV_WIDTH 0x07u
#define MSSPLL_FIXED_DIV 4u
+/*
+ * This clock ID is defined here, rather than the binding headers, as it is an
+ * internal clock only, and therefore has no consumers in other peripheral
+ * blocks.
+ */
+#define CLK_MSSPLL_INTERNAL 38u
+
struct mpfs_clock_data {
struct device *dev;
void __iomem *base;
@@ -39,17 +46,27 @@ struct mpfs_clock_data {
struct mpfs_msspll_hw_clock {
void __iomem *base;
+ struct clk_hw hw;
+ struct clk_init_data init;
unsigned int id;
u32 reg_offset;
u32 shift;
u32 width;
u32 flags;
- struct clk_hw hw;
- struct clk_init_data init;
};
#define to_mpfs_msspll_clk(_hw) container_of(_hw, struct mpfs_msspll_hw_clock, hw)
+struct mpfs_msspll_out_hw_clock {
+ void __iomem *base;
+ struct clk_hw hw;
+ struct clk_init_data init;
+ unsigned int id;
+ u32 flags;
+};
+
+#define to_mpfs_msspll_out_clk(_hw) container_of(_hw, struct mpfs_msspll_out_hw_clock, hw)
+
struct mpfs_cfg_hw_clock {
struct clk_divider cfg;
struct clk_init_data init;
@@ -93,93 +110,40 @@ static const struct clk_div_table mpfs_div_rtcref_table[] = {
{ 0, 0 }
};
+/*
+ * MSS PLL internal clock
+ */
+
static unsigned long mpfs_clk_msspll_recalc_rate(struct clk_hw *hw, unsigned long prate)
-{
- struct mpfs_msspll_hw_clock *msspll_hw = to_mpfs_msspll_clk(hw);
- void __iomem *mult_addr = msspll_hw->base + msspll_hw->reg_offset;
- void __iomem *ref_div_addr = msspll_hw->base + REG_MSSPLL_REF_CR;
- void __iomem *postdiv_addr = msspll_hw->base + REG_MSSPLL_POSTDIV_CR;
- u32 mult, ref_div, postdiv;
-
- mult = readl_relaxed(mult_addr) >> MSSPLL_FBDIV_SHIFT;
- mult &= clk_div_mask(MSSPLL_FBDIV_WIDTH);
- ref_div = readl_relaxed(ref_div_addr) >> MSSPLL_REFDIV_SHIFT;
- ref_div &= clk_div_mask(MSSPLL_REFDIV_WIDTH);
- postdiv = readl_relaxed(postdiv_addr) >> MSSPLL_POSTDIV_SHIFT;
- postdiv &= clk_div_mask(MSSPLL_POSTDIV_WIDTH);
-
- return prate * mult / (ref_div * MSSPLL_FIXED_DIV * postdiv);
-}
-
-static long mpfs_clk_msspll_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate)
{
struct mpfs_msspll_hw_clock *msspll_hw = to_mpfs_msspll_clk(hw);
void __iomem *mult_addr = msspll_hw->base + msspll_hw->reg_offset;
void __iomem *ref_div_addr = msspll_hw->base + REG_MSSPLL_REF_CR;
u32 mult, ref_div;
- unsigned long rate_before_ctrl;
mult = readl_relaxed(mult_addr) >> MSSPLL_FBDIV_SHIFT;
mult &= clk_div_mask(MSSPLL_FBDIV_WIDTH);
ref_div = readl_relaxed(ref_div_addr) >> MSSPLL_REFDIV_SHIFT;
ref_div &= clk_div_mask(MSSPLL_REFDIV_WIDTH);
- rate_before_ctrl = rate * (ref_div * MSSPLL_FIXED_DIV) / mult;
-
- return divider_round_rate(hw, rate_before_ctrl, prate, NULL, MSSPLL_POSTDIV_WIDTH,
- msspll_hw->flags);
-}
-
-static int mpfs_clk_msspll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long prate)
-{
- struct mpfs_msspll_hw_clock *msspll_hw = to_mpfs_msspll_clk(hw);
- void __iomem *mult_addr = msspll_hw->base + msspll_hw->reg_offset;
- void __iomem *ref_div_addr = msspll_hw->base + REG_MSSPLL_REF_CR;
- void __iomem *postdiv_addr = msspll_hw->base + REG_MSSPLL_POSTDIV_CR;
- u32 mult, ref_div, postdiv;
- int divider_setting;
- unsigned long rate_before_ctrl, flags;
-
- mult = readl_relaxed(mult_addr) >> MSSPLL_FBDIV_SHIFT;
- mult &= clk_div_mask(MSSPLL_FBDIV_WIDTH);
- ref_div = readl_relaxed(ref_div_addr) >> MSSPLL_REFDIV_SHIFT;
- ref_div &= clk_div_mask(MSSPLL_REFDIV_WIDTH);
-
- rate_before_ctrl = rate * (ref_div * MSSPLL_FIXED_DIV) / mult;
- divider_setting = divider_get_val(rate_before_ctrl, prate, NULL, MSSPLL_POSTDIV_WIDTH,
- msspll_hw->flags);
-
- if (divider_setting < 0)
- return divider_setting;
-
- spin_lock_irqsave(&mpfs_clk_lock, flags);
-
- postdiv = readl_relaxed(postdiv_addr);
- postdiv &= ~(clk_div_mask(MSSPLL_POSTDIV_WIDTH) << MSSPLL_POSTDIV_SHIFT);
- writel_relaxed(postdiv, postdiv_addr);
-
- spin_unlock_irqrestore(&mpfs_clk_lock, flags);
-
- return 0;
+ return prate * mult / (ref_div * MSSPLL_FIXED_DIV);
}
static const struct clk_ops mpfs_clk_msspll_ops = {
.recalc_rate = mpfs_clk_msspll_recalc_rate,
- .round_rate = mpfs_clk_msspll_round_rate,
- .set_rate = mpfs_clk_msspll_set_rate,
};
#define CLK_PLL(_id, _name, _parent, _shift, _width, _flags, _offset) { \
.id = _id, \
+ .flags = _flags, \
.shift = _shift, \
.width = _width, \
.reg_offset = _offset, \
- .flags = _flags, \
.hw.init = CLK_HW_INIT_PARENTS_DATA(_name, _parent, &mpfs_clk_msspll_ops, 0), \
}
static struct mpfs_msspll_hw_clock mpfs_msspll_clks[] = {
- CLK_PLL(CLK_MSSPLL, "clk_msspll", mpfs_ext_ref, MSSPLL_FBDIV_SHIFT,
+ CLK_PLL(CLK_MSSPLL_INTERNAL, "clk_msspll_internal", mpfs_ext_ref, MSSPLL_FBDIV_SHIFT,
MSSPLL_FBDIV_WIDTH, 0, REG_MSSPLL_SSCG_2_CR),
};
@@ -196,7 +160,7 @@ static int mpfs_clk_register_mssplls(struct device *dev, struct mpfs_msspll_hw_c
ret = devm_clk_hw_register(dev, &msspll_hw->hw);
if (ret)
return dev_err_probe(dev, ret, "failed to register msspll id: %d\n",
- CLK_MSSPLL);
+ CLK_MSSPLL_INTERNAL);
data->hw_data.hws[msspll_hw->id] = &msspll_hw->hw;
}
@@ -204,6 +168,94 @@ static int mpfs_clk_register_mssplls(struct device *dev, struct mpfs_msspll_hw_c
return 0;
}
+/*
+ * MSS PLL output clocks
+ */
+
+static unsigned long mpfs_clk_msspll_out_recalc_rate(struct clk_hw *hw, unsigned long prate)
+{
+ struct mpfs_msspll_out_hw_clock *msspll_out_hw = to_mpfs_msspll_out_clk(hw);
+ void __iomem *postdiv_addr = msspll_out_hw->base + REG_MSSPLL_POSTDIV_CR;
+ u32 postdiv;
+
+ postdiv = readl_relaxed(postdiv_addr) >> MSSPLL_POSTDIV_SHIFT;
+ postdiv &= clk_div_mask(MSSPLL_POSTDIV_WIDTH);
+
+ return prate / postdiv;
+}
+
+static long mpfs_clk_msspll_out_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct mpfs_msspll_out_hw_clock *msspll_out_hw = to_mpfs_msspll_out_clk(hw);
+
+ return divider_round_rate(hw, rate, prate, NULL, MSSPLL_POSTDIV_WIDTH,
+ msspll_out_hw->flags);
+}
+
+static int mpfs_clk_msspll_out_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long prate)
+{
+ struct mpfs_msspll_out_hw_clock *msspll_out_hw = to_mpfs_msspll_out_clk(hw);
+ void __iomem *postdiv_addr = msspll_out_hw->base + REG_MSSPLL_POSTDIV_CR;
+ u32 postdiv;
+ int divider_setting;
+ unsigned long flags;
+
+ divider_setting = divider_get_val(rate, prate, NULL, MSSPLL_POSTDIV_WIDTH,
+ msspll_out_hw->flags);
+
+ if (divider_setting < 0)
+ return divider_setting;
+
+ spin_lock_irqsave(&mpfs_clk_lock, flags);
+
+ postdiv = readl_relaxed(postdiv_addr);
+ postdiv &= ~(clk_div_mask(MSSPLL_POSTDIV_WIDTH) << MSSPLL_POSTDIV_SHIFT);
+ writel_relaxed(postdiv, postdiv_addr);
+
+ spin_unlock_irqrestore(&mpfs_clk_lock, flags);
+
+ return 0;
+}
+
+static const struct clk_ops mpfs_clk_msspll_out_ops = {
+ .recalc_rate = mpfs_clk_msspll_out_recalc_rate,
+ .round_rate = mpfs_clk_msspll_out_round_rate,
+ .set_rate = mpfs_clk_msspll_out_set_rate,
+};
+
+#define CLK_PLL_OUT(_id, _name, _parent, _flags) { \
+ .id = _id, \
+ .flags = _flags, \
+ .hw.init = CLK_HW_INIT(_name, _parent, &mpfs_clk_msspll_out_ops, 0), \
+}
+
+static struct mpfs_msspll_out_hw_clock mpfs_msspll_out_clks[] = {
+ CLK_PLL_OUT(CLK_MSSPLL0, "clk_msspll", "clk_msspll_internal", 0),
+};
+
+static int mpfs_clk_register_msspll_outs(struct device *dev,
+ struct mpfs_msspll_out_hw_clock *msspll_out_hws,
+ unsigned int num_clks, struct mpfs_clock_data *data)
+{
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < num_clks; i++) {
+ struct mpfs_msspll_out_hw_clock *msspll_out_hw = &msspll_out_hws[i];
+
+ msspll_out_hw->base = data->msspll_base;
+ ret = devm_clk_hw_register(dev, &msspll_out_hw->hw);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to register msspll out id: %d\n",
+ msspll_out_hw->id);
+
+ data->hw_data.hws[msspll_out_hw->id] = &msspll_out_hw->hw;
+ }
+
+ return 0;
+}
+
/*
* "CFG" clocks
*/
@@ -442,8 +494,8 @@ static int mpfs_clk_probe(struct platform_device *pdev)
int ret;
/* CLK_RESERVED is not part of clock arrays, so add 1 */
- num_clks = ARRAY_SIZE(mpfs_msspll_clks) + ARRAY_SIZE(mpfs_cfg_clks)
- + ARRAY_SIZE(mpfs_periph_clks) + 1;
+ num_clks = ARRAY_SIZE(mpfs_msspll_clks) + ARRAY_SIZE(mpfs_msspll_out_clks)
+ + ARRAY_SIZE(mpfs_cfg_clks) + ARRAY_SIZE(mpfs_periph_clks) + 1;
clk_data = devm_kzalloc(dev, struct_size(clk_data, hw_data.hws, num_clks), GFP_KERNEL);
if (!clk_data)
@@ -466,6 +518,12 @@ static int mpfs_clk_probe(struct platform_device *pdev)
if (ret)
return ret;
+ ret = mpfs_clk_register_msspll_outs(dev, mpfs_msspll_out_clks,
+ ARRAY_SIZE(mpfs_msspll_out_clks),
+ clk_data);
+ if (ret)
+ return ret;
+
ret = mpfs_clk_register_cfgs(dev, mpfs_cfg_clks, ARRAY_SIZE(mpfs_cfg_clks), clk_data);
if (ret)
return ret;
--
2.43.0
From: Conor Dooley <[email protected]>
Now that the MSSPLL is split, and the "postdiv" divider of the
cpu/AHB/AXI bus clock is represented by its own "hw" struct, make the
shifts, register offset and width a parameter of the initialisation
macro, rather than using defines that only work for one of the four
outputs.
Configuring this at initialisaion paves the way for using the other
three output clocks, where the register offset, and the bit shift
within that register, will differ.
Signed-off-by: Conor Dooley <[email protected]>
---
drivers/clk/microchip/clk-mpfs.c | 30 +++++++++++++++++++-----------
1 file changed, 19 insertions(+), 11 deletions(-)
diff --git a/drivers/clk/microchip/clk-mpfs.c b/drivers/clk/microchip/clk-mpfs.c
index acf598a32ce0..911905d0433d 100644
--- a/drivers/clk/microchip/clk-mpfs.c
+++ b/drivers/clk/microchip/clk-mpfs.c
@@ -15,7 +15,8 @@
/* address offset of control registers */
#define REG_MSSPLL_REF_CR 0x08u
-#define REG_MSSPLL_POSTDIV_CR 0x10u
+#define REG_MSSPLL_POSTDIV01_CR 0x10u
+#define REG_MSSPLL_POSTDIV23_CR 0x14u
#define REG_MSSPLL_SSCG_2_CR 0x2Cu
#define REG_CLOCK_CONFIG_CR 0x08u
#define REG_RTC_CLOCK_CR 0x0Cu
@@ -26,7 +27,7 @@
#define MSSPLL_FBDIV_WIDTH 0x0Cu
#define MSSPLL_REFDIV_SHIFT 0x08u
#define MSSPLL_REFDIV_WIDTH 0x06u
-#define MSSPLL_POSTDIV_SHIFT 0x08u
+#define MSSPLL_POSTDIV02_SHIFT 0x08u
#define MSSPLL_POSTDIV_WIDTH 0x07u
#define MSSPLL_FIXED_DIV 4u
@@ -62,6 +63,9 @@ struct mpfs_msspll_out_hw_clock {
struct clk_hw hw;
struct clk_init_data init;
unsigned int id;
+ u32 reg_offset;
+ u32 shift;
+ u32 width;
u32 flags;
};
@@ -175,11 +179,11 @@ static int mpfs_clk_register_mssplls(struct device *dev, struct mpfs_msspll_hw_c
static unsigned long mpfs_clk_msspll_out_recalc_rate(struct clk_hw *hw, unsigned long prate)
{
struct mpfs_msspll_out_hw_clock *msspll_out_hw = to_mpfs_msspll_out_clk(hw);
- void __iomem *postdiv_addr = msspll_out_hw->base + REG_MSSPLL_POSTDIV_CR;
+ void __iomem *postdiv_addr = msspll_out_hw->base + msspll_out_hw->reg_offset;
u32 postdiv;
- postdiv = readl_relaxed(postdiv_addr) >> MSSPLL_POSTDIV_SHIFT;
- postdiv &= clk_div_mask(MSSPLL_POSTDIV_WIDTH);
+ postdiv = readl_relaxed(postdiv_addr) >> msspll_out_hw->shift;
+ postdiv &= clk_div_mask(msspll_out_hw->width);
return prate / postdiv;
}
@@ -189,19 +193,19 @@ static long mpfs_clk_msspll_out_round_rate(struct clk_hw *hw, unsigned long rate
{
struct mpfs_msspll_out_hw_clock *msspll_out_hw = to_mpfs_msspll_out_clk(hw);
- return divider_round_rate(hw, rate, prate, NULL, MSSPLL_POSTDIV_WIDTH,
+ return divider_round_rate(hw, rate, prate, NULL, msspll_out_hw->width,
msspll_out_hw->flags);
}
static int mpfs_clk_msspll_out_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long prate)
{
struct mpfs_msspll_out_hw_clock *msspll_out_hw = to_mpfs_msspll_out_clk(hw);
- void __iomem *postdiv_addr = msspll_out_hw->base + REG_MSSPLL_POSTDIV_CR;
+ void __iomem *postdiv_addr = msspll_out_hw->base + msspll_out_hw->reg_offset;
u32 postdiv;
int divider_setting;
unsigned long flags;
- divider_setting = divider_get_val(rate, prate, NULL, MSSPLL_POSTDIV_WIDTH,
+ divider_setting = divider_get_val(rate, prate, NULL, msspll_out_hw->width,
msspll_out_hw->flags);
if (divider_setting < 0)
@@ -210,7 +214,7 @@ static int mpfs_clk_msspll_out_set_rate(struct clk_hw *hw, unsigned long rate, u
spin_lock_irqsave(&mpfs_clk_lock, flags);
postdiv = readl_relaxed(postdiv_addr);
- postdiv &= ~(clk_div_mask(MSSPLL_POSTDIV_WIDTH) << MSSPLL_POSTDIV_SHIFT);
+ postdiv &= ~(clk_div_mask(msspll_out_hw->width) << msspll_out_hw->shift);
writel_relaxed(postdiv, postdiv_addr);
spin_unlock_irqrestore(&mpfs_clk_lock, flags);
@@ -224,14 +228,18 @@ static const struct clk_ops mpfs_clk_msspll_out_ops = {
.set_rate = mpfs_clk_msspll_out_set_rate,
};
-#define CLK_PLL_OUT(_id, _name, _parent, _flags) { \
+#define CLK_PLL_OUT(_id, _name, _parent, _flags, _shift, _width, _offset) { \
.id = _id, \
+ .shift = _shift, \
+ .width = _width, \
+ .reg_offset = _offset, \
.flags = _flags, \
.hw.init = CLK_HW_INIT(_name, _parent, &mpfs_clk_msspll_out_ops, 0), \
}
static struct mpfs_msspll_out_hw_clock mpfs_msspll_out_clks[] = {
- CLK_PLL_OUT(CLK_MSSPLL0, "clk_msspll", "clk_msspll_internal", 0),
+ CLK_PLL_OUT(CLK_MSSPLL0, "clk_msspll", "clk_msspll_internal", 0,
+ MSSPLL_POSTDIV02_SHIFT, MSSPLL_POSTDIV_WIDTH, REG_MSSPLL_POSTDIV01_CR),
};
static int mpfs_clk_register_msspll_outs(struct device *dev,
--
2.43.0
From: Conor Dooley <[email protected]>
The CAN controller on PolarFire SoC has an AHB peripheral clock _and_ a
CAN bus clock. The bus clock was omitted when the binding was written,
but is required for operation. Make up for lost time and add to the DT.
Fixes: 38a71fc04895 ("riscv: dts: microchip: add mpfs's CAN controllers")
Signed-off-by: Conor Dooley <[email protected]>
---
arch/riscv/boot/dts/microchip/mpfs.dtsi | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/riscv/boot/dts/microchip/mpfs.dtsi b/arch/riscv/boot/dts/microchip/mpfs.dtsi
index 266489d43912..4d70df0f908c 100644
--- a/arch/riscv/boot/dts/microchip/mpfs.dtsi
+++ b/arch/riscv/boot/dts/microchip/mpfs.dtsi
@@ -416,7 +416,7 @@ i2c1: i2c@2010b000 {
can0: can@2010c000 {
compatible = "microchip,mpfs-can";
reg = <0x0 0x2010c000 0x0 0x1000>;
- clocks = <&clkcfg CLK_CAN0>;
+ clocks = <&clkcfg CLK_CAN0>, <&clkcfg CLK_MSSPLL3>;
interrupt-parent = <&plic>;
interrupts = <56>;
status = "disabled";
@@ -425,7 +425,7 @@ can0: can@2010c000 {
can1: can@2010d000 {
compatible = "microchip,mpfs-can";
reg = <0x0 0x2010d000 0x0 0x1000>;
- clocks = <&clkcfg CLK_CAN1>;
+ clocks = <&clkcfg CLK_CAN1>, <&clkcfg CLK_MSSPLL3>;
interrupt-parent = <&plic>;
interrupts = <57>;
status = "disabled";
--
2.43.0
From: Conor Dooley <[email protected]>
On Mon, 22 Jan 2024 12:19:48 +0000, Conor Dooley wrote:
> From: Conor Dooley <[email protected]>
>
> While reviewing a CAN driver internally for MPFS [1], I realised
> that the modeling of the MSSPLL such that only one of its outputs could
> be used was not correct. The CAN controllers on MPFS take 2 input
> clocks - one that is the bus clock, acquired from the main MSSPLL and
> a second clock for the AHB interface to the result of the SoC.
> Currently the binding for the CAN controllers and the represetnation
> of the MSSPLL only allows for one of these clocks.
> Modify the binding and devicetree to expect two clocks and rework the
> main clock controller driver for MPFS such that it is capable of
> providing multiple outputs from the MSSPLL.
>
> [...]
And this one is applied to riscv-dt-for-next. I don't think sending this
for the -rcs is needed as there's no impact until the CAN driver shows up.
[7/7] riscv: dts: microchip: add missing CAN bus clocks
https://git.kernel.org/conor/c/6c7353836a91
Thanks,
Conor.