diff mbox

[PATCHv2,0/5] Support for Marvell switches with integrated CPUs

Message ID 20170106041517.9589-1-chris.packham@alliedtelesis.co.nz (mailing list archive)
State New, archived
Headers show

Commit Message

Chris Packham Jan. 6, 2017, 4:14 a.m. UTC
The 98DX3236, 98DX3336 and 98DX4251 are a set of switch ASICs with
integrated CPUs. They CPU block is common within these product lines and
(as far as I can tell/have been told) is based on the Armada XP. There
are a few differences due to the fact they have to squeeze the CPU into
the same package as the switch.

Chris Packham (4):
  clk: mvebu: support for 98DX3236 SoC
    Changes in v2:
    - Update devicetree binding documentation for new compatible string
    Changes in v3:
    - Add 98dx3236 support to mvebu/clk-corediv.c rather than creating a
      new driver.
    - Document mv98dx3236-corediv-clock binding
  arm: mvebu: support for SMP on 98DX3336 SoC
    Changes in v2:
    - Document new enable-method value
    - Correct some references from 98DX4521 to 98DX3236
    Changes in v3:
    - Simplify mv98dx3236_resume_init by using of_io_request_and_map()
  arm: mvebu: Add device tree for 98DX3236 SoCs
    Changes in v2:
    - Update devicetree binding documentation to reflect that 98DX3336 and
      984251 are supersets of 98DX3236.
    - disable crypto block
    - disable sdio for 98DX3236, enable for 98DX4251
    Changes in v3:
    - fix typo 4521 -> 4251
    - document prestera bindings
    - rework corediv-clock binding
    - add label to packet processor node
    - add new compativle string for DFX server
  arm: mvebu: Add device tree for db-dxbc2 and db-xc3-24g4xg boards
    Changes in v2/v3:
    - none

Kalyan Kinthada (1):
  pinctrl: mvebu: pinctrl driver for 98DX3236 SoC
    Changes in v2:
    - include sdio support for the 98DX4251
    Changes in v3:
    - None


 Documentation/devicetree/bindings/arm/cpus.txt     |   1 +
 .../bindings/arm/marvell/98dx3236-resume-ctrl.txt  |  18 ++
 .../devicetree/bindings/arm/marvell/98dx3236.txt   |  23 ++
 .../bindings/clock/mvebu-corediv-clock.txt         |   1 +
 .../devicetree/bindings/clock/mvebu-cpu-clock.txt  |   1 +
 .../devicetree/bindings/net/marvell,prestera.txt   |  50 ++++
 .../pinctrl/marvell,armada-98dx3236-pinctrl.txt    |  46 ++++
 arch/arm/boot/dts/armada-xp-98dx3236.dtsi          | 254 +++++++++++++++++++++
 arch/arm/boot/dts/armada-xp-98dx3336.dtsi          |  76 ++++++
 arch/arm/boot/dts/armada-xp-98dx4251.dtsi          |  90 ++++++++
 arch/arm/boot/dts/db-dxbc2.dts                     | 159 +++++++++++++
 arch/arm/boot/dts/db-xc3-24g4xg.dts                | 155 +++++++++++++
 arch/arm/mach-mvebu/Makefile                       |   1 +
 arch/arm/mach-mvebu/common.h                       |   1 +
 arch/arm/mach-mvebu/platsmp.c                      |  43 ++++
 arch/arm/mach-mvebu/pmsu-98dx3236.c                |  52 +++++
 drivers/clk/mvebu/armada-xp.c                      |  42 ++++
 drivers/clk/mvebu/clk-corediv.c                    |  23 ++
 drivers/clk/mvebu/clk-cpu.c                        |  31 ++-
 drivers/pinctrl/mvebu/pinctrl-armada-xp.c          | 155 +++++++++++++
 20 files changed, 1220 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/marvell/98dx3236-resume-ctrl.txt
 create mode 100644 Documentation/devicetree/bindings/arm/marvell/98dx3236.txt
 create mode 100644 Documentation/devicetree/bindings/net/marvell,prestera.txt
 create mode 100644 Documentation/devicetree/bindings/pinctrl/marvell,armada-98dx3236-pinctrl.txt
 create mode 100644 arch/arm/boot/dts/armada-xp-98dx3236.dtsi
 create mode 100644 arch/arm/boot/dts/armada-xp-98dx3336.dtsi
 create mode 100644 arch/arm/boot/dts/armada-xp-98dx4251.dtsi
 create mode 100644 arch/arm/boot/dts/db-dxbc2.dts
 create mode 100644 arch/arm/boot/dts/db-xc3-24g4xg.dts
 create mode 100644 arch/arm/mach-mvebu/pmsu-98dx3236.c

Interdiff to v2:

-       kfree(clks);
-err_unmap:
-       iounmap(base);
-}
-
-CLK_OF_DECLARE(mv98dx3236_corediv_clk,
"marvell,mv98dx3236-corediv-clock",
-              mv98dx3236_corediv_clk_init);
diff mbox

Patch

diff --git
a/Documentation/devicetree/bindings/clock/mvebu-corediv-clock.txt
b/Documentation/devicetree/bindings/clock/mvebu-corediv-clock.txt
index 520562a7dc2a..c7b4e3a6b2c6 100644
--- a/Documentation/devicetree/bindings/clock/mvebu-corediv-clock.txt
+++ b/Documentation/devicetree/bindings/clock/mvebu-corediv-clock.txt
@@ -7,6 +7,7 @@  Required properties:
 - compatible : must be "marvell,armada-370-corediv-clock",
                       "marvell,armada-375-corediv-clock",
                       "marvell,armada-380-corediv-clock",
+                       "marvell,mv98dx3236-corediv-clock",
 
 - reg : must be the register address of Core Divider control register
 - #clock-cells : from common clock binding; shall be set to 1
diff --git a/Documentation/devicetree/bindings/net/marvell,prestera.txt
b/Documentation/devicetree/bindings/net/marvell,prestera.txt
new file mode 100644
index 000000000000..5fbab29718e8
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/marvell,prestera.txt
@@ -0,0 +1,50 @@ 
+Marvell Prestera Switch Chip bindings
+-------------------------------------
+
+Required properties:
+- compatible: one of the following
+       "marvell,prestera-98dx3236",
+       "marvell,prestera-98dx3336",
+       "marvell,prestera-98dx4251",
+- reg: address and length of the register set for the device.
+- interrupts: interrupt for the device
+
+Optional properties:
+- dfx: phandle reference to the "DFX Server" node
+
+Example:
+
+switch {
+       compatible = "simple-bus";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       ranges = <0 MBUS_ID(0x03, 0x00) 0 0x100000>;
+
+       packet-processor@0 {
+               compatible = "marvell,prestera-98dx3236";
+               reg = <0 0x4000000>;
+               interrupts = <33>, <34>, <35>;
+               dfx = <&dfx>;
+       };
+};
+
+DFX Server bindings
+-------------------
+
+Required properties:
+- compatible: must be "marvell,dfx-server"
+- reg: address and length of the register set for the device.
+
+Example:
+
+dfx-registers {
+       compatible = "simple-bus";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       ranges = <0 MBUS_ID(0x08, 0x00) 0 0x100000>;
+
+       dfx: dfx@0 {
+               compatible = "marvell,dfx-server";
+               reg = <0 0x100000>;
+       };
+};
diff --git a/arch/arm/boot/dts/armada-xp-98dx3236.dtsi
b/arch/arm/boot/dts/armada-xp-98dx3236.dtsi
index 61bd3acc5cfe..4b7b2fe3b682 100644
--- a/arch/arm/boot/dts/armada-xp-98dx3236.dtsi
+++ b/arch/arm/boot/dts/armada-xp-98dx3236.dtsi
@@ -126,12 +126,7 @@ 
                        };
 
                        corediv-clock@18740 {
-                               compatible =
                                "marvell,mv98dx3236-corediv-clock";
-                               reg = <0xf8268 0xc>;
-                               base = <&dfx>;
-                               #clock-cells = <1>;
-                               clocks = <&mainpll>;
-                               clock-output-names = "nand";
+                               status = "disabled";
                        };
 
                        xor@60900 {
@@ -194,6 +189,10 @@ 
                                #interrupt-cells = <2>;
                                interrupts = <87>;
                        };
+
+                       nand: nand@d0000 {
+                               clocks = <&dfx_coredivclk 0>;
+                       };
                };
 
                dfx-registers {
@@ -202,8 +201,16 @@ 
                        #size-cells = <1>;
                        ranges = <0 MBUS_ID(0x08, 0x00) 0 0x100000>;
 
+                        dfx_coredivclk: corediv-clock@f8268 {
+                                compatible =
"marvell,mv98dx3236-corediv-clock";
+                                reg = <0xf8268 0xc>;
+                                #clock-cells = <1>;
+                                clocks = <&mainpll>;
+                                clock-output-names = "nand";
+                        };
+
                        dfx: dfx@0 {
-                               compatible = "simple-bus";
+                               compatible = "marvell,dfx-server";
                                reg = <0 0x100000>;
                        };
                };
@@ -214,7 +221,7 @@ 
                        #size-cells = <1>;
                        ranges = <0 MBUS_ID(0x03, 0x00) 0 0x100000>;
 
-                       packet-processor@0 {
+                       pp0: packet-processor@0 {
                                compatible =
"marvell,prestera-98dx3236";
                                reg = <0 0x4000000>;
                                interrupts = <33>, <34>, <35>;
diff --git a/arch/arm/boot/dts/armada-xp-98dx3336.dtsi
b/arch/arm/boot/dts/armada-xp-98dx3336.dtsi
index 9c9aa565fd82..a9b0f47f8df9 100644
--- a/arch/arm/boot/dts/armada-xp-98dx3336.dtsi
+++ b/arch/arm/boot/dts/armada-xp-98dx3336.dtsi
@@ -68,11 +68,9 @@ 
                                reg = <0x20980 0x10>;
                        };
                };
-
-               switch {
-                       packet-processor@0 {
-                               compatible =
                                "marvell,prestera-98dx3336";
-                       };
-               };
        };
 };
+
+&pp0 {
+       compatible = "marvell,prestera-98dx3336";
+};
diff --git a/arch/arm/boot/dts/armada-xp-98dx4251.dtsi
b/arch/arm/boot/dts/armada-xp-98dx4251.dtsi
index 5f7edc23d5ae..446e6e65ec59 100644
--- a/arch/arm/boot/dts/armada-xp-98dx4251.dtsi
+++ b/arch/arm/boot/dts/armada-xp-98dx4251.dtsi
@@ -68,12 +68,6 @@ 
                                reg = <0x20980 0x10>;
                        };
                };
-
-               switch {
-                       packet-processor@0 {
-                               compatible =
                                "marvell,prestera-98dx4521";
-                       };
-               };
        };
 };
 
@@ -90,3 +84,7 @@ 
                marvell,function = "sd0";
        };
 };
+
+&pp0 {
+       compatible = "marvell,prestera-98dx4251";
+};
diff --git a/arch/arm/mach-mvebu/pmsu-98dx3236.c
b/arch/arm/mach-mvebu/pmsu-98dx3236.c
index 87ca42ef40c7..1052674dd439 100644
--- a/arch/arm/mach-mvebu/pmsu-98dx3236.c
+++ b/arch/arm/mach-mvebu/pmsu-98dx3236.c
@@ -31,39 +31,22 @@  void mv98dx3236_resume_set_cpu_boot_addr(int hw_cpu,
void *boot_addr)
 static int __init mv98dx3236_resume_init(void)
 {
        struct device_node *np;
-       struct resource res;
-       int ret = 0;
+       void __iomem *base;
 
        np = of_find_matching_node(NULL, of_mv98dx3236_resume_table);
        if (!np)
                return 0;
 
-       pr_info("Initializing 98DX3236 Resume\n");
-
-       if (of_address_to_resource(np, 0, &res)) {
-               pr_err("unable to get resource\n");
-               ret = -ENOENT;
-               goto out;
-       }
-
-       if (!request_mem_region(res.start, resource_size(&res),
-                               np->full_name)) {
-               pr_err("unable to request region\n");
-               ret = -EBUSY;
-               goto out;
-       }
-
-       mv98dx3236_resume_base = ioremap(res.start,
        resource_size(&res));
-       if (!mv98dx3236_resume_base) {
+       base = of_io_request_and_map(np, 0, of_node_full_name(np));
+       if (IS_ERR(base)) {
                pr_err("unable to map registers\n");
-               release_mem_region(res.start, resource_size(&res));
-               ret = -ENOMEM;
-               goto out;
+               of_node_put(np);
+               return PTR_ERR(mv98dx3236_resume_base);
        }
 
-out:
+       mv98dx3236_resume_base = base;
        of_node_put(np);
-       return ret;
+       return 0;
 }
 
 early_initcall(mv98dx3236_resume_init);
diff --git a/drivers/clk/mvebu/Makefile b/drivers/clk/mvebu/Makefile
index 6a3681e3d6db..d9ae97fb43c4 100644
--- a/drivers/clk/mvebu/Makefile
+++ b/drivers/clk/mvebu/Makefile
@@ -9,7 +9,7 @@  obj-$(CONFIG_ARMADA_39X_CLK)    += armada-39x.o
 obj-$(CONFIG_ARMADA_37XX_CLK)  += armada-37xx-xtal.o
 obj-$(CONFIG_ARMADA_37XX_CLK)  += armada-37xx-tbg.o
 obj-$(CONFIG_ARMADA_37XX_CLK)  += armada-37xx-periph.o
-obj-$(CONFIG_ARMADA_XP_CLK)    += armada-xp.o mv98dx3236-corediv.o
+obj-$(CONFIG_ARMADA_XP_CLK)    += armada-xp.o
 obj-$(CONFIG_ARMADA_AP806_SYSCON) += ap806-system-controller.o
 obj-$(CONFIG_ARMADA_CP110_SYSCON) += cp110-system-controller.o
 obj-$(CONFIG_DOVE_CLK)         += dove.o dove-divider.o
diff --git a/drivers/clk/mvebu/clk-corediv.c
b/drivers/clk/mvebu/clk-corediv.c
index d1e5863d3375..8491979f4096 100644
--- a/drivers/clk/mvebu/clk-corediv.c
+++ b/drivers/clk/mvebu/clk-corediv.c
@@ -71,6 +71,10 @@  static const struct clk_corediv_desc
mvebu_corediv_desc[] = {
        { .mask = 0x3f, .offset = 8, .fieldbit = 1 }, /* NAND clock */
 };
 
+static const struct clk_corediv_desc mv98dx3236_corediv_desc[] = {
+       { .mask = 0x0f, .offset = 6, .fieldbit = 26 }, /* NAND clock */
+};
+
 #define to_corediv_clk(p) container_of(p, struct clk_corediv, hw)
 
 static int clk_corediv_is_enabled(struct clk_hw *hwclk)
@@ -232,6 +236,18 @@  static const struct clk_corediv_soc_desc
armada375_corediv_soc = {
        .ratio_offset = 0x4,
 };
 
+static const struct clk_corediv_soc_desc mv98dx3236_corediv_soc = {
+       .descs = mv98dx3236_corediv_desc,
+       .ndescs = ARRAY_SIZE(mv98dx3236_corediv_desc),
+       .ops = {
+               .recalc_rate = clk_corediv_recalc_rate,
+               .round_rate = clk_corediv_round_rate,
+               .set_rate = clk_corediv_set_rate,
+       },
+       .ratio_reload = BIT(10),
+       .ratio_offset = 0x8,
+};
+
 static void __init
 mvebu_corediv_clk_init(struct device_node *node,
                       const struct clk_corediv_soc_desc *soc_desc)
@@ -313,3 +329,10 @@  static void __init
armada380_corediv_clk_init(struct device_node *node)
 }
 CLK_OF_DECLARE(armada380_corediv_clk,
"marvell,armada-380-corediv-clock",
               armada380_corediv_clk_init);
+
+static void __init mv98dx3236_corediv_clk_init(struct device_node
*node)
+{
+       return mvebu_corediv_clk_init(node, &mv98dx3236_corediv_soc);
+}
+CLK_OF_DECLARE(mv98dx3236_corediv_clk,
"marvell,mv98dx3236-corediv-clock",
+              mv98dx3236_corediv_clk_init);
diff --git a/drivers/clk/mvebu/clk-cpu.c b/drivers/clk/mvebu/clk-cpu.c
index 29f295e7a36b..3b8f0e14fa01 100644
--- a/drivers/clk/mvebu/clk-cpu.c
+++ b/drivers/clk/mvebu/clk-cpu.c
@@ -254,7 +254,7 @@  static void __init of_cpu_clk_setup(struct
device_node *node)
 }
 
 CLK_OF_DECLARE(armada_xp_cpu_clock, "marvell,armada-xp-cpu-clock",
-                                       of_cpu_clk_setup);
+                                        of_cpu_clk_setup);
 
 /* Define the clock and operations for the mv98dx3236 - it cannot
 * perform
  * any operations.
diff --git a/drivers/clk/mvebu/mv98dx3236-corediv.c
b/drivers/clk/mvebu/mv98dx3236-corediv.c
deleted file mode 100644
index 3060764a8e5d..000000000000
--- a/drivers/clk/mvebu/mv98dx3236-corediv.c
+++ /dev/null
@@ -1,207 +0,0 @@ 
-/*
- * MV98DX3236 Core divider clock
- *
- * Copyright (C) 2015 Allied Telesis Labs
- *
- * Based on armada-xp-corediv.c
- * Copyright (C) 2015 Marvell
- *
- * John Thompson <john.thompson@alliedtelesis.co.nz>
- *
- * 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-provider.h>
-#include <linux/of_address.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include "common.h"
-
-#define CORE_CLK_DIV_RATIO_MASK                0xff
-
-#define CLK_DIV_RATIO_NAND_MASK 0x0f
-#define CLK_DIV_RATIO_NAND_OFFSET 6
-#define CLK_DIV_RATIO_NAND_FORCE_RELOAD_BIT 26
-
-#define RATIO_RELOAD_BIT BIT(10)
-#define RATIO_REG_OFFSET 0x08
-
-/*
- * This structure represents one core divider clock for the clock
- * framework, and is dynamically allocated for each core divider clock
- * existing in the current SoC.
- */
-struct clk_corediv {
-       struct clk_hw hw;
-       void __iomem *reg;
-       spinlock_t lock;
-};
-
-static struct clk_onecell_data clk_data;
-
-
-#define to_corediv_clk(p) container_of(p, struct clk_corediv, hw)
-
-static int mv98dx3236_corediv_is_enabled(struct clk_hw *hwclk)
-{
-       /* Core divider is always active */
-       return 1;
-}
-
-static int mv98dx3236_corediv_enable(struct clk_hw *hwclk)
-{
-       /* always succeeds */
-       return 0;
-}
-
-static void mv98dx3236_corediv_disable(struct clk_hw *hwclk)
-{
-       /* can't be disabled so is left alone */
-}
-
-static unsigned long mv98dx3236_corediv_recalc_rate(struct clk_hw
*hwclk,
-                                        unsigned long parent_rate)
-{
-       struct clk_corediv *corediv = to_corediv_clk(hwclk);
-       u32 reg, div;
-
-       reg = readl(corediv->reg + RATIO_REG_OFFSET);
-       div = (reg >> CLK_DIV_RATIO_NAND_OFFSET) &
        CLK_DIV_RATIO_NAND_MASK;
-       return parent_rate / div;
-}
-
-static long mv98dx3236_corediv_round_rate(struct clk_hw *hwclk,
-                              unsigned long rate, unsigned long
                               *parent_rate)
-{
-       /* Valid ratio are 1:4, 1:5, 1:6 and 1:8 */
-       u32 div;
-
-       div = *parent_rate / rate;
-       if (div < 4)
-               div = 4;
-       else if (div > 6)
-               div = 8;
-
-       return *parent_rate / div;
-}
-
-static int mv98dx3236_corediv_set_rate(struct clk_hw *hwclk, unsigned
long rate,
-                           unsigned long parent_rate)
-{
-       struct clk_corediv *corediv = to_corediv_clk(hwclk);
-       unsigned long flags = 0;
-       u32 reg, div;
-
-       div = parent_rate / rate;
-
-       spin_lock_irqsave(&corediv->lock, flags);
-
-       /* Write new divider to the divider ratio register */
-       reg = readl(corediv->reg + RATIO_REG_OFFSET);
-       reg &= ~(CLK_DIV_RATIO_NAND_MASK << CLK_DIV_RATIO_NAND_OFFSET);
-       reg |= (div & CLK_DIV_RATIO_NAND_MASK) <<
        CLK_DIV_RATIO_NAND_OFFSET;
-       writel(reg, corediv->reg + RATIO_REG_OFFSET);
-
-       /* Set reload-force for this clock */
-       reg = readl(corediv->reg) |
        BIT(CLK_DIV_RATIO_NAND_FORCE_RELOAD_BIT);
-       writel(reg, corediv->reg);
-
-       /* Now trigger the clock update */
-       reg = readl(corediv->reg + RATIO_REG_OFFSET) | RATIO_RELOAD_BIT;
-       writel(reg, corediv->reg + RATIO_REG_OFFSET);
-
-       /*
-        * Wait for clocks to settle down, and then clear all the
-        * ratios request and the reload request.
-        */
-       udelay(1000);
-       reg &= ~(CORE_CLK_DIV_RATIO_MASK | RATIO_RELOAD_BIT);
-       writel(reg, corediv->reg + RATIO_REG_OFFSET);
-       udelay(1000);
-
-       spin_unlock_irqrestore(&corediv->lock, flags);
-
-       return 0;
-}
-
-static const struct clk_ops ops = {
-       .enable = mv98dx3236_corediv_enable,
-       .disable = mv98dx3236_corediv_disable,
-       .is_enabled = mv98dx3236_corediv_is_enabled,
-       .recalc_rate = mv98dx3236_corediv_recalc_rate,
-       .round_rate = mv98dx3236_corediv_round_rate,
-       .set_rate = mv98dx3236_corediv_set_rate,
-};
-
-static void __init mv98dx3236_corediv_clk_init(struct device_node
*node)
-{
-       struct clk_init_data init;
-       struct clk_corediv *corediv;
-       struct clk **clks;
-       void __iomem *base;
-       const __be32 *off;
-       const char *parent_name;
-       const char *clk_name;
-       int len;
-       struct device_node *dfx_node;
-
-       dfx_node = of_parse_phandle(node, "base", 0);
-       if (WARN_ON(!dfx_node))
-               return;
-
-       off = of_get_property(node, "reg", &len);
-       if (WARN_ON(!off))
-               return;
-
-       base = of_iomap(dfx_node, 0);
-       if (WARN_ON(!base))
-               return;
-
-       of_node_put(dfx_node);
-
-       parent_name = of_clk_get_parent_name(node, 0);
-
-       clk_data.clk_num = 1;
-
-       /* clks holds the clock array */
-       clks = kcalloc(clk_data.clk_num, sizeof(struct clk *),
-                               GFP_KERNEL);
-       if (WARN_ON(!clks))
-               goto err_unmap;
-       /* corediv holds the clock specific array */
-       corediv = kcalloc(clk_data.clk_num, sizeof(struct clk_corediv),
-                               GFP_KERNEL);
-       if (WARN_ON(!corediv))
-               goto err_free_clks;
-
-       spin_lock_init(&corediv->lock);
-
-       of_property_read_string_index(node, "clock-output-names",
-                                         0, &clk_name);
-
-       init.num_parents = 1;
-       init.parent_names = &parent_name;
-       init.name = clk_name;
-       init.ops = &ops;
-       init.flags = 0;
-
-       corediv[0].reg = (void *)((int)base + be32_to_cpu(*off));
-       corediv[0].hw.init = &init;
-
-       clks[0] = clk_register(NULL, &corediv[0].hw);
-       WARN_ON(IS_ERR(clks[0]));
-
-       clk_data.clks = clks;
-       of_clk_add_provider(node, of_clk_src_onecell_get, &clk_data);
-       return;
-
-err_free_clks: