2020-06-08 12:33:04

by Lars Povlsen

[permalink] [raw]
Subject: [PATCH v2 00/10] Adding support for Microchip Sparx5 SoC

This patch series adds support for Microchip Sparx5 SoC, the CPU
system of a advanced, TSN capable gigabit switch. The CPU is an armv8
x 2 CPU core (A53).

Although this is an ARM core, it shares some peripherals with the
Microsemi Ocelot SoC.

Changes in v2:
- Misc fixes to bindings/arm/microchip,sparx5.yaml
- Changed clock driver to platform driver, among other fixes
- arch/arm64/boot/dts/microchip/sparx5.dtsi:
- Added pmu and psci node, using PSCI
- Updates to GICv3 register spaces (GICV/GICH)
- Updated timer interrupt specifiers
- pinctrl: ocelot: Fixed symbol clashes from powerpc
- pinctrl: ocelot: Patches already in next-20200605 have been removed
from this series.

Lars Povlsen (10):
dt-bindings: arm: sparx5: Add documentation for Microchip Sparx5 SoC
arm64: sparx5: Add support for Microchip 2xA53 SoC
arm64: dts: sparx5: Add basic cpu support
arm64: dts: sparx5: Add pinctrl support
pinctrl: ocelot: Add Sparx5 SoC support
dt-bindings: clock: sparx5: Add Sparx5 SoC DPLL clock
dt-bindings: clock: sparx5: Add bindings include file
clk: sparx5: Add Sparx5 SoC DPLL clock driver
arm64: dts: sparx5: Add Sparx5 SoC DPLL clock
arm64: dts: sparx5: Add i2c devices, i2c muxes

.../bindings/arm/microchip,sparx5.yaml | 65 +++
.../bindings/clock/microchip,sparx5-dpll.yaml | 52 +++
.../devicetree/bindings/mfd/syscon.yaml | 1 +
MAINTAINERS | 9 +
arch/arm64/Kconfig.platforms | 14 +
arch/arm64/boot/dts/Makefile | 1 +
arch/arm64/boot/dts/microchip/Makefile | 4 +
arch/arm64/boot/dts/microchip/sparx5.dtsi | 213 +++++++++
.../boot/dts/microchip/sparx5_pcb125.dts | 21 +
.../boot/dts/microchip/sparx5_pcb134.dts | 17 +
.../dts/microchip/sparx5_pcb134_board.dtsi | 252 ++++++++++
.../boot/dts/microchip/sparx5_pcb134_emmc.dts | 17 +
.../boot/dts/microchip/sparx5_pcb135.dts | 17 +
.../dts/microchip/sparx5_pcb135_board.dtsi | 92 ++++
.../boot/dts/microchip/sparx5_pcb135_emmc.dts | 17 +
.../boot/dts/microchip/sparx5_pcb_common.dtsi | 19 +
drivers/clk/Makefile | 1 +
drivers/clk/clk-sparx5.c | 312 +++++++++++++
drivers/pinctrl/pinctrl-ocelot.c | 431 +++++++++++++++++-
include/dt-bindings/clock/microchip,sparx5.h | 23 +
20 files changed, 1577 insertions(+), 1 deletion(-)
create mode 100644 Documentation/devicetree/bindings/arm/microchip,sparx5.yaml
create mode 100644 Documentation/devicetree/bindings/clock/microchip,sparx5-dpll.yaml
create mode 100644 arch/arm64/boot/dts/microchip/Makefile
create mode 100644 arch/arm64/boot/dts/microchip/sparx5.dtsi
create mode 100644 arch/arm64/boot/dts/microchip/sparx5_pcb125.dts
create mode 100644 arch/arm64/boot/dts/microchip/sparx5_pcb134.dts
create mode 100644 arch/arm64/boot/dts/microchip/sparx5_pcb134_board.dtsi
create mode 100644 arch/arm64/boot/dts/microchip/sparx5_pcb134_emmc.dts
create mode 100644 arch/arm64/boot/dts/microchip/sparx5_pcb135.dts
create mode 100644 arch/arm64/boot/dts/microchip/sparx5_pcb135_board.dtsi
create mode 100644 arch/arm64/boot/dts/microchip/sparx5_pcb135_emmc.dts
create mode 100644 arch/arm64/boot/dts/microchip/sparx5_pcb_common.dtsi
create mode 100644 drivers/clk/clk-sparx5.c
create mode 100644 include/dt-bindings/clock/microchip,sparx5.h

--
2.27.0


2020-06-09 08:10:04

by Lars Povlsen

[permalink] [raw]
Subject: [PATCH v2 01/10] dt-bindings: arm: sparx5: Add documentation for Microchip Sparx5 SoC

This adds the main Sparx5 SoC DT documentation file, with information
abut the supported board types.

Reviewed-by: Alexandre Belloni <[email protected]>
Signed-off-by: Lars Povlsen <[email protected]>
---
.../bindings/arm/microchip,sparx5.yaml | 65 +++++++++++++++++++
.../devicetree/bindings/mfd/syscon.yaml | 1 +
2 files changed, 66 insertions(+)
create mode 100644 Documentation/devicetree/bindings/arm/microchip,sparx5.yaml

diff --git a/Documentation/devicetree/bindings/arm/microchip,sparx5.yaml b/Documentation/devicetree/bindings/arm/microchip,sparx5.yaml
new file mode 100644
index 0000000000000..ecf6fa12e6ad2
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/microchip,sparx5.yaml
@@ -0,0 +1,65 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/microchip,sparx5.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip Sparx5 Boards Device Tree Bindings
+
+maintainers:
+ - Lars Povlsen <[email protected]>
+
+description: |+
+ The Microchip Sparx5 SoC is a ARMv8-based used in a family of
+ gigabit TSN-capable gigabit switches.
+
+ The SparX-5 Ethernet switch family provides a rich set of switching
+ features such as advanced TCAM-based VLAN and QoS processing
+ enabling delivery of differentiated services, and security through
+ TCAM-based frame processing using versatile content aware processor
+ (VCAP)
+
+properties:
+ $nodename:
+ const: '/'
+ compatible:
+ oneOf:
+ - description: The Sparx5 pcb125 board is a modular board,
+ which has both spi-nor and eMMC storage. The modular design
+ allows for connection of different network ports.
+ items:
+ - const: microchip,sparx5-pcb125
+ - const: microchip,sparx5
+
+ - description: The Sparx5 pcb134 is a pizzabox form factor
+ gigabit switch with 20 SFP ports. It features spi-nor and
+ either spi-nand or eMMC storage (mount option).
+ items:
+ - const: microchip,sparx5-pcb134
+ - const: microchip,sparx5
+
+ - description: The Sparx5 pcb135 is a pizzabox form factor
+ gigabit switch with 48+4 Cu ports. It features spi-nor and
+ either spi-nand or eMMC storage (mount option).
+ items:
+ - const: microchip,sparx5-pcb135
+ - const: microchip,sparx5
+
+ axi@600000000:
+ type: object
+ description: the root node in the Sparx5 platforms must contain
+ an axi bus child node. They are always at physical address
+ 0x600000000 in all the Sparx5 variants.
+ properties:
+ compatible:
+ items:
+ - const: simple-bus
+
+ required:
+ - compatible
+
+required:
+ - compatible
+ - axi@600000000
+
+...
diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml
index 19bdaf781853b..f3fba860d3cc5 100644
--- a/Documentation/devicetree/bindings/mfd/syscon.yaml
+++ b/Documentation/devicetree/bindings/mfd/syscon.yaml
@@ -38,6 +38,7 @@ properties:
- allwinner,sun8i-h3-system-controller
- allwinner,sun8i-v3s-system-controller
- allwinner,sun50i-a64-system-controller
+ - microchip,sparx5-cpu-syscon

- const: syscon

--
2.27.0

2020-06-09 08:10:22

by Lars Povlsen

[permalink] [raw]
Subject: [PATCH v2 03/10] arm64: dts: sparx5: Add basic cpu support

This adds the basic DT structure for the Microchip Sparx5 SoC, and the
reference boards, pcb125, pcb134 and pcb135. The two latter have a
NAND vs a eMMC centric variant (as a mount option).

Reviewed-by: Alexandre Belloni <[email protected]>
Signed-off-by: Lars Povlsen <[email protected]>
---
MAINTAINERS | 1 +
arch/arm64/boot/dts/Makefile | 1 +
arch/arm64/boot/dts/microchip/Makefile | 4 +
arch/arm64/boot/dts/microchip/sparx5.dtsi | 142 ++++++++++++++++++
.../boot/dts/microchip/sparx5_pcb125.dts | 17 +++
.../boot/dts/microchip/sparx5_pcb134.dts | 17 +++
.../dts/microchip/sparx5_pcb134_board.dtsi | 15 ++
.../boot/dts/microchip/sparx5_pcb134_emmc.dts | 17 +++
.../boot/dts/microchip/sparx5_pcb135.dts | 17 +++
.../dts/microchip/sparx5_pcb135_board.dtsi | 15 ++
.../boot/dts/microchip/sparx5_pcb135_emmc.dts | 17 +++
.../boot/dts/microchip/sparx5_pcb_common.dtsi | 15 ++
12 files changed, 278 insertions(+)
create mode 100644 arch/arm64/boot/dts/microchip/Makefile
create mode 100644 arch/arm64/boot/dts/microchip/sparx5.dtsi
create mode 100644 arch/arm64/boot/dts/microchip/sparx5_pcb125.dts
create mode 100644 arch/arm64/boot/dts/microchip/sparx5_pcb134.dts
create mode 100644 arch/arm64/boot/dts/microchip/sparx5_pcb134_board.dtsi
create mode 100644 arch/arm64/boot/dts/microchip/sparx5_pcb134_emmc.dts
create mode 100644 arch/arm64/boot/dts/microchip/sparx5_pcb135.dts
create mode 100644 arch/arm64/boot/dts/microchip/sparx5_pcb135_board.dtsi
create mode 100644 arch/arm64/boot/dts/microchip/sparx5_pcb135_emmc.dts
create mode 100644 arch/arm64/boot/dts/microchip/sparx5_pcb_common.dtsi

diff --git a/MAINTAINERS b/MAINTAINERS
index 3fe6f314df3e7..908f9ac96f6ef 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2116,6 +2116,7 @@ M: Lars Povlsen <[email protected]>
M: Steen Hegelund <[email protected]>
M: Microchip Linux Driver Support <[email protected]>
L: [email protected] (moderated for non-subscribers)
+F: arch/arm64/boot/dts/microchip/
N: sparx5
S: Supported

diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
index f19b762c008d8..9680a7f20c307 100644
--- a/arch/arm64/boot/dts/Makefile
+++ b/arch/arm64/boot/dts/Makefile
@@ -17,6 +17,7 @@ subdir-y += intel
subdir-y += lg
subdir-y += marvell
subdir-y += mediatek
+subdir-y += microchip
subdir-y += nvidia
subdir-y += qcom
subdir-y += realtek
diff --git a/arch/arm64/boot/dts/microchip/Makefile b/arch/arm64/boot/dts/microchip/Makefile
new file mode 100644
index 0000000000000..c6e0313eea0f9
--- /dev/null
+++ b/arch/arm64/boot/dts/microchip/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+dtb-$(CONFIG_ARCH_SPARX5) += sparx5_pcb125.dtb
+dtb-$(CONFIG_ARCH_SPARX5) += sparx5_pcb134.dtb sparx5_pcb134_emmc.dtb
+dtb-$(CONFIG_ARCH_SPARX5) += sparx5_pcb135.dtb sparx5_pcb135_emmc.dtb
diff --git a/arch/arm64/boot/dts/microchip/sparx5.dtsi b/arch/arm64/boot/dts/microchip/sparx5.dtsi
new file mode 100644
index 0000000000000..4a54b7d039167
--- /dev/null
+++ b/arch/arm64/boot/dts/microchip/sparx5.dtsi
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2020 Microchip Technology Inc. and its subsidiaries.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+ compatible = "microchip,sparx5";
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&cpu0>;
+ };
+ core1 {
+ cpu = <&cpu1>;
+ };
+ };
+ };
+ cpu0: cpu@0 {
+ compatible = "arm,cortex-a53";
+ device_type = "cpu";
+ reg = <0x0 0x0>;
+ enable-method = "psci";
+ next-level-cache = <&L2_0>;
+ };
+ cpu1: cpu@1 {
+ compatible = "arm,cortex-a53";
+ device_type = "cpu";
+ reg = <0x0 0x1>;
+ enable-method = "psci";
+ next-level-cache = <&L2_0>;
+ };
+ L2_0: l2-cache0 {
+ compatible = "cache";
+ };
+ };
+
+ arm-pmu {
+ compatible = "arm,cortex-a53-pmu";
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu0>, <&cpu1>;
+ };
+
+ psci {
+ compatible = "arm,psci-0.2";
+ method = "smc";
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ clocks: clocks {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges;
+ ahb_clk: ahb-clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <250000000>;
+ };
+ sys_clk: sys-clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <625000000>;
+ };
+ };
+
+ axi: axi@600000000 {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges;
+
+ gic: interrupt-controller@600300000 {
+ compatible = "arm,gic-v3";
+ #interrupt-cells = <3>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-controller;
+ reg = <0x6 0x00300000 0x10000>, /* GIC Dist */
+ <0x6 0x00340000 0xc0000>, /* GICR */
+ <0x6 0x00200000 0x2000>, /* GICC */
+ <0x6 0x00210000 0x2000>, /* GICV */
+ <0x6 0x00220000 0x2000>; /* GICH */
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ uart0: serial@600100000 {
+ compatible = "ns16550a";
+ reg = <0x6 0x00100000 0x20>;
+ clocks = <&ahb_clk>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+
+ status = "disabled";
+ };
+
+ uart1: serial@600102000 {
+ compatible = "ns16550a";
+ reg = <0x6 0x00102000 0x20>;
+ clocks = <&ahb_clk>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+
+ status = "disabled";
+ };
+
+ timer1: timer@600105000 {
+ compatible = "snps,dw-apb-timer";
+ reg = <0x6 0x00105000 0x1000>;
+ clocks = <&ahb_clk>;
+ clock-names = "timer";
+ interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ };
+};
diff --git a/arch/arm64/boot/dts/microchip/sparx5_pcb125.dts b/arch/arm64/boot/dts/microchip/sparx5_pcb125.dts
new file mode 100644
index 0000000000000..d7f985f7ee020
--- /dev/null
+++ b/arch/arm64/boot/dts/microchip/sparx5_pcb125.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2020 Microchip Technology Inc. and its subsidiaries.
+ */
+
+/dts-v1/;
+#include "sparx5_pcb_common.dtsi"
+
+/ {
+ model = "Sparx5 PCB125 Reference Board";
+ compatible = "microchip,sparx5-pcb125", "microchip,sparx5";
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x00000000 0x00000000 0x10000000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/microchip/sparx5_pcb134.dts b/arch/arm64/boot/dts/microchip/sparx5_pcb134.dts
new file mode 100644
index 0000000000000..feee4e99ff57c
--- /dev/null
+++ b/arch/arm64/boot/dts/microchip/sparx5_pcb134.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2020 Microchip Technology Inc. and its subsidiaries.
+ */
+
+/dts-v1/;
+#include "sparx5_pcb134_board.dtsi"
+
+/ {
+ model = "Sparx5 PCB134 Reference Board (NAND)";
+ compatible = "microchip,sparx5-pcb134", "microchip,sparx5";
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x00000000 0x00000000 0x10000000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/microchip/sparx5_pcb134_board.dtsi b/arch/arm64/boot/dts/microchip/sparx5_pcb134_board.dtsi
new file mode 100644
index 0000000000000..9b2aec400101b
--- /dev/null
+++ b/arch/arm64/boot/dts/microchip/sparx5_pcb134_board.dtsi
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2020 Microchip Technology Inc. and its subsidiaries.
+ */
+
+/dts-v1/;
+#include "sparx5_pcb_common.dtsi"
+
+/{
+ gpio-restart {
+ compatible = "gpio-restart";
+ gpios = <&gpio 37 GPIO_ACTIVE_LOW>;
+ priority = <200>;
+ };
+};
diff --git a/arch/arm64/boot/dts/microchip/sparx5_pcb134_emmc.dts b/arch/arm64/boot/dts/microchip/sparx5_pcb134_emmc.dts
new file mode 100644
index 0000000000000..10081a66961bb
--- /dev/null
+++ b/arch/arm64/boot/dts/microchip/sparx5_pcb134_emmc.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2020 Microchip Technology Inc. and its subsidiaries.
+ */
+
+/dts-v1/;
+#include "sparx5_pcb134_board.dtsi"
+
+/ {
+ model = "Sparx5 PCB134 Reference Board (eMMC enabled)";
+ compatible = "microchip,sparx5-pcb134", "microchip,sparx5";
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x00000000 0x00000000 0x10000000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/microchip/sparx5_pcb135.dts b/arch/arm64/boot/dts/microchip/sparx5_pcb135.dts
new file mode 100644
index 0000000000000..20e409a9be196
--- /dev/null
+++ b/arch/arm64/boot/dts/microchip/sparx5_pcb135.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2020 Microchip Technology Inc. and its subsidiaries.
+ */
+
+/dts-v1/;
+#include "sparx5_pcb135_board.dtsi"
+
+/ {
+ model = "Sparx5 PCB135 Reference Board (NAND)";
+ compatible = "microchip,sparx5-pcb135", "microchip,sparx5";
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x00000000 0x00000000 0x10000000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/microchip/sparx5_pcb135_board.dtsi b/arch/arm64/boot/dts/microchip/sparx5_pcb135_board.dtsi
new file mode 100644
index 0000000000000..9b2aec400101b
--- /dev/null
+++ b/arch/arm64/boot/dts/microchip/sparx5_pcb135_board.dtsi
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2020 Microchip Technology Inc. and its subsidiaries.
+ */
+
+/dts-v1/;
+#include "sparx5_pcb_common.dtsi"
+
+/{
+ gpio-restart {
+ compatible = "gpio-restart";
+ gpios = <&gpio 37 GPIO_ACTIVE_LOW>;
+ priority = <200>;
+ };
+};
diff --git a/arch/arm64/boot/dts/microchip/sparx5_pcb135_emmc.dts b/arch/arm64/boot/dts/microchip/sparx5_pcb135_emmc.dts
new file mode 100644
index 0000000000000..741f0e12260e5
--- /dev/null
+++ b/arch/arm64/boot/dts/microchip/sparx5_pcb135_emmc.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2020 Microchip Technology Inc. and its subsidiaries.
+ */
+
+/dts-v1/;
+#include "sparx5_pcb135_board.dtsi"
+
+/ {
+ model = "Sparx5 PCB135 Reference Board (eMMC enabled)";
+ compatible = "microchip,sparx5-pcb135", "microchip,sparx5";
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x00000000 0x00000000 0x10000000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/microchip/sparx5_pcb_common.dtsi b/arch/arm64/boot/dts/microchip/sparx5_pcb_common.dtsi
new file mode 100644
index 0000000000000..1f99d0db1284f
--- /dev/null
+++ b/arch/arm64/boot/dts/microchip/sparx5_pcb_common.dtsi
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2020 Microchip Technology Inc. and its subsidiaries.
+ */
+
+/dts-v1/;
+#include "sparx5.dtsi"
+
+&uart0 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
--
2.27.0

2020-06-09 08:10:37

by Lars Povlsen

[permalink] [raw]
Subject: [PATCH v2 04/10] arm64: dts: sparx5: Add pinctrl support

This add pinctrl support to the Microchip Sparx5 SoC.

Reviewed-by: Alexandre Belloni <[email protected]>
Signed-off-by: Lars Povlsen <[email protected]>
---
arch/arm64/boot/dts/microchip/sparx5.dtsi | 26 +++++++++++++++++++++++
1 file changed, 26 insertions(+)

diff --git a/arch/arm64/boot/dts/microchip/sparx5.dtsi b/arch/arm64/boot/dts/microchip/sparx5.dtsi
index 4a54b7d039167..baf4176ce1dfe 100644
--- a/arch/arm64/boot/dts/microchip/sparx5.dtsi
+++ b/arch/arm64/boot/dts/microchip/sparx5.dtsi
@@ -109,6 +109,8 @@ gic: interrupt-controller@600300000 {
};

uart0: serial@600100000 {
+ pinctrl-0 = <&uart_pins>;
+ pinctrl-names = "default";
compatible = "ns16550a";
reg = <0x6 0x00100000 0x20>;
clocks = <&ahb_clk>;
@@ -120,6 +122,8 @@ uart0: serial@600100000 {
};

uart1: serial@600102000 {
+ pinctrl-0 = <&uart2_pins>;
+ pinctrl-names = "default";
compatible = "ns16550a";
reg = <0x6 0x00102000 0x20>;
clocks = <&ahb_clk>;
@@ -138,5 +142,27 @@ timer1: timer@600105000 {
interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
};

+ gpio: pinctrl@6110101e0 {
+ compatible = "microchip,sparx5-pinctrl";
+ reg = <0x6 0x110101e0 0x90>, <0x6 0x10508010 0x100>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&gpio 0 0 64>;
+ interrupt-controller;
+ interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+ #interrupt-cells = <2>;
+
+ uart_pins: uart-pins {
+ pins = "GPIO_10", "GPIO_11";
+ function = "uart";
+ };
+
+ uart2_pins: uart2-pins {
+ pins = "GPIO_26", "GPIO_27";
+ function = "uart2";
+ };
+
+ };
+
};
};
--
2.27.0

2020-06-09 08:10:43

by Lars Povlsen

[permalink] [raw]
Subject: [PATCH v2 05/10] pinctrl: ocelot: Add Sparx5 SoC support

This add support for Sparx5 pinctrl, using the ocelot drives as
basis. It adds pinconfig support as well, as supported by the
platform.

Reviewed-by: Alexandre Belloni <[email protected]>
Signed-off-by: Lars Povlsen <[email protected]>
---
drivers/pinctrl/pinctrl-ocelot.c | 431 ++++++++++++++++++++++++++++++-
1 file changed, 430 insertions(+), 1 deletion(-)

diff --git a/drivers/pinctrl/pinctrl-ocelot.c b/drivers/pinctrl/pinctrl-ocelot.c
index 95c225bc7572f..c2f8e35616278 100644
--- a/drivers/pinctrl/pinctrl-ocelot.c
+++ b/drivers/pinctrl/pinctrl-ocelot.c
@@ -25,6 +25,23 @@
#include "pinconf.h"
#include "pinmux.h"

+#define ocelot_clrsetbits(addr, clear, set) \
+ writel((readl(addr) & ~(clear)) | (set), (addr))
+
+/* PINCONFIG bits (sparx5 only) */
+enum {
+ PINCONF_BIAS,
+ PINCONF_SCHMITT,
+ PINCONF_DRIVE_STRENGTH,
+};
+
+#define BIAS_PD_BIT BIT(4)
+#define BIAS_PU_BIT BIT(3)
+#define BIAS_BITS (BIAS_PD_BIT|BIAS_PU_BIT)
+#define SCHMITT_BIT BIT(2)
+#define DRIVE_BITS GENMASK(1, 0)
+
+/* GPIO standard registers */
#define OCELOT_GPIO_OUT_SET 0x0
#define OCELOT_GPIO_OUT_CLR 0x4
#define OCELOT_GPIO_OUT 0x8
@@ -42,12 +59,17 @@
enum {
FUNC_NONE,
FUNC_GPIO,
+ FUNC_IRQ0,
FUNC_IRQ0_IN,
FUNC_IRQ0_OUT,
+ FUNC_IRQ1,
FUNC_IRQ1_IN,
FUNC_IRQ1_OUT,
+ FUNC_EXT_IRQ,
FUNC_MIIM,
+ FUNC_PHY_LED,
FUNC_PCI_WAKE,
+ FUNC_MD,
FUNC_PTP0,
FUNC_PTP1,
FUNC_PTP2,
@@ -59,24 +81,36 @@ enum {
FUNC_SG1,
FUNC_SG2,
FUNC_SI,
+ FUNC_SI2,
FUNC_TACHO,
FUNC_TWI,
FUNC_TWI2,
+ FUNC_TWI3,
FUNC_TWI_SCL_M,
FUNC_UART,
FUNC_UART2,
+ FUNC_UART3,
+ FUNC_PLL_STAT,
+ FUNC_EMMC,
+ FUNC_REF_CLK,
+ FUNC_RCVRD_CLK,
FUNC_MAX
};

static const char *const ocelot_function_names[] = {
[FUNC_NONE] = "none",
[FUNC_GPIO] = "gpio",
+ [FUNC_IRQ0] = "irq0",
[FUNC_IRQ0_IN] = "irq0_in",
[FUNC_IRQ0_OUT] = "irq0_out",
+ [FUNC_IRQ1] = "irq1",
[FUNC_IRQ1_IN] = "irq1_in",
[FUNC_IRQ1_OUT] = "irq1_out",
+ [FUNC_EXT_IRQ] = "ext_irq",
[FUNC_MIIM] = "miim",
+ [FUNC_PHY_LED] = "phy_led",
[FUNC_PCI_WAKE] = "pci_wake",
+ [FUNC_MD] = "md",
[FUNC_PTP0] = "ptp0",
[FUNC_PTP1] = "ptp1",
[FUNC_PTP2] = "ptp2",
@@ -88,12 +122,19 @@ static const char *const ocelot_function_names[] = {
[FUNC_SG1] = "sg1",
[FUNC_SG2] = "sg2",
[FUNC_SI] = "si",
+ [FUNC_SI2] = "si2",
[FUNC_TACHO] = "tacho",
[FUNC_TWI] = "twi",
[FUNC_TWI2] = "twi2",
+ [FUNC_TWI3] = "twi3",
[FUNC_TWI_SCL_M] = "twi_scl_m",
[FUNC_UART] = "uart",
[FUNC_UART2] = "uart2",
+ [FUNC_UART3] = "uart3",
+ [FUNC_PLL_STAT] = "pll_stat",
+ [FUNC_EMMC] = "emmc",
+ [FUNC_REF_CLK] = "ref_clk",
+ [FUNC_RCVRD_CLK] = "rcvrd_clk",
};

struct ocelot_pmx_func {
@@ -111,6 +152,7 @@ struct ocelot_pinctrl {
struct pinctrl_dev *pctl;
struct gpio_chip gpio_chip;
struct regmap *map;
+ void __iomem *pincfg;
struct pinctrl_desc *desc;
struct ocelot_pmx_func func[FUNC_MAX];
u8 stride;
@@ -324,6 +366,152 @@ static const struct pinctrl_pin_desc jaguar2_pins[] = {
JAGUAR2_PIN(63),
};

+#define SPARX5_P(p, f0, f1, f2) \
+static struct ocelot_pin_caps sparx5_pin_##p = { \
+ .pin = p, \
+ .functions = { \
+ FUNC_GPIO, FUNC_##f0, FUNC_##f1, FUNC_##f2 \
+ }, \
+}
+
+SPARX5_P(0, SG0, PLL_STAT, NONE);
+SPARX5_P(1, SG0, NONE, NONE);
+SPARX5_P(2, SG0, NONE, NONE);
+SPARX5_P(3, SG0, NONE, NONE);
+SPARX5_P(4, SG1, NONE, NONE);
+SPARX5_P(5, SG1, NONE, NONE);
+SPARX5_P(6, IRQ0_IN, IRQ0_OUT, SFP);
+SPARX5_P(7, IRQ1_IN, IRQ1_OUT, SFP);
+SPARX5_P(8, PTP0, NONE, SFP);
+SPARX5_P(9, PTP1, SFP, TWI_SCL_M);
+SPARX5_P(10, UART, NONE, NONE);
+SPARX5_P(11, UART, NONE, NONE);
+SPARX5_P(12, SG1, NONE, NONE);
+SPARX5_P(13, SG1, NONE, NONE);
+SPARX5_P(14, TWI, TWI_SCL_M, NONE);
+SPARX5_P(15, TWI, NONE, NONE);
+SPARX5_P(16, SI, TWI_SCL_M, SFP);
+SPARX5_P(17, SI, TWI_SCL_M, SFP);
+SPARX5_P(18, SI, TWI_SCL_M, SFP);
+SPARX5_P(19, PCI_WAKE, TWI_SCL_M, SFP);
+SPARX5_P(20, IRQ0_OUT, TWI_SCL_M, SFP);
+SPARX5_P(21, IRQ1_OUT, TACHO, SFP);
+SPARX5_P(22, TACHO, IRQ0_OUT, TWI_SCL_M);
+SPARX5_P(23, PWM, UART3, TWI_SCL_M);
+SPARX5_P(24, PTP2, UART3, TWI_SCL_M);
+SPARX5_P(25, PTP3, SI, TWI_SCL_M);
+SPARX5_P(26, UART2, SI, TWI_SCL_M);
+SPARX5_P(27, UART2, SI, TWI_SCL_M);
+SPARX5_P(28, TWI2, SI, SFP);
+SPARX5_P(29, TWI2, SI, SFP);
+SPARX5_P(30, SG2, SI, PWM);
+SPARX5_P(31, SG2, SI, TWI_SCL_M);
+SPARX5_P(32, SG2, SI, TWI_SCL_M);
+SPARX5_P(33, SG2, SI, SFP);
+SPARX5_P(34, NONE, TWI_SCL_M, EMMC);
+SPARX5_P(35, SFP, TWI_SCL_M, EMMC);
+SPARX5_P(36, SFP, TWI_SCL_M, EMMC);
+SPARX5_P(37, SFP, NONE, EMMC);
+SPARX5_P(38, NONE, TWI_SCL_M, EMMC);
+SPARX5_P(39, SI2, TWI_SCL_M, EMMC);
+SPARX5_P(40, SI2, TWI_SCL_M, EMMC);
+SPARX5_P(41, SI2, TWI_SCL_M, EMMC);
+SPARX5_P(42, SI2, TWI_SCL_M, EMMC);
+SPARX5_P(43, SI2, TWI_SCL_M, EMMC);
+SPARX5_P(44, SI, SFP, EMMC);
+SPARX5_P(45, SI, SFP, EMMC);
+SPARX5_P(46, NONE, SFP, EMMC);
+SPARX5_P(47, NONE, SFP, EMMC);
+SPARX5_P(48, TWI3, SI, SFP);
+SPARX5_P(49, TWI3, NONE, SFP);
+SPARX5_P(50, SFP, NONE, TWI_SCL_M);
+SPARX5_P(51, SFP, SI, TWI_SCL_M);
+SPARX5_P(52, SFP, MIIM, TWI_SCL_M);
+SPARX5_P(53, SFP, MIIM, TWI_SCL_M);
+SPARX5_P(54, SFP, PTP2, TWI_SCL_M);
+SPARX5_P(55, SFP, PTP3, PCI_WAKE);
+SPARX5_P(56, MIIM, SFP, TWI_SCL_M);
+SPARX5_P(57, MIIM, SFP, TWI_SCL_M);
+SPARX5_P(58, MIIM, SFP, TWI_SCL_M);
+SPARX5_P(59, MIIM, SFP, NONE);
+SPARX5_P(60, RECO_CLK, NONE, NONE);
+SPARX5_P(61, RECO_CLK, NONE, NONE);
+SPARX5_P(62, RECO_CLK, PLL_STAT, NONE);
+SPARX5_P(63, RECO_CLK, NONE, NONE);
+
+#define SPARX5_PIN(n) { \
+ .number = n, \
+ .name = "GPIO_"#n, \
+ .drv_data = &sparx5_pin_##n \
+}
+
+static const struct pinctrl_pin_desc sparx5_pins[] = {
+ SPARX5_PIN(0),
+ SPARX5_PIN(1),
+ SPARX5_PIN(2),
+ SPARX5_PIN(3),
+ SPARX5_PIN(4),
+ SPARX5_PIN(5),
+ SPARX5_PIN(6),
+ SPARX5_PIN(7),
+ SPARX5_PIN(8),
+ SPARX5_PIN(9),
+ SPARX5_PIN(10),
+ SPARX5_PIN(11),
+ SPARX5_PIN(12),
+ SPARX5_PIN(13),
+ SPARX5_PIN(14),
+ SPARX5_PIN(15),
+ SPARX5_PIN(16),
+ SPARX5_PIN(17),
+ SPARX5_PIN(18),
+ SPARX5_PIN(19),
+ SPARX5_PIN(20),
+ SPARX5_PIN(21),
+ SPARX5_PIN(22),
+ SPARX5_PIN(23),
+ SPARX5_PIN(24),
+ SPARX5_PIN(25),
+ SPARX5_PIN(26),
+ SPARX5_PIN(27),
+ SPARX5_PIN(28),
+ SPARX5_PIN(29),
+ SPARX5_PIN(30),
+ SPARX5_PIN(31),
+ SPARX5_PIN(32),
+ SPARX5_PIN(33),
+ SPARX5_PIN(34),
+ SPARX5_PIN(35),
+ SPARX5_PIN(36),
+ SPARX5_PIN(37),
+ SPARX5_PIN(38),
+ SPARX5_PIN(39),
+ SPARX5_PIN(40),
+ SPARX5_PIN(41),
+ SPARX5_PIN(42),
+ SPARX5_PIN(43),
+ SPARX5_PIN(44),
+ SPARX5_PIN(45),
+ SPARX5_PIN(46),
+ SPARX5_PIN(47),
+ SPARX5_PIN(48),
+ SPARX5_PIN(49),
+ SPARX5_PIN(50),
+ SPARX5_PIN(51),
+ SPARX5_PIN(52),
+ SPARX5_PIN(53),
+ SPARX5_PIN(54),
+ SPARX5_PIN(55),
+ SPARX5_PIN(56),
+ SPARX5_PIN(57),
+ SPARX5_PIN(58),
+ SPARX5_PIN(59),
+ SPARX5_PIN(60),
+ SPARX5_PIN(61),
+ SPARX5_PIN(62),
+ SPARX5_PIN(63),
+};
+
static int ocelot_get_functions_count(struct pinctrl_dev *pctldev)
{
return ARRAY_SIZE(ocelot_function_names);
@@ -382,6 +570,7 @@ static int ocelot_pinmux_set_mux(struct pinctrl_dev *pctldev,
* ALT[1]
* This is racy because both registers can't be updated at the same time
* but it doesn't matter much for now.
+ * Note: ALT0/ALT1 are organized specially for 64 gpio targets
*/
regmap_update_bits(info->map, REG_ALT(0, info, pin->pin),
BIT(p), f << p);
@@ -458,6 +647,220 @@ static int ocelot_pctl_get_group_pins(struct pinctrl_dev *pctldev,
return 0;
}

+static int ocelot_hw_get_value(struct ocelot_pinctrl *info,
+ unsigned int pin,
+ unsigned int reg,
+ int *val)
+{
+ int ret = -ENOTSUPP;
+
+ if (info->pincfg) {
+ u32 regcfg = readl(info->pincfg + (pin * sizeof(u32)));
+ u32 value;
+
+ ret = 0;
+ switch (reg) {
+ case PINCONF_BIAS:
+ value = regcfg & BIAS_BITS;
+ break;
+
+ case PINCONF_SCHMITT:
+ value = regcfg & SCHMITT_BIT;
+ break;
+
+ case PINCONF_DRIVE_STRENGTH:
+ value = regcfg & DRIVE_BITS;
+ break;
+
+ default:
+ ret = -ENOTSUPP;
+ break;
+ }
+ }
+ return ret;
+}
+
+static int ocelot_hw_set_value(struct ocelot_pinctrl *info,
+ unsigned int pin,
+ unsigned int reg,
+ int val)
+{
+ int ret = -ENOTSUPP;
+
+ if (info->pincfg) {
+ void __iomem *regaddr = info->pincfg + (pin * sizeof(u32));
+
+ ret = 0;
+ switch (reg) {
+ case PINCONF_BIAS:
+ ocelot_clrsetbits(regaddr, BIAS_BITS, val);
+ break;
+
+ case PINCONF_SCHMITT:
+ ocelot_clrsetbits(regaddr, SCHMITT_BIT, val);
+ break;
+
+ case PINCONF_DRIVE_STRENGTH:
+ if (val <= 3)
+ ocelot_clrsetbits(regaddr, DRIVE_BITS, val);
+ else
+ ret = -EINVAL;
+ break;
+
+ default:
+ ret = -ENOTSUPP;
+ break;
+ }
+ }
+ return ret;
+}
+
+static int ocelot_pinconf_get(struct pinctrl_dev *pctldev,
+ unsigned int pin, unsigned long *config)
+{
+ struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ u32 param = pinconf_to_config_param(*config);
+ int val, err;
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ case PIN_CONFIG_BIAS_PULL_UP:
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ err = ocelot_hw_get_value(info, pin, PINCONF_BIAS, &val);
+ if (err)
+ return err;
+ if (param == PIN_CONFIG_BIAS_DISABLE)
+ val = (val == 0 ? true : false);
+ else if (param == PIN_CONFIG_BIAS_PULL_DOWN)
+ val = (val & BIAS_PD_BIT ? true : false);
+ else /* PIN_CONFIG_BIAS_PULL_UP */
+ val = (val & BIAS_PU_BIT ? true : false);
+ break;
+
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ err = ocelot_hw_get_value(info, pin, PINCONF_SCHMITT, &val);
+ if (err)
+ return err;
+
+ val = (val & SCHMITT_BIT ? true : false);
+ break;
+
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ err = ocelot_hw_get_value(info, pin, PINCONF_DRIVE_STRENGTH,
+ &val);
+ if (err)
+ return err;
+ break;
+
+ case PIN_CONFIG_OUTPUT:
+ err = regmap_read(info->map, REG(OCELOT_GPIO_OUT, info, pin),
+ &val);
+ if (err)
+ return err;
+ val = !!(val & BIT(pin % 32));
+ break;
+
+ case PIN_CONFIG_INPUT_ENABLE:
+ case PIN_CONFIG_OUTPUT_ENABLE:
+ err = regmap_read(info->map, REG(OCELOT_GPIO_OE, info, pin),
+ &val);
+ if (err)
+ return err;
+ val = val & BIT(pin % 32);
+ if (param == PIN_CONFIG_OUTPUT_ENABLE)
+ val = !!val;
+ else
+ val = !val;
+ break;
+
+ default:
+ return -ENOTSUPP;
+ }
+
+ *config = pinconf_to_config_packed(param, val);
+
+ return 0;
+}
+
+noinline int ocelot_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+ unsigned long *configs, unsigned int num_configs)
+{
+ struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ u32 param, arg, p;
+ int cfg, err = 0;
+
+ for (cfg = 0; cfg < num_configs; cfg++) {
+ param = pinconf_to_config_param(configs[cfg]);
+ arg = pinconf_to_config_argument(configs[cfg]);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ case PIN_CONFIG_BIAS_PULL_UP:
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ arg = (param == PIN_CONFIG_BIAS_DISABLE) ? 0 :
+ (param == PIN_CONFIG_BIAS_PULL_UP) ? BIAS_PU_BIT :
+ BIAS_PD_BIT;
+
+ err = ocelot_hw_set_value(info, pin, PINCONF_BIAS, arg);
+ if (err)
+ goto err;
+
+ break;
+
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ arg = arg ? SCHMITT_BIT : 0;
+ err = ocelot_hw_set_value(info, pin, PINCONF_SCHMITT,
+ arg);
+ if (err)
+ goto err;
+
+ break;
+
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ err = ocelot_hw_set_value(info, pin,
+ PINCONF_DRIVE_STRENGTH,
+ arg);
+ if (err)
+ goto err;
+
+ break;
+
+ case PIN_CONFIG_OUTPUT_ENABLE:
+ case PIN_CONFIG_INPUT_ENABLE:
+ case PIN_CONFIG_OUTPUT:
+ p = pin % 32;
+ if (arg)
+ regmap_write(info->map,
+ REG(OCELOT_GPIO_OUT_SET, info,
+ pin),
+ BIT(p));
+ else
+ regmap_write(info->map,
+ REG(OCELOT_GPIO_OUT_CLR, info,
+ pin),
+ BIT(p));
+ regmap_update_bits(info->map,
+ REG(OCELOT_GPIO_OE, info, pin),
+ BIT(p),
+ param == PIN_CONFIG_INPUT_ENABLE ?
+ 0 : BIT(p));
+ break;
+
+ default:
+ err = -ENOTSUPP;
+ }
+ }
+err:
+ return err;
+}
+
+static const struct pinconf_ops ocelot_confops = {
+ .is_generic = true,
+ .pin_config_get = ocelot_pinconf_get,
+ .pin_config_set = ocelot_pinconf_set,
+ .pin_config_config_dbg_show = pinconf_generic_dump_config,
+};
+
static const struct pinctrl_ops ocelot_pctl_ops = {
.get_groups_count = ocelot_pctl_get_groups_count,
.get_group_name = ocelot_pctl_get_group_name,
@@ -484,6 +887,16 @@ static struct pinctrl_desc jaguar2_desc = {
.owner = THIS_MODULE,
};

+static struct pinctrl_desc sparx5_desc = {
+ .name = "sparx5-pinctrl",
+ .pins = sparx5_pins,
+ .npins = ARRAY_SIZE(sparx5_pins),
+ .pctlops = &ocelot_pctl_ops,
+ .pmxops = &ocelot_pmx_ops,
+ .confops = &ocelot_confops,
+ .owner = THIS_MODULE,
+};
+
static int ocelot_create_group_func_map(struct device *dev,
struct ocelot_pinctrl *info)
{
@@ -511,7 +924,8 @@ static int ocelot_create_group_func_map(struct device *dev,
}

for (i = 0; i < npins; i++)
- info->func[f].groups[i] = info->desc->pins[pins[i]].name;
+ info->func[f].groups[i] =
+ info->desc->pins[pins[i]].name;
}

kfree(pins);
@@ -744,6 +1158,7 @@ static int ocelot_gpiochip_register(struct platform_device *pdev,
static const struct of_device_id ocelot_pinctrl_of_match[] = {
{ .compatible = "mscc,ocelot-pinctrl", .data = &ocelot_desc },
{ .compatible = "mscc,jaguar2-pinctrl", .data = &jaguar2_desc },
+ { .compatible = "microchip,sparx5-pinctrl", .data = &sparx5_desc },
{},
};

@@ -752,6 +1167,7 @@ static int ocelot_pinctrl_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct ocelot_pinctrl *info;
void __iomem *base;
+ struct resource *res;
int ret;
struct regmap_config regmap_config = {
.reg_bits = 32,
@@ -773,6 +1189,7 @@ static int ocelot_pinctrl_probe(struct platform_device *pdev)
}

info->stride = 1 + (info->desc->npins - 1) / 32;
+
regmap_config.max_register = OCELOT_GPIO_SD_MAP * info->stride + 15 * 4;

info->map = devm_regmap_init_mmio(dev, base, &regmap_config);
@@ -783,6 +1200,16 @@ static int ocelot_pinctrl_probe(struct platform_device *pdev)
dev_set_drvdata(dev, info->map);
info->dev = dev;

+ /* Pinconf registers */
+ if (info->desc->confops) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(base))
+ dev_dbg(dev, "Failed to ioremap config registers (no extended pinconf)\n");
+ else
+ info->pincfg = base;
+ }
+
ret = ocelot_pinctrl_register(pdev, info);
if (ret)
return ret;
@@ -791,6 +1218,8 @@ static int ocelot_pinctrl_probe(struct platform_device *pdev)
if (ret)
return ret;

+ dev_info(dev, "driver registered\n");
+
return 0;
}

--
2.27.0

2020-06-09 08:10:52

by Lars Povlsen

[permalink] [raw]
Subject: [PATCH v2 06/10] dt-bindings: clock: sparx5: Add Sparx5 SoC DPLL clock

This add the DT bindings documentation for the Sparx5 SoC DPLL clock

Reviewed-by: Alexandre Belloni <[email protected]>
Signed-off-by: Lars Povlsen <[email protected]>
---
.../bindings/clock/microchip,sparx5-dpll.yaml | 52 +++++++++++++++++++
1 file changed, 52 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/microchip,sparx5-dpll.yaml

diff --git a/Documentation/devicetree/bindings/clock/microchip,sparx5-dpll.yaml b/Documentation/devicetree/bindings/clock/microchip,sparx5-dpll.yaml
new file mode 100644
index 0000000000000..39559a0a598ad
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/microchip,sparx5-dpll.yaml
@@ -0,0 +1,52 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/microchip,sparx5-dpll.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip Sparx5 DPLL Clock
+
+maintainers:
+ - Lars Povlsen <[email protected]>
+
+description: |
+ The Sparx5 DPLL clock controller generates and supplies clock to
+ various peripherals within the SoC.
+
+properties:
+ compatible:
+ const: microchip,sparx5-dpll
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ '#clock-cells':
+ const: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - '#clock-cells'
+
+additionalProperties: false
+
+examples:
+ # Clock provider for eMMC:
+ - |
+ lcpll_clk: lcpll-clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <2500000000>;
+ };
+ clks: clock-controller@61110000c {
+ compatible = "microchip,sparx5-dpll";
+ #clock-cells = <1>;
+ clocks = <&lcpll_clk>;
+ reg = <0x1110000c 0x24>;
+ };
+
+...
--
2.27.0

2020-06-09 08:11:01

by Lars Povlsen

[permalink] [raw]
Subject: [PATCH v2 08/10] clk: sparx5: Add Sparx5 SoC DPLL clock driver

This adds a device driver for the Sparx5 SoC DPLL clock

Reviewed-by: Alexandre Belloni <[email protected]>
Signed-off-by: Lars Povlsen <[email protected]>
---
drivers/clk/Makefile | 1 +
drivers/clk/clk-sparx5.c | 312 +++++++++++++++++++++++++++++++++++++++
2 files changed, 313 insertions(+)
create mode 100644 drivers/clk/clk-sparx5.c

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index ca9af11d33913..da8fcf147eb13 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_COMMON_CLK_CDCE925) += clk-cdce925.o
obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o
obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o
obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o
+obj-$(CONFIG_ARCH_SPARX5) += clk-sparx5.o
obj-$(CONFIG_COMMON_CLK_FIXED_MMIO) += clk-fixed-mmio.o
obj-$(CONFIG_COMMON_CLK_FSL_SAI) += clk-fsl-sai.o
obj-$(CONFIG_COMMON_CLK_GEMINI) += clk-gemini.o
diff --git a/drivers/clk/clk-sparx5.c b/drivers/clk/clk-sparx5.c
new file mode 100644
index 0000000000000..313d47bd87553
--- /dev/null
+++ b/drivers/clk/clk-sparx5.c
@@ -0,0 +1,312 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Microchip Sparx5 SoC Clock driver.
+ *
+ * Copyright (c) 2019 Microchip Inc.
+ *
+ * Author: Lars Povlsen <[email protected]>
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/clk-provider.h>
+#include <linux/bitfield.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <dt-bindings/clock/microchip,sparx5.h>
+
+#define PLL_DIV GENMASK(7, 0)
+#define PLL_PRE_DIV GENMASK(10, 8)
+#define PLL_ROT_DIR BIT(11)
+#define PLL_ROT_SEL GENMASK(13, 12)
+#define PLL_ROT_ENA BIT(14)
+#define PLL_CLK_ENA BIT(15)
+
+#define MAX_SEL 4
+#define MAX_PRE BIT(3)
+
+static const u8 sel_rates[MAX_SEL] = { 0, 2*8, 2*4, 2*2 };
+
+static const char *clk_names[N_CLOCKS] = {
+ "core", "ddr", "cpu2", "arm2",
+ "aux1", "aux2", "aux3", "aux4",
+ "synce",
+};
+
+struct s5_hw_clk {
+ struct clk_hw hw;
+ void __iomem *reg;
+ int index;
+};
+
+struct s5_clk_data {
+ void __iomem *base;
+ struct s5_hw_clk s5_hw[N_CLOCKS];
+};
+
+struct s5_pll_conf {
+ int freq;
+ u8 div;
+ bool rot_ena;
+ u8 rot_sel;
+ u8 rot_dir;
+ u8 pre_div;
+};
+
+#define to_s5_pll(hw) container_of(hw, struct s5_hw_clk, hw)
+
+static unsigned long s5_calc_freq(unsigned long parent_rate,
+ const struct s5_pll_conf *conf)
+{
+ unsigned long rate = parent_rate / conf->div;
+
+ if (conf->rot_ena) {
+ int sign = conf->rot_dir ? -1 : 1;
+ int divt = sel_rates[conf->rot_sel] * (1 + conf->pre_div);
+ int divb = divt + sign;
+
+ rate = mult_frac(rate, divt, divb);
+ rate = roundup(rate, 1000);
+ }
+
+ return rate;
+}
+
+static void s5_search_fractional(unsigned long rate,
+ unsigned long parent_rate,
+ int div,
+ struct s5_pll_conf *conf)
+{
+ struct s5_pll_conf best;
+ ulong cur_offset, best_offset = rate;
+ int d, i, j;
+
+ memset(conf, 0, sizeof(*conf));
+ conf->div = div;
+ conf->rot_ena = 1; /* Fractional rate */
+
+ for (d = 0; best_offset > 0 && d <= 1 ; d++) {
+ conf->rot_dir = !!d;
+ for (i = 0; best_offset > 0 && i < MAX_PRE; i++) {
+ conf->pre_div = i;
+ for (j = 1; best_offset > 0 && j < MAX_SEL; j++) {
+ conf->rot_sel = j;
+ conf->freq = s5_calc_freq(parent_rate, conf);
+ cur_offset = abs(rate - conf->freq);
+ if (cur_offset < best_offset) {
+ best_offset = cur_offset;
+ best = *conf;
+ }
+ }
+ }
+ }
+
+ /* Best match */
+ *conf = best;
+}
+
+static unsigned long s5_calc_params(unsigned long rate,
+ unsigned long parent_rate,
+ struct s5_pll_conf *conf)
+{
+ if (parent_rate % rate) {
+ struct s5_pll_conf alt1, alt2;
+ int div;
+
+ div = DIV_ROUND_CLOSEST_ULL(parent_rate, rate);
+ s5_search_fractional(rate, parent_rate, div, &alt1);
+
+ /* Straight match? */
+ if (alt1.freq == rate) {
+ *conf = alt1;
+ } else {
+ /* Try without rounding divider */
+ div = parent_rate / rate;
+ if (div != alt1.div) {
+ s5_search_fractional(rate, parent_rate, div,
+ &alt2);
+ /* Select the better match */
+ if (abs(rate - alt1.freq) <
+ abs(rate - alt2.freq))
+ *conf = alt1;
+ else
+ *conf = alt2;
+ }
+ }
+ } else {
+ /* Straight fit */
+ memset(conf, 0, sizeof(*conf));
+ conf->div = parent_rate / rate;
+ }
+
+ return conf->freq;
+}
+
+static int s5_pll_enable(struct clk_hw *hw)
+{
+ struct s5_hw_clk *pll = to_s5_pll(hw);
+ u32 val = readl(pll->reg);
+
+ val |= PLL_CLK_ENA;
+ writel(val, pll->reg);
+
+ return 0;
+}
+
+static void s5_pll_disable(struct clk_hw *hw)
+{
+ struct s5_hw_clk *pll = to_s5_pll(hw);
+ u32 val = readl(pll->reg);
+
+ val &= ~PLL_CLK_ENA;
+ writel(val, pll->reg);
+}
+
+static int s5_pll_set_rate(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct s5_hw_clk *pll = to_s5_pll(hw);
+ struct s5_pll_conf conf;
+ unsigned long eff_rate;
+ u32 val;
+
+ eff_rate = s5_calc_params(rate, parent_rate, &conf);
+ if (eff_rate != rate)
+ return -ENOTSUPP;
+
+ val = readl(pll->reg) & PLL_CLK_ENA;
+ val |= FIELD_PREP(PLL_DIV, conf.div);
+ if (conf.rot_ena) {
+ val |= PLL_ROT_ENA;
+ val |= FIELD_PREP(PLL_ROT_SEL, conf.rot_sel);
+ val |= FIELD_PREP(PLL_PRE_DIV, conf.pre_div);
+ if (conf.rot_dir)
+ val |= PLL_ROT_DIR;
+ }
+ writel(val, pll->reg);
+
+ return 0;
+}
+
+static unsigned long s5_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct s5_hw_clk *pll = to_s5_pll(hw);
+ struct s5_pll_conf conf;
+ u32 val;
+
+ val = readl(pll->reg);
+
+ if (val & PLL_CLK_ENA) {
+ conf.div = FIELD_GET(PLL_DIV, val);
+ conf.pre_div = FIELD_GET(PLL_PRE_DIV, val);
+ conf.rot_ena = FIELD_GET(PLL_ROT_ENA, val);
+ conf.rot_dir = FIELD_GET(PLL_ROT_DIR, val);
+ conf.rot_sel = FIELD_GET(PLL_ROT_SEL, val);
+
+ conf.freq = s5_calc_freq(parent_rate, &conf);
+ } else
+ conf.freq = 0;
+
+ return conf.freq;
+}
+
+static long s5_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct s5_pll_conf conf;
+
+ return s5_calc_params(rate, *parent_rate, &conf);
+}
+
+static const struct clk_ops s5_pll_ops = {
+ .enable = s5_pll_enable,
+ .disable = s5_pll_disable,
+ .set_rate = s5_pll_set_rate,
+ .round_rate = s5_pll_round_rate,
+ .recalc_rate = s5_pll_recalc_rate,
+};
+
+static struct clk_hw *s5_clk_hw_get(struct of_phandle_args *clkspec, void *data)
+{
+ struct s5_clk_data *s5_clk = data;
+ unsigned int idx = clkspec->args[0];
+
+ if (idx >= N_CLOCKS) {
+ pr_err("%s: invalid index %u\n", __func__, idx);
+ return ERR_PTR(-EINVAL);
+ }
+
+ return &s5_clk->s5_hw[idx].hw;
+}
+
+static int s5_clk_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ int i, ret;
+ struct s5_clk_data *s5_clk;
+ const char *parent_name;
+ struct clk_init_data init = {
+ .ops = &s5_pll_ops,
+ .parent_names = &parent_name,
+ .num_parents = 1,
+ };
+
+ s5_clk = devm_kzalloc(dev, sizeof(*s5_clk), GFP_KERNEL);
+ if (!s5_clk)
+ return -ENOMEM;
+
+ s5_clk->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(s5_clk->base))
+ return PTR_ERR(s5_clk->base);
+
+ parent_name = of_clk_get_parent_name(np, 0);
+ if (!parent_name) {
+ dev_err(dev, "%pOFn: missing parent clock\n", np);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < N_CLOCKS; i++) {
+ struct s5_hw_clk *s5_hw = &s5_clk->s5_hw[i];
+
+ init.name = clk_names[i];
+ s5_hw->index = i;
+ s5_hw->reg = s5_clk->base + (i * sizeof(u32));
+ s5_hw->hw.init = &init;
+ ret = devm_clk_hw_register(dev, &s5_hw->hw);
+ if (ret) {
+ dev_err(dev, "failed to register %s clock\n",
+ init.name);
+ return ret;
+ }
+ }
+
+ return of_clk_add_hw_provider(np, s5_clk_hw_get, s5_clk);
+}
+
+static int s5_clk_remove(struct platform_device *pdev)
+{
+ of_clk_del_provider(pdev->dev.of_node);
+
+ return 0;
+}
+
+static const struct of_device_id s5_clk_dt_ids[] = {
+ { .compatible = "microchip,sparx5-dpll", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, s5_clk_dt_ids);
+
+static struct platform_driver s5_clk_driver = {
+ .probe = s5_clk_probe,
+ .remove = s5_clk_remove,
+ .driver = {
+ .name = "sparx5-clk",
+ .of_match_table = s5_clk_dt_ids,
+ },
+};
+builtin_platform_driver(s5_clk_driver);
--
2.27.0

2020-06-09 08:11:21

by Lars Povlsen

[permalink] [raw]
Subject: [PATCH v2 09/10] arm64: dts: sparx5: Add Sparx5 SoC DPLL clock

This adds a DPLL clock to the Sparx5 SoC. It is used to generate clock
to misc peripherals, specifically the SDHCI/eMMC controller.

Reviewed-by: Alexandre Belloni <[email protected]>
Signed-off-by: Lars Povlsen <[email protected]>
---
arch/arm64/boot/dts/microchip/sparx5.dtsi | 37 ++++++++++++++---------
1 file changed, 23 insertions(+), 14 deletions(-)

diff --git a/arch/arm64/boot/dts/microchip/sparx5.dtsi b/arch/arm64/boot/dts/microchip/sparx5.dtsi
index baf4176ce1dfe..d4d7f9ce627bc 100644
--- a/arch/arm64/boot/dts/microchip/sparx5.dtsi
+++ b/arch/arm64/boot/dts/microchip/sparx5.dtsi
@@ -72,20 +72,29 @@ timer {
<GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
};

- clocks: clocks {
- #address-cells = <2>;
- #size-cells = <1>;
- ranges;
- ahb_clk: ahb-clk {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <250000000>;
- };
- sys_clk: sys-clk {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <625000000>;
- };
+ lcpll_clk: lcpll-clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <2500000000>;
+ };
+
+ clks: clock-controller@61110000c {
+ compatible = "microchip,sparx5-dpll";
+ #clock-cells = <1>;
+ clocks = <&lcpll_clk>;
+ reg = <0x6 0x1110000c 0x24>;
+ };
+
+ ahb_clk: ahb-clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <250000000>;
+ };
+
+ sys_clk: sys-clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <625000000>;
};

axi: axi@600000000 {
--
2.27.0

2020-06-09 08:12:05

by Lars Povlsen

[permalink] [raw]
Subject: [PATCH v2 10/10] arm64: dts: sparx5: Add i2c devices, i2c muxes

This patch adds i2c devices and muxes to the Sparx5 reference boards.

Reviewed-by: Alexandre Belloni <[email protected]>
Signed-off-by: Lars Povlsen <[email protected]>
---
arch/arm64/boot/dts/microchip/sparx5.dtsi | 36 +++
.../boot/dts/microchip/sparx5_pcb125.dts | 4 +
.../dts/microchip/sparx5_pcb134_board.dtsi | 237 ++++++++++++++++++
.../dts/microchip/sparx5_pcb135_board.dtsi | 77 ++++++
.../boot/dts/microchip/sparx5_pcb_common.dtsi | 4 +
5 files changed, 358 insertions(+)

diff --git a/arch/arm64/boot/dts/microchip/sparx5.dtsi b/arch/arm64/boot/dts/microchip/sparx5.dtsi
index d4d7f9ce627bc..cf712e80615da 100644
--- a/arch/arm64/boot/dts/microchip/sparx5.dtsi
+++ b/arch/arm64/boot/dts/microchip/sparx5.dtsi
@@ -171,7 +171,43 @@ uart2_pins: uart2-pins {
function = "uart2";
};

+ i2c_pins: i2c-pins {
+ pins = "GPIO_14", "GPIO_15";
+ function = "twi";
+ };
+
+ i2c2_pins: i2c2-pins {
+ pins = "GPIO_28", "GPIO_29";
+ function = "twi2";
+ };
+ };
+
+ i2c0: i2c@600101000 {
+ compatible = "snps,designware-i2c";
+ status = "disabled";
+ pinctrl-0 = <&i2c_pins>;
+ pinctrl-names = "default";
+ reg = <0x6 0x00101000 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+ i2c-sda-hold-time-ns = <300>;
+ clock-frequency = <100000>;
+ clocks = <&ahb_clk>;
};

+ i2c1: i2c@600103000 {
+ compatible = "snps,designware-i2c";
+ status = "disabled";
+ pinctrl-0 = <&i2c2_pins>;
+ pinctrl-names = "default";
+ reg = <0x6 0x00103000 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+ i2c-sda-hold-time-ns = <300>;
+ clock-frequency = <100000>;
+ clocks = <&ahb_clk>;
+ };
};
};
diff --git a/arch/arm64/boot/dts/microchip/sparx5_pcb125.dts b/arch/arm64/boot/dts/microchip/sparx5_pcb125.dts
index d7f985f7ee020..91ee5b6cfc37a 100644
--- a/arch/arm64/boot/dts/microchip/sparx5_pcb125.dts
+++ b/arch/arm64/boot/dts/microchip/sparx5_pcb125.dts
@@ -15,3 +15,7 @@ memory@0 {
reg = <0x00000000 0x00000000 0x10000000>;
};
};
+
+&i2c1 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/microchip/sparx5_pcb134_board.dtsi b/arch/arm64/boot/dts/microchip/sparx5_pcb134_board.dtsi
index 9b2aec400101b..18a535a043686 100644
--- a/arch/arm64/boot/dts/microchip/sparx5_pcb134_board.dtsi
+++ b/arch/arm64/boot/dts/microchip/sparx5_pcb134_board.dtsi
@@ -7,9 +7,246 @@
#include "sparx5_pcb_common.dtsi"

/{
+ aliases {
+ i2c0 = &i2c0;
+ i2c100 = &i2c100;
+ i2c101 = &i2c101;
+ i2c102 = &i2c102;
+ i2c103 = &i2c103;
+ i2c104 = &i2c104;
+ i2c105 = &i2c105;
+ i2c106 = &i2c106;
+ i2c107 = &i2c107;
+ i2c108 = &i2c108;
+ i2c109 = &i2c109;
+ i2c110 = &i2c110;
+ i2c111 = &i2c111;
+ i2c112 = &i2c112;
+ i2c113 = &i2c113;
+ i2c114 = &i2c114;
+ i2c115 = &i2c115;
+ i2c116 = &i2c116;
+ i2c117 = &i2c117;
+ i2c118 = &i2c118;
+ i2c119 = &i2c119;
+ };
+
gpio-restart {
compatible = "gpio-restart";
gpios = <&gpio 37 GPIO_ACTIVE_LOW>;
priority = <200>;
};
};
+
+&gpio {
+ i2cmux_pins_i: i2cmux-pins-i {
+ pins = "GPIO_16", "GPIO_17", "GPIO_18", "GPIO_19",
+ "GPIO_20", "GPIO_22", "GPIO_36", "GPIO_35",
+ "GPIO_50", "GPIO_51", "GPIO_56", "GPIO_57";
+ function = "twi_scl_m";
+ output-low;
+ };
+ i2cmux_0: i2cmux-0 {
+ pins = "GPIO_16";
+ function = "twi_scl_m";
+ output-high;
+ };
+ i2cmux_1: i2cmux-1 {
+ pins = "GPIO_17";
+ function = "twi_scl_m";
+ output-high;
+ };
+ i2cmux_2: i2cmux-2 {
+ pins = "GPIO_18";
+ function = "twi_scl_m";
+ output-high;
+ };
+ i2cmux_3: i2cmux-3 {
+ pins = "GPIO_19";
+ function = "twi_scl_m";
+ output-high;
+ };
+ i2cmux_4: i2cmux-4 {
+ pins = "GPIO_20";
+ function = "twi_scl_m";
+ output-high;
+ };
+ i2cmux_5: i2cmux-5 {
+ pins = "GPIO_22";
+ function = "twi_scl_m";
+ output-high;
+ };
+ i2cmux_6: i2cmux-6 {
+ pins = "GPIO_36";
+ function = "twi_scl_m";
+ output-high;
+ };
+ i2cmux_7: i2cmux-7 {
+ pins = "GPIO_35";
+ function = "twi_scl_m";
+ output-high;
+ };
+ i2cmux_8: i2cmux-8 {
+ pins = "GPIO_50";
+ function = "twi_scl_m";
+ output-high;
+ };
+ i2cmux_9: i2cmux-9 {
+ pins = "GPIO_51";
+ function = "twi_scl_m";
+ output-high;
+ };
+ i2cmux_10: i2cmux-10 {
+ pins = "GPIO_56";
+ function = "twi_scl_m";
+ output-high;
+ };
+ i2cmux_11: i2cmux-11 {
+ pins = "GPIO_57";
+ function = "twi_scl_m";
+ output-high;
+ };
+};
+
+&axi {
+ i2c0_imux: i2c0-imux@0 {
+ compatible = "i2c-mux-pinctrl";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ i2c-parent = <&i2c0>;
+ };
+ i2c0_emux: i2c0-emux@0 {
+ compatible = "i2c-mux-gpio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ i2c-parent = <&i2c0>;
+ };
+};
+
+&i2c0_imux {
+ pinctrl-names =
+ "i2c100", "i2c101", "i2c102", "i2c103",
+ "i2c104", "i2c105", "i2c106", "i2c107",
+ "i2c108", "i2c109", "i2c110", "i2c111", "idle";
+ pinctrl-0 = <&i2cmux_0>;
+ pinctrl-1 = <&i2cmux_1>;
+ pinctrl-2 = <&i2cmux_2>;
+ pinctrl-3 = <&i2cmux_3>;
+ pinctrl-4 = <&i2cmux_4>;
+ pinctrl-5 = <&i2cmux_5>;
+ pinctrl-6 = <&i2cmux_6>;
+ pinctrl-7 = <&i2cmux_7>;
+ pinctrl-8 = <&i2cmux_8>;
+ pinctrl-9 = <&i2cmux_9>;
+ pinctrl-10 = <&i2cmux_10>;
+ pinctrl-11 = <&i2cmux_11>;
+ pinctrl-12 = <&i2cmux_pins_i>;
+ i2c100: i2c_sfp1 {
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ i2c101: i2c_sfp2 {
+ reg = <0x1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ i2c102: i2c_sfp3 {
+ reg = <0x2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ i2c103: i2c_sfp4 {
+ reg = <0x3>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ i2c104: i2c_sfp5 {
+ reg = <0x4>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ i2c105: i2c_sfp6 {
+ reg = <0x5>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ i2c106: i2c_sfp7 {
+ reg = <0x6>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ i2c107: i2c_sfp8 {
+ reg = <0x7>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ i2c108: i2c_sfp9 {
+ reg = <0x8>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ i2c109: i2c_sfp10 {
+ reg = <0x9>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ i2c110: i2c_sfp11 {
+ reg = <0xa>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ i2c111: i2c_sfp12 {
+ reg = <0xb>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+};
+
+&i2c0_emux {
+ mux-gpios = <&gpio 55 GPIO_ACTIVE_HIGH
+ &gpio 60 GPIO_ACTIVE_HIGH
+ &gpio 61 GPIO_ACTIVE_HIGH
+ &gpio 54 GPIO_ACTIVE_HIGH>;
+ idle-state = <0x8>;
+ i2c112: i2c_sfp13 {
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ i2c113: i2c_sfp14 {
+ reg = <0x1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ i2c114: i2c_sfp15 {
+ reg = <0x2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ i2c115: i2c_sfp16 {
+ reg = <0x3>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ i2c116: i2c_sfp17 {
+ reg = <0x4>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ i2c117: i2c_sfp18 {
+ reg = <0x5>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ i2c118: i2c_sfp19 {
+ reg = <0x6>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ i2c119: i2c_sfp20 {
+ reg = <0x7>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/microchip/sparx5_pcb135_board.dtsi b/arch/arm64/boot/dts/microchip/sparx5_pcb135_board.dtsi
index 9b2aec400101b..d71f11a10b3d2 100644
--- a/arch/arm64/boot/dts/microchip/sparx5_pcb135_board.dtsi
+++ b/arch/arm64/boot/dts/microchip/sparx5_pcb135_board.dtsi
@@ -7,9 +7,86 @@
#include "sparx5_pcb_common.dtsi"

/{
+ aliases {
+ i2c0 = &i2c0;
+ i2c152 = &i2c152;
+ i2c153 = &i2c153;
+ i2c154 = &i2c154;
+ i2c155 = &i2c155;
+ };
+
gpio-restart {
compatible = "gpio-restart";
gpios = <&gpio 37 GPIO_ACTIVE_LOW>;
priority = <200>;
};
};
+
+&gpio {
+ i2cmux_pins_i: i2cmux-pins-i {
+ pins = "GPIO_35", "GPIO_36",
+ "GPIO_50", "GPIO_51";
+ function = "twi_scl_m";
+ output-low;
+ };
+ i2cmux_s29: i2cmux-0 {
+ pins = "GPIO_35";
+ function = "twi_scl_m";
+ output-high;
+ };
+ i2cmux_s30: i2cmux-1 {
+ pins = "GPIO_36";
+ function = "twi_scl_m";
+ output-high;
+ };
+ i2cmux_s31: i2cmux-2 {
+ pins = "GPIO_50";
+ function = "twi_scl_m";
+ output-high;
+ };
+ i2cmux_s32: i2cmux-3 {
+ pins = "GPIO_51";
+ function = "twi_scl_m";
+ output-high;
+ };
+};
+
+&axi {
+ i2c0_imux: i2c0-imux@0 {
+ compatible = "i2c-mux-pinctrl";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ i2c-parent = <&i2c0>;
+ };
+};
+
+&i2c0_imux {
+ pinctrl-names =
+ "i2c152", "i2c153", "i2c154", "i2c155",
+ "idle";
+ pinctrl-0 = <&i2cmux_s29>;
+ pinctrl-1 = <&i2cmux_s30>;
+ pinctrl-2 = <&i2cmux_s31>;
+ pinctrl-3 = <&i2cmux_s32>;
+ pinctrl-4 = <&i2cmux_pins_i>;
+ i2c152: i2c_sfp1 {
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ i2c153: i2c_sfp2 {
+ reg = <0x1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ i2c154: i2c_sfp3 {
+ reg = <0x2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ i2c155: i2c_sfp4 {
+ reg = <0x3>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/microchip/sparx5_pcb_common.dtsi b/arch/arm64/boot/dts/microchip/sparx5_pcb_common.dtsi
index 1f99d0db1284f..9d1a082de3e29 100644
--- a/arch/arm64/boot/dts/microchip/sparx5_pcb_common.dtsi
+++ b/arch/arm64/boot/dts/microchip/sparx5_pcb_common.dtsi
@@ -13,3 +13,7 @@ &uart0 {
&uart1 {
status = "okay";
};
+
+&i2c0 {
+ status = "okay";
+};
--
2.27.0

2020-06-09 08:14:19

by Lars Povlsen

[permalink] [raw]
Subject: [PATCH v2 07/10] dt-bindings: clock: sparx5: Add bindings include file

The Sparx5 support 9 different clock outputs. This include file has
defines for each supported clock ordinal.

Reviewed-by: Stephen Boyd <[email protected]>
Reviewed-by: Alexandre Belloni <[email protected]>
Signed-off-by: Lars Povlsen <[email protected]>
---
include/dt-bindings/clock/microchip,sparx5.h | 23 ++++++++++++++++++++
1 file changed, 23 insertions(+)
create mode 100644 include/dt-bindings/clock/microchip,sparx5.h

diff --git a/include/dt-bindings/clock/microchip,sparx5.h b/include/dt-bindings/clock/microchip,sparx5.h
new file mode 100644
index 0000000000000..4b04dabacec2c
--- /dev/null
+++ b/include/dt-bindings/clock/microchip,sparx5.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2019 Microchip Inc.
+ *
+ * Author: Lars Povlsen <[email protected]>
+ */
+
+#ifndef _DT_BINDINGS_CLK_SPARX5_H
+#define _DT_BINDINGS_CLK_SPARX5_H
+
+#define CLK_ID_CORE 0
+#define CLK_ID_DDR 1
+#define CLK_ID_CPU2 2
+#define CLK_ID_ARM2 3
+#define CLK_ID_AUX1 4
+#define CLK_ID_AUX2 5
+#define CLK_ID_AUX3 6
+#define CLK_ID_AUX4 7
+#define CLK_ID_SYNCE 8
+
+#define N_CLOCKS 9
+
+#endif
--
2.27.0

2020-06-09 09:10:09

by Lars Povlsen

[permalink] [raw]
Subject: [PATCH v2 02/10] arm64: sparx5: Add support for Microchip 2xA53 SoC

This adds support for the Microchip Sparx5 ARMv8-based SoC family of
TSN-capable gigabit switches.

Reviewed-by: Alexandre Belloni <[email protected]>
Signed-off-by: Lars Povlsen <[email protected]>
---
MAINTAINERS | 8 ++++++++
arch/arm64/Kconfig.platforms | 14 ++++++++++++++
2 files changed, 22 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 411cd97bb4858..3fe6f314df3e7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2111,6 +2111,14 @@ X: drivers/net/wireless/atmel/
N: at91
N: atmel

+ARM/Microchip Sparx5 SoC support
+M: Lars Povlsen <[email protected]>
+M: Steen Hegelund <[email protected]>
+M: Microchip Linux Driver Support <[email protected]>
+L: [email protected] (moderated for non-subscribers)
+N: sparx5
+S: Supported
+
ARM/MIOA701 MACHINE SUPPORT
M: Robert Jarzmik <[email protected]>
L: [email protected] (moderated for non-subscribers)
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 8dd05b2a925c5..8939e4e6e34c2 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -89,6 +89,20 @@ config ARCH_EXYNOS
help
This enables support for ARMv8 based Samsung Exynos SoC family.

+config ARCH_SPARX5
+ bool "ARMv8 based Microchip Sparx5 SoC family"
+ select PINCTRL
+ select DW_APB_TIMER_OF
+ help
+ This enables support for the Microchip Sparx5 ARMv8-based
+ SoC family of TSN-capable gigabit switches.
+
+ The SparX-5 Ethernet switch family provides a rich set of
+ switching features such as advanced TCAM-based VLAN and QoS
+ processing enabling delivery of differentiated services, and
+ security through TCAM-based frame processing using versatile
+ content aware processor (VCAP).
+
config ARCH_K3
bool "Texas Instruments Inc. K3 multicore SoC architecture"
select PM_GENERIC_DOMAINS if PM
--
2.27.0