* [PATCH 3/7] clk: armada-370-xp: add support for clock framework
From: Thomas Petazzoni @ 2012-11-15 21:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1353014906-31566-4-git-send-email-andrew@lunn.ch>
Dear Andrew Lunn,
On Thu, 15 Nov 2012 22:28:22 +0100, Andrew Lunn wrote:
> diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
> index 416d46e..e5f0ae2 100644
> --- a/arch/arm/mach-mvebu/Kconfig
> +++ b/arch/arm/mach-mvebu/Kconfig
> @@ -9,11 +9,17 @@ config ARCH_MVEBU
> select PINCTRL
> select PLAT_ORION
> select SPARSE_IRQ
> + select CLKDEV_LOOKUP
> + select MVEBU_CLK_CORE
> + select MVEBU_CLK_CPU
>
> if ARCH_MVEBU
>
> menu "Marvell SOC with device tree"
>
> +config MVEBU_CLK_CPU
> + bool
> +
This config option is added to drivers/clk/mvebu/Kconfig in patch 2/7,
so I think it shouldn't be added here in patch 3/7.
Thomas
--
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* [PATCH 2/7] clk: mvebu: add armada-370-xp CPU specific clocks
From: Thomas Petazzoni @ 2012-11-15 21:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1353014906-31566-3-git-send-email-andrew@lunn.ch>
Dear Andrew Lunn,
On Thu, 15 Nov 2012 22:28:21 +0100, Andrew Lunn wrote:
> From: Gregory CLEMENT <gregory.clement@free-electrons.com>
>
> Add Armada 370/XP specific CPU clocks
>
> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> ---
> .../devicetree/bindings/clock/mvebu-core-clock.txt | 18 +--
The changes to this file.
> .../devicetree/bindings/clock/mvebu-cpu-clock.txt | 21 +++
> drivers/clk/mvebu/Kconfig | 3 +
> drivers/clk/mvebu/Makefile | 1 +
> drivers/clk/mvebu/clk-core.c | 4 +-
And this one don't appear to belong in this commit, do they?
Thomas
--
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* [PATCH] ARM: cti: fix manipulation of debug lock registers
From: Will Deacon @ 2012-11-15 21:40 UTC (permalink / raw)
To: linux-arm-kernel
The LOCKSTATUS register for memory-mapped coresight devices indicates
whether or not the device in question implements hardware locking. If
not, locking is not present (i.e. LSR.SLI == 0) and LAR is write-ignore,
so software doesn't actually need to check the status register at all.
This patch removes the broken LSR checks.
Cc: Ming Lei <ming.lei@canonical.com>
Reported-by: Mike Williams <michael.williams@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
arch/arm/include/asm/cti.h | 20 ++------------------
1 files changed, 2 insertions(+), 18 deletions(-)
diff --git a/arch/arm/include/asm/cti.h b/arch/arm/include/asm/cti.h
index a0ada3e..f2e5cad 100644
--- a/arch/arm/include/asm/cti.h
+++ b/arch/arm/include/asm/cti.h
@@ -146,15 +146,7 @@ static inline void cti_irq_ack(struct cti *cti)
*/
static inline void cti_unlock(struct cti *cti)
{
- void __iomem *base = cti->base;
- unsigned long val;
-
- val = __raw_readl(base + LOCKSTATUS);
-
- if (val & 1) {
- val = LOCKCODE;
- __raw_writel(val, base + LOCKACCESS);
- }
+ __raw_writel(LOCKCODE, cti->base + LOCKACCESS);
}
/**
@@ -166,14 +158,6 @@ static inline void cti_unlock(struct cti *cti)
*/
static inline void cti_lock(struct cti *cti)
{
- void __iomem *base = cti->base;
- unsigned long val;
-
- val = __raw_readl(base + LOCKSTATUS);
-
- if (!(val & 1)) {
- val = ~LOCKCODE;
- __raw_writel(val, base + LOCKACCESS);
- }
+ __raw_writel(~LOCKCODE, cti->base + LOCKACCESS);
}
#endif
--
1.7.4.1
^ permalink raw reply related
* [PATCH V2 0/3] ARM: tegra: add speedo identification for T20/T30
From: Stephen Warren @ 2012-11-15 21:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1352965354-650-1-git-send-email-dahuang@nvidia.com>
On 11/15/2012 12:42 AM, Danny Huang wrote:
> This patch series adds speedo identification functionality for tegra
> T20 and T30. It reads speedo value from fuse and chooses CPU and core
> process ID by checking speedo corner tables.
I think this all looks fine; I assume there will be some forthcoming
usage of the new variables.
I applied the series with some very minor changes to the printfs and
commit description to that "Tegra20" was consistently used instead of
"T20" or "Tegra2", and the same for Tegra30.
^ permalink raw reply
* [PATCH] OMAP2+: mux: Fixed gpio mux mode analysis.
From: oleg.matcovschi at ti.com @ 2012-11-15 21:39 UTC (permalink / raw)
To: linux-arm-kernel
From: Oleg Matcovschi <oleg.matcovschi@ti.com>
OMAP_MODE_GPIO() macro verified only OMAP_MUX_MODE4.
It is not correct for following platforms:
2430 - gpio mux mode 3
44xx - gpio mux mode 3
54xx - gpio mux mode 6
Patch reserves first 3 bits in partition flags for storing gpio mux
mode in same format as stored in control pad register.
Modified OMAP_MODE_GPIO() macro handles all possible cases of gpio mux mode.
Modified omap_mux_init() flags of omap34xx to include OMAP_MUX_GPIO_IN_MODE4.
Signed-off-by: Oleg Matcovschi <oleg.matcovschi@ti.com>
---
arch/arm/mach-omap2/mux.c | 4 ++--
arch/arm/mach-omap2/mux.h | 18 +++++++++++++-----
arch/arm/mach-omap2/mux34xx.c | 2 +-
3 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index 701e17c..75f854e 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -799,7 +799,7 @@ int __init omap_mux_late_init(void)
struct omap_mux *m = &e->mux;
u16 mode = omap_mux_read(partition, m->reg_offset);
- if (OMAP_MODE_GPIO(mode))
+ if (OMAP_MODE_GPIO(partition, mode))
continue;
#ifndef CONFIG_DEBUG_FS
@@ -1064,7 +1064,7 @@ static void __init omap_mux_init_list(struct omap_mux_partition *partition,
}
#else
/* Skip pins that are not muxed as GPIO by bootloader */
- if (!OMAP_MODE_GPIO(omap_mux_read(partition,
+ if (!OMAP_MODE_GPIO(partition, omap_mux_read(partition,
superset->reg_offset))) {
superset++;
continue;
diff --git a/arch/arm/mach-omap2/mux.h b/arch/arm/mach-omap2/mux.h
index 76f9b3c..8393284 100644
--- a/arch/arm/mach-omap2/mux.h
+++ b/arch/arm/mach-omap2/mux.h
@@ -58,7 +58,8 @@
#define OMAP_PIN_OFF_INPUT_PULLDOWN (OMAP_OFF_EN | OMAP_OFF_PULL_EN)
#define OMAP_PIN_OFF_WAKEUPENABLE OMAP_WAKEUP_EN
-#define OMAP_MODE_GPIO(x) (((x) & OMAP_MUX_MODE7) == OMAP_MUX_MODE4)
+#define OMAP_MODE_GPIO(partition, x) (((x) & OMAP_MUX_MODE7) == \
+ (partition->flags & OMAP_MUX_MODE7))
#define OMAP_MODE_UART(x) (((x) & OMAP_MUX_MODE7) == OMAP_MUX_MODE0)
/* Flags for omapX_mux_init */
@@ -79,13 +80,20 @@
/*
* omap_mux_init flags definition:
*
+ * OMAP_GPIO_MUX_MODE, bits 0-2: gpio muxing mode, same like pad control
+ * register which includes values from 0-7.
* OMAP_MUX_REG_8BIT: Ensure that access to padconf is done in 8 bits.
* The default value is 16 bits.
- * OMAP_MUX_GPIO_IN_MODE3: The GPIO is selected in mode3.
- * The default is mode4.
*/
-#define OMAP_MUX_REG_8BIT (1 << 0)
-#define OMAP_MUX_GPIO_IN_MODE3 (1 << 1)
+#define OMAP_MUX_GPIO_IN_MODE0 OMAP_MUX_MODE0
+#define OMAP_MUX_GPIO_IN_MODE1 OMAP_MUX_MODE1
+#define OMAP_MUX_GPIO_IN_MODE2 OMAP_MUX_MODE2
+#define OMAP_MUX_GPIO_IN_MODE3 OMAP_MUX_MODE3
+#define OMAP_MUX_GPIO_IN_MODE4 OMAP_MUX_MODE4
+#define OMAP_MUX_GPIO_IN_MODE5 OMAP_MUX_MODE5
+#define OMAP_MUX_GPIO_IN_MODE6 OMAP_MUX_MODE6
+#define OMAP_MUX_GPIO_IN_MODE7 OMAP_MUX_MODE7
+#define OMAP_MUX_REG_8BIT (1 << 3)
/**
* struct omap_board_data - board specific device data
diff --git a/arch/arm/mach-omap2/mux34xx.c b/arch/arm/mach-omap2/mux34xx.c
index c47140b..c53609f4 100644
--- a/arch/arm/mach-omap2/mux34xx.c
+++ b/arch/arm/mach-omap2/mux34xx.c
@@ -2053,7 +2053,7 @@ int __init omap3_mux_init(struct omap_board_mux *board_subset, int flags)
return -EINVAL;
}
- return omap_mux_init("core", 0,
+ return omap_mux_init("core", OMAP_MUX_GPIO_IN_MODE4,
OMAP3_CONTROL_PADCONF_MUX_PBASE,
OMAP3_CONTROL_PADCONF_MUX_SIZE,
omap3_muxmodes, package_subset, board_subset,
--
1.7.4.1
^ permalink raw reply related
* [PATCH] ARM: OMAP2+: Fix compiler warning for 32k timer
From: Jon Hunter @ 2012-11-15 21:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121115204526.GC12466@arwen.pp.htv.fi>
On 11/15/2012 02:45 PM, Felipe Balbi wrote:
> Hi,
>
> On Thu, Nov 15, 2012 at 01:44:04PM -0600, Jon Hunter wrote:
>> +static struct of_device_id omap_counter_match[] __initdata = {
>
> not directly related to $SUBJECT, but shouldn't this be static const
> __initconst ?
Yes you are right. Looks like there are several other of_device_id
structs in arch/arm/mach-omap2 that could be updated to const too.
Cheers
Jon
^ permalink raw reply
* [PATCH 7/7] ARM: Kirkwood: switch to DT clock providers
From: Andrew Lunn @ 2012-11-15 21:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1353014906-31566-1-git-send-email-andrew@lunn.ch>
With true DT clock providers available switch Kirkwood clock setup in
DT- enabled boards. While AUXDATA can be removed completely from bus
probing, some devices still don't know about DT. Therefore, some clkdev
aliases are created until these devices also move to DT.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
arch/arm/boot/dts/kirkwood.dtsi | 22 +++++++++
arch/arm/mach-kirkwood/Kconfig | 2 +
arch/arm/mach-kirkwood/board-dt.c | 72 +++++++++++++++++++++++------
arch/arm/plat-orion/include/plat/common.h | 1 +
4 files changed, 84 insertions(+), 13 deletions(-)
diff --git a/arch/arm/boot/dts/kirkwood.dtsi b/arch/arm/boot/dts/kirkwood.dtsi
index 4e5b815..5c85a57 100644
--- a/arch/arm/boot/dts/kirkwood.dtsi
+++ b/arch/arm/boot/dts/kirkwood.dtsi
@@ -19,6 +19,12 @@
#address-cells = <1>;
#size-cells = <1>;
+ core_clk: core-clocks at 10030 {
+ compatible = "marvell,kirkwood-core-clocks";
+ reg = <0x10030 0x4>;
+ #clock-cells = <1>;
+ };
+
gpio0: gpio at 10100 {
compatible = "marvell,orion-gpio";
#gpio-cells = <2>;
@@ -42,6 +48,7 @@
reg = <0x12000 0x100>;
reg-shift = <2>;
interrupts = <33>;
+ clocks = <&clk_gate 7>;
/* set clock-frequency in board dts */
status = "disabled";
};
@@ -51,6 +58,7 @@
reg = <0x12100 0x100>;
reg-shift = <2>;
interrupts = <34>;
+ clocks = <&clk_gate 7>;
/* set clock-frequency in board dts */
status = "disabled";
};
@@ -68,12 +76,21 @@
cell-index = <0>;
interrupts = <23>;
reg = <0x10600 0x28>;
+ clocks = <&clk_gate 7>;
status = "disabled";
};
+ clk_gate: clock-gating-control at 2011c {
+ compatible = "marvell,kirkwood-clock-gating";
+ reg = <0x2011c 0x4>;
+ clocks = <&core_clk 0>;
+ #clock-cells = <1>;
+ };
+
wdt at 20300 {
compatible = "marvell,orion-wdt";
reg = <0x20300 0x28>;
+ clocks = <&clk_gate 7>;
status = "okay";
};
@@ -81,6 +98,8 @@
compatible = "marvell,orion-sata";
reg = <0x80000 0x5000>;
interrupts = <21>;
+ clocks = <&clk_gate 14>, <&clk_gate 15>;
+ clock-names = "0", "1";
status = "disabled";
};
@@ -94,6 +113,7 @@
reg = <0x3000000 0x400>;
chip-delay = <25>;
/* set partition map and/or chip-delay in board dts */
+ clocks = <&clk_gate 7>;
status = "disabled";
};
@@ -104,6 +124,7 @@
#size-cells = <0>;
interrupts = <29>;
clock-frequency = <100000>;
+ clocks = <&clk_gate 7>;
status = "disabled";
};
@@ -113,6 +134,7 @@
<0xf5000000 0x800>;
reg-names = "regs", "sram";
interrupts = <22>;
+ clocks = <&clk_gate 17>;
status = "okay";
};
};
diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
index 50bca50..2833492 100644
--- a/arch/arm/mach-kirkwood/Kconfig
+++ b/arch/arm/mach-kirkwood/Kconfig
@@ -46,6 +46,8 @@ config MACH_GURUPLUG
config ARCH_KIRKWOOD_DT
bool "Marvell Kirkwood Flattened Device Tree"
+ select MVEBU_CLK_CORE
+ select MVEBU_CLK_GATING
select USE_OF
help
Say 'Y' here if you want your kernel to support the
diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c
index d94872f..0129cdc 100644
--- a/arch/arm/mach-kirkwood/board-dt.c
+++ b/arch/arm/mach-kirkwood/board-dt.c
@@ -14,11 +14,15 @@
#include <linux/init.h>
#include <linux/of.h>
#include <linux/of_platform.h>
+#include <linux/clk-provider.h>
+#include <linux/clk/mvebu.h>
#include <linux/kexec.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <mach/bridge-regs.h>
+#include <linux/platform_data/usb-ehci-orion.h>
#include <plat/irq.h>
+#include <plat/common.h>
#include "common.h"
static struct of_device_id kirkwood_dt_match_table[] __initdata = {
@@ -26,16 +30,59 @@ static struct of_device_id kirkwood_dt_match_table[] __initdata = {
{ }
};
-struct of_dev_auxdata kirkwood_auxdata_lookup[] __initdata = {
- OF_DEV_AUXDATA("marvell,orion-spi", 0xf1010600, "orion_spi.0", NULL),
- OF_DEV_AUXDATA("marvell,mv64xxx-i2c", 0xf1011000, "mv64xxx_i2c.0",
- NULL),
- OF_DEV_AUXDATA("marvell,orion-wdt", 0xf1020300, "orion_wdt", NULL),
- OF_DEV_AUXDATA("marvell,orion-sata", 0xf1080000, "sata_mv.0", NULL),
- OF_DEV_AUXDATA("marvell,orion-nand", 0xf4000000, "orion_nand", NULL),
- OF_DEV_AUXDATA("marvell,orion-crypto", 0xf1030000, "mv_crypto", NULL),
- {},
-};
+/*
+ * There are still devices that doesn't know about DT yet. Get clock
+ * gates here and add a clock lookup alias, so that old platform
+ * devices still work.
+*/
+
+static void __init kirkwood_legacy_clk_init(void)
+{
+
+ struct device_node *np = of_find_compatible_node(NULL, NULL,
+ "marvell,kirkwood-clock-gating");
+
+ struct of_phandle_args clkspec;
+
+ clkspec.np = np;
+ clkspec.args_count = 1;
+
+ clkspec.args[0] = CGC_BIT_GE0;
+ orion_clkdev_add(NULL, "mv643xx_eth_port.0",
+ of_clk_get_from_provider(&clkspec));
+
+ clkspec.args[0] = CGC_BIT_PEX0;
+ orion_clkdev_add("0", "pcie",
+ of_clk_get_from_provider(&clkspec));
+
+ clkspec.args[0] = CGC_BIT_USB0;
+ orion_clkdev_add(NULL, "orion-ehci.0",
+ of_clk_get_from_provider(&clkspec));
+
+ clkspec.args[0] = CGC_BIT_XOR0;
+ orion_clkdev_add(NULL, "mv_xor_shared.0",
+ of_clk_get_from_provider(&clkspec));
+
+ clkspec.args[0] = CGC_BIT_XOR1;
+ orion_clkdev_add(NULL, "mv_xor_shared.1",
+ of_clk_get_from_provider(&clkspec));
+
+ clkspec.args[0] = CGC_BIT_PEX1;
+ orion_clkdev_add("1", "pcie",
+ of_clk_get_from_provider(&clkspec));
+
+ clkspec.args[0] = CGC_BIT_GE1;
+ orion_clkdev_add(NULL, "mv643xx_eth_port.1",
+ of_clk_get_from_provider(&clkspec));
+
+}
+
+static void __init kirkwood_of_clk_init(void)
+{
+ mvebu_clocks_init();
+ mvebu_clk_gating_init();
+ kirkwood_legacy_clk_init();
+}
static void __init kirkwood_dt_init(void)
{
@@ -54,7 +101,7 @@ static void __init kirkwood_dt_init(void)
kirkwood_l2_init();
/* Setup root of clk tree */
- kirkwood_clk_init();
+ kirkwood_of_clk_init();
/* internal devices that every board has */
kirkwood_xor0_init();
@@ -94,8 +141,7 @@ static void __init kirkwood_dt_init(void)
if (of_machine_is_compatible("keymile,km_kirkwood"))
km_kirkwood_init();
- of_platform_populate(NULL, kirkwood_dt_match_table,
- kirkwood_auxdata_lookup, NULL);
+ of_platform_populate(NULL, kirkwood_dt_match_table, NULL, NULL);
}
static const char *kirkwood_dt_board_compat[] = {
diff --git a/arch/arm/plat-orion/include/plat/common.h b/arch/arm/plat-orion/include/plat/common.h
index 6bbc3fe..e06fc5f 100644
--- a/arch/arm/plat-orion/include/plat/common.h
+++ b/arch/arm/plat-orion/include/plat/common.h
@@ -12,6 +12,7 @@
#include <linux/mv643xx_eth.h>
struct dsa_platform_data;
+struct mv_sata_platform_data;
void __init orion_uart0_init(void __iomem *membase,
resource_size_t mapbase,
--
1.7.10.4
^ permalink raw reply related
* [PATCH 6/7] ARM: dove: switch to DT clock providers
From: Andrew Lunn @ 2012-11-15 21:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1353014906-31566-1-git-send-email-andrew@lunn.ch>
From: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
With true DT clock providers available switch Dove clock setup in DT-
enabled boards. While AUXDATA can be removed completely from bus probing,
some devices still don't know about DT at all. Therefore, some clock
aliases are created until the devices also move to DT.
Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---
arch/arm/Kconfig | 1 +
arch/arm/boot/dts/dove.dtsi | 20 ++++++++++++++
arch/arm/mach-dove/Kconfig | 2 ++
arch/arm/mach-dove/common.c | 64 +++++++++++++++++++++++++++++++++----------
4 files changed, 72 insertions(+), 15 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index ade7e92..0590099 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -533,6 +533,7 @@ config ARCH_IXP4XX
config ARCH_DOVE
bool "Marvell Dove"
select ARCH_REQUIRE_GPIOLIB
+ select COMMON_CLK_DOVE
select CPU_V7
select GENERIC_CLOCKEVENTS
select MIGHT_HAVE_PCI
diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi
index 5a00022..6c3919a 100644
--- a/arch/arm/boot/dts/dove.dtsi
+++ b/arch/arm/boot/dts/dove.dtsi
@@ -31,6 +31,19 @@
reg = <0x20204 0x04>, <0x20214 0x04>;
};
+ core_clk: core-clocks at d0214 {
+ compatible = "marvell,dove-core-clocks";
+ reg = <0xd0214 0x4>;
+ #clock-cells = <1>;
+ };
+
+ clk_gate: clock-gating-control at d0038 {
+ compatible = "marvell,dove-clock-gating";
+ reg = <0xd0038 0x4>;
+ clocks = <&core_clk 0>;
+ #clock-cells = <1>;
+ };
+
uart0: serial at 12000 {
compatible = "ns16550a";
reg = <0x12000 0x100>;
@@ -100,6 +113,7 @@
cell-index = <0>;
interrupts = <6>;
reg = <0x10600 0x28>;
+ clocks = <&core_clk 0>;
status = "disabled";
};
@@ -110,6 +124,7 @@
cell-index = <1>;
interrupts = <5>;
reg = <0x14600 0x28>;
+ clocks = <&core_clk 0>;
status = "disabled";
};
@@ -121,6 +136,7 @@
interrupts = <11>;
clock-frequency = <400000>;
timeout-ms = <1000>;
+ clocks = <&core_clk 0>;
status = "disabled";
};
@@ -128,6 +144,7 @@
compatible = "marvell,dove-sdhci";
reg = <0x92000 0x100>;
interrupts = <35>, <37>;
+ clocks = <&clk_gate 8>;
status = "disabled";
};
@@ -135,6 +152,7 @@
compatible = "marvell,dove-sdhci";
reg = <0x90000 0x100>;
interrupts = <36>, <38>;
+ clocks = <&clk_gate 9>;
status = "disabled";
};
@@ -142,6 +160,7 @@
compatible = "marvell,orion-sata";
reg = <0xa0000 0x2400>;
interrupts = <62>;
+ clocks = <&clk_gate 3>;
nr-ports = <1>;
status = "disabled";
};
@@ -152,6 +171,7 @@
<0xc8000000 0x800>;
reg-names = "regs", "sram";
interrupts = <31>;
+ clocks = <&clk_gate 15>;
status = "okay";
};
};
diff --git a/arch/arm/mach-dove/Kconfig b/arch/arm/mach-dove/Kconfig
index 00154e7..603c5fd 100644
--- a/arch/arm/mach-dove/Kconfig
+++ b/arch/arm/mach-dove/Kconfig
@@ -17,6 +17,8 @@ config MACH_CM_A510
config MACH_DOVE_DT
bool "Marvell Dove Flattened Device Tree"
+ select MVEBU_CLK_CORE
+ select MVEBU_CLK_GATING
select USE_OF
help
Say 'Y' here if you want your kernel to support the
diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c
index f723fe1..96b40e3 100644
--- a/arch/arm/mach-dove/common.c
+++ b/arch/arm/mach-dove/common.c
@@ -14,6 +14,7 @@
#include <linux/platform_device.h>
#include <linux/pci.h>
#include <linux/clk-provider.h>
+#include <linux/clk/mvebu.h>
#include <linux/ata_platform.h>
#include <linux/gpio.h>
#include <linux/of.h>
@@ -376,19 +377,53 @@ void dove_restart(char mode, const char *cmd)
#if defined(CONFIG_MACH_DOVE_DT)
/*
- * Auxdata required until real OF clock provider
+ * There are still devices that doesn't even know about DT,
+ * get clock gates here and add a clock lookup.
*/
-struct of_dev_auxdata dove_auxdata_lookup[] __initdata = {
- OF_DEV_AUXDATA("marvell,orion-spi", 0xf1010600, "orion_spi.0", NULL),
- OF_DEV_AUXDATA("marvell,orion-spi", 0xf1014600, "orion_spi.1", NULL),
- OF_DEV_AUXDATA("marvell,orion-wdt", 0xf1020300, "orion_wdt", NULL),
- OF_DEV_AUXDATA("marvell,mv64xxx-i2c", 0xf1011000, "mv64xxx_i2c.0",
- NULL),
- OF_DEV_AUXDATA("marvell,orion-sata", 0xf10a0000, "sata_mv.0", NULL),
- OF_DEV_AUXDATA("marvell,dove-sdhci", 0xf1092000, "sdhci-dove.0", NULL),
- OF_DEV_AUXDATA("marvell,dove-sdhci", 0xf1090000, "sdhci-dove.1", NULL),
- {},
-};
+static void __init dove_legacy_clk_init(void)
+{
+ struct device_node *np = of_find_compatible_node(NULL, NULL,
+ "marvell,dove-clock-gating");
+ struct of_phandle_args clkspec;
+
+ clkspec.np = np;
+ clkspec.args_count = 1;
+
+ clkspec.args[0] = CLOCK_GATING_BIT_USB0;
+ orion_clkdev_add(NULL, "orion-ehci.0",
+ of_clk_get_from_provider(&clkspec));
+
+ clkspec.args[0] = CLOCK_GATING_BIT_USB1;
+ orion_clkdev_add(NULL, "orion-ehci.1",
+ of_clk_get_from_provider(&clkspec));
+
+ clkspec.args[0] = CLOCK_GATING_BIT_GBE;
+ orion_clkdev_add(NULL, "mv643xx_eth_port.0",
+ of_clk_get_from_provider(&clkspec));
+
+ clkspec.args[0] = CLOCK_GATING_BIT_PCIE0;
+ orion_clkdev_add("0", "pcie",
+ of_clk_get_from_provider(&clkspec));
+
+ clkspec.args[0] = CLOCK_GATING_BIT_PCIE1;
+ orion_clkdev_add("1", "pcie",
+ of_clk_get_from_provider(&clkspec));
+
+ clkspec.args[0] = CLOCK_GATING_BIT_XOR0;
+ orion_clkdev_add(NULL, "mv_xor_shared.0",
+ of_clk_get_from_provider(&clkspec));
+
+ clkspec.args[0] = CLOCK_GATING_BIT_XOR1;
+ orion_clkdev_add(NULL, "mv_xor_shared.1",
+ of_clk_get_from_provider(&clkspec));
+}
+
+static void __init dove_of_clk_init(void)
+{
+ mvebu_clocks_init();
+ mvebu_clk_gating_init();
+ dove_legacy_clk_init();
+}
static struct mv643xx_eth_platform_data dove_dt_ge00_data = {
.phy_addr = MV643XX_ETH_PHY_ADDR_DEFAULT,
@@ -405,7 +440,7 @@ static void __init dove_dt_init(void)
dove_setup_cpu_mbus();
/* Setup root of clk tree */
- dove_clk_init();
+ dove_of_clk_init();
/* Internal devices not ported to DT yet */
dove_rtc_init();
@@ -417,8 +452,7 @@ static void __init dove_dt_init(void)
dove_ehci1_init();
dove_pcie_init(1, 1);
- of_platform_populate(NULL, of_default_bus_match_table,
- dove_auxdata_lookup, NULL);
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
static const char * const dove_dt_board_compat[] = {
--
1.7.10.4
^ permalink raw reply related
* [PATCH 5/7] clk: mvebu: add clock gating control provider for DT
From: Andrew Lunn @ 2012-11-15 21:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1353014906-31566-1-git-send-email-andrew@lunn.ch>
From: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
This driver allows to provide DT clocks for clock gates found on
Marvell Dove and Kirkwood SoCs. The clock gates are referenced by
the phandle index of the corresponding bit in the clock gating control
register to ease lookup in the datasheet.
Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---
.../bindings/clock/mvebu-gated-clock.txt | 76 +++++++++
drivers/clk/mvebu/Kconfig | 2 +
drivers/clk/mvebu/Makefile | 1 +
drivers/clk/mvebu/clk-gating-ctrl.c | 177 ++++++++++++++++++++
include/linux/clk/mvebu.h | 1 +
5 files changed, 257 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
create mode 100644 drivers/clk/mvebu/clk-gating-ctrl.c
diff --git a/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
new file mode 100644
index 0000000..7497cc0
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
@@ -0,0 +1,76 @@
+* Gated Clock bindings for Marvell Orion SoCs
+
+Marvell Dove and Kirkwood allow some peripheral clocks to be gated to save
+some power. The clock consumer should specify the desired clock by having
+the clock ID in its "clocks" phandle cell. The clock ID is directly mapped to
+the corresponding clock gating control bit in HW to ease manual clock lookup
+in datasheet.
+
+The following is a list of provided IDs for Dove:
+ID Clock Peripheral
+-----------------------------------
+0 usb0 USB Host 0
+1 usb1 USB Host 1
+2 ge Gigabit Ethernet
+3 sata SATA Host
+4 pex0 PCIe Cntrl 0
+5 pex1 PCIe Cntrl 1
+8 sdio0 SDHCI Host 0
+9 sdio1 SDHCI Host 1
+10 nand NAND Cntrl
+11 camera Camera Cntrl
+12 i2s0 I2S Cntrl 0
+13 i2s1 I2S Cntrl 1
+15 crypto CESA engine
+21 ac97 AC97 Cntrl
+22 pdma Peripheral DMA
+23 xor0 XOR DMA 0
+24 xor1 XOR DMA 1
+30 gephy Gigabit Ethernel PHY
+Note: gephy(30) is implemented as a parent clock of ge(2)
+
+The following is a list of provided IDs for Kirkwood:
+ID Clock Peripheral
+-----------------------------------
+0 ge0 Gigabit Ethernet 0
+2 pex0 PCIe Cntrl 0
+3 usb0 USB Host 0
+4 sdio SDIO Cntrl
+5 tsu Transp. Stream Unit
+6 dunit SDRAM Cntrl
+7 runit Runit
+8 xor0 XOR DMA 0
+9 audio I2S Cntrl 0
+14 sata0 SATA Host 0
+15 sata1 SATA Host 1
+16 xor1 XOR DMA 1
+17 crypto CESA engine
+18 pex1 PCIe Cntrl 1
+19 ge1 Gigabit Ethernet 0
+20 tdm Time Division Mplx
+
+Required properties:
+- compatible : shall be one of the following:
+ "marvell,dove-clock-gating" - for Dove SoC clock gating
+ "marvell,kirkwood-clock-gating" - for Kirkwood SoC clock gating
+- reg : shall be the register address of the Clock Gating Control register
+- #clock-cells : from common clock binding; shall be set to 1
+
+Optional properties:
+- clocks : default parent clock phandle (e.g. tclk)
+
+Example:
+
+clk_gate: clock-gating-control at d0038 {
+ compatible = "marvell,dove-clock-gating";
+ reg = <0xd0038 0x4>;
+ /* default parent clock is tclk */
+ clocks = <&core_clk 0>;
+ #clock-cells = <1>;
+};
+
+sdio0: sdio at 92000 {
+ compatible = "marvell,dove-sdhci";
+ /* get clk gate bit 8 (sdio0) */
+ clocks = <&clk_gate 8>;
+};
diff --git a/drivers/clk/mvebu/Kconfig b/drivers/clk/mvebu/Kconfig
index 1dd93ad..57323fd 100644
--- a/drivers/clk/mvebu/Kconfig
+++ b/drivers/clk/mvebu/Kconfig
@@ -4,3 +4,5 @@ config MVEBU_CLK_CORE
config MVEBU_CLK_CPU
bool
+config MVEBU_CLK_GATING
+ bool
diff --git a/drivers/clk/mvebu/Makefile b/drivers/clk/mvebu/Makefile
index 93da083..58df3dc 100644
--- a/drivers/clk/mvebu/Makefile
+++ b/drivers/clk/mvebu/Makefile
@@ -1,2 +1,3 @@
obj-$(CONFIG_MVEBU_CLK_CORE) += clk.o clk-core.o
obj-$(CONFIG_MVEBU_CLK_CPU) += clk-cpu.o
+obj-$(CONFIG_MVEBU_CLK_GATING) += clk-gating-ctrl.o
diff --git a/drivers/clk/mvebu/clk-gating-ctrl.c b/drivers/clk/mvebu/clk-gating-ctrl.c
new file mode 100644
index 0000000..3ac7607
--- /dev/null
+++ b/drivers/clk/mvebu/clk-gating-ctrl.c
@@ -0,0 +1,177 @@
+/*
+ * Marvell MVEBU clock gating control.
+ *
+ * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/clk/mvebu.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+struct mvebu_gating_ctrl {
+ spinlock_t lock;
+ struct clk **gates;
+ int num_gates;
+};
+
+struct mvebu_soc_descr {
+ const char *name;
+ const char *parent;
+ int bit_idx;
+};
+
+#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
+
+static struct clk __init *mvebu_clk_gating_get_src(
+ struct of_phandle_args *clkspec, void *data)
+{
+ struct mvebu_gating_ctrl *ctrl = (struct mvebu_gating_ctrl *)data;
+ int n;
+
+ if (clkspec->args_count < 1)
+ return ERR_PTR(-EINVAL);
+
+ for (n = 0; n < ctrl->num_gates; n++) {
+ struct clk_gate *gate =
+ to_clk_gate(__clk_get_hw(ctrl->gates[n]));
+ if (clkspec->args[0] == gate->bit_idx)
+ return ctrl->gates[n];
+ }
+ return ERR_PTR(-ENODEV);
+}
+
+static void __init mvebu_clk_gating_setup(
+ struct device_node *np, const struct mvebu_soc_descr *descr)
+{
+ struct mvebu_gating_ctrl *ctrl;
+ struct clk *clk;
+ void __iomem *base;
+ const char *default_parent = NULL;
+ int n;
+
+ base = of_iomap(np, 0);
+
+ clk = of_clk_get(np, 0);
+ if (!IS_ERR(clk)) {
+ default_parent = __clk_get_name(clk);
+ clk_put(clk);
+ }
+
+ ctrl = kzalloc(sizeof(struct mvebu_gating_ctrl), GFP_KERNEL);
+ if (WARN_ON(!ctrl))
+ return;
+
+ spin_lock_init(&ctrl->lock);
+
+ /*
+ * Count, allocate, and register clock gates
+ */
+ for (n = 0; descr[n].name;)
+ n++;
+
+ ctrl->num_gates = n;
+ ctrl->gates = kzalloc(ctrl->num_gates * sizeof(struct clk *),
+ GFP_KERNEL);
+ if (WARN_ON(!ctrl->gates)) {
+ kfree(ctrl);
+ return;
+ }
+
+ for (n = 0; n < ctrl->num_gates; n++) {
+ const char *parent =
+ (descr[n].parent) ? descr[n].parent : default_parent;
+ ctrl->gates[n] = clk_register_gate(NULL, descr[n].name, parent,
+ 0, base, descr[n].bit_idx, 0, &ctrl->lock);
+ WARN_ON(IS_ERR(ctrl->gates[n]));
+ }
+ of_clk_add_provider(np, mvebu_clk_gating_get_src, ctrl);
+}
+
+/*
+ * SoC specific clock gating control
+ */
+
+#ifdef CONFIG_ARCH_DOVE
+static const struct mvebu_soc_descr __initconst dove_gating_descr[] = {
+ { "usb0", NULL, 0 },
+ { "usb1", NULL, 1 },
+ { "ge", "gephy", 2 },
+ { "sata", NULL, 3 },
+ { "pex0", NULL, 4 },
+ { "pex1", NULL, 5 },
+ { "sdio0", NULL, 8 },
+ { "sdio1", NULL, 9 },
+ { "nand", NULL, 10 },
+ { "camera", NULL, 11 },
+ { "i2s0", NULL, 12 },
+ { "i2s1", NULL, 13 },
+ { "crypto", NULL, 15 },
+ { "ac97", NULL, 21 },
+ { "pdma", NULL, 22 },
+ { "xor0", NULL, 23 },
+ { "xor1", NULL, 24 },
+ { "gephy", NULL, 30 },
+ { }
+};
+#endif
+
+#ifdef CONFIG_ARCH_KIRKWOOD
+static const struct mvebu_soc_descr __initconst kirkwood_gating_descr[] = {
+ { "ge0", NULL, 0 },
+ { "pex0", NULL, 2 },
+ { "usb0", NULL, 3 },
+ { "sdio", NULL, 4 },
+ { "tsu", NULL, 5 },
+ { "runit", NULL, 7 },
+ { "xor0", NULL, 8 },
+ { "audio", NULL, 9 },
+ { "sata0", NULL, 14 },
+ { "sata1", NULL, 15 },
+ { "xor1", NULL, 16 },
+ { "crypto", NULL, 17 },
+ { "pex1", NULL, 18 },
+ { "ge1", NULL, 19 },
+ { "tdm", NULL, 20 },
+ { }
+};
+#endif
+
+static const __initdata struct of_device_id clk_gating_match[] = {
+#ifdef CONFIG_ARCH_DOVE
+ {
+ .compatible = "marvell,dove-clock-gating",
+ .data = dove_gating_descr,
+ },
+#endif
+
+#ifdef CONFIG_ARCH_KIRKWOOD
+ {
+ .compatible = "marvell,kirkwood-clock-gating",
+ .data = kirkwood_gating_descr,
+ },
+#endif
+
+ { }
+};
+
+void __init mvebu_clk_gating_init(void)
+{
+ struct device_node *np;
+
+ for_each_matching_node(np, clk_gating_match) {
+ const struct of_device_id *match =
+ of_match_node(clk_gating_match, np);
+ mvebu_clk_gating_setup(np,
+ (const struct mvebu_soc_descr *)match->data);
+ }
+}
diff --git a/include/linux/clk/mvebu.h b/include/linux/clk/mvebu.h
index 8c4ae71..70c366f 100644
--- a/include/linux/clk/mvebu.h
+++ b/include/linux/clk/mvebu.h
@@ -18,5 +18,6 @@
#define __CLK_MVEBU_H_
void __init mvebu_clocks_init(void);
+void mvebu_clk_gating_init(void);
#endif
--
1.7.10.4
^ permalink raw reply related
* [PATCH 4/7] clocksource: time-armada-370-xp converted to clk framework
From: Andrew Lunn @ 2012-11-15 21:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1353014906-31566-1-git-send-email-andrew@lunn.ch>
From: Gregory CLEMENT <gregory.clement@free-electrons.com>
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
cc: John Stultz <johnstul@us.ibm.com>
---
arch/arm/boot/dts/armada-370-db.dts | 4 ----
arch/arm/boot/dts/armada-370-xp.dtsi | 1 +
drivers/clocksource/time-armada-370-xp.c | 11 ++++++-----
3 files changed, 7 insertions(+), 9 deletions(-)
diff --git a/arch/arm/boot/dts/armada-370-db.dts b/arch/arm/boot/dts/armada-370-db.dts
index fffd5c2..4a31b03 100644
--- a/arch/arm/boot/dts/armada-370-db.dts
+++ b/arch/arm/boot/dts/armada-370-db.dts
@@ -34,9 +34,5 @@
clock-frequency = <200000000>;
status = "okay";
};
- timer at d0020300 {
- clock-frequency = <600000000>;
- status = "okay";
- };
};
};
diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi
index 16cc82c..94b4b9e 100644
--- a/arch/arm/boot/dts/armada-370-xp.dtsi
+++ b/arch/arm/boot/dts/armada-370-xp.dtsi
@@ -62,6 +62,7 @@
compatible = "marvell,armada-370-xp-timer";
reg = <0xd0020300 0x30>;
interrupts = <37>, <38>, <39>, <40>;
+ clocks = <&coreclk 2>;
};
addr-decoding at d0020000 {
diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c
index 4674f94..a4605fd 100644
--- a/drivers/clocksource/time-armada-370-xp.c
+++ b/drivers/clocksource/time-armada-370-xp.c
@@ -18,6 +18,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
+#include <linux/clk.h>
#include <linux/timer.h>
#include <linux/clockchips.h>
#include <linux/interrupt.h>
@@ -167,7 +168,6 @@ void __init armada_370_xp_timer_init(void)
u32 u;
struct device_node *np;
unsigned int timer_clk;
- int ret;
np = of_find_compatible_node(NULL, NULL, "marvell,armada-370-xp-timer");
timer_base = of_iomap(np, 0);
WARN_ON(!timer_base);
@@ -179,13 +179,14 @@ void __init armada_370_xp_timer_init(void)
timer_base + TIMER_CTRL_OFF);
timer_clk = 25000000;
} else {
- u32 clk = 0;
- ret = of_property_read_u32(np, "clock-frequency", &clk);
- WARN_ON(!clk || ret < 0);
+ unsigned long rate = 0;
+ struct clk *clk = of_clk_get(np, 0);
+ WARN_ON(IS_ERR(clk));
+ rate = clk_get_rate(clk);
u = readl(timer_base + TIMER_CTRL_OFF);
writel(u & ~(TIMER0_25MHZ | TIMER1_25MHZ),
timer_base + TIMER_CTRL_OFF);
- timer_clk = clk / TIMER_DIVIDER;
+ timer_clk = rate / TIMER_DIVIDER;
}
/* We use timer 0 as clocksource, and timer 1 for
--
1.7.10.4
^ permalink raw reply related
* [PATCH 3/7] clk: armada-370-xp: add support for clock framework
From: Andrew Lunn @ 2012-11-15 21:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1353014906-31566-1-git-send-email-andrew@lunn.ch>
From: Gregory CLEMENT <gregory.clement@free-electrons.com>
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
arch/arm/boot/dts/armada-370.dtsi | 7 ++++++
arch/arm/boot/dts/armada-xp.dtsi | 42 +++++++++++++++++++++++++++++++++++
arch/arm/mach-mvebu/Kconfig | 6 +++++
arch/arm/mach-mvebu/armada-370-xp.c | 9 +++++++-
4 files changed, 63 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi
index 2069151..dae966c 100644
--- a/arch/arm/boot/dts/armada-370.dtsi
+++ b/arch/arm/boot/dts/armada-370.dtsi
@@ -75,5 +75,12 @@
#interrupts-cells = <2>;
interrupts = <91>;
};
+
+ coreclk: mvebu-sar at d0018230 {
+ compatible = "marvell,armada-370-core-clocks";
+ reg = <0xd0018230 0x08>;
+ #clock-cells = <1>;
+ };
+
};
};
diff --git a/arch/arm/boot/dts/armada-xp.dtsi b/arch/arm/boot/dts/armada-xp.dtsi
index 71d6b5d..f8382a8 100644
--- a/arch/arm/boot/dts/armada-xp.dtsi
+++ b/arch/arm/boot/dts/armada-xp.dtsi
@@ -27,6 +27,35 @@
<0xd0021870 0x58>;
};
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu at 0 {
+ compatible = "marvell,sheeva-v7";
+ reg = <0>;
+ clocks = <&cpuclk 0>;
+ };
+
+ cpu at 1 {
+ compatible = "marvell,sheeva-v7";
+ reg = <1>;
+ clocks = <&cpuclk 1>;
+ };
+
+ cpu at 2 {
+ compatible = "marvell,sheeva-v7";
+ reg = <2>;
+ clocks = <&cpuclk 2>;
+ };
+
+ cpu at 3 {
+ compatible = "marvell,sheeva-v7";
+ reg = <3>;
+ clocks = <&cpuclk 3>;
+ };
+ };
+
soc {
serial at d0012200 {
compatible = "ns16550";
@@ -47,6 +76,19 @@
marvell,timer-25Mhz;
};
+ coreclk: mvebu-sar at d0018230 {
+ compatible = "marvell,armada-xp-core-clocks";
+ reg = <0xd0018230 0x08>;
+ #clock-cells = <1>;
+ };
+
+ cpuclk: clock-complex at d0018700 {
+ #clock-cells = <1>;
+ compatible = "marvell,armada-xp-cpu-clockctrl";
+ reg = <0xd0018700 0xA0>;
+ clocks = <&coreclk 1>;
+ };
+
system-controller at d0018200 {
compatible = "marvell,armada-370-xp-system-controller";
reg = <0xd0018200 0x500>;
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 416d46e..e5f0ae2 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -9,11 +9,17 @@ config ARCH_MVEBU
select PINCTRL
select PLAT_ORION
select SPARSE_IRQ
+ select CLKDEV_LOOKUP
+ select MVEBU_CLK_CORE
+ select MVEBU_CLK_CPU
if ARCH_MVEBU
menu "Marvell SOC with device tree"
+config MVEBU_CLK_CPU
+ bool
+
config MACH_ARMADA_370_XP
bool
select ARMADA_370_XP_TIMER
diff --git a/arch/arm/mach-mvebu/armada-370-xp.c b/arch/arm/mach-mvebu/armada-370-xp.c
index 49d7915..3292d6d 100644
--- a/arch/arm/mach-mvebu/armada-370-xp.c
+++ b/arch/arm/mach-mvebu/armada-370-xp.c
@@ -17,6 +17,7 @@
#include <linux/of_platform.h>
#include <linux/io.h>
#include <linux/time-armada-370-xp.h>
+#include <linux/clk/mvebu.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/time.h>
@@ -37,8 +38,14 @@ void __init armada_370_xp_map_io(void)
iotable_init(armada_370_xp_io_desc, ARRAY_SIZE(armada_370_xp_io_desc));
}
+void __init armada_370_xp_timer_and_clk_init(void)
+{
+ mvebu_clocks_init();
+ armada_370_xp_timer_init();
+}
+
struct sys_timer armada_370_xp_timer = {
- .init = armada_370_xp_timer_init,
+ .init = armada_370_xp_timer_and_clk_init,
};
static void __init armada_370_xp_dt_init(void)
--
1.7.10.4
^ permalink raw reply related
* [PATCH 2/7] clk: mvebu: add armada-370-xp CPU specific clocks
From: Andrew Lunn @ 2012-11-15 21:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1353014906-31566-1-git-send-email-andrew@lunn.ch>
From: Gregory CLEMENT <gregory.clement@free-electrons.com>
Add Armada 370/XP specific CPU clocks
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
.../devicetree/bindings/clock/mvebu-core-clock.txt | 18 +--
.../devicetree/bindings/clock/mvebu-cpu-clock.txt | 21 +++
drivers/clk/mvebu/Kconfig | 3 +
drivers/clk/mvebu/Makefile | 1 +
drivers/clk/mvebu/clk-core.c | 4 +-
drivers/clk/mvebu/clk-cpu.c | 155 ++++++++++++++++++++
drivers/clk/mvebu/clk-cpu.h | 18 +++
drivers/clk/mvebu/clk.c | 14 ++
8 files changed, 223 insertions(+), 11 deletions(-)
create mode 100644 Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt
create mode 100644 drivers/clk/mvebu/clk-cpu.c
create mode 100644 drivers/clk/mvebu/clk-cpu.h
diff --git a/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt
index 84cfae7..ffb3d69 100644
--- a/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt
+++ b/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt
@@ -4,26 +4,26 @@ Marvell MVEBU SoCs usually allow to determine core clock frequencies by
reading the Sample-At-Reset (SAR) register. The core clock consumer should
specify the desired clock by having the clock ID in its "clocks" phandle cell.
-The following is a list of provided IDs and clock names on Kirkwood and Dove:
- 0 = tclk (Internal Bus clock)
- 1 = cpuclk (CPU0 clock)
- 2 = l2clk (L2 Cache clock derived from CPU0 clock)
- 3 = ddrclk (DDR controller clock derived from CPU0 clock)
-
-The following is a list of provided IDs and clock names on 370/XP:
+The following is a list of provided IDs and clock names on Armada 370/XP:
0 = tclk (Internal Bus clock)
1 = cpuclk (CPU clock)
2 = nbclk (L2 Cache clock)
3 = hclk (DRAM control clock)
4 = dramclk (DDR clock)
+The following is a list of provided IDs and clock names on Kirkwood and Dove:
+ 0 = tclk (Internal Bus clock)
+ 1 = cpuclk (CPU0 clock)
+ 2 = l2clk (L2 Cache clock derived from CPU0 clock)
+ 3 = ddrclk (DDR controller clock derived from CPU0 clock)
+
Required properties:
- compatible : shall be one of the following:
+ "marvell,armada-370-core-clocks" - For Armada 370 SoC core clocks
+ "marvell,armada-xp-core-clocks" - For Armada XP SoC core clocks
"marvell,dove-core-clocks" - for Dove SoC core clocks
"marvell,kirkwood-core-clocks" - for Kirkwood SoC (except mv88f6180)
"marvell,mv88f6180-core-clocks" - for Kirkwood MV88f6180 SoC
- "marvell,370-core-clocks" - For 370 SoC core clocks
- "marvell,xp-core-clocks" - For XP SoC core clocks
- reg : shall be the register address of the Sample-At-Reset (SAR) register
- #clock-cells : from common clock binding; shall be set to 1
diff --git a/Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt
new file mode 100644
index 0000000..1fb5a64
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt
@@ -0,0 +1,21 @@
+Device Tree Clock bindings for cpu clock of Marvell EBU platforms
+
+Required properties:
+- compatible : shall be one of the following:
+ "marvell,armada-xp-cpu-clockctrl" - cpu clocks for Armada XP
+- reg : Address and length of the clock complex register set
+- #clock-cells : should be set to 1.
+- clocks : shall be the input parent clock phandle for the clock.
+
+cpuclk: clock-complex at d0018700 {
+ #clock-cells = <1>;
+ compatible = "marvell,armada-xp-cpu-clockctrl";
+ reg = <0xd0018700 0xA0>;
+ clocks = <&coreclk 1>;
+}
+
+cpu at 0 {
+ compatible = "marvell,sheeva-v7";
+ reg = <0>;
+ clocks = <&cpuclk 0>;
+};
diff --git a/drivers/clk/mvebu/Kconfig b/drivers/clk/mvebu/Kconfig
index fd7bf97..1dd93ad 100644
--- a/drivers/clk/mvebu/Kconfig
+++ b/drivers/clk/mvebu/Kconfig
@@ -1,3 +1,6 @@
config MVEBU_CLK_CORE
bool
+config MVEBU_CLK_CPU
+ bool
+
diff --git a/drivers/clk/mvebu/Makefile b/drivers/clk/mvebu/Makefile
index de1d961..93da083 100644
--- a/drivers/clk/mvebu/Makefile
+++ b/drivers/clk/mvebu/Makefile
@@ -1 +1,2 @@
obj-$(CONFIG_MVEBU_CLK_CORE) += clk.o clk-core.o
+obj-$(CONFIG_MVEBU_CLK_CPU) += clk-cpu.o
diff --git a/drivers/clk/mvebu/clk-core.c b/drivers/clk/mvebu/clk-core.c
index 26ba835..1881872 100644
--- a/drivers/clk/mvebu/clk-core.c
+++ b/drivers/clk/mvebu/clk-core.c
@@ -634,11 +634,11 @@ static const struct core_clocks mv88f6180_core_clocks = {
static const __initdata struct of_device_id clk_core_match[] = {
#ifdef CONFIG_MACH_ARMADA_370_XP
{
- .compatible = "marvell,370-core-clocks",
+ .compatible = "marvell,armada-370-core-clocks",
.data = &a370_core_clocks,
},
{
- .compatible = "marvell,xp-core-clocks",
+ .compatible = "marvell,armada-xp-core-clocks",
.data = &xp_core_clocks,
},
#endif
diff --git a/drivers/clk/mvebu/clk-cpu.c b/drivers/clk/mvebu/clk-cpu.c
new file mode 100644
index 0000000..1df027a
--- /dev/null
+++ b/drivers/clk/mvebu/clk-cpu.c
@@ -0,0 +1,155 @@
+/*
+ * Marvell MVEBU CPU clock handling.
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/delay.h>
+#include "clk-cpu.h"
+
+#define SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET 0x0
+#define SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET 0xC
+#define SYS_CTRL_CLK_DIVIDER_MASK 0x3F
+
+#define MAX_CPU 4
+struct cpu_clk {
+ struct clk_hw hw;
+ int cpu;
+ const char *clk_name;
+ const char *parent_name;
+ void __iomem *reg_base;
+};
+
+static struct clk **clks;
+
+static struct clk_onecell_data clk_data;
+
+#define to_cpu_clk(p) container_of(p, struct cpu_clk, hw)
+
+static unsigned long clk_cpu_recalc_rate(struct clk_hw *hwclk,
+ unsigned long parent_rate)
+{
+ struct cpu_clk *cpuclk = to_cpu_clk(hwclk);
+ u32 reg, div;
+
+ reg = readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET);
+ div = (reg >> (cpuclk->cpu * 8)) & SYS_CTRL_CLK_DIVIDER_MASK;
+ return parent_rate / div;
+}
+
+static long clk_cpu_round_rate(struct clk_hw *hwclk, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ /* Valid ratio are 1:1, 1:2 and 1:3 */
+ u32 div;
+
+ div = *parent_rate / rate;
+ if (div == 0)
+ div = 1;
+ else if (div > 3)
+ div = 3;
+
+ return *parent_rate / div;
+}
+
+static int clk_cpu_set_rate(struct clk_hw *hwclk, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct cpu_clk *cpuclk = to_cpu_clk(hwclk);
+ u32 reg, div;
+ u32 reload_mask;
+
+ div = parent_rate / rate;
+ reg = (readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET)
+ & (~(SYS_CTRL_CLK_DIVIDER_MASK << (cpuclk->cpu * 8))))
+ | (div << (cpuclk->cpu * 8));
+ writel(reg, cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET);
+ /* Set clock divider reload smooth bit mask */
+ reload_mask = 1 << (20 + cpuclk->cpu);
+
+ reg = readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET)
+ | reload_mask;
+ writel(reg, cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET);
+
+ /* Now trigger the clock update */
+ reg = readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET)
+ | 1 << 24;
+ writel(reg, cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET);
+
+ /* Wait for clocks to settle down then clear reload request */
+ udelay(1000);
+ reg &= ~(reload_mask | 1 << 24);
+ writel(reg, cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET);
+ udelay(1000);
+
+ return 0;
+}
+
+static const struct clk_ops cpu_ops = {
+ .recalc_rate = clk_cpu_recalc_rate,
+ .round_rate = clk_cpu_round_rate,
+ .set_rate = clk_cpu_set_rate,
+};
+
+void __init of_cpu_clk_setup(struct device_node *node)
+{
+ struct cpu_clk *cpuclk;
+ void __iomem *clock_complex_base = of_iomap(node, 0);
+ int cpu;
+ if (clock_complex_base == NULL) {
+ pr_err("%s: clock-complex base register not set\n",
+ __func__);
+ return;
+ }
+
+ cpuclk = kzalloc(MAX_CPU * sizeof(*cpuclk), GFP_KERNEL);
+ clks = kzalloc(MAX_CPU * sizeof(*clks), GFP_KERNEL);
+
+ if (WARN_ON(!cpuclk))
+ return;
+ for (cpu = 0; cpu < MAX_CPU; cpu++) {
+ struct clk_init_data init;
+ struct clk *clk;
+ struct clk *parent_clk;
+ char *clk_name = kzalloc(5, GFP_KERNEL);
+
+ sprintf(clk_name, "cpu%d", cpu);
+ parent_clk = of_clk_get(node, 0);
+
+ cpuclk[cpu].parent_name = __clk_get_name(parent_clk);
+ cpuclk[cpu].clk_name = clk_name;
+ cpuclk[cpu].cpu = cpu;
+ cpuclk[cpu].reg_base = clock_complex_base;
+ cpuclk[cpu].hw.init = &init;
+
+ init.name = cpuclk[cpu].clk_name;
+ init.ops = &cpu_ops;
+ init.flags = 0;
+ init.parent_names = &cpuclk[cpu].parent_name;
+ init.num_parents = 1;
+
+ clk = clk_register(NULL, &cpuclk[cpu].hw);
+ if (WARN_ON(IS_ERR(clk)))
+ goto bail_out;
+ clks[cpu] = clk;
+ }
+ clk_data.clk_num = MAX_CPU;
+ clk_data.clks = clks;
+ of_clk_add_provider(node, of_clk_src_onecell_get, &clk_data);
+
+ return;
+bail_out:
+ kfree(clks);
+ kfree(cpuclk);
+}
diff --git a/drivers/clk/mvebu/clk-cpu.h b/drivers/clk/mvebu/clk-cpu.h
new file mode 100644
index 0000000..e208336
--- /dev/null
+++ b/drivers/clk/mvebu/clk-cpu.h
@@ -0,0 +1,18 @@
+/*
+ * Marvell MVEBU CPU clock handling.
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __MVEBU_CLK_CPU_H
+#define __MVEBU_CLK_CPU_H
+
+void __init of_cpu_clk_setup(struct device_node *node);
+
+#endif
diff --git a/drivers/clk/mvebu/clk.c b/drivers/clk/mvebu/clk.c
index e6742ac..dc310d6 100644
--- a/drivers/clk/mvebu/clk.c
+++ b/drivers/clk/mvebu/clk.c
@@ -16,8 +16,22 @@
#include <linux/clk/mvebu.h>
#include <linux/of.h>
#include "clk-core.h"
+#include "clk-cpu.h"
+
+static const __initconst struct of_device_id clk_match[] = {
+#ifdef CONFIG_MVEBU_CLK_CPU
+ {
+ .compatible = "marvell,armada-xp-cpu-clockctrl",
+ .data = of_cpu_clk_setup,
+ },
+#endif
+ {
+ /* sentinel */
+ }
+};
void __init mvebu_clocks_init(void)
{
mvebu_core_clk_init();
+ of_clk_init(clk_match);
}
--
1.7.10.4
^ permalink raw reply related
* [PATCH 1/7] clk: mvebu: add mvebu core clocks.
From: Andrew Lunn @ 2012-11-15 21:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1353014906-31566-1-git-send-email-andrew@lunn.ch>
From: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
This driver allows to provide DT clocks for core clocks found on
Marvell Kirkwood, Dove & 370/XP SoCs. The core clock frequencies and
ratios are determined by decoding the Sample-At-Reset registers.
Although technically correct, using a divider of 0 will lead to
div_by_zero panic. Let's use a ratio of 0/1 instead to fail later
with a zero clock.
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
.../devicetree/bindings/clock/mvebu-core-clock.txt | 47 ++
drivers/clk/Kconfig | 2 +
drivers/clk/Makefile | 1 +
drivers/clk/mvebu/Kconfig | 3 +
drivers/clk/mvebu/Makefile | 1 +
drivers/clk/mvebu/clk-core.c | 675 ++++++++++++++++++++
drivers/clk/mvebu/clk-core.h | 18 +
drivers/clk/mvebu/clk.c | 23 +
include/linux/clk/mvebu.h | 22 +
9 files changed, 792 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/mvebu-core-clock.txt
create mode 100644 drivers/clk/mvebu/Kconfig
create mode 100644 drivers/clk/mvebu/Makefile
create mode 100644 drivers/clk/mvebu/clk-core.c
create mode 100644 drivers/clk/mvebu/clk-core.h
create mode 100644 drivers/clk/mvebu/clk.c
create mode 100644 include/linux/clk/mvebu.h
diff --git a/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt
new file mode 100644
index 0000000..84cfae7
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt
@@ -0,0 +1,47 @@
+* Core Clock bindings for Marvell MVEBU SoCs
+
+Marvell MVEBU SoCs usually allow to determine core clock frequencies by
+reading the Sample-At-Reset (SAR) register. The core clock consumer should
+specify the desired clock by having the clock ID in its "clocks" phandle cell.
+
+The following is a list of provided IDs and clock names on Kirkwood and Dove:
+ 0 = tclk (Internal Bus clock)
+ 1 = cpuclk (CPU0 clock)
+ 2 = l2clk (L2 Cache clock derived from CPU0 clock)
+ 3 = ddrclk (DDR controller clock derived from CPU0 clock)
+
+The following is a list of provided IDs and clock names on 370/XP:
+ 0 = tclk (Internal Bus clock)
+ 1 = cpuclk (CPU clock)
+ 2 = nbclk (L2 Cache clock)
+ 3 = hclk (DRAM control clock)
+ 4 = dramclk (DDR clock)
+
+Required properties:
+- compatible : shall be one of the following:
+ "marvell,dove-core-clocks" - for Dove SoC core clocks
+ "marvell,kirkwood-core-clocks" - for Kirkwood SoC (except mv88f6180)
+ "marvell,mv88f6180-core-clocks" - for Kirkwood MV88f6180 SoC
+ "marvell,370-core-clocks" - For 370 SoC core clocks
+ "marvell,xp-core-clocks" - For XP SoC core clocks
+- reg : shall be the register address of the Sample-At-Reset (SAR) register
+- #clock-cells : from common clock binding; shall be set to 1
+
+Optional properties:
+- clock-output-names : from common clock binding; allows overwrite default clock
+ output names ("tclk", "cpuclk", "l2clk", "ddrclk")
+
+Example:
+
+core_clk: core-clocks at d0214 {
+ compatible = "marvell,dove-core-clocks";
+ reg = <0xd0214 0x4>;
+ #clock-cells = <1>;
+};
+
+spi0: spi at 10600 {
+ compatible = "marvell,orion-spi";
+ /* ... */
+ /* get tclk from core clock provider */
+ clocks = <&core_clk 0>;
+};
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index bace9e9..60427c0 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -54,3 +54,5 @@ config COMMON_CLK_MAX77686
This driver supports Maxim 77686 crystal oscillator clock.
endmenu
+
+source "drivers/clk/mvebu/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 71a25b9..d0a14ae 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_PLAT_SPEAR) += spear/
obj-$(CONFIG_ARCH_U300) += clk-u300.o
obj-$(CONFIG_COMMON_CLK_VERSATILE) += versatile/
obj-$(CONFIG_ARCH_PRIMA2) += clk-prima2.o
+obj-$(CONFIG_PLAT_ORION) += mvebu/
ifeq ($(CONFIG_COMMON_CLK), y)
obj-$(CONFIG_ARCH_MMP) += mmp/
endif
diff --git a/drivers/clk/mvebu/Kconfig b/drivers/clk/mvebu/Kconfig
new file mode 100644
index 0000000..fd7bf97
--- /dev/null
+++ b/drivers/clk/mvebu/Kconfig
@@ -0,0 +1,3 @@
+config MVEBU_CLK_CORE
+ bool
+
diff --git a/drivers/clk/mvebu/Makefile b/drivers/clk/mvebu/Makefile
new file mode 100644
index 0000000..de1d961
--- /dev/null
+++ b/drivers/clk/mvebu/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_MVEBU_CLK_CORE) += clk.o clk-core.o
diff --git a/drivers/clk/mvebu/clk-core.c b/drivers/clk/mvebu/clk-core.c
new file mode 100644
index 0000000..26ba835
--- /dev/null
+++ b/drivers/clk/mvebu/clk-core.c
@@ -0,0 +1,675 @@
+/*
+ * Marvell EBU clock core handling defined at reset
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include "clk-core.h"
+
+struct core_ratio {
+ int id;
+ const char *name;
+};
+
+struct core_clocks {
+ u32 (*get_tclk_freq)(void __iomem *sar);
+ u32 (*get_cpu_freq)(void __iomem *sar);
+ void (*get_clk_ratio)(void __iomem *sar, int id, int *mult, int *div);
+ const struct core_ratio *ratios;
+ int num_ratios;
+};
+
+static struct clk_onecell_data clk_data;
+
+static void __init mvebu_clk_core_setup(struct device_node *np,
+ struct core_clocks *coreclk)
+{
+ const char *tclk_name = "tclk";
+ const char *cpuclk_name = "cpuclk";
+ void __iomem *base;
+ unsigned long rate;
+ int n;
+
+ base = of_iomap(np, 0);
+ if (WARN_ON(!base))
+ return;
+
+ /*
+ * Allocate struct for TCLK, cpu clk, and core ratio clocks
+ */
+ clk_data.clk_num = 2 + coreclk->num_ratios;
+ clk_data.clks = kzalloc(clk_data.clk_num * sizeof(struct clk *),
+ GFP_KERNEL);
+ if (WARN_ON(!clk_data.clks))
+ return;
+
+ /*
+ * Register TCLK
+ */
+ of_property_read_string_index(np, "clock-output-names", 0,
+ &tclk_name);
+ rate = coreclk->get_tclk_freq(base);
+ clk_data.clks[0] = clk_register_fixed_rate(NULL, tclk_name, NULL,
+ CLK_IS_ROOT, rate);
+ WARN_ON(IS_ERR(clk_data.clks[0]));
+
+ /*
+ * Register CPU clock
+ */
+ of_property_read_string_index(np, "clock-output-names", 1,
+ &cpuclk_name);
+ rate = coreclk->get_cpu_freq(base);
+ clk_data.clks[1] = clk_register_fixed_rate(NULL, cpuclk_name, NULL,
+ CLK_IS_ROOT, rate);
+ WARN_ON(IS_ERR(clk_data.clks[1]));
+
+ /*
+ * Register fixed-factor clocks derived from CPU clock
+ */
+ for (n = 0; n < coreclk->num_ratios; n++) {
+ const char *rclk_name = coreclk->ratios[n].name;
+ int mult, div;
+
+ of_property_read_string_index(np, "clock-output-names",
+ 2+n, &rclk_name);
+ coreclk->get_clk_ratio(base, coreclk->ratios[n].id,
+ &mult, &div);
+ clk_data.clks[2+n] = clk_register_fixed_factor(NULL, rclk_name,
+ cpuclk_name, 0, mult, div);
+ WARN_ON(IS_ERR(clk_data.clks[2+n]));
+ };
+
+ /*
+ * SAR register isn't needed anymore
+ */
+ iounmap(base);
+
+ of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+}
+
+#ifdef CONFIG_MACH_ARMADA_370_XP
+/*
+ * 370/XP Sample At Reset is a 64 bit bitfiled split in two register
+ * of 32 bits
+ */
+
+#define SARL 0 /* Low part [0:31] */
+#define SARL_AXP_PCLK_FREQ_OPT 21
+#define SARL_AXP_PCLK_FREQ_OPT_MASK 0x7
+#define SARL_A370_PCLK_FREQ_OPT 11
+#define SARL_A370_PCLK_FREQ_OPT_MASK 0xF
+#define SARL_AXP_FAB_FREQ_OPT 24
+#define SARL_AXP_FAB_FREQ_OPT_MASK 0xF
+#define SARL_A370_FAB_FREQ_OPT 15
+#define SARL_A370_FAB_FREQ_OPT_MASK 0x1F
+#define SARL_A370_TCLK_FREQ_OPT 20
+#define SARL_A370_TCLK_FREQ_OPT_MASK 0x1
+#define SARH 4 /* High part [32:63] */
+#define SARH_AXP_PCLK_FREQ_OPT (52-32)
+#define SARH_AXP_PCLK_FREQ_OPT_MASK 0x1
+#define SARH_AXP_PCLK_FREQ_OPT_SHIFT 3
+#define SARH_AXP_FAB_FREQ_OPT (51-32)
+#define SARH_AXP_FAB_FREQ_OPT_MASK 0x1
+#define SARH_AXP_FAB_FREQ_OPT_SHIFT 4
+
+static const u32 __initconst a370_tclk_frequencies[] = {
+ 16600000,
+ 20000000,
+};
+
+static u32 __init a370_get_tclk_freq(void __iomem *sar)
+{
+ u8 tclk_freq_select = 0;
+
+ tclk_freq_select = ((readl(sar) >> SARL_A370_TCLK_FREQ_OPT) &
+ SARL_A370_TCLK_FREQ_OPT_MASK);
+ return a370_tclk_frequencies[tclk_freq_select];
+}
+
+static const u32 __initconst a370_cpu_frequencies[] = {
+ 400000000,
+ 533000000,
+ 667000000,
+ 800000000,
+ 1000000000,
+ 1067000000,
+ 1200000000,
+};
+
+static u32 __init a370_get_cpu_freq(void __iomem *sar)
+{
+ u32 cpu_freq;
+ u8 cpu_freq_select = 0;
+
+ cpu_freq_select = ((readl(sar) >> SARL_A370_PCLK_FREQ_OPT) &
+ SARL_A370_PCLK_FREQ_OPT_MASK);
+ if (cpu_freq_select > ARRAY_SIZE(a370_cpu_frequencies)) {
+ pr_err("CPU freq select unsuported %d\n", cpu_freq_select);
+ cpu_freq = 0;
+ } else
+ cpu_freq = a370_cpu_frequencies[cpu_freq_select];
+
+ return cpu_freq;
+}
+
+enum { A370_XP_NBCLK, A370_XP_HCLK, A370_XP_DRAMCLK };
+
+static const struct core_ratio __initconst a370_xp_core_ratios[] = {
+ { .id = A370_XP_NBCLK, .name = "nbclk" },
+ { .id = A370_XP_HCLK, .name = "hclk" },
+ { .id = A370_XP_DRAMCLK, .name = "dramclk" },
+};
+
+static const int __initconst a370_xp_nbclk_ratios[32][2] = {
+ {0, 1}, {1, 2}, {2, 2}, {2, 2},
+ {1, 2}, {1, 2}, {1, 1}, {2, 3},
+ {0, 1}, {1, 2}, {2, 4}, {0, 1},
+ {1, 2}, {0, 1}, {0, 1}, {2, 2},
+ {0, 1}, {0, 1}, {0, 1}, {1, 1},
+ {2, 3}, {0, 1}, {0, 1}, {0, 1},
+ {0, 1}, {0, 1}, {0, 1}, {1, 1},
+ {0, 1}, {0, 1}, {0, 1}, {0, 1},
+};
+
+static const int __initconst a370_xp_hclk_ratios[32][2] = {
+ {0, 1}, {1, 2}, {2, 6}, {2, 3},
+ {1, 3}, {1, 4}, {1, 2}, {2, 6},
+ {0, 1}, {1, 6}, {2, 10}, {0, 1},
+ {1, 4}, {0, 1}, {0, 1}, {2, 5},
+ {0, 1}, {0, 1}, {0, 1}, {1, 2},
+ {2, 6}, {0, 1}, {0, 1}, {0, 1},
+ {0, 1}, {0, 1}, {0, 1}, {1, 1},
+ {0, 1}, {0, 1}, {0, 1}, {0, 1},
+};
+
+static const int __initconst a370_xp_dramclk_ratios[32][2] = {
+ {0, 1}, {1, 2}, {2, 3}, {2, 3},
+ {1, 3}, {1, 2}, {1, 2}, {2, 6},
+ {0, 1}, {1, 3}, {2, 5}, {0, 1},
+ {1, 4}, {0, 1}, {0, 1}, {2, 5},
+ {0, 1}, {0, 1}, {0, 1}, {1, 1},
+ {2, 3}, {0, 1}, {0, 1}, {0, 1},
+ {0, 1}, {0, 1}, {0, 1}, {1, 1},
+ {0, 1}, {0, 1}, {0, 1}, {0, 1},
+};
+
+static void __init a370_xp_get_clk_ratio(u32 opt,
+ void __iomem *sar, int id, int *mult, int *div)
+{
+ switch (id) {
+ case A370_XP_NBCLK:
+ *mult = a370_xp_nbclk_ratios[opt][0];
+ *div = a370_xp_nbclk_ratios[opt][1];
+ break;
+ case A370_XP_HCLK:
+ *mult = a370_xp_hclk_ratios[opt][0];
+ *div = a370_xp_hclk_ratios[opt][1];
+ break;
+ case A370_XP_DRAMCLK:
+ *mult = a370_xp_dramclk_ratios[opt][0];
+ *div = a370_xp_dramclk_ratios[opt][1];
+ break;
+ }
+}
+
+static void __init a370_get_clk_ratio(
+ void __iomem *sar, int id, int *mult, int *div)
+{
+ u32 opt = ((readl(sar) >> SARL_A370_FAB_FREQ_OPT) &
+ SARL_A370_FAB_FREQ_OPT_MASK);
+
+ a370_xp_get_clk_ratio(opt, sar, id, mult, div);
+}
+
+
+static const struct core_clocks a370_core_clocks = {
+ .get_tclk_freq = a370_get_tclk_freq,
+ .get_cpu_freq = a370_get_cpu_freq,
+ .get_clk_ratio = a370_get_clk_ratio,
+ .ratios = a370_xp_core_ratios,
+ .num_ratios = ARRAY_SIZE(a370_xp_core_ratios),
+};
+
+static const u32 __initconst xp_cpu_frequencies[] = {
+ 1000000000,
+ 1066000000,
+ 1200000000,
+ 1333000000,
+ 1500000000,
+ 1666000000,
+ 1800000000,
+ 2000000000,
+ 667000000,
+ 0,
+ 800000000,
+ 1600000000,
+};
+
+/* For Armada XP TCLK frequency is fix: 250MHz */
+static u32 __init xp_get_tclk_freq(void __iomem *sar)
+{
+ return 250 * 1000 * 1000;
+}
+
+static u32 __init xp_get_cpu_freq(void __iomem *sar)
+{
+ u32 cpu_freq;
+ u8 cpu_freq_select = 0;
+
+ cpu_freq_select = ((readl(sar) >> SARL_AXP_PCLK_FREQ_OPT) &
+ SARL_AXP_PCLK_FREQ_OPT_MASK);
+ /*
+ * The upper bit is not contiguous to the other ones and
+ * located in the high part of the SAR registers
+ */
+ cpu_freq_select |= (((readl(sar+4) >> SARH_AXP_PCLK_FREQ_OPT) &
+ SARH_AXP_PCLK_FREQ_OPT_MASK)
+ << SARH_AXP_PCLK_FREQ_OPT_SHIFT);
+ if (cpu_freq_select > ARRAY_SIZE(xp_cpu_frequencies)) {
+ pr_err("CPU freq select unsuported: %d\n", cpu_freq_select);
+ cpu_freq = 0;
+ } else
+ cpu_freq = xp_cpu_frequencies[cpu_freq_select];
+
+ return cpu_freq;
+}
+
+static void __init xp_get_clk_ratio(
+ void __iomem *sar, int id, int *mult, int *div)
+{
+
+ u32 opt = ((readl(sar) >> SARL_AXP_FAB_FREQ_OPT) &
+ SARL_AXP_FAB_FREQ_OPT_MASK);
+ /*
+ * The upper bit is not contiguous to the other ones and
+ * located in the high part of the SAR registers
+ */
+ opt |= (((readl(sar+4) >> SARH_AXP_FAB_FREQ_OPT) &
+ SARH_AXP_FAB_FREQ_OPT_MASK)
+ << SARH_AXP_FAB_FREQ_OPT_SHIFT);
+
+ a370_xp_get_clk_ratio(opt, sar, id, mult, div);
+}
+
+static const struct core_clocks xp_core_clocks = {
+ .get_tclk_freq = xp_get_tclk_freq,
+ .get_cpu_freq = xp_get_cpu_freq,
+ .get_clk_ratio = xp_get_clk_ratio,
+ .ratios = a370_xp_core_ratios,
+ .num_ratios = ARRAY_SIZE(a370_xp_core_ratios),
+};
+
+#endif /* CONFIG_MACH_ARMADA_370_XP */
+
+/*
+ * Dove PLL sample-at-reset configuration
+ *
+ * SAR0[8:5] : CPU frequency
+ * 5 = 1000 MHz
+ * 6 = 933 MHz
+ * 7 = 933 MHz
+ * 8 = 800 MHz
+ * 9 = 800 MHz
+ * 10 = 800 MHz
+ * 11 = 1067 MHz
+ * 12 = 667 MHz
+ * 13 = 533 MHz
+ * 14 = 400 MHz
+ * 15 = 333 MHz
+ * others reserved.
+ *
+ * SAR0[11:9] : CPU to L2 Clock divider ratio
+ * 0 = (1/1) * CPU
+ * 2 = (1/2) * CPU
+ * 4 = (1/3) * CPU
+ * 6 = (1/4) * CPU
+ * others reserved.
+ *
+ * SAR0[15:12] : CPU to DDR DRAM Clock divider ratio
+ * 0 = (1/1) * CPU
+ * 2 = (1/2) * CPU
+ * 3 = (2/5) * CPU
+ * 4 = (1/3) * CPU
+ * 6 = (1/4) * CPU
+ * 8 = (1/5) * CPU
+ * 10 = (1/6) * CPU
+ * 12 = (1/7) * CPU
+ * 14 = (1/8) * CPU
+ * 15 = (1/10) * CPU
+ * others reserved.
+ *
+ * SAR0[24:23] : TCLK frequency
+ * 0 = 166 MHz
+ * 1 = 125 MHz
+ * others reserved.
+ */
+#ifdef CONFIG_ARCH_DOVE
+#define SAR_DOVE_CPU_FREQ 5
+#define SAR_DOVE_CPU_FREQ_MASK 0xf
+#define SAR_DOVE_L2_RATIO 9
+#define SAR_DOVE_L2_RATIO_MASK 0x7
+#define SAR_DOVE_DDR_RATIO 12
+#define SAR_DOVE_DDR_RATIO_MASK 0xf
+#define SAR_DOVE_TCLK_FREQ 23
+#define SAR_DOVE_TCLK_FREQ_MASK 0x3
+
+static const u32 __initconst dove_tclk_frequencies[] = {
+ 166666667,
+ 125000000,
+ 0, 0
+};
+
+static u32 __init dove_get_tclk_freq(void __iomem *sar)
+{
+ u32 opt = (readl(sar) >> SAR_DOVE_TCLK_FREQ) &
+ SAR_DOVE_TCLK_FREQ_MASK;
+ return dove_tclk_frequencies[opt];
+}
+
+static const u32 __initconst dove_cpu_frequencies[] = {
+ 0, 0, 0, 0, 0,
+ 1000000000,
+ 933333333, 933333333,
+ 800000000, 800000000, 800000000,
+ 1066666667,
+ 666666667,
+ 533333333,
+ 400000000,
+ 333333333
+};
+
+static u32 __init dove_get_cpu_freq(void __iomem *sar)
+{
+ u32 opt = (readl(sar) >> SAR_DOVE_CPU_FREQ) &
+ SAR_DOVE_CPU_FREQ_MASK;
+ return dove_cpu_frequencies[opt];
+}
+
+enum { DOVE_CPU_TO_L2, DOVE_CPU_TO_DDR };
+
+static const struct core_ratio __initconst dove_core_ratios[] = {
+ { .id = DOVE_CPU_TO_L2, .name = "l2clk", },
+ { .id = DOVE_CPU_TO_DDR, .name = "ddrclk", }
+};
+
+static const int __initconst dove_cpu_l2_ratios[8][2] = {
+ { 1, 1 }, { 0, 1 }, { 1, 2 }, { 0, 1 },
+ { 1, 3 }, { 0, 1 }, { 1, 4 }, { 0, 1 }
+};
+
+static const int __initconst dove_cpu_ddr_ratios[16][2] = {
+ { 1, 1 }, { 0, 1 }, { 1, 2 }, { 2, 5 },
+ { 1, 3 }, { 0, 1 }, { 1, 4 }, { 0, 1 },
+ { 1, 5 }, { 0, 1 }, { 1, 6 }, { 0, 1 },
+ { 1, 7 }, { 0, 1 }, { 1, 8 }, { 1, 10 }
+};
+
+static void __init dove_get_clk_ratio(
+ void __iomem *sar, int id, int *mult, int *div)
+{
+ switch (id) {
+ case DOVE_CPU_TO_L2:
+ {
+ u32 opt = (readl(sar) >> SAR_DOVE_L2_RATIO) &
+ SAR_DOVE_L2_RATIO_MASK;
+ *mult = dove_cpu_l2_ratios[opt][0];
+ *div = dove_cpu_l2_ratios[opt][1];
+ break;
+ }
+ case DOVE_CPU_TO_DDR:
+ {
+ u32 opt = (readl(sar) >> SAR_DOVE_DDR_RATIO) &
+ SAR_DOVE_DDR_RATIO_MASK;
+ *mult = dove_cpu_ddr_ratios[opt][0];
+ *div = dove_cpu_ddr_ratios[opt][1];
+ break;
+ }
+ }
+}
+
+static const struct core_clocks dove_core_clocks = {
+ .get_tclk_freq = dove_get_tclk_freq,
+ .get_cpu_freq = dove_get_cpu_freq,
+ .get_clk_ratio = dove_get_clk_ratio,
+ .ratios = dove_core_ratios,
+ .num_ratios = ARRAY_SIZE(dove_core_ratios),
+};
+#endif /* CONFIG_ARCH_DOVE */
+
+/*
+ * Kirkwood PLL sample-at-reset configuration
+ * (6180 has different SAR layout than other Kirkwood SoCs)
+ *
+ * SAR0[4:3,22,1] : CPU frequency (6281,6292,6282)
+ * 4 = 600 MHz
+ * 6 = 800 MHz
+ * 7 = 1000 MHz
+ * 9 = 1200 MHz
+ * 12 = 1500 MHz
+ * 13 = 1600 MHz
+ * 14 = 1800 MHz
+ * 15 = 2000 MHz
+ * others reserved.
+ *
+ * SAR0[19,10:9] : CPU to L2 Clock divider ratio (6281,6292,6282)
+ * 1 = (1/2) * CPU
+ * 3 = (1/3) * CPU
+ * 5 = (1/4) * CPU
+ * others reserved.
+ *
+ * SAR0[8:5] : CPU to DDR DRAM Clock divider ratio (6281,6292,6282)
+ * 2 = (1/2) * CPU
+ * 4 = (1/3) * CPU
+ * 6 = (1/4) * CPU
+ * 7 = (2/9) * CPU
+ * 8 = (1/5) * CPU
+ * 9 = (1/6) * CPU
+ * others reserved.
+ *
+ * SAR0[4:2] : Kirkwood 6180 cpu/l2/ddr clock configuration (6180 only)
+ * 5 = [CPU = 600 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/3) * CPU]
+ * 6 = [CPU = 800 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/4) * CPU]
+ * 7 = [CPU = 1000 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/5) * CPU]
+ * others reserved.
+ *
+ * SAR0[21] : TCLK frequency
+ * 0 = 200 MHz
+ * 1 = 166 MHz
+ * others reserved.
+ */
+#ifdef CONFIG_ARCH_KIRKWOOD
+#define SAR_KIRKWOOD_CPU_FREQ(x) \
+ (((x & (1 << 1)) >> 1) | \
+ ((x & (1 << 22)) >> 21) | \
+ ((x & (3 << 3)) >> 1))
+#define SAR_KIRKWOOD_L2_RATIO(x) \
+ (((x & (3 << 9)) >> 9) | \
+ (((x & (1 << 19)) >> 17)))
+#define SAR_KIRKWOOD_DDR_RATIO 5
+#define SAR_KIRKWOOD_DDR_RATIO_MASK 0xf
+#define SAR_MV88F6180_CLK 2
+#define SAR_MV88F6180_CLK_MASK 0x7
+#define SAR_KIRKWOOD_TCLK_FREQ 21
+#define SAR_KIRKWOOD_TCLK_FREQ_MASK 0x1
+
+enum { KIRKWOOD_CPU_TO_L2, KIRKWOOD_CPU_TO_DDR };
+
+static const struct core_ratio __initconst kirkwood_core_ratios[] = {
+ { .id = KIRKWOOD_CPU_TO_L2, .name = "l2clk", },
+ { .id = KIRKWOOD_CPU_TO_DDR, .name = "ddrclk", }
+};
+
+static u32 __init kirkwood_get_tclk_freq(void __iomem *sar)
+{
+ u32 opt = (readl(sar) >> SAR_KIRKWOOD_TCLK_FREQ) &
+ SAR_KIRKWOOD_TCLK_FREQ_MASK;
+ return (opt) ? 166666667 : 200000000;
+}
+
+static const u32 __initconst kirkwood_cpu_frequencies[] = {
+ 0, 0, 0, 0,
+ 600000000,
+ 0,
+ 800000000,
+ 1000000000,
+ 0,
+ 1200000000,
+ 0, 0,
+ 1500000000,
+ 1600000000,
+ 1800000000,
+ 2000000000
+};
+
+static u32 __init kirkwood_get_cpu_freq(void __iomem *sar)
+{
+ u32 opt = SAR_KIRKWOOD_CPU_FREQ(readl(sar));
+ return kirkwood_cpu_frequencies[opt];
+}
+
+static const int __initconst kirkwood_cpu_l2_ratios[8][2] = {
+ { 0, 1 }, { 1, 2 }, { 0, 1 }, { 1, 3 },
+ { 0, 1 }, { 1, 4 }, { 0, 1 }, { 0, 1 }
+};
+
+static const int __initconst kirkwood_cpu_ddr_ratios[16][2] = {
+ { 0, 1 }, { 0, 1 }, { 1, 2 }, { 0, 1 },
+ { 1, 3 }, { 0, 1 }, { 1, 4 }, { 2, 9 },
+ { 1, 5 }, { 1, 6 }, { 0, 1 }, { 0, 1 },
+ { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }
+};
+
+static void __init kirkwood_get_clk_ratio(
+ void __iomem *sar, int id, int *mult, int *div)
+{
+ switch (id) {
+ case KIRKWOOD_CPU_TO_L2:
+ {
+ u32 opt = SAR_KIRKWOOD_L2_RATIO(readl(sar));
+ *mult = kirkwood_cpu_l2_ratios[opt][0];
+ *div = kirkwood_cpu_l2_ratios[opt][1];
+ break;
+ }
+ case KIRKWOOD_CPU_TO_DDR:
+ {
+ u32 opt = (readl(sar) >> SAR_KIRKWOOD_DDR_RATIO) &
+ SAR_KIRKWOOD_DDR_RATIO_MASK;
+ *mult = kirkwood_cpu_ddr_ratios[opt][0];
+ *div = kirkwood_cpu_ddr_ratios[opt][1];
+ break;
+ }
+ }
+}
+
+static const struct core_clocks kirkwood_core_clocks = {
+ .get_tclk_freq = kirkwood_get_tclk_freq,
+ .get_cpu_freq = kirkwood_get_cpu_freq,
+ .get_clk_ratio = kirkwood_get_clk_ratio,
+ .ratios = kirkwood_core_ratios,
+ .num_ratios = ARRAY_SIZE(kirkwood_core_ratios),
+};
+
+static const u32 __initconst mv88f6180_cpu_frequencies[] = {
+ 0, 0, 0, 0, 0,
+ 600000000,
+ 800000000,
+ 1000000000
+};
+
+static u32 __init mv88f6180_get_cpu_freq(void __iomem *sar)
+{
+ u32 opt = (readl(sar) >> SAR_MV88F6180_CLK) & SAR_MV88F6180_CLK_MASK;
+ return mv88f6180_cpu_frequencies[opt];
+}
+
+static const int __initconst mv88f6180_cpu_ddr_ratios[8][2] = {
+ { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 },
+ { 0, 1 }, { 1, 3 }, { 1, 4 }, { 1, 5 }
+};
+
+static void __init mv88f6180_get_clk_ratio(
+ void __iomem *sar, int id, int *mult, int *div)
+{
+ switch (id) {
+ case KIRKWOOD_CPU_TO_L2:
+ {
+ /* mv88f6180 has a fixed 1:2 CPU-to-L2 ratio */
+ *mult = 1;
+ *div = 2;
+ break;
+ }
+ case KIRKWOOD_CPU_TO_DDR:
+ {
+ u32 opt = (readl(sar) >> SAR_MV88F6180_CLK) &
+ SAR_MV88F6180_CLK_MASK;
+ *mult = mv88f6180_cpu_ddr_ratios[opt][0];
+ *div = mv88f6180_cpu_ddr_ratios[opt][1];
+ break;
+ }
+ }
+}
+
+static const struct core_clocks mv88f6180_core_clocks = {
+ .get_tclk_freq = kirkwood_get_tclk_freq,
+ .get_cpu_freq = mv88f6180_get_cpu_freq,
+ .get_clk_ratio = mv88f6180_get_clk_ratio,
+ .ratios = kirkwood_core_ratios,
+ .num_ratios = ARRAY_SIZE(kirkwood_core_ratios),
+};
+#endif /* CONFIG_ARCH_KIRKWOOD */
+
+static const __initdata struct of_device_id clk_core_match[] = {
+#ifdef CONFIG_MACH_ARMADA_370_XP
+ {
+ .compatible = "marvell,370-core-clocks",
+ .data = &a370_core_clocks,
+ },
+ {
+ .compatible = "marvell,xp-core-clocks",
+ .data = &xp_core_clocks,
+ },
+#endif
+#ifdef CONFIG_ARCH_DOVE
+ {
+ .compatible = "marvell,dove-core-clocks",
+ .data = &dove_core_clocks,
+ },
+#endif
+
+#ifdef CONFIG_ARCH_KIRKWOOD
+ {
+ .compatible = "marvell,kirkwood-core-clocks",
+ .data = &kirkwood_core_clocks,
+ },
+ {
+ .compatible = "marvell,mv88f6180-core-clocks",
+ .data = &mv88f6180_core_clocks,
+ },
+#endif
+
+ { }
+};
+
+void __init mvebu_core_clk_init(void)
+{
+ struct device_node *np;
+
+ for_each_matching_node(np, clk_core_match) {
+ const struct of_device_id *match =
+ of_match_node(clk_core_match, np);
+ mvebu_clk_core_setup(np, (struct core_clocks *)match->data);
+ }
+}
diff --git a/drivers/clk/mvebu/clk-core.h b/drivers/clk/mvebu/clk-core.h
new file mode 100644
index 0000000..28b5e02
--- /dev/null
+++ b/drivers/clk/mvebu/clk-core.h
@@ -0,0 +1,18 @@
+/*
+ * * Marvell EBU clock core handling defined at reset
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __MVEBU_CLK_CORE_H
+#define __MVEBU_CLK_CORE_H
+
+void __init mvebu_core_clk_init(void);
+
+#endif
diff --git a/drivers/clk/mvebu/clk.c b/drivers/clk/mvebu/clk.c
new file mode 100644
index 0000000..e6742ac
--- /dev/null
+++ b/drivers/clk/mvebu/clk.c
@@ -0,0 +1,23 @@
+/*
+ * Marvell EBU SoC clock handling.
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/clk/mvebu.h>
+#include <linux/of.h>
+#include "clk-core.h"
+
+void __init mvebu_clocks_init(void)
+{
+ mvebu_core_clk_init();
+}
diff --git a/include/linux/clk/mvebu.h b/include/linux/clk/mvebu.h
new file mode 100644
index 0000000..8c4ae71
--- /dev/null
+++ b/include/linux/clk/mvebu.h
@@ -0,0 +1,22 @@
+/*
+ * This program 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __CLK_MVEBU_H_
+#define __CLK_MVEBU_H_
+
+void __init mvebu_clocks_init(void);
+
+#endif
--
1.7.10.4
^ permalink raw reply related
* [PATCH 0/7] core, cpu and gated clocks for mvebu
From: Andrew Lunn @ 2012-11-15 21:28 UTC (permalink / raw)
To: linux-arm-kernel
This patchset combines code from Gregory Clement, Sebastian
Hesselbarth and myself to implement core clks, cpu clock and gated
clocks on Marvel MVEBU SoCs.
The Armada 370/XP core clock code is a refactored version of the
already submitted and ACKed code from Gregory. It has been made to fit
inside a framework developed by Sebastian which can handle all MVEBU
SoCs. The Armarda 370/XP SoCs have more core clocks than the older SoCs, and
the framework needs to handle this. Rather than specify the clock
frequencies in DT, a Sample At Reset register is used, which describes
each core clock frequency.
Armarda XP is an SMP processor, with each CPU having its own
clock. Gregories code for this has been taken as is.
The Armarda 370/XP clock source has been converted to the common clock
framework.
Dove, Kirkword, and probably Armarda 370/XP have the ability to gate
clocks to various blocks. A clk-gate clock is created for each of the
gateable clocks on Dove and Kirkwood. Armarda 370/XP clock gates are
currently unimplemented. Dove and Kirkwood board-dt.c and DT
descriptions are then modified to make use of these clk gates.
This code has been tested on:
Kirkwood based QNAP TS219
Armarda 370 based mirabox
Armara XP based OpenBlocks
and by Sebastian on:
Dove based Cubox.
Andrew Lunn (1):
ARM: Kirkwood: switch to DT clock providers
Gregory CLEMENT (3):
clk: mvebu: add armada-370-xp CPU specific clocks
clk: armada-370-xp: add support for clock framework
clocksource: time-armada-370-xp converted to clk framework
Sebastian Hesselbarth (3):
clk: mvebu: add mvebu core clocks.
clk: mvebu: add clock gating control provider for DT
ARM: dove: switch to DT clock providers
.../devicetree/bindings/clock/mvebu-core-clock.txt | 47 ++
.../devicetree/bindings/clock/mvebu-cpu-clock.txt | 21 +
.../bindings/clock/mvebu-gated-clock.txt | 76 +++
arch/arm/Kconfig | 1 +
arch/arm/boot/dts/armada-370-db.dts | 4 -
arch/arm/boot/dts/armada-370-xp.dtsi | 1 +
arch/arm/boot/dts/armada-370.dtsi | 7 +
arch/arm/boot/dts/armada-xp.dtsi | 42 ++
arch/arm/boot/dts/dove.dtsi | 20 +
arch/arm/boot/dts/kirkwood.dtsi | 22 +
arch/arm/mach-dove/Kconfig | 2 +
arch/arm/mach-dove/common.c | 64 +-
arch/arm/mach-kirkwood/Kconfig | 2 +
arch/arm/mach-kirkwood/board-dt.c | 72 ++-
arch/arm/mach-mvebu/Kconfig | 6 +
arch/arm/mach-mvebu/armada-370-xp.c | 9 +-
arch/arm/plat-orion/include/plat/common.h | 1 +
drivers/clk/Kconfig | 2 +
drivers/clk/Makefile | 1 +
drivers/clk/mvebu/Kconfig | 8 +
drivers/clk/mvebu/Makefile | 3 +
drivers/clk/mvebu/clk-core.c | 675 ++++++++++++++++++++
drivers/clk/mvebu/clk-core.h | 18 +
drivers/clk/mvebu/clk-cpu.c | 155 +++++
drivers/clk/mvebu/clk-cpu.h | 18 +
drivers/clk/mvebu/clk-gating-ctrl.c | 177 +++++
drivers/clk/mvebu/clk.c | 37 ++
drivers/clocksource/time-armada-370-xp.c | 11 +-
include/linux/clk/mvebu.h | 23 +
29 files changed, 1487 insertions(+), 38 deletions(-)
create mode 100644 Documentation/devicetree/bindings/clock/mvebu-core-clock.txt
create mode 100644 Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt
create mode 100644 Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
create mode 100644 drivers/clk/mvebu/Kconfig
create mode 100644 drivers/clk/mvebu/Makefile
create mode 100644 drivers/clk/mvebu/clk-core.c
create mode 100644 drivers/clk/mvebu/clk-core.h
create mode 100644 drivers/clk/mvebu/clk-cpu.c
create mode 100644 drivers/clk/mvebu/clk-cpu.h
create mode 100644 drivers/clk/mvebu/clk-gating-ctrl.c
create mode 100644 drivers/clk/mvebu/clk.c
create mode 100644 include/linux/clk/mvebu.h
--
1.7.10.4
^ permalink raw reply
* [RFC PATCH 3.7.0-rc4] ARM:smp: introduce smp_notify_cpu_stop to fix kexec smp case
From: Will Deacon @ 2012-11-15 21:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1353003478-22291-1-git-send-email-srinivas.kandagatla@st.com>
Hello,
On Thu, Nov 15, 2012 at 06:17:58PM +0000, Srinivas KANDAGATLA wrote:
> From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
>
> Use-case is simple kexec on smp system.
>
> Lets say there are two cores core-0 and core-1.
>
> sequence here is:
> As part of kexec call, the secondary cores are stopped by calling
> machine_shutdown(), which in turn issues IPIs to off-line the other CPUs
> and then call smp_ops.cpu_kill.
>
> machine_shutdown invokes smp_send_stop from core-0 which then sends
> IPI_CPU_STOP ipi message for core-1 and then smp_kill_cpus call
> smp_ops.cpu_kill from core-0 with cpu=1.
>
> The expectation here is that cpu_kill will relocate secondary-core
> to safe location from primary-core(core-0).
Not quite. The expectation is actually that you wiggle a line to a power
controller and the secondary core either disappears or resets.
> This is a catch 22 situation for SOCs, which can't change PC's of other
> cores. At the point when cpu_kill is invoked, it cant execute any
> function calls for core-1, as it is off-line and is spinning in
> cpu_relax.
I thought these SoCs were fairly rare in production -- usually there is
some way to power down secondary cores.
> So the only way is to put the core into safe place by executing some
> SOC specific relocation code.
>
> Having a callback from ipi handler when cpu is stopped would be very
> usefull for SOC's which want to relocate the secondary-core to safe
> location.
I thought about this for Versatile Express but even if you do that, your
problems are just beginning. The bigger issue is co-ordinating with the
secondaries so you know when they're safely out of the way and you can
proceed with the kexec. Remember that you won't have working locks and you
can't cross-call a function because it won't actually return.
If you can solve the synchronisation problem then we can think about adding
these hooks.
Will
^ permalink raw reply
* [PATCH v5 0/4] arch/arm: support seccomp
From: Will Deacon @ 2012-11-15 21:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAGXu5jL6og3xq_V=FkemV828Tso5F4wSoLy_24HA_LFw_x20Zw@mail.gmail.com>
On Thu, Nov 15, 2012 at 08:23:48PM +0000, Kees Cook wrote:
> On Thu, Nov 15, 2012 at 5:25 AM, Will Deacon <will.deacon@arm.com> wrote:
> > On Wed, Nov 14, 2012 at 07:07:13PM +0000, Kees Cook wrote:
> >> Hi, any more thoughts on this series? I'd really like to get it into
> >> -next. It's been running happily for a while now in the Chrome OS ARM
> >> devices.
> >
> > I'm not familiar with seccomp in general, but the changes look ok now from
> > an ARM point-of-view:
> >
> > Reviewed-by: Will Deacon <will.deacon@arm.com>
> >
> > These should probably go via Russell (who will put them into -next), so
> > please send them to the patch system.
>
> Thanks. Is there a sensible way to send an ordered patch series to the
> patch system? The Help doc says:
> Please omit [PATCH] and other "useful" prefixes.
> (and it wants the "KernelVersion: " in there too)
>
> Is there some way to indicate 1/4, 2/4, etc?
If you're using git send-email, you don't need to do anything other than
add a new tag below your S-o-B to indicate the kernel version, e.g:
KernelVersion: 3.7-rc5
then send the patches (1 by 1 so they don't get re-ordered) to
patches at arm.linux.org.uk
You should receive a response indicating whether they were correctly
formatted or not.
Will
^ permalink raw reply
* [PATCH] ARM: OMAP2+: Fix compiler warning for 32k timer
From: Felipe Balbi @ 2012-11-15 20:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1353008644-24745-1-git-send-email-jon-hunter@ti.com>
Hi,
On Thu, Nov 15, 2012 at 01:44:04PM -0600, Jon Hunter wrote:
> +static struct of_device_id omap_counter_match[] __initdata = {
not directly related to $SUBJECT, but shouldn't this be static const
__initconst ?
--
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121115/ee3b61c2/attachment.sig>
^ permalink raw reply
* [PATCH 7/8] ARM: OMAP: Remove unnecessary inclusion of dmtimer.h
From: Omar Ramirez Luna @ 2012-11-15 20:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50A3BE85.5000804@ti.com>
Hi Jon,
On 14 November 2012 09:53, Jon Hunter <jon-hunter@ti.com> wrote:
>> diff --git a/drivers/staging/tidspbridge/core/ue_deh.c b/drivers/staging/tidspbridge/core/ue_deh.c
>> index 3d28b23..6aea6f1 100644
>> --- a/drivers/staging/tidspbridge/core/ue_deh.c
>> +++ b/drivers/staging/tidspbridge/core/ue_deh.c
>> @@ -19,7 +19,6 @@
>>
>> #include <linux/kernel.h>
>> #include <linux/interrupt.h>
>> -#include <plat/dmtimer.h>
>>
>> #include <dspbridge/dbdefs.h>
>> #include <dspbridge/dspdeh.h>
>
> Hi Omar, I should have had you in copy on this one. Are you ok with the
> removal of the above dmtimer.h include? It does not appear that this
> file needs to include dmtimer.h.
Indeed, we don't use it here.
> Is it ok for this to go through Tony's tree? If so, care to ACK?
Looks fine to me, but I believe you will want to let Greg know if this
patch will bypass staging tree.
Acked-by: Omar Ramirez Luna <omar.luna@linaro.org>
Cheers,
Omar
^ permalink raw reply
* [PATCH v5 0/4] arch/arm: support seccomp
From: Will Drewry @ 2012-11-15 20:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121115132550.GA5570@mudshark.cambridge.arm.com>
On Thu, Nov 15, 2012 at 7:25 AM, Will Deacon <will.deacon@arm.com> wrote:
> On Wed, Nov 14, 2012 at 07:07:13PM +0000, Kees Cook wrote:
>> Hi, any more thoughts on this series? I'd really like to get it into
>> -next. It's been running happily for a while now in the Chrome OS ARM
>> devices.
>
> I'm not familiar with seccomp in general, but the changes look ok now from
> an ARM point-of-view:
>
> Reviewed-by: Will Deacon <will.deacon@arm.com>
>
> These should probably go via Russell (who will put them into -next), so
> please send them to the patch system.
>
For the seccomp side,
Acked-by: Will Drewry <wad@chromium.org>
for the whole series. Thanks!
^ permalink raw reply
* [PATCH v5 0/4] arch/arm: support seccomp
From: Kees Cook @ 2012-11-15 20:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121115132550.GA5570@mudshark.cambridge.arm.com>
On Thu, Nov 15, 2012 at 5:25 AM, Will Deacon <will.deacon@arm.com> wrote:
> On Wed, Nov 14, 2012 at 07:07:13PM +0000, Kees Cook wrote:
>> Hi, any more thoughts on this series? I'd really like to get it into
>> -next. It's been running happily for a while now in the Chrome OS ARM
>> devices.
>
> I'm not familiar with seccomp in general, but the changes look ok now from
> an ARM point-of-view:
>
> Reviewed-by: Will Deacon <will.deacon@arm.com>
>
> These should probably go via Russell (who will put them into -next), so
> please send them to the patch system.
Thanks. Is there a sensible way to send an ordered patch series to the
patch system? The Help doc says:
Please omit [PATCH] and other "useful" prefixes.
(and it wants the "KernelVersion: " in there too)
Is there some way to indicate 1/4, 2/4, etc?
-Kees
--
Kees Cook
Chrome OS Security
^ permalink raw reply
* common clk fixes for 3.7-rc6, part 2
From: Mike Turquette @ 2012-11-15 20:07 UTC (permalink / raw)
To: linux-arm-kernel
The following changes since commit 77b67063bb6bce6d475e910d3b886a606d0d91f7:
Linux 3.7-rc5 (2012-11-11 13:44:33 +0100)
are available in the git repository at:
git://git.linaro.org/people/mturquette/linux.git tags/clk-fixes-for-linus
for you to fetch changes up to 93532c8a4890871aa0d84dd91b80dad9f58542e0:
clk: remove inline usage from clk-provider.h (2012-11-15 11:38:34 -0800)
----------------------------------------------------------------
GCC 4.7 users get compilation errors from unnecessary use of inline in
clk-provider.h. This pull request fixes the regression by removing inline
usage from those function declarations.
----------------------------------------------------------------
Igor Mazanov (1):
clk: remove inline usage from clk-provider.h
include/linux/clk-provider.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
^ permalink raw reply
* [PATCH] ARM: OMAP2+: Fix compiler warning for 32k timer
From: Jon Hunter @ 2012-11-15 19:44 UTC (permalink / raw)
To: linux-arm-kernel
Commit "ARM: OMAP2+: Add device-tree support for 32kHz counter"
added structure omap_counter_match to the OMAP2 timer code. When
CONFIG_OMAP_32K_TIMER is not defined this structure generates the
following as it is not used.
CC arch/arm/mach-omap2/timer.o
arch/arm/mach-omap2/timer.c:163:28: warning: 'omap_counter_match'
defined but not used [-Wunused-variable]
Move the definition of omap_counter_match to avoid this warning when
CONFIG_OMAP_32K_TIMER is not set.
Thanks to Kevin Hilman for tracking down and reporting this problem.
Reported-by: Kevin Hilam <khilman@deeprootsystems.com>
Signed-off-by: Jon Hunter <jon-hunter@ti.com>
---
This is based upon Tony Lindgren's OMAP master branch.
arch/arm/mach-omap2/timer.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 099e406..2b9d485 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -160,11 +160,6 @@ static struct of_device_id omap_timer_match[] __initdata = {
{ }
};
-static struct of_device_id omap_counter_match[] __initdata = {
- { .compatible = "ti,omap-counter32k", },
- { }
-};
-
/**
* omap_get_timer_dt - get a timer using device-tree
* @match - device-tree match structure for matching a device type
@@ -408,6 +403,11 @@ static u32 notrace dmtimer_read_sched_clock(void)
}
#ifdef CONFIG_OMAP_32K_TIMER
+static struct of_device_id omap_counter_match[] __initdata = {
+ { .compatible = "ti,omap-counter32k", },
+ { }
+};
+
/* Setup free-running counter for clocksource */
static int __init omap2_sync32k_clocksource_init(void)
{
--
1.7.9.5
^ permalink raw reply related
* [PATCH 1/1 v2] of_spi: add generic binding support to specify cs gpio
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-11-15 19:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121115165048.543FE3E194B@localhost>
This will allow to use gpio for chip select with no modification in the
driver binding
When use the cs-gpios, the gpio number will be passed via the cs_gpio field
and the number of chip select will automatically increased with max(hw cs, gpio cs).
So if for example the controller has 2 CS lines, and the cs-gpios
property looks like this:
cs-gpios = <&gpio1 0 0> <0> <&gpio1 1 0> <&gpio1 2 0>;
Then it should be configured so that num_chipselect = 4 with the
following mapping:
cs0 : &gpio1 0 0
cs1 : native
cs2 : &gpio1 1 0
cs3 : &gpio1 2 0
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Cc: devicetree-discuss at lists.ozlabs.org
Cc: spi-devel-general at lists.sourceforge.net
Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
---
v2:
update to allow to overwrite hw gpio via cs-gpio
as sugested by Grant
Best Regards,
J.
Documentation/devicetree/bindings/spi/spi-bus.txt | 20 ++++++++
drivers/spi/spi.c | 54 +++++++++++++++++++--
include/linux/spi/spi.h | 3 ++
3 files changed, 74 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/spi/spi-bus.txt b/Documentation/devicetree/bindings/spi/spi-bus.txt
index d2c33d0..77a8b0d 100644
--- a/Documentation/devicetree/bindings/spi/spi-bus.txt
+++ b/Documentation/devicetree/bindings/spi/spi-bus.txt
@@ -12,6 +12,7 @@ The SPI master node requires the following properties:
- #size-cells - should be zero.
- compatible - name of SPI bus controller following generic names
recommended practice.
+- cs-gpios - (optional) gpios chip select.
No other properties are required in the SPI bus node. It is assumed
that a driver for an SPI bus device will understand that it is an SPI bus.
However, the binding does not attempt to define the specific method for
@@ -24,6 +25,22 @@ support describing the chip select layout.
Optional property:
- num-cs : total number of chipselects
+If cs-gpios is used the number of chip select will automatically increased
+with max(cs-gpios > hw cs)
+
+So if for example the controller has 2 CS lines, and the cs-gpios
+property looks like this:
+
+cs-gpios = <&gpio1 0 0> <0> <&gpio1 1 0> <&gpio1 2 0>;
+
+Then it should be configured so that num_chipselect = 4 with the
+following mapping:
+
+cs0 : &gpio1 0 0
+cs1 : native
+cs2 : &gpio1 1 0
+cs3 : &gpio1 2 0
+
SPI slave nodes must be children of the SPI master node and can
contain the following properties.
- reg - (required) chip select address of device.
@@ -37,6 +54,9 @@ contain the following properties.
- spi-cs-high - (optional) Empty property indicating device requires
chip select active high
+If a gpio chipselect is used for the SPI slave the gpio number will be passed
+via the cs_gpio
+
SPI example for an MPC5200 SPI bus:
spi at f00 {
#address-cells = <1>;
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index fc0da39..efb635f 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -30,6 +30,7 @@
#include <linux/slab.h>
#include <linux/mod_devicetable.h>
#include <linux/spi/spi.h>
+#include <linux/of_gpio.h>
#include <linux/pm_runtime.h>
#include <linux/export.h>
#include <linux/sched.h>
@@ -327,6 +328,7 @@ struct spi_device *spi_alloc_device(struct spi_master *master)
spi->dev.parent = &master->dev;
spi->dev.bus = &spi_bus_type;
spi->dev.release = spidev_release;
+ spi->cs_gpio = -EINVAL;
device_initialize(&spi->dev);
return spi;
}
@@ -344,15 +346,16 @@ EXPORT_SYMBOL_GPL(spi_alloc_device);
int spi_add_device(struct spi_device *spi)
{
static DEFINE_MUTEX(spi_add_lock);
- struct device *dev = spi->master->dev.parent;
+ struct spi_master *master = spi->master;
+ struct device *dev = master->dev.parent;
struct device *d;
int status;
/* Chipselects are numbered 0..max; validate. */
- if (spi->chip_select >= spi->master->num_chipselect) {
+ if (spi->chip_select >= master->num_chipselect) {
dev_err(dev, "cs%d >= max %d\n",
spi->chip_select,
- spi->master->num_chipselect);
+ master->num_chipselect);
return -EINVAL;
}
@@ -376,6 +379,9 @@ int spi_add_device(struct spi_device *spi)
goto done;
}
+ if (master->cs_gpios)
+ spi->cs_gpio = master->cs_gpios[spi->chip_select];
+
/* Drivers may modify this initial i/o setup, but will
* normally rely on the device being setup. Devices
* using SPI_CS_HIGH can't coexist well otherwise...
@@ -949,6 +955,44 @@ struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
}
EXPORT_SYMBOL_GPL(spi_alloc_master);
+#ifdef CONFIG_OF
+static int of_spi_register_master(struct spi_master *master)
+{
+ int nb, i;
+ int *cs;
+ struct device_node *np = master->dev.of_node;
+
+ if (!np)
+ return 0;
+
+ nb = of_gpio_named_count(np, "cs-gpios");
+ master->num_chipselect = max(nb, master->num_chipselect);
+
+ if (nb < 1)
+ return 0;
+
+ cs = devm_kzalloc(&master->dev,
+ sizeof(int) * master->num_chipselect,
+ GFP_KERNEL);
+ master->cs_gpios = cs;
+
+ if (!master->cs_gpios)
+ return -ENOMEM;
+
+ memset(cs, -EINVAL, master->num_chipselect);
+
+ for (i = 0; i < nb; i++)
+ cs[i] = of_get_named_gpio(np, "cs-gpios", i);
+
+ return 0;
+}
+#else
+static int of_spi_register_master(struct spi_master *master)
+{
+ return 0;
+}
+#endif
+
/**
* spi_register_master - register SPI master controller
* @master: initialized master, originally from spi_alloc_master()
@@ -980,6 +1024,10 @@ int spi_register_master(struct spi_master *master)
if (!dev)
return -ENODEV;
+ status = of_spi_register_master(master);
+ if (status)
+ return status;
+
/* even if it's just one always-selected device, there must
* be@least one chipselect
*/
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index fa702ae..f629189 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -90,6 +90,7 @@ struct spi_device {
void *controller_state;
void *controller_data;
char modalias[SPI_NAME_SIZE];
+ int cs_gpio; /* chip select gpio */
/*
* likely need more hooks for more protocol options affecting how
@@ -362,6 +363,8 @@ struct spi_master {
int (*transfer_one_message)(struct spi_master *master,
struct spi_message *mesg);
int (*unprepare_transfer_hardware)(struct spi_master *master);
+ /* gpio chip select */
+ int *cs_gpios;
};
static inline void *spi_master_get_devdata(struct spi_master *master)
--
1.7.10.4
^ permalink raw reply related
* [PATCH 2/4] pinctrl: kirkwood: Prevent NULL dereference if of_match_device returns NULL
From: Thomas Petazzoni @ 2012-11-15 19:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1352955159.6793.2.camel@phoenix>
Dear Axel Lin,
On Thu, 15 Nov 2012 12:52:39 +0800, Axel Lin wrote:
> of_match_device() may return NULL.
>
> Signed-off-by: Axel Lin <axel.lin@ingics.com>
Why? We already discussed together that this situation could not
happen: if you are in the probe() function, then there *must* be a
match, because the probe() function precisely gets called when there is
a match.
So unless you give more details about what the problem is, I don't
think this patch and the similar one you sent for Dove are useful.
Best regards,
Thomas
--
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* [PATCH 01/14] pinctrl: SPEAr: add spi chipselect control driver
From: Linus Walleij @ 2012-11-15 19:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKohpomLRYAKJ=dNLVsjj1xf=G6xj4EcTpPmhSDvgBYUMXc1mA@mail.gmail.com>
On Thu, Nov 15, 2012 at 3:19 PM, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> On 15 November 2012 19:47, Linus Walleij <linus.walleij@linaro.org> wrote:
>> Just one question: since this driver is not using any
>> pinctrl interfaces, why is it under drivers/pinctrl/*?
>>
>> Shouldn't it be under drivers/gpio from a technical
>> point of view?
>>
>> I think I'd accept it under drivers/pinctrl/spear/*
>> if you just want this to keep everything SPEAr-related
>> in one place though, so enlighten me.
>
> That's because they are controlling few pads. They are not
> actually gpio's but just pads that we are controlling.
>
> That's why we thought they are better in this place.
The grouping of drivers in the kernel is about what in-kernel
subsystem interface they're using, not how their electronics
work...
Since this driver is only using the GPIO API it should be
in drivers/gpio/gpio-*.c.
Many, many drivers in drivers/gpio* are controlling pads
too, so it will be in good company ;-)
Yours,
Linus Walleij
^ 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