* [PATCH v4 10/31] net: can: mscan: add a comment on reg to idx mapping
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
linux-arm-kernel, devicetree
Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
Wolfgang Grandegger, Mauro Carvalho Chehab
In-Reply-To: <1375821851-31609-1-git-send-email-gsi@denx.de>
add a comment about the magic of deriving an MSCAN component index
from the peripheral's physical address / register offset
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
drivers/net/can/mscan/mpc5xxx_can.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index 5b0ee8e..bc422ba 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -148,7 +148,10 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
goto exit_put;
}
- /* Determine the MSCAN device index from the physical address */
+ /* Determine the MSCAN device index from the peripheral's
+ * physical address. Register address offsets against the
+ * IMMR base are: 0x1300, 0x1380, 0x2300, 0x2380
+ */
pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
BUG_ON(!pval || plen < sizeof(*pval));
clockidx = (*pval & 0x80) ? 1 : 0;
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 11/31] net: can: mscan: improve clock API use
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
linux-arm-kernel, devicetree
Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
Wolfgang Grandegger, Mauro Carvalho Chehab
In-Reply-To: <1375821851-31609-1-git-send-email-gsi@denx.de>
the .get_clock() callback is run from probe() and might allocate
resources, introduce a .put_clock() callback that is run from remove()
to undo any allocation activities
prepare and enable the clocks in open(), disable and unprepare the
clocks in close() if clocks were acquired during probe(), to not assume
knowledge about which activities are done in probe() and remove()
use devm_get_clk() to lookup the SYS and REF clocks, to have the clocks
put upon device shutdown
store pointers to data structures upon successful allocation already
instead of deferral until complete setup, such that subroutines in the
setup sequence may access those data structures as well to track their
resource acquisition
since clock allocation remains optional, the release callback as well as
the enable/disable calls in open/close are optional as well
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
drivers/net/can/mscan/mpc5xxx_can.c | 18 ++++++++++++------
drivers/net/can/mscan/mscan.c | 27 ++++++++++++++++++++++++++-
drivers/net/can/mscan/mscan.h | 3 +++
3 files changed, 41 insertions(+), 7 deletions(-)
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index bc422ba..e59b3a3 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -40,6 +40,7 @@ struct mpc5xxx_can_data {
unsigned int type;
u32 (*get_clock)(struct platform_device *ofdev, const char *clock_name,
int *mscan_clksrc);
+ void (*put_clock)(struct platform_device *ofdev);
};
#ifdef CONFIG_PPC_MPC52xx
@@ -180,7 +181,7 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
clockdiv = 1;
if (!clock_name || !strcmp(clock_name, "sys")) {
- sys_clk = clk_get(&ofdev->dev, "sys_clk");
+ sys_clk = devm_clk_get(&ofdev->dev, "sys_clk");
if (IS_ERR(sys_clk)) {
dev_err(&ofdev->dev, "couldn't get sys_clk\n");
goto exit_unmap;
@@ -203,7 +204,7 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
}
if (clocksrc < 0) {
- ref_clk = clk_get(&ofdev->dev, "ref_clk");
+ ref_clk = devm_clk_get(&ofdev->dev, "ref_clk");
if (IS_ERR(ref_clk)) {
dev_err(&ofdev->dev, "couldn't get ref_clk\n");
goto exit_unmap;
@@ -280,6 +281,8 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
dev = alloc_mscandev();
if (!dev)
goto exit_dispose_irq;
+ platform_set_drvdata(ofdev, dev);
+ SET_NETDEV_DEV(dev, &ofdev->dev);
priv = netdev_priv(dev);
priv->reg_base = base;
@@ -296,8 +299,6 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
goto exit_free_mscan;
}
- SET_NETDEV_DEV(dev, &ofdev->dev);
-
err = register_mscandev(dev, mscan_clksrc);
if (err) {
dev_err(&ofdev->dev, "registering %s failed (err=%d)\n",
@@ -305,8 +306,6 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
goto exit_free_mscan;
}
- platform_set_drvdata(ofdev, dev);
-
dev_info(&ofdev->dev, "MSCAN at 0x%p, irq %d, clock %d Hz\n",
priv->reg_base, dev->irq, priv->can.clock.freq);
@@ -324,10 +323,17 @@ exit_unmap_mem:
static int mpc5xxx_can_remove(struct platform_device *ofdev)
{
+ const struct of_device_id *match;
+ const struct mpc5xxx_can_data *data;
struct net_device *dev = platform_get_drvdata(ofdev);
struct mscan_priv *priv = netdev_priv(dev);
+ match = of_match_device(mpc5xxx_can_table, &ofdev->dev);
+ data = match ? match->data : NULL;
+
unregister_mscandev(dev);
+ if (data && data->put_clock)
+ data->put_clock(ofdev);
iounmap(priv->reg_base);
irq_dispose_mapping(dev->irq);
free_candev(dev);
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
index e6b4095..4f998f5 100644
--- a/drivers/net/can/mscan/mscan.c
+++ b/drivers/net/can/mscan/mscan.c
@@ -573,10 +573,24 @@ static int mscan_open(struct net_device *dev)
struct mscan_priv *priv = netdev_priv(dev);
struct mscan_regs __iomem *regs = priv->reg_base;
+ if (priv->clk_ipg) {
+ ret = clk_prepare_enable(priv->clk_ipg);
+ if (ret)
+ goto exit_retcode;
+ }
+ if (priv->clk_can) {
+ ret = clk_prepare_enable(priv->clk_can);
+ if (ret) {
+ if (priv->clk_ipg)
+ clk_disable_unprepare(priv->clk_ipg);
+ goto exit_retcode;
+ }
+ }
+
/* common open */
ret = open_candev(dev);
if (ret)
- return ret;
+ goto exit_dis_clock;
napi_enable(&priv->napi);
@@ -604,6 +618,12 @@ exit_free_irq:
exit_napi_disable:
napi_disable(&priv->napi);
close_candev(dev);
+exit_dis_clock:
+ if (priv->clk_can)
+ clk_disable_unprepare(priv->clk_can);
+ if (priv->clk_ipg)
+ clk_disable_unprepare(priv->clk_ipg);
+exit_retcode:
return ret;
}
@@ -621,6 +641,11 @@ static int mscan_close(struct net_device *dev)
close_candev(dev);
free_irq(dev->irq, dev);
+ if (priv->clk_can)
+ clk_disable_unprepare(priv->clk_can);
+ if (priv->clk_ipg)
+ clk_disable_unprepare(priv->clk_ipg);
+
return 0;
}
diff --git a/drivers/net/can/mscan/mscan.h b/drivers/net/can/mscan/mscan.h
index af2ed8b..9c24d60 100644
--- a/drivers/net/can/mscan/mscan.h
+++ b/drivers/net/can/mscan/mscan.h
@@ -21,6 +21,7 @@
#ifndef __MSCAN_H__
#define __MSCAN_H__
+#include <linux/clk.h>
#include <linux/types.h>
/* MSCAN control register 0 (CANCTL0) bits */
@@ -283,6 +284,8 @@ struct mscan_priv {
unsigned int type; /* MSCAN type variants */
unsigned long flags;
void __iomem *reg_base; /* ioremap'ed address to registers */
+ struct clk *clk_ipg; /* clock for registers */
+ struct clk *clk_can; /* clock for bitrates */
u8 shadow_statflg;
u8 shadow_canrier;
u8 cur_pri;
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 12/31] powerpc: mpc512x: array decl for MCLK registers in CCM
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
linux-arm-kernel, devicetree
Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
Wolfgang Grandegger, Mauro Carvalho Chehab
In-Reply-To: <1375821851-31609-1-git-send-email-gsi@denx.de>
reword the clock control module's registers declaration such that the
MCLK related registers form an array and get indexed by PSC controller
or CAN controller component number
this change is in preparation to COMMON_CLK support for the MPC512x
platform, the changed declaration remains neutral to existing code since
the PSC and MSCAN CCR fields declared here aren't referenced anywhere
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
arch/powerpc/include/asm/mpc5121.h | 18 ++----------------
1 file changed, 2 insertions(+), 16 deletions(-)
diff --git a/arch/powerpc/include/asm/mpc5121.h b/arch/powerpc/include/asm/mpc5121.h
index 8ae133e..887d3d6 100644
--- a/arch/powerpc/include/asm/mpc5121.h
+++ b/arch/powerpc/include/asm/mpc5121.h
@@ -32,25 +32,11 @@ struct mpc512x_ccm {
u32 scfr2; /* System Clock Frequency Register 2 */
u32 scfr2s; /* System Clock Frequency Shadow Register 2 */
u32 bcr; /* Bread Crumb Register */
- u32 p0ccr; /* PSC0 Clock Control Register */
- u32 p1ccr; /* PSC1 CCR */
- u32 p2ccr; /* PSC2 CCR */
- u32 p3ccr; /* PSC3 CCR */
- u32 p4ccr; /* PSC4 CCR */
- u32 p5ccr; /* PSC5 CCR */
- u32 p6ccr; /* PSC6 CCR */
- u32 p7ccr; /* PSC7 CCR */
- u32 p8ccr; /* PSC8 CCR */
- u32 p9ccr; /* PSC9 CCR */
- u32 p10ccr; /* PSC10 CCR */
- u32 p11ccr; /* PSC11 CCR */
+ u32 psc_ccr[12]; /* PSC Clock Control Registers */
u32 spccr; /* SPDIF Clock Control Register */
u32 cccr; /* CFM Clock Control Register */
u32 dccr; /* DIU Clock Control Register */
- u32 m1ccr; /* MSCAN1 CCR */
- u32 m2ccr; /* MSCAN2 CCR */
- u32 m3ccr; /* MSCAN3 CCR */
- u32 m4ccr; /* MSCAN4 CCR */
+ u32 mscan_ccr[4]; /* MSCAN Clock Control Registers */
u8 res[0x98]; /* Reserved */
};
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 13/31] clk: wrap I/O access for improved portability
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
linux-arm-kernel, devicetree
Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
Wolfgang Grandegger, Mauro Carvalho Chehab
In-Reply-To: <1375821851-31609-1-git-send-email-gsi@denx.de>
the common clock drivers were motivated/initiated by ARM development
and apparently assume little endian peripherals
wrap register/peripherals access in the common code (div, gate, mux)
in preparation of adding COMMON_CLK support for other platforms
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
drivers/clk/clk-divider.c | 6 +++---
drivers/clk/clk-gate.c | 6 +++---
drivers/clk/clk-mux.c | 6 +++---
include/linux/clk-provider.h | 17 +++++++++++++++++
4 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 6d55eb2..2c07061 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
struct clk_divider *divider = to_clk_divider(hw);
unsigned int div, val;
- val = readl(divider->reg) >> divider->shift;
+ val = clk_readl(divider->reg) >> divider->shift;
val &= div_mask(divider);
div = _get_div(divider, val);
@@ -230,11 +230,11 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
val = div_mask(divider) << (divider->shift + 16);
} else {
- val = readl(divider->reg);
+ val = clk_readl(divider->reg);
val &= ~(div_mask(divider) << divider->shift);
}
val |= value << divider->shift;
- writel(val, divider->reg);
+ clk_writel(val, divider->reg);
if (divider->lock)
spin_unlock_irqrestore(divider->lock, flags);
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 790306e..b7fbd96 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -58,7 +58,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
if (set)
reg |= BIT(gate->bit_idx);
} else {
- reg = readl(gate->reg);
+ reg = clk_readl(gate->reg);
if (set)
reg |= BIT(gate->bit_idx);
@@ -66,7 +66,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
reg &= ~BIT(gate->bit_idx);
}
- writel(reg, gate->reg);
+ clk_writel(reg, gate->reg);
if (gate->lock)
spin_unlock_irqrestore(gate->lock, flags);
@@ -89,7 +89,7 @@ static int clk_gate_is_enabled(struct clk_hw *hw)
u32 reg;
struct clk_gate *gate = to_clk_gate(hw);
- reg = readl(gate->reg);
+ reg = clk_readl(gate->reg);
/* if a set bit disables this clk, flip it before masking */
if (gate->flags & CLK_GATE_SET_TO_DISABLE)
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 614444c..02ef506 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -42,7 +42,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
* OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
* val = 0x4 really means "bit 2, index starts at bit 0"
*/
- val = readl(mux->reg) >> mux->shift;
+ val = clk_readl(mux->reg) >> mux->shift;
val &= mux->mask;
if (mux->table) {
@@ -89,11 +89,11 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
if (mux->flags & CLK_MUX_HIWORD_MASK) {
val = mux->mask << (mux->shift + 16);
} else {
- val = readl(mux->reg);
+ val = clk_readl(mux->reg);
val &= ~(mux->mask << mux->shift);
}
val |= index << mux->shift;
- writel(val, mux->reg);
+ clk_writel(val, mux->reg);
if (mux->lock)
spin_unlock_irqrestore(mux->lock, flags);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 1ec14a7..c4f7799 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -12,6 +12,7 @@
#define __LINUX_CLK_PROVIDER_H
#include <linux/clk.h>
+#include <linux/io.h>
#ifdef CONFIG_COMMON_CLK
@@ -490,5 +491,21 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
#define of_clk_init(matches) \
{ while (0); }
#endif /* CONFIG_OF */
+
+/*
+ * wrap access to peripherals in accessor routines
+ * for improved portability across platforms
+ */
+
+static inline u32 clk_readl(u32 __iomem *reg)
+{
+ return readl(reg);
+}
+
+static inline void clk_writel(u32 val, u32 __iomem *reg)
+{
+ writel(val, reg);
+}
+
#endif /* CONFIG_COMMON_CLK */
#endif /* CLK_PROVIDER_H */
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 14/31] dts: mpc512x: prepare for preprocessor support
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
linux-arm-kernel, devicetree
Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
Wolfgang Grandegger, Mauro Carvalho Chehab
In-Reply-To: <1375821851-31609-1-git-send-email-gsi@denx.de>
prepare C preprocessor support when processing MPC512x DTS files
- switch from DTS syntax to CPP syntax for include specs
- create a symlink such that DTS processing can reference includes
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
arch/powerpc/boot/dts/ac14xx.dts | 2 +-
arch/powerpc/boot/dts/include/dt-bindings | 1 +
arch/powerpc/boot/dts/mpc5121ads.dts | 2 +-
arch/powerpc/boot/dts/pdm360ng.dts | 2 +-
4 files changed, 4 insertions(+), 3 deletions(-)
create mode 120000 arch/powerpc/boot/dts/include/dt-bindings
diff --git a/arch/powerpc/boot/dts/ac14xx.dts b/arch/powerpc/boot/dts/ac14xx.dts
index a27a460..a543c40 100644
--- a/arch/powerpc/boot/dts/ac14xx.dts
+++ b/arch/powerpc/boot/dts/ac14xx.dts
@@ -10,7 +10,7 @@
*/
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
/ {
model = "ac14xx";
diff --git a/arch/powerpc/boot/dts/include/dt-bindings b/arch/powerpc/boot/dts/include/dt-bindings
new file mode 120000
index 0000000..08c00e4
--- /dev/null
+++ b/arch/powerpc/boot/dts/include/dt-bindings
@@ -0,0 +1 @@
+../../../../../include/dt-bindings
\ No newline at end of file
diff --git a/arch/powerpc/boot/dts/mpc5121ads.dts b/arch/powerpc/boot/dts/mpc5121ads.dts
index 7d3cb79..c228a0a 100644
--- a/arch/powerpc/boot/dts/mpc5121ads.dts
+++ b/arch/powerpc/boot/dts/mpc5121ads.dts
@@ -9,7 +9,7 @@
* option) any later version.
*/
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
/ {
model = "mpc5121ads";
diff --git a/arch/powerpc/boot/dts/pdm360ng.dts b/arch/powerpc/boot/dts/pdm360ng.dts
index 7433740..871c16d 100644
--- a/arch/powerpc/boot/dts/pdm360ng.dts
+++ b/arch/powerpc/boot/dts/pdm360ng.dts
@@ -13,7 +13,7 @@
* option) any later version.
*/
-/include/ "mpc5121.dtsi"
+#include <mpc5121.dtsi>
/ {
model = "pdm360ng";
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 15/31] dts: mpc512x: introduce dt-bindings/clock/ header
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
linux-arm-kernel, devicetree
Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
Wolfgang Grandegger, Mauro Carvalho Chehab
In-Reply-To: <1375821851-31609-1-git-send-email-gsi@denx.de>
introduce a dt-bindings/ header file for MPC512x clocks,
providing symbolic identifiers for those SoC clocks which
clients will reference from their device tree nodes
Reviewed-by: Mike Turquette <mturquette@linaro.org> # for v3: w/o bdlc, PSC ipg
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
include/dt-bindings/clock/mpc512x-clock.h | 69 +++++++++++++++++++++++++++++
1 file changed, 69 insertions(+)
create mode 100644 include/dt-bindings/clock/mpc512x-clock.h
diff --git a/include/dt-bindings/clock/mpc512x-clock.h b/include/dt-bindings/clock/mpc512x-clock.h
new file mode 100644
index 0000000..9e81b3b
--- /dev/null
+++ b/include/dt-bindings/clock/mpc512x-clock.h
@@ -0,0 +1,69 @@
+/*
+ * This header provides constants for MPC512x clock specs in DT bindings.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
+#define _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
+
+#define MPC512x_CLK_DUMMY 0
+#define MPC512x_CLK_REF 1
+#define MPC512x_CLK_SYS 2
+#define MPC512x_CLK_DIU 3
+#define MPC512x_CLK_VIU 4
+#define MPC512x_CLK_CSB 5
+#define MPC512x_CLK_E300 6
+#define MPC512x_CLK_IPS 7
+#define MPC512x_CLK_FEC 8
+#define MPC512x_CLK_SATA 9
+#define MPC512x_CLK_PATA 10
+#define MPC512x_CLK_NFC 11
+#define MPC512x_CLK_LPC 12
+#define MPC512x_CLK_MBX_BUS 13
+#define MPC512x_CLK_MBX 14
+#define MPC512x_CLK_MBX_3D 15
+#define MPC512x_CLK_AXE 16
+#define MPC512x_CLK_USB1 17
+#define MPC512x_CLK_USB2 18
+#define MPC512x_CLK_I2C 19
+#define MPC512x_CLK_MSCAN0_MCLK 20
+#define MPC512x_CLK_MSCAN1_MCLK 21
+#define MPC512x_CLK_MSCAN2_MCLK 22
+#define MPC512x_CLK_MSCAN3_MCLK 23
+#define MPC512x_CLK_BDLC 24
+#define MPC512x_CLK_SDHC 25
+#define MPC512x_CLK_PCI 26
+#define MPC512x_CLK_PSC_MCLK_IN 27
+#define MPC512x_CLK_SPDIF_TX 28
+#define MPC512x_CLK_SPDIF_RX 29
+#define MPC512x_CLK_SPDIF_MCLK 30
+#define MPC512x_CLK_SPDIF 31
+#define MPC512x_CLK_AC97 32
+#define MPC512x_CLK_PSC0_MCLK 33
+#define MPC512x_CLK_PSC1_MCLK 34
+#define MPC512x_CLK_PSC2_MCLK 35
+#define MPC512x_CLK_PSC3_MCLK 36
+#define MPC512x_CLK_PSC4_MCLK 37
+#define MPC512x_CLK_PSC5_MCLK 38
+#define MPC512x_CLK_PSC6_MCLK 39
+#define MPC512x_CLK_PSC7_MCLK 40
+#define MPC512x_CLK_PSC8_MCLK 41
+#define MPC512x_CLK_PSC9_MCLK 42
+#define MPC512x_CLK_PSC10_MCLK 43
+#define MPC512x_CLK_PSC11_MCLK 44
+#define MPC512x_CLK_PSC_FIFO 45
+#define MPC512x_CLK_PSC0 46
+#define MPC512x_CLK_PSC1 47
+#define MPC512x_CLK_PSC2 48
+#define MPC512x_CLK_PSC3 49
+#define MPC512x_CLK_PSC4 50
+#define MPC512x_CLK_PSC5 51
+#define MPC512x_CLK_PSC6 52
+#define MPC512x_CLK_PSC7 53
+#define MPC512x_CLK_PSC8 54
+#define MPC512x_CLK_PSC9 55
+#define MPC512x_CLK_PSC10 56
+#define MPC512x_CLK_PSC11 57
+
+#define MPC512x_CLK_LAST_PUBLIC 57
+
+#endif
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 16/31] dts: mpc512x: add clock related device tree specs
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
linux-arm-kernel, devicetree
Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
Wolfgang Grandegger, Mauro Carvalho Chehab
In-Reply-To: <1375821851-31609-1-git-send-email-gsi@denx.de>
this addresses the clock driver aka provider's side of clocks
- prepare for future '<&clks ID>' phandle references for device tree
based clock lookup in client drivers
- introduce a 'clocks' subtree with an 'osc' node for the crystal
or oscillator SoC input (fixed frequency)
- provide default values with 33MHz oscillator frequency in the
common include (the 66MHz IPS bus already was there), add
override values for the ifm AC14xx board which deviates from
the reference design (25MHz xtal, 80MHz IPS bus)
Reviewed-by: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
arch/powerpc/boot/dts/ac14xx.dts | 7 +++++++
arch/powerpc/boot/dts/mpc5121.dtsi | 15 ++++++++++++++-
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/boot/dts/ac14xx.dts b/arch/powerpc/boot/dts/ac14xx.dts
index a543c40..a1b8837 100644
--- a/arch/powerpc/boot/dts/ac14xx.dts
+++ b/arch/powerpc/boot/dts/ac14xx.dts
@@ -139,7 +139,14 @@
};
};
+ clocks {
+ osc {
+ clock-frequency = <25000000>;
+ };
+ };
+
soc@80000000 {
+ bus-frequency = <80000000>; /* 80 MHz ips bus */
clock@f00 {
compatible = "fsl,mpc5121rev2-clock", "fsl,mpc5121-clock";
diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index bd14c00..8f4cba0 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -9,6 +9,8 @@
* option) any later version.
*/
+#include <dt-bindings/clock/mpc512x-clock.h>
+
/dts-v1/;
/ {
@@ -73,6 +75,16 @@
ranges = <0x0 0x0 0xfc000000 0x04000000>;
};
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ osc {
+ compatible = "fsl,mpc512x-osc", "fixed-clock";
+ clock-frequency = <33000000>;
+ };
+ };
+
soc@80000000 {
compatible = "fsl,mpc5121-immr";
#address-cells = <1>;
@@ -118,9 +130,10 @@
};
/* Clock control */
- clock@f00 {
+ clks: clock@f00 {
compatible = "fsl,mpc5121-clock";
reg = <0xf00 0x100>;
+ #clock-cells = <1>;
};
/* Power Management Controller */
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
linux-arm-kernel, devicetree
Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
Wolfgang Grandegger, Mauro Carvalho Chehab
In-Reply-To: <1375821851-31609-1-git-send-email-gsi@denx.de>
this change implements a clock driver for the MPC512x PowerPC platform
which follows the COMMON_CLK approach and uses common clock drivers
shared with other platforms
this driver implements the publicly announced set of clocks (which can
get referenced by means of symbolic identifiers from the dt-bindings
header file), as well as generates additional 'struct clk' items where
the SoC hardware cannot easily get mapped to the common primitives of
the clock API, or requires "intermediate" clock nodes to represent
clocks that have both gates and dividers
the previous PPC_CLOCK implementation is kept in place and remains in
parallel to the common clock implementation for test and comparison
during migration, a compile time option picks one of the two
alternatives (Kconfig switch, common clock used by default)
some of the clock items get pre-enabled in the clock driver to not have
them automatically disabled by the underlying clock subsystem because of
their being unused -- this approach is desirable because
- some of the clocks are useful to have for diagnostics and information
despite their not getting claimed by any drivers (CPU, internal and
external RAM, internal busses, boot media)
- some of the clocks aren't claimed by their peripheral drivers yet,
either because of missing driver support or because device tree specs
aren't available yet (but the workarounds will get removed as the
drivers get adjusted and the device tree provides the clock specs)
clkdev registration provides "alias names" for few clock items
- to not break those peripheral drivers which encode their component
index into the name that is used for clock lookup (UART, SPI, USB)
- to not break those drivers which use names for the clock lookup which
were encoded in the previous PPC_CLOCK implementation (NFC, VIU, CAN)
this workaround will get removed as these drivers get adjusted after
device tree based clock lookup has become available
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
arch/powerpc/platforms/512x/Kconfig | 14 +-
arch/powerpc/platforms/512x/Makefile | 4 +-
arch/powerpc/platforms/512x/clock-commonclk.c | 748 +++++++++++++++++++++++++
include/linux/clk-provider.h | 16 +
4 files changed, 780 insertions(+), 2 deletions(-)
create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index fc9c1cb..c5fcdd0 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,9 +1,21 @@
+config MPC512x_COMMON_CLK
+ bool "MPC512x platform uses COMMON_CLK"
+ default y
+ depends on PPC_MPC512x
+ help
+ This option is only here to support tests and comparison
+ during development and migration. This option will get
+ removed after the COMMON_CLK support for MPC512x has become
+ fully operational and all drivers were adjusted to explicitly
+ acquire their required clocks.
+
config PPC_MPC512x
bool "512x-based boards"
depends on 6xx
select FSL_SOC
select IPIC
- select PPC_CLOCK
+ select PPC_CLOCK if !MPC512x_COMMON_CLK
+ select COMMON_CLK if MPC512x_COMMON_CLK
select PPC_PCI_CHOICE
select FSL_PCI if PCI
select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 72fb934..1e05f9d 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,7 +1,9 @@
#
# Makefile for the Freescale PowerPC 512x linux kernel.
#
-obj-y += clock.o mpc512x_shared.o
+obj-$(CONFIG_PPC_CLOCK) += clock.o
+obj-$(CONFIG_COMMON_CLK) += clock-commonclk.o
+obj-y += mpc512x_shared.o
obj-$(CONFIG_MPC5121_ADS) += mpc5121_ads.o mpc5121_ads_cpld.o
obj-$(CONFIG_MPC512x_GENERIC) += mpc512x_generic.o
obj-$(CONFIG_PDM360NG) += pdm360ng.o
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
new file mode 100644
index 0000000..09721d5
--- /dev/null
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -0,0 +1,748 @@
+/*
+ * Copyright (C) 2013 DENX Software Engineering
+ *
+ * Gerhard Sittig, <gsi@denx.de>
+ *
+ * common clock driver support for the MPC512x platform
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#include <asm/mpc5121.h>
+#include <dt-bindings/clock/mpc512x-clock.h>
+
+#include "mpc512x.h" /* our public mpc5121_clk_init() API */
+
+/* helpers to keep the MCLK intermediates "somewhere" in our table */
+enum {
+ MCLK_IDX_MUX0,
+ MCLK_IDX_EN0,
+ MCLK_IDX_DIV0,
+ MCLK_MAX_IDX,
+};
+
+#define NR_PSCS 12
+#define NR_MSCANS 4
+#define NR_SPDIFS 1
+#define NR_MCLKS (NR_PSCS + NR_MSCANS + NR_SPDIFS)
+
+/* extend the public set of clocks by adding internal slots for management */
+enum {
+ /* arrange for adjacent numbers after the public set */
+ MPC512x_CLK_START_PRIVATE = MPC512x_CLK_LAST_PUBLIC,
+ /* clocks which aren't announced to the public */
+ MPC512x_CLK_DDR,
+ MPC512x_CLK_MEM,
+ MPC512x_CLK_IIM,
+ MPC512x_CLK_SDHC_2,
+ /* intermediates in div+gate combos or fractional dividers */
+ MPC512x_CLK_DDR_UG,
+ MPC512x_CLK_SDHC_x4,
+ MPC512x_CLK_SDHC_UG,
+ MPC512x_CLK_DIU_x4,
+ MPC512x_CLK_DIU_UG,
+ MPC512x_CLK_MBX_BUS_UG,
+ MPC512x_CLK_MBX_UG,
+ MPC512x_CLK_MBX_3D_UG,
+ MPC512x_CLK_PCI_UG,
+ MPC512x_CLK_NFC_UG,
+ MPC512x_CLK_LPC_UG,
+ MPC512x_CLK_SPDIF_TX_IN,
+ /* intermediates for the mux+gate+div+mux MCLK generation */
+ MPC512x_CLK_MCLKS_FIRST,
+ MPC512x_CLK_MCLKS_LAST = MPC512x_CLK_MCLKS_FIRST
+ + NR_MCLKS * MCLK_MAX_IDX,
+ /* internal, symbolic spec for the number of slots */
+ MPC512x_CLK_LAST_PRIVATE,
+};
+
+/* data required for the OF clock provider registration */
+static struct clk *clks[MPC512x_CLK_LAST_PRIVATE];
+static struct clk_onecell_data clk_data;
+
+/* CCM register access */
+static struct mpc512x_ccm __iomem *clkregs;
+static DEFINE_SPINLOCK(clklock);
+
+/* convenience wrappers around the common clk API */
+static inline struct clk *mpc512x_clk_fixed(const char *name, int rate)
+{
+ return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
+}
+
+static inline struct clk *mpc512x_clk_factor(
+ const char *name, const char *parent_name,
+ int mul, int div)
+{
+ int clkflags;
+
+ clkflags = CLK_SET_RATE_PARENT;
+ return clk_register_fixed_factor(NULL, name, parent_name, clkflags,
+ mul, div);
+}
+
+static inline struct clk *mpc512x_clk_divider(
+ const char *name, const char *parent_name, u8 clkflags,
+ u32 __iomem *reg, u8 pos, u8 len, int divflags)
+{
+ return clk_register_divider(NULL, name, parent_name, clkflags,
+ reg, pos, len, divflags, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_divtable(
+ const char *name, const char *parent_name,
+ u32 __iomem *reg, u8 pos, u8 len,
+ const struct clk_div_table *divtab)
+{
+ u8 divflags;
+
+ divflags = 0;
+ return clk_register_divider_table(NULL, name, parent_name, 0,
+ reg, pos, len, divflags,
+ divtab, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_gated(
+ const char *name, const char *parent_name,
+ u32 __iomem *reg, u8 pos)
+{
+ int clkflags;
+
+ clkflags = CLK_SET_RATE_PARENT;
+ return clk_register_gate(NULL, name, parent_name, clkflags,
+ reg, pos, 0, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_muxed(const char *name,
+ const char **parent_names, int parent_count,
+ u32 __iomem *reg, u8 pos, u8 len)
+{
+ int clkflags;
+ u8 muxflags;
+
+ clkflags = CLK_SET_RATE_PARENT;
+ muxflags = 0;
+ return clk_register_mux(NULL, name,
+ parent_names, parent_count, clkflags,
+ reg, pos, len, muxflags, &clklock);
+}
+
+/* helper to isolate a bit field from a register */
+static inline int get_bit_field(uint32_t __iomem *reg, uint8_t pos, uint8_t len)
+{
+ uint32_t val;
+
+ val = in_be32(reg);
+ val >>= pos;
+ val &= (1 << len) - 1;
+ return val;
+}
+
+/* get the SPMF and translate it into the "sys pll" multiplier */
+static int get_spmf_mult(void)
+{
+ static int spmf_to_mult[] = {
+ 68, 1, 12, 16, 20, 24, 28, 32,
+ 36, 40, 44, 48, 52, 56, 60, 64,
+ };
+ int spmf;
+
+ spmf = get_bit_field(&clkregs->spmr, 24, 4);
+ return spmf_to_mult[spmf];
+}
+
+/*
+ * get the SYS_DIV value and translate it into a divide factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * divide ratio is fractional
+ */
+static int get_sys_div_x2(void)
+{
+ static int sysdiv_code_to_x2[] = {
+ 4, 5, 6, 7, 8, 9, 10, 14,
+ 12, 16, 18, 22, 20, 24, 26, 30,
+ 28, 32, 34, 38, 36, 40, 42, 46,
+ 44, 48, 50, 54, 52, 56, 58, 62,
+ 60, 64, 66,
+ };
+ int divcode;
+
+ divcode = get_bit_field(&clkregs->scfr2, 26, 6);
+ return sysdiv_code_to_x2[divcode];
+}
+
+/*
+ * get the CPMF value and translate it into a multiplier factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * multiplier ratio is fractional
+ */
+static int get_cpmf_mult_x2(void)
+{
+ static int cpmf_to_mult[] = {
+ 72, 2, 2, 3, 4, 5, 6, 7,
+ };
+ int cpmf;
+
+ cpmf = get_bit_field(&clkregs->spmr, 16, 4);
+ return cpmf_to_mult[cpmf];
+}
+
+/*
+ * some of the clock dividers do scale in a linear way, yet not all of
+ * their bit combinations are legal; use a divider table to get a
+ * resulting set of applicable divider values
+ */
+
+/* applies to the IPS_DIV, and PCI_DIV values */
+static struct clk_div_table divtab_2346[] = {
+ { .val = 2, .div = 2, },
+ { .val = 3, .div = 3, },
+ { .val = 4, .div = 4, },
+ { .val = 6, .div = 6, },
+ { .div = 0, },
+};
+
+/* applies to the MBX_DIV, LPC_DIV, and NFC_DIV values */
+static struct clk_div_table divtab_1234[] = {
+ { .val = 1, .div = 1, },
+ { .val = 2, .div = 2, },
+ { .val = 3, .div = 3, },
+ { .val = 4, .div = 4, },
+ { .div = 0, },
+};
+
+static int get_freq_from_dt(char *propname)
+{
+ struct device_node *np;
+ const unsigned int *prop;
+ int val;
+
+ val = 0;
+ np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
+ if (np) {
+ prop = of_get_property(np, propname, NULL);
+ if (prop)
+ val = *prop;
+ of_node_put(np);
+ }
+ return val;
+}
+
+static void mpc512x_clk_preset_data(void)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(clks); i++)
+ clks[i] = ERR_PTR(-ENODEV);
+}
+
+/*
+ * - receives the "bus frequency" from the caller (that's the IPS clock
+ * rate, the historical source of clock information)
+ * - fetches the system PLL multiplier and divider values as well as the
+ * IPS divider value from hardware
+ * - determines the REF clock rate either from the XTAL/OSC spec (if
+ * there is a device tree node describing the oscillator) or from the
+ * IPS bus clock (supported for backwards compatibility, such that
+ * setups without XTAL/OSC specs keep working)
+ * - creates the "ref" clock item in the clock tree, such that
+ * subsequent code can create the remainder of the hierarchy (REF ->
+ * SYS -> CSB -> IPS) from the REF clock rate and the returned mul/div
+ * values
+ */
+static void mpc512x_clk_setup_ref_clock(int bus_freq,
+ int *sys_mul, int *sys_div, int *ips_div)
+{
+ struct clk *osc_clk;
+ int calc_freq;
+
+ /* fetch mul/div factors from the hardware */
+ *sys_mul = get_spmf_mult();
+ *sys_mul *= 2; /* compensate for the fractional divider */
+ *sys_div = get_sys_div_x2();
+ *ips_div = get_bit_field(&clkregs->scfr1, 23, 3);
+
+ /* lookup the oscillator node */
+ osc_clk = clk_get(NULL, "osc");
+ if (osc_clk) {
+ /* descend REF directly from OSC, verify the IPS rate */
+ clks[MPC512x_CLK_REF] = mpc512x_clk_factor("ref", "osc", 1, 1);
+ calc_freq = clk_get_rate(clks[MPC512x_CLK_REF]);
+ calc_freq *= *sys_mul;
+ calc_freq /= *sys_div;
+ calc_freq /= 2;
+ calc_freq /= *ips_div;
+ if (bus_freq && calc_freq != bus_freq)
+ pr_warn("calc rate %d != OF spec %d\n",
+ calc_freq, bus_freq);
+ } else {
+ /* calculate OSC rate and create REF from the freq value */
+ calc_freq = bus_freq; /* start with IPS */
+ calc_freq *= *ips_div; /* IPS -> CSB */
+ calc_freq *= 2; /* CSB -> SYS */
+ calc_freq *= *sys_div; /* SYS -> PLL out */
+ calc_freq /= *sys_mul; /* PLL out -> REF == OSC */
+ clks[MPC512x_CLK_REF] = mpc512x_clk_fixed("ref", calc_freq);
+ }
+}
+
+/*
+ * helper code for the MCLK subtree setup
+ *
+ * the overview in section 5.2.4 of the MPC5121e Reference Manual rev4
+ * suggests that all instances of the "PSC clock generation" are equal,
+ * and that one might re-use the PSC setup for MSCAN clock generation
+ * (section 5.2.5) as well, at least the logic if not the data for
+ * description
+ *
+ * the details (starting at page 5-20) show differences in the specific
+ * inputs of the first mux stage ("can clk in", "spdif tx"), and the
+ * factual non-availability of the second mux stage (it's present yet
+ * only one input is valid)
+ *
+ * the MSCAN clock related registers (starting at page 5-35) all
+ * reference "spdif clk" at the first mux stage and don't mention any
+ * "can clk" at all, which somehow is unexpected
+ *
+ * TODO re-check the document, and clarify whether the RM is correct in
+ * the overview or in the details, and whether the difference is a
+ * clipboard induced error or results from chip revisions
+ *
+ * it turns out that the RM rev4 as of 2012-06 talks about "can" for the
+ * PSCs while RM rev3 as of 2008-10 talks about "spdif", so I guess that
+ * first a doc update is required which better reflects reality in the
+ * SoC before the implementation should follow while no questions remain
+ */
+
+/*
+ * note that this declaration raises a checkpatch warning, but
+ * it's the very data type which <linux/clk-provider.h> expects,
+ * making this declaration pass checkpatch will break compilation
+ */
+static const char *parent_names_mux0[] = {
+ "sys", "ref", "psc-mclk-in", "spdif-tx",
+};
+
+enum mclk_type {
+ MCLK_TYPE_PSC,
+ MCLK_TYPE_MSCAN,
+ MCLK_TYPE_SPDIF,
+};
+
+struct mclk_setup_data {
+ enum mclk_type type;
+ bool has_mclk1;
+ const char *name_mux0;
+ const char *name_en0;
+ const char *name_div0;
+ const char *parent_names_mux1[2];
+ const char *name_mclk;
+};
+
+#define MCLK_SETUP_DATA_PSC(id) { \
+ MCLK_TYPE_PSC, 0, \
+ "psc" #id "-mux0", \
+ "psc" #id "-en0", \
+ "psc" #id "_mclk_div", \
+ { "psc" #id "_mclk_div", "dummy", }, \
+ "psc" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_MSCAN(id) { \
+ MCLK_TYPE_MSCAN, 0, \
+ "mscan" #id "-mux0", \
+ "mscan" #id "-en0", \
+ "mscan" #id "_mclk_div", \
+ { "mscan" #id "_mclk_div", "dummy", }, \
+ "mscan" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_SPDIF { \
+ MCLK_TYPE_SPDIF, 1, \
+ "spdif-mux0", \
+ "spdif-en0", \
+ "spdif_mclk_div", \
+ { "spdif_mclk_div", "spdif-rx", }, \
+ "spdif_mclk", \
+}
+
+static struct mclk_setup_data mclk_psc_data[] = {
+ MCLK_SETUP_DATA_PSC(0),
+ MCLK_SETUP_DATA_PSC(1),
+ MCLK_SETUP_DATA_PSC(2),
+ MCLK_SETUP_DATA_PSC(3),
+ MCLK_SETUP_DATA_PSC(4),
+ MCLK_SETUP_DATA_PSC(5),
+ MCLK_SETUP_DATA_PSC(6),
+ MCLK_SETUP_DATA_PSC(7),
+ MCLK_SETUP_DATA_PSC(8),
+ MCLK_SETUP_DATA_PSC(9),
+ MCLK_SETUP_DATA_PSC(10),
+ MCLK_SETUP_DATA_PSC(11),
+};
+
+static struct mclk_setup_data mclk_mscan_data[] = {
+ MCLK_SETUP_DATA_MSCAN(0),
+ MCLK_SETUP_DATA_MSCAN(1),
+ MCLK_SETUP_DATA_MSCAN(2),
+ MCLK_SETUP_DATA_MSCAN(3),
+};
+
+static struct mclk_setup_data mclk_spdif_data[] = {
+ MCLK_SETUP_DATA_SPDIF,
+};
+
+/* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */
+static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry, size_t idx)
+{
+ size_t clks_idx_pub, clks_idx_int;
+ u32 __iomem *mccr_reg; /* MCLK control register (mux, en, div) */
+ int div;
+
+ /* derive a few parameters from the component type and index */
+ switch (entry->type) {
+ case MCLK_TYPE_PSC:
+ clks_idx_pub = MPC512x_CLK_PSC0_MCLK + idx;
+ clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+ + (idx) * MCLK_MAX_IDX;
+ mccr_reg = &clkregs->psc_ccr[idx];
+ break;
+ case MCLK_TYPE_MSCAN:
+ clks_idx_pub = MPC512x_CLK_MSCAN0_MCLK + idx;
+ clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+ + (NR_PSCS + idx) * MCLK_MAX_IDX;
+ mccr_reg = &clkregs->mscan_ccr[idx];
+ break;
+ case MCLK_TYPE_SPDIF:
+ clks_idx_pub = MPC512x_CLK_SPDIF_MCLK;
+ clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+ + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX;
+ mccr_reg = &clkregs->spccr;
+ break;
+ default:
+ return;
+ }
+
+ /*
+ * this was grabbed from the PPC_CLOCK implementation, which
+ * enforced a specific MCLK divider while the clock was gated
+ * during setup (that's a documented hardware requirement)
+ *
+ * the PPC_CLOCK implementation might even have violated the
+ * "MCLK <= IPS" constraint, the fixed divider value of 1
+ * results in a divider of 2 and thus MCLK = SYS/2 which equals
+ * CSB which is greater than IPS; the serial port setup may have
+ * adjusted the divider which the clock setup might have left in
+ * an undesirable state
+ *
+ * initial setup is:
+ * - MCLK 0 from SYS
+ * - MCLK DIV such to not exceed the IPS clock
+ * - MCLK 0 enabled
+ * - MCLK 1 from MCLK DIV
+ */
+ div = clk_get_rate(clks[MPC512x_CLK_SYS]);
+ div /= clk_get_rate(clks[MPC512x_CLK_IPS]);
+ out_be32(mccr_reg, (0 << 16));
+ out_be32(mccr_reg, (0 << 16) | ((div - 1) << 17));
+ out_be32(mccr_reg, (1 << 16) | ((div - 1) << 17));
+
+ /*
+ * create the 'struct clk' items of the MCLK's clock subtree
+ *
+ * note that by design we always create all nodes and won't take
+ * shortcuts here, because
+ * - the "internal" MCLK_DIV and MCLK_OUT signal in turn are
+ * selectable inputs to the CFM while those who "actually use"
+ * the PSC/MSCAN/SPDIF (serial drivers et al) need the MCLK
+ * for their bitrate
+ * - in the absence of "aliases" for clocks we need to create
+ * individial 'struct clk' items for whatever might get
+ * referenced or looked up, even if several of those items are
+ * identical from the logical POV (their rate value)
+ * - for easier future maintenance and for better reflection of
+ * the SoC's documentation, it appears appropriate to generate
+ * clock items even for those muxers which actually are NOPs
+ * (those with two inputs of which one is reserved)
+ */
+ clks[clks_idx_int + MCLK_IDX_MUX0] = mpc512x_clk_muxed(
+ entry->name_mux0,
+ &parent_names_mux0[0], ARRAY_SIZE(parent_names_mux0),
+ mccr_reg, 14, 2);
+ clks[clks_idx_int + MCLK_IDX_EN0] = mpc512x_clk_gated(
+ entry->name_en0, entry->name_mux0,
+ mccr_reg, 16);
+ clks[clks_idx_int + MCLK_IDX_DIV0] = mpc512x_clk_divider(
+ entry->name_div0,
+ entry->name_en0, CLK_SET_RATE_GATE,
+ mccr_reg, 17, 15, 0);
+ if (entry->has_mclk1) {
+ clks[clks_idx_pub] = mpc512x_clk_muxed(
+ entry->name_mclk,
+ &entry->parent_names_mux1[0],
+ ARRAY_SIZE(entry->parent_names_mux1),
+ mccr_reg, 7, 1);
+ } else {
+ clks[clks_idx_pub] = mpc512x_clk_factor(
+ entry->name_mclk,
+ entry->parent_names_mux1[0],
+ 1, 1);
+ }
+
+ /*
+ * without this "clock device" registration, "simple" lookups in
+ * the SPI master initialization and serial port setup will fail
+ *
+ * those drivers need to get adjusted to lookup their required
+ * clocks from device tree specs, and device tree nodes need to
+ * provide the clock specs, before this clkdev registration
+ * becomes obsolete
+ */
+ clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
+}
+
+static void mpc512x_clk_setup_clock_tree(int busfreq)
+{
+ int sys_mul, sys_div, ips_div;
+ int mul, div;
+ size_t mclk_idx;
+ int freq;
+
+ /*
+ * TODO
+ * - consider whether to handle clocks which have both gates and
+ * dividers via intermediates or by means of composites
+ * - fractional dividers appear to not map well to composites
+ * since they can be seen as a fixed multiplier and an
+ * adjustable divider, while composites can only combine at
+ * most one of a mux, div, and gate each into one 'struct clk'
+ * item
+ * - PSC/MSCAN/SPDIF clock generation OTOH already is very
+ * specific and cannot get mapped to componsites (at least not
+ * a single one, maybe two of them, but see the comment about
+ * "intermediates are referenced from elsewhere, too")
+ * - trim the list of auto-enabled clocks after drivers acquire
+ * them correctly as needed
+ */
+
+ /* regardless of whether XTAL/OSC exists, have REF created */
+ mpc512x_clk_setup_ref_clock(busfreq, &sys_mul, &sys_div, &ips_div);
+
+ /* now setup the REF -> SYS -> CSB -> IPS hierarchy */
+ clks[MPC512x_CLK_SYS] = mpc512x_clk_factor("sys", "ref",
+ sys_mul, sys_div);
+ clks[MPC512x_CLK_CSB] = mpc512x_clk_factor("csb", "sys", 1, 2);
+ clks[MPC512x_CLK_IPS] = mpc512x_clk_divtable("ips", "csb",
+ &clkregs->scfr1, 23, 3,
+ divtab_2346);
+
+ /* now setup anything below SYS and CSB and IPS */
+ clks[MPC512x_CLK_DDR_UG] = mpc512x_clk_factor("ddr-ug", "sys", 1, 2);
+ clks[MPC512x_CLK_SDHC_x4] = mpc512x_clk_factor("sdhc-x4", "csb", 4, 1);
+ clks[MPC512x_CLK_SDHC_UG] = mpc512x_clk_divider("sdhc-ug", "sdhc-x4", 0,
+ &clkregs->scfr2, 0, 8,
+ CLK_DIVIDER_ONE_BASED);
+ clks[MPC512x_CLK_DIU_x4] = mpc512x_clk_factor("diu-x4", "csb", 4, 1);
+ clks[MPC512x_CLK_DIU_UG] = mpc512x_clk_divider("diu-ug", "diu-x4", 0,
+ &clkregs->scfr1, 0, 8,
+ CLK_DIVIDER_ONE_BASED);
+
+ /*
+ * the "power architecture PLL" was setup from data which was
+ * sampled from the reset config word, at this point in time the
+ * configuration can be considered fixed and read only (i.e. no
+ * longer adjustable, or no longer in need of adjustment), which
+ * is why we don't register a PLL here but assume fixed factors
+ */
+ mul = get_cpmf_mult_x2();
+ div = 2; /* compensate for the fractional factor */
+ clks[MPC512x_CLK_E300] = mpc512x_clk_factor("e300", "csb", mul, div);
+
+ clks[MPC512x_CLK_MBX_BUS_UG] = mpc512x_clk_factor("mbx-bus-ug", "csb",
+ 1, 2);
+ clks[MPC512x_CLK_MBX_UG] = mpc512x_clk_divtable("mbx-ug", "mbx-bus-ug",
+ &clkregs->scfr1, 14, 3,
+ divtab_1234);
+ clks[MPC512x_CLK_MBX_3D_UG] = mpc512x_clk_factor("mbx-3d-ug", "mbx-ug",
+ 1, 1);
+ clks[MPC512x_CLK_PCI_UG] = mpc512x_clk_divtable("pci-ug", "csb",
+ &clkregs->scfr1, 20, 3,
+ divtab_2346);
+ clks[MPC512x_CLK_NFC_UG] = mpc512x_clk_divtable("nfc-ug", "ips",
+ &clkregs->scfr1, 8, 3,
+ divtab_1234);
+ clks[MPC512x_CLK_LPC_UG] = mpc512x_clk_divtable("lpc-ug", "ips",
+ &clkregs->scfr1, 11, 3,
+ divtab_1234);
+
+ clks[MPC512x_CLK_LPC] = mpc512x_clk_gated("lpc", "lpc-ug",
+ &clkregs->sccr1, 30);
+ clks[MPC512x_CLK_NFC] = mpc512x_clk_gated("nfc", "nfc-ug",
+ &clkregs->sccr1, 29);
+ clks[MPC512x_CLK_PATA] = mpc512x_clk_gated("pata", "ips",
+ &clkregs->sccr1, 28);
+ /* for PSCs there is a "registers" gate and a bitrate MCLK subtree */
+ for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_psc_data); mclk_idx++) {
+ char name[12];
+ snprintf(name, sizeof(name), "psc%d", mclk_idx);
+ clks[MPC512x_CLK_PSC0 + mclk_idx] = mpc512x_clk_gated(
+ name, "ips", &clkregs->sccr1, 27 - mclk_idx);
+ mpc512x_clk_setup_mclk(&mclk_psc_data[mclk_idx], mclk_idx);
+ }
+ clks[MPC512x_CLK_PSC_FIFO] = mpc512x_clk_gated("psc-fifo", "ips",
+ &clkregs->sccr1, 15);
+ clks[MPC512x_CLK_SATA] = mpc512x_clk_gated("sata", "ips",
+ &clkregs->sccr1, 14);
+ clks[MPC512x_CLK_FEC] = mpc512x_clk_gated("fec", "ips",
+ &clkregs->sccr1, 13);
+ clks[MPC512x_CLK_PCI] = mpc512x_clk_gated("pci", "pci-ug",
+ &clkregs->sccr1, 11);
+ clks[MPC512x_CLK_DDR] = mpc512x_clk_gated("ddr", "ddr-ug",
+ &clkregs->sccr1, 10);
+
+ clks[MPC512x_CLK_DIU] = mpc512x_clk_gated("diu", "diu-ug",
+ &clkregs->sccr2, 31);
+ clks[MPC512x_CLK_AXE] = mpc512x_clk_gated("axe", "csb",
+ &clkregs->sccr2, 30);
+ clks[MPC512x_CLK_MEM] = mpc512x_clk_gated("mem", "ips",
+ &clkregs->sccr2, 29);
+ clks[MPC512x_CLK_USB1] = mpc512x_clk_gated("usb1", "csb",
+ &clkregs->sccr2, 28);
+ clks[MPC512x_CLK_USB2] = mpc512x_clk_gated("usb2", "csb",
+ &clkregs->sccr2, 27);
+ clks[MPC512x_CLK_I2C] = mpc512x_clk_gated("i2c", "ips",
+ &clkregs->sccr2, 26);
+ /* MSCAN differs from PSC with just one gate for multiple components */
+ clks[MPC512x_CLK_BDLC] = mpc512x_clk_gated("bdlc", "ips",
+ &clkregs->sccr2, 25);
+ for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_mscan_data); mclk_idx++)
+ mpc512x_clk_setup_mclk(&mclk_mscan_data[mclk_idx], mclk_idx);
+ clks[MPC512x_CLK_SDHC] = mpc512x_clk_gated("sdhc", "sdhc-ug",
+ &clkregs->sccr2, 24);
+ /* there is only one SPDIF component, which shares MCLK support code */
+ clks[MPC512x_CLK_SPDIF] = mpc512x_clk_gated("spdif", "ips",
+ &clkregs->sccr2, 23);
+ mpc512x_clk_setup_mclk(&mclk_spdif_data[0], 0);
+ clks[MPC512x_CLK_MBX_BUS] = mpc512x_clk_gated("mbx-bus", "mbx-bus-ug",
+ &clkregs->sccr2, 22);
+ clks[MPC512x_CLK_MBX] = mpc512x_clk_gated("mbx", "mbx-ug",
+ &clkregs->sccr2, 21);
+ clks[MPC512x_CLK_MBX_3D] = mpc512x_clk_gated("mbx-3d", "mbx-3d-ug",
+ &clkregs->sccr2, 20);
+ clks[MPC512x_CLK_IIM] = mpc512x_clk_gated("iim", "csb",
+ &clkregs->sccr2, 19);
+ clks[MPC512x_CLK_VIU] = mpc512x_clk_gated("viu", "csb",
+ &clkregs->sccr2, 18);
+ clks[MPC512x_CLK_SDHC_2] = mpc512x_clk_gated("sdhc-2", "sdhc-ug",
+ &clkregs->sccr2, 17);
+
+ /*
+ * externally provided clocks (when implemented in hardware,
+ * device tree may specify values which otherwise were unknown)
+ */
+ freq = get_freq_from_dt("psc_mclk_in");
+ if (!freq)
+ freq = 25000000;
+ clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq);
+ freq = get_freq_from_dt("spdif_tx_in");
+ clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_tx_in", freq);
+ freq = get_freq_from_dt("spdif_rx_in");
+ clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_rx_in", freq);
+
+ /* fixed frequency for AC97, always 24.567MHz */
+ clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000);
+
+ /* clkdev registration for compatibility reasons */
+ clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
+ clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
+ clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
+ clk_register_clkdev(clks[MPC512x_CLK_NFC], "nfc_clk", NULL);
+ clk_register_clkdev(clks[MPC512x_CLK_USB1], "usb1_clk", NULL);
+ clk_register_clkdev(clks[MPC512x_CLK_USB2], "usb2_clk", NULL);
+
+ /* enable some of the clocks here unconditionally because ... */
+ pr_debug("automatically enabling some clocks\n");
+ /* some are essential yet never get claimed by any driver */
+ clk_prepare_enable(clks[MPC512x_CLK_DUMMY]);
+ clk_prepare_enable(clks[MPC512x_CLK_E300]); /* PowerPC CPU */
+ clk_prepare_enable(clks[MPC512x_CLK_DDR]); /* DRAM */
+ clk_prepare_enable(clks[MPC512x_CLK_MEM]); /* SRAM */
+ clk_prepare_enable(clks[MPC512x_CLK_IPS]); /* SoC periph */
+ clk_prepare_enable(clks[MPC512x_CLK_LPC]); /* boot media */
+ /* some are required yet no dependencies were declared */
+ clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
+ /* some are not yet acquired by their respective drivers */
+ clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
+ clk_prepare_enable(clks[MPC512x_CLK_FEC]); /* network, NFS */
+ clk_prepare_enable(clks[MPC512x_CLK_DIU]); /* display */
+ clk_prepare_enable(clks[MPC512x_CLK_I2C]);
+ for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_psc_data); mclk_idx++)
+ clk_prepare_enable(clks[MPC512x_CLK_PSC0 + mclk_idx]);
+ clk_prepare_enable(clks[MPC512x_CLK_BDLC]);
+ for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_mscan_data); mclk_idx++)
+ clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK + mclk_idx]);
+}
+
+/*
+ * registers the set of public clocks (those listed in the dt-bindings/
+ * header file) for OF lookups, keeps the intermediates private to us
+ */
+static void mpc5121_clk_register_of_provider(struct device_node *np)
+{
+ clk_data.clks = clks;
+ clk_data.clk_num = MPC512x_CLK_LAST_PUBLIC + 1; /* _not_ ARRAY_SIZE() */
+ of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+}
+
+int __init mpc5121_clk_init(void)
+{
+ struct device_node *clk_np;
+ int busfreq;
+
+ /* map the clock control registers */
+ clk_np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+ if (!clk_np)
+ return -ENODEV;
+ clkregs = of_iomap(clk_np, 0);
+ WARN_ON(!clkregs);
+
+ /* invalidate all not yet registered clock slots */
+ mpc512x_clk_preset_data();
+
+ /*
+ * have the device tree scanned for "fixed-clock" nodes (which
+ * includes the oscillator node if the board's DT provides one)
+ */
+ of_clk_init(NULL);
+
+ /*
+ * add a dummy clock for those situations where a clock spec is
+ * required yet no real clock is involved
+ */
+ clks[MPC512x_CLK_DUMMY] = mpc512x_clk_fixed("dummy", 0);
+
+ /*
+ * have all the real nodes in the clock tree populated from REF
+ * down to all leaves, either starting from the OSC node or from
+ * a REF root that was created from the IPS bus clock input
+ */
+ busfreq = get_freq_from_dt("bus-frequency");
+ mpc512x_clk_setup_clock_tree(busfreq);
+
+ /* register as an OF clock provider */
+ mpc5121_clk_register_of_provider(clk_np);
+
+ return 0;
+}
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index c4f7799..7f8fc64 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -497,6 +497,20 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
* for improved portability across platforms
*/
+#if IS_ENABLED(CONFIG_PPC)
+
+static inline u32 clk_readl(u32 __iomem *reg)
+{
+ return ioread32be(reg);
+}
+
+static inline void clk_writel(u32 val, u32 __iomem *reg)
+{
+ iowrite32be(val, reg);
+}
+
+#else /* platform dependent I/O accessors */
+
static inline u32 clk_readl(u32 __iomem *reg)
{
return readl(reg);
@@ -507,5 +521,7 @@ static inline void clk_writel(u32 val, u32 __iomem *reg)
writel(val, reg);
}
+#endif /* platform dependent I/O accessors */
+
#endif /* CONFIG_COMMON_CLK */
#endif /* CLK_PROVIDER_H */
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 18/31] dts: mpc512x: add clock specs for client lookups
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
linux-arm-kernel, devicetree
Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
Wolfgang Grandegger, Mauro Carvalho Chehab
In-Reply-To: <1375821851-31609-1-git-send-email-gsi@denx.de>
this addresses the client side of device tree based clock lookups
add clock specifiers to the mbx, nfc, mscan, sdhc, i2c, axe, diu, viu,
mdio, fec, usb, pata, psc, psc fifo, and pci nodes in the shared
mpc5121.dtsi include
these specs map 'clock-names' encoded in drivers to their respective
'struct clk' items in the platform's clock driver
Reviewed-by: Mike Turquette <mturquette@linaro.org> # for v3: w/o bdlc, PSC ipg
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
arch/powerpc/boot/dts/mpc5121.dtsi | 95 ++++++++++++++++++++++++++++++++++++
1 file changed, 95 insertions(+)
diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index 8f4cba0..4cef164 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -51,6 +51,10 @@
compatible = "fsl,mpc5121-mbx";
reg = <0x20000000 0x4000>;
interrupts = <66 0x8>;
+ clocks = <&clks MPC512x_CLK_MBX_BUS>,
+ <&clks MPC512x_CLK_MBX_3D>,
+ <&clks MPC512x_CLK_MBX>;
+ clock-names = "mbx-bus", "mbx-3d", "mbx";
};
sram@30000000 {
@@ -64,6 +68,8 @@
interrupts = <6 8>;
#address-cells = <1>;
#size-cells = <1>;
+ clocks = <&clks MPC512x_CLK_NFC>;
+ clock-names = "per";
};
localbus@80000020 {
@@ -153,12 +159,24 @@
compatible = "fsl,mpc5121-mscan";
reg = <0x1300 0x80>;
interrupts = <12 0x8>;
+ clocks = <&clks MPC512x_CLK_IPS>,
+ <&clks MPC512x_CLK_SYS>,
+ <&clks MPC512x_CLK_REF>,
+ <&clks MPC512x_CLK_MSCAN0_MCLK>,
+ <&clks MPC512x_CLK_BDLC>;
+ clock-names = "ips", "sys", "ref", "mclk", "ipg";
};
can@1380 {
compatible = "fsl,mpc5121-mscan";
reg = <0x1380 0x80>;
interrupts = <13 0x8>;
+ clocks = <&clks MPC512x_CLK_IPS>,
+ <&clks MPC512x_CLK_SYS>,
+ <&clks MPC512x_CLK_REF>,
+ <&clks MPC512x_CLK_MSCAN1_MCLK>,
+ <&clks MPC512x_CLK_BDLC>;
+ clock-names = "ips", "sys", "ref", "mclk", "ipg";
};
sdhc@1500 {
@@ -167,6 +185,9 @@
interrupts = <8 0x8>;
dmas = <&dma0 30>;
dma-names = "rx-tx";
+ clocks = <&clks MPC512x_CLK_IPS>,
+ <&clks MPC512x_CLK_SDHC>;
+ clock-names = "ipg", "per";
};
i2c@1700 {
@@ -175,6 +196,8 @@
compatible = "fsl,mpc5121-i2c", "fsl-i2c";
reg = <0x1700 0x20>;
interrupts = <9 0x8>;
+ clocks = <&clks MPC512x_CLK_I2C>;
+ clock-names = "per";
};
i2c@1720 {
@@ -183,6 +206,8 @@
compatible = "fsl,mpc5121-i2c", "fsl-i2c";
reg = <0x1720 0x20>;
interrupts = <10 0x8>;
+ clocks = <&clks MPC512x_CLK_I2C>;
+ clock-names = "per";
};
i2c@1740 {
@@ -191,6 +216,8 @@
compatible = "fsl,mpc5121-i2c", "fsl-i2c";
reg = <0x1740 0x20>;
interrupts = <11 0x8>;
+ clocks = <&clks MPC512x_CLK_I2C>;
+ clock-names = "per";
};
i2ccontrol@1760 {
@@ -202,30 +229,48 @@
compatible = "fsl,mpc5121-axe";
reg = <0x2000 0x100>;
interrupts = <42 0x8>;
+ clocks = <&clks MPC512x_CLK_AXE>;
+ clock-names = "per";
};
display@2100 {
compatible = "fsl,mpc5121-diu";
reg = <0x2100 0x100>;
interrupts = <64 0x8>;
+ clocks = <&clks MPC512x_CLK_DIU>;
+ clock-names = "per";
};
can@2300 {
compatible = "fsl,mpc5121-mscan";
reg = <0x2300 0x80>;
interrupts = <90 0x8>;
+ clocks = <&clks MPC512x_CLK_IPS>,
+ <&clks MPC512x_CLK_SYS>,
+ <&clks MPC512x_CLK_REF>,
+ <&clks MPC512x_CLK_MSCAN2_MCLK>,
+ <&clks MPC512x_CLK_BDLC>;
+ clock-names = "ips", "sys", "ref", "mclk", "ipg";
};
can@2380 {
compatible = "fsl,mpc5121-mscan";
reg = <0x2380 0x80>;
interrupts = <91 0x8>;
+ clocks = <&clks MPC512x_CLK_IPS>,
+ <&clks MPC512x_CLK_SYS>,
+ <&clks MPC512x_CLK_REF>,
+ <&clks MPC512x_CLK_MSCAN3_MCLK>,
+ <&clks MPC512x_CLK_BDLC>;
+ clock-names = "ips", "sys", "ref", "mclk", "ipg";
};
viu@2400 {
compatible = "fsl,mpc5121-viu";
reg = <0x2400 0x400>;
interrupts = <67 0x8>;
+ clocks = <&clks MPC512x_CLK_VIU>;
+ clock-names = "per";
};
mdio@2800 {
@@ -233,6 +278,8 @@
reg = <0x2800 0x800>;
#address-cells = <1>;
#size-cells = <0>;
+ clocks = <&clks MPC512x_CLK_FEC>;
+ clock-names = "per";
};
eth0: ethernet@2800 {
@@ -241,6 +288,8 @@
reg = <0x2800 0x800>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <4 0x8>;
+ clocks = <&clks MPC512x_CLK_FEC>;
+ clock-names = "per";
};
/* USB1 using external ULPI PHY */
@@ -252,6 +301,8 @@
interrupts = <43 0x8>;
dr_mode = "otg";
phy_type = "ulpi";
+ clocks = <&clks MPC512x_CLK_USB1>;
+ clock-names = "per";
};
/* USB0 using internal UTMI PHY */
@@ -263,6 +314,8 @@
interrupts = <44 0x8>;
dr_mode = "otg";
phy_type = "utmi_wide";
+ clocks = <&clks MPC512x_CLK_USB2>;
+ clock-names = "per";
};
/* IO control */
@@ -281,6 +334,8 @@
compatible = "fsl,mpc5121-pata";
reg = <0x10200 0x100>;
interrupts = <5 0x8>;
+ clocks = <&clks MPC512x_CLK_PATA>;
+ clock-names = "per";
};
/* 512x PSCs are not 52xx PSC compatible */
@@ -292,6 +347,9 @@
interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>;
+ clocks = <&clks MPC512x_CLK_PSC0_MCLK>,
+ <&clks MPC512x_CLK_PSC0>;
+ clock-names = "mclk", "ipg";
};
/* PSC1 */
@@ -301,6 +359,9 @@
interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>;
+ clocks = <&clks MPC512x_CLK_PSC1_MCLK>,
+ <&clks MPC512x_CLK_PSC1>;
+ clock-names = "mclk", "ipg";
};
/* PSC2 */
@@ -310,6 +371,9 @@
interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>;
+ clocks = <&clks MPC512x_CLK_PSC2_MCLK>,
+ <&clks MPC512x_CLK_PSC2>;
+ clock-names = "mclk", "ipg";
};
/* PSC3 */
@@ -319,6 +383,9 @@
interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>;
+ clocks = <&clks MPC512x_CLK_PSC3_MCLK>,
+ <&clks MPC512x_CLK_PSC3>;
+ clock-names = "mclk", "ipg";
};
/* PSC4 */
@@ -328,6 +395,9 @@
interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>;
+ clocks = <&clks MPC512x_CLK_PSC4_MCLK>,
+ <&clks MPC512x_CLK_PSC4>;
+ clock-names = "mclk", "ipg";
};
/* PSC5 */
@@ -337,6 +407,9 @@
interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>;
+ clocks = <&clks MPC512x_CLK_PSC5_MCLK>,
+ <&clks MPC512x_CLK_PSC5>;
+ clock-names = "mclk", "ipg";
};
/* PSC6 */
@@ -346,6 +419,9 @@
interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>;
+ clocks = <&clks MPC512x_CLK_PSC6_MCLK>,
+ <&clks MPC512x_CLK_PSC6>;
+ clock-names = "mclk", "ipg";
};
/* PSC7 */
@@ -355,6 +431,9 @@
interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>;
+ clocks = <&clks MPC512x_CLK_PSC7_MCLK>,
+ <&clks MPC512x_CLK_PSC7>;
+ clock-names = "mclk", "ipg";
};
/* PSC8 */
@@ -364,6 +443,9 @@
interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>;
+ clocks = <&clks MPC512x_CLK_PSC8_MCLK>,
+ <&clks MPC512x_CLK_PSC8>;
+ clock-names = "mclk", "ipg";
};
/* PSC9 */
@@ -373,6 +455,9 @@
interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>;
+ clocks = <&clks MPC512x_CLK_PSC9_MCLK>,
+ <&clks MPC512x_CLK_PSC9>;
+ clock-names = "mclk", "ipg";
};
/* PSC10 */
@@ -382,6 +467,9 @@
interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>;
+ clocks = <&clks MPC512x_CLK_PSC10_MCLK>,
+ <&clks MPC512x_CLK_PSC10>;
+ clock-names = "mclk", "ipg";
};
/* PSC11 */
@@ -391,12 +479,17 @@
interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>;
+ clocks = <&clks MPC512x_CLK_PSC11_MCLK>,
+ <&clks MPC512x_CLK_PSC11>;
+ clock-names = "mclk", "ipg";
};
pscfifo@11f00 {
compatible = "fsl,mpc5121-psc-fifo";
reg = <0x11f00 0x100>;
interrupts = <40 0x8>;
+ clocks = <&clks MPC512x_CLK_PSC_FIFO>;
+ clock-names = "per";
};
dma0: dma@14000 {
@@ -414,6 +507,8 @@
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
+ clocks = <&clks MPC512x_CLK_PCI>;
+ clock-names = "per";
reg = <0x80008500 0x100 /* internal registers */
0x80008300 0x8>; /* config space access registers */
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 19/31] clk: mpc512x: don't pre-enable FEC and I2C clocks
From: Gerhard Sittig @ 2013-08-06 20:43 UTC (permalink / raw)
To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
linux-arm-kernel, devicetree
Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
Wolfgang Grandegger, Mauro Carvalho Chehab
In-Reply-To: <1375821851-31609-1-git-send-email-gsi@denx.de>
after the device tree nodes provide clock specs for client side lookups,
peripheral drivers can attach to their clocks and the clock driver need
no longer pre-enable those clock items
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
arch/powerpc/platforms/512x/clock-commonclk.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 09721d5..3f559fe 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -685,9 +685,7 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
/* some are not yet acquired by their respective drivers */
clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
- clk_prepare_enable(clks[MPC512x_CLK_FEC]); /* network, NFS */
clk_prepare_enable(clks[MPC512x_CLK_DIU]); /* display */
- clk_prepare_enable(clks[MPC512x_CLK_I2C]);
for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_psc_data); mclk_idx++)
clk_prepare_enable(clks[MPC512x_CLK_PSC0 + mclk_idx]);
clk_prepare_enable(clks[MPC512x_CLK_BDLC]);
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 20/31] spi: mpc512x: switch to CCF names in clock lookup
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
linux-arm-kernel, devicetree
Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
Wolfgang Grandegger, Mauro Carvalho Chehab
In-Reply-To: <1375821851-31609-1-git-send-email-gsi@denx.de>
after device tree based clock lookup became available, the peripheral
driver need no longer construct clock names which include the PSC index,
remove the "psc%d_mclk" template and unconditionally use 'mclk'
acquire and release the 'ipg' clock for register access as well
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
drivers/spi/spi-mpc512x-psc.c | 30 +++++++++++++++++++++---------
1 file changed, 21 insertions(+), 9 deletions(-)
diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 85581f3..daedee7 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -38,6 +38,7 @@ struct mpc512x_psc_spi {
struct mpc512x_psc_fifo __iomem *fifo;
unsigned int irq;
u8 bits_per_word;
+ struct clk *clk_ipg;
struct clk *clk_mclk;
u32 mclk_rate;
@@ -474,8 +475,6 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
struct spi_master *master;
int ret;
void *tempp;
- int psc_num;
- char clk_name[16];
struct clk *clk;
master = spi_alloc_master(dev, sizeof *mps);
@@ -519,29 +518,41 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
goto free_master;
init_completion(&mps->txisrdone);
- psc_num = master->bus_num;
- snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
- clk = devm_clk_get(dev, clk_name);
- if (IS_ERR(clk))
+ clk = devm_clk_get(dev, "ipg");
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
goto free_irq;
+ }
ret = clk_prepare_enable(clk);
if (ret)
goto free_irq;
+ mps->clk_ipg = clk;
+
+ clk = devm_clk_get(dev, "mclk");
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ goto free_ipg_clock;
+ }
+ ret = clk_prepare_enable(clk);
+ if (ret)
+ goto free_ipg_clock;
mps->clk_mclk = clk;
mps->mclk_rate = clk_get_rate(clk);
ret = mpc512x_psc_spi_port_config(master, mps);
if (ret < 0)
- goto free_clock;
+ goto free_mclk_clock;
ret = spi_register_master(master);
if (ret < 0)
- goto free_clock;
+ goto free_mclk_clock;
return ret;
-free_clock:
+free_mclk_clock:
clk_disable_unprepare(mps->clk_mclk);
+free_ipg_clock:
+ clk_disable_unprepare(mps->clk_ipg);
free_irq:
free_irq(mps->irq, mps);
free_master:
@@ -559,6 +570,7 @@ static int mpc512x_psc_spi_do_remove(struct device *dev)
spi_unregister_master(master);
clk_disable_unprepare(mps->clk_mclk);
+ clk_disable_unprepare(mps->clk_ipg);
free_irq(mps->irq, mps);
if (mps->psc)
iounmap(mps->psc);
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 21/31] serial: mpc512x: switch to CCF names in clock lookup
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
linux-arm-kernel, devicetree
Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
Wolfgang Grandegger, Mauro Carvalho Chehab
In-Reply-To: <1375821851-31609-1-git-send-email-gsi@denx.de>
after device tree based clock lookup became available, the peripheral
driver need no longer construct clock names which include the PSC index,
remove the "psc%d_mclk" template and unconditionally use 'mclk'
acquire and release the 'ipg' clock for register access as well
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
drivers/tty/serial/mpc52xx_uart.c | 45 ++++++++++++++++++++++++++++++++-----
1 file changed, 40 insertions(+), 5 deletions(-)
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 5be1df3..f4d2b70 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -618,30 +618,58 @@ static irqreturn_t mpc512x_psc_handle_irq(struct uart_port *port)
return IRQ_NONE;
}
+static struct clk *psc_ipg_clk[MPC52xx_PSC_MAXNUM];
static struct clk *psc_mclk_clk[MPC52xx_PSC_MAXNUM];
/* called from within the .request_port() callback (allocation) */
static int mpc512x_psc_alloc_clock(struct uart_port *port)
{
int psc_num;
- char clk_name[16];
struct clk *clk;
int err;
psc_num = (port->mapbase & 0xf00) >> 8;
- snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
- clk = devm_clk_get(port->dev, clk_name);
+
+ clk = devm_clk_get(port->dev, "ipg");
+ if (IS_ERR(clk)) {
+ dev_err(port->dev, "Failed to get IPG clock!\n");
+ err = PTR_ERR(clk);
+ goto out_err;
+ }
+ err = clk_prepare_enable(clk);
+ if (err) {
+ dev_err(port->dev, "Failed to enable IPG clock!\n");
+ goto out_err;
+ }
+ psc_ipg_clk[psc_num] = clk;
+
+ clk = devm_clk_get(port->dev, "mclk");
if (IS_ERR(clk)) {
dev_err(port->dev, "Failed to get MCLK!\n");
- return PTR_ERR(clk);
+ err = PTR_ERR(clk);
+ goto out_err;
}
err = clk_prepare_enable(clk);
if (err) {
dev_err(port->dev, "Failed to enable MCLK!\n");
- return err;
+ goto out_err;
}
psc_mclk_clk[psc_num] = clk;
+
return 0;
+
+out_err:
+ clk = psc_mclk_clk[psc_num];
+ if (clk) {
+ clk_disable_unprepare(clk);
+ psc_mclk_clk[psc_num] = NULL;
+ }
+ clk = psc_ipg_clk[psc_num];
+ if (clk) {
+ clk_disable_unprepare(clk);
+ psc_ipg_clk[psc_num] = NULL;
+ }
+ return err;
}
/* called from within the .release_port() callback (release) */
@@ -651,11 +679,18 @@ static void mpc512x_psc_relse_clock(struct uart_port *port)
struct clk *clk;
psc_num = (port->mapbase & 0xf00) >> 8;
+
clk = psc_mclk_clk[psc_num];
if (clk) {
clk_disable_unprepare(clk);
psc_mclk_clk[psc_num] = NULL;
}
+
+ clk = psc_ipg_clk[psc_num];
+ if (clk) {
+ clk_disable_unprepare(clk);
+ psc_ipg_clk[psc_num] = NULL;
+ }
}
/* implementation of the .clock() callback (enable/disable) */
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 22/31] clk: mpc512x: remove PSC (UART, SPI) compat workarounds
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
linux-arm-kernel, devicetree
Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
Wolfgang Grandegger, Mauro Carvalho Chehab
In-Reply-To: <1375821851-31609-1-git-send-email-gsi@denx.de>
after the UART and SPI peripheral drivers have switched to device tree
based clock lookup and no longer construct clock names from their PSC
component index, the "psc%d_mclk" alias names have become obsolete --
remove the corresponding clk_register_clkdev() calls
after the UART and SPI peripheral drivers acquire the 'ipg' clock item,
the platform's clock driver need no longer pre-enable it
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
arch/powerpc/platforms/512x/clock-commonclk.c | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 3f559fe..bd704b3 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -500,17 +500,6 @@ static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry, size_t idx)
entry->parent_names_mux1[0],
1, 1);
}
-
- /*
- * without this "clock device" registration, "simple" lookups in
- * the SPI master initialization and serial port setup will fail
- *
- * those drivers need to get adjusted to lookup their required
- * clocks from device tree specs, and device tree nodes need to
- * provide the clock specs, before this clkdev registration
- * becomes obsolete
- */
- clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
}
static void mpc512x_clk_setup_clock_tree(int busfreq)
@@ -686,8 +675,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
/* some are not yet acquired by their respective drivers */
clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
clk_prepare_enable(clks[MPC512x_CLK_DIU]); /* display */
- for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_psc_data); mclk_idx++)
- clk_prepare_enable(clks[MPC512x_CLK_PSC0 + mclk_idx]);
clk_prepare_enable(clks[MPC512x_CLK_BDLC]);
for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_mscan_data); mclk_idx++)
clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK + mclk_idx]);
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 23/31] serial: mpc512x: setup the PSC FIFO clock as well
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
linux-arm-kernel, devicetree
Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
Wolfgang Grandegger, Mauro Carvalho Chehab
In-Reply-To: <1375821851-31609-1-git-send-email-gsi@denx.de>
prepare and enable the FIFO clock upon PSC FIFO initialization,
check for and propagage errors when enabling the PSC FIFO clock,
disable and unprepare the FIFO clock upon PSC FIFO uninitialization,
remove the pre-enable workaround from the platform's clock driver
devm_{get,put}_clk() doesn't apply here, as the SoC provides a
single FIFO component which is shared among several PSC components,
thus the FIFO isn't associated with a device (while the PSCs are)
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
arch/powerpc/platforms/512x/clock-commonclk.c | 2 --
drivers/tty/serial/mpc52xx_uart.c | 46 +++++++++++++++++++++----
2 files changed, 40 insertions(+), 8 deletions(-)
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index bd704b3..803f3be 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -670,8 +670,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
clk_prepare_enable(clks[MPC512x_CLK_MEM]); /* SRAM */
clk_prepare_enable(clks[MPC512x_CLK_IPS]); /* SoC periph */
clk_prepare_enable(clks[MPC512x_CLK_LPC]); /* boot media */
- /* some are required yet no dependencies were declared */
- clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
/* some are not yet acquired by their respective drivers */
clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
clk_prepare_enable(clks[MPC512x_CLK_DIU]); /* display */
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index f4d2b70..d16ed6c 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -421,6 +421,7 @@ struct psc_fifoc {
static struct psc_fifoc __iomem *psc_fifoc;
static unsigned int psc_fifoc_irq;
+static struct clk *psc_fifoc_clk;
static void mpc512x_psc_fifo_init(struct uart_port *port)
{
@@ -568,36 +569,69 @@ static unsigned int mpc512x_psc_set_baudrate(struct uart_port *port,
/* Init PSC FIFO Controller */
static int __init mpc512x_psc_fifoc_init(void)
{
+ int err;
struct device_node *np;
+ struct clk *clk;
+
+ /* default error code, potentially overwritten by clock calls */
+ err = -ENODEV;
np = of_find_compatible_node(NULL, NULL,
"fsl,mpc5121-psc-fifo");
if (!np) {
pr_err("%s: Can't find FIFOC node\n", __func__);
- return -ENODEV;
+ goto out_err;
}
+ clk = of_clk_get_by_name(np, "per");
+ if (IS_ERR(clk)) {
+ pr_err("%s: Can't lookup FIFO clock\n", __func__);
+ err = PTR_ERR(clk);
+ goto out_ofnode_put;
+ }
+ if (clk_prepare_enable(clk)) {
+ pr_err("%s: Can't enable FIFO clock\n", __func__);
+ clk_put(clk);
+ goto out_ofnode_put;
+ }
+ psc_fifoc_clk = clk;
+
psc_fifoc = of_iomap(np, 0);
if (!psc_fifoc) {
pr_err("%s: Can't map FIFOC\n", __func__);
- of_node_put(np);
- return -ENODEV;
+ goto out_clk_disable;
}
psc_fifoc_irq = irq_of_parse_and_map(np, 0);
- of_node_put(np);
if (psc_fifoc_irq == 0) {
pr_err("%s: Can't get FIFOC irq\n", __func__);
- iounmap(psc_fifoc);
- return -ENODEV;
+ goto out_unmap;
}
+ of_node_put(np);
return 0;
+
+out_unmap:
+ iounmap(psc_fifoc);
+out_clk_disable:
+ clk_disable_unprepare(psc_fifoc_clk);
+ clk_put(psc_fifoc_clk);
+out_ofnode_put:
+ of_node_put(np);
+out_err:
+ return err;
}
static void __exit mpc512x_psc_fifoc_uninit(void)
{
iounmap(psc_fifoc);
+
+ /* disable the clock, errors are not fatal */
+ if (psc_fifoc_clk) {
+ clk_disable_unprepare(psc_fifoc_clk);
+ clk_put(psc_fifoc_clk);
+ psc_fifoc_clk = NULL;
+ }
}
/* 512x specific interrupt handler. The caller holds the port lock */
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 24/31] USB: fsl-mph-dr-of: remove now obsolete clock lookup name
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
linux-arm-kernel, devicetree
Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
Wolfgang Grandegger, Mauro Carvalho Chehab
In-Reply-To: <1375821851-31609-1-git-send-email-gsi@denx.de>
after device tree based clock lookup became available, the peripheral
driver need no longer construct clock names which include the component
index -- remove the "usb%d_clk" template and unconditionally use "per",
remove the clock driver's clkdev registration
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
arch/powerpc/platforms/512x/clock-commonclk.c | 2 --
drivers/usb/host/fsl-mph-dr-of.c | 13 +------------
2 files changed, 1 insertion(+), 14 deletions(-)
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 803f3be..4615fad 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -658,8 +658,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
clk_register_clkdev(clks[MPC512x_CLK_NFC], "nfc_clk", NULL);
- clk_register_clkdev(clks[MPC512x_CLK_USB1], "usb1_clk", NULL);
- clk_register_clkdev(clks[MPC512x_CLK_USB2], "usb2_clk", NULL);
/* enable some of the clocks here unconditionally because ... */
pr_debug("automatically enabling some clocks\n");
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index b8a1866..2b323fb 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -261,19 +261,8 @@ int fsl_usb2_mpc5121_init(struct platform_device *pdev)
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
struct clk *clk;
int err;
- char clk_name[10];
- int base, clk_num;
-
- base = pdev->resource->start & 0xf000;
- if (base == 0x3000)
- clk_num = 1;
- else if (base == 0x4000)
- clk_num = 2;
- else
- return -ENODEV;
- snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num);
- clk = devm_clk_get(&pdev->dev, clk_name);
+ clk = devm_clk_get(&pdev->dev, "per");
if (IS_ERR(clk)) {
dev_err(&pdev->dev, "failed to get clk\n");
return PTR_ERR(clk);
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 25/31] mtd: mpc5121_nfc: remove now obsolete clock lookup name
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
linux-arm-kernel, devicetree
Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
Wolfgang Grandegger, Mauro Carvalho Chehab
In-Reply-To: <1375821851-31609-1-git-send-email-gsi@denx.de>
after device tree based clock lookup became available, the NAND flash
driver need no longer use the previous "nfc_clk" name but can switch to
the fixed "per" clock name -- adjust the peripheral driver and remove
the clock driver's clkdev registration
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
arch/powerpc/platforms/512x/clock-commonclk.c | 1 -
drivers/mtd/nand/mpc5121_nfc.c | 2 +-
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 4615fad..0e23b45 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -657,7 +657,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
- clk_register_clkdev(clks[MPC512x_CLK_NFC], "nfc_clk", NULL);
/* enable some of the clocks here unconditionally because ... */
pr_debug("automatically enabling some clocks\n");
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 3c60a00..e541ec0 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -729,7 +729,7 @@ static int mpc5121_nfc_probe(struct platform_device *op)
of_node_put(rootnode);
/* Enable NFC clock */
- clk = devm_clk_get(dev, "nfc_clk");
+ clk = devm_clk_get(dev, "per");
if (IS_ERR(clk)) {
dev_err(dev, "Unable to acquire NFC clock!\n");
retval = PTR_ERR(clk);
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 26/31] [media] fsl-viu: remove now obsolete clock lookup name
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
linux-arm-kernel, devicetree
Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
Wolfgang Grandegger, Mauro Carvalho Chehab
In-Reply-To: <1375821851-31609-1-git-send-email-gsi@denx.de>
after device tree based clock lookup became available, the VIU driver
need no longer use the previous "viu_clk" name but can switch to the
fixed "per" clock name -- adjust the peripheral driver and remove the
clock driver's clkdev registration
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
arch/powerpc/platforms/512x/clock-commonclk.c | 1 -
drivers/media/platform/fsl-viu.c | 2 +-
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 0e23b45..e5e9cbe 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -656,7 +656,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
/* clkdev registration for compatibility reasons */
clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
- clk_register_clkdev(clks[MPC512x_CLK_VIU], "viu_clk", NULL);
/* enable some of the clocks here unconditionally because ... */
pr_debug("automatically enabling some clocks\n");
diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c
index fe9898c..1b1a070 100644
--- a/drivers/media/platform/fsl-viu.c
+++ b/drivers/media/platform/fsl-viu.c
@@ -1578,7 +1578,7 @@ static int viu_of_probe(struct platform_device *op)
}
/* enable VIU clock */
- clk = devm_clk_get(&op->dev, "viu_clk");
+ clk = devm_clk_get(&op->dev, "per");
if (IS_ERR(clk)) {
dev_err(&op->dev, "failed to lookup the clock!\n");
ret = PTR_ERR(clk);
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 27/31] net: can: mscan: add common clock support for mpc512x
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
linux-arm-kernel, devicetree
Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
Wolfgang Grandegger, Mauro Carvalho Chehab
In-Reply-To: <1375821851-31609-1-git-send-email-gsi@denx.de>
implement a .get_clock() callback for the MPC512x platform which uses
the common clock infrastructure (eliminating direct access to the clock
control registers from within the CAN network driver), and provide the
corresponding .put_clock() callback to release resources after use
keep the previous implementation of MPC512x support in place during
migration, since common clock support is optional
acquire both the 'ipg' as well as "can" clock items in the mscan driver,
remove pre-enable workarounds for the BDLC (CAN related 'ipg') as well
as the CAN related MCLK (bitrate) items in the platform's clock driver
this change is neutral to the MPC5200 platform
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
arch/powerpc/platforms/512x/clock-commonclk.c | 3 -
drivers/net/can/mscan/mpc5xxx_can.c | 179 +++++++++++++++++++++++++
2 files changed, 179 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index e5e9cbe..afbb01d 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -669,9 +669,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
/* some are not yet acquired by their respective drivers */
clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
clk_prepare_enable(clks[MPC512x_CLK_DIU]); /* display */
- clk_prepare_enable(clks[MPC512x_CLK_BDLC]);
- for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_mscan_data); mclk_idx++)
- clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK + mclk_idx]);
}
/*
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index e59b3a3..f48f129 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -109,6 +109,177 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
#endif /* CONFIG_PPC_MPC52xx */
#ifdef CONFIG_PPC_MPC512x
+
+#if IS_ENABLED(CONFIG_COMMON_CLK)
+
+static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
+ const char *clock_source, int *mscan_clksrc)
+{
+ struct device_node *np;
+ u32 clockdiv;
+ enum {
+ CLK_FROM_AUTO,
+ CLK_FROM_IPS,
+ CLK_FROM_SYS,
+ CLK_FROM_REF,
+ } clk_from;
+ struct clk *clk_in, *clk_can;
+ unsigned long freq_calc;
+ struct mscan_priv *priv;
+ struct clk *clk_ipg;
+
+ /* the caller passed in the clock source spec that was read from
+ * the device tree, get the optional clock divider as well
+ */
+ np = ofdev->dev.of_node;
+ clockdiv = 1;
+ of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
+ dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
+ clock_source ? clock_source : "<NULL>", clockdiv);
+
+ /* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
+ * get set, and the 'ips' clock is the input to the MSCAN
+ * component
+ *
+ * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
+ * bit needs to get cleared, an optional clock-divider may have
+ * been specified (the default value is 1), the appropriate
+ * MSCAN related MCLK is the input to the MSCAN component
+ *
+ * in the absence of a clock-source spec, first an optimal clock
+ * gets determined based on the 'sys' clock, if that fails the
+ * 'ref' clock is used
+ */
+ clk_from = CLK_FROM_AUTO;
+ if (clock_source) {
+ /* interpret the device tree's spec for the clock source */
+ if (!strcmp(clock_source, "ip"))
+ clk_from = CLK_FROM_IPS;
+ else if (!strcmp(clock_source, "sys"))
+ clk_from = CLK_FROM_SYS;
+ else if (!strcmp(clock_source, "ref"))
+ clk_from = CLK_FROM_REF;
+ else
+ goto err_invalid;
+ dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
+ }
+ if (clk_from == CLK_FROM_AUTO) {
+ /* no spec so far, try the 'sys' clock; round to the
+ * next MHz and see if we can get a multiple of 16MHz
+ */
+ dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
+ clk_in = devm_clk_get(&ofdev->dev, "sys");
+ if (IS_ERR(clk_in))
+ goto err_notavail;
+ freq_calc = clk_get_rate(clk_in);
+ freq_calc += 499999;
+ freq_calc /= 1000000;
+ freq_calc *= 1000000;
+ if ((freq_calc % 16000000) == 0) {
+ clk_from = CLK_FROM_SYS;
+ clockdiv = freq_calc / 16000000;
+ dev_dbg(&ofdev->dev,
+ "clk fit, sys[%lu] div[%d] freq[%lu]\n",
+ freq_calc, clockdiv, freq_calc / clockdiv);
+ }
+ }
+ if (clk_from == CLK_FROM_AUTO) {
+ /* no spec so far, use the 'ref' clock */
+ dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
+ clk_in = devm_clk_get(&ofdev->dev, "ref");
+ if (IS_ERR(clk_in))
+ goto err_notavail;
+ clk_from = CLK_FROM_REF;
+ freq_calc = clk_get_rate(clk_in);
+ dev_dbg(&ofdev->dev,
+ "clk fit, ref[%lu] (no div) freq[%lu]\n",
+ freq_calc, freq_calc);
+ }
+
+ /* select IPS or MCLK as the MSCAN input (returned to the caller),
+ * setup the MCLK mux source and rate if applicable, apply the
+ * optionally specified or derived above divider, and determine
+ * the actual resulting clock rate to return to the caller
+ */
+ switch (clk_from) {
+ case CLK_FROM_IPS:
+ clk_can = devm_clk_get(&ofdev->dev, "ips");
+ if (IS_ERR(clk_can))
+ goto err_notavail;
+ priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+ priv->clk_can = clk_can;
+ freq_calc = clk_get_rate(clk_can);
+ *mscan_clksrc = MSCAN_CLKSRC_IPS;
+ dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
+ *mscan_clksrc, freq_calc);
+ break;
+ case CLK_FROM_SYS:
+ case CLK_FROM_REF:
+ clk_can = devm_clk_get(&ofdev->dev, "mclk");
+ if (IS_ERR(clk_can))
+ goto err_notavail;
+ priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+ priv->clk_can = clk_can;
+ if (clk_from == CLK_FROM_SYS)
+ clk_in = devm_clk_get(&ofdev->dev, "sys");
+ if (clk_from == CLK_FROM_REF)
+ clk_in = devm_clk_get(&ofdev->dev, "ref");
+ if (IS_ERR(clk_in))
+ goto err_notavail;
+ clk_set_parent(clk_can, clk_in);
+ freq_calc = clk_get_rate(clk_in);
+ freq_calc /= clockdiv;
+ clk_set_rate(clk_can, freq_calc);
+ freq_calc = clk_get_rate(clk_can);
+ *mscan_clksrc = MSCAN_CLKSRC_BUS;
+ dev_dbg(&ofdev->dev, "clk from MCLK, clksrc[%d] freq[%lu]\n",
+ *mscan_clksrc, freq_calc);
+ break;
+ default:
+ goto err_invalid;
+ }
+
+ /* the above clk_can item is used for the bitrate, access to
+ * the peripheral's register set needs the clk_ipg item
+ */
+ clk_ipg = devm_clk_get(&ofdev->dev, "ipg");
+ if (IS_ERR(clk_ipg))
+ goto err_notavail_ipg;
+ if (clk_prepare_enable(clk_ipg))
+ goto err_notavail_ipg;
+ priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+ priv->clk_ipg = clk_ipg;
+
+ /* return the determined clock source rate */
+ return freq_calc;
+
+err_invalid:
+ dev_err(&ofdev->dev, "invalid clock source specification\n");
+ /* clock source rate could not get determined */
+ return 0;
+
+err_notavail:
+ dev_err(&ofdev->dev, "cannot acquire or setup bitrate clock source\n");
+ /* clock source rate could not get determined */
+ return 0;
+
+err_notavail_ipg:
+ dev_err(&ofdev->dev, "cannot acquire or setup register clock\n");
+ /* clock source rate could not get determined */
+ return 0;
+}
+
+static void mpc512x_can_put_clock(struct platform_device *ofdev)
+{
+ struct mscan_priv *priv;
+
+ priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+ if (priv->clk_ipg)
+ clk_disable_unprepare(priv->clk_ipg);
+}
+
+#else /* COMMON_CLK */
+
struct mpc512x_clockctl {
u32 spmr; /* System PLL Mode Reg */
u32 sccr[2]; /* System Clk Ctrl Reg 1 & 2 */
@@ -239,12 +410,18 @@ exit_put:
of_node_put(np_clock);
return freq;
}
+
+#define mpc512x_can_put_clock NULL
+
+#endif /* COMMON_CLK */
+
#else /* !CONFIG_PPC_MPC512x */
static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
const char *clock_name, int *mscan_clksrc)
{
return 0;
}
+#define mpc512x_can_put_clock NULL
#endif /* CONFIG_PPC_MPC512x */
static const struct of_device_id mpc5xxx_can_table[];
@@ -386,11 +563,13 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev)
static const struct mpc5xxx_can_data mpc5200_can_data = {
.type = MSCAN_TYPE_MPC5200,
.get_clock = mpc52xx_can_get_clock,
+ /* .put_clock not applicable */
};
static const struct mpc5xxx_can_data mpc5121_can_data = {
.type = MSCAN_TYPE_MPC5121,
.get_clock = mpc512x_can_get_clock,
+ .put_clock = mpc512x_can_put_clock,
};
static const struct of_device_id mpc5xxx_can_table[] = {
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 28/31] powerpc/mpc512x: improve DIU related clock setup
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
linux-arm-kernel, devicetree
Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
Wolfgang Grandegger, Mauro Carvalho Chehab
In-Reply-To: <1375821851-31609-1-git-send-email-gsi@denx.de>
adapt the DIU clock initialization to the COMMON_CLK approach:
device tree based clock lookup, prepare and unprepare for clocks,
work with frequencies not dividers, call the appropriate clk_*()
routines and don't access CCM registers, remove the pre-enable
workaround in the platform's clock driver
the "best clock" determination now completely relies on the
platform's clock driver to pick a frequency close to what the
caller requests, and merely checks whether the desired frequency
was met (is acceptable since it meets the tolerance of the monitor)
this approach shall succeed upon first try in the usual case,
will test a few less desirable yet acceptable frequencies in
edge cases, and will fallback to "best effort" if none of the
previously tried frequencies pass the test
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
arch/powerpc/platforms/512x/clock-commonclk.c | 1 -
arch/powerpc/platforms/512x/mpc512x_shared.c | 165 +++++++++++++------------
2 files changed, 88 insertions(+), 78 deletions(-)
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index afbb01d..fa95814 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -668,7 +668,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
clk_prepare_enable(clks[MPC512x_CLK_LPC]); /* boot media */
/* some are not yet acquired by their respective drivers */
clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
- clk_prepare_enable(clks[MPC512x_CLK_DIU]); /* display */
}
/*
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index a82a41b..3381eea 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -12,6 +12,7 @@
* (at your option) any later version.
*/
+#include <linux/clk.h>
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/irq.h>
@@ -70,98 +71,108 @@ struct fsl_diu_shared_fb {
bool in_use;
};
-#define DIU_DIV_MASK 0x000000ff
+/* receives a pixel clock spec in pico seconds, adjusts the DIU clock rate */
void mpc512x_set_pixel_clock(unsigned int pixclock)
{
- unsigned long bestval, bestfreq, speed, busfreq;
- unsigned long minpixclock, maxpixclock, pixval;
- struct mpc512x_ccm __iomem *ccm;
struct device_node *np;
- u32 temp;
- long err;
- int i;
+ struct clk *clk_diu;
+ unsigned long epsilon, minpixclock, maxpixclock;
+ unsigned long offset, want, got, delta;
- np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+ /* lookup and enable the DIU clock */
+ np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-diu");
if (!np) {
- pr_err("Can't find clock control module.\n");
+ pr_err("Could not find DIU device tree node.\n");
return;
}
-
- ccm = of_iomap(np, 0);
+ clk_diu = of_clk_get_by_name(np, "per");
of_node_put(np);
- if (!ccm) {
- pr_err("Can't map clock control module reg.\n");
+ if (IS_ERR(clk_diu)) {
+ pr_err("Could not lookup DIU clock.\n");
return;
}
-
- np = of_find_node_by_type(NULL, "cpu");
- if (np) {
- const unsigned int *prop =
- of_get_property(np, "bus-frequency", NULL);
-
- of_node_put(np);
- if (prop) {
- busfreq = *prop;
- } else {
- pr_err("Can't get bus-frequency property\n");
- return;
- }
- } else {
- pr_err("Can't find 'cpu' node.\n");
+ if (clk_prepare_enable(clk_diu)) {
+ pr_err("Could not enable DIU clock.\n");
return;
}
- /* Pixel Clock configuration */
- pr_debug("DIU: Bus Frequency = %lu\n", busfreq);
- speed = busfreq * 4; /* DIU_DIV ratio is 4 * CSB_CLK / DIU_CLK */
-
- /* Calculate the pixel clock with the smallest error */
- /* calculate the following in steps to avoid overflow */
- pr_debug("DIU pixclock in ps - %d\n", pixclock);
- temp = (1000000000 / pixclock) * 1000;
- pixclock = temp;
- pr_debug("DIU pixclock freq - %u\n", pixclock);
-
- temp = temp / 20; /* pixclock * 0.05 */
- pr_debug("deviation = %d\n", temp);
- minpixclock = pixclock - temp;
- maxpixclock = pixclock + temp;
- pr_debug("DIU minpixclock - %lu\n", minpixclock);
- pr_debug("DIU maxpixclock - %lu\n", maxpixclock);
- pixval = speed/pixclock;
- pr_debug("DIU pixval = %lu\n", pixval);
-
- err = LONG_MAX;
- bestval = pixval;
- pr_debug("DIU bestval = %lu\n", bestval);
-
- bestfreq = 0;
- for (i = -1; i <= 1; i++) {
- temp = speed / (pixval+i);
- pr_debug("DIU test pixval i=%d, pixval=%lu, temp freq. = %u\n",
- i, pixval, temp);
- if ((temp < minpixclock) || (temp > maxpixclock))
- pr_debug("DIU exceeds monitor range (%lu to %lu)\n",
- minpixclock, maxpixclock);
- else if (abs(temp - pixclock) < err) {
- pr_debug("Entered the else if block %d\n", i);
- err = abs(temp - pixclock);
- bestval = pixval + i;
- bestfreq = temp;
- }
+ /*
+ * convert the picoseconds spec into the desired clock rate,
+ * determine the acceptable clock range for the monitor (+/- 5%),
+ * do the calculation in steps to avoid integer overflow
+ */
+ pr_debug("DIU pixclock in ps - %u\n", pixclock);
+ pixclock = (1000000000 / pixclock) * 1000;
+ pr_debug("DIU pixclock freq - %u\n", pixclock);
+ epsilon = pixclock / 20; /* pixclock * 0.05 */
+ pr_debug("DIU deviation - %lu\n", epsilon);
+ minpixclock = pixclock - epsilon;
+ maxpixclock = pixclock + epsilon;
+ pr_debug("DIU minpixclock - %lu\n", minpixclock);
+ pr_debug("DIU maxpixclock - %lu\n", maxpixclock);
+
+ /*
+ * check whether the DIU supports the desired pixel clock
+ *
+ * - simply request the desired clock and see what the
+ * platform's clock driver will make of it, assuming that it
+ * will setup the best approximation of the requested value
+ * - try other candidate frequencies in the order of decreasing
+ * preference (i.e. with increasing distance from the desired
+ * pixel clock, and checking the lower frequency before the
+ * higher frequency to not overload the hardware) until the
+ * first match is found -- any potential subsequent match
+ * would only be as good as the former match or typically
+ * would be less preferrable
+ *
+ * the offset increment of pixelclock divided by 64 is an
+ * arbitrary choice -- it's simple to calculate, in the typical
+ * case we expect the first check to succeed already, in the
+ * worst case seven frequencies get tested (the exact center and
+ * three more values each to the left and to the right) before
+ * the 5% tolerance window is exceeded, resulting in fast enough
+ * execution yet high enough probability of finding a suitable
+ * value, while the error rate will be in the order of single
+ * percents
+ */
+ for (offset = 0; offset <= epsilon; offset += pixclock / 64) {
+ want = pixclock - offset;
+ pr_debug("DIU checking clock - %lu\n", want);
+ clk_set_rate(clk_diu, want);
+ got = clk_get_rate(clk_diu);
+ delta = abs(pixclock - got);
+ if (delta < epsilon)
+ break;
+ if (!offset)
+ continue;
+ want = pixclock + offset;
+ pr_debug("DIU checking clock - %lu\n", want);
+ clk_set_rate(clk_diu, want);
+ got = clk_get_rate(clk_diu);
+ delta = abs(pixclock - got);
+ if (delta < epsilon)
+ break;
}
+ if (offset <= epsilon) {
+ pr_debug("DIU clock accepted - %lu\n", want);
+ pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
+ pixclock, got, delta, epsilon);
+ return;
+ }
+ pr_warn("DIU pixclock auto search unsuccessful\n");
- pr_debug("DIU chose = %lx\n", bestval);
- pr_debug("DIU error = %ld\n NomPixClk ", err);
- pr_debug("DIU: Best Freq = %lx\n", bestfreq);
- /* Modify DIU_DIV in CCM SCFR1 */
- temp = in_be32(&ccm->scfr1);
- pr_debug("DIU: Current value of SCFR1: 0x%08x\n", temp);
- temp &= ~DIU_DIV_MASK;
- temp |= (bestval & DIU_DIV_MASK);
- out_be32(&ccm->scfr1, temp);
- pr_debug("DIU: Modified value of SCFR1: 0x%08x\n", temp);
- iounmap(ccm);
+ /*
+ * what is the most appropriate action to take when the search
+ * for an available pixel clock which is acceptable to the
+ * monitor has failed? disable the DIU (clock) or just provide
+ * a "best effort"? we go with the latter
+ */
+ pr_warn("DIU pixclock best effort fallback (backend's choice)\n");
+ clk_set_rate(clk_diu, pixclock);
+ got = clk_get_rate(clk_diu);
+ delta = abs(pixclock - got);
+ pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
+ pixclock, got, delta, epsilon);
}
enum fsl_diu_monitor_port
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 29/31] clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
linux-arm-kernel, devicetree
Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
Wolfgang Grandegger, Mauro Carvalho Chehab
In-Reply-To: <1375821851-31609-1-git-send-email-gsi@denx.de>
completely switch to, i.e. unconditionally use COMMON_CLK for the
MPC512x platform, and retire the PPC_CLOCK implementation for that
platform after the transition has completed
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
arch/powerpc/platforms/512x/Kconfig | 14 +-
arch/powerpc/platforms/512x/Makefile | 3 +-
arch/powerpc/platforms/512x/clock.c | 753 ----------------------------------
3 files changed, 2 insertions(+), 768 deletions(-)
delete mode 100644 arch/powerpc/platforms/512x/clock.c
diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index c5fcdd0..5aa3f4b 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,21 +1,9 @@
-config MPC512x_COMMON_CLK
- bool "MPC512x platform uses COMMON_CLK"
- default y
- depends on PPC_MPC512x
- help
- This option is only here to support tests and comparison
- during development and migration. This option will get
- removed after the COMMON_CLK support for MPC512x has become
- fully operational and all drivers were adjusted to explicitly
- acquire their required clocks.
-
config PPC_MPC512x
bool "512x-based boards"
depends on 6xx
+ select COMMON_CLK
select FSL_SOC
select IPIC
- select PPC_CLOCK if !MPC512x_COMMON_CLK
- select COMMON_CLK if MPC512x_COMMON_CLK
select PPC_PCI_CHOICE
select FSL_PCI if PCI
select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 1e05f9d..bb20116 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,8 +1,7 @@
#
# Makefile for the Freescale PowerPC 512x linux kernel.
#
-obj-$(CONFIG_PPC_CLOCK) += clock.o
-obj-$(CONFIG_COMMON_CLK) += clock-commonclk.o
+obj-y += clock-commonclk.o
obj-y += mpc512x_shared.o
obj-$(CONFIG_MPC5121_ADS) += mpc5121_ads.o mpc5121_ads_cpld.o
obj-$(CONFIG_MPC512x_GENERIC) += mpc512x_generic.o
diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c
deleted file mode 100644
index e504166..0000000
--- a/arch/powerpc/platforms/512x/clock.c
+++ /dev/null
@@ -1,753 +0,0 @@
-/*
- * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Author: John Rigby <jrigby@freescale.com>
- *
- * Implements the clk api defined in include/linux/clk.h
- *
- * Original based on linux/arch/arm/mach-integrator/clock.c
- *
- * Copyright (C) 2004 ARM Limited.
- * Written by Deep Blue Solutions Limited.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
-
-#include <linux/of_platform.h>
-#include <asm/mpc5xxx.h>
-#include <asm/mpc5121.h>
-#include <asm/clk_interface.h>
-
-#include "mpc512x.h"
-
-#undef CLK_DEBUG
-
-static int clocks_initialized;
-
-#define CLK_HAS_RATE 0x1 /* has rate in MHz */
-#define CLK_HAS_CTRL 0x2 /* has control reg and bit */
-
-struct clk {
- struct list_head node;
- char name[32];
- int flags;
- struct device *dev;
- unsigned long rate;
- struct module *owner;
- void (*calc) (struct clk *);
- struct clk *parent;
- int reg, bit; /* CLK_HAS_CTRL */
- int div_shift; /* only used by generic_div_clk_calc */
-};
-
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-
-static struct clk *mpc5121_clk_get(struct device *dev, const char *id)
-{
- struct clk *p, *clk = ERR_PTR(-ENOENT);
- int dev_match;
- int id_match;
-
- if (dev == NULL || id == NULL)
- return clk;
-
- mutex_lock(&clocks_mutex);
- list_for_each_entry(p, &clocks, node) {
- dev_match = id_match = 0;
-
- if (dev == p->dev)
- dev_match++;
- if (strcmp(id, p->name) == 0)
- id_match++;
- if ((dev_match || id_match) && try_module_get(p->owner)) {
- clk = p;
- break;
- }
- }
- mutex_unlock(&clocks_mutex);
-
- return clk;
-}
-
-#ifdef CLK_DEBUG
-static void dump_clocks(void)
-{
- struct clk *p;
-
- mutex_lock(&clocks_mutex);
- printk(KERN_INFO "CLOCKS:\n");
- list_for_each_entry(p, &clocks, node) {
- pr_info(" %s=%ld", p->name, p->rate);
- if (p->parent)
- pr_cont(" %s=%ld", p->parent->name,
- p->parent->rate);
- if (p->flags & CLK_HAS_CTRL)
- pr_cont(" reg/bit=%d/%d", p->reg, p->bit);
- pr_cont("\n");
- }
- mutex_unlock(&clocks_mutex);
-}
-#define DEBUG_CLK_DUMP() dump_clocks()
-#else
-#define DEBUG_CLK_DUMP()
-#endif
-
-
-static void mpc5121_clk_put(struct clk *clk)
-{
- module_put(clk->owner);
-}
-
-#define NRPSC 12
-
-struct mpc512x_clockctl {
- u32 spmr; /* System PLL Mode Reg */
- u32 sccr[2]; /* System Clk Ctrl Reg 1 & 2 */
- u32 scfr1; /* System Clk Freq Reg 1 */
- u32 scfr2; /* System Clk Freq Reg 2 */
- u32 reserved;
- u32 bcr; /* Bread Crumb Reg */
- u32 pccr[NRPSC]; /* PSC Clk Ctrl Reg 0-11 */
- u32 spccr; /* SPDIF Clk Ctrl Reg */
- u32 cccr; /* CFM Clk Ctrl Reg */
- u32 dccr; /* DIU Clk Cnfg Reg */
-};
-
-static struct mpc512x_clockctl __iomem *clockctl;
-
-static int mpc5121_clk_enable(struct clk *clk)
-{
- unsigned int mask;
-
- if (clk->flags & CLK_HAS_CTRL) {
- mask = in_be32(&clockctl->sccr[clk->reg]);
- mask |= 1 << clk->bit;
- out_be32(&clockctl->sccr[clk->reg], mask);
- }
- return 0;
-}
-
-static void mpc5121_clk_disable(struct clk *clk)
-{
- unsigned int mask;
-
- if (clk->flags & CLK_HAS_CTRL) {
- mask = in_be32(&clockctl->sccr[clk->reg]);
- mask &= ~(1 << clk->bit);
- out_be32(&clockctl->sccr[clk->reg], mask);
- }
-}
-
-static unsigned long mpc5121_clk_get_rate(struct clk *clk)
-{
- if (clk->flags & CLK_HAS_RATE)
- return clk->rate;
- else
- return 0;
-}
-
-static long mpc5121_clk_round_rate(struct clk *clk, unsigned long rate)
-{
- return rate;
-}
-
-static int mpc5121_clk_set_rate(struct clk *clk, unsigned long rate)
-{
- return 0;
-}
-
-static int clk_register(struct clk *clk)
-{
- mutex_lock(&clocks_mutex);
- list_add(&clk->node, &clocks);
- mutex_unlock(&clocks_mutex);
- return 0;
-}
-
-static unsigned long spmf_mult(void)
-{
- /*
- * Convert spmf to multiplier
- */
- static int spmf_to_mult[] = {
- 68, 1, 12, 16,
- 20, 24, 28, 32,
- 36, 40, 44, 48,
- 52, 56, 60, 64
- };
- int spmf = (in_be32(&clockctl->spmr) >> 24) & 0xf;
- return spmf_to_mult[spmf];
-}
-
-static unsigned long sysdiv_div_x_2(void)
-{
- /*
- * Convert sysdiv to divisor x 2
- * Some divisors have fractional parts so
- * multiply by 2 then divide by this value
- */
- static int sysdiv_to_div_x_2[] = {
- 4, 5, 6, 7,
- 8, 9, 10, 14,
- 12, 16, 18, 22,
- 20, 24, 26, 30,
- 28, 32, 34, 38,
- 36, 40, 42, 46,
- 44, 48, 50, 54,
- 52, 56, 58, 62,
- 60, 64, 66,
- };
- int sysdiv = (in_be32(&clockctl->scfr2) >> 26) & 0x3f;
- return sysdiv_to_div_x_2[sysdiv];
-}
-
-static unsigned long ref_to_sys(unsigned long rate)
-{
- rate *= spmf_mult();
- rate *= 2;
- rate /= sysdiv_div_x_2();
-
- return rate;
-}
-
-static unsigned long sys_to_ref(unsigned long rate)
-{
- rate *= sysdiv_div_x_2();
- rate /= 2;
- rate /= spmf_mult();
-
- return rate;
-}
-
-static long ips_to_ref(unsigned long rate)
-{
- int ips_div = (in_be32(&clockctl->scfr1) >> 23) & 0x7;
-
- rate *= ips_div; /* csb_clk = ips_clk * ips_div */
- rate *= 2; /* sys_clk = csb_clk * 2 */
- return sys_to_ref(rate);
-}
-
-static unsigned long devtree_getfreq(char *clockname)
-{
- struct device_node *np;
- const unsigned int *prop;
- unsigned int val = 0;
-
- np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
- if (np) {
- prop = of_get_property(np, clockname, NULL);
- if (prop)
- val = *prop;
- of_node_put(np);
- }
- return val;
-}
-
-static void ref_clk_calc(struct clk *clk)
-{
- unsigned long rate;
-
- rate = devtree_getfreq("bus-frequency");
- if (rate == 0) {
- printk(KERN_ERR "No bus-frequency in dev tree\n");
- clk->rate = 0;
- return;
- }
- clk->rate = ips_to_ref(rate);
-}
-
-static struct clk ref_clk = {
- .name = "ref_clk",
- .calc = ref_clk_calc,
-};
-
-
-static void sys_clk_calc(struct clk *clk)
-{
- clk->rate = ref_to_sys(ref_clk.rate);
-}
-
-static struct clk sys_clk = {
- .name = "sys_clk",
- .calc = sys_clk_calc,
-};
-
-static void diu_clk_calc(struct clk *clk)
-{
- int diudiv_x_2 = in_be32(&clockctl->scfr1) & 0xff;
- unsigned long rate;
-
- rate = sys_clk.rate;
-
- rate *= 2;
- rate /= diudiv_x_2;
-
- clk->rate = rate;
-}
-
-static void viu_clk_calc(struct clk *clk)
-{
- unsigned long rate;
-
- rate = sys_clk.rate;
- rate /= 2;
- clk->rate = rate;
-}
-
-static void half_clk_calc(struct clk *clk)
-{
- clk->rate = clk->parent->rate / 2;
-}
-
-static void generic_div_clk_calc(struct clk *clk)
-{
- int div = (in_be32(&clockctl->scfr1) >> clk->div_shift) & 0x7;
-
- clk->rate = clk->parent->rate / div;
-}
-
-static void unity_clk_calc(struct clk *clk)
-{
- clk->rate = clk->parent->rate;
-}
-
-static struct clk csb_clk = {
- .name = "csb_clk",
- .calc = half_clk_calc,
- .parent = &sys_clk,
-};
-
-static void e300_clk_calc(struct clk *clk)
-{
- int spmf = (in_be32(&clockctl->spmr) >> 16) & 0xf;
- int ratex2 = clk->parent->rate * spmf;
-
- clk->rate = ratex2 / 2;
-}
-
-static struct clk e300_clk = {
- .name = "e300_clk",
- .calc = e300_clk_calc,
- .parent = &csb_clk,
-};
-
-static struct clk ips_clk = {
- .name = "ips_clk",
- .calc = generic_div_clk_calc,
- .parent = &csb_clk,
- .div_shift = 23,
-};
-
-/*
- * Clocks controlled by SCCR1 (.reg = 0)
- */
-static struct clk lpc_clk = {
- .name = "lpc_clk",
- .flags = CLK_HAS_CTRL,
- .reg = 0,
- .bit = 30,
- .calc = generic_div_clk_calc,
- .parent = &ips_clk,
- .div_shift = 11,
-};
-
-static struct clk nfc_clk = {
- .name = "nfc_clk",
- .flags = CLK_HAS_CTRL,
- .reg = 0,
- .bit = 29,
- .calc = generic_div_clk_calc,
- .parent = &ips_clk,
- .div_shift = 8,
-};
-
-static struct clk pata_clk = {
- .name = "pata_clk",
- .flags = CLK_HAS_CTRL,
- .reg = 0,
- .bit = 28,
- .calc = unity_clk_calc,
- .parent = &ips_clk,
-};
-
-/*
- * PSC clocks (bits 27 - 16)
- * are setup elsewhere
- */
-
-static struct clk sata_clk = {
- .name = "sata_clk",
- .flags = CLK_HAS_CTRL,
- .reg = 0,
- .bit = 14,
- .calc = unity_clk_calc,
- .parent = &ips_clk,
-};
-
-static struct clk fec_clk = {
- .name = "fec_clk",
- .flags = CLK_HAS_CTRL,
- .reg = 0,
- .bit = 13,
- .calc = unity_clk_calc,
- .parent = &ips_clk,
-};
-
-static struct clk pci_clk = {
- .name = "pci_clk",
- .flags = CLK_HAS_CTRL,
- .reg = 0,
- .bit = 11,
- .calc = generic_div_clk_calc,
- .parent = &csb_clk,
- .div_shift = 20,
-};
-
-/*
- * Clocks controlled by SCCR2 (.reg = 1)
- */
-static struct clk diu_clk = {
- .name = "diu_clk",
- .flags = CLK_HAS_CTRL,
- .reg = 1,
- .bit = 31,
- .calc = diu_clk_calc,
-};
-
-static struct clk viu_clk = {
- .name = "viu_clk",
- .flags = CLK_HAS_CTRL,
- .reg = 1,
- .bit = 18,
- .calc = viu_clk_calc,
-};
-
-static struct clk axe_clk = {
- .name = "axe_clk",
- .flags = CLK_HAS_CTRL,
- .reg = 1,
- .bit = 30,
- .calc = unity_clk_calc,
- .parent = &csb_clk,
-};
-
-static struct clk usb1_clk = {
- .name = "usb1_clk",
- .flags = CLK_HAS_CTRL,
- .reg = 1,
- .bit = 28,
- .calc = unity_clk_calc,
- .parent = &csb_clk,
-};
-
-static struct clk usb2_clk = {
- .name = "usb2_clk",
- .flags = CLK_HAS_CTRL,
- .reg = 1,
- .bit = 27,
- .calc = unity_clk_calc,
- .parent = &csb_clk,
-};
-
-static struct clk i2c_clk = {
- .name = "i2c_clk",
- .flags = CLK_HAS_CTRL,
- .reg = 1,
- .bit = 26,
- .calc = unity_clk_calc,
- .parent = &ips_clk,
-};
-
-static struct clk mscan_clk = {
- .name = "mscan_clk",
- .flags = CLK_HAS_CTRL,
- .reg = 1,
- .bit = 25,
- .calc = unity_clk_calc,
- .parent = &ips_clk,
-};
-
-static struct clk sdhc_clk = {
- .name = "sdhc_clk",
- .flags = CLK_HAS_CTRL,
- .reg = 1,
- .bit = 24,
- .calc = unity_clk_calc,
- .parent = &ips_clk,
-};
-
-static struct clk mbx_bus_clk = {
- .name = "mbx_bus_clk",
- .flags = CLK_HAS_CTRL,
- .reg = 1,
- .bit = 22,
- .calc = half_clk_calc,
- .parent = &csb_clk,
-};
-
-static struct clk mbx_clk = {
- .name = "mbx_clk",
- .flags = CLK_HAS_CTRL,
- .reg = 1,
- .bit = 21,
- .calc = unity_clk_calc,
- .parent = &csb_clk,
-};
-
-static struct clk mbx_3d_clk = {
- .name = "mbx_3d_clk",
- .flags = CLK_HAS_CTRL,
- .reg = 1,
- .bit = 20,
- .calc = generic_div_clk_calc,
- .parent = &mbx_bus_clk,
- .div_shift = 14,
-};
-
-static void psc_mclk_in_calc(struct clk *clk)
-{
- clk->rate = devtree_getfreq("psc_mclk_in");
- if (!clk->rate)
- clk->rate = 25000000;
-}
-
-static struct clk psc_mclk_in = {
- .name = "psc_mclk_in",
- .calc = psc_mclk_in_calc,
-};
-
-static struct clk spdif_txclk = {
- .name = "spdif_txclk",
- .flags = CLK_HAS_CTRL,
- .reg = 1,
- .bit = 23,
-};
-
-static struct clk spdif_rxclk = {
- .name = "spdif_rxclk",
- .flags = CLK_HAS_CTRL,
- .reg = 1,
- .bit = 23,
-};
-
-static void ac97_clk_calc(struct clk *clk)
-{
- /* ac97 bit clock is always 24.567 MHz */
- clk->rate = 24567000;
-}
-
-static struct clk ac97_clk = {
- .name = "ac97_clk_in",
- .calc = ac97_clk_calc,
-};
-
-static struct clk *rate_clks[] = {
- &ref_clk,
- &sys_clk,
- &diu_clk,
- &viu_clk,
- &csb_clk,
- &e300_clk,
- &ips_clk,
- &fec_clk,
- &sata_clk,
- &pata_clk,
- &nfc_clk,
- &lpc_clk,
- &mbx_bus_clk,
- &mbx_clk,
- &mbx_3d_clk,
- &axe_clk,
- &usb1_clk,
- &usb2_clk,
- &i2c_clk,
- &mscan_clk,
- &sdhc_clk,
- &pci_clk,
- &psc_mclk_in,
- &spdif_txclk,
- &spdif_rxclk,
- &ac97_clk,
- NULL
-};
-
-static void rate_clk_init(struct clk *clk)
-{
- if (clk->calc) {
- clk->calc(clk);
- clk->flags |= CLK_HAS_RATE;
- clk_register(clk);
- } else {
- printk(KERN_WARNING
- "Could not initialize clk %s without a calc routine\n",
- clk->name);
- }
-}
-
-static void rate_clks_init(void)
-{
- struct clk **cpp, *clk;
-
- cpp = rate_clks;
- while ((clk = *cpp++))
- rate_clk_init(clk);
-}
-
-/*
- * There are two clk enable registers with 32 enable bits each
- * psc clocks and device clocks are all stored in dev_clks
- */
-static struct clk dev_clks[2][32];
-
-/*
- * Given a psc number return the dev_clk
- * associated with it
- */
-static struct clk *psc_dev_clk(int pscnum)
-{
- int reg, bit;
- struct clk *clk;
-
- reg = 0;
- bit = 27 - pscnum;
-
- clk = &dev_clks[reg][bit];
- clk->reg = 0;
- clk->bit = bit;
- return clk;
-}
-
-/*
- * PSC clock rate calculation
- */
-static void psc_calc_rate(struct clk *clk, int pscnum, struct device_node *np)
-{
- unsigned long mclk_src = sys_clk.rate;
- unsigned long mclk_div;
-
- /*
- * Can only change value of mclk divider
- * when the divider is disabled.
- *
- * Zero is not a valid divider so minimum
- * divider is 1
- *
- * disable/set divider/enable
- */
- out_be32(&clockctl->pccr[pscnum], 0);
- out_be32(&clockctl->pccr[pscnum], 0x00020000);
- out_be32(&clockctl->pccr[pscnum], 0x00030000);
-
- if (in_be32(&clockctl->pccr[pscnum]) & 0x80) {
- clk->rate = spdif_rxclk.rate;
- return;
- }
-
- switch ((in_be32(&clockctl->pccr[pscnum]) >> 14) & 0x3) {
- case 0:
- mclk_src = sys_clk.rate;
- break;
- case 1:
- mclk_src = ref_clk.rate;
- break;
- case 2:
- mclk_src = psc_mclk_in.rate;
- break;
- case 3:
- mclk_src = spdif_txclk.rate;
- break;
- }
-
- mclk_div = ((in_be32(&clockctl->pccr[pscnum]) >> 17) & 0x7fff) + 1;
- clk->rate = mclk_src / mclk_div;
-}
-
-/*
- * Find all psc nodes in device tree and assign a clock
- * with name "psc%d_mclk" and dev pointing at the device
- * returned from of_find_device_by_node
- */
-static void psc_clks_init(void)
-{
- struct device_node *np;
- struct platform_device *ofdev;
- u32 reg;
- const char *psc_compat;
-
- psc_compat = mpc512x_select_psc_compat();
- if (!psc_compat)
- return;
-
- for_each_compatible_node(np, NULL, psc_compat) {
- if (!of_property_read_u32(np, "reg", ®)) {
- int pscnum = (reg & 0xf00) >> 8;
- struct clk *clk = psc_dev_clk(pscnum);
-
- clk->flags = CLK_HAS_RATE | CLK_HAS_CTRL;
- ofdev = of_find_device_by_node(np);
- clk->dev = &ofdev->dev;
- /*
- * AC97 is special rate clock does
- * not go through normal path
- */
- if (of_device_is_compatible(np, "fsl,mpc5121-psc-ac97"))
- clk->rate = ac97_clk.rate;
- else
- psc_calc_rate(clk, pscnum, np);
- sprintf(clk->name, "psc%d_mclk", pscnum);
- clk_register(clk);
- clk_enable(clk);
- }
- }
-}
-
-static struct clk_interface mpc5121_clk_functions = {
- .clk_get = mpc5121_clk_get,
- .clk_enable = mpc5121_clk_enable,
- .clk_disable = mpc5121_clk_disable,
- .clk_get_rate = mpc5121_clk_get_rate,
- .clk_put = mpc5121_clk_put,
- .clk_round_rate = mpc5121_clk_round_rate,
- .clk_set_rate = mpc5121_clk_set_rate,
- .clk_set_parent = NULL,
- .clk_get_parent = NULL,
-};
-
-int __init mpc5121_clk_init(void)
-{
- struct device_node *np;
-
- np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
- if (np) {
- clockctl = of_iomap(np, 0);
- of_node_put(np);
- }
-
- if (!clockctl) {
- printk(KERN_ERR "Could not map clock control registers\n");
- return 0;
- }
-
- rate_clks_init();
- psc_clks_init();
-
- /* leave clockctl mapped forever */
- /*iounmap(clockctl); */
- DEBUG_CLK_DUMP();
- clocks_initialized++;
- clk_functions = mpc5121_clk_functions;
- return 0;
-}
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 30/31] net: can: mscan: remove non-CCF code for MPC512x
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
linux-arm-kernel, devicetree
Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
Wolfgang Grandegger, Mauro Carvalho Chehab
In-Reply-To: <1375821851-31609-1-git-send-email-gsi@denx.de>
transition to the common clock framework has completed and the PPC_CLOCK
is no longer available for the MPC512x platform, remove the now obsolete
code path of the mpc5xxx mscan driver which accessed clock control
module registers directly
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
drivers/net/can/mscan/mpc5xxx_can.c | 141 -----------------------------------
1 file changed, 141 deletions(-)
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index f48f129..6b0c995 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -109,9 +109,6 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
#endif /* CONFIG_PPC_MPC52xx */
#ifdef CONFIG_PPC_MPC512x
-
-#if IS_ENABLED(CONFIG_COMMON_CLK)
-
static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
const char *clock_source, int *mscan_clksrc)
{
@@ -277,144 +274,6 @@ static void mpc512x_can_put_clock(struct platform_device *ofdev)
if (priv->clk_ipg)
clk_disable_unprepare(priv->clk_ipg);
}
-
-#else /* COMMON_CLK */
-
-struct mpc512x_clockctl {
- u32 spmr; /* System PLL Mode Reg */
- u32 sccr[2]; /* System Clk Ctrl Reg 1 & 2 */
- u32 scfr1; /* System Clk Freq Reg 1 */
- u32 scfr2; /* System Clk Freq Reg 2 */
- u32 reserved;
- u32 bcr; /* Bread Crumb Reg */
- u32 pccr[12]; /* PSC Clk Ctrl Reg 0-11 */
- u32 spccr; /* SPDIF Clk Ctrl Reg */
- u32 cccr; /* CFM Clk Ctrl Reg */
- u32 dccr; /* DIU Clk Cnfg Reg */
- u32 mccr[4]; /* MSCAN Clk Ctrl Reg 1-3 */
-};
-
-static struct of_device_id mpc512x_clock_ids[] = {
- { .compatible = "fsl,mpc5121-clock", },
- {}
-};
-
-static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
- const char *clock_name, int *mscan_clksrc)
-{
- struct mpc512x_clockctl __iomem *clockctl;
- struct device_node *np_clock;
- struct clk *sys_clk, *ref_clk;
- int plen, clockidx, clocksrc = -1;
- u32 sys_freq, val, clockdiv = 1, freq = 0;
- const u32 *pval;
-
- np_clock = of_find_matching_node(NULL, mpc512x_clock_ids);
- if (!np_clock) {
- dev_err(&ofdev->dev, "couldn't find clock node\n");
- return 0;
- }
- clockctl = of_iomap(np_clock, 0);
- if (!clockctl) {
- dev_err(&ofdev->dev, "couldn't map clock registers\n");
- goto exit_put;
- }
-
- /* Determine the MSCAN device index from the peripheral's
- * physical address. Register address offsets against the
- * IMMR base are: 0x1300, 0x1380, 0x2300, 0x2380
- */
- pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
- BUG_ON(!pval || plen < sizeof(*pval));
- clockidx = (*pval & 0x80) ? 1 : 0;
- if (*pval & 0x2000)
- clockidx += 2;
-
- /*
- * Clock source and divider selection: 3 different clock sources
- * can be selected: "ip", "ref" or "sys". For the latter two, a
- * clock divider can be defined as well. If the clock source is
- * not specified by the device tree, we first try to find an
- * optimal CAN source clock based on the system clock. If that
- * is not posslible, the reference clock will be used.
- */
- if (clock_name && !strcmp(clock_name, "ip")) {
- *mscan_clksrc = MSCAN_CLKSRC_IPS;
- freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node);
- } else {
- *mscan_clksrc = MSCAN_CLKSRC_BUS;
-
- pval = of_get_property(ofdev->dev.of_node,
- "fsl,mscan-clock-divider", &plen);
- if (pval && plen == sizeof(*pval))
- clockdiv = *pval;
- if (!clockdiv)
- clockdiv = 1;
-
- if (!clock_name || !strcmp(clock_name, "sys")) {
- sys_clk = devm_clk_get(&ofdev->dev, "sys_clk");
- if (IS_ERR(sys_clk)) {
- dev_err(&ofdev->dev, "couldn't get sys_clk\n");
- goto exit_unmap;
- }
- /* Get and round up/down sys clock rate */
- sys_freq = 1000000 *
- ((clk_get_rate(sys_clk) + 499999) / 1000000);
-
- if (!clock_name) {
- /* A multiple of 16 MHz would be optimal */
- if ((sys_freq % 16000000) == 0) {
- clocksrc = 0;
- clockdiv = sys_freq / 16000000;
- freq = sys_freq / clockdiv;
- }
- } else {
- clocksrc = 0;
- freq = sys_freq / clockdiv;
- }
- }
-
- if (clocksrc < 0) {
- ref_clk = devm_clk_get(&ofdev->dev, "ref_clk");
- if (IS_ERR(ref_clk)) {
- dev_err(&ofdev->dev, "couldn't get ref_clk\n");
- goto exit_unmap;
- }
- clocksrc = 1;
- freq = clk_get_rate(ref_clk) / clockdiv;
- }
- }
-
- /* Disable clock */
- out_be32(&clockctl->mccr[clockidx], 0x0);
- if (clocksrc >= 0) {
- /* Set source and divider */
- val = (clocksrc << 14) | ((clockdiv - 1) << 17);
- out_be32(&clockctl->mccr[clockidx], val);
- /* Enable clock */
- out_be32(&clockctl->mccr[clockidx], val | 0x10000);
- }
-
- /* Enable MSCAN clock domain */
- val = in_be32(&clockctl->sccr[1]);
- if (!(val & (1 << 25)))
- out_be32(&clockctl->sccr[1], val | (1 << 25));
-
- dev_dbg(&ofdev->dev, "using '%s' with frequency divider %d\n",
- *mscan_clksrc == MSCAN_CLKSRC_IPS ? "ips_clk" :
- clocksrc == 1 ? "ref_clk" : "sys_clk", clockdiv);
-
-exit_unmap:
- iounmap(clockctl);
-exit_put:
- of_node_put(np_clock);
- return freq;
-}
-
-#define mpc512x_can_put_clock NULL
-
-#endif /* COMMON_CLK */
-
#else /* !CONFIG_PPC_MPC512x */
static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
const char *clock_name, int *mscan_clksrc)
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 31/31] clk: mpc512x: remove remaining migration workarounds
From: Gerhard Sittig @ 2013-08-06 20:44 UTC (permalink / raw)
To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
linux-arm-kernel, devicetree
Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Gerhard Sittig,
Rob Herring, Mark Brown, Marc Kleine-Budde, David Woodhouse,
Wolfgang Grandegger, Mauro Carvalho Chehab
In-Reply-To: <1375821851-31609-1-git-send-email-gsi@denx.de>
remove the last clkdev registration call ("sys_clk" and "ref_clk"
for CAN), as well as the clkdev header inclusion and the "compat
registration" comment
all client lookups for clock items are device tree based now, no
compatibility alias names need to get provided any longer
remove the now obsolete TODO comment on trimming the list of pre-enabled
clock items, after all the respective peripheral drivers were adjusted
Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
arch/powerpc/platforms/512x/clock-commonclk.c | 7 -------
1 file changed, 7 deletions(-)
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index fa95814..621a8d9 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -12,7 +12,6 @@
*/
#include <linux/clk-provider.h>
-#include <linux/clkdev.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/io.h>
@@ -522,8 +521,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
* specific and cannot get mapped to componsites (at least not
* a single one, maybe two of them, but see the comment about
* "intermediates are referenced from elsewhere, too")
- * - trim the list of auto-enabled clocks after drivers acquire
- * them correctly as needed
*/
/* regardless of whether XTAL/OSC exists, have REF created */
@@ -653,10 +650,6 @@ static void mpc512x_clk_setup_clock_tree(int busfreq)
/* fixed frequency for AC97, always 24.567MHz */
clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000);
- /* clkdev registration for compatibility reasons */
- clk_register_clkdev(clks[MPC512x_CLK_REF], "ref_clk", NULL);
- clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys_clk", NULL);
-
/* enable some of the clocks here unconditionally because ... */
pr_debug("automatically enabling some clocks\n");
/* some are essential yet never get claimed by any driver */
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH v4 00/31] add COMMON_CLK support for PowerPC MPC512x
From: Gerhard Sittig @ 2013-08-06 21:31 UTC (permalink / raw)
To: linuxppc-dev, Anatolij Gustschin, Mike Turquette,
linux-arm-kernel, devicetree
Cc: Detlev Zundel, Wolfram Sang, Greg Kroah-Hartman, Rob Herring,
Mark Brown, Marc Kleine-Budde, David Woodhouse,
Wolfgang Grandegger, Mauro Carvalho Chehab
In-Reply-To: <1375821851-31609-1-git-send-email-gsi@denx.de>
[ this is an overview on how to split the series if necessary ]
On Tue, Aug 06, 2013 at 22:43 +0200, Gerhard Sittig wrote:
>
> this series
> - fixes several drivers that are used in the MPC512x platform (UART,
> SPI, ethernet, PCI, USB, CAN, NAND flash, video capture) in how they
> handle clocks (appropriately acquire and setup them, hold references
> during use, release clocks after use)
> - introduces support for the common clock framework (CCF, COMMON_CLK
> Kconfig option) in the PowerPC based MPC512x platform, which brings
> device tree based clock lookup as well
>
> although the series does touch several subsystems -- tty (serial), spi,
> net (can, fs_enet), mtd (nfc), usb, i2c, media (viu), and dts -- all of
> the patches are strictly clock related or trivial
>
> it appears most appropriate to take this series through either the clk
> or the powerpc trees after it has passed review and other subsystem
> maintainers ACKed the clock setup related driver modifications
It was suggested that the series may not be kept together when
applying, i.e. that individual patches may need to take separate
routes through individual subsystem trees.
Here is how the parts of the series interact:
- parts 01-14 are apparent fixes and improvements to existing
drivers, they may immediately get applied via their respective
subsystems when they are considered acceptable in review
(number 13 already was taken into clk-next)
- parts 15-16 are device tree improvements (providing previously
lacking information on the hardware, plus introducing support
for symbolic references in DT nodes), and can get applied
immediately via their respective subsystem
- part 17 introduces the platform clock driver which provides
common clock support (uses shared drivers and common
infrastructure, is an OF clock provider) -- this patch
introduces _and_ enables the driver which strictly depends on
the device tree update from part 16, and when common clock
support gets enabled all peripheral drivers shall have received
their clock API use cleanup
- part 18 introduces clock specs in the device tree which is used
for client side lookups (from within peripheral drivers), this
part must not get applied before the OF clock provider from
part 17
- parts 19-21 and 23-28 further adjust peripheral drivers _after_
the common clock support and OF clock lookup have become
available, they strictly depend on parts 17 and 18, finally
bring peripheral drivers into the common clock world and remove
workarounds in the backend which support migration
- parts 22 and 29-31 finally remove remaining compat and
migration stuff that has become obsolete after everything else
was adjusted (I'd happily re-spin the series to move 22 to the
end if eliminating this seemingly out-of-order item helps,
currently it's at that position since it finishes what patch 20
and 21 have prepared, while I did not dare to squash SPI and
UART related patches since they reside in different subsystems)
The above results in the following stages, when the series needs
to get split:
- parts 01-16 could be taken immediately and need not be kept in
any order, as they don't depend on each other
- parts 17-18 could be taken after 01-16 all are in place (while
18 requires 17)
- parts 19-28 (see the remark on 22) could be taken after 17 and
18 are in place (22 depends on 20 and 21 but may get moved to
any later position at will, all other parts don't depend on
each other and can get applied in any order)
- parts 29-31 (and 22 if not applied so far) could be taken after
all parts up to 28 were applied
Please consider that I'm not trying to be pushy :) but that I
want to provide all the possible help and information on how the
series might get applied, assuming that it will pass review. So
far there has not been objection, all feedback got addressed,
while explicit ACKs still are pending.
For your reference here is the stats and the (numbered) list of
files again:
0000-cover-letter.patch
0001-spi-mpc512x-cleanup-clock-API-use.patch
0002-serial-mpc512x-cleanup-clock-API-use.patch
0003-USB-fsl-mph-dr-of-cleanup-clock-API-use.patch
0004-mtd-mpc5121_nfc-cleanup-clock-API-use.patch
0005-media-fsl-viu-cleanup-clock-API-use.patch
0006-i2c-mpc-cleanup-clock-API-use.patch
0007-fs_enet-silence-a-build-warning-unused-variable.patch
0008-fs_enet-cleanup-clock-API-use.patch
0009-powerpc-fsl-pci-improve-clock-API-use.patch
0010-net-can-mscan-add-a-comment-on-reg-to-idx-mapping.patch
0011-net-can-mscan-improve-clock-API-use.patch
0012-powerpc-mpc512x-array-decl-for-MCLK-registers-in-CCM.patch
0013-clk-wrap-I-O-access-for-improved-portability.patch
0014-dts-mpc512x-prepare-for-preprocessor-support.patch
0015-dts-mpc512x-introduce-dt-bindings-clock-header.patch
0016-dts-mpc512x-add-clock-related-device-tree-specs.patch
0017-clk-mpc512x-introduce-COMMON_CLK-for-MPC512x.patch
0018-dts-mpc512x-add-clock-specs-for-client-lookups.patch
0019-clk-mpc512x-don-t-pre-enable-FEC-and-I2C-clocks.patch
0020-spi-mpc512x-switch-to-CCF-names-in-clock-lookup.patch
0021-serial-mpc512x-switch-to-CCF-names-in-clock-lookup.patch
0022-clk-mpc512x-remove-PSC-UART-SPI-compat-workarounds.patch
0023-serial-mpc512x-setup-the-PSC-FIFO-clock-as-well.patch
0024-USB-fsl-mph-dr-of-remove-now-obsolete-clock-lookup-n.patch
0025-mtd-mpc5121_nfc-remove-now-obsolete-clock-lookup-nam.patch
0026-media-fsl-viu-remove-now-obsolete-clock-lookup-name.patch
0027-net-can-mscan-add-common-clock-support-for-mpc512x.patch
0028-powerpc-mpc512x-improve-DIU-related-clock-setup.patch
0029-clk-mpc512x-switch-to-COMMON_CLK-remove-PPC_CLOCK.patch
0030-net-can-mscan-remove-non-CCF-code-for-MPC512x.patch
0031-clk-mpc512x-remove-remaining-migration-workarounds.patch
> Gerhard Sittig (31):
> spi: mpc512x: cleanup clock API use
> serial: mpc512x: cleanup clock API use
> USB: fsl-mph-dr-of: cleanup clock API use
> mtd: mpc5121_nfc: cleanup clock API use
> [media] fsl-viu: cleanup clock API use
> i2c: mpc: cleanup clock API use
> fs_enet: silence a build warning (unused variable)
> fs_enet: cleanup clock API use
> powerpc/fsl-pci: improve clock API use
> net: can: mscan: add a comment on reg to idx mapping
> net: can: mscan: improve clock API use
> powerpc: mpc512x: array decl for MCLK registers in CCM
> clk: wrap I/O access for improved portability
> dts: mpc512x: prepare for preprocessor support
> dts: mpc512x: introduce dt-bindings/clock/ header
> dts: mpc512x: add clock related device tree specs
> clk: mpc512x: introduce COMMON_CLK for MPC512x
> dts: mpc512x: add clock specs for client lookups
> clk: mpc512x: don't pre-enable FEC and I2C clocks
> spi: mpc512x: switch to CCF names in clock lookup
> serial: mpc512x: switch to CCF names in clock lookup
> clk: mpc512x: remove PSC (UART, SPI) compat workarounds
> serial: mpc512x: setup the PSC FIFO clock as well
> USB: fsl-mph-dr-of: remove now obsolete clock lookup name
> mtd: mpc5121_nfc: remove now obsolete clock lookup name
> [media] fsl-viu: remove now obsolete clock lookup name
> net: can: mscan: add common clock support for mpc512x
> powerpc/mpc512x: improve DIU related clock setup
> clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK
> net: can: mscan: remove non-CCF code for MPC512x
> clk: mpc512x: remove remaining migration workarounds
>
> arch/powerpc/boot/dts/ac14xx.dts | 9 +-
> arch/powerpc/boot/dts/include/dt-bindings | 1 +
> arch/powerpc/boot/dts/mpc5121.dtsi | 110 ++-
> arch/powerpc/boot/dts/mpc5121ads.dts | 2 +-
> arch/powerpc/boot/dts/pdm360ng.dts | 2 +-
> arch/powerpc/include/asm/mpc5121.h | 18 +-
> arch/powerpc/platforms/512x/Kconfig | 2 +-
> arch/powerpc/platforms/512x/Makefile | 3 +-
> arch/powerpc/platforms/512x/clock-commonclk.c | 716 +++++++++++++++++++
> arch/powerpc/platforms/512x/clock.c | 753 --------------------
> arch/powerpc/platforms/512x/mpc512x_shared.c | 165 +++--
> arch/powerpc/sysdev/fsl_pci.c | 22 +
> drivers/clk/clk-divider.c | 6 +-
> drivers/clk/clk-gate.c | 6 +-
> drivers/clk/clk-mux.c | 6 +-
> drivers/i2c/busses/i2c-mpc.c | 24 +
> drivers/media/platform/fsl-viu.c | 23 +-
> drivers/mtd/nand/mpc5121_nfc.c | 21 +-
> drivers/net/can/mscan/mpc5xxx_can.c | 281 +++++---
> drivers/net/can/mscan/mscan.c | 27 +-
> drivers/net/can/mscan/mscan.h | 3 +
> .../net/ethernet/freescale/fs_enet/fs_enet-main.c | 21 +-
> drivers/spi/spi-mpc512x-psc.c | 60 +-
> drivers/tty/serial/mpc52xx_uart.c | 179 ++++-
> drivers/usb/host/fsl-mph-dr-of.c | 27 +-
> include/dt-bindings/clock/mpc512x-clock.h | 69 ++
> include/linux/clk-provider.h | 33 +
> include/linux/fs_enet_pd.h | 3 +
> 28 files changed, 1534 insertions(+), 1058 deletions(-)
> create mode 120000 arch/powerpc/boot/dts/include/dt-bindings
> create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c
> delete mode 100644 arch/powerpc/platforms/512x/clock.c
> create mode 100644 include/dt-bindings/clock/mpc512x-clock.h
virtually yours
Gerhard Sittig
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80 Email: office@denx.de
^ permalink raw reply
* Re: [PATCH V2 5/6] cpuidle/powerpc: Backend-powerpc idle driver for powernv and pseries.
From: Scott Wood @ 2013-08-06 23:08 UTC (permalink / raw)
To: Deepthi Dharwar
Cc: rjw, linux-pm, daniel.lezcano, linux-kernel, dongsheng.wang,
srivatsa.bhat, preeti, linuxppc-dev
In-Reply-To: <20130731025934.19448.16658.stgit@deepthi>
On Wed, 2013-07-31 at 08:29 +0530, Deepthi Dharwar wrote:
> /*
> - * pseries_idle_probe()
> + * powerpc_idle_probe()
> * Choose state table for shared versus dedicated partition
> */
> -static int pseries_idle_probe(void)
> +static int powerpc_idle_probe(void)
> {
>
> +#ifndef PPC_POWERNV
> if (!firmware_has_feature(FW_FEATURE_SPLPAR))
> return -ENODEV;
> +#endif
A bunch of ifdefs is not a good start for a file you're claiming is now
generic for all powerpc.
Certainly you shouldn't be calling pseries stuff based only on the
absence of powernv.
And do you not support building one kernel that supports both pseries
and powernv?
> if (cpuidle_disable != IDLE_NO_OVERRIDE)
> return -ENODEV;
>
> if (max_idle_state == 0) {
> - printk(KERN_DEBUG "pseries processor idle disabled.\n");
> + printk(KERN_DEBUG "powerpc processor idle disabled.\n");
> return -EPERM;
> }
>
> +#ifdef PPC_POWERNV
> + cpuidle_state_table = powernv_states;
> +#else
> if (get_lppaca()->shared_proc)
Here's another example. get_lppaca() will only build on book3s -- and
yet we get requests for e500 code to use this file.
-Scott
^ permalink raw reply
* Re: [PATCH] net/fsl_pq_mdio: fix handling of TBIPA register
From: Scott Wood @ 2013-08-06 23:10 UTC (permalink / raw)
To: Lutz Jaenicke; +Cc: linuxppc-dev
In-Reply-To: <1375379355-18594-1-git-send-email-ljaenicke@innominate.com>
On Thu, 2013-08-01 at 19:49 +0200, Lutz Jaenicke wrote:
> The TBIPA register is part of gianfar's full register set. When starting
> from the MII registers, the start address of struct gfar needs to
> be determined via container_of().
> Experienced with mpc8313 and "fsl,gianfar-mdio" device tree entries.
>
> Signed-off-by: Lutz Jaenicke <ljaenicke@innominate.com>
> ---
> drivers/net/ethernet/freescale/fsl_pq_mdio.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c
> index c93a056..9485fdb 100644
> --- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c
> +++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c
> @@ -193,7 +193,8 @@ static int fsl_pq_mdio_reset(struct mii_bus *bus)
> */
> static uint32_t __iomem *get_gfar_tbipa(void __iomem *p)
> {
> - struct gfar __iomem *enet_regs = p;
> + struct gfar __iomem *enet_regs =
> + container_of(p, struct gfar, gfar_mii_regs);
>
> return &enet_regs->tbipa;
> }
Please send this to the netdev list/maintainer.
-Scott
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox