All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/8] Support for Fujitsu MB86S7X SoCs
@ 2015-01-09 11:19 ` Vincent Yang
  0 siblings, 0 replies; 39+ messages in thread
From: Vincent Yang @ 2015-01-09 11:19 UTC (permalink / raw)
  To: devicetree, linux-arm-kernel
  Cc: mark.rutland, andy.green, linux, arnd, pawel.moll,
	ijc+devicetree, patches, Vincent Yang, jaswinder.singh, robh+dt,
	galak, olof

Hello,

  Fujitsu have a series of SoC already shipping based around
variations of 2xCA7+2xCA15 big.LITTLE architecture, and we would like
to upstream the basic support in this series.

  MB86S70 is a big.LITTLE platform with 2xCA7+2xCA15 and an additional
CM3 as the master. MB86S73 is a simple 2xCA7 and an additional CM3
master.

  The DT includes references to sdhci patches which are being sent to
the mmc list at the same time.

  We welcome any comments or questions.

Changes since v2:
* Minor cleanup of MCPM as suggested by Nicolas Pitre.

Changes since v1:
* Thanks to Arnd, modified clock driver to populate clocks only when
some user need them. Node name changed from "fujitsu,mb86s70-clk" to
"fujitsu,mb86s70-crg11" . Controller+Domain+Port of a clock are now
three cells specified by the user node.
* aliases moved into board DTS files
* Voltage supply moved as per-board DT node.
* Removed default overly verbose loglevel=8
* Specify -march=armv7-a flag for mcpm.c and smc.S that contain ARMv7
specific code.
* Removed wrongly put outer_flush_all(), now using standard
v7_exit_coherency_flush() instead of platform specific macro.
* Simplified GPIO offset calculations in gpio-mb86s70.c driver. And
added .remove() for the driver
* ARM MHU driver provided a .remove() to enable module unloading.
* A few other misc cleanups suggested in v1 submission.

Thanks.

Jassi Brar (8):
  ARM: Add platform support for Fujitsu MB86S7X SoCs
  mailbox: arm_mhu: add driver for ARM MHU controller
  ARM: MB86S7X: Add MCPM support
  clk: Add clock driver for mb86s7x
  gpio: Add Fujitsu MB86S7x GPIO driver
  dt: mb86s7x: add dt files for MB86S7x evbs
  of: add Fujitsu vendor prefix
  ARM: MB86S7x: Add configs

 Documentation/devicetree/bindings/arm/mb86s7x.txt  |   8 +
 .../bindings/clock/fujitsu,mb86s70-crg11.txt       |  26 +
 .../bindings/gpio/fujitsu,mb86s70-gpio.txt         |  20 +
 .../devicetree/bindings/mailbox/arm-mhu.txt        |  33 ++
 .../devicetree/bindings/soc/mb86s7x/scb_mhu.txt    |  35 ++
 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 MAINTAINERS                                        |   7 +
 arch/arm/Kconfig                                   |   2 +
 arch/arm/Makefile                                  |   1 +
 arch/arm/boot/dts/Makefile                         |   1 +
 arch/arm/boot/dts/mb86s70.dtsi                     |  91 ++++
 arch/arm/boot/dts/mb86s70eb.dts                    |  57 +++
 arch/arm/boot/dts/mb86s73.dtsi                     |  63 +++
 arch/arm/boot/dts/mb86s73eb.dts                    |  44 ++
 arch/arm/boot/dts/mb86s7x.dtsi                     | 140 ++++++
 arch/arm/configs/fujitsu_defconfig                 | 232 +++++++++
 arch/arm/configs/multi_v7_defconfig                |   5 +
 arch/arm/mach-mb86s7x/Kconfig                      |  19 +
 arch/arm/mach-mb86s7x/Makefile                     |   3 +
 arch/arm/mach-mb86s7x/board.c                      |  23 +
 arch/arm/mach-mb86s7x/mcpm.c                       | 315 ++++++++++++
 arch/arm/mach-mb86s7x/smc.S                        |  27 ++
 drivers/clk/Makefile                               |   1 +
 drivers/clk/clk-mb86s7x.c                          | 379 +++++++++++++++
 drivers/gpio/Kconfig                               |   6 +
 drivers/gpio/Makefile                              |   1 +
 drivers/gpio/gpio-mb86s7x.c                        | 231 +++++++++
 drivers/mailbox/Kconfig                            |   7 +
 drivers/mailbox/Makefile                           |   2 +
 drivers/mailbox/arm_mhu.c                          | 212 +++++++++
 drivers/soc/Makefile                               |   1 +
 drivers/soc/mb86s7x/Makefile                       |   4 +
 drivers/soc/mb86s7x/scb_mhu.c                      | 528 +++++++++++++++++++++
 include/soc/mb86s7x/scb_mhu.h                      | 105 ++++
 34 files changed, 2630 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/mb86s7x.txt
 create mode 100644 Documentation/devicetree/bindings/clock/fujitsu,mb86s70-crg11.txt
 create mode 100644 Documentation/devicetree/bindings/gpio/fujitsu,mb86s70-gpio.txt
 create mode 100644 Documentation/devicetree/bindings/mailbox/arm-mhu.txt
 create mode 100644 Documentation/devicetree/bindings/soc/mb86s7x/scb_mhu.txt
 create mode 100644 arch/arm/boot/dts/mb86s70.dtsi
 create mode 100644 arch/arm/boot/dts/mb86s70eb.dts
 create mode 100644 arch/arm/boot/dts/mb86s73.dtsi
 create mode 100644 arch/arm/boot/dts/mb86s73eb.dts
 create mode 100644 arch/arm/boot/dts/mb86s7x.dtsi
 create mode 100644 arch/arm/configs/fujitsu_defconfig
 create mode 100644 arch/arm/mach-mb86s7x/Kconfig
 create mode 100644 arch/arm/mach-mb86s7x/Makefile
 create mode 100644 arch/arm/mach-mb86s7x/board.c
 create mode 100644 arch/arm/mach-mb86s7x/mcpm.c
 create mode 100644 arch/arm/mach-mb86s7x/smc.S
 create mode 100644 drivers/clk/clk-mb86s7x.c
 create mode 100644 drivers/gpio/gpio-mb86s7x.c
 create mode 100644 drivers/mailbox/arm_mhu.c
 create mode 100644 drivers/soc/mb86s7x/Makefile
 create mode 100644 drivers/soc/mb86s7x/scb_mhu.c
 create mode 100644 include/soc/mb86s7x/scb_mhu.h

-- 
1.9.0

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v3 0/8] Support for Fujitsu MB86S7X SoCs
@ 2015-01-09 11:19 ` Vincent Yang
  0 siblings, 0 replies; 39+ messages in thread
From: Vincent Yang @ 2015-01-09 11:19 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

  Fujitsu have a series of SoC already shipping based around
variations of 2xCA7+2xCA15 big.LITTLE architecture, and we would like
to upstream the basic support in this series.

  MB86S70 is a big.LITTLE platform with 2xCA7+2xCA15 and an additional
CM3 as the master. MB86S73 is a simple 2xCA7 and an additional CM3
master.

  The DT includes references to sdhci patches which are being sent to
the mmc list at the same time.

  We welcome any comments or questions.

Changes since v2:
* Minor cleanup of MCPM as suggested by Nicolas Pitre.

Changes since v1:
* Thanks to Arnd, modified clock driver to populate clocks only when
some user need them. Node name changed from "fujitsu,mb86s70-clk" to
"fujitsu,mb86s70-crg11" . Controller+Domain+Port of a clock are now
three cells specified by the user node.
* aliases moved into board DTS files
* Voltage supply moved as per-board DT node.
* Removed default overly verbose loglevel=8
* Specify -march=armv7-a flag for mcpm.c and smc.S that contain ARMv7
specific code.
* Removed wrongly put outer_flush_all(), now using standard
v7_exit_coherency_flush() instead of platform specific macro.
* Simplified GPIO offset calculations in gpio-mb86s70.c driver. And
added .remove() for the driver
* ARM MHU driver provided a .remove() to enable module unloading.
* A few other misc cleanups suggested in v1 submission.

Thanks.

Jassi Brar (8):
  ARM: Add platform support for Fujitsu MB86S7X SoCs
  mailbox: arm_mhu: add driver for ARM MHU controller
  ARM: MB86S7X: Add MCPM support
  clk: Add clock driver for mb86s7x
  gpio: Add Fujitsu MB86S7x GPIO driver
  dt: mb86s7x: add dt files for MB86S7x evbs
  of: add Fujitsu vendor prefix
  ARM: MB86S7x: Add configs

 Documentation/devicetree/bindings/arm/mb86s7x.txt  |   8 +
 .../bindings/clock/fujitsu,mb86s70-crg11.txt       |  26 +
 .../bindings/gpio/fujitsu,mb86s70-gpio.txt         |  20 +
 .../devicetree/bindings/mailbox/arm-mhu.txt        |  33 ++
 .../devicetree/bindings/soc/mb86s7x/scb_mhu.txt    |  35 ++
 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 MAINTAINERS                                        |   7 +
 arch/arm/Kconfig                                   |   2 +
 arch/arm/Makefile                                  |   1 +
 arch/arm/boot/dts/Makefile                         |   1 +
 arch/arm/boot/dts/mb86s70.dtsi                     |  91 ++++
 arch/arm/boot/dts/mb86s70eb.dts                    |  57 +++
 arch/arm/boot/dts/mb86s73.dtsi                     |  63 +++
 arch/arm/boot/dts/mb86s73eb.dts                    |  44 ++
 arch/arm/boot/dts/mb86s7x.dtsi                     | 140 ++++++
 arch/arm/configs/fujitsu_defconfig                 | 232 +++++++++
 arch/arm/configs/multi_v7_defconfig                |   5 +
 arch/arm/mach-mb86s7x/Kconfig                      |  19 +
 arch/arm/mach-mb86s7x/Makefile                     |   3 +
 arch/arm/mach-mb86s7x/board.c                      |  23 +
 arch/arm/mach-mb86s7x/mcpm.c                       | 315 ++++++++++++
 arch/arm/mach-mb86s7x/smc.S                        |  27 ++
 drivers/clk/Makefile                               |   1 +
 drivers/clk/clk-mb86s7x.c                          | 379 +++++++++++++++
 drivers/gpio/Kconfig                               |   6 +
 drivers/gpio/Makefile                              |   1 +
 drivers/gpio/gpio-mb86s7x.c                        | 231 +++++++++
 drivers/mailbox/Kconfig                            |   7 +
 drivers/mailbox/Makefile                           |   2 +
 drivers/mailbox/arm_mhu.c                          | 212 +++++++++
 drivers/soc/Makefile                               |   1 +
 drivers/soc/mb86s7x/Makefile                       |   4 +
 drivers/soc/mb86s7x/scb_mhu.c                      | 528 +++++++++++++++++++++
 include/soc/mb86s7x/scb_mhu.h                      | 105 ++++
 34 files changed, 2630 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/mb86s7x.txt
 create mode 100644 Documentation/devicetree/bindings/clock/fujitsu,mb86s70-crg11.txt
 create mode 100644 Documentation/devicetree/bindings/gpio/fujitsu,mb86s70-gpio.txt
 create mode 100644 Documentation/devicetree/bindings/mailbox/arm-mhu.txt
 create mode 100644 Documentation/devicetree/bindings/soc/mb86s7x/scb_mhu.txt
 create mode 100644 arch/arm/boot/dts/mb86s70.dtsi
 create mode 100644 arch/arm/boot/dts/mb86s70eb.dts
 create mode 100644 arch/arm/boot/dts/mb86s73.dtsi
 create mode 100644 arch/arm/boot/dts/mb86s73eb.dts
 create mode 100644 arch/arm/boot/dts/mb86s7x.dtsi
 create mode 100644 arch/arm/configs/fujitsu_defconfig
 create mode 100644 arch/arm/mach-mb86s7x/Kconfig
 create mode 100644 arch/arm/mach-mb86s7x/Makefile
 create mode 100644 arch/arm/mach-mb86s7x/board.c
 create mode 100644 arch/arm/mach-mb86s7x/mcpm.c
 create mode 100644 arch/arm/mach-mb86s7x/smc.S
 create mode 100644 drivers/clk/clk-mb86s7x.c
 create mode 100644 drivers/gpio/gpio-mb86s7x.c
 create mode 100644 drivers/mailbox/arm_mhu.c
 create mode 100644 drivers/soc/mb86s7x/Makefile
 create mode 100644 drivers/soc/mb86s7x/scb_mhu.c
 create mode 100644 include/soc/mb86s7x/scb_mhu.h

-- 
1.9.0

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v3 1/8] ARM: Add platform support for Fujitsu MB86S7X SoCs
  2015-01-09 11:19 ` Vincent Yang
@ 2015-01-09 11:24     ` Vincent Yang
  -1 siblings, 0 replies; 39+ messages in thread
From: Vincent Yang @ 2015-01-09 11:24 UTC (permalink / raw)
  To: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: arnd-r2nGTMty4D4, olof-nZhT3qVonbNeoWH0uzbU5w,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	pawel.moll-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
	ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ, andy.green-QSEj5FYQhm4dnm+yROfE0A,
	patches-QSEj5FYQhm4dnm+yROfE0A,
	jaswinder.singh-QSEj5FYQhm4dnm+yROfE0A, Vincent Yang,
	Tetsuya Nuriya

From: Jassi Brar <jaswinder.singh-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

The MB86S7X is a bigLITTLE configuration of 2xCA7 & 2xCA15 under Linux.
And the remote master firmware (called SCB) running on CM3. Linux asks
for things to be done over Mailbox API, to SCB which controls most of
the important things. variations S70 & S73 are supported.

Signed-off-by: Andy Green <andy.green-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Signed-off-by: Jassi Brar <jaswinder.singh-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Signed-off-by: Vincent Yang <Vincent.Yang-l16TxrwUIHTQFUHtdCDX3A@public.gmane.org>
Signed-off-by: Tetsuya Nuriya <nuriya.tetsuya-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
---
 Documentation/devicetree/bindings/arm/mb86s7x.txt  |   8 +
 .../devicetree/bindings/soc/mb86s7x/scb_mhu.txt    |  35 ++
 MAINTAINERS                                        |   7 +
 arch/arm/Kconfig                                   |   2 +
 arch/arm/Makefile                                  |   1 +
 arch/arm/mach-mb86s7x/Kconfig                      |  19 +
 arch/arm/mach-mb86s7x/Makefile                     |   1 +
 arch/arm/mach-mb86s7x/board.c                      |  23 +
 drivers/soc/Makefile                               |   1 +
 drivers/soc/mb86s7x/Makefile                       |   4 +
 drivers/soc/mb86s7x/scb_mhu.c                      | 514 +++++++++++++++++++++
 include/soc/mb86s7x/scb_mhu.h                      |  97 ++++
 12 files changed, 712 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/mb86s7x.txt
 create mode 100644 Documentation/devicetree/bindings/soc/mb86s7x/scb_mhu.txt
 create mode 100644 arch/arm/mach-mb86s7x/Kconfig
 create mode 100644 arch/arm/mach-mb86s7x/Makefile
 create mode 100644 arch/arm/mach-mb86s7x/board.c
 create mode 100644 drivers/soc/mb86s7x/Makefile
 create mode 100644 drivers/soc/mb86s7x/scb_mhu.c
 create mode 100644 include/soc/mb86s7x/scb_mhu.h

diff --git a/Documentation/devicetree/bindings/arm/mb86s7x.txt b/Documentation/devicetree/bindings/arm/mb86s7x.txt
new file mode 100644
index 0000000..fbaad20
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mb86s7x.txt
@@ -0,0 +1,8 @@
+Fujitsu MB86S7X Device Tree Bindings
+
+Fujitsu has a few closely related platforms that are basically different
+configurations of each others. Like MB86S7{0,1,2,3}.
+
+The EVB boards with S70/S73 have the following property:
+Required root node property:
+	compatible: must contain "fujitsu,mb86s70-evb" or "fujitsu,mb86s73-evb"
diff --git a/Documentation/devicetree/bindings/soc/mb86s7x/scb_mhu.txt b/Documentation/devicetree/bindings/soc/mb86s7x/scb_mhu.txt
new file mode 100644
index 0000000..adee45c
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/mb86s7x/scb_mhu.txt
@@ -0,0 +1,35 @@
+Fujitsu SCB (Mailbox's Remote Firmware) bindings
+------------------------------------------------
+
+The firmware (running of a remote Cortex-M3 master) on Fujitsu's MB86S7X
+platforms is named SCB. The SCB owns most of core h/w IPs like Clock,
+CPUFreq/DVFS, CPUIdle/SMP, Thermal, a recovery block device and even an
+I2C controller. Linux has to map all of these functionalities on to
+the Mailbox API and get things done by the remote master.
+ Let the current state of SCB firmware be versioned 1.0.
+
+Required properties :
+- compatible : Shall contain "fujitsu,mb86s70-scb-1.0"
+- reg : Point to SharedMemory used for Mailbox protocol.
+- mboxes : phandle to the mailbox controller:channel node.
+
+The consumer specifies the desired clock pointing to its phandle.
+
+Example:
+
+	mhu: mhu0@2b1f0000 {
+		#mbox-cells = <1>;
+		compatible = "arm,mbox-mhu";
+		reg = <0 0x2b1f0000 0x1000>;
+		interrupts = <0 36 4>, /* LP Non-Sec */
+			     <0 35 4>, /* HP Non-Sec */
+			     <0 37 4>; /* Secure */
+		clocks = <&clk 0 2 1>;
+		clock-names = "clk";
+	};
+
+	mhu_client: scb@2e000000 {
+		compatible = "fujitsu,mb86s70-scb-1.0";
+		reg = <0 0x2e000000 0x4000>; /* SHM for IPC */
+		mboxes = <&mhu 1>;
+	};
diff --git a/MAINTAINERS b/MAINTAINERS
index ddb9ac8..a57c74c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1108,6 +1108,13 @@ M:	Lennert Buytenhek <kernel-OLH4Qvv75CYX/NnBR394Jw@public.gmane.org>
 L:	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org (moderated for non-subscribers)
 S:	Maintained
 
+ARM/MB86S7X SOC SUPPORT
+M:	Vincent Yang <Vincent.Yang-l16TxrwUIHTQFUHtdCDX3A@public.gmane.org>
+M:	Tetsuya Nuriya <nuriya.tetsuya-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
+L:	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org (moderated for non-subscribers)
+S:	Supported
+F:	arch/arm/mach-mb86s7x/
+
 ARM/TEXAS INSTRUMENT KEYSTONE ARCHITECTURE
 M:	Santosh Shilimkar <ssantosh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
 L:	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org (moderated for non-subscribers)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 97d07ed..3c80a9b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -884,6 +884,8 @@ source "arch/arm/mach-keystone/Kconfig"
 
 source "arch/arm/mach-ks8695/Kconfig"
 
+source "arch/arm/mach-mb86s7x/Kconfig"
+
 source "arch/arm/mach-meson/Kconfig"
 
 source "arch/arm/mach-msm/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index c1785ee..c65aff2 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -167,6 +167,7 @@ machine-$(CONFIG_ARCH_IXP4XX)		+= ixp4xx
 machine-$(CONFIG_ARCH_KEYSTONE)		+= keystone
 machine-$(CONFIG_ARCH_KS8695)		+= ks8695
 machine-$(CONFIG_ARCH_LPC32XX)		+= lpc32xx
+machine-$(CONFIG_ARCH_MB86S7X)		+= mb86s7x
 machine-$(CONFIG_ARCH_MESON)		+= meson
 machine-$(CONFIG_ARCH_MMP)		+= mmp
 machine-$(CONFIG_ARCH_MOXART)		+= moxart
diff --git a/arch/arm/mach-mb86s7x/Kconfig b/arch/arm/mach-mb86s7x/Kconfig
new file mode 100644
index 0000000..f58b104
--- /dev/null
+++ b/arch/arm/mach-mb86s7x/Kconfig
@@ -0,0 +1,19 @@
+config ARCH_MB86S7X
+	bool "Fujitsu MB86S7x platforms" if ARCH_MULTI_V7
+	select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
+	select ARCH_HAS_CPUFREQ
+	select ARCH_HAS_OPP
+	select ARCH_REQUIRE_GPIOLIB
+	select ARM_AMBA
+	select ARM_CCI
+	select ARM_GIC
+	select ARM_TIMER_SP804
+	select BIG_LITTLE
+	select HAVE_ARM_ARCH_TIMER
+	select MAILBOX
+	select PINCTRL
+	select PINCTRL_MB86S7X
+	select PM_OPP
+	select ZONE_DMA if ARM_LPAE
+	help
+	  Support for Fujitsu MB86S7x based platforms
diff --git a/arch/arm/mach-mb86s7x/Makefile b/arch/arm/mach-mb86s7x/Makefile
new file mode 100644
index 0000000..97640b6
--- /dev/null
+++ b/arch/arm/mach-mb86s7x/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ARCH_MB86S7X)	+= board.o
diff --git a/arch/arm/mach-mb86s7x/board.c b/arch/arm/mach-mb86s7x/board.c
new file mode 100644
index 0000000..222b63f
--- /dev/null
+++ b/arch/arm/mach-mb86s7x/board.c
@@ -0,0 +1,23 @@
+/*
+ * Support for the Fujitsu's MB86S7x based devices.
+ *
+ * Copyright (C) 2015 Linaro, LTD
+ *
+ * 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, version 2 of the License.
+ *
+ */
+
+#include <linux/of.h>
+#include <asm/mach/arch.h>
+
+static const char *mb86s7x_dt_match[] __initconst = {
+	"fujitsu,mb86s70-evb",
+	"fujitsu,mb86s73-evb",
+	NULL,
+};
+
+DT_MACHINE_START(MB86S7X_DT, "Fujitsu MB86S7X-based board")
+	.dt_compat	= mb86s7x_dt_match,
+MACHINE_END
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 063113d..fb64bf2 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -2,6 +2,7 @@
 # Makefile for the Linux Kernel SOC specific device drivers.
 #
 
+obj-$(CONFIG_ARCH_MB86S7X)	+= mb86s7x/
 obj-$(CONFIG_ARCH_QCOM)		+= qcom/
 obj-$(CONFIG_ARCH_TEGRA)	+= tegra/
 obj-$(CONFIG_SOC_TI)		+= ti/
diff --git a/drivers/soc/mb86s7x/Makefile b/drivers/soc/mb86s7x/Makefile
new file mode 100644
index 0000000..f6b96cf
--- /dev/null
+++ b/drivers/soc/mb86s7x/Makefile
@@ -0,0 +1,4 @@
+#
+# Fujitsu's MB86S7X drivers
+#
+obj-$(CONFIG_ARCH_MB86S7X)	+= scb_mhu.o
diff --git a/drivers/soc/mb86s7x/scb_mhu.c b/drivers/soc/mb86s7x/scb_mhu.c
new file mode 100644
index 0000000..08a3c88
--- /dev/null
+++ b/drivers/soc/mb86s7x/scb_mhu.c
@@ -0,0 +1,514 @@
+/*
+ * arch/arm/mach-mb86s7x/scb_mhu.c Shim 'server' for Mailbox clients
+ *
+ * Created by: Jassi Brar <jassisinghbrar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ * Copyright:	(C) 2013-2015 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/reboot.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/of_address.h>
+#include <linux/mailbox_client.h>
+#include <linux/platform_device.h>
+
+#include <soc/mb86s7x/scb_mhu.h>
+
+#include <asm/system_misc.h>
+
+#define INTR_STAT_OFS	0x0
+#define INTR_SET_OFS	0x8
+#define INTR_CLR_OFS	0x10
+
+static LIST_HEAD(free_xfers);
+static LIST_HEAD(pending_xfers);
+static DEFINE_SPINLOCK(fsm_lock);
+static struct completion fsm_rsp;
+static struct mbox_client mhu_cl;
+static struct mbox_chan *mhu_chan;
+static mb86s7x_mhu_handler_t handler[MHU_NUM_CMDS];
+
+static void __iomem *mhu_base, *mb86s7x_shm_base;
+static void __iomem *cmd_to_scb, *rsp_to_scb;
+static void __iomem *cmd_from_scb, *rsp_from_scb;
+
+static enum {
+	MHU_PARK = 0,
+	MHU_WRR, /* Waiting to get Remote's Reply */
+	MHU_WRL, /* Waiting to send Reply */
+	MHU_WRRL, /* WAIT_Ra && WAIT_Rb */
+	MHU_INVLD,
+} fsm_state;
+
+enum fsm_event {
+	EV_LC = 0, /* Local sent a command */
+	EV_RC, /* Remote sent a command */
+	EV_RR, /* Remote sent a reply */
+	EV_LR, /* Local sent a reply */
+};
+
+static int mhu_fsm[4][4] = {
+	[MHU_PARK] = {
+		[EV_LC] = MHU_WRR,
+		[EV_RC] = MHU_WRL,
+		[EV_RR] = MHU_INVLD,
+		[EV_LR] = MHU_INVLD,
+	},
+	[MHU_WRR] = {
+		[EV_LC] = MHU_INVLD,
+		[EV_RC] = MHU_WRRL,
+		[EV_RR] = MHU_PARK,
+		[EV_LR] = MHU_INVLD,
+	},
+	[MHU_WRL] = {
+		[EV_LC] = MHU_WRRL,
+		[EV_RC] = MHU_INVLD,
+		[EV_RR] = MHU_INVLD,
+		[EV_LR] = MHU_PARK,
+	},
+	[MHU_WRRL] = {
+		[EV_LC] = MHU_INVLD,
+		[EV_RC] = MHU_INVLD,
+		[EV_RR] = MHU_WRL,
+		[EV_LR] = MHU_WRR,
+	},
+};
+
+static struct mhu_xfer {
+	int code;
+	int len;
+	void *buf;
+	struct completion *c;
+	struct list_head node;
+} *ax; /* stages of xfer */
+
+static int mhu_alloc_xfers(int n, struct list_head *list)
+{
+	struct mhu_xfer *x = kcalloc(n, sizeof(struct mhu_xfer), GFP_ATOMIC);
+	int i;
+
+	if (!x)
+		return -ENOMEM;
+
+	for (i = 0; i < n; i++)
+		list_add(&x[i].node, &free_xfers);
+
+	return 0;
+}
+
+static void got_data(u32 code)
+{
+	mb86s7x_mhu_handler_t hndlr = NULL;
+	unsigned long flags;
+	int ev;
+
+	if (code & RESP_BIT)
+		ev = EV_RR;
+	else
+		ev = EV_RC;
+
+	spin_lock_irqsave(&fsm_lock, flags);
+
+	if (mhu_fsm[fsm_state][ev] == MHU_INVLD) {
+		spin_unlock_irqrestore(&fsm_lock, flags);
+		pr_err("State-%d EV-%d FSM Broken!\n", fsm_state, ev);
+		return;
+	}
+	fsm_state = mhu_fsm[fsm_state][ev];
+
+	if (code & RESP_BIT) {
+		memcpy_fromio(ax->buf, rsp_from_scb, ax->len);
+		if (ax->c)
+			complete(ax->c);
+		list_move(&ax->node, &free_xfers);
+		ax = NULL;
+	} else {
+		/* Find and dispatch relevant registered handler */
+		if (code < MHU_NUM_CMDS)
+			hndlr = handler[code];
+		if (hndlr)
+			hndlr(code, cmd_from_scb);
+		else
+			pr_err("No handler for CMD_%u\n", code);
+	}
+
+	spin_unlock_irqrestore(&fsm_lock, flags);
+}
+
+static int do_xfer(void)
+{
+	unsigned long flags;
+	struct mhu_xfer *x;
+	int ev, code;
+
+	spin_lock_irqsave(&fsm_lock, flags);
+
+	if (list_empty(&pending_xfers)) {
+		struct mbox_chan *_ch = NULL;
+		int cmd;
+
+		for (cmd = 0; cmd < MHU_NUM_CMDS && !handler[cmd]; cmd++)
+			;
+		/* Don't free channel if any user is listening */
+		if (cmd != MHU_NUM_CMDS) {
+			spin_unlock_irqrestore(&fsm_lock, flags);
+			return 0;
+		}
+
+		if (fsm_state == MHU_PARK) {
+			_ch = mhu_chan;
+			mhu_chan = NULL;
+		}
+
+		spin_unlock_irqrestore(&fsm_lock, flags);
+
+		if (_ch)
+			mbox_free_channel(_ch);
+
+		return 0;
+	}
+
+	x = list_first_entry(&pending_xfers, struct mhu_xfer, node);
+	code = x->code;
+
+	ev = code & RESP_BIT ? EV_LR : EV_LC;
+	if (mhu_fsm[fsm_state][ev] == MHU_INVLD) {
+		spin_unlock_irqrestore(&fsm_lock, flags);
+		return 1;
+	}
+	list_del_init(&x->node);
+
+	/* Layout the SHM */
+	if (code & RESP_BIT)
+		memcpy_toio(rsp_to_scb, x->buf, x->len);
+	else
+		memcpy_toio(cmd_to_scb, x->buf, x->len);
+
+	if (ev == EV_LC)
+		ax = x;
+	else
+		list_move(&x->node, &free_xfers);
+	fsm_state = mhu_fsm[fsm_state][ev];
+
+	spin_unlock_irqrestore(&fsm_lock, flags);
+
+	/* Prefer mailbox API */
+	if (!mhu_chan) {
+		struct mbox_chan *_ch;
+
+		_ch = mbox_request_channel(&mhu_cl, 0);
+		if (!IS_ERR(_ch))
+			mhu_chan = _ch;
+	}
+
+	if (mhu_chan) {
+		int ret;
+
+		init_completion(&fsm_rsp);
+
+		/* Send via generic api */
+		ret = mbox_send_message(mhu_chan, (void *)code);
+		if (ret < 0) {
+			pr_err("%s:%d CMD_%d Send Failed\n",
+			       __func__, __LINE__, code);
+			BUG();
+		}
+		if (!(code & RESP_BIT)) {
+			ret = wait_for_completion_timeout(&fsm_rsp,
+						msecs_to_jiffies(1000));
+			if (!ret) {
+				pr_err("%s:%d CMD_%d Got No Reply\n",
+				       __func__, __LINE__, code);
+				BUG();
+			}
+			got_data(ax->code);
+		}
+	} else {
+		void __iomem *tx_reg = mhu_base + 0x120; /* HP-NonSec */
+		void __iomem *rx_reg = mhu_base + 0x20; /* HP-NonSec */
+		u32 val, count;
+
+		/* Send via early-boot api */
+		val = readl_relaxed(tx_reg + INTR_STAT_OFS);
+		if (val) {
+			pr_err("Last CMD not yet read by SCB\n");
+			writel_relaxed(val, tx_reg + INTR_CLR_OFS);
+		}
+
+		writel_relaxed(x->code, tx_reg + INTR_SET_OFS);
+
+		/* Wait until this message is read */
+		count = 0x1000000;
+		do {
+			cpu_relax();
+			val = readl_relaxed(tx_reg + INTR_STAT_OFS);
+		} while (--count && val);
+		if (val)
+			pr_err("%s:%d SCB not listening!\n",
+			       __func__, __LINE__);
+
+		if (!ax) {
+			/* A quick poll for pending remote cmd */
+			val = readl_relaxed(rx_reg + INTR_STAT_OFS);
+			if (val) {
+				got_data(val);
+				writel_relaxed(val, rx_reg + INTR_CLR_OFS);
+			}
+		} else {
+			do {
+				/* Wait until we get reply */
+				count = 0x1000000;
+				do {
+					cpu_relax();
+					val = readl_relaxed(
+						rx_reg + INTR_STAT_OFS);
+				} while (--count && !val);
+
+				if (val) {
+					got_data(val);
+					writel_relaxed(val,
+						     rx_reg + INTR_CLR_OFS);
+				} else {
+					pr_err("%s:%d SCB didn't reply\n",
+					       __func__, __LINE__);
+					return 1;
+				}
+			} while (!(val & RESP_BIT));
+		}
+		if (list_empty(&pending_xfers))
+			return 0;
+	}
+
+	return do_xfer();
+}
+
+static void mhu_recv(struct mbox_client *cl, void *data)
+{
+	if ((u32)data & RESP_BIT) {
+		/* Now that we got a reply to last TX, that
+		 * must mean the last TX was successful */
+		mbox_client_txdone(mhu_chan, 0);
+
+		ax->code = (u32)data; /* Save response */
+		complete(&fsm_rsp);
+		return;
+	}
+
+	got_data((u32)data);
+}
+
+int mb86s7x_hndlr_set(u32 cmd, mb86s7x_mhu_handler_t hndlr)
+{
+	unsigned long flags;
+	int ret = -EINVAL;
+
+	spin_lock_irqsave(&fsm_lock, flags);
+	if (cmd < MHU_NUM_CMDS && !handler[cmd]) {
+		ret = 0;
+		handler[cmd] = hndlr;
+	}
+	spin_unlock_irqrestore(&fsm_lock, flags);
+
+	if (!mhu_chan) {
+		struct mbox_chan *_ch;
+
+		_ch = mbox_request_channel(&mhu_cl, 0);
+		if (!IS_ERR(_ch))
+			mhu_chan = _ch;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(mb86s7x_hndlr_set);
+
+void mb86s7x_hndlr_clr(u32 cmd, mb86s7x_mhu_handler_t hndlr)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&fsm_lock, flags);
+
+	if (cmd < MHU_NUM_CMDS && handler[cmd] == hndlr)
+		handler[cmd] = NULL;
+
+	if (list_empty(&pending_xfers)) {
+		struct mbox_chan *_ch = NULL;
+
+		for (cmd = 0; cmd < MHU_NUM_CMDS && !handler[cmd]; cmd++)
+			;
+		/* Don't free channel if any user is listening */
+		if (cmd != MHU_NUM_CMDS) {
+			spin_unlock_irqrestore(&fsm_lock, flags);
+			return;
+		}
+
+		if (fsm_state == MHU_PARK) {
+			_ch = mhu_chan;
+			mhu_chan = NULL;
+		}
+
+		spin_unlock_irqrestore(&fsm_lock, flags);
+
+		if (_ch)
+			mbox_free_channel(_ch);
+
+		return;
+	}
+	spin_unlock_irqrestore(&fsm_lock, flags);
+}
+EXPORT_SYMBOL_GPL(mb86s7x_hndlr_clr);
+
+static int setup_mhu(void)
+{
+	struct device_node *node;
+
+	node = of_find_compatible_node(NULL, NULL, "arm,mbox-mhu");
+	mhu_base = of_iomap(node, 0);
+	if (mhu_base == NULL) {
+		pr_err("Can't work without MHU\n");
+		return -ENODEV;
+	}
+
+	node = of_find_compatible_node(NULL, NULL, "fujitsu,mb86s70-scb-1.0");
+	mb86s7x_shm_base = of_iomap(node, 0);
+	if (mb86s7x_shm_base == NULL) {
+		pr_err("Can't work without SHM SRAM\n");
+		return -ENODEV;
+	}
+
+	cmd_from_scb = mb86s7x_shm_base + 0x3800;
+	rsp_from_scb = mb86s7x_shm_base + 0x3900;
+	cmd_to_scb = mb86s7x_shm_base + 0x3a00;
+	rsp_to_scb = mb86s7x_shm_base + 0x3b00;
+
+	return 0;
+}
+
+int mb86s7x_send_packet(int code, void *buf, int len)
+{
+	struct completion got_rsp;
+	unsigned long flags;
+	struct mhu_xfer *x;
+	int ret;
+
+	/*
+	 * The first caller could be as early as system clocksource,
+	 * when the platform devices are not populated yet.
+	 */
+	if (unlikely(!mb86s7x_shm_base) && setup_mhu())
+		return -ENODEV;
+
+	if ((code & ~0xff) || ((code & RESP_BIT)
+				&& fsm_state != MHU_WRRL
+				&& fsm_state != MHU_WRL)) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	init_completion(&got_rsp);
+
+	spin_lock_irqsave(&fsm_lock, flags);
+
+	if (list_empty(&free_xfers) && mhu_alloc_xfers(5, &free_xfers)) {
+		spin_unlock_irqrestore(&fsm_lock, flags);
+		pr_err("%s:%d OOM\n", __func__, __LINE__);
+		return -EAGAIN;
+	}
+
+	x = list_first_entry(&free_xfers, struct mhu_xfer, node);
+	x->code = code;
+	x->buf = buf;
+	x->len = len;
+	x->c = &got_rsp;
+
+	if (code & RESP_BIT)
+		list_move(&x->node, &pending_xfers);
+	else
+		list_move_tail(&x->node, &pending_xfers);
+
+	spin_unlock_irqrestore(&fsm_lock, flags);
+
+	ret = do_xfer();
+	if (ret > 0) {
+		ret = wait_for_completion_timeout(&got_rsp,
+						  msecs_to_jiffies(1000));
+		return ret ? 0 : -EIO;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(mb86s7x_send_packet);
+
+struct mb86s7x_hard_reset {
+	u32 payload_size;
+	u32 delay;
+};
+
+static void mb86s7x_reboot(u32 delay)
+{
+	void __iomem *tx_reg = mhu_base + 0x120; /* HP-NonSec */
+	struct mb86s7x_hard_reset cmd;
+	u32 val;
+
+	cmd.payload_size = sizeof(cmd);
+	cmd.delay = delay;
+
+	val = readl_relaxed(tx_reg + INTR_STAT_OFS);
+	if (val) /* Flush anything pending */
+		writel_relaxed(val, tx_reg + INTR_CLR_OFS);
+
+	memcpy_toio(cmd_to_scb, &cmd, sizeof(cmd));
+	writel_relaxed(CMD_HARD_RESET_REQ, tx_reg + INTR_SET_OFS);
+}
+
+static void
+mb86s7x_restart(enum reboot_mode reboot_mode, const char *unused)
+{
+	/* Reboot immediately (after 50ms) */
+	mb86s7x_reboot(50);
+}
+
+static void mb86s7x_poweroff(void)
+{
+	/* Reboot never, remain dead */
+	mb86s7x_reboot(~0);
+}
+
+static int f_scb_probe(struct platform_device *pdev)
+{
+	mhu_cl.tx_block = true;
+	mhu_cl.knows_txdone = true;
+	mhu_cl.rx_callback = mhu_recv;
+	mhu_cl.dev = &pdev->dev;
+
+	arm_pm_restart = mb86s7x_restart;
+	pm_power_off = mb86s7x_poweroff;
+
+	return 0;
+}
+
+static const struct of_device_id scb_dt_ids[] = {
+	{ .compatible = "fujitsu,mb86s70-scb-1.0" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, scb_dt_ids);
+
+static struct platform_driver f_scb_driver = {
+	.driver		= {
+		.name	= "f_scb",
+		.of_match_table = scb_dt_ids,
+	},
+	.probe = f_scb_probe,
+};
+
+static int __init f_scb_init(void)
+{
+	return platform_driver_register(&f_scb_driver);
+}
+module_init(f_scb_init);
diff --git a/include/soc/mb86s7x/scb_mhu.h b/include/soc/mb86s7x/scb_mhu.h
new file mode 100644
index 0000000..334fa9f
--- /dev/null
+++ b/include/soc/mb86s7x/scb_mhu.h
@@ -0,0 +1,97 @@
+/*
+ * include/soc/mb86s7x/scb_mhu.h
+ *
+ * Created by: Jassi Brar <jassisinghbrar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ * Copyright:	(C) 2013-2015 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __MB86S7X_SCB_MHU_H
+#define __MB86S7X_SCB_MHU_H
+
+#define CMD_MASK    0x7f    /* 128 possible commands */
+#define RESP_BIT    (1 << 7) /* If it's a response */
+
+#define ENC_CMD(c)  ((c) & CMD_MASK)
+#define DEC_CMD(v)  (((v) & ~CMD_MASK) ? CMD_INVALID : ((v) & CMD_MASK))
+
+#define ENC_REP(r)  (((r) & CMD_MASK) | RESP_BIT)
+
+/* If v is the reply to command c */
+#define IS_A_REP(v, c)  (((v) & RESP_BIT) && (((v) & CMD_MASK) == (c)))
+
+enum {
+	CMD_INVALID = 0,
+	CMD_I2C_XFER_REQ = 1,
+	CMD_PERI_POWER_SET_REQ = 2,
+	CMD_PERI_CLOCK_GATE_SET_REQ = 3,
+	CMD_PERI_CLOCK_GATE_GET_REQ = 4,
+	CMD_PERI_CLOCK_RATE_SET_REQ = 5,
+	CMD_PERI_CLOCK_RATE_GET_REQ = 6,
+	CMD_CPU_CLOCK_GATE_SET_REQ = 7,
+	CMD_CPU_CLOCK_GATE_GET_REQ = 8,
+	CMD_CPU_CLOCK_RATE_SET_REQ = 9,
+	CMD_CPU_CLOCK_RATE_GET_REQ = 0xa,
+	CMD_CLUSTER_OPP_GET_REQ = 0xb,
+	CMD_CLOCK_DSI_PIXEL_REQ = 0xc,
+	CMD_SCB_CAPABILITY_GET_REQ = 0xd,
+	CMD_SYS_RESET_CAUSE_GET_REQ = 0xe,
+	CMD_SYS_SPECIFIC_INFO_GET_REQ = 0xf,
+	CMD_REBOOT_AP_AFTER_REQ = 0x10,
+	CMD_TAIKI_REQ = 0x11,
+	CMD_TAIKI_ASYNC_MSG_REQ = 0x12,
+	CMD_GET_WORD_REQ = 0x13,
+	CMD_HARD_RESET_REQ = 0x14,
+	CMD_MAINTENANCE_MODE_REQ = 0x15,
+	CMD_STG_GET_SIZE_REQ = 0x16,
+	CMD_STG_BLOCK_READ_REQ = 0x17,
+	CMD_STG_BLOCK_WRITE_REQ = 0x18,
+	CMD_MEMORY_LAYOUT_GET_REQ = 0x19,
+	CMD_POWERDOMAIN_GET_REQ = 0x1a,
+	CMD_POWERDOMAIN_SET_REQ = 0x1b,
+	CMD_STG_BLOCK_ERASE_REQ = 0x1c,
+
+	/* Do NOT add new commands below this line */
+	MHU_NUM_CMDS,
+};
+
+#define CMD_I2C_XFER_REP	ENC_REP(CMD_I2C_XFER_REQ)
+#define CMD_PERI_POWER_SET_REP	ENC_REP(CMD_PERI_POWER_SET_REQ)
+#define CMD_PERI_CLOCK_GATE_SET_REP	ENC_REP(CMD_PERI_CLOCK_GATE_SET_REQ)
+#define CMD_PERI_CLOCK_GATE_GET_REP	ENC_REP(CMD_PERI_CLOCK_GATE_GET_REQ)
+#define CMD_PERI_CLOCK_RATE_SET_REP	ENC_REP(CMD_PERI_CLOCK_RATE_SET_REQ)
+#define CMD_PERI_CLOCK_RATE_GET_REP	ENC_REP(CMD_PERI_CLOCK_RATE_GET_REQ)
+#define CMD_CPU_CLOCK_GATE_SET_REP	ENC_REP(CMD_CPU_CLOCK_GATE_SET_REQ)
+#define CMD_CPU_CLOCK_GATE_GET_REP	ENC_REP(CMD_CPU_CLOCK_GATE_GET_REQ)
+#define CMD_CPU_CLOCK_RATE_SET_REP	ENC_REP(CMD_CPU_CLOCK_RATE_SET_REQ)
+#define CMD_CPU_CLOCK_RATE_GET_REP	ENC_REP(CMD_CPU_CLOCK_RATE_GET_REQ)
+#define CMD_CLUSTER_OPP_GET_REP	ENC_REP(CMD_CLUSTER_OPP_GET_REQ)
+#define CMD_CLOCK_DSI_PIXEL_REP	ENC_REP(CMD_CLOCK_DSI_PIXEL_REQ)
+#define CMD_SCB_CAPABILITY_GET_REP	ENC_REP(CMD_SCB_CAPABILITY_GET_REQ)
+#define CMD_SYS_RESET_CAUSE_GET_REP	ENC_REP(CMD_SYS_RESET_CAUSE_GET_REQ)
+#define CMD_SYS_SPECIFIC_INFO_GET_REP	ENC_REP(CMD_SYS_SPECIFIC_INFO_GET_REQ)
+#define CMD_GET_WORD_REP	ENC_REP(CMD_GET_WORD_REQ)
+#define CMD_REBOOT_AP_AFTER_REP	ENC_REP(CMD_REBOOT_AP_AFTER_REQ)
+#define CMD_TAIKI_REP			ENC_REP(CMD_TAIKI_REQ)
+#define CMD_TAIKI_ASYNC_MSG_REP		ENC_REP(CMD_TAIKI_ASYNC_MSG_REQ)
+#define CMD_HARD_RESET_REP		ENC_REP(CMD_HARD_RESET_REQ)
+#define CMD_MAINTENANCE_MODE_REP	ENC_RSP(CMD_MAINTENANCE_MODE_REQ)
+#define CMD_STG_GET_SIZE_REP		ENC_REP(CMD_STG_GET_SIZE_REQ)
+#define CMD_STG_BLOCK_READ_REP		ENC_REP(CMD_STG_BLOCK_READ_REQ)
+#define CMD_STG_BLOCK_WRITE_REP		ENC_REP(CMD_STG_BLOCK_WRITE_REQ)
+#define CMD_MEMORY_LAYOUT_GET_REP	ENC_REP(CMD_MEMORY_LAYOUT_GET_REQ)
+#define CMD_POWERDOMAIN_GET_REP		ENC_REP(CMD_POWERDOMAIN_GET_REQ)
+#define CMD_POWERDOMAIN_SET_REP		ENC_REP(CMD_POWERDOMAIN_SET_REQ)
+#define CMD_STG_BLOCK_ERASE_REP		ENC_REP(CMD_STG_BLOCK_ERASE_REQ)
+
+/* Helper functions to talk to remote */
+int mb86s7x_send_packet(int cmd, void *buf, int len);
+
+typedef void (*mb86s7x_mhu_handler_t)(u32 cmd, u8 rcbuf[]);
+int mb86s7x_hndlr_set(u32 cmd, mb86s7x_mhu_handler_t);
+void mb86s7x_hndlr_clr(u32 cmd, mb86s7x_mhu_handler_t);
+
+#endif /* __MB86S7X_SCB_MHU_H */
-- 
1.9.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 1/8] ARM: Add platform support for Fujitsu MB86S7X SoCs
@ 2015-01-09 11:24     ` Vincent Yang
  0 siblings, 0 replies; 39+ messages in thread
From: Vincent Yang @ 2015-01-09 11:24 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jassi Brar <jaswinder.singh@linaro.org>

The MB86S7X is a bigLITTLE configuration of 2xCA7 & 2xCA15 under Linux.
And the remote master firmware (called SCB) running on CM3. Linux asks
for things to be done over Mailbox API, to SCB which controls most of
the important things. variations S70 & S73 are supported.

Signed-off-by: Andy Green <andy.green@linaro.org>
Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
Signed-off-by: Vincent Yang <Vincent.Yang@tw.fujitsu.com>
Signed-off-by: Tetsuya Nuriya <nuriya.tetsuya@jp.fujitsu.com>
---
 Documentation/devicetree/bindings/arm/mb86s7x.txt  |   8 +
 .../devicetree/bindings/soc/mb86s7x/scb_mhu.txt    |  35 ++
 MAINTAINERS                                        |   7 +
 arch/arm/Kconfig                                   |   2 +
 arch/arm/Makefile                                  |   1 +
 arch/arm/mach-mb86s7x/Kconfig                      |  19 +
 arch/arm/mach-mb86s7x/Makefile                     |   1 +
 arch/arm/mach-mb86s7x/board.c                      |  23 +
 drivers/soc/Makefile                               |   1 +
 drivers/soc/mb86s7x/Makefile                       |   4 +
 drivers/soc/mb86s7x/scb_mhu.c                      | 514 +++++++++++++++++++++
 include/soc/mb86s7x/scb_mhu.h                      |  97 ++++
 12 files changed, 712 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/mb86s7x.txt
 create mode 100644 Documentation/devicetree/bindings/soc/mb86s7x/scb_mhu.txt
 create mode 100644 arch/arm/mach-mb86s7x/Kconfig
 create mode 100644 arch/arm/mach-mb86s7x/Makefile
 create mode 100644 arch/arm/mach-mb86s7x/board.c
 create mode 100644 drivers/soc/mb86s7x/Makefile
 create mode 100644 drivers/soc/mb86s7x/scb_mhu.c
 create mode 100644 include/soc/mb86s7x/scb_mhu.h

diff --git a/Documentation/devicetree/bindings/arm/mb86s7x.txt b/Documentation/devicetree/bindings/arm/mb86s7x.txt
new file mode 100644
index 0000000..fbaad20
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mb86s7x.txt
@@ -0,0 +1,8 @@
+Fujitsu MB86S7X Device Tree Bindings
+
+Fujitsu has a few closely related platforms that are basically different
+configurations of each others. Like MB86S7{0,1,2,3}.
+
+The EVB boards with S70/S73 have the following property:
+Required root node property:
+	compatible: must contain "fujitsu,mb86s70-evb" or "fujitsu,mb86s73-evb"
diff --git a/Documentation/devicetree/bindings/soc/mb86s7x/scb_mhu.txt b/Documentation/devicetree/bindings/soc/mb86s7x/scb_mhu.txt
new file mode 100644
index 0000000..adee45c
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/mb86s7x/scb_mhu.txt
@@ -0,0 +1,35 @@
+Fujitsu SCB (Mailbox's Remote Firmware) bindings
+------------------------------------------------
+
+The firmware (running of a remote Cortex-M3 master) on Fujitsu's MB86S7X
+platforms is named SCB. The SCB owns most of core h/w IPs like Clock,
+CPUFreq/DVFS, CPUIdle/SMP, Thermal, a recovery block device and even an
+I2C controller. Linux has to map all of these functionalities on to
+the Mailbox API and get things done by the remote master.
+ Let the current state of SCB firmware be versioned 1.0.
+
+Required properties :
+- compatible : Shall contain "fujitsu,mb86s70-scb-1.0"
+- reg : Point to SharedMemory used for Mailbox protocol.
+- mboxes : phandle to the mailbox controller:channel node.
+
+The consumer specifies the desired clock pointing to its phandle.
+
+Example:
+
+	mhu: mhu0 at 2b1f0000 {
+		#mbox-cells = <1>;
+		compatible = "arm,mbox-mhu";
+		reg = <0 0x2b1f0000 0x1000>;
+		interrupts = <0 36 4>, /* LP Non-Sec */
+			     <0 35 4>, /* HP Non-Sec */
+			     <0 37 4>; /* Secure */
+		clocks = <&clk 0 2 1>;
+		clock-names = "clk";
+	};
+
+	mhu_client: scb at 2e000000 {
+		compatible = "fujitsu,mb86s70-scb-1.0";
+		reg = <0 0x2e000000 0x4000>; /* SHM for IPC */
+		mboxes = <&mhu 1>;
+	};
diff --git a/MAINTAINERS b/MAINTAINERS
index ddb9ac8..a57c74c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1108,6 +1108,13 @@ M:	Lennert Buytenhek <kernel@wantstofly.org>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 
+ARM/MB86S7X SOC SUPPORT
+M:	Vincent Yang <Vincent.Yang@tw.fujitsu.com>
+M:	Tetsuya Nuriya <nuriya.tetsuya@jp.fujitsu.com>
+L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
+S:	Supported
+F:	arch/arm/mach-mb86s7x/
+
 ARM/TEXAS INSTRUMENT KEYSTONE ARCHITECTURE
 M:	Santosh Shilimkar <ssantosh@kernel.org>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 97d07ed..3c80a9b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -884,6 +884,8 @@ source "arch/arm/mach-keystone/Kconfig"
 
 source "arch/arm/mach-ks8695/Kconfig"
 
+source "arch/arm/mach-mb86s7x/Kconfig"
+
 source "arch/arm/mach-meson/Kconfig"
 
 source "arch/arm/mach-msm/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index c1785ee..c65aff2 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -167,6 +167,7 @@ machine-$(CONFIG_ARCH_IXP4XX)		+= ixp4xx
 machine-$(CONFIG_ARCH_KEYSTONE)		+= keystone
 machine-$(CONFIG_ARCH_KS8695)		+= ks8695
 machine-$(CONFIG_ARCH_LPC32XX)		+= lpc32xx
+machine-$(CONFIG_ARCH_MB86S7X)		+= mb86s7x
 machine-$(CONFIG_ARCH_MESON)		+= meson
 machine-$(CONFIG_ARCH_MMP)		+= mmp
 machine-$(CONFIG_ARCH_MOXART)		+= moxart
diff --git a/arch/arm/mach-mb86s7x/Kconfig b/arch/arm/mach-mb86s7x/Kconfig
new file mode 100644
index 0000000..f58b104
--- /dev/null
+++ b/arch/arm/mach-mb86s7x/Kconfig
@@ -0,0 +1,19 @@
+config ARCH_MB86S7X
+	bool "Fujitsu MB86S7x platforms" if ARCH_MULTI_V7
+	select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
+	select ARCH_HAS_CPUFREQ
+	select ARCH_HAS_OPP
+	select ARCH_REQUIRE_GPIOLIB
+	select ARM_AMBA
+	select ARM_CCI
+	select ARM_GIC
+	select ARM_TIMER_SP804
+	select BIG_LITTLE
+	select HAVE_ARM_ARCH_TIMER
+	select MAILBOX
+	select PINCTRL
+	select PINCTRL_MB86S7X
+	select PM_OPP
+	select ZONE_DMA if ARM_LPAE
+	help
+	  Support for Fujitsu MB86S7x based platforms
diff --git a/arch/arm/mach-mb86s7x/Makefile b/arch/arm/mach-mb86s7x/Makefile
new file mode 100644
index 0000000..97640b6
--- /dev/null
+++ b/arch/arm/mach-mb86s7x/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ARCH_MB86S7X)	+= board.o
diff --git a/arch/arm/mach-mb86s7x/board.c b/arch/arm/mach-mb86s7x/board.c
new file mode 100644
index 0000000..222b63f
--- /dev/null
+++ b/arch/arm/mach-mb86s7x/board.c
@@ -0,0 +1,23 @@
+/*
+ * Support for the Fujitsu's MB86S7x based devices.
+ *
+ * Copyright (C) 2015 Linaro, LTD
+ *
+ * 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, version 2 of the License.
+ *
+ */
+
+#include <linux/of.h>
+#include <asm/mach/arch.h>
+
+static const char *mb86s7x_dt_match[] __initconst = {
+	"fujitsu,mb86s70-evb",
+	"fujitsu,mb86s73-evb",
+	NULL,
+};
+
+DT_MACHINE_START(MB86S7X_DT, "Fujitsu MB86S7X-based board")
+	.dt_compat	= mb86s7x_dt_match,
+MACHINE_END
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 063113d..fb64bf2 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -2,6 +2,7 @@
 # Makefile for the Linux Kernel SOC specific device drivers.
 #
 
+obj-$(CONFIG_ARCH_MB86S7X)	+= mb86s7x/
 obj-$(CONFIG_ARCH_QCOM)		+= qcom/
 obj-$(CONFIG_ARCH_TEGRA)	+= tegra/
 obj-$(CONFIG_SOC_TI)		+= ti/
diff --git a/drivers/soc/mb86s7x/Makefile b/drivers/soc/mb86s7x/Makefile
new file mode 100644
index 0000000..f6b96cf
--- /dev/null
+++ b/drivers/soc/mb86s7x/Makefile
@@ -0,0 +1,4 @@
+#
+# Fujitsu's MB86S7X drivers
+#
+obj-$(CONFIG_ARCH_MB86S7X)	+= scb_mhu.o
diff --git a/drivers/soc/mb86s7x/scb_mhu.c b/drivers/soc/mb86s7x/scb_mhu.c
new file mode 100644
index 0000000..08a3c88
--- /dev/null
+++ b/drivers/soc/mb86s7x/scb_mhu.c
@@ -0,0 +1,514 @@
+/*
+ * arch/arm/mach-mb86s7x/scb_mhu.c Shim 'server' for Mailbox clients
+ *
+ * Created by: Jassi Brar <jassisinghbrar@gmail.com>
+ * Copyright:	(C) 2013-2015 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/reboot.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/of_address.h>
+#include <linux/mailbox_client.h>
+#include <linux/platform_device.h>
+
+#include <soc/mb86s7x/scb_mhu.h>
+
+#include <asm/system_misc.h>
+
+#define INTR_STAT_OFS	0x0
+#define INTR_SET_OFS	0x8
+#define INTR_CLR_OFS	0x10
+
+static LIST_HEAD(free_xfers);
+static LIST_HEAD(pending_xfers);
+static DEFINE_SPINLOCK(fsm_lock);
+static struct completion fsm_rsp;
+static struct mbox_client mhu_cl;
+static struct mbox_chan *mhu_chan;
+static mb86s7x_mhu_handler_t handler[MHU_NUM_CMDS];
+
+static void __iomem *mhu_base, *mb86s7x_shm_base;
+static void __iomem *cmd_to_scb, *rsp_to_scb;
+static void __iomem *cmd_from_scb, *rsp_from_scb;
+
+static enum {
+	MHU_PARK = 0,
+	MHU_WRR, /* Waiting to get Remote's Reply */
+	MHU_WRL, /* Waiting to send Reply */
+	MHU_WRRL, /* WAIT_Ra && WAIT_Rb */
+	MHU_INVLD,
+} fsm_state;
+
+enum fsm_event {
+	EV_LC = 0, /* Local sent a command */
+	EV_RC, /* Remote sent a command */
+	EV_RR, /* Remote sent a reply */
+	EV_LR, /* Local sent a reply */
+};
+
+static int mhu_fsm[4][4] = {
+	[MHU_PARK] = {
+		[EV_LC] = MHU_WRR,
+		[EV_RC] = MHU_WRL,
+		[EV_RR] = MHU_INVLD,
+		[EV_LR] = MHU_INVLD,
+	},
+	[MHU_WRR] = {
+		[EV_LC] = MHU_INVLD,
+		[EV_RC] = MHU_WRRL,
+		[EV_RR] = MHU_PARK,
+		[EV_LR] = MHU_INVLD,
+	},
+	[MHU_WRL] = {
+		[EV_LC] = MHU_WRRL,
+		[EV_RC] = MHU_INVLD,
+		[EV_RR] = MHU_INVLD,
+		[EV_LR] = MHU_PARK,
+	},
+	[MHU_WRRL] = {
+		[EV_LC] = MHU_INVLD,
+		[EV_RC] = MHU_INVLD,
+		[EV_RR] = MHU_WRL,
+		[EV_LR] = MHU_WRR,
+	},
+};
+
+static struct mhu_xfer {
+	int code;
+	int len;
+	void *buf;
+	struct completion *c;
+	struct list_head node;
+} *ax; /* stages of xfer */
+
+static int mhu_alloc_xfers(int n, struct list_head *list)
+{
+	struct mhu_xfer *x = kcalloc(n, sizeof(struct mhu_xfer), GFP_ATOMIC);
+	int i;
+
+	if (!x)
+		return -ENOMEM;
+
+	for (i = 0; i < n; i++)
+		list_add(&x[i].node, &free_xfers);
+
+	return 0;
+}
+
+static void got_data(u32 code)
+{
+	mb86s7x_mhu_handler_t hndlr = NULL;
+	unsigned long flags;
+	int ev;
+
+	if (code & RESP_BIT)
+		ev = EV_RR;
+	else
+		ev = EV_RC;
+
+	spin_lock_irqsave(&fsm_lock, flags);
+
+	if (mhu_fsm[fsm_state][ev] == MHU_INVLD) {
+		spin_unlock_irqrestore(&fsm_lock, flags);
+		pr_err("State-%d EV-%d FSM Broken!\n", fsm_state, ev);
+		return;
+	}
+	fsm_state = mhu_fsm[fsm_state][ev];
+
+	if (code & RESP_BIT) {
+		memcpy_fromio(ax->buf, rsp_from_scb, ax->len);
+		if (ax->c)
+			complete(ax->c);
+		list_move(&ax->node, &free_xfers);
+		ax = NULL;
+	} else {
+		/* Find and dispatch relevant registered handler */
+		if (code < MHU_NUM_CMDS)
+			hndlr = handler[code];
+		if (hndlr)
+			hndlr(code, cmd_from_scb);
+		else
+			pr_err("No handler for CMD_%u\n", code);
+	}
+
+	spin_unlock_irqrestore(&fsm_lock, flags);
+}
+
+static int do_xfer(void)
+{
+	unsigned long flags;
+	struct mhu_xfer *x;
+	int ev, code;
+
+	spin_lock_irqsave(&fsm_lock, flags);
+
+	if (list_empty(&pending_xfers)) {
+		struct mbox_chan *_ch = NULL;
+		int cmd;
+
+		for (cmd = 0; cmd < MHU_NUM_CMDS && !handler[cmd]; cmd++)
+			;
+		/* Don't free channel if any user is listening */
+		if (cmd != MHU_NUM_CMDS) {
+			spin_unlock_irqrestore(&fsm_lock, flags);
+			return 0;
+		}
+
+		if (fsm_state == MHU_PARK) {
+			_ch = mhu_chan;
+			mhu_chan = NULL;
+		}
+
+		spin_unlock_irqrestore(&fsm_lock, flags);
+
+		if (_ch)
+			mbox_free_channel(_ch);
+
+		return 0;
+	}
+
+	x = list_first_entry(&pending_xfers, struct mhu_xfer, node);
+	code = x->code;
+
+	ev = code & RESP_BIT ? EV_LR : EV_LC;
+	if (mhu_fsm[fsm_state][ev] == MHU_INVLD) {
+		spin_unlock_irqrestore(&fsm_lock, flags);
+		return 1;
+	}
+	list_del_init(&x->node);
+
+	/* Layout the SHM */
+	if (code & RESP_BIT)
+		memcpy_toio(rsp_to_scb, x->buf, x->len);
+	else
+		memcpy_toio(cmd_to_scb, x->buf, x->len);
+
+	if (ev == EV_LC)
+		ax = x;
+	else
+		list_move(&x->node, &free_xfers);
+	fsm_state = mhu_fsm[fsm_state][ev];
+
+	spin_unlock_irqrestore(&fsm_lock, flags);
+
+	/* Prefer mailbox API */
+	if (!mhu_chan) {
+		struct mbox_chan *_ch;
+
+		_ch = mbox_request_channel(&mhu_cl, 0);
+		if (!IS_ERR(_ch))
+			mhu_chan = _ch;
+	}
+
+	if (mhu_chan) {
+		int ret;
+
+		init_completion(&fsm_rsp);
+
+		/* Send via generic api */
+		ret = mbox_send_message(mhu_chan, (void *)code);
+		if (ret < 0) {
+			pr_err("%s:%d CMD_%d Send Failed\n",
+			       __func__, __LINE__, code);
+			BUG();
+		}
+		if (!(code & RESP_BIT)) {
+			ret = wait_for_completion_timeout(&fsm_rsp,
+						msecs_to_jiffies(1000));
+			if (!ret) {
+				pr_err("%s:%d CMD_%d Got No Reply\n",
+				       __func__, __LINE__, code);
+				BUG();
+			}
+			got_data(ax->code);
+		}
+	} else {
+		void __iomem *tx_reg = mhu_base + 0x120; /* HP-NonSec */
+		void __iomem *rx_reg = mhu_base + 0x20; /* HP-NonSec */
+		u32 val, count;
+
+		/* Send via early-boot api */
+		val = readl_relaxed(tx_reg + INTR_STAT_OFS);
+		if (val) {
+			pr_err("Last CMD not yet read by SCB\n");
+			writel_relaxed(val, tx_reg + INTR_CLR_OFS);
+		}
+
+		writel_relaxed(x->code, tx_reg + INTR_SET_OFS);
+
+		/* Wait until this message is read */
+		count = 0x1000000;
+		do {
+			cpu_relax();
+			val = readl_relaxed(tx_reg + INTR_STAT_OFS);
+		} while (--count && val);
+		if (val)
+			pr_err("%s:%d SCB not listening!\n",
+			       __func__, __LINE__);
+
+		if (!ax) {
+			/* A quick poll for pending remote cmd */
+			val = readl_relaxed(rx_reg + INTR_STAT_OFS);
+			if (val) {
+				got_data(val);
+				writel_relaxed(val, rx_reg + INTR_CLR_OFS);
+			}
+		} else {
+			do {
+				/* Wait until we get reply */
+				count = 0x1000000;
+				do {
+					cpu_relax();
+					val = readl_relaxed(
+						rx_reg + INTR_STAT_OFS);
+				} while (--count && !val);
+
+				if (val) {
+					got_data(val);
+					writel_relaxed(val,
+						     rx_reg + INTR_CLR_OFS);
+				} else {
+					pr_err("%s:%d SCB didn't reply\n",
+					       __func__, __LINE__);
+					return 1;
+				}
+			} while (!(val & RESP_BIT));
+		}
+		if (list_empty(&pending_xfers))
+			return 0;
+	}
+
+	return do_xfer();
+}
+
+static void mhu_recv(struct mbox_client *cl, void *data)
+{
+	if ((u32)data & RESP_BIT) {
+		/* Now that we got a reply to last TX, that
+		 * must mean the last TX was successful */
+		mbox_client_txdone(mhu_chan, 0);
+
+		ax->code = (u32)data; /* Save response */
+		complete(&fsm_rsp);
+		return;
+	}
+
+	got_data((u32)data);
+}
+
+int mb86s7x_hndlr_set(u32 cmd, mb86s7x_mhu_handler_t hndlr)
+{
+	unsigned long flags;
+	int ret = -EINVAL;
+
+	spin_lock_irqsave(&fsm_lock, flags);
+	if (cmd < MHU_NUM_CMDS && !handler[cmd]) {
+		ret = 0;
+		handler[cmd] = hndlr;
+	}
+	spin_unlock_irqrestore(&fsm_lock, flags);
+
+	if (!mhu_chan) {
+		struct mbox_chan *_ch;
+
+		_ch = mbox_request_channel(&mhu_cl, 0);
+		if (!IS_ERR(_ch))
+			mhu_chan = _ch;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(mb86s7x_hndlr_set);
+
+void mb86s7x_hndlr_clr(u32 cmd, mb86s7x_mhu_handler_t hndlr)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&fsm_lock, flags);
+
+	if (cmd < MHU_NUM_CMDS && handler[cmd] == hndlr)
+		handler[cmd] = NULL;
+
+	if (list_empty(&pending_xfers)) {
+		struct mbox_chan *_ch = NULL;
+
+		for (cmd = 0; cmd < MHU_NUM_CMDS && !handler[cmd]; cmd++)
+			;
+		/* Don't free channel if any user is listening */
+		if (cmd != MHU_NUM_CMDS) {
+			spin_unlock_irqrestore(&fsm_lock, flags);
+			return;
+		}
+
+		if (fsm_state == MHU_PARK) {
+			_ch = mhu_chan;
+			mhu_chan = NULL;
+		}
+
+		spin_unlock_irqrestore(&fsm_lock, flags);
+
+		if (_ch)
+			mbox_free_channel(_ch);
+
+		return;
+	}
+	spin_unlock_irqrestore(&fsm_lock, flags);
+}
+EXPORT_SYMBOL_GPL(mb86s7x_hndlr_clr);
+
+static int setup_mhu(void)
+{
+	struct device_node *node;
+
+	node = of_find_compatible_node(NULL, NULL, "arm,mbox-mhu");
+	mhu_base = of_iomap(node, 0);
+	if (mhu_base == NULL) {
+		pr_err("Can't work without MHU\n");
+		return -ENODEV;
+	}
+
+	node = of_find_compatible_node(NULL, NULL, "fujitsu,mb86s70-scb-1.0");
+	mb86s7x_shm_base = of_iomap(node, 0);
+	if (mb86s7x_shm_base == NULL) {
+		pr_err("Can't work without SHM SRAM\n");
+		return -ENODEV;
+	}
+
+	cmd_from_scb = mb86s7x_shm_base + 0x3800;
+	rsp_from_scb = mb86s7x_shm_base + 0x3900;
+	cmd_to_scb = mb86s7x_shm_base + 0x3a00;
+	rsp_to_scb = mb86s7x_shm_base + 0x3b00;
+
+	return 0;
+}
+
+int mb86s7x_send_packet(int code, void *buf, int len)
+{
+	struct completion got_rsp;
+	unsigned long flags;
+	struct mhu_xfer *x;
+	int ret;
+
+	/*
+	 * The first caller could be as early as system clocksource,
+	 * when the platform devices are not populated yet.
+	 */
+	if (unlikely(!mb86s7x_shm_base) && setup_mhu())
+		return -ENODEV;
+
+	if ((code & ~0xff) || ((code & RESP_BIT)
+				&& fsm_state != MHU_WRRL
+				&& fsm_state != MHU_WRL)) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	init_completion(&got_rsp);
+
+	spin_lock_irqsave(&fsm_lock, flags);
+
+	if (list_empty(&free_xfers) && mhu_alloc_xfers(5, &free_xfers)) {
+		spin_unlock_irqrestore(&fsm_lock, flags);
+		pr_err("%s:%d OOM\n", __func__, __LINE__);
+		return -EAGAIN;
+	}
+
+	x = list_first_entry(&free_xfers, struct mhu_xfer, node);
+	x->code = code;
+	x->buf = buf;
+	x->len = len;
+	x->c = &got_rsp;
+
+	if (code & RESP_BIT)
+		list_move(&x->node, &pending_xfers);
+	else
+		list_move_tail(&x->node, &pending_xfers);
+
+	spin_unlock_irqrestore(&fsm_lock, flags);
+
+	ret = do_xfer();
+	if (ret > 0) {
+		ret = wait_for_completion_timeout(&got_rsp,
+						  msecs_to_jiffies(1000));
+		return ret ? 0 : -EIO;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(mb86s7x_send_packet);
+
+struct mb86s7x_hard_reset {
+	u32 payload_size;
+	u32 delay;
+};
+
+static void mb86s7x_reboot(u32 delay)
+{
+	void __iomem *tx_reg = mhu_base + 0x120; /* HP-NonSec */
+	struct mb86s7x_hard_reset cmd;
+	u32 val;
+
+	cmd.payload_size = sizeof(cmd);
+	cmd.delay = delay;
+
+	val = readl_relaxed(tx_reg + INTR_STAT_OFS);
+	if (val) /* Flush anything pending */
+		writel_relaxed(val, tx_reg + INTR_CLR_OFS);
+
+	memcpy_toio(cmd_to_scb, &cmd, sizeof(cmd));
+	writel_relaxed(CMD_HARD_RESET_REQ, tx_reg + INTR_SET_OFS);
+}
+
+static void
+mb86s7x_restart(enum reboot_mode reboot_mode, const char *unused)
+{
+	/* Reboot immediately (after 50ms) */
+	mb86s7x_reboot(50);
+}
+
+static void mb86s7x_poweroff(void)
+{
+	/* Reboot never, remain dead */
+	mb86s7x_reboot(~0);
+}
+
+static int f_scb_probe(struct platform_device *pdev)
+{
+	mhu_cl.tx_block = true;
+	mhu_cl.knows_txdone = true;
+	mhu_cl.rx_callback = mhu_recv;
+	mhu_cl.dev = &pdev->dev;
+
+	arm_pm_restart = mb86s7x_restart;
+	pm_power_off = mb86s7x_poweroff;
+
+	return 0;
+}
+
+static const struct of_device_id scb_dt_ids[] = {
+	{ .compatible = "fujitsu,mb86s70-scb-1.0" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, scb_dt_ids);
+
+static struct platform_driver f_scb_driver = {
+	.driver		= {
+		.name	= "f_scb",
+		.of_match_table = scb_dt_ids,
+	},
+	.probe = f_scb_probe,
+};
+
+static int __init f_scb_init(void)
+{
+	return platform_driver_register(&f_scb_driver);
+}
+module_init(f_scb_init);
diff --git a/include/soc/mb86s7x/scb_mhu.h b/include/soc/mb86s7x/scb_mhu.h
new file mode 100644
index 0000000..334fa9f
--- /dev/null
+++ b/include/soc/mb86s7x/scb_mhu.h
@@ -0,0 +1,97 @@
+/*
+ * include/soc/mb86s7x/scb_mhu.h
+ *
+ * Created by: Jassi Brar <jassisinghbrar@gmail.com>
+ * Copyright:	(C) 2013-2015 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __MB86S7X_SCB_MHU_H
+#define __MB86S7X_SCB_MHU_H
+
+#define CMD_MASK    0x7f    /* 128 possible commands */
+#define RESP_BIT    (1 << 7) /* If it's a response */
+
+#define ENC_CMD(c)  ((c) & CMD_MASK)
+#define DEC_CMD(v)  (((v) & ~CMD_MASK) ? CMD_INVALID : ((v) & CMD_MASK))
+
+#define ENC_REP(r)  (((r) & CMD_MASK) | RESP_BIT)
+
+/* If v is the reply to command c */
+#define IS_A_REP(v, c)  (((v) & RESP_BIT) && (((v) & CMD_MASK) == (c)))
+
+enum {
+	CMD_INVALID = 0,
+	CMD_I2C_XFER_REQ = 1,
+	CMD_PERI_POWER_SET_REQ = 2,
+	CMD_PERI_CLOCK_GATE_SET_REQ = 3,
+	CMD_PERI_CLOCK_GATE_GET_REQ = 4,
+	CMD_PERI_CLOCK_RATE_SET_REQ = 5,
+	CMD_PERI_CLOCK_RATE_GET_REQ = 6,
+	CMD_CPU_CLOCK_GATE_SET_REQ = 7,
+	CMD_CPU_CLOCK_GATE_GET_REQ = 8,
+	CMD_CPU_CLOCK_RATE_SET_REQ = 9,
+	CMD_CPU_CLOCK_RATE_GET_REQ = 0xa,
+	CMD_CLUSTER_OPP_GET_REQ = 0xb,
+	CMD_CLOCK_DSI_PIXEL_REQ = 0xc,
+	CMD_SCB_CAPABILITY_GET_REQ = 0xd,
+	CMD_SYS_RESET_CAUSE_GET_REQ = 0xe,
+	CMD_SYS_SPECIFIC_INFO_GET_REQ = 0xf,
+	CMD_REBOOT_AP_AFTER_REQ = 0x10,
+	CMD_TAIKI_REQ = 0x11,
+	CMD_TAIKI_ASYNC_MSG_REQ = 0x12,
+	CMD_GET_WORD_REQ = 0x13,
+	CMD_HARD_RESET_REQ = 0x14,
+	CMD_MAINTENANCE_MODE_REQ = 0x15,
+	CMD_STG_GET_SIZE_REQ = 0x16,
+	CMD_STG_BLOCK_READ_REQ = 0x17,
+	CMD_STG_BLOCK_WRITE_REQ = 0x18,
+	CMD_MEMORY_LAYOUT_GET_REQ = 0x19,
+	CMD_POWERDOMAIN_GET_REQ = 0x1a,
+	CMD_POWERDOMAIN_SET_REQ = 0x1b,
+	CMD_STG_BLOCK_ERASE_REQ = 0x1c,
+
+	/* Do NOT add new commands below this line */
+	MHU_NUM_CMDS,
+};
+
+#define CMD_I2C_XFER_REP	ENC_REP(CMD_I2C_XFER_REQ)
+#define CMD_PERI_POWER_SET_REP	ENC_REP(CMD_PERI_POWER_SET_REQ)
+#define CMD_PERI_CLOCK_GATE_SET_REP	ENC_REP(CMD_PERI_CLOCK_GATE_SET_REQ)
+#define CMD_PERI_CLOCK_GATE_GET_REP	ENC_REP(CMD_PERI_CLOCK_GATE_GET_REQ)
+#define CMD_PERI_CLOCK_RATE_SET_REP	ENC_REP(CMD_PERI_CLOCK_RATE_SET_REQ)
+#define CMD_PERI_CLOCK_RATE_GET_REP	ENC_REP(CMD_PERI_CLOCK_RATE_GET_REQ)
+#define CMD_CPU_CLOCK_GATE_SET_REP	ENC_REP(CMD_CPU_CLOCK_GATE_SET_REQ)
+#define CMD_CPU_CLOCK_GATE_GET_REP	ENC_REP(CMD_CPU_CLOCK_GATE_GET_REQ)
+#define CMD_CPU_CLOCK_RATE_SET_REP	ENC_REP(CMD_CPU_CLOCK_RATE_SET_REQ)
+#define CMD_CPU_CLOCK_RATE_GET_REP	ENC_REP(CMD_CPU_CLOCK_RATE_GET_REQ)
+#define CMD_CLUSTER_OPP_GET_REP	ENC_REP(CMD_CLUSTER_OPP_GET_REQ)
+#define CMD_CLOCK_DSI_PIXEL_REP	ENC_REP(CMD_CLOCK_DSI_PIXEL_REQ)
+#define CMD_SCB_CAPABILITY_GET_REP	ENC_REP(CMD_SCB_CAPABILITY_GET_REQ)
+#define CMD_SYS_RESET_CAUSE_GET_REP	ENC_REP(CMD_SYS_RESET_CAUSE_GET_REQ)
+#define CMD_SYS_SPECIFIC_INFO_GET_REP	ENC_REP(CMD_SYS_SPECIFIC_INFO_GET_REQ)
+#define CMD_GET_WORD_REP	ENC_REP(CMD_GET_WORD_REQ)
+#define CMD_REBOOT_AP_AFTER_REP	ENC_REP(CMD_REBOOT_AP_AFTER_REQ)
+#define CMD_TAIKI_REP			ENC_REP(CMD_TAIKI_REQ)
+#define CMD_TAIKI_ASYNC_MSG_REP		ENC_REP(CMD_TAIKI_ASYNC_MSG_REQ)
+#define CMD_HARD_RESET_REP		ENC_REP(CMD_HARD_RESET_REQ)
+#define CMD_MAINTENANCE_MODE_REP	ENC_RSP(CMD_MAINTENANCE_MODE_REQ)
+#define CMD_STG_GET_SIZE_REP		ENC_REP(CMD_STG_GET_SIZE_REQ)
+#define CMD_STG_BLOCK_READ_REP		ENC_REP(CMD_STG_BLOCK_READ_REQ)
+#define CMD_STG_BLOCK_WRITE_REP		ENC_REP(CMD_STG_BLOCK_WRITE_REQ)
+#define CMD_MEMORY_LAYOUT_GET_REP	ENC_REP(CMD_MEMORY_LAYOUT_GET_REQ)
+#define CMD_POWERDOMAIN_GET_REP		ENC_REP(CMD_POWERDOMAIN_GET_REQ)
+#define CMD_POWERDOMAIN_SET_REP		ENC_REP(CMD_POWERDOMAIN_SET_REQ)
+#define CMD_STG_BLOCK_ERASE_REP		ENC_REP(CMD_STG_BLOCK_ERASE_REQ)
+
+/* Helper functions to talk to remote */
+int mb86s7x_send_packet(int cmd, void *buf, int len);
+
+typedef void (*mb86s7x_mhu_handler_t)(u32 cmd, u8 rcbuf[]);
+int mb86s7x_hndlr_set(u32 cmd, mb86s7x_mhu_handler_t);
+void mb86s7x_hndlr_clr(u32 cmd, mb86s7x_mhu_handler_t);
+
+#endif /* __MB86S7X_SCB_MHU_H */
-- 
1.9.0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 2/8] mailbox: arm_mhu: add driver for ARM MHU controller
  2015-01-09 11:19 ` Vincent Yang
@ 2015-01-09 11:28     ` Vincent Yang
  -1 siblings, 0 replies; 39+ messages in thread
From: Vincent Yang @ 2015-01-09 11:28 UTC (permalink / raw)
  To: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: arnd-r2nGTMty4D4, olof-nZhT3qVonbNeoWH0uzbU5w,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	pawel.moll-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
	ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ, sudeep.holla-5wv7dgnIgG8,
	andy.green-QSEj5FYQhm4dnm+yROfE0A,
	patches-QSEj5FYQhm4dnm+yROfE0A,
	jaswinder.singh-QSEj5FYQhm4dnm+yROfE0A, Vincent Yang,
	Tetsuya Nuriya

From: Jassi Brar <jaswinder.singh-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

Add driver for the ARM Message-Handling-Unit (MHU).

Signed-off-by: Andy Green <andy.green-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Signed-off-by: Jassi Brar <jaswinder.singh-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Signed-off-by: Vincent Yang <Vincent.Yang-l16TxrwUIHTQFUHtdCDX3A@public.gmane.org>
Signed-off-by: Tetsuya Nuriya <nuriya.tetsuya-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
---
 .../devicetree/bindings/mailbox/arm-mhu.txt        |  33 ++++
 drivers/mailbox/Kconfig                            |   7 +
 drivers/mailbox/Makefile                           |   2 +
 drivers/mailbox/arm_mhu.c                          | 212 +++++++++++++++++++++
 4 files changed, 254 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/arm-mhu.txt
 create mode 100644 drivers/mailbox/arm_mhu.c

diff --git a/Documentation/devicetree/bindings/mailbox/arm-mhu.txt b/Documentation/devicetree/bindings/mailbox/arm-mhu.txt
new file mode 100644
index 0000000..b1b9888
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/arm-mhu.txt
@@ -0,0 +1,33 @@
+ARM MHU Mailbox Driver
+======================
+
+The ARM's Message-Handling-Unit (MHU) is a mailbox controller that has
+3 independent channels/links to communicate with remote processor(s).
+ MHU links are hardwired on a platform. A link raises interrupt for any
+received data. However, there is no specified way of knowing if the sent
+data has been read by the remote. This driver assumes the sender polls
+STAT register and the remote clears it after having read the data.
+
+Mailbox Device Node:
+====================
+
+Required properties:
+--------------------
+- compatible:		Shall be "arm,mbox-mhu"
+- reg:			Contains the mailbox register address range (base
+			address and length)
+- #mbox-cells		Shall be 1
+- interrupts:		Contains the interrupt information corresponding to
+			each of the 3 links of MHU.
+
+Example:
+--------
+
+	mhu: mailbox@2b1f0000 {
+		#mbox-cells = <1>;
+		compatible = "arm,mbox-mhu";
+		reg = <0 0x2b1f0000 0x1000>;
+		interrupts = <0 36 4>,
+			     <0 35 4>,
+			     <0 37 4>;
+	};
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index c04fed9..9238440 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -6,6 +6,13 @@ menuconfig MAILBOX
 	  signals. Say Y if your platform supports hardware mailboxes.
 
 if MAILBOX
+
+config ARM_MHU
+	tristate "ARM MHU Mailbox"
+	depends on ARM
+	help
+	  Say Y here if you want to build the ARM MHU controller driver
+
 config PL320_MBOX
 	bool "ARM PL320 Mailbox"
 	depends on ARM_AMBA
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index dd412c2..c83791d 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -2,6 +2,8 @@
 
 obj-$(CONFIG_MAILBOX)		+= mailbox.o
 
+obj-$(CONFIG_ARM_MHU)	+= arm_mhu.o
+
 obj-$(CONFIG_PL320_MBOX)	+= pl320-ipc.o
 
 obj-$(CONFIG_OMAP2PLUS_MBOX)	+= omap-mailbox.o
diff --git a/drivers/mailbox/arm_mhu.c b/drivers/mailbox/arm_mhu.c
new file mode 100644
index 0000000..8d061b6
--- /dev/null
+++ b/drivers/mailbox/arm_mhu.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2013-2015 Fujitsu Semiconductor Ltd.
+ * Copyright (C) 2015 Linaro Ltd.
+ * Author: Jassi Brar <jaswinder.singh-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
+ *
+ * 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, version 2 of the License.
+ *
+ * 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.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/mailbox_controller.h>
+#include <linux/platform_device.h>
+
+#define INTR_STAT_OFS	0x0
+#define INTR_SET_OFS	0x8
+#define INTR_CLR_OFS	0x10
+
+struct mhu_link {
+	unsigned irq;
+	void __iomem *tx_reg;
+	void __iomem *rx_reg;
+};
+
+struct arm_mhu {
+	void __iomem *base;
+	struct clk *clk;
+	struct mhu_link mlink[3];
+	struct mbox_chan chan[3];
+	struct mbox_controller mbox;
+};
+
+static irqreturn_t mhu_rx_interrupt(int irq, void *p)
+{
+	struct mbox_chan *chan = p;
+	struct mhu_link *mlink = (struct mhu_link *)chan->con_priv;
+	u32 val;
+
+	pr_debug("%s:%d\n", __func__, __LINE__);
+	val = readl_relaxed(mlink->rx_reg + INTR_STAT_OFS);
+	mbox_chan_received_data(chan, (void *)val);
+
+	writel_relaxed(val, mlink->rx_reg + INTR_CLR_OFS);
+
+	return IRQ_HANDLED;
+}
+
+static bool mhu_last_tx_done(struct mbox_chan *chan)
+{
+	struct mhu_link *mlink = (struct mhu_link *)chan->con_priv;
+	u32 val;
+
+	pr_debug("%s:%d\n", __func__, __LINE__);
+	val = readl_relaxed(mlink->tx_reg + INTR_STAT_OFS);
+
+	return (val == 0);
+}
+
+static int mhu_send_data(struct mbox_chan *chan, void *data)
+{
+	struct mhu_link *mlink = (struct mhu_link *)chan->con_priv;
+
+	pr_debug("%s:%d\n", __func__, __LINE__);
+	if (!mhu_last_tx_done(chan)) {
+		pr_err("%s:%d Shouldn't have seen the day!\n",
+		       __func__, __LINE__);
+		return -EBUSY;
+	}
+
+	writel_relaxed((u32)data, mlink->tx_reg + INTR_SET_OFS);
+
+	return 0;
+}
+
+static int mhu_startup(struct mbox_chan *chan)
+{
+	struct mhu_link *mlink = (struct mhu_link *)chan->con_priv;
+	u32 val;
+	int ret;
+
+	pr_debug("%s:%d\n", __func__, __LINE__);
+	val = readl_relaxed(mlink->tx_reg + INTR_STAT_OFS);
+	writel_relaxed(val, mlink->tx_reg + INTR_CLR_OFS);
+
+	ret = request_irq(mlink->irq, mhu_rx_interrupt,
+			  IRQF_SHARED, "mhu_link", chan);
+	if (unlikely(ret)) {
+		pr_err("Unable to aquire IRQ\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static void mhu_shutdown(struct mbox_chan *chan)
+{
+	struct mhu_link *mlink = (struct mhu_link *)chan->con_priv;
+
+	pr_debug("%s:%d\n", __func__, __LINE__);
+	free_irq(mlink->irq, chan);
+}
+
+static struct mbox_chan_ops mhu_ops = {
+	.send_data = mhu_send_data,
+	.startup = mhu_startup,
+	.shutdown = mhu_shutdown,
+	.last_tx_done = mhu_last_tx_done,
+};
+
+static int arm_mhu_probe(struct platform_device *pdev)
+{
+	int i, err;
+	struct arm_mhu *mhu;
+	struct resource *res;
+	int mhu_reg[3] = {0x0, 0x20, 0x200};
+
+	/* Allocate memory for device */
+	mhu = kzalloc(sizeof(*mhu), GFP_KERNEL);
+	if (!mhu)
+		return -ENOMEM;
+
+	mhu->clk = clk_get(&pdev->dev, "clk");
+	if (unlikely(IS_ERR(mhu->clk)))
+		dev_info(&pdev->dev, "unable to init clock\n");
+	else
+		clk_prepare_enable(mhu->clk);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mhu->base = ioremap(res->start, resource_size(res));
+	if (!mhu->base) {
+		dev_err(&pdev->dev, "ioremap failed.\n");
+		kfree(mhu);
+		return -EBUSY;
+	}
+
+	for (i = 0; i < 3; i++) {
+		mhu->chan[i].con_priv = &mhu->mlink[i];
+		res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+		mhu->mlink[i].irq = res->start;
+		mhu->mlink[i].rx_reg = mhu->base + mhu_reg[i];
+		mhu->mlink[i].tx_reg = mhu->mlink[i].rx_reg + 0x100;
+	}
+
+	mhu->mbox.dev = &pdev->dev;
+	mhu->mbox.chans = &mhu->chan[0];
+	mhu->mbox.num_chans = 3;
+	mhu->mbox.ops = &mhu_ops;
+	mhu->mbox.txdone_irq = false;
+	mhu->mbox.txdone_poll = true;
+	mhu->mbox.txpoll_period = 10;
+
+	platform_set_drvdata(pdev, mhu);
+
+	err = mbox_controller_register(&mhu->mbox);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to register mailboxes %d\n", err);
+		iounmap(mhu->base);
+		kfree(mhu);
+	} else {
+		dev_info(&pdev->dev, "ARM MHU Mailbox registered\n");
+	}
+
+	return 0;
+}
+
+static int arm_mhu_remove(struct platform_device *pdev)
+{
+	struct arm_mhu *mhu = platform_get_drvdata(pdev);
+
+	mbox_controller_unregister(&mhu->mbox);
+
+	iounmap(mhu->base);
+
+	if (!IS_ERR(mhu->clk))
+		clk_disable_unprepare(mhu->clk);
+
+	kfree(mhu);
+	return 0;
+}
+
+static const struct of_device_id arm_mhu_dt_ids[] = {
+	{ .compatible = "arm,mbox-mhu" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, arm_mhu_dt_ids);
+
+static struct platform_driver arm_mhu_driver = {
+	.driver = {
+		.name = "arm_mhu",
+		.of_match_table = arm_mhu_dt_ids,
+	},
+	.probe = arm_mhu_probe,
+	.remove = arm_mhu_remove,
+};
+module_platform_driver(arm_mhu_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("ARM MHU Driver");
+MODULE_AUTHOR("Jassi Brar <jassisinghbrar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>");
-- 
1.9.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 2/8] mailbox: arm_mhu: add driver for ARM MHU controller
@ 2015-01-09 11:28     ` Vincent Yang
  0 siblings, 0 replies; 39+ messages in thread
From: Vincent Yang @ 2015-01-09 11:28 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jassi Brar <jaswinder.singh@linaro.org>

Add driver for the ARM Message-Handling-Unit (MHU).

Signed-off-by: Andy Green <andy.green@linaro.org>
Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
Signed-off-by: Vincent Yang <Vincent.Yang@tw.fujitsu.com>
Signed-off-by: Tetsuya Nuriya <nuriya.tetsuya@jp.fujitsu.com>
---
 .../devicetree/bindings/mailbox/arm-mhu.txt        |  33 ++++
 drivers/mailbox/Kconfig                            |   7 +
 drivers/mailbox/Makefile                           |   2 +
 drivers/mailbox/arm_mhu.c                          | 212 +++++++++++++++++++++
 4 files changed, 254 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/arm-mhu.txt
 create mode 100644 drivers/mailbox/arm_mhu.c

diff --git a/Documentation/devicetree/bindings/mailbox/arm-mhu.txt b/Documentation/devicetree/bindings/mailbox/arm-mhu.txt
new file mode 100644
index 0000000..b1b9888
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/arm-mhu.txt
@@ -0,0 +1,33 @@
+ARM MHU Mailbox Driver
+======================
+
+The ARM's Message-Handling-Unit (MHU) is a mailbox controller that has
+3 independent channels/links to communicate with remote processor(s).
+ MHU links are hardwired on a platform. A link raises interrupt for any
+received data. However, there is no specified way of knowing if the sent
+data has been read by the remote. This driver assumes the sender polls
+STAT register and the remote clears it after having read the data.
+
+Mailbox Device Node:
+====================
+
+Required properties:
+--------------------
+- compatible:		Shall be "arm,mbox-mhu"
+- reg:			Contains the mailbox register address range (base
+			address and length)
+- #mbox-cells		Shall be 1
+- interrupts:		Contains the interrupt information corresponding to
+			each of the 3 links of MHU.
+
+Example:
+--------
+
+	mhu: mailbox at 2b1f0000 {
+		#mbox-cells = <1>;
+		compatible = "arm,mbox-mhu";
+		reg = <0 0x2b1f0000 0x1000>;
+		interrupts = <0 36 4>,
+			     <0 35 4>,
+			     <0 37 4>;
+	};
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index c04fed9..9238440 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -6,6 +6,13 @@ menuconfig MAILBOX
 	  signals. Say Y if your platform supports hardware mailboxes.
 
 if MAILBOX
+
+config ARM_MHU
+	tristate "ARM MHU Mailbox"
+	depends on ARM
+	help
+	  Say Y here if you want to build the ARM MHU controller driver
+
 config PL320_MBOX
 	bool "ARM PL320 Mailbox"
 	depends on ARM_AMBA
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index dd412c2..c83791d 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -2,6 +2,8 @@
 
 obj-$(CONFIG_MAILBOX)		+= mailbox.o
 
+obj-$(CONFIG_ARM_MHU)	+= arm_mhu.o
+
 obj-$(CONFIG_PL320_MBOX)	+= pl320-ipc.o
 
 obj-$(CONFIG_OMAP2PLUS_MBOX)	+= omap-mailbox.o
diff --git a/drivers/mailbox/arm_mhu.c b/drivers/mailbox/arm_mhu.c
new file mode 100644
index 0000000..8d061b6
--- /dev/null
+++ b/drivers/mailbox/arm_mhu.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2013-2015 Fujitsu Semiconductor Ltd.
+ * Copyright (C) 2015 Linaro Ltd.
+ * Author: Jassi Brar <jaswinder.singh@linaro.org>
+ *
+ * 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, version 2 of the License.
+ *
+ * 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.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/mailbox_controller.h>
+#include <linux/platform_device.h>
+
+#define INTR_STAT_OFS	0x0
+#define INTR_SET_OFS	0x8
+#define INTR_CLR_OFS	0x10
+
+struct mhu_link {
+	unsigned irq;
+	void __iomem *tx_reg;
+	void __iomem *rx_reg;
+};
+
+struct arm_mhu {
+	void __iomem *base;
+	struct clk *clk;
+	struct mhu_link mlink[3];
+	struct mbox_chan chan[3];
+	struct mbox_controller mbox;
+};
+
+static irqreturn_t mhu_rx_interrupt(int irq, void *p)
+{
+	struct mbox_chan *chan = p;
+	struct mhu_link *mlink = (struct mhu_link *)chan->con_priv;
+	u32 val;
+
+	pr_debug("%s:%d\n", __func__, __LINE__);
+	val = readl_relaxed(mlink->rx_reg + INTR_STAT_OFS);
+	mbox_chan_received_data(chan, (void *)val);
+
+	writel_relaxed(val, mlink->rx_reg + INTR_CLR_OFS);
+
+	return IRQ_HANDLED;
+}
+
+static bool mhu_last_tx_done(struct mbox_chan *chan)
+{
+	struct mhu_link *mlink = (struct mhu_link *)chan->con_priv;
+	u32 val;
+
+	pr_debug("%s:%d\n", __func__, __LINE__);
+	val = readl_relaxed(mlink->tx_reg + INTR_STAT_OFS);
+
+	return (val == 0);
+}
+
+static int mhu_send_data(struct mbox_chan *chan, void *data)
+{
+	struct mhu_link *mlink = (struct mhu_link *)chan->con_priv;
+
+	pr_debug("%s:%d\n", __func__, __LINE__);
+	if (!mhu_last_tx_done(chan)) {
+		pr_err("%s:%d Shouldn't have seen the day!\n",
+		       __func__, __LINE__);
+		return -EBUSY;
+	}
+
+	writel_relaxed((u32)data, mlink->tx_reg + INTR_SET_OFS);
+
+	return 0;
+}
+
+static int mhu_startup(struct mbox_chan *chan)
+{
+	struct mhu_link *mlink = (struct mhu_link *)chan->con_priv;
+	u32 val;
+	int ret;
+
+	pr_debug("%s:%d\n", __func__, __LINE__);
+	val = readl_relaxed(mlink->tx_reg + INTR_STAT_OFS);
+	writel_relaxed(val, mlink->tx_reg + INTR_CLR_OFS);
+
+	ret = request_irq(mlink->irq, mhu_rx_interrupt,
+			  IRQF_SHARED, "mhu_link", chan);
+	if (unlikely(ret)) {
+		pr_err("Unable to aquire IRQ\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static void mhu_shutdown(struct mbox_chan *chan)
+{
+	struct mhu_link *mlink = (struct mhu_link *)chan->con_priv;
+
+	pr_debug("%s:%d\n", __func__, __LINE__);
+	free_irq(mlink->irq, chan);
+}
+
+static struct mbox_chan_ops mhu_ops = {
+	.send_data = mhu_send_data,
+	.startup = mhu_startup,
+	.shutdown = mhu_shutdown,
+	.last_tx_done = mhu_last_tx_done,
+};
+
+static int arm_mhu_probe(struct platform_device *pdev)
+{
+	int i, err;
+	struct arm_mhu *mhu;
+	struct resource *res;
+	int mhu_reg[3] = {0x0, 0x20, 0x200};
+
+	/* Allocate memory for device */
+	mhu = kzalloc(sizeof(*mhu), GFP_KERNEL);
+	if (!mhu)
+		return -ENOMEM;
+
+	mhu->clk = clk_get(&pdev->dev, "clk");
+	if (unlikely(IS_ERR(mhu->clk)))
+		dev_info(&pdev->dev, "unable to init clock\n");
+	else
+		clk_prepare_enable(mhu->clk);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mhu->base = ioremap(res->start, resource_size(res));
+	if (!mhu->base) {
+		dev_err(&pdev->dev, "ioremap failed.\n");
+		kfree(mhu);
+		return -EBUSY;
+	}
+
+	for (i = 0; i < 3; i++) {
+		mhu->chan[i].con_priv = &mhu->mlink[i];
+		res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+		mhu->mlink[i].irq = res->start;
+		mhu->mlink[i].rx_reg = mhu->base + mhu_reg[i];
+		mhu->mlink[i].tx_reg = mhu->mlink[i].rx_reg + 0x100;
+	}
+
+	mhu->mbox.dev = &pdev->dev;
+	mhu->mbox.chans = &mhu->chan[0];
+	mhu->mbox.num_chans = 3;
+	mhu->mbox.ops = &mhu_ops;
+	mhu->mbox.txdone_irq = false;
+	mhu->mbox.txdone_poll = true;
+	mhu->mbox.txpoll_period = 10;
+
+	platform_set_drvdata(pdev, mhu);
+
+	err = mbox_controller_register(&mhu->mbox);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to register mailboxes %d\n", err);
+		iounmap(mhu->base);
+		kfree(mhu);
+	} else {
+		dev_info(&pdev->dev, "ARM MHU Mailbox registered\n");
+	}
+
+	return 0;
+}
+
+static int arm_mhu_remove(struct platform_device *pdev)
+{
+	struct arm_mhu *mhu = platform_get_drvdata(pdev);
+
+	mbox_controller_unregister(&mhu->mbox);
+
+	iounmap(mhu->base);
+
+	if (!IS_ERR(mhu->clk))
+		clk_disable_unprepare(mhu->clk);
+
+	kfree(mhu);
+	return 0;
+}
+
+static const struct of_device_id arm_mhu_dt_ids[] = {
+	{ .compatible = "arm,mbox-mhu" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, arm_mhu_dt_ids);
+
+static struct platform_driver arm_mhu_driver = {
+	.driver = {
+		.name = "arm_mhu",
+		.of_match_table = arm_mhu_dt_ids,
+	},
+	.probe = arm_mhu_probe,
+	.remove = arm_mhu_remove,
+};
+module_platform_driver(arm_mhu_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("ARM MHU Driver");
+MODULE_AUTHOR("Jassi Brar <jassisinghbrar@gmail.com>");
-- 
1.9.0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 3/8] ARM: MB86S7X: Add MCPM support
  2015-01-09 11:19 ` Vincent Yang
  (?)
  (?)
@ 2015-01-09 11:28 ` Vincent Yang
  2015-01-09 12:41   ` Russell King - ARM Linux
  2015-01-09 20:04   ` Nicolas Pitre
  -1 siblings, 2 replies; 39+ messages in thread
From: Vincent Yang @ 2015-01-09 11:28 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jassi Brar <jaswinder.singh@linaro.org>

The remote firmware(SCB) owns the SMP control. This MCPM driver gets
CPU/CLUSTER power up/down done by SCB over mailbox.

Signed-off-by: Andy Green <andy.green@linaro.org>
Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
Signed-off-by: Vincent Yang <Vincent.Yang@tw.fujitsu.com>
Signed-off-by: Tetsuya Nuriya <nuriya.tetsuya@jp.fujitsu.com>
---
 arch/arm/mach-mb86s7x/Makefile |   4 +-
 arch/arm/mach-mb86s7x/mcpm.c   | 315 +++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-mb86s7x/smc.S    |  27 ++++
 drivers/soc/mb86s7x/scb_mhu.c  |  14 ++
 include/soc/mb86s7x/scb_mhu.h  |   8 ++
 5 files changed, 367 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-mb86s7x/mcpm.c
 create mode 100644 arch/arm/mach-mb86s7x/smc.S

diff --git a/arch/arm/mach-mb86s7x/Makefile b/arch/arm/mach-mb86s7x/Makefile
index 97640b6..00e843c 100644
--- a/arch/arm/mach-mb86s7x/Makefile
+++ b/arch/arm/mach-mb86s7x/Makefile
@@ -1 +1,3 @@
-obj-$(CONFIG_ARCH_MB86S7X)	+= board.o
+obj-$(CONFIG_ARCH_MB86S7X)	+= board.o mcpm.o smc.o
+CFLAGS_smc.o			+= -march=armv7-a
+CFLAGS_mcpm.o			+= -march=armv7-a
diff --git a/arch/arm/mach-mb86s7x/mcpm.c b/arch/arm/mach-mb86s7x/mcpm.c
new file mode 100644
index 0000000..c278c6e
--- /dev/null
+++ b/arch/arm/mach-mb86s7x/mcpm.c
@@ -0,0 +1,315 @@
+/*
+ * arch/arm/mach-mb86s7x/mcpm.c
+ * Copyright:	(C) 2013-2015 Fujitsu Semiconductor Limited
+ * Copyright:	(C) 2015 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/cpu_pm.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/arm-cci.h>
+#include <linux/spinlock.h>
+#include <linux/suspend.h>
+#include <linux/of_device.h>
+#include <linux/irqchip/arm-gic.h>
+#include <linux/platform_device.h>
+
+#include <soc/mb86s7x/scb_mhu.h>
+
+#include <asm/mcpm.h>
+#include <asm/cp15.h>
+#include <asm/cputype.h>
+#include <asm/suspend.h>
+#include <asm/idmap.h>
+
+#define S7X_MAX_CLUSTER	2
+#define S7X_MAX_CPU	2
+
+#define MHU_SHM_OFFSET		0x3800
+#define TRAMPOLINE_OFFSET	0x3c00
+#define RESET_OFFSET		(TRAMPOLINE_OFFSET + 0x3fc)
+
+static arch_spinlock_t mb86s7x_pm_lock = __ARCH_SPIN_LOCK_UNLOCKED;
+static int mb86s7x_pm_use_count[S7X_MAX_CLUSTER][S7X_MAX_CPU];
+
+struct mb86s7x_cpu_gate {
+	u32 payload_size;
+	u32 cluster_class;
+	u32 cluster_id;
+	u32 cpu_id;
+#define SCB_CPU_STATE_OFF	0x0
+#define SCB_CPU_STATE_ON	0x1
+#define SCB_CPU_STATE_SUSP	0x2
+	u32 cpu_state;
+};
+
+static int mb86s7x_pm_power_up(unsigned int cpu, unsigned int cluster)
+{
+	int ret = 0;
+
+	if (cluster >= S7X_MAX_CLUSTER || cpu >= S7X_MAX_CPU)
+		return -EINVAL;
+
+	pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
+
+	local_irq_disable();
+	arch_spin_lock(&mb86s7x_pm_lock);
+
+	mb86s7x_pm_use_count[cluster][cpu]++;
+
+	if (mb86s7x_pm_use_count[cluster][cpu] == 1) {
+		struct mb86s7x_cpu_gate cmd;
+
+		mb86s7x_set_wficolor(cluster, cpu, AT_WFI_DO_NOTHING);
+		arch_spin_unlock(&mb86s7x_pm_lock);
+		local_irq_enable();
+
+		cmd.payload_size = sizeof(cmd);
+		cmd.cluster_class = 0;
+		cmd.cluster_id = cluster;
+		cmd.cpu_id = cpu;
+		cmd.cpu_state = SCB_CPU_STATE_ON;
+
+		pr_debug("%s:%d CMD Cl_Class-%u CL_ID-%u CPU_ID-%u STATE-%u}\n",
+			 __func__, __LINE__, cmd.cluster_class,
+			 cmd.cluster_id, cmd.cpu_id, cmd.cpu_state);
+
+		ret = mb86s7x_send_packet(CMD_CPU_CLOCK_GATE_SET_REQ,
+					  &cmd, sizeof(cmd));
+		if (ret < 0) {
+			pr_err("%s:%d failed!\n", __func__, __LINE__);
+			return ret;
+		}
+
+		pr_debug("%s:%d REP Cl_Class-%u CL_ID-%u CPU_ID-%u STATE-%u}\n",
+			 __func__, __LINE__, cmd.cluster_class,
+			 cmd.cluster_id, cmd.cpu_id, cmd.cpu_state);
+
+		if (cmd.cpu_state != SCB_CPU_STATE_ON)
+			return -ENODEV;
+	} else if (mb86s7x_pm_use_count[cluster][cpu] == 2) {
+		arch_spin_unlock(&mb86s7x_pm_lock);
+		local_irq_enable();
+	} else {
+		/*
+		 * The only possible values are:
+		 * 0 = CPU down
+		 * 1 = CPU (still) up
+		 * 2 = CPU requested to be up before it had a chance
+		 *     to actually make itself down.
+		 * Any other value is a bug.
+		 */
+		BUG();
+	}
+
+	return 0;
+}
+
+static void mb86s7x_pm_suspend(u64 ignored)
+{
+	unsigned int mpidr, cpu, cluster;
+	bool last_man = false, skip_wfi = false;
+
+	mpidr = read_cpuid_mpidr();
+	cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+	cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+
+	pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
+	__mcpm_cpu_going_down(cpu, cluster);
+
+	arch_spin_lock(&mb86s7x_pm_lock);
+	BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP);
+
+	mb86s7x_pm_use_count[cluster][cpu]--;
+
+	if (mb86s7x_pm_use_count[cluster][cpu] == 0) {
+		if (!mb86s7x_pm_use_count[cluster][0] &&
+		    !mb86s7x_pm_use_count[cluster][1])
+			last_man = true;
+		mb86s7x_set_wficolor(cluster, cpu, AT_WFI_DO_POWEROFF);
+	} else if (mb86s7x_pm_use_count[cluster][cpu] == 1) {
+		skip_wfi = true; /* Overtaken by a power up */
+	} else {
+		BUG();
+	}
+
+	if (!skip_wfi)
+		gic_cpu_if_down();
+
+	if (last_man && __mcpm_outbound_enter_critical(cpu, cluster)) {
+		arch_spin_unlock(&mb86s7x_pm_lock);
+
+		if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) {
+			/*
+			 * On the Cortex-A15 we need to disable
+			 * L2 prefetching before flushing the cache.
+			 */
+			asm volatile(
+			"mcr p15, 1, %0, c15, c0, 3\n\t"
+			"isb\n\t"
+			"dsb"
+			: : "r" (0x400));
+		}
+
+		v7_exit_coherency_flush(all);
+
+		cci_disable_port_by_cpu(mpidr);
+
+		__mcpm_outbound_leave_critical(cluster, CLUSTER_DOWN);
+	} else {
+		arch_spin_unlock(&mb86s7x_pm_lock);
+		v7_exit_coherency_flush(louis);
+	}
+
+	__mcpm_cpu_down(cpu, cluster);
+
+	/* Now we are prepared for power-down, do it: */
+	if (!skip_wfi)
+		wfi();
+}
+
+static void mb86s7x_pm_power_down(void)
+{
+	mb86s7x_pm_suspend(0);
+}
+
+static int mb86s7x_wait_for_powerdown(unsigned int cpu, unsigned int cluster)
+{
+	struct mb86s7x_cpu_gate cmd;
+	int i, ret;
+
+	BUG_ON(cluster >= S7X_MAX_CLUSTER || cpu >= S7X_MAX_CPU);
+
+	cmd.payload_size = sizeof(cmd);
+	cmd.cluster_class = 0;
+	cmd.cluster_id = cluster;
+	cmd.cpu_id = cpu;
+	cmd.cpu_state = SCB_CPU_STATE_ON;
+
+	for (i = 0; i < 50; i++) {
+		ret = mb86s7x_send_packet(CMD_CPU_CLOCK_GATE_GET_REQ,
+					  &cmd, sizeof(cmd));
+		if (ret < 0) {
+			pr_err("%s:%d failed to get CPU status\n",
+			       __func__, __LINE__);
+			return ret;
+		}
+
+		pr_debug("%s:%d Cl_Class-%u CL_ID-%u CPU_ID-%u STATE-%u\n",
+			 __func__, __LINE__,
+			 cmd.cluster_class, cmd.cluster_id,
+			 cmd.cpu_id, cmd.cpu_state);
+
+		if (cmd.cpu_state == SCB_CPU_STATE_OFF)
+			return 0;
+
+		msleep(20);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static void mb86s7x_pm_powered_up(void)
+{
+	unsigned int mpidr, cpu, cluster;
+
+	mpidr = read_cpuid_mpidr();
+	cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+	cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+
+	arch_spin_lock(&mb86s7x_pm_lock);
+	if (!mb86s7x_pm_use_count[cluster][cpu])
+		mb86s7x_pm_use_count[cluster][cpu] = 1;
+	arch_spin_unlock(&mb86s7x_pm_lock);
+}
+
+static const struct mcpm_platform_ops mb86s7x_pm_power_ops = {
+	.power_up		= mb86s7x_pm_power_up,
+	.power_down		= mb86s7x_pm_power_down,
+	.wait_for_powerdown	= mb86s7x_wait_for_powerdown,
+	.suspend		= mb86s7x_pm_suspend,
+	.powered_up		= mb86s7x_pm_powered_up,
+};
+
+/*
+ * Enable cluster-level coherency, in preparation for turning on the MMU.
+ */
+static void __naked mb86s7x_pm_power_up_setup(unsigned int affinity_level)
+{
+	asm volatile ("\n"
+"	cmp	r0, #1\n"
+"	bxne	lr\n"
+"	b	cci_enable_port_for_self");
+}
+
+static void __init mb86s7x_cache_off(void)
+{
+	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) {
+		/* disable L2 prefetching on the Cortex-A15 */
+		asm volatile(
+		"mcr	p15, 1, %0, c15, c0, 3\n\t"
+		"isb\n\t"
+		"dsb"
+		: : "r" (0x400));
+	}
+	v7_exit_coherency_flush(all);
+}
+
+struct mb86s7x_scb_version {
+	u32 payload_size;
+	u32 version;
+	u32 config_version;
+};
+
+static int __init mb86s7x_mcpm_init(void)
+{
+	unsigned int mpidr, cpu, cluster;
+	struct mb86s7x_scb_version cmd;
+	int ret;
+
+	if (!cci_probed())
+		return -ENODEV;
+
+	mpidr = read_cpuid_mpidr();
+	cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+	cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+
+	pr_info("Booting on cpu_%u cluster_%u\n", cpu, cluster);
+	mb86s7x_pm_use_count[cluster][cpu] = 1;
+
+	/* reset the wfi 'color' for primary cpu */
+	mb86s7x_set_wficolor(cluster, cpu, AT_WFI_DO_NOTHING);
+
+	/* Do SMC to set entry address for CPUs coming online */
+	mb86s7x_cpu_entry(virt_to_phys(mcpm_entry_point));
+
+	cmd.payload_size = sizeof(cmd);
+	cmd.version = 0;
+	cmd.config_version = 0;
+	ret = mb86s7x_send_packet(CMD_SCB_CAPABILITY_GET_REQ,
+				  &cmd, sizeof(cmd));
+	if (ret < 0) /* non fatal */
+		pr_err("%s:%d failed to get SCB version\n",
+		       __func__, __LINE__);
+	else
+		pr_err("MB86S7x SCB version 0x%x:0x%x\n",
+		       cmd.version, cmd.config_version);
+
+	ret = mcpm_platform_register(&mb86s7x_pm_power_ops);
+	if (!ret)
+		ret = mcpm_sync_init(mb86s7x_pm_power_up_setup);
+	if (!ret)
+		ret = mcpm_loopback(mb86s7x_cache_off); /* turn on the CCI */
+	if (!ret)
+		mcpm_smp_set_ops();
+
+	return ret;
+}
+early_initcall(mb86s7x_mcpm_init);
diff --git a/arch/arm/mach-mb86s7x/smc.S b/arch/arm/mach-mb86s7x/smc.S
new file mode 100644
index 0000000..3ffe4f7
--- /dev/null
+++ b/arch/arm/mach-mb86s7x/smc.S
@@ -0,0 +1,27 @@
+/*
+ * SMC command interface to set secondary entry point
+ * Copyright: (C) 2013-2015 Fujitsu Semiconductor Limited
+ * Copyright: (C) 2015 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+
+.arch_extension sec
+
+/* void mb86s7x_cpu_entry(unsigned long secondary_entry); */
+ENTRY(mb86s7x_cpu_entry)
+	stmfd   sp!, {r1-r11, lr}
+	mov r1, r0
+	ldr r0, =1
+	mrc p15, 0, r3, c1, c0, 0
+	mov r4, r3
+	and r3, #0xbfffffff
+	mcr p15, 0, r3, c1, c0, 0
+	smc #0
+	mcr p15, 0, r4, c1, c0, 0
+	ldmfd   sp!, {r1-r11, pc}
+ENDPROC(mb86s7x_cpu_entry)
diff --git a/drivers/soc/mb86s7x/scb_mhu.c b/drivers/soc/mb86s7x/scb_mhu.c
index 08a3c88..a86ed0a 100644
--- a/drivers/soc/mb86s7x/scb_mhu.c
+++ b/drivers/soc/mb86s7x/scb_mhu.c
@@ -89,6 +89,20 @@ static struct mhu_xfer {
 	struct list_head node;
 } *ax; /* stages of xfer */
 
+#define WFI_COLOR_OFFSET	0x3f00
+
+void mb86s7x_set_wficolor(unsigned clstr, unsigned cpu, unsigned clr)
+{
+	u8 val;
+
+	val = readb_relaxed(mb86s7x_shm_base
+			    + WFI_COLOR_OFFSET + clstr * 2 + cpu);
+	val &= ~AT_WFI_COLOR_MASK;
+	val |= clr;
+	writeb_relaxed(val, mb86s7x_shm_base
+		       + WFI_COLOR_OFFSET + clstr * 2 + cpu);
+}
+
 static int mhu_alloc_xfers(int n, struct list_head *list)
 {
 	struct mhu_xfer *x = kcalloc(n, sizeof(struct mhu_xfer), GFP_ATOMIC);
diff --git a/include/soc/mb86s7x/scb_mhu.h b/include/soc/mb86s7x/scb_mhu.h
index 334fa9f..f792950 100644
--- a/include/soc/mb86s7x/scb_mhu.h
+++ b/include/soc/mb86s7x/scb_mhu.h
@@ -87,6 +87,14 @@ enum {
 #define CMD_POWERDOMAIN_SET_REP		ENC_REP(CMD_POWERDOMAIN_SET_REQ)
 #define CMD_STG_BLOCK_ERASE_REP		ENC_REP(CMD_STG_BLOCK_ERASE_REQ)
 
+#define AT_WFI_DO_NOTHING	0x0
+#define AT_WFI_DO_SUSPEND	0x1
+#define AT_WFI_DO_POWEROFF	0x2
+#define AT_WFI_COLOR_MASK	0x3
+
+void mb86s7x_set_wficolor(unsigned clstr, unsigned cpu, unsigned clr);
+void mb86s7x_cpu_entry(unsigned long secondary_entry);
+
 /* Helper functions to talk to remote */
 int mb86s7x_send_packet(int cmd, void *buf, int len);
 
-- 
1.9.0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 4/8] clk: Add clock driver for mb86s7x
  2015-01-09 11:19 ` Vincent Yang
@ 2015-01-09 11:29     ` Vincent Yang
  -1 siblings, 0 replies; 39+ messages in thread
From: Vincent Yang @ 2015-01-09 11:29 UTC (permalink / raw)
  To: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: arnd-r2nGTMty4D4, olof-nZhT3qVonbNeoWH0uzbU5w,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	pawel.moll-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
	ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ, mturquette-QSEj5FYQhm4dnm+yROfE0A,
	andy.green-QSEj5FYQhm4dnm+yROfE0A,
	patches-QSEj5FYQhm4dnm+yROfE0A,
	jaswinder.singh-QSEj5FYQhm4dnm+yROfE0A, Vincent Yang,
	Tetsuya Nuriya

From: Jassi Brar <jaswinder.singh-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

 The CRG11 clock controller is managed by remote f/w.
This driver simply maps Linux CLK ops onto mailbox api.

Signed-off-by: Andy Green <andy.green-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Signed-off-by: Jassi Brar <jaswinder.singh-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Signed-off-by: Vincent Yang <Vincent.Yang-l16TxrwUIHTQFUHtdCDX3A@public.gmane.org>
Signed-off-by: Tetsuya Nuriya <nuriya.tetsuya-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
---
 .../bindings/clock/fujitsu,mb86s70-crg11.txt       |  26 ++
 drivers/clk/Makefile                               |   1 +
 drivers/clk/clk-mb86s7x.c                          | 379 +++++++++++++++++++++
 3 files changed, 406 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/fujitsu,mb86s70-crg11.txt
 create mode 100644 drivers/clk/clk-mb86s7x.c

diff --git a/Documentation/devicetree/bindings/clock/fujitsu,mb86s70-crg11.txt b/Documentation/devicetree/bindings/clock/fujitsu,mb86s70-crg11.txt
new file mode 100644
index 0000000..f692d0b
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/fujitsu,mb86s70-crg11.txt
@@ -0,0 +1,26 @@
+Fujitsu CRG11 clock driver bindings
+-----------------------------------
+
+Required properties :
+- compatible : Shall contain "fujitsu,mb86s70-crg11"
+- #clock-cells : Shall be 3 {cntrlr domain port}
+
+The consumer specifies the desired clock pointing to its phandle.
+
+Example:
+
+	clock: crg11 {
+		compatible = "fujitsu,mb86s70-crg11";
+		#clock-cells = <3>;
+	};
+
+	mhu: mhu0@2b1f0000 {
+		#mbox-cells = <1>;
+		compatible = "arm,mbox-mhu";
+		reg = <0 0x2B1F0000 0x1000>;
+		interrupts = <0 36 4>, /* LP Non-Sec */
+			     <0 35 4>, /* HP Non-Sec */
+			     <0 37 4>; /* Secure */
+		clocks = <&clock 0 2 1>; /* Cntrlr:0 Domain:2 Port:1 */
+		clock-names = "clk";
+	};
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index d5fba5b..19d73a1 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_MACH_LOONGSON1)		+= clk-ls1x.o
 obj-$(CONFIG_COMMON_CLK_MAX_GEN)	+= clk-max-gen.o
 obj-$(CONFIG_COMMON_CLK_MAX77686)	+= clk-max77686.o
 obj-$(CONFIG_COMMON_CLK_MAX77802)	+= clk-max77802.o
+obj-$(CONFIG_ARCH_MB86S7X)		+= clk-mb86s7x.o
 obj-$(CONFIG_ARCH_MOXART)		+= clk-moxart.o
 obj-$(CONFIG_ARCH_NOMADIK)		+= clk-nomadik.o
 obj-$(CONFIG_ARCH_NSPIRE)		+= clk-nspire.o
diff --git a/drivers/clk/clk-mb86s7x.c b/drivers/clk/clk-mb86s7x.c
new file mode 100644
index 0000000..6c38928
--- /dev/null
+++ b/drivers/clk/clk-mb86s7x.c
@@ -0,0 +1,379 @@
+/*
+ * Copyright (C) 2013-2015 FUJITSU SEMICONDUCTOR LIMITED
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * 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, version 2 of the License.
+ *
+ * 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.
+ */
+
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/cpu.h>
+#include <linux/clk-provider.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/topology.h>
+#include <linux/mailbox_client.h>
+#include <linux/platform_device.h>
+
+#include <soc/mb86s7x/scb_mhu.h>
+
+#define to_crg_clk(p) container_of(p, struct crg_clk, hw)
+#define to_clc_clk(p) container_of(p, struct cl_clk, hw)
+
+struct mb86s7x_peri_clk {
+	u32 payload_size;
+	u32 cntrlr;
+	u32 domain;
+	u32 port;
+	u32 en;
+	u64 freqency;
+} __packed __aligned(4);
+
+struct hack_rate {
+	unsigned clk_id;
+	unsigned long rate;
+	int gated;
+};
+
+struct crg_clk {
+	struct clk_hw hw;
+	u8 cntrlr, domain, port;
+};
+
+static int crg_gate_control(struct clk_hw *hw, int en)
+{
+	struct crg_clk *crgclk = to_crg_clk(hw);
+	struct mb86s7x_peri_clk cmd;
+	int ret;
+
+	cmd.payload_size = sizeof(cmd);
+	cmd.cntrlr = crgclk->cntrlr;
+	cmd.domain = crgclk->domain;
+	cmd.port = crgclk->port;
+	cmd.en = en;
+
+	/* Port is UngatedCLK */
+	if (cmd.port == 8)
+		return en ? 0 : -EINVAL;
+
+	pr_debug("%s:%d CMD Cntrlr-%u Dom-%u Port-%u En-%u}\n",
+		 __func__, __LINE__, cmd.cntrlr,
+		 cmd.domain, cmd.port, cmd.en);
+
+	ret = mb86s7x_send_packet(CMD_PERI_CLOCK_GATE_SET_REQ,
+				  &cmd, sizeof(cmd));
+	if (ret < 0) {
+		pr_err("%s:%d failed!\n", __func__, __LINE__);
+		return ret;
+	}
+
+	pr_debug("%s:%d REP Cntrlr-%u Dom-%u Port-%u En-%u}\n",
+		 __func__, __LINE__, cmd.cntrlr,
+		 cmd.domain, cmd.port, cmd.en);
+
+	/* If the request was rejected */
+	if (cmd.en != en)
+		ret = -EINVAL;
+	else
+		ret = 0;
+
+	return ret;
+}
+
+static int crg_port_prepare(struct clk_hw *hw)
+{
+	return crg_gate_control(hw, 1);
+}
+
+static void crg_port_unprepare(struct clk_hw *hw)
+{
+	crg_gate_control(hw, 0);
+}
+
+static int
+crg_rate_control(struct clk_hw *hw, int set, unsigned long *rate)
+{
+	struct crg_clk *crgclk = to_crg_clk(hw);
+	struct mb86s7x_peri_clk cmd;
+	int code, ret;
+
+	cmd.payload_size = sizeof(cmd);
+	cmd.cntrlr = crgclk->cntrlr;
+	cmd.domain = crgclk->domain;
+	cmd.port = crgclk->port;
+	cmd.freqency = *rate;
+
+	if (set) {
+		code = CMD_PERI_CLOCK_RATE_SET_REQ;
+		pr_debug("%s:%d CMD Cntrlr-%u Dom-%u Port-%u Rate-SET %lluHz}\n",
+			 __func__, __LINE__, cmd.cntrlr,
+			 cmd.domain, cmd.port, cmd.freqency);
+	} else {
+		code = CMD_PERI_CLOCK_RATE_GET_REQ;
+		pr_debug("%s:%d CMD Cntrlr-%u Dom-%u Port-%u Rate-GET}\n",
+			 __func__, __LINE__, cmd.cntrlr,
+			 cmd.domain, cmd.port);
+	}
+
+	ret = mb86s7x_send_packet(code, &cmd, sizeof(cmd));
+	if (ret < 0) {
+		pr_err("%s:%d failed!\n", __func__, __LINE__);
+		return ret;
+	}
+
+	if (set)
+		pr_debug("%s:%d REP Cntrlr-%u Dom-%u Port-%u Rate-SET %lluHz}\n",
+			 __func__, __LINE__, cmd.cntrlr,
+			 cmd.domain, cmd.port, cmd.freqency);
+	else
+		pr_debug("%s:%d REP Cntrlr-%u Dom-%u Port-%u Rate-GOT %lluHz}\n",
+			 __func__, __LINE__, cmd.cntrlr,
+			 cmd.domain, cmd.port, cmd.freqency);
+
+	*rate = cmd.freqency;
+	return 0;
+}
+
+static unsigned long
+crg_port_recalc_rate(struct clk_hw *hw,	unsigned long parent_rate)
+{
+	unsigned long rate;
+
+	crg_rate_control(hw, 0, &rate);
+
+	return rate;
+}
+
+static long
+crg_port_round_rate(struct clk_hw *hw,
+		    unsigned long rate, unsigned long *pr)
+{
+	return rate;
+}
+
+static int
+crg_port_set_rate(struct clk_hw *hw,
+		  unsigned long rate, unsigned long parent_rate)
+{
+	return crg_rate_control(hw, 1, &rate);
+}
+
+const struct clk_ops crg_port_ops = {
+	.prepare = crg_port_prepare,
+	.unprepare = crg_port_unprepare,
+	.recalc_rate = crg_port_recalc_rate,
+	.round_rate = crg_port_round_rate,
+	.set_rate = crg_port_set_rate,
+};
+
+struct mb86s70_crg11 {
+	struct mutex lock; /* protects CLK populating and searching */
+};
+
+static struct clk *crg11_get(struct of_phandle_args *clkspec, void *data)
+{
+	struct mb86s70_crg11 *crg11 = data;
+	struct clk_init_data init;
+	u32 cntrlr, domain, port;
+	struct crg_clk *crgclk;
+	struct clk *clk;
+	char clkp[20];
+
+	if (clkspec->args_count != 3)
+		return ERR_PTR(-EINVAL);
+
+	cntrlr = clkspec->args[0];
+	domain = clkspec->args[1];
+	port = clkspec->args[2];
+
+	if (port > 7)
+		snprintf(clkp, 20, "UngatedCLK%d_%X", cntrlr, domain);
+	else
+		snprintf(clkp, 20, "CLK%d_%X_%d", cntrlr, domain, port);
+
+	mutex_lock(&crg11->lock);
+
+	clk = __clk_lookup(clkp);
+	if (clk) {
+		mutex_unlock(&crg11->lock);
+		return clk;
+	}
+
+	crgclk = kzalloc(sizeof(*crgclk), GFP_KERNEL);
+	if (!crgclk) {
+		mutex_unlock(&crg11->lock);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	init.name = clkp;
+	init.num_parents = 0;
+	init.ops = &crg_port_ops;
+	init.flags = CLK_IS_ROOT;
+	crgclk->hw.init = &init;
+	crgclk->cntrlr = cntrlr;
+	crgclk->domain = domain;
+	crgclk->port = port;
+	clk = clk_register(NULL, &crgclk->hw);
+	if (IS_ERR(clk))
+		pr_err("%s:%d Error!\n", __func__, __LINE__);
+	else
+		pr_debug("Registered %s\n", clkp);
+
+	clk_register_clkdev(clk, clkp, NULL);
+	mutex_unlock(&crg11->lock);
+	return clk;
+}
+
+static void __init crg_port_init(struct device_node *node)
+{
+	struct mb86s70_crg11 *crg11;
+
+	crg11 = kzalloc(sizeof(*crg11), GFP_KERNEL);
+	if (!crg11)
+		return;
+
+	mutex_init(&crg11->lock);
+
+	of_clk_add_provider(node, crg11_get, crg11);
+}
+CLK_OF_DECLARE(crg11_gate, "fujitsu,mb86s70-crg11", crg_port_init);
+
+struct cl_clk {
+	struct clk_hw hw;
+	int cluster;
+};
+
+struct mb86s7x_cpu_freq {
+	u32 payload_size;
+	u32 cluster_class;
+	u32 cluster_id;
+	u32 cpu_id;
+	u64 freqency;
+};
+
+static void mhu_cluster_rate(struct clk_hw *hw, unsigned long *rate, int get)
+{
+	struct cl_clk *clc = to_clc_clk(hw);
+	struct mb86s7x_cpu_freq cmd;
+	int code, ret;
+
+	cmd.payload_size = sizeof(cmd);
+	cmd.cluster_class = 0;
+	cmd.cluster_id = clc->cluster;
+	cmd.cpu_id = 0;
+	cmd.freqency = *rate;
+
+	if (get)
+		code = CMD_CPU_CLOCK_RATE_GET_REQ;
+	else
+		code = CMD_CPU_CLOCK_RATE_SET_REQ;
+
+	pr_debug("%s:%d CMD Cl_Class-%u CL_ID-%u CPU_ID-%u Freq-%llu}\n",
+		 __func__, __LINE__, cmd.cluster_class,
+		 cmd.cluster_id, cmd.cpu_id, cmd.freqency);
+
+	ret = mb86s7x_send_packet(code, &cmd, sizeof(cmd));
+	if (ret < 0) {
+		pr_err("%s:%d failed!\n", __func__, __LINE__);
+		return;
+	}
+
+	pr_debug("%s:%d REP Cl_Class-%u CL_ID-%u CPU_ID-%u Freq-%llu}\n",
+		 __func__, __LINE__, cmd.cluster_class,
+		 cmd.cluster_id, cmd.cpu_id, cmd.freqency);
+
+	*rate = cmd.freqency;
+}
+
+static unsigned long
+clc_recalc_rate(struct clk_hw *hw, unsigned long unused)
+{
+	unsigned long rate;
+
+	mhu_cluster_rate(hw, &rate, 1);
+	return rate;
+}
+
+static long
+clc_round_rate(struct clk_hw *hw, unsigned long rate,
+	       unsigned long *unused)
+{
+	return rate;
+}
+
+static int
+clc_set_rate(struct clk_hw *hw, unsigned long rate,
+	     unsigned long unused)
+{
+	unsigned long res = rate;
+
+	mhu_cluster_rate(hw, &res, 0);
+
+	return (res == rate) ? 0 : -EINVAL;
+}
+
+static struct clk_ops clk_clc_ops = {
+	.recalc_rate = clc_recalc_rate,
+	.round_rate = clc_round_rate,
+	.set_rate = clc_set_rate,
+};
+
+struct clk *mb86s7x_clclk_register(struct device *cpu_dev)
+{
+	struct clk_init_data init;
+	struct cl_clk *clc;
+
+	clc = kzalloc(sizeof(*clc), GFP_KERNEL);
+	if (!clc)
+		return ERR_PTR(-ENOMEM);
+
+	clc->hw.init = &init;
+	clc->cluster = topology_physical_package_id(cpu_dev->id);
+
+	init.name = dev_name(cpu_dev);
+	init.ops = &clk_clc_ops;
+	init.flags = CLK_IS_ROOT | CLK_GET_RATE_NOCACHE;
+	init.num_parents = 0;
+
+	return devm_clk_register(cpu_dev, &clc->hw);
+}
+
+static int mb86s7x_clclk_of_init(void)
+{
+	int cpu;
+	struct clk *clk;
+
+	for_each_possible_cpu(cpu) {
+		struct device *cpu_dev = get_cpu_device(cpu);
+
+		if (!cpu_dev) {
+			pr_err("failed to get cpu%d device\n", cpu);
+			continue;
+		}
+
+		clk = mb86s7x_clclk_register(cpu_dev);
+		if (IS_ERR(clk)) {
+			pr_err("failed to register cpu%d clock\n", cpu);
+			continue;
+		}
+		if (clk_register_clkdev(clk, NULL, dev_name(cpu_dev))) {
+			pr_err("failed to register cpu%d clock lookup\n", cpu);
+			continue;
+		}
+		pr_debug("registered clk for %s\n", dev_name(cpu_dev));
+	}
+
+	platform_device_register_simple("arm-bL-cpufreq-dt", -1, NULL, 0);
+
+	return 0;
+}
+module_init(mb86s7x_clclk_of_init);
-- 
1.9.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 4/8] clk: Add clock driver for mb86s7x
@ 2015-01-09 11:29     ` Vincent Yang
  0 siblings, 0 replies; 39+ messages in thread
From: Vincent Yang @ 2015-01-09 11:29 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jassi Brar <jaswinder.singh@linaro.org>

 The CRG11 clock controller is managed by remote f/w.
This driver simply maps Linux CLK ops onto mailbox api.

Signed-off-by: Andy Green <andy.green@linaro.org>
Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
Signed-off-by: Vincent Yang <Vincent.Yang@tw.fujitsu.com>
Signed-off-by: Tetsuya Nuriya <nuriya.tetsuya@jp.fujitsu.com>
---
 .../bindings/clock/fujitsu,mb86s70-crg11.txt       |  26 ++
 drivers/clk/Makefile                               |   1 +
 drivers/clk/clk-mb86s7x.c                          | 379 +++++++++++++++++++++
 3 files changed, 406 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/fujitsu,mb86s70-crg11.txt
 create mode 100644 drivers/clk/clk-mb86s7x.c

diff --git a/Documentation/devicetree/bindings/clock/fujitsu,mb86s70-crg11.txt b/Documentation/devicetree/bindings/clock/fujitsu,mb86s70-crg11.txt
new file mode 100644
index 0000000..f692d0b
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/fujitsu,mb86s70-crg11.txt
@@ -0,0 +1,26 @@
+Fujitsu CRG11 clock driver bindings
+-----------------------------------
+
+Required properties :
+- compatible : Shall contain "fujitsu,mb86s70-crg11"
+- #clock-cells : Shall be 3 {cntrlr domain port}
+
+The consumer specifies the desired clock pointing to its phandle.
+
+Example:
+
+	clock: crg11 {
+		compatible = "fujitsu,mb86s70-crg11";
+		#clock-cells = <3>;
+	};
+
+	mhu: mhu0 at 2b1f0000 {
+		#mbox-cells = <1>;
+		compatible = "arm,mbox-mhu";
+		reg = <0 0x2B1F0000 0x1000>;
+		interrupts = <0 36 4>, /* LP Non-Sec */
+			     <0 35 4>, /* HP Non-Sec */
+			     <0 37 4>; /* Secure */
+		clocks = <&clock 0 2 1>; /* Cntrlr:0 Domain:2 Port:1 */
+		clock-names = "clk";
+	};
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index d5fba5b..19d73a1 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_MACH_LOONGSON1)		+= clk-ls1x.o
 obj-$(CONFIG_COMMON_CLK_MAX_GEN)	+= clk-max-gen.o
 obj-$(CONFIG_COMMON_CLK_MAX77686)	+= clk-max77686.o
 obj-$(CONFIG_COMMON_CLK_MAX77802)	+= clk-max77802.o
+obj-$(CONFIG_ARCH_MB86S7X)		+= clk-mb86s7x.o
 obj-$(CONFIG_ARCH_MOXART)		+= clk-moxart.o
 obj-$(CONFIG_ARCH_NOMADIK)		+= clk-nomadik.o
 obj-$(CONFIG_ARCH_NSPIRE)		+= clk-nspire.o
diff --git a/drivers/clk/clk-mb86s7x.c b/drivers/clk/clk-mb86s7x.c
new file mode 100644
index 0000000..6c38928
--- /dev/null
+++ b/drivers/clk/clk-mb86s7x.c
@@ -0,0 +1,379 @@
+/*
+ * Copyright (C) 2013-2015 FUJITSU SEMICONDUCTOR LIMITED
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * 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, version 2 of the License.
+ *
+ * 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.
+ */
+
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/cpu.h>
+#include <linux/clk-provider.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/topology.h>
+#include <linux/mailbox_client.h>
+#include <linux/platform_device.h>
+
+#include <soc/mb86s7x/scb_mhu.h>
+
+#define to_crg_clk(p) container_of(p, struct crg_clk, hw)
+#define to_clc_clk(p) container_of(p, struct cl_clk, hw)
+
+struct mb86s7x_peri_clk {
+	u32 payload_size;
+	u32 cntrlr;
+	u32 domain;
+	u32 port;
+	u32 en;
+	u64 freqency;
+} __packed __aligned(4);
+
+struct hack_rate {
+	unsigned clk_id;
+	unsigned long rate;
+	int gated;
+};
+
+struct crg_clk {
+	struct clk_hw hw;
+	u8 cntrlr, domain, port;
+};
+
+static int crg_gate_control(struct clk_hw *hw, int en)
+{
+	struct crg_clk *crgclk = to_crg_clk(hw);
+	struct mb86s7x_peri_clk cmd;
+	int ret;
+
+	cmd.payload_size = sizeof(cmd);
+	cmd.cntrlr = crgclk->cntrlr;
+	cmd.domain = crgclk->domain;
+	cmd.port = crgclk->port;
+	cmd.en = en;
+
+	/* Port is UngatedCLK */
+	if (cmd.port == 8)
+		return en ? 0 : -EINVAL;
+
+	pr_debug("%s:%d CMD Cntrlr-%u Dom-%u Port-%u En-%u}\n",
+		 __func__, __LINE__, cmd.cntrlr,
+		 cmd.domain, cmd.port, cmd.en);
+
+	ret = mb86s7x_send_packet(CMD_PERI_CLOCK_GATE_SET_REQ,
+				  &cmd, sizeof(cmd));
+	if (ret < 0) {
+		pr_err("%s:%d failed!\n", __func__, __LINE__);
+		return ret;
+	}
+
+	pr_debug("%s:%d REP Cntrlr-%u Dom-%u Port-%u En-%u}\n",
+		 __func__, __LINE__, cmd.cntrlr,
+		 cmd.domain, cmd.port, cmd.en);
+
+	/* If the request was rejected */
+	if (cmd.en != en)
+		ret = -EINVAL;
+	else
+		ret = 0;
+
+	return ret;
+}
+
+static int crg_port_prepare(struct clk_hw *hw)
+{
+	return crg_gate_control(hw, 1);
+}
+
+static void crg_port_unprepare(struct clk_hw *hw)
+{
+	crg_gate_control(hw, 0);
+}
+
+static int
+crg_rate_control(struct clk_hw *hw, int set, unsigned long *rate)
+{
+	struct crg_clk *crgclk = to_crg_clk(hw);
+	struct mb86s7x_peri_clk cmd;
+	int code, ret;
+
+	cmd.payload_size = sizeof(cmd);
+	cmd.cntrlr = crgclk->cntrlr;
+	cmd.domain = crgclk->domain;
+	cmd.port = crgclk->port;
+	cmd.freqency = *rate;
+
+	if (set) {
+		code = CMD_PERI_CLOCK_RATE_SET_REQ;
+		pr_debug("%s:%d CMD Cntrlr-%u Dom-%u Port-%u Rate-SET %lluHz}\n",
+			 __func__, __LINE__, cmd.cntrlr,
+			 cmd.domain, cmd.port, cmd.freqency);
+	} else {
+		code = CMD_PERI_CLOCK_RATE_GET_REQ;
+		pr_debug("%s:%d CMD Cntrlr-%u Dom-%u Port-%u Rate-GET}\n",
+			 __func__, __LINE__, cmd.cntrlr,
+			 cmd.domain, cmd.port);
+	}
+
+	ret = mb86s7x_send_packet(code, &cmd, sizeof(cmd));
+	if (ret < 0) {
+		pr_err("%s:%d failed!\n", __func__, __LINE__);
+		return ret;
+	}
+
+	if (set)
+		pr_debug("%s:%d REP Cntrlr-%u Dom-%u Port-%u Rate-SET %lluHz}\n",
+			 __func__, __LINE__, cmd.cntrlr,
+			 cmd.domain, cmd.port, cmd.freqency);
+	else
+		pr_debug("%s:%d REP Cntrlr-%u Dom-%u Port-%u Rate-GOT %lluHz}\n",
+			 __func__, __LINE__, cmd.cntrlr,
+			 cmd.domain, cmd.port, cmd.freqency);
+
+	*rate = cmd.freqency;
+	return 0;
+}
+
+static unsigned long
+crg_port_recalc_rate(struct clk_hw *hw,	unsigned long parent_rate)
+{
+	unsigned long rate;
+
+	crg_rate_control(hw, 0, &rate);
+
+	return rate;
+}
+
+static long
+crg_port_round_rate(struct clk_hw *hw,
+		    unsigned long rate, unsigned long *pr)
+{
+	return rate;
+}
+
+static int
+crg_port_set_rate(struct clk_hw *hw,
+		  unsigned long rate, unsigned long parent_rate)
+{
+	return crg_rate_control(hw, 1, &rate);
+}
+
+const struct clk_ops crg_port_ops = {
+	.prepare = crg_port_prepare,
+	.unprepare = crg_port_unprepare,
+	.recalc_rate = crg_port_recalc_rate,
+	.round_rate = crg_port_round_rate,
+	.set_rate = crg_port_set_rate,
+};
+
+struct mb86s70_crg11 {
+	struct mutex lock; /* protects CLK populating and searching */
+};
+
+static struct clk *crg11_get(struct of_phandle_args *clkspec, void *data)
+{
+	struct mb86s70_crg11 *crg11 = data;
+	struct clk_init_data init;
+	u32 cntrlr, domain, port;
+	struct crg_clk *crgclk;
+	struct clk *clk;
+	char clkp[20];
+
+	if (clkspec->args_count != 3)
+		return ERR_PTR(-EINVAL);
+
+	cntrlr = clkspec->args[0];
+	domain = clkspec->args[1];
+	port = clkspec->args[2];
+
+	if (port > 7)
+		snprintf(clkp, 20, "UngatedCLK%d_%X", cntrlr, domain);
+	else
+		snprintf(clkp, 20, "CLK%d_%X_%d", cntrlr, domain, port);
+
+	mutex_lock(&crg11->lock);
+
+	clk = __clk_lookup(clkp);
+	if (clk) {
+		mutex_unlock(&crg11->lock);
+		return clk;
+	}
+
+	crgclk = kzalloc(sizeof(*crgclk), GFP_KERNEL);
+	if (!crgclk) {
+		mutex_unlock(&crg11->lock);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	init.name = clkp;
+	init.num_parents = 0;
+	init.ops = &crg_port_ops;
+	init.flags = CLK_IS_ROOT;
+	crgclk->hw.init = &init;
+	crgclk->cntrlr = cntrlr;
+	crgclk->domain = domain;
+	crgclk->port = port;
+	clk = clk_register(NULL, &crgclk->hw);
+	if (IS_ERR(clk))
+		pr_err("%s:%d Error!\n", __func__, __LINE__);
+	else
+		pr_debug("Registered %s\n", clkp);
+
+	clk_register_clkdev(clk, clkp, NULL);
+	mutex_unlock(&crg11->lock);
+	return clk;
+}
+
+static void __init crg_port_init(struct device_node *node)
+{
+	struct mb86s70_crg11 *crg11;
+
+	crg11 = kzalloc(sizeof(*crg11), GFP_KERNEL);
+	if (!crg11)
+		return;
+
+	mutex_init(&crg11->lock);
+
+	of_clk_add_provider(node, crg11_get, crg11);
+}
+CLK_OF_DECLARE(crg11_gate, "fujitsu,mb86s70-crg11", crg_port_init);
+
+struct cl_clk {
+	struct clk_hw hw;
+	int cluster;
+};
+
+struct mb86s7x_cpu_freq {
+	u32 payload_size;
+	u32 cluster_class;
+	u32 cluster_id;
+	u32 cpu_id;
+	u64 freqency;
+};
+
+static void mhu_cluster_rate(struct clk_hw *hw, unsigned long *rate, int get)
+{
+	struct cl_clk *clc = to_clc_clk(hw);
+	struct mb86s7x_cpu_freq cmd;
+	int code, ret;
+
+	cmd.payload_size = sizeof(cmd);
+	cmd.cluster_class = 0;
+	cmd.cluster_id = clc->cluster;
+	cmd.cpu_id = 0;
+	cmd.freqency = *rate;
+
+	if (get)
+		code = CMD_CPU_CLOCK_RATE_GET_REQ;
+	else
+		code = CMD_CPU_CLOCK_RATE_SET_REQ;
+
+	pr_debug("%s:%d CMD Cl_Class-%u CL_ID-%u CPU_ID-%u Freq-%llu}\n",
+		 __func__, __LINE__, cmd.cluster_class,
+		 cmd.cluster_id, cmd.cpu_id, cmd.freqency);
+
+	ret = mb86s7x_send_packet(code, &cmd, sizeof(cmd));
+	if (ret < 0) {
+		pr_err("%s:%d failed!\n", __func__, __LINE__);
+		return;
+	}
+
+	pr_debug("%s:%d REP Cl_Class-%u CL_ID-%u CPU_ID-%u Freq-%llu}\n",
+		 __func__, __LINE__, cmd.cluster_class,
+		 cmd.cluster_id, cmd.cpu_id, cmd.freqency);
+
+	*rate = cmd.freqency;
+}
+
+static unsigned long
+clc_recalc_rate(struct clk_hw *hw, unsigned long unused)
+{
+	unsigned long rate;
+
+	mhu_cluster_rate(hw, &rate, 1);
+	return rate;
+}
+
+static long
+clc_round_rate(struct clk_hw *hw, unsigned long rate,
+	       unsigned long *unused)
+{
+	return rate;
+}
+
+static int
+clc_set_rate(struct clk_hw *hw, unsigned long rate,
+	     unsigned long unused)
+{
+	unsigned long res = rate;
+
+	mhu_cluster_rate(hw, &res, 0);
+
+	return (res == rate) ? 0 : -EINVAL;
+}
+
+static struct clk_ops clk_clc_ops = {
+	.recalc_rate = clc_recalc_rate,
+	.round_rate = clc_round_rate,
+	.set_rate = clc_set_rate,
+};
+
+struct clk *mb86s7x_clclk_register(struct device *cpu_dev)
+{
+	struct clk_init_data init;
+	struct cl_clk *clc;
+
+	clc = kzalloc(sizeof(*clc), GFP_KERNEL);
+	if (!clc)
+		return ERR_PTR(-ENOMEM);
+
+	clc->hw.init = &init;
+	clc->cluster = topology_physical_package_id(cpu_dev->id);
+
+	init.name = dev_name(cpu_dev);
+	init.ops = &clk_clc_ops;
+	init.flags = CLK_IS_ROOT | CLK_GET_RATE_NOCACHE;
+	init.num_parents = 0;
+
+	return devm_clk_register(cpu_dev, &clc->hw);
+}
+
+static int mb86s7x_clclk_of_init(void)
+{
+	int cpu;
+	struct clk *clk;
+
+	for_each_possible_cpu(cpu) {
+		struct device *cpu_dev = get_cpu_device(cpu);
+
+		if (!cpu_dev) {
+			pr_err("failed to get cpu%d device\n", cpu);
+			continue;
+		}
+
+		clk = mb86s7x_clclk_register(cpu_dev);
+		if (IS_ERR(clk)) {
+			pr_err("failed to register cpu%d clock\n", cpu);
+			continue;
+		}
+		if (clk_register_clkdev(clk, NULL, dev_name(cpu_dev))) {
+			pr_err("failed to register cpu%d clock lookup\n", cpu);
+			continue;
+		}
+		pr_debug("registered clk for %s\n", dev_name(cpu_dev));
+	}
+
+	platform_device_register_simple("arm-bL-cpufreq-dt", -1, NULL, 0);
+
+	return 0;
+}
+module_init(mb86s7x_clclk_of_init);
-- 
1.9.0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 5/8] gpio: Add Fujitsu MB86S7x GPIO driver
  2015-01-09 11:19 ` Vincent Yang
@ 2015-01-09 11:33   ` Vincent Yang
  -1 siblings, 0 replies; 39+ messages in thread
From: Vincent Yang @ 2015-01-09 11:33 UTC (permalink / raw)
  To: devicetree, linux-gpio, linux-arm-kernel
  Cc: arnd, olof, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, grant.likely, linus.walleij, gnurou, andy.green, patches,
	jaswinder.singh, Vincent Yang, Tetsuya Nuriya

From: Jassi Brar <jaswinder.singh@linaro.org>

Driver for Fujitsu MB86S7x SoCs that have a memory mapped GPIO controller.

Signed-off-by: Andy Green <andy.green@linaro.org>
Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
Signed-off-by: Vincent Yang <Vincent.Yang@tw.fujitsu.com>
Signed-off-by: Tetsuya Nuriya <nuriya.tetsuya@jp.fujitsu.com>
---
 .../bindings/gpio/fujitsu,mb86s70-gpio.txt         |  20 ++
 drivers/gpio/Kconfig                               |   6 +
 drivers/gpio/Makefile                              |   1 +
 drivers/gpio/gpio-mb86s7x.c                        | 231 +++++++++++++++++++++
 4 files changed, 258 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/gpio/fujitsu,mb86s70-gpio.txt
 create mode 100644 drivers/gpio/gpio-mb86s7x.c

diff --git a/Documentation/devicetree/bindings/gpio/fujitsu,mb86s70-gpio.txt b/Documentation/devicetree/bindings/gpio/fujitsu,mb86s70-gpio.txt
new file mode 100644
index 0000000..bef353f
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/fujitsu,mb86s70-gpio.txt
@@ -0,0 +1,20 @@
+Fujitsu MB86S7x GPIO Controller
+-------------------------------
+
+Required properties:
+- compatible: Should be "fujitsu,mb86s70-gpio"
+- reg: Base address and length of register space
+- clocks: Specify the clock
+- gpio-controller: Marks the device node as a gpio controller.
+- #gpio-cells: Should be <2>. The first cell is the pin number and the
+  second cell is used to specify optional parameters:
+   - bit 0 specifies polarity (0 for normal, 1 for inverted).
+
+Examples:
+	gpio0: gpio@31000000 {
+		compatible = "fujitsu,mb86s70-gpio";
+		reg = <0 0x31000000 0x10000>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		clocks = <&clk 0 2 1>;
+	};
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 633ec21..699e629 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -197,6 +197,12 @@ config GPIO_F7188X
 	  To compile this driver as a module, choose M here: the module will
 	  be called f7188x-gpio.
 
+config GPIO_MB86S7X
+	bool "GPIO support for Fujitsu MB86S7x Platforms"
+	depends on ARCH_MB86S7X
+	help
+	  Say yes here to support the GPIO controller in Fujitsu MB86S70 SoCs.
+
 config GPIO_MOXART
 	bool "MOXART GPIO support"
 	depends on ARCH_MOXART
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 81755f1..793b45e 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_GPIO_MAX730X)	+= gpio-max730x.o
 obj-$(CONFIG_GPIO_MAX7300)	+= gpio-max7300.o
 obj-$(CONFIG_GPIO_MAX7301)	+= gpio-max7301.o
 obj-$(CONFIG_GPIO_MAX732X)	+= gpio-max732x.o
+obj-$(CONFIG_GPIO_MB86S7X)	+= gpio-mb86s7x.o
 obj-$(CONFIG_GPIO_MC33880)	+= gpio-mc33880.o
 obj-$(CONFIG_GPIO_MC9S08DZ60)	+= gpio-mc9s08dz60.o
 obj-$(CONFIG_GPIO_MCP23S08)	+= gpio-mcp23s08.o
diff --git a/drivers/gpio/gpio-mb86s7x.c b/drivers/gpio/gpio-mb86s7x.c
new file mode 100644
index 0000000..c912585
--- /dev/null
+++ b/drivers/gpio/gpio-mb86s7x.c
@@ -0,0 +1,231 @@
+/*
+ *  linux/drivers/gpio/gpio-mb86s7x.c
+ *
+ *  Copyright (C) 2015 Fujitsu Semiconductor Limited
+ *  Copyright (C) 2015 Linaro Ltd.
+ *
+ *  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, version 2 of the License.
+ *
+ *  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.
+ */
+
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+
+/*
+ * Only first 8bits of a register correspond to each pin,
+ * so there are 4 registers for 32 pins.
+ */
+#define PDR(x)	(0x0 + x / 8 * 4)
+#define DDR(x)	(0x10 + x / 8 * 4)
+#define PFR(x)	(0x20 + x / 8 * 4)
+
+#define OFFSET(x)	BIT((x) % 8)
+
+struct mb86s70_gpio_chip {
+	struct gpio_chip gc;
+	void __iomem *base;
+	struct clk *clk;
+	spinlock_t lock;
+};
+
+static inline struct mb86s70_gpio_chip *chip_to_mb86s70(struct gpio_chip *gc)
+{
+	return container_of(gc, struct mb86s70_gpio_chip, gc);
+}
+
+static int mb86s70_gpio_request(struct gpio_chip *gc, unsigned gpio)
+{
+	struct mb86s70_gpio_chip *gchip = chip_to_mb86s70(gc);
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&gchip->lock, flags);
+
+	val = readl(gchip->base + PFR(gpio));
+	val &= ~OFFSET(gpio);
+	writel(val, gchip->base + PFR(gpio));
+
+	spin_unlock_irqrestore(&gchip->lock, flags);
+
+	return 0;
+}
+
+static void mb86s70_gpio_free(struct gpio_chip *gc, unsigned gpio)
+{
+	struct mb86s70_gpio_chip *gchip = chip_to_mb86s70(gc);
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&gchip->lock, flags);
+
+	val = readl(gchip->base + PFR(gpio));
+	val |= OFFSET(gpio);
+	writel(val, gchip->base + PFR(gpio));
+
+	spin_unlock_irqrestore(&gchip->lock, flags);
+}
+
+static int mb86s70_gpio_direction_input(struct gpio_chip *gc, unsigned gpio)
+{
+	struct mb86s70_gpio_chip *gchip = chip_to_mb86s70(gc);
+	unsigned long flags;
+	unsigned char val;
+
+	spin_lock_irqsave(&gchip->lock, flags);
+
+	val = readl(gchip->base + DDR(gpio));
+	val &= ~OFFSET(gpio);
+	writel(val, gchip->base + DDR(gpio));
+
+	spin_unlock_irqrestore(&gchip->lock, flags);
+
+	return 0;
+}
+
+static int mb86s70_gpio_direction_output(struct gpio_chip *gc,
+					 unsigned gpio, int value)
+{
+	struct mb86s70_gpio_chip *gchip = chip_to_mb86s70(gc);
+	unsigned long flags;
+	unsigned char val;
+
+	spin_lock_irqsave(&gchip->lock, flags);
+
+	val = readl(gchip->base + PDR(gpio));
+	if (value)
+		val |= OFFSET(gpio);
+	else
+		val &= ~OFFSET(gpio);
+	writel(val, gchip->base + PDR(gpio));
+
+	val = readl(gchip->base + DDR(gpio));
+	val |= OFFSET(gpio);
+	writel(val, gchip->base + DDR(gpio));
+
+	spin_unlock_irqrestore(&gchip->lock, flags);
+
+	return 0;
+}
+
+static int mb86s70_gpio_get(struct gpio_chip *gc, unsigned gpio)
+{
+	struct mb86s70_gpio_chip *gchip = chip_to_mb86s70(gc);
+
+	return !!(readl(gchip->base + PDR(gpio)) & OFFSET(gpio));
+}
+
+static void mb86s70_gpio_set(struct gpio_chip *gc, unsigned gpio, int value)
+{
+	struct mb86s70_gpio_chip *gchip = chip_to_mb86s70(gc);
+	unsigned long flags;
+	unsigned char val;
+
+	spin_lock_irqsave(&gchip->lock, flags);
+
+	val = readl(gchip->base + PDR(gpio));
+	if (value)
+		val |= OFFSET(gpio);
+	else
+		val &= ~OFFSET(gpio);
+	writel(val, gchip->base + PDR(gpio));
+
+	spin_unlock_irqrestore(&gchip->lock, flags);
+}
+
+static int mb86s70_gpio_probe(struct platform_device *pdev)
+{
+	struct mb86s70_gpio_chip *gchip;
+	struct resource *res;
+	int ret;
+
+	gchip = devm_kzalloc(&pdev->dev, sizeof(*gchip), GFP_KERNEL);
+	if (gchip == NULL)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, gchip);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	gchip->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(gchip->base))
+		return PTR_ERR(gchip->base);
+
+	gchip->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(gchip->clk))
+		return PTR_ERR(gchip->clk);
+
+	clk_prepare_enable(gchip->clk);
+
+	spin_lock_init(&gchip->lock);
+
+	gchip->gc.direction_output = mb86s70_gpio_direction_output;
+	gchip->gc.direction_input = mb86s70_gpio_direction_input;
+	gchip->gc.request = mb86s70_gpio_request;
+	gchip->gc.free = mb86s70_gpio_free;
+	gchip->gc.get = mb86s70_gpio_get;
+	gchip->gc.set = mb86s70_gpio_set;
+	gchip->gc.label = dev_name(&pdev->dev);
+	gchip->gc.ngpio = 32;
+	gchip->gc.owner = THIS_MODULE;
+	gchip->gc.dev = &pdev->dev;
+	gchip->gc.base = -1;
+
+	platform_set_drvdata(pdev, gchip);
+
+	ret = gpiochip_add(&gchip->gc);
+	if (ret) {
+		dev_err(&pdev->dev, "couldn't register gpio driver\n");
+		clk_disable_unprepare(gchip->clk);
+	}
+
+	return ret;
+}
+
+static int mb86s70_gpio_remove(struct platform_device *pdev)
+{
+	struct mb86s70_gpio_chip *gchip = platform_get_drvdata(pdev);
+
+	gpiochip_remove(&gchip->gc);
+
+	return 0;
+}
+
+static const struct of_device_id mb86s70_gpio_dt_ids[] = {
+	{ .compatible = "fujitsu,mb86s70-gpio" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mb86s70_gpio_dt_ids);
+
+static struct platform_driver mb86s70_gpio_driver = {
+	.driver = {
+		.name = "mb86s70-gpio",
+		.of_match_table = mb86s70_gpio_dt_ids,
+	},
+	.probe = mb86s70_gpio_probe,
+	.remove = mb86s70_gpio_remove,
+};
+
+static int __init mb86s70_gpio_init(void)
+{
+	return platform_driver_register(&mb86s70_gpio_driver);
+}
+subsys_initcall(mb86s70_gpio_init);
+
+MODULE_DESCRIPTION("MB86S7x GPIO Driver");
+MODULE_ALIAS("platform:mb86s70-gpio");
+MODULE_LICENSE("GPL");
-- 
1.9.0


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 5/8] gpio: Add Fujitsu MB86S7x GPIO driver
@ 2015-01-09 11:33   ` Vincent Yang
  0 siblings, 0 replies; 39+ messages in thread
From: Vincent Yang @ 2015-01-09 11:33 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jassi Brar <jaswinder.singh@linaro.org>

Driver for Fujitsu MB86S7x SoCs that have a memory mapped GPIO controller.

Signed-off-by: Andy Green <andy.green@linaro.org>
Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
Signed-off-by: Vincent Yang <Vincent.Yang@tw.fujitsu.com>
Signed-off-by: Tetsuya Nuriya <nuriya.tetsuya@jp.fujitsu.com>
---
 .../bindings/gpio/fujitsu,mb86s70-gpio.txt         |  20 ++
 drivers/gpio/Kconfig                               |   6 +
 drivers/gpio/Makefile                              |   1 +
 drivers/gpio/gpio-mb86s7x.c                        | 231 +++++++++++++++++++++
 4 files changed, 258 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/gpio/fujitsu,mb86s70-gpio.txt
 create mode 100644 drivers/gpio/gpio-mb86s7x.c

diff --git a/Documentation/devicetree/bindings/gpio/fujitsu,mb86s70-gpio.txt b/Documentation/devicetree/bindings/gpio/fujitsu,mb86s70-gpio.txt
new file mode 100644
index 0000000..bef353f
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/fujitsu,mb86s70-gpio.txt
@@ -0,0 +1,20 @@
+Fujitsu MB86S7x GPIO Controller
+-------------------------------
+
+Required properties:
+- compatible: Should be "fujitsu,mb86s70-gpio"
+- reg: Base address and length of register space
+- clocks: Specify the clock
+- gpio-controller: Marks the device node as a gpio controller.
+- #gpio-cells: Should be <2>. The first cell is the pin number and the
+  second cell is used to specify optional parameters:
+   - bit 0 specifies polarity (0 for normal, 1 for inverted).
+
+Examples:
+	gpio0: gpio at 31000000 {
+		compatible = "fujitsu,mb86s70-gpio";
+		reg = <0 0x31000000 0x10000>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		clocks = <&clk 0 2 1>;
+	};
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 633ec21..699e629 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -197,6 +197,12 @@ config GPIO_F7188X
 	  To compile this driver as a module, choose M here: the module will
 	  be called f7188x-gpio.
 
+config GPIO_MB86S7X
+	bool "GPIO support for Fujitsu MB86S7x Platforms"
+	depends on ARCH_MB86S7X
+	help
+	  Say yes here to support the GPIO controller in Fujitsu MB86S70 SoCs.
+
 config GPIO_MOXART
 	bool "MOXART GPIO support"
 	depends on ARCH_MOXART
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 81755f1..793b45e 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_GPIO_MAX730X)	+= gpio-max730x.o
 obj-$(CONFIG_GPIO_MAX7300)	+= gpio-max7300.o
 obj-$(CONFIG_GPIO_MAX7301)	+= gpio-max7301.o
 obj-$(CONFIG_GPIO_MAX732X)	+= gpio-max732x.o
+obj-$(CONFIG_GPIO_MB86S7X)	+= gpio-mb86s7x.o
 obj-$(CONFIG_GPIO_MC33880)	+= gpio-mc33880.o
 obj-$(CONFIG_GPIO_MC9S08DZ60)	+= gpio-mc9s08dz60.o
 obj-$(CONFIG_GPIO_MCP23S08)	+= gpio-mcp23s08.o
diff --git a/drivers/gpio/gpio-mb86s7x.c b/drivers/gpio/gpio-mb86s7x.c
new file mode 100644
index 0000000..c912585
--- /dev/null
+++ b/drivers/gpio/gpio-mb86s7x.c
@@ -0,0 +1,231 @@
+/*
+ *  linux/drivers/gpio/gpio-mb86s7x.c
+ *
+ *  Copyright (C) 2015 Fujitsu Semiconductor Limited
+ *  Copyright (C) 2015 Linaro Ltd.
+ *
+ *  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, version 2 of the License.
+ *
+ *  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.
+ */
+
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+
+/*
+ * Only first 8bits of a register correspond to each pin,
+ * so there are 4 registers for 32 pins.
+ */
+#define PDR(x)	(0x0 + x / 8 * 4)
+#define DDR(x)	(0x10 + x / 8 * 4)
+#define PFR(x)	(0x20 + x / 8 * 4)
+
+#define OFFSET(x)	BIT((x) % 8)
+
+struct mb86s70_gpio_chip {
+	struct gpio_chip gc;
+	void __iomem *base;
+	struct clk *clk;
+	spinlock_t lock;
+};
+
+static inline struct mb86s70_gpio_chip *chip_to_mb86s70(struct gpio_chip *gc)
+{
+	return container_of(gc, struct mb86s70_gpio_chip, gc);
+}
+
+static int mb86s70_gpio_request(struct gpio_chip *gc, unsigned gpio)
+{
+	struct mb86s70_gpio_chip *gchip = chip_to_mb86s70(gc);
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&gchip->lock, flags);
+
+	val = readl(gchip->base + PFR(gpio));
+	val &= ~OFFSET(gpio);
+	writel(val, gchip->base + PFR(gpio));
+
+	spin_unlock_irqrestore(&gchip->lock, flags);
+
+	return 0;
+}
+
+static void mb86s70_gpio_free(struct gpio_chip *gc, unsigned gpio)
+{
+	struct mb86s70_gpio_chip *gchip = chip_to_mb86s70(gc);
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&gchip->lock, flags);
+
+	val = readl(gchip->base + PFR(gpio));
+	val |= OFFSET(gpio);
+	writel(val, gchip->base + PFR(gpio));
+
+	spin_unlock_irqrestore(&gchip->lock, flags);
+}
+
+static int mb86s70_gpio_direction_input(struct gpio_chip *gc, unsigned gpio)
+{
+	struct mb86s70_gpio_chip *gchip = chip_to_mb86s70(gc);
+	unsigned long flags;
+	unsigned char val;
+
+	spin_lock_irqsave(&gchip->lock, flags);
+
+	val = readl(gchip->base + DDR(gpio));
+	val &= ~OFFSET(gpio);
+	writel(val, gchip->base + DDR(gpio));
+
+	spin_unlock_irqrestore(&gchip->lock, flags);
+
+	return 0;
+}
+
+static int mb86s70_gpio_direction_output(struct gpio_chip *gc,
+					 unsigned gpio, int value)
+{
+	struct mb86s70_gpio_chip *gchip = chip_to_mb86s70(gc);
+	unsigned long flags;
+	unsigned char val;
+
+	spin_lock_irqsave(&gchip->lock, flags);
+
+	val = readl(gchip->base + PDR(gpio));
+	if (value)
+		val |= OFFSET(gpio);
+	else
+		val &= ~OFFSET(gpio);
+	writel(val, gchip->base + PDR(gpio));
+
+	val = readl(gchip->base + DDR(gpio));
+	val |= OFFSET(gpio);
+	writel(val, gchip->base + DDR(gpio));
+
+	spin_unlock_irqrestore(&gchip->lock, flags);
+
+	return 0;
+}
+
+static int mb86s70_gpio_get(struct gpio_chip *gc, unsigned gpio)
+{
+	struct mb86s70_gpio_chip *gchip = chip_to_mb86s70(gc);
+
+	return !!(readl(gchip->base + PDR(gpio)) & OFFSET(gpio));
+}
+
+static void mb86s70_gpio_set(struct gpio_chip *gc, unsigned gpio, int value)
+{
+	struct mb86s70_gpio_chip *gchip = chip_to_mb86s70(gc);
+	unsigned long flags;
+	unsigned char val;
+
+	spin_lock_irqsave(&gchip->lock, flags);
+
+	val = readl(gchip->base + PDR(gpio));
+	if (value)
+		val |= OFFSET(gpio);
+	else
+		val &= ~OFFSET(gpio);
+	writel(val, gchip->base + PDR(gpio));
+
+	spin_unlock_irqrestore(&gchip->lock, flags);
+}
+
+static int mb86s70_gpio_probe(struct platform_device *pdev)
+{
+	struct mb86s70_gpio_chip *gchip;
+	struct resource *res;
+	int ret;
+
+	gchip = devm_kzalloc(&pdev->dev, sizeof(*gchip), GFP_KERNEL);
+	if (gchip == NULL)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, gchip);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	gchip->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(gchip->base))
+		return PTR_ERR(gchip->base);
+
+	gchip->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(gchip->clk))
+		return PTR_ERR(gchip->clk);
+
+	clk_prepare_enable(gchip->clk);
+
+	spin_lock_init(&gchip->lock);
+
+	gchip->gc.direction_output = mb86s70_gpio_direction_output;
+	gchip->gc.direction_input = mb86s70_gpio_direction_input;
+	gchip->gc.request = mb86s70_gpio_request;
+	gchip->gc.free = mb86s70_gpio_free;
+	gchip->gc.get = mb86s70_gpio_get;
+	gchip->gc.set = mb86s70_gpio_set;
+	gchip->gc.label = dev_name(&pdev->dev);
+	gchip->gc.ngpio = 32;
+	gchip->gc.owner = THIS_MODULE;
+	gchip->gc.dev = &pdev->dev;
+	gchip->gc.base = -1;
+
+	platform_set_drvdata(pdev, gchip);
+
+	ret = gpiochip_add(&gchip->gc);
+	if (ret) {
+		dev_err(&pdev->dev, "couldn't register gpio driver\n");
+		clk_disable_unprepare(gchip->clk);
+	}
+
+	return ret;
+}
+
+static int mb86s70_gpio_remove(struct platform_device *pdev)
+{
+	struct mb86s70_gpio_chip *gchip = platform_get_drvdata(pdev);
+
+	gpiochip_remove(&gchip->gc);
+
+	return 0;
+}
+
+static const struct of_device_id mb86s70_gpio_dt_ids[] = {
+	{ .compatible = "fujitsu,mb86s70-gpio" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mb86s70_gpio_dt_ids);
+
+static struct platform_driver mb86s70_gpio_driver = {
+	.driver = {
+		.name = "mb86s70-gpio",
+		.of_match_table = mb86s70_gpio_dt_ids,
+	},
+	.probe = mb86s70_gpio_probe,
+	.remove = mb86s70_gpio_remove,
+};
+
+static int __init mb86s70_gpio_init(void)
+{
+	return platform_driver_register(&mb86s70_gpio_driver);
+}
+subsys_initcall(mb86s70_gpio_init);
+
+MODULE_DESCRIPTION("MB86S7x GPIO Driver");
+MODULE_ALIAS("platform:mb86s70-gpio");
+MODULE_LICENSE("GPL");
-- 
1.9.0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 6/8] dt: mb86s7x: add dt files for MB86S7x evbs
  2015-01-09 11:19 ` Vincent Yang
@ 2015-01-09 11:34   ` Vincent Yang
  -1 siblings, 0 replies; 39+ messages in thread
From: Vincent Yang @ 2015-01-09 11:34 UTC (permalink / raw)
  To: devicetree, linux-arm-kernel
  Cc: mark.rutland, andy.green, arnd, pawel.moll, ijc+devicetree,
	patches, Vincent Yang, jaswinder.singh, robh+dt, galak, olof,
	Sneeker.Yeh, Tetsuya Nuriya

From: Jassi Brar <jaswinder.singh@linaro.org>

Add dt files for MB86S7x evb.

Signed-off-by: Andy Green <andy.green@linaro.org>
Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
Signed-off-by: Vincent Yang <Vincent.Yang@tw.fujitsu.com>
Signed-off-by: Tetsuya Nuriya <nuriya.tetsuya@jp.fujitsu.com>
---
 arch/arm/boot/dts/Makefile      |   1 +
 arch/arm/boot/dts/mb86s70.dtsi  |  91 ++++++++++++++++++++++++++
 arch/arm/boot/dts/mb86s70eb.dts |  57 ++++++++++++++++
 arch/arm/boot/dts/mb86s73.dtsi  |  63 ++++++++++++++++++
 arch/arm/boot/dts/mb86s73eb.dts |  44 +++++++++++++
 arch/arm/boot/dts/mb86s7x.dtsi  | 140 ++++++++++++++++++++++++++++++++++++++++
 6 files changed, 396 insertions(+)
 create mode 100644 arch/arm/boot/dts/mb86s70.dtsi
 create mode 100644 arch/arm/boot/dts/mb86s70eb.dts
 create mode 100644 arch/arm/boot/dts/mb86s73.dtsi
 create mode 100644 arch/arm/boot/dts/mb86s73eb.dts
 create mode 100644 arch/arm/boot/dts/mb86s7x.dtsi

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 91bd5bd..43b091b 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -176,6 +176,7 @@ dtb-$(CONFIG_MACH_KIRKWOOD) += kirkwood-b3.dtb \
 	kirkwood-ts419-6282.dtb
 dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb
 dtb-$(CONFIG_ARCH_MARCO) += marco-evb.dtb
+dtb-$(CONFIG_ARCH_MB86S7X) += mb86s70eb.dtb mb86s73eb.dtb
 dtb-$(CONFIG_MACH_MESON6) += meson6-atv1200.dtb
 dtb-$(CONFIG_ARCH_MMP) += pxa168-aspenite.dtb \
 	pxa910-dkb.dtb \
diff --git a/arch/arm/boot/dts/mb86s70.dtsi b/arch/arm/boot/dts/mb86s70.dtsi
new file mode 100644
index 0000000..057e135
--- /dev/null
+++ b/arch/arm/boot/dts/mb86s70.dtsi
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2013-2015 FUJITSU SEMICONDUCTOR LIMITED
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * 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, version 2 of the License.
+ */
+
+#include "mb86s7x.dtsi"
+
+/ {
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x0>;
+			cci-control-port = <&cci_control4>;
+			clock-frequency = <1200000000>;
+			clock-latency = <100000>;
+		};
+
+		cpu1: cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x1>;
+			cci-control-port = <&cci_control4>;
+			clock-frequency = <1200000000>;
+			clock-latency = <100000>;
+		};
+
+		cpu2: cpu@100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x100>;
+			cci-control-port = <&cci_control3>;
+			clock-frequency = <800000000>;
+			clock-latency = <100000>;
+		};
+
+		cpu3: cpu@101 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x101>;
+			cci-control-port = <&cci_control3>;
+			clock-frequency = <800000000>;
+			clock-latency = <100000>;
+		};
+	};
+
+	cci@2c090000 {
+		compatible = "arm,cci-400";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0 0x2c090000 0x1000>;
+		ranges = <0x0 0x0 0x2c090000 0x10000>;
+
+		cci_control3: slave-if@4000 {
+			compatible = "arm,cci-400-ctrl-if";
+			interface-type = "ace";
+			reg = <0x4000 0x1000>;
+		};
+
+		cci_control4: slave-if@5000 {
+			compatible = "arm,cci-400-ctrl-if";
+			interface-type = "ace";
+			reg = <0x5000 0x1000>;
+		};
+
+		pmu@9000 {
+			compatible = "arm,cci-400-pmu";
+			reg = <0x9000 0x5000>;
+			interrupts = <0 77 4>,
+					<0 77 4>,
+					<0 77 4>,
+					<0 77 4>,
+					<0 77 4>;
+		};
+	};
+};
+
+&archtimer {
+	status = "disabled";
+};
+
+&pmua7 {
+	status = "disabled";
+};
diff --git a/arch/arm/boot/dts/mb86s70eb.dts b/arch/arm/boot/dts/mb86s70eb.dts
new file mode 100644
index 0000000..1e51ce0
--- /dev/null
+++ b/arch/arm/boot/dts/mb86s70eb.dts
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2013-2015 FUJITSU SEMICONDUCTOR LIMITED
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * 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, version 2 of the License.
+ */
+
+/dts-v1/;
+
+#include "mb86s70.dtsi"
+
+/ {
+	model = "Fujitsu MB86S70 EVB";
+	compatible = "fujitsu,mb86s70-evb";
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0 0x80000000 0x80000000>, <0x08 0x80000000 0x80000000>;
+
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200 root=/dev/mmcblk1p1 rootfstype=ext4 rootwait rw";
+		linux,initrd-start = <0xc0000000>;
+		linux,initrd-end =   <0xc0800000>;
+	};
+
+	vccq_sdhci1: regulator@0 {
+		compatible = "regulator-gpio";
+		regulator-name = "SDHCI1 VccQ";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+		gpios = <&gpio0 7 0>;
+		gpios-states = <1>;
+		states = <3300000 1
+			  1800000 0>;
+	};
+};
+
+&sdhci0 {
+	status = "ok";
+	bus-width = <8>;
+};
+
+&sdhci1 {
+	status = "ok";
+	bus-width = <4>;
+	vqmmc-supply = <&vccq_sdhci1>;
+};
diff --git a/arch/arm/boot/dts/mb86s73.dtsi b/arch/arm/boot/dts/mb86s73.dtsi
new file mode 100644
index 0000000..3c9d8d0
--- /dev/null
+++ b/arch/arm/boot/dts/mb86s73.dtsi
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2013-2015 FUJITSU SEMICONDUCTOR LIMITED
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * 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, version 2 of the License.
+ */
+
+#include "mb86s7x.dtsi"
+
+/ {
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x100>;
+			cci-control-port = <&cci_control3>;
+			clock-frequency = <800000000>;
+			clock-latency = <100000>;
+		};
+
+		cpu1: cpu@101 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x101>;
+			cci-control-port = <&cci_control3>;
+			clock-frequency = <800000000>;
+			clock-latency = <100000>;
+		};
+	};
+
+	cci@2c090000 {
+		compatible = "arm,cci-400";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0 0x2c090000 0x1000>;
+		ranges = <0x0 0x0 0x2c090000 0x10000>;
+
+		cci_control3: slave-if@4000 {
+			compatible = "arm,cci-400-ctrl-if";
+			interface-type = "ace";
+			reg = <0x4000 0x1000>;
+		};
+	};
+
+	hcd21_ehci: f_usb20ho_echi@34240000 {
+		compatible = "fujitsu,f_usb20ho", "generic-ehci";
+		reg = <0 0x34240000 0x1000>;
+		interrupts = <0 419 0x4>;
+		clocks = <&clock 2 2 4>, <&clock 2 4 5>, <&clock 4 0 0>;
+	};
+
+	hcd21_ohci: f_usb20ho_ochi@34240000 {
+		compatible = "fujitsu,f_usb20ho", "generic-ohci";
+		reg = <0 0x34241000 0x1000>;
+		interrupts = <0 419 0x4>;
+		clocks = <&clock 2 2 4>, <&clock 2 4 5>, <&clock 4 0 0>;
+	};
+};
diff --git a/arch/arm/boot/dts/mb86s73eb.dts b/arch/arm/boot/dts/mb86s73eb.dts
new file mode 100644
index 0000000..43f2fc6
--- /dev/null
+++ b/arch/arm/boot/dts/mb86s73eb.dts
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013-2015 FUJITSU SEMICONDUCTOR LIMITED
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * 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, version 2 of the License.
+ */
+
+/dts-v1/;
+
+#include "mb86s73.dtsi"
+
+/ {
+	model = "Fujitsu MB86S73 EVB";
+	compatible = "fujitsu,mb86s73-evb";
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0 0x80000000 0x80000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200 root=/dev/mmcblk1p1 rootfstype=ext4 rootwait rw";
+		linux,initrd-start = <0xc0000000>;
+		linux,initrd-end =   <0xc0800000>;
+	};
+};
+
+&sdhci0 {
+	status = "ok";
+	bus-width = <8>;
+};
+
+&sdhci1 {
+	status = "ok";
+	bus-width = <4>;
+};
diff --git a/arch/arm/boot/dts/mb86s7x.dtsi b/arch/arm/boot/dts/mb86s7x.dtsi
new file mode 100644
index 0000000..d1aa017
--- /dev/null
+++ b/arch/arm/boot/dts/mb86s7x.dtsi
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2013-2015 FUJITSU SEMICONDUCTOR LIMITED
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * 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, version 2 of the License.
+ */
+
+#include "skeleton.dtsi"
+
+/ {
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <1>;
+
+	pmua7: pmu_a7 {
+		compatible = "arm,cortex-a7-pmu";
+		interrupts = <0 18 4>,
+			     <0 22 4>;
+	};
+
+	clock: crg11 {
+		compatible = "fujitsu,mb86s70-crg11";
+		#clock-cells = <3>;
+	};
+
+	timer0: timer@31080000 {
+		compatible = "arm,sp804", "arm,primecell";
+		reg = <0 0x31080000 0x1000>;
+		interrupts = <0 324 4>,
+			     <0 325 4>;
+		clocks = <&clock 0 6 8>;
+		clock-names = "apb_pclk";
+	};
+
+	archtimer: archtimer {
+		compatible = "arm,armv7-timer";
+		clock-frequency = <125000000>;
+		interrupts = <1 13 0xf08>,
+			     <1 14 0xf08>,
+			     <1 11 0xf08>,
+			     <1 10 0xf08>;
+	};
+
+	gic: interrupt-controller@2c001000 {
+		compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		reg = <0 0x2c001000 0x1000>,
+		      <0 0x2c002000 0x1000>,
+		      <0 0x2c004000 0x2000>,
+		      <0 0x2c006000 0x2000>;
+		interrupts = <1 9 0xf04>;
+	};
+
+	mhu: mailbox@2b1f0000 {
+		#mbox-cells = <1>;
+		compatible = "arm,mbox-mhu";
+		reg = <0 0x2b1f0000 0x1000>;
+		interrupts = <0 36 4>, /* LP Non-Sec */
+			     <0 35 4>, /* HP Non-Sec */
+			     <0 37 4>; /* Secure */
+	};
+
+	mhu_client: scb@2e000000 {
+		compatible = "fujitsu,mb86s70-scb-1.0";
+		reg = <0 0x2e000000 0x4000>; /* SHM for IPC */
+		mboxes = <&mhu 1>;
+	};
+
+	uart0: serial@31040000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0 0x31040000 0x100>;
+		interrupts = <0 320 0x4>;
+		clock-frequency = <62500000>;
+		reg-io-width = <4>;
+		reg-shift = <2>;
+		clocks = <&clock 0 2 1>;
+		clock-names = "sclk";
+	};
+
+	uart1: serial@31050000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0 0x31050000 0x100>;
+		interrupts = <0 321 0x4>;
+		clock-frequency = <62500000>;
+		reg-io-width = <4>;
+		reg-shift = <2>;
+		clocks = <&clock 0 2 1>;
+		clock-names = "sclk";
+	};
+
+	uart2: serial@31060000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0 0x31060000 0x100>;
+		interrupts = <0 322 0x4>;
+		clock-frequency = <62500000>;
+		reg-io-width = <4>;
+		reg-shift = <2>;
+		clocks = <&clock 0 2 1>;
+		clock-names = "sclk";
+	};
+
+	gpio0: gpio@31000000 {
+		compatible = "fujitsu,mb86s70-gpio";
+		reg = <0 0x31000000 0x10000>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		clocks = <&clock 0 2 1>;
+	};
+
+	gpio1: gpio@31010000 {
+		compatible = "fujitsu,mb86s70-gpio";
+		reg = <0 0x31010000 0x10000>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		clocks = <&clock 0 2 1>;
+	};
+
+	sdhci0: mmc@300c0000 {
+		status = "disabled";
+		compatible = "fujitsu,mb86s70-sdhci-3.0";
+		reg = <0 0x300c0000 0x1000>;
+		interrupts = <0 164 0x4>,
+			     <0 165 0x4>;
+		clocks = <&clock 0 0xc 0>, <&clock 0 0xb 0>;
+		clock-names = "iface", "core";
+	};
+
+	sdhci1: mmc@36600000 {
+		status = "disabled";
+		compatible = "fujitsu,mb86s70-sdhci-3.0";
+		reg = <0 0x36600000 0x1000>;
+		interrupts = <0 172 0x4>,
+			     <0 173 0x4>;
+		clocks = <&clock 2 0xc 0>, <&clock 2 0xd 0>;
+		clock-names = "iface", "core";
+	};
+};
-- 
1.9.0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 6/8] dt: mb86s7x: add dt files for MB86S7x evbs
@ 2015-01-09 11:34   ` Vincent Yang
  0 siblings, 0 replies; 39+ messages in thread
From: Vincent Yang @ 2015-01-09 11:34 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jassi Brar <jaswinder.singh@linaro.org>

Add dt files for MB86S7x evb.

Signed-off-by: Andy Green <andy.green@linaro.org>
Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
Signed-off-by: Vincent Yang <Vincent.Yang@tw.fujitsu.com>
Signed-off-by: Tetsuya Nuriya <nuriya.tetsuya@jp.fujitsu.com>
---
 arch/arm/boot/dts/Makefile      |   1 +
 arch/arm/boot/dts/mb86s70.dtsi  |  91 ++++++++++++++++++++++++++
 arch/arm/boot/dts/mb86s70eb.dts |  57 ++++++++++++++++
 arch/arm/boot/dts/mb86s73.dtsi  |  63 ++++++++++++++++++
 arch/arm/boot/dts/mb86s73eb.dts |  44 +++++++++++++
 arch/arm/boot/dts/mb86s7x.dtsi  | 140 ++++++++++++++++++++++++++++++++++++++++
 6 files changed, 396 insertions(+)
 create mode 100644 arch/arm/boot/dts/mb86s70.dtsi
 create mode 100644 arch/arm/boot/dts/mb86s70eb.dts
 create mode 100644 arch/arm/boot/dts/mb86s73.dtsi
 create mode 100644 arch/arm/boot/dts/mb86s73eb.dts
 create mode 100644 arch/arm/boot/dts/mb86s7x.dtsi

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 91bd5bd..43b091b 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -176,6 +176,7 @@ dtb-$(CONFIG_MACH_KIRKWOOD) += kirkwood-b3.dtb \
 	kirkwood-ts419-6282.dtb
 dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb
 dtb-$(CONFIG_ARCH_MARCO) += marco-evb.dtb
+dtb-$(CONFIG_ARCH_MB86S7X) += mb86s70eb.dtb mb86s73eb.dtb
 dtb-$(CONFIG_MACH_MESON6) += meson6-atv1200.dtb
 dtb-$(CONFIG_ARCH_MMP) += pxa168-aspenite.dtb \
 	pxa910-dkb.dtb \
diff --git a/arch/arm/boot/dts/mb86s70.dtsi b/arch/arm/boot/dts/mb86s70.dtsi
new file mode 100644
index 0000000..057e135
--- /dev/null
+++ b/arch/arm/boot/dts/mb86s70.dtsi
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2013-2015 FUJITSU SEMICONDUCTOR LIMITED
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * 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, version 2 of the License.
+ */
+
+#include "mb86s7x.dtsi"
+
+/ {
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x0>;
+			cci-control-port = <&cci_control4>;
+			clock-frequency = <1200000000>;
+			clock-latency = <100000>;
+		};
+
+		cpu1: cpu at 1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0x1>;
+			cci-control-port = <&cci_control4>;
+			clock-frequency = <1200000000>;
+			clock-latency = <100000>;
+		};
+
+		cpu2: cpu at 100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x100>;
+			cci-control-port = <&cci_control3>;
+			clock-frequency = <800000000>;
+			clock-latency = <100000>;
+		};
+
+		cpu3: cpu at 101 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x101>;
+			cci-control-port = <&cci_control3>;
+			clock-frequency = <800000000>;
+			clock-latency = <100000>;
+		};
+	};
+
+	cci at 2c090000 {
+		compatible = "arm,cci-400";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0 0x2c090000 0x1000>;
+		ranges = <0x0 0x0 0x2c090000 0x10000>;
+
+		cci_control3: slave-if at 4000 {
+			compatible = "arm,cci-400-ctrl-if";
+			interface-type = "ace";
+			reg = <0x4000 0x1000>;
+		};
+
+		cci_control4: slave-if at 5000 {
+			compatible = "arm,cci-400-ctrl-if";
+			interface-type = "ace";
+			reg = <0x5000 0x1000>;
+		};
+
+		pmu at 9000 {
+			compatible = "arm,cci-400-pmu";
+			reg = <0x9000 0x5000>;
+			interrupts = <0 77 4>,
+					<0 77 4>,
+					<0 77 4>,
+					<0 77 4>,
+					<0 77 4>;
+		};
+	};
+};
+
+&archtimer {
+	status = "disabled";
+};
+
+&pmua7 {
+	status = "disabled";
+};
diff --git a/arch/arm/boot/dts/mb86s70eb.dts b/arch/arm/boot/dts/mb86s70eb.dts
new file mode 100644
index 0000000..1e51ce0
--- /dev/null
+++ b/arch/arm/boot/dts/mb86s70eb.dts
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2013-2015 FUJITSU SEMICONDUCTOR LIMITED
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * 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, version 2 of the License.
+ */
+
+/dts-v1/;
+
+#include "mb86s70.dtsi"
+
+/ {
+	model = "Fujitsu MB86S70 EVB";
+	compatible = "fujitsu,mb86s70-evb";
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0 0x80000000 0x80000000>, <0x08 0x80000000 0x80000000>;
+
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200 root=/dev/mmcblk1p1 rootfstype=ext4 rootwait rw";
+		linux,initrd-start = <0xc0000000>;
+		linux,initrd-end =   <0xc0800000>;
+	};
+
+	vccq_sdhci1: regulator at 0 {
+		compatible = "regulator-gpio";
+		regulator-name = "SDHCI1 VccQ";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+		gpios = <&gpio0 7 0>;
+		gpios-states = <1>;
+		states = <3300000 1
+			  1800000 0>;
+	};
+};
+
+&sdhci0 {
+	status = "ok";
+	bus-width = <8>;
+};
+
+&sdhci1 {
+	status = "ok";
+	bus-width = <4>;
+	vqmmc-supply = <&vccq_sdhci1>;
+};
diff --git a/arch/arm/boot/dts/mb86s73.dtsi b/arch/arm/boot/dts/mb86s73.dtsi
new file mode 100644
index 0000000..3c9d8d0
--- /dev/null
+++ b/arch/arm/boot/dts/mb86s73.dtsi
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2013-2015 FUJITSU SEMICONDUCTOR LIMITED
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * 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, version 2 of the License.
+ */
+
+#include "mb86s7x.dtsi"
+
+/ {
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu at 100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x100>;
+			cci-control-port = <&cci_control3>;
+			clock-frequency = <800000000>;
+			clock-latency = <100000>;
+		};
+
+		cpu1: cpu at 101 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x101>;
+			cci-control-port = <&cci_control3>;
+			clock-frequency = <800000000>;
+			clock-latency = <100000>;
+		};
+	};
+
+	cci at 2c090000 {
+		compatible = "arm,cci-400";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0 0x2c090000 0x1000>;
+		ranges = <0x0 0x0 0x2c090000 0x10000>;
+
+		cci_control3: slave-if at 4000 {
+			compatible = "arm,cci-400-ctrl-if";
+			interface-type = "ace";
+			reg = <0x4000 0x1000>;
+		};
+	};
+
+	hcd21_ehci: f_usb20ho_echi at 34240000 {
+		compatible = "fujitsu,f_usb20ho", "generic-ehci";
+		reg = <0 0x34240000 0x1000>;
+		interrupts = <0 419 0x4>;
+		clocks = <&clock 2 2 4>, <&clock 2 4 5>, <&clock 4 0 0>;
+	};
+
+	hcd21_ohci: f_usb20ho_ochi at 34240000 {
+		compatible = "fujitsu,f_usb20ho", "generic-ohci";
+		reg = <0 0x34241000 0x1000>;
+		interrupts = <0 419 0x4>;
+		clocks = <&clock 2 2 4>, <&clock 2 4 5>, <&clock 4 0 0>;
+	};
+};
diff --git a/arch/arm/boot/dts/mb86s73eb.dts b/arch/arm/boot/dts/mb86s73eb.dts
new file mode 100644
index 0000000..43f2fc6
--- /dev/null
+++ b/arch/arm/boot/dts/mb86s73eb.dts
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013-2015 FUJITSU SEMICONDUCTOR LIMITED
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * 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, version 2 of the License.
+ */
+
+/dts-v1/;
+
+#include "mb86s73.dtsi"
+
+/ {
+	model = "Fujitsu MB86S73 EVB";
+	compatible = "fujitsu,mb86s73-evb";
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0 0x80000000 0x80000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200 root=/dev/mmcblk1p1 rootfstype=ext4 rootwait rw";
+		linux,initrd-start = <0xc0000000>;
+		linux,initrd-end =   <0xc0800000>;
+	};
+};
+
+&sdhci0 {
+	status = "ok";
+	bus-width = <8>;
+};
+
+&sdhci1 {
+	status = "ok";
+	bus-width = <4>;
+};
diff --git a/arch/arm/boot/dts/mb86s7x.dtsi b/arch/arm/boot/dts/mb86s7x.dtsi
new file mode 100644
index 0000000..d1aa017
--- /dev/null
+++ b/arch/arm/boot/dts/mb86s7x.dtsi
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2013-2015 FUJITSU SEMICONDUCTOR LIMITED
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * 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, version 2 of the License.
+ */
+
+#include "skeleton.dtsi"
+
+/ {
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <1>;
+
+	pmua7: pmu_a7 {
+		compatible = "arm,cortex-a7-pmu";
+		interrupts = <0 18 4>,
+			     <0 22 4>;
+	};
+
+	clock: crg11 {
+		compatible = "fujitsu,mb86s70-crg11";
+		#clock-cells = <3>;
+	};
+
+	timer0: timer at 31080000 {
+		compatible = "arm,sp804", "arm,primecell";
+		reg = <0 0x31080000 0x1000>;
+		interrupts = <0 324 4>,
+			     <0 325 4>;
+		clocks = <&clock 0 6 8>;
+		clock-names = "apb_pclk";
+	};
+
+	archtimer: archtimer {
+		compatible = "arm,armv7-timer";
+		clock-frequency = <125000000>;
+		interrupts = <1 13 0xf08>,
+			     <1 14 0xf08>,
+			     <1 11 0xf08>,
+			     <1 10 0xf08>;
+	};
+
+	gic: interrupt-controller at 2c001000 {
+		compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		reg = <0 0x2c001000 0x1000>,
+		      <0 0x2c002000 0x1000>,
+		      <0 0x2c004000 0x2000>,
+		      <0 0x2c006000 0x2000>;
+		interrupts = <1 9 0xf04>;
+	};
+
+	mhu: mailbox at 2b1f0000 {
+		#mbox-cells = <1>;
+		compatible = "arm,mbox-mhu";
+		reg = <0 0x2b1f0000 0x1000>;
+		interrupts = <0 36 4>, /* LP Non-Sec */
+			     <0 35 4>, /* HP Non-Sec */
+			     <0 37 4>; /* Secure */
+	};
+
+	mhu_client: scb at 2e000000 {
+		compatible = "fujitsu,mb86s70-scb-1.0";
+		reg = <0 0x2e000000 0x4000>; /* SHM for IPC */
+		mboxes = <&mhu 1>;
+	};
+
+	uart0: serial at 31040000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0 0x31040000 0x100>;
+		interrupts = <0 320 0x4>;
+		clock-frequency = <62500000>;
+		reg-io-width = <4>;
+		reg-shift = <2>;
+		clocks = <&clock 0 2 1>;
+		clock-names = "sclk";
+	};
+
+	uart1: serial at 31050000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0 0x31050000 0x100>;
+		interrupts = <0 321 0x4>;
+		clock-frequency = <62500000>;
+		reg-io-width = <4>;
+		reg-shift = <2>;
+		clocks = <&clock 0 2 1>;
+		clock-names = "sclk";
+	};
+
+	uart2: serial at 31060000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0 0x31060000 0x100>;
+		interrupts = <0 322 0x4>;
+		clock-frequency = <62500000>;
+		reg-io-width = <4>;
+		reg-shift = <2>;
+		clocks = <&clock 0 2 1>;
+		clock-names = "sclk";
+	};
+
+	gpio0: gpio at 31000000 {
+		compatible = "fujitsu,mb86s70-gpio";
+		reg = <0 0x31000000 0x10000>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		clocks = <&clock 0 2 1>;
+	};
+
+	gpio1: gpio at 31010000 {
+		compatible = "fujitsu,mb86s70-gpio";
+		reg = <0 0x31010000 0x10000>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		clocks = <&clock 0 2 1>;
+	};
+
+	sdhci0: mmc at 300c0000 {
+		status = "disabled";
+		compatible = "fujitsu,mb86s70-sdhci-3.0";
+		reg = <0 0x300c0000 0x1000>;
+		interrupts = <0 164 0x4>,
+			     <0 165 0x4>;
+		clocks = <&clock 0 0xc 0>, <&clock 0 0xb 0>;
+		clock-names = "iface", "core";
+	};
+
+	sdhci1: mmc at 36600000 {
+		status = "disabled";
+		compatible = "fujitsu,mb86s70-sdhci-3.0";
+		reg = <0 0x36600000 0x1000>;
+		interrupts = <0 172 0x4>,
+			     <0 173 0x4>;
+		clocks = <&clock 2 0xc 0>, <&clock 2 0xd 0>;
+		clock-names = "iface", "core";
+	};
+};
-- 
1.9.0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 7/8] of: add Fujitsu vendor prefix
  2015-01-09 11:19 ` Vincent Yang
@ 2015-01-09 11:35     ` Vincent Yang
  -1 siblings, 0 replies; 39+ messages in thread
From: Vincent Yang @ 2015-01-09 11:35 UTC (permalink / raw)
  To: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: arnd-r2nGTMty4D4, olof-nZhT3qVonbNeoWH0uzbU5w,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, pawel.moll-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ, andy.green-QSEj5FYQhm4dnm+yROfE0A,
	patches-QSEj5FYQhm4dnm+yROfE0A,
	jaswinder.singh-QSEj5FYQhm4dnm+yROfE0A, Vincent Yang,
	Tetsuya Nuriya

From: Jassi Brar <jaswinder.singh-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

Add 'fujitsu' as the vendor prefix for Fujitsu Semiconductor Ltd.

Signed-off-by: Andy Green <andy.green-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Signed-off-by: Jassi Brar <jaswinder.singh-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Signed-off-by: Vincent Yang <Vincent.Yang-l16TxrwUIHTQFUHtdCDX3A@public.gmane.org>
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Signed-off-by: Tetsuya Nuriya <nuriya.tetsuya-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index b1df0ad..4bc8103 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -59,6 +59,7 @@ everest	Everest Semiconductor Co. Ltd.
 excito	Excito
 fcs	Fairchild Semiconductor
 fsl	Freescale Semiconductor
+fujitsu Fujitsu Semiconductor Ltd.
 GEFanuc	GE Fanuc Intelligent Platforms Embedded Systems, Inc.
 gef	GE Fanuc Intelligent Platforms Embedded Systems, Inc.
 geniatech	Geniatech, Inc.
-- 
1.9.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 7/8] of: add Fujitsu vendor prefix
@ 2015-01-09 11:35     ` Vincent Yang
  0 siblings, 0 replies; 39+ messages in thread
From: Vincent Yang @ 2015-01-09 11:35 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jassi Brar <jaswinder.singh@linaro.org>

Add 'fujitsu' as the vendor prefix for Fujitsu Semiconductor Ltd.

Signed-off-by: Andy Green <andy.green@linaro.org>
Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
Signed-off-by: Vincent Yang <Vincent.Yang@tw.fujitsu.com>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Tetsuya Nuriya <nuriya.tetsuya@jp.fujitsu.com>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index b1df0ad..4bc8103 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -59,6 +59,7 @@ everest	Everest Semiconductor Co. Ltd.
 excito	Excito
 fcs	Fairchild Semiconductor
 fsl	Freescale Semiconductor
+fujitsu Fujitsu Semiconductor Ltd.
 GEFanuc	GE Fanuc Intelligent Platforms Embedded Systems, Inc.
 gef	GE Fanuc Intelligent Platforms Embedded Systems, Inc.
 geniatech	Geniatech, Inc.
-- 
1.9.0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v3 8/8] ARM: MB86S7x: Add configs
  2015-01-09 11:19 ` Vincent Yang
                   ` (4 preceding siblings ...)
  (?)
@ 2015-01-09 11:36 ` Vincent Yang
  -1 siblings, 0 replies; 39+ messages in thread
From: Vincent Yang @ 2015-01-09 11:36 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jassi Brar <jaswinder.singh@linaro.org>

Fujitsu's ARCH_MB86S7X is multi_v7 compatible, so add options to
multi_v7_defconfig. Also add a new defconfig for MB86S7X for those
who want the kernel built specifically for ARCH_MB86S7X.

Signed-off-by: Andy Green <andy.green@linaro.org>
Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
Signed-off-by: Vincent Yang <Vincent.Yang@tw.fujitsu.com>
Signed-off-by: Tetsuya Nuriya <nuriya.tetsuya@jp.fujitsu.com>
---
 arch/arm/configs/fujitsu_defconfig  | 232 ++++++++++++++++++++++++++++++++++++
 arch/arm/configs/multi_v7_defconfig |   5 +
 2 files changed, 237 insertions(+)
 create mode 100644 arch/arm/configs/fujitsu_defconfig

diff --git a/arch/arm/configs/fujitsu_defconfig b/arch/arm/configs/fujitsu_defconfig
new file mode 100644
index 0000000..2d922e4
--- /dev/null
+++ b/arch/arm/configs/fujitsu_defconfig
@@ -0,0 +1,232 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_DEFAULT_HOSTNAME="MB86S7x"
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_NAMESPACES=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_XZ=y
+CONFIG_RD_LZO=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EXPERT=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_ARCH_MB86S7X=y
+CONFIG_ARM_LPAE=y
+CONFIG_ARM_ERRATA_754322=y
+CONFIG_ARM_ERRATA_754327=y
+CONFIG_ARM_ERRATA_764369=y
+CONFIG_ARM_ERRATA_775420=y
+CONFIG_ARM_ERRATA_798181=y
+CONFIG_PCI=y
+CONFIG_SMP=y
+CONFIG_SCHED_MC=y
+CONFIG_SCHED_SMT=y
+CONFIG_VMSPLIT_2G=y
+CONFIG_PREEMPT=y
+CONFIG_THUMB2_KERNEL=y
+CONFIG_HIGHMEM=y
+CONFIG_CMA=y
+CONFIG_CMA_AREAS=8
+# CONFIG_ATAGS is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=2048M console=ttyS0,115200 root=/dev/mmcblk1p1 rootfstype=ext4 rootwait rw"
+CONFIG_KEXEC=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPUFREQ_DT=m
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_RUNTIME=y
+CONFIG_PM_DEBUG=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=192
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_ROM=y
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_PLATRAM=y
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=2
+CONFIG_BLK_DEV_RAM_SIZE=1024
+CONFIG_BLK_DEV_SD=m
+CONFIG_ATA=m
+# CONFIG_ATA_VERBOSE_ERROR is not set
+# CONFIG_SATA_PMP is not set
+CONFIG_SATA_AHCI_PLATFORM=m
+# CONFIG_ATA_SFF is not set
+CONFIG_NETDEVICES=y
+CONFIG_TUN=m
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PHYLIB=y
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
+CONFIG_INPUT_EVDEV=m
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO_POLLED=y
+# CONFIG_MOUSE_PS2 is not set
+CONFIG_MOUSE_GPIO=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_EGALAX=m
+CONFIG_TOUCHSCREEN_ILI210X=m
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=m
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_SPI=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_MB86S7X=y
+CONFIG_GPIO_MCP23S08=m
+# CONFIG_HWMON is not set
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_GPIO=y
+# CONFIG_VGA_ARB is not set
+CONFIG_DRM=y
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=m
+CONFIG_SND=m
+CONFIG_SND_DYNAMIC_MINORS=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_SOC=m
+CONFIG_HID=m
+CONFIG_HID_PID=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=m
+CONFIG_USB_OTG=y
+CONFIG_USB_XHCI_HCD=m
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_HCD_PLATFORM=m
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_HCD_PCI is not set
+CONFIG_USB_OHCI_HCD_PLATFORM=m
+CONFIG_USB_ACM=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_DWC3=m
+CONFIG_USB_DWC3_HOST=y
+CONFIG_USB_DWC3_DEBUG=y
+CONFIG_USB_GADGET=m
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_MULTI=m
+CONFIG_MMC=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_F_SDH30=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_CPU=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_LEDS_TRIGGER_TRANSIENT=m
+CONFIG_DMADEVICES=y
+CONFIG_STAGING=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_LOGGER=m
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ION=y
+CONFIG_ARM_MHU=y
+CONFIG_ARM_SMMU=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_VFAT_FS=m
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=m
+CONFIG_CRAMFS=y
+CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BOTH=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_RCU_CPU_STALL_VERBOSE is not set
+# CONFIG_FTRACE is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+CONFIG_FONTS=y
+CONFIG_FONT_SUN8x16=y
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index bc393b7..102e457 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -49,6 +49,7 @@ CONFIG_SOC_AM43XX=y
 CONFIG_SOC_DRA7XX=y
 CONFIG_ARCH_QCOM=y
 CONFIG_ARCH_MEDIATEK=y
+CONFIG_ARCH_MB86S7X=y
 CONFIG_ARCH_MSM8X60=y
 CONFIG_ARCH_MSM8960=y
 CONFIG_ARCH_MSM8974=y
@@ -259,6 +260,7 @@ CONFIG_GPIO_TWL4030=y
 CONFIG_GPIO_PALMAS=y
 CONFIG_GPIO_TPS6586X=y
 CONFIG_GPIO_TPS65910=y
+CONFIG_GPIO_MB86S7X=y
 CONFIG_BATTERY_SBS=y
 CONFIG_CHARGER_TPS65090=y
 CONFIG_POWER_RESET_AS3722=y
@@ -370,6 +372,7 @@ CONFIG_MMC_SDHCI_SPEAR=y
 CONFIG_MMC_SDHCI_S3C=y
 CONFIG_MMC_SDHCI_S3C_DMA=y
 CONFIG_MMC_SDHCI_BCM_KONA=y
+CONFIG_MMC_SDHCI_F_SDH30=y
 CONFIG_MMC_SDHCI_ST=y
 CONFIG_MMC_OMAP=y
 CONFIG_MMC_OMAP_HS=y
@@ -457,6 +460,8 @@ CONFIG_TI_PIPE3=y
 CONFIG_PHY_MIPHY365X=y
 CONFIG_PHY_STIH41X_USB=y
 CONFIG_PHY_SUN4I_USB=y
+CONFIG_MAILBOX=y
+CONFIG_ARM_MHU=y
 CONFIG_EXT4_FS=y
 CONFIG_AUTOFS4_FS=y
 CONFIG_MSDOS_FS=y
-- 
1.9.0

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* Re: [PATCH v3 4/8] clk: Add clock driver for mb86s7x
  2015-01-09 11:29     ` Vincent Yang
@ 2015-01-09 12:39         ` Russell King - ARM Linux
  -1 siblings, 0 replies; 39+ messages in thread
From: Russell King - ARM Linux @ 2015-01-09 12:39 UTC (permalink / raw)
  To: Vincent Yang
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	arnd-r2nGTMty4D4, olof-nZhT3qVonbNeoWH0uzbU5w,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, pawel.moll-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ, mturquette-QSEj5FYQhm4dnm+yROfE0A,
	andy.green-QSEj5FYQhm4dnm+yROfE0A,
	patches-QSEj5FYQhm4dnm+yROfE0A,
	jaswinder.singh-QSEj5FYQhm4dnm+yROfE0A, Vincent Yang,
	Tetsuya Nuriya

On Fri, Jan 09, 2015 at 07:29:37PM +0800, Vincent Yang wrote:
> +static int mb86s7x_clclk_of_init(void)
> +{
> +	int cpu;
> +	struct clk *clk;
> +
> +	for_each_possible_cpu(cpu) {
> +		struct device *cpu_dev = get_cpu_device(cpu);
> +
> +		if (!cpu_dev) {
> +			pr_err("failed to get cpu%d device\n", cpu);
> +			continue;
> +		}
> +
> +		clk = mb86s7x_clclk_register(cpu_dev);
> +		if (IS_ERR(clk)) {
> +			pr_err("failed to register cpu%d clock\n", cpu);
> +			continue;
> +		}
> +		if (clk_register_clkdev(clk, NULL, dev_name(cpu_dev))) {
> +			pr_err("failed to register cpu%d clock lookup\n", cpu);
> +			continue;
> +		}
> +		pr_debug("registered clk for %s\n", dev_name(cpu_dev));
> +	}
> +
> +	platform_device_register_simple("arm-bL-cpufreq-dt", -1, NULL, 0);
> +
> +	return 0;
> +}
> +module_init(mb86s7x_clclk_of_init);

What is the effect of this initialising on platforms which are not
a "mb86s7x" ?

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v3 4/8] clk: Add clock driver for mb86s7x
@ 2015-01-09 12:39         ` Russell King - ARM Linux
  0 siblings, 0 replies; 39+ messages in thread
From: Russell King - ARM Linux @ 2015-01-09 12:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jan 09, 2015 at 07:29:37PM +0800, Vincent Yang wrote:
> +static int mb86s7x_clclk_of_init(void)
> +{
> +	int cpu;
> +	struct clk *clk;
> +
> +	for_each_possible_cpu(cpu) {
> +		struct device *cpu_dev = get_cpu_device(cpu);
> +
> +		if (!cpu_dev) {
> +			pr_err("failed to get cpu%d device\n", cpu);
> +			continue;
> +		}
> +
> +		clk = mb86s7x_clclk_register(cpu_dev);
> +		if (IS_ERR(clk)) {
> +			pr_err("failed to register cpu%d clock\n", cpu);
> +			continue;
> +		}
> +		if (clk_register_clkdev(clk, NULL, dev_name(cpu_dev))) {
> +			pr_err("failed to register cpu%d clock lookup\n", cpu);
> +			continue;
> +		}
> +		pr_debug("registered clk for %s\n", dev_name(cpu_dev));
> +	}
> +
> +	platform_device_register_simple("arm-bL-cpufreq-dt", -1, NULL, 0);
> +
> +	return 0;
> +}
> +module_init(mb86s7x_clclk_of_init);

What is the effect of this initialising on platforms which are not
a "mb86s7x" ?

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v3 3/8] ARM: MB86S7X: Add MCPM support
  2015-01-09 11:28 ` [PATCH v3 3/8] ARM: MB86S7X: Add MCPM support Vincent Yang
@ 2015-01-09 12:41   ` Russell King - ARM Linux
  2015-01-09 13:23     ` Jassi Brar
  2015-01-09 20:04   ` Nicolas Pitre
  1 sibling, 1 reply; 39+ messages in thread
From: Russell King - ARM Linux @ 2015-01-09 12:41 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jan 09, 2015 at 07:28:54PM +0800, Vincent Yang wrote:
> +static int __init mb86s7x_mcpm_init(void)
> +{
> +	unsigned int mpidr, cpu, cluster;
> +	struct mb86s7x_scb_version cmd;
> +	int ret;
> +
> +	if (!cci_probed())
> +		return -ENODEV;
> +
> +	mpidr = read_cpuid_mpidr();
> +	cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
> +	cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
> +
> +	pr_info("Booting on cpu_%u cluster_%u\n", cpu, cluster);
> +	mb86s7x_pm_use_count[cluster][cpu] = 1;
> +
> +	/* reset the wfi 'color' for primary cpu */
> +	mb86s7x_set_wficolor(cluster, cpu, AT_WFI_DO_NOTHING);
> +
> +	/* Do SMC to set entry address for CPUs coming online */
> +	mb86s7x_cpu_entry(virt_to_phys(mcpm_entry_point));
> +
> +	cmd.payload_size = sizeof(cmd);
> +	cmd.version = 0;
> +	cmd.config_version = 0;
> +	ret = mb86s7x_send_packet(CMD_SCB_CAPABILITY_GET_REQ,
> +				  &cmd, sizeof(cmd));
> +	if (ret < 0) /* non fatal */
> +		pr_err("%s:%d failed to get SCB version\n",
> +		       __func__, __LINE__);
> +	else
> +		pr_err("MB86S7x SCB version 0x%x:0x%x\n",
> +		       cmd.version, cmd.config_version);
> +
> +	ret = mcpm_platform_register(&mb86s7x_pm_power_ops);
> +	if (!ret)
> +		ret = mcpm_sync_init(mb86s7x_pm_power_up_setup);
> +	if (!ret)
> +		ret = mcpm_loopback(mb86s7x_cache_off); /* turn on the CCI */
> +	if (!ret)
> +		mcpm_smp_set_ops();
> +
> +	return ret;
> +}
> +early_initcall(mb86s7x_mcpm_init);

What happens if this is built into a kernel running on another SoC where
CCI has been probed?

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v3 2/8] mailbox: arm_mhu: add driver for ARM MHU controller
  2015-01-09 11:28     ` Vincent Yang
@ 2015-01-09 12:51         ` Russell King - ARM Linux
  -1 siblings, 0 replies; 39+ messages in thread
From: Russell King - ARM Linux @ 2015-01-09 12:51 UTC (permalink / raw)
  To: Vincent Yang
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	arnd-r2nGTMty4D4, olof-nZhT3qVonbNeoWH0uzbU5w,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, pawel.moll-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ, sudeep.holla-5wv7dgnIgG8,
	andy.green-QSEj5FYQhm4dnm+yROfE0A,
	patches-QSEj5FYQhm4dnm+yROfE0A,
	jaswinder.singh-QSEj5FYQhm4dnm+yROfE0A, Vincent Yang,
	Tetsuya Nuriya

On Fri, Jan 09, 2015 at 07:28:09PM +0800, Vincent Yang wrote:
> +static irqreturn_t mhu_rx_interrupt(int irq, void *p)
> +{
> +	struct mbox_chan *chan = p;
> +	struct mhu_link *mlink = (struct mhu_link *)chan->con_priv;
> +	u32 val;
> +
> +	pr_debug("%s:%d\n", __func__, __LINE__);
> +	val = readl_relaxed(mlink->rx_reg + INTR_STAT_OFS);
> +	mbox_chan_received_data(chan, (void *)val);
> +
> +	writel_relaxed(val, mlink->rx_reg + INTR_CLR_OFS);
> +
> +	return IRQ_HANDLED;

What if 'val' was zero - is the interrupt still "handled" ?

> +static int mhu_startup(struct mbox_chan *chan)
> +{
> +	struct mhu_link *mlink = (struct mhu_link *)chan->con_priv;

Casts from void * are not necessary (repeated many times.)

> +	u32 val;
> +	int ret;
> +
> +	pr_debug("%s:%d\n", __func__, __LINE__);
> +	val = readl_relaxed(mlink->tx_reg + INTR_STAT_OFS);
> +	writel_relaxed(val, mlink->tx_reg + INTR_CLR_OFS);
> +
> +	ret = request_irq(mlink->irq, mhu_rx_interrupt,
> +			  IRQF_SHARED, "mhu_link", chan);
> +	if (unlikely(ret)) {
> +		pr_err("Unable to aquire IRQ\n");
> +		return ret;
> +	}
> +
> +	return 0;

Needlessly complicated, and doesn't need that unlikely().  Also doesn't
print the reason for failure, and merely printing "Unable to aquire IRQ"
into the kernel log with no indication what produced it is silly.  You
have the device struct (via chan->mbox->dev), so using dev_err() is a
definite possibility and improvement.

I'm sure this can be cleaned up and simplified.

> +static int arm_mhu_probe(struct platform_device *pdev)
> +{
> +	int i, err;
> +	struct arm_mhu *mhu;
> +	struct resource *res;
> +	int mhu_reg[3] = {0x0, 0x20, 0x200};
> +
> +	/* Allocate memory for device */
> +	mhu = kzalloc(sizeof(*mhu), GFP_KERNEL);
> +	if (!mhu)
> +		return -ENOMEM;

Consider using dev_kzalloc().

> +
> +	mhu->clk = clk_get(&pdev->dev, "clk");

devm_clk_get().

> +	if (unlikely(IS_ERR(mhu->clk)))
> +		dev_info(&pdev->dev, "unable to init clock\n");
> +	else
> +		clk_prepare_enable(mhu->clk);
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	mhu->base = ioremap(res->start, resource_size(res));

That's an oops waiting to happen.  Consider using devm_ioremap_resource()
which will check for !res.

> +	if (!mhu->base) {
> +		dev_err(&pdev->dev, "ioremap failed.\n");
> +		kfree(mhu);
> +		return -EBUSY;
> +	}
> +
> +	for (i = 0; i < 3; i++) {
> +		mhu->chan[i].con_priv = &mhu->mlink[i];
> +		res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
> +		mhu->mlink[i].irq = res->start;
> +		mhu->mlink[i].rx_reg = mhu->base + mhu_reg[i];
> +		mhu->mlink[i].tx_reg = mhu->mlink[i].rx_reg + 0x100;
> +	}
> +
> +	mhu->mbox.dev = &pdev->dev;
> +	mhu->mbox.chans = &mhu->chan[0];
> +	mhu->mbox.num_chans = 3;
> +	mhu->mbox.ops = &mhu_ops;
> +	mhu->mbox.txdone_irq = false;
> +	mhu->mbox.txdone_poll = true;
> +	mhu->mbox.txpoll_period = 10;
> +
> +	platform_set_drvdata(pdev, mhu);
> +
> +	err = mbox_controller_register(&mhu->mbox);
> +	if (err) {
> +		dev_err(&pdev->dev, "Failed to register mailboxes %d\n", err);
> +		iounmap(mhu->base);

You don't clk_put() the clock here.  Using devm_* as suggested above
means you wouldn't have made this mistake here...

> +		kfree(mhu);
> +	} else {
> +		dev_info(&pdev->dev, "ARM MHU Mailbox registered\n");
> +	}
> +
> +	return 0;

Always returns success even if mbox_controller_register() fails?

> +}
> +
> +static int arm_mhu_remove(struct platform_device *pdev)
> +{
> +	struct arm_mhu *mhu = platform_get_drvdata(pdev);
> +
> +	mbox_controller_unregister(&mhu->mbox);
> +
> +	iounmap(mhu->base);
> +
> +	if (!IS_ERR(mhu->clk))
> +		clk_disable_unprepare(mhu->clk);

No clk_put() ?  If you used devm_* stuff as suggested above, you wouldn't
need to...

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v3 2/8] mailbox: arm_mhu: add driver for ARM MHU controller
@ 2015-01-09 12:51         ` Russell King - ARM Linux
  0 siblings, 0 replies; 39+ messages in thread
From: Russell King - ARM Linux @ 2015-01-09 12:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jan 09, 2015 at 07:28:09PM +0800, Vincent Yang wrote:
> +static irqreturn_t mhu_rx_interrupt(int irq, void *p)
> +{
> +	struct mbox_chan *chan = p;
> +	struct mhu_link *mlink = (struct mhu_link *)chan->con_priv;
> +	u32 val;
> +
> +	pr_debug("%s:%d\n", __func__, __LINE__);
> +	val = readl_relaxed(mlink->rx_reg + INTR_STAT_OFS);
> +	mbox_chan_received_data(chan, (void *)val);
> +
> +	writel_relaxed(val, mlink->rx_reg + INTR_CLR_OFS);
> +
> +	return IRQ_HANDLED;

What if 'val' was zero - is the interrupt still "handled" ?

> +static int mhu_startup(struct mbox_chan *chan)
> +{
> +	struct mhu_link *mlink = (struct mhu_link *)chan->con_priv;

Casts from void * are not necessary (repeated many times.)

> +	u32 val;
> +	int ret;
> +
> +	pr_debug("%s:%d\n", __func__, __LINE__);
> +	val = readl_relaxed(mlink->tx_reg + INTR_STAT_OFS);
> +	writel_relaxed(val, mlink->tx_reg + INTR_CLR_OFS);
> +
> +	ret = request_irq(mlink->irq, mhu_rx_interrupt,
> +			  IRQF_SHARED, "mhu_link", chan);
> +	if (unlikely(ret)) {
> +		pr_err("Unable to aquire IRQ\n");
> +		return ret;
> +	}
> +
> +	return 0;

Needlessly complicated, and doesn't need that unlikely().  Also doesn't
print the reason for failure, and merely printing "Unable to aquire IRQ"
into the kernel log with no indication what produced it is silly.  You
have the device struct (via chan->mbox->dev), so using dev_err() is a
definite possibility and improvement.

I'm sure this can be cleaned up and simplified.

> +static int arm_mhu_probe(struct platform_device *pdev)
> +{
> +	int i, err;
> +	struct arm_mhu *mhu;
> +	struct resource *res;
> +	int mhu_reg[3] = {0x0, 0x20, 0x200};
> +
> +	/* Allocate memory for device */
> +	mhu = kzalloc(sizeof(*mhu), GFP_KERNEL);
> +	if (!mhu)
> +		return -ENOMEM;

Consider using dev_kzalloc().

> +
> +	mhu->clk = clk_get(&pdev->dev, "clk");

devm_clk_get().

> +	if (unlikely(IS_ERR(mhu->clk)))
> +		dev_info(&pdev->dev, "unable to init clock\n");
> +	else
> +		clk_prepare_enable(mhu->clk);
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	mhu->base = ioremap(res->start, resource_size(res));

That's an oops waiting to happen.  Consider using devm_ioremap_resource()
which will check for !res.

> +	if (!mhu->base) {
> +		dev_err(&pdev->dev, "ioremap failed.\n");
> +		kfree(mhu);
> +		return -EBUSY;
> +	}
> +
> +	for (i = 0; i < 3; i++) {
> +		mhu->chan[i].con_priv = &mhu->mlink[i];
> +		res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
> +		mhu->mlink[i].irq = res->start;
> +		mhu->mlink[i].rx_reg = mhu->base + mhu_reg[i];
> +		mhu->mlink[i].tx_reg = mhu->mlink[i].rx_reg + 0x100;
> +	}
> +
> +	mhu->mbox.dev = &pdev->dev;
> +	mhu->mbox.chans = &mhu->chan[0];
> +	mhu->mbox.num_chans = 3;
> +	mhu->mbox.ops = &mhu_ops;
> +	mhu->mbox.txdone_irq = false;
> +	mhu->mbox.txdone_poll = true;
> +	mhu->mbox.txpoll_period = 10;
> +
> +	platform_set_drvdata(pdev, mhu);
> +
> +	err = mbox_controller_register(&mhu->mbox);
> +	if (err) {
> +		dev_err(&pdev->dev, "Failed to register mailboxes %d\n", err);
> +		iounmap(mhu->base);

You don't clk_put() the clock here.  Using devm_* as suggested above
means you wouldn't have made this mistake here...

> +		kfree(mhu);
> +	} else {
> +		dev_info(&pdev->dev, "ARM MHU Mailbox registered\n");
> +	}
> +
> +	return 0;

Always returns success even if mbox_controller_register() fails?

> +}
> +
> +static int arm_mhu_remove(struct platform_device *pdev)
> +{
> +	struct arm_mhu *mhu = platform_get_drvdata(pdev);
> +
> +	mbox_controller_unregister(&mhu->mbox);
> +
> +	iounmap(mhu->base);
> +
> +	if (!IS_ERR(mhu->clk))
> +		clk_disable_unprepare(mhu->clk);

No clk_put() ?  If you used devm_* stuff as suggested above, you wouldn't
need to...

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v3 5/8] gpio: Add Fujitsu MB86S7x GPIO driver
  2015-01-09 11:33   ` Vincent Yang
@ 2015-01-09 12:52       ` Russell King - ARM Linux
  -1 siblings, 0 replies; 39+ messages in thread
From: Russell King - ARM Linux @ 2015-01-09 12:52 UTC (permalink / raw)
  To: Vincent Yang
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-gpio-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	mark.rutland-5wv7dgnIgG8, gnurou-Re5JQEeQqe8AvxtiuMwx3w,
	andy.green-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
	pawel.moll-5wv7dgnIgG8, ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
	patches-QSEj5FYQhm4dnm+yROfE0A, Vincent Yang,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, galak-sgV2jX0FEOL9JmXXK+q4OQ,
	olof-nZhT3qVonbNeoWH0uzbU5w,
	jaswinder.singh-QSEj5FYQhm4dnm+yROfE0A, Tetsuya Nuriya

On Fri, Jan 09, 2015 at 07:33:32PM +0800, Vincent Yang wrote:
> +static int mb86s70_gpio_remove(struct platform_device *pdev)
> +{
> +	struct mb86s70_gpio_chip *gchip = platform_get_drvdata(pdev);
> +
> +	gpiochip_remove(&gchip->gc);

This doesn't disable and unprepare the clock.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v3 5/8] gpio: Add Fujitsu MB86S7x GPIO driver
@ 2015-01-09 12:52       ` Russell King - ARM Linux
  0 siblings, 0 replies; 39+ messages in thread
From: Russell King - ARM Linux @ 2015-01-09 12:52 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jan 09, 2015 at 07:33:32PM +0800, Vincent Yang wrote:
> +static int mb86s70_gpio_remove(struct platform_device *pdev)
> +{
> +	struct mb86s70_gpio_chip *gchip = platform_get_drvdata(pdev);
> +
> +	gpiochip_remove(&gchip->gc);

This doesn't disable and unprepare the clock.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v3 4/8] clk: Add clock driver for mb86s7x
  2015-01-09 12:39         ` Russell King - ARM Linux
@ 2015-01-09 13:03             ` Jassi Brar
  -1 siblings, 0 replies; 39+ messages in thread
From: Jassi Brar @ 2015-01-09 13:03 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Vincent Yang, Devicetree List,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Arnd Bergmann,
	Olof Johansson, Rob Herring, Paweł Moll, Mark Rutland,
	ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg, Kumar Gala,
	Mike Turquette, Andy Green, Patch Tracking, Vincent Yang,
	Tetsuya Nuriya

On 9 January 2015 at 18:09, Russell King - ARM Linux
<linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org> wrote:
> On Fri, Jan 09, 2015 at 07:29:37PM +0800, Vincent Yang wrote:
>> +static int mb86s7x_clclk_of_init(void)
>> +{
>> +     int cpu;
>> +     struct clk *clk;
>> +
>> +     for_each_possible_cpu(cpu) {
>> +             struct device *cpu_dev = get_cpu_device(cpu);
>> +
>> +             if (!cpu_dev) {
>> +                     pr_err("failed to get cpu%d device\n", cpu);
>> +                     continue;
>> +             }
>> +
>> +             clk = mb86s7x_clclk_register(cpu_dev);
>> +             if (IS_ERR(clk)) {
>> +                     pr_err("failed to register cpu%d clock\n", cpu);
>> +                     continue;
>> +             }
>> +             if (clk_register_clkdev(clk, NULL, dev_name(cpu_dev))) {
>> +                     pr_err("failed to register cpu%d clock lookup\n", cpu);
>> +                     continue;
>> +             }
>> +             pr_debug("registered clk for %s\n", dev_name(cpu_dev));
>> +     }
>> +
>> +     platform_device_register_simple("arm-bL-cpufreq-dt", -1, NULL, 0);
>> +
>> +     return 0;
>> +}
>> +module_init(mb86s7x_clclk_of_init);
>
> What is the effect of this initialising on platforms which are not
> a "mb86s7x" ?
>
Yeah, there should have been some check for node
"fujitsu,mb86s70-scb-1.0" that guarantees we have a remote+protocol
that this driver assumes.

Thanks
Jassi
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v3 4/8] clk: Add clock driver for mb86s7x
@ 2015-01-09 13:03             ` Jassi Brar
  0 siblings, 0 replies; 39+ messages in thread
From: Jassi Brar @ 2015-01-09 13:03 UTC (permalink / raw)
  To: linux-arm-kernel

On 9 January 2015 at 18:09, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Fri, Jan 09, 2015 at 07:29:37PM +0800, Vincent Yang wrote:
>> +static int mb86s7x_clclk_of_init(void)
>> +{
>> +     int cpu;
>> +     struct clk *clk;
>> +
>> +     for_each_possible_cpu(cpu) {
>> +             struct device *cpu_dev = get_cpu_device(cpu);
>> +
>> +             if (!cpu_dev) {
>> +                     pr_err("failed to get cpu%d device\n", cpu);
>> +                     continue;
>> +             }
>> +
>> +             clk = mb86s7x_clclk_register(cpu_dev);
>> +             if (IS_ERR(clk)) {
>> +                     pr_err("failed to register cpu%d clock\n", cpu);
>> +                     continue;
>> +             }
>> +             if (clk_register_clkdev(clk, NULL, dev_name(cpu_dev))) {
>> +                     pr_err("failed to register cpu%d clock lookup\n", cpu);
>> +                     continue;
>> +             }
>> +             pr_debug("registered clk for %s\n", dev_name(cpu_dev));
>> +     }
>> +
>> +     platform_device_register_simple("arm-bL-cpufreq-dt", -1, NULL, 0);
>> +
>> +     return 0;
>> +}
>> +module_init(mb86s7x_clclk_of_init);
>
> What is the effect of this initialising on platforms which are not
> a "mb86s7x" ?
>
Yeah, there should have been some check for node
"fujitsu,mb86s70-scb-1.0" that guarantees we have a remote+protocol
that this driver assumes.

Thanks
Jassi

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v3 2/8] mailbox: arm_mhu: add driver for ARM MHU controller
  2015-01-09 12:51         ` Russell King - ARM Linux
@ 2015-01-09 13:19             ` Jassi Brar
  -1 siblings, 0 replies; 39+ messages in thread
From: Jassi Brar @ 2015-01-09 13:19 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Vincent Yang, Devicetree List,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Arnd Bergmann,
	Olof Johansson, Rob Herring, Paweł Moll, Mark Rutland,
	ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg, Kumar Gala, Sudeep Holla,
	Andy Green, Patch Tracking, Vincent Yang, Tetsuya Nuriya

On 9 January 2015 at 18:21, Russell King - ARM Linux
<linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org> wrote:
> On Fri, Jan 09, 2015 at 07:28:09PM +0800, Vincent Yang wrote:
>> +static irqreturn_t mhu_rx_interrupt(int irq, void *p)
>> +{
>> +     struct mbox_chan *chan = p;
>> +     struct mhu_link *mlink = (struct mhu_link *)chan->con_priv;
>> +     u32 val;
>> +
>> +     pr_debug("%s:%d\n", __func__, __LINE__);
>> +     val = readl_relaxed(mlink->rx_reg + INTR_STAT_OFS);
>> +     mbox_chan_received_data(chan, (void *)val);
>> +
>> +     writel_relaxed(val, mlink->rx_reg + INTR_CLR_OFS);
>> +
>> +     return IRQ_HANDLED;
>
> What if 'val' was zero - is the interrupt still "handled" ?
>
This irq shouldn't fire unless RX_STAT register has some non-zero value.

>> +static int mhu_startup(struct mbox_chan *chan)
>> +{
>> +     struct mhu_link *mlink = (struct mhu_link *)chan->con_priv;
>
> Casts from void * are not necessary (repeated many times.)
>
>> +     u32 val;
>> +     int ret;
>> +
>> +     pr_debug("%s:%d\n", __func__, __LINE__);
>> +     val = readl_relaxed(mlink->tx_reg + INTR_STAT_OFS);
>> +     writel_relaxed(val, mlink->tx_reg + INTR_CLR_OFS);
>> +
>> +     ret = request_irq(mlink->irq, mhu_rx_interrupt,
>> +                       IRQF_SHARED, "mhu_link", chan);
>> +     if (unlikely(ret)) {
>> +             pr_err("Unable to aquire IRQ\n");
>> +             return ret;
>> +     }
>> +
>> +     return 0;
>
> Needlessly complicated, and doesn't need that unlikely().  Also doesn't
> print the reason for failure, and merely printing "Unable to aquire IRQ"
> into the kernel log with no indication what produced it is silly.  You
> have the device struct (via chan->mbox->dev), so using dev_err() is a
> definite possibility and improvement.
>
> I'm sure this can be cleaned up and simplified.
>
>> +static int arm_mhu_probe(struct platform_device *pdev)
>> +{
>> +     int i, err;
>> +     struct arm_mhu *mhu;
>> +     struct resource *res;
>> +     int mhu_reg[3] = {0x0, 0x20, 0x200};
>> +
>> +     /* Allocate memory for device */
>> +     mhu = kzalloc(sizeof(*mhu), GFP_KERNEL);
>> +     if (!mhu)
>> +             return -ENOMEM;
>
> Consider using dev_kzalloc().
>
>> +
>> +     mhu->clk = clk_get(&pdev->dev, "clk");
>
> devm_clk_get().
>
>> +     if (unlikely(IS_ERR(mhu->clk)))
>> +             dev_info(&pdev->dev, "unable to init clock\n");
>> +     else
>> +             clk_prepare_enable(mhu->clk);
>> +
>> +     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +     mhu->base = ioremap(res->start, resource_size(res));
>
> That's an oops waiting to happen.  Consider using devm_ioremap_resource()
> which will check for !res.
>
>> +     if (!mhu->base) {
>> +             dev_err(&pdev->dev, "ioremap failed.\n");
>> +             kfree(mhu);
>> +             return -EBUSY;
>> +     }
>> +
>> +     for (i = 0; i < 3; i++) {
>> +             mhu->chan[i].con_priv = &mhu->mlink[i];
>> +             res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
>> +             mhu->mlink[i].irq = res->start;
>> +             mhu->mlink[i].rx_reg = mhu->base + mhu_reg[i];
>> +             mhu->mlink[i].tx_reg = mhu->mlink[i].rx_reg + 0x100;
>> +     }
>> +
>> +     mhu->mbox.dev = &pdev->dev;
>> +     mhu->mbox.chans = &mhu->chan[0];
>> +     mhu->mbox.num_chans = 3;
>> +     mhu->mbox.ops = &mhu_ops;
>> +     mhu->mbox.txdone_irq = false;
>> +     mhu->mbox.txdone_poll = true;
>> +     mhu->mbox.txpoll_period = 10;
>> +
>> +     platform_set_drvdata(pdev, mhu);
>> +
>> +     err = mbox_controller_register(&mhu->mbox);
>> +     if (err) {
>> +             dev_err(&pdev->dev, "Failed to register mailboxes %d\n", err);
>> +             iounmap(mhu->base);
>
> You don't clk_put() the clock here.  Using devm_* as suggested above
> means you wouldn't have made this mistake here...
>
>> +             kfree(mhu);
>> +     } else {
>> +             dev_info(&pdev->dev, "ARM MHU Mailbox registered\n");
>> +     }
>> +
>> +     return 0;
>
> Always returns success even if mbox_controller_register() fails?
>
>> +}
>> +
>> +static int arm_mhu_remove(struct platform_device *pdev)
>> +{
>> +     struct arm_mhu *mhu = platform_get_drvdata(pdev);
>> +
>> +     mbox_controller_unregister(&mhu->mbox);
>> +
>> +     iounmap(mhu->base);
>> +
>> +     if (!IS_ERR(mhu->clk))
>> +             clk_disable_unprepare(mhu->clk);
>
> No clk_put() ?  If you used devm_* stuff as suggested above, you wouldn't
> need to...
>
Yes, we should have implemented managed resource allocation. Will do.

Thanks,
Jassi
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v3 2/8] mailbox: arm_mhu: add driver for ARM MHU controller
@ 2015-01-09 13:19             ` Jassi Brar
  0 siblings, 0 replies; 39+ messages in thread
From: Jassi Brar @ 2015-01-09 13:19 UTC (permalink / raw)
  To: linux-arm-kernel

On 9 January 2015 at 18:21, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Fri, Jan 09, 2015 at 07:28:09PM +0800, Vincent Yang wrote:
>> +static irqreturn_t mhu_rx_interrupt(int irq, void *p)
>> +{
>> +     struct mbox_chan *chan = p;
>> +     struct mhu_link *mlink = (struct mhu_link *)chan->con_priv;
>> +     u32 val;
>> +
>> +     pr_debug("%s:%d\n", __func__, __LINE__);
>> +     val = readl_relaxed(mlink->rx_reg + INTR_STAT_OFS);
>> +     mbox_chan_received_data(chan, (void *)val);
>> +
>> +     writel_relaxed(val, mlink->rx_reg + INTR_CLR_OFS);
>> +
>> +     return IRQ_HANDLED;
>
> What if 'val' was zero - is the interrupt still "handled" ?
>
This irq shouldn't fire unless RX_STAT register has some non-zero value.

>> +static int mhu_startup(struct mbox_chan *chan)
>> +{
>> +     struct mhu_link *mlink = (struct mhu_link *)chan->con_priv;
>
> Casts from void * are not necessary (repeated many times.)
>
>> +     u32 val;
>> +     int ret;
>> +
>> +     pr_debug("%s:%d\n", __func__, __LINE__);
>> +     val = readl_relaxed(mlink->tx_reg + INTR_STAT_OFS);
>> +     writel_relaxed(val, mlink->tx_reg + INTR_CLR_OFS);
>> +
>> +     ret = request_irq(mlink->irq, mhu_rx_interrupt,
>> +                       IRQF_SHARED, "mhu_link", chan);
>> +     if (unlikely(ret)) {
>> +             pr_err("Unable to aquire IRQ\n");
>> +             return ret;
>> +     }
>> +
>> +     return 0;
>
> Needlessly complicated, and doesn't need that unlikely().  Also doesn't
> print the reason for failure, and merely printing "Unable to aquire IRQ"
> into the kernel log with no indication what produced it is silly.  You
> have the device struct (via chan->mbox->dev), so using dev_err() is a
> definite possibility and improvement.
>
> I'm sure this can be cleaned up and simplified.
>
>> +static int arm_mhu_probe(struct platform_device *pdev)
>> +{
>> +     int i, err;
>> +     struct arm_mhu *mhu;
>> +     struct resource *res;
>> +     int mhu_reg[3] = {0x0, 0x20, 0x200};
>> +
>> +     /* Allocate memory for device */
>> +     mhu = kzalloc(sizeof(*mhu), GFP_KERNEL);
>> +     if (!mhu)
>> +             return -ENOMEM;
>
> Consider using dev_kzalloc().
>
>> +
>> +     mhu->clk = clk_get(&pdev->dev, "clk");
>
> devm_clk_get().
>
>> +     if (unlikely(IS_ERR(mhu->clk)))
>> +             dev_info(&pdev->dev, "unable to init clock\n");
>> +     else
>> +             clk_prepare_enable(mhu->clk);
>> +
>> +     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +     mhu->base = ioremap(res->start, resource_size(res));
>
> That's an oops waiting to happen.  Consider using devm_ioremap_resource()
> which will check for !res.
>
>> +     if (!mhu->base) {
>> +             dev_err(&pdev->dev, "ioremap failed.\n");
>> +             kfree(mhu);
>> +             return -EBUSY;
>> +     }
>> +
>> +     for (i = 0; i < 3; i++) {
>> +             mhu->chan[i].con_priv = &mhu->mlink[i];
>> +             res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
>> +             mhu->mlink[i].irq = res->start;
>> +             mhu->mlink[i].rx_reg = mhu->base + mhu_reg[i];
>> +             mhu->mlink[i].tx_reg = mhu->mlink[i].rx_reg + 0x100;
>> +     }
>> +
>> +     mhu->mbox.dev = &pdev->dev;
>> +     mhu->mbox.chans = &mhu->chan[0];
>> +     mhu->mbox.num_chans = 3;
>> +     mhu->mbox.ops = &mhu_ops;
>> +     mhu->mbox.txdone_irq = false;
>> +     mhu->mbox.txdone_poll = true;
>> +     mhu->mbox.txpoll_period = 10;
>> +
>> +     platform_set_drvdata(pdev, mhu);
>> +
>> +     err = mbox_controller_register(&mhu->mbox);
>> +     if (err) {
>> +             dev_err(&pdev->dev, "Failed to register mailboxes %d\n", err);
>> +             iounmap(mhu->base);
>
> You don't clk_put() the clock here.  Using devm_* as suggested above
> means you wouldn't have made this mistake here...
>
>> +             kfree(mhu);
>> +     } else {
>> +             dev_info(&pdev->dev, "ARM MHU Mailbox registered\n");
>> +     }
>> +
>> +     return 0;
>
> Always returns success even if mbox_controller_register() fails?
>
>> +}
>> +
>> +static int arm_mhu_remove(struct platform_device *pdev)
>> +{
>> +     struct arm_mhu *mhu = platform_get_drvdata(pdev);
>> +
>> +     mbox_controller_unregister(&mhu->mbox);
>> +
>> +     iounmap(mhu->base);
>> +
>> +     if (!IS_ERR(mhu->clk))
>> +             clk_disable_unprepare(mhu->clk);
>
> No clk_put() ?  If you used devm_* stuff as suggested above, you wouldn't
> need to...
>
Yes, we should have implemented managed resource allocation. Will do.

Thanks,
Jassi

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v3 5/8] gpio: Add Fujitsu MB86S7x GPIO driver
  2015-01-09 12:52       ` Russell King - ARM Linux
@ 2015-01-09 13:20         ` Jassi Brar
  -1 siblings, 0 replies; 39+ messages in thread
From: Jassi Brar @ 2015-01-09 13:20 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Mark Rutland, Alexandre Courbot, Andy Green, Paweł Moll,
	Arnd Bergmann, Devicetree List, Olof Johansson, Vincent Yang,
	Linus Walleij, ijc+devicetree, Vincent Yang, linux-gpio,
	Rob Herring, Patch Tracking, Kumar Gala, Grant Likely,
	Tetsuya Nuriya, linux-arm-kernel

On 9 January 2015 at 18:22, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Fri, Jan 09, 2015 at 07:33:32PM +0800, Vincent Yang wrote:
>> +static int mb86s70_gpio_remove(struct platform_device *pdev)
>> +{
>> +     struct mb86s70_gpio_chip *gchip = platform_get_drvdata(pdev);
>> +
>> +     gpiochip_remove(&gchip->gc);
>
> This doesn't disable and unprepare the clock.
>
Will do.

Thanks,
Jassi

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v3 5/8] gpio: Add Fujitsu MB86S7x GPIO driver
@ 2015-01-09 13:20         ` Jassi Brar
  0 siblings, 0 replies; 39+ messages in thread
From: Jassi Brar @ 2015-01-09 13:20 UTC (permalink / raw)
  To: linux-arm-kernel

On 9 January 2015 at 18:22, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Fri, Jan 09, 2015 at 07:33:32PM +0800, Vincent Yang wrote:
>> +static int mb86s70_gpio_remove(struct platform_device *pdev)
>> +{
>> +     struct mb86s70_gpio_chip *gchip = platform_get_drvdata(pdev);
>> +
>> +     gpiochip_remove(&gchip->gc);
>
> This doesn't disable and unprepare the clock.
>
Will do.

Thanks,
Jassi

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v3 3/8] ARM: MB86S7X: Add MCPM support
  2015-01-09 12:41   ` Russell King - ARM Linux
@ 2015-01-09 13:23     ` Jassi Brar
  0 siblings, 0 replies; 39+ messages in thread
From: Jassi Brar @ 2015-01-09 13:23 UTC (permalink / raw)
  To: linux-arm-kernel

On 9 January 2015 at 18:11, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Fri, Jan 09, 2015 at 07:28:54PM +0800, Vincent Yang wrote:
>> +static int __init mb86s7x_mcpm_init(void)
>> +{
>> +     unsigned int mpidr, cpu, cluster;
>> +     struct mb86s7x_scb_version cmd;
>> +     int ret;
>> +
>> +     if (!cci_probed())
>> +             return -ENODEV;
>> +
>> +     mpidr = read_cpuid_mpidr();
>> +     cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
>> +     cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
>> +
>> +     pr_info("Booting on cpu_%u cluster_%u\n", cpu, cluster);
>> +     mb86s7x_pm_use_count[cluster][cpu] = 1;
>> +
>> +     /* reset the wfi 'color' for primary cpu */
>> +     mb86s7x_set_wficolor(cluster, cpu, AT_WFI_DO_NOTHING);
>> +
>> +     /* Do SMC to set entry address for CPUs coming online */
>> +     mb86s7x_cpu_entry(virt_to_phys(mcpm_entry_point));
>> +
>> +     cmd.payload_size = sizeof(cmd);
>> +     cmd.version = 0;
>> +     cmd.config_version = 0;
>> +     ret = mb86s7x_send_packet(CMD_SCB_CAPABILITY_GET_REQ,
>> +                               &cmd, sizeof(cmd));
>> +     if (ret < 0) /* non fatal */
>> +             pr_err("%s:%d failed to get SCB version\n",
>> +                    __func__, __LINE__);
>> +     else
>> +             pr_err("MB86S7x SCB version 0x%x:0x%x\n",
>> +                    cmd.version, cmd.config_version);
>> +
>> +     ret = mcpm_platform_register(&mb86s7x_pm_power_ops);
>> +     if (!ret)
>> +             ret = mcpm_sync_init(mb86s7x_pm_power_up_setup);
>> +     if (!ret)
>> +             ret = mcpm_loopback(mb86s7x_cache_off); /* turn on the CCI */
>> +     if (!ret)
>> +             mcpm_smp_set_ops();
>> +
>> +     return ret;
>> +}
>> +early_initcall(mb86s7x_mcpm_init);
>
> What happens if this is built into a kernel running on another SoC where
> CCI has been probed?
>
Yeah, need to check for presence of "fujitsu,mb86s70-scb-1.0" node at
the start of this and other xxx_initcall()s.

thanks
jassi

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v3 2/8] mailbox: arm_mhu: add driver for ARM MHU controller
  2015-01-09 13:19             ` Jassi Brar
@ 2015-01-09 15:24               ` Russell King - ARM Linux
  -1 siblings, 0 replies; 39+ messages in thread
From: Russell King - ARM Linux @ 2015-01-09 15:24 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Mark Rutland, Devicetree List, Andy Green, Paweł Moll,
	Arnd Bergmann, ijc+devicetree, Vincent Yang, Sudeep Holla,
	Vincent Yang, Rob Herring, Patch Tracking, Kumar Gala,
	Olof Johansson, Tetsuya Nuriya, linux-arm-kernel

On Fri, Jan 09, 2015 at 06:49:12PM +0530, Jassi Brar wrote:
> On 9 January 2015 at 18:21, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
> > On Fri, Jan 09, 2015 at 07:28:09PM +0800, Vincent Yang wrote:
> >> +static irqreturn_t mhu_rx_interrupt(int irq, void *p)
> >> +{
> >> +     struct mbox_chan *chan = p;
> >> +     struct mhu_link *mlink = (struct mhu_link *)chan->con_priv;
> >> +     u32 val;
> >> +
> >> +     pr_debug("%s:%d\n", __func__, __LINE__);
> >> +     val = readl_relaxed(mlink->rx_reg + INTR_STAT_OFS);
> >> +     mbox_chan_received_data(chan, (void *)val);
> >> +
> >> +     writel_relaxed(val, mlink->rx_reg + INTR_CLR_OFS);
> >> +
> >> +     return IRQ_HANDLED;
> >
> > What if 'val' was zero - is the interrupt still "handled" ?
> >
> This irq shouldn't fire unless RX_STAT register has some non-zero value.

You claim this interrupt handler using IRQF_SHARED - what if another user
of this interrupt gets stuck?  Your handler above will prevent the kernel
recovering as it will think that you are validly processing the stuck
interrupt each time.

If it isn't shared, then don't use IRQF_SHARED.

Either way, it is good practice to return IRQ_NONE if there's no work to
be done.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v3 2/8] mailbox: arm_mhu: add driver for ARM MHU controller
@ 2015-01-09 15:24               ` Russell King - ARM Linux
  0 siblings, 0 replies; 39+ messages in thread
From: Russell King - ARM Linux @ 2015-01-09 15:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jan 09, 2015 at 06:49:12PM +0530, Jassi Brar wrote:
> On 9 January 2015 at 18:21, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
> > On Fri, Jan 09, 2015 at 07:28:09PM +0800, Vincent Yang wrote:
> >> +static irqreturn_t mhu_rx_interrupt(int irq, void *p)
> >> +{
> >> +     struct mbox_chan *chan = p;
> >> +     struct mhu_link *mlink = (struct mhu_link *)chan->con_priv;
> >> +     u32 val;
> >> +
> >> +     pr_debug("%s:%d\n", __func__, __LINE__);
> >> +     val = readl_relaxed(mlink->rx_reg + INTR_STAT_OFS);
> >> +     mbox_chan_received_data(chan, (void *)val);
> >> +
> >> +     writel_relaxed(val, mlink->rx_reg + INTR_CLR_OFS);
> >> +
> >> +     return IRQ_HANDLED;
> >
> > What if 'val' was zero - is the interrupt still "handled" ?
> >
> This irq shouldn't fire unless RX_STAT register has some non-zero value.

You claim this interrupt handler using IRQF_SHARED - what if another user
of this interrupt gets stuck?  Your handler above will prevent the kernel
recovering as it will think that you are validly processing the stuck
interrupt each time.

If it isn't shared, then don't use IRQF_SHARED.

Either way, it is good practice to return IRQ_NONE if there's no work to
be done.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v3 2/8] mailbox: arm_mhu: add driver for ARM MHU controller
  2015-01-09 15:24               ` Russell King - ARM Linux
@ 2015-01-09 15:29                   ` Jassi Brar
  -1 siblings, 0 replies; 39+ messages in thread
From: Jassi Brar @ 2015-01-09 15:29 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Vincent Yang, Devicetree List,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Arnd Bergmann,
	Olof Johansson, Rob Herring, Paweł Moll, Mark Rutland,
	ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg, Kumar Gala, Sudeep Holla,
	Andy Green, Patch Tracking, Vincent Yang, Tetsuya Nuriya

On 9 January 2015 at 20:54, Russell King - ARM Linux
<linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org> wrote:
> On Fri, Jan 09, 2015 at 06:49:12PM +0530, Jassi Brar wrote:
>> On 9 January 2015 at 18:21, Russell King - ARM Linux
>> <linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org> wrote:
>> > On Fri, Jan 09, 2015 at 07:28:09PM +0800, Vincent Yang wrote:
>> >> +static irqreturn_t mhu_rx_interrupt(int irq, void *p)
>> >> +{
>> >> +     struct mbox_chan *chan = p;
>> >> +     struct mhu_link *mlink = (struct mhu_link *)chan->con_priv;
>> >> +     u32 val;
>> >> +
>> >> +     pr_debug("%s:%d\n", __func__, __LINE__);
>> >> +     val = readl_relaxed(mlink->rx_reg + INTR_STAT_OFS);
>> >> +     mbox_chan_received_data(chan, (void *)val);
>> >> +
>> >> +     writel_relaxed(val, mlink->rx_reg + INTR_CLR_OFS);
>> >> +
>> >> +     return IRQ_HANDLED;
>> >
>> > What if 'val' was zero - is the interrupt still "handled" ?
>> >
>> This irq shouldn't fire unless RX_STAT register has some non-zero value.
>
> You claim this interrupt handler using IRQF_SHARED - what if another user
> of this interrupt gets stuck?  Your handler above will prevent the kernel
> recovering as it will think that you are validly processing the stuck
> interrupt each time.
>
> If it isn't shared, then don't use IRQF_SHARED.
>
> Either way, it is good practice to return IRQ_NONE if there's no work to
> be done.
>
OK, will do.

thanks.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v3 2/8] mailbox: arm_mhu: add driver for ARM MHU controller
@ 2015-01-09 15:29                   ` Jassi Brar
  0 siblings, 0 replies; 39+ messages in thread
From: Jassi Brar @ 2015-01-09 15:29 UTC (permalink / raw)
  To: linux-arm-kernel

On 9 January 2015 at 20:54, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Fri, Jan 09, 2015 at 06:49:12PM +0530, Jassi Brar wrote:
>> On 9 January 2015 at 18:21, Russell King - ARM Linux
>> <linux@arm.linux.org.uk> wrote:
>> > On Fri, Jan 09, 2015 at 07:28:09PM +0800, Vincent Yang wrote:
>> >> +static irqreturn_t mhu_rx_interrupt(int irq, void *p)
>> >> +{
>> >> +     struct mbox_chan *chan = p;
>> >> +     struct mhu_link *mlink = (struct mhu_link *)chan->con_priv;
>> >> +     u32 val;
>> >> +
>> >> +     pr_debug("%s:%d\n", __func__, __LINE__);
>> >> +     val = readl_relaxed(mlink->rx_reg + INTR_STAT_OFS);
>> >> +     mbox_chan_received_data(chan, (void *)val);
>> >> +
>> >> +     writel_relaxed(val, mlink->rx_reg + INTR_CLR_OFS);
>> >> +
>> >> +     return IRQ_HANDLED;
>> >
>> > What if 'val' was zero - is the interrupt still "handled" ?
>> >
>> This irq shouldn't fire unless RX_STAT register has some non-zero value.
>
> You claim this interrupt handler using IRQF_SHARED - what if another user
> of this interrupt gets stuck?  Your handler above will prevent the kernel
> recovering as it will think that you are validly processing the stuck
> interrupt each time.
>
> If it isn't shared, then don't use IRQF_SHARED.
>
> Either way, it is good practice to return IRQ_NONE if there's no work to
> be done.
>
OK, will do.

thanks.

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v3 3/8] ARM: MB86S7X: Add MCPM support
  2015-01-09 11:28 ` [PATCH v3 3/8] ARM: MB86S7X: Add MCPM support Vincent Yang
  2015-01-09 12:41   ` Russell King - ARM Linux
@ 2015-01-09 20:04   ` Nicolas Pitre
  1 sibling, 0 replies; 39+ messages in thread
From: Nicolas Pitre @ 2015-01-09 20:04 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 9 Jan 2015, Vincent Yang wrote:

> From: Jassi Brar <jaswinder.singh@linaro.org>
> 
> The remote firmware(SCB) owns the SMP control. This MCPM driver gets
> CPU/CLUSTER power up/down done by SCB over mailbox.
> 
> Signed-off-by: Andy Green <andy.green@linaro.org>
> Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
> Signed-off-by: Vincent Yang <Vincent.Yang@tw.fujitsu.com>
> Signed-off-by: Tetsuya Nuriya <nuriya.tetsuya@jp.fujitsu.com>

Once the initcall issue raised by Russell is fixed you can add:

Reviewed-by: Nicolas Pitre <nico@linaro.org>


> ---
>  arch/arm/mach-mb86s7x/Makefile |   4 +-
>  arch/arm/mach-mb86s7x/mcpm.c   | 315 +++++++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-mb86s7x/smc.S    |  27 ++++
>  drivers/soc/mb86s7x/scb_mhu.c  |  14 ++
>  include/soc/mb86s7x/scb_mhu.h  |   8 ++
>  5 files changed, 367 insertions(+), 1 deletion(-)
>  create mode 100644 arch/arm/mach-mb86s7x/mcpm.c
>  create mode 100644 arch/arm/mach-mb86s7x/smc.S
> 
> diff --git a/arch/arm/mach-mb86s7x/Makefile b/arch/arm/mach-mb86s7x/Makefile
> index 97640b6..00e843c 100644
> --- a/arch/arm/mach-mb86s7x/Makefile
> +++ b/arch/arm/mach-mb86s7x/Makefile
> @@ -1 +1,3 @@
> -obj-$(CONFIG_ARCH_MB86S7X)	+= board.o
> +obj-$(CONFIG_ARCH_MB86S7X)	+= board.o mcpm.o smc.o
> +CFLAGS_smc.o			+= -march=armv7-a
> +CFLAGS_mcpm.o			+= -march=armv7-a
> diff --git a/arch/arm/mach-mb86s7x/mcpm.c b/arch/arm/mach-mb86s7x/mcpm.c
> new file mode 100644
> index 0000000..c278c6e
> --- /dev/null
> +++ b/arch/arm/mach-mb86s7x/mcpm.c
> @@ -0,0 +1,315 @@
> +/*
> + * arch/arm/mach-mb86s7x/mcpm.c
> + * Copyright:	(C) 2013-2015 Fujitsu Semiconductor Limited
> + * Copyright:	(C) 2015 Linaro Ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/io.h>
> +#include <linux/pm.h>
> +#include <linux/delay.h>
> +#include <linux/cpu_pm.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/arm-cci.h>
> +#include <linux/spinlock.h>
> +#include <linux/suspend.h>
> +#include <linux/of_device.h>
> +#include <linux/irqchip/arm-gic.h>
> +#include <linux/platform_device.h>
> +
> +#include <soc/mb86s7x/scb_mhu.h>
> +
> +#include <asm/mcpm.h>
> +#include <asm/cp15.h>
> +#include <asm/cputype.h>
> +#include <asm/suspend.h>
> +#include <asm/idmap.h>
> +
> +#define S7X_MAX_CLUSTER	2
> +#define S7X_MAX_CPU	2
> +
> +#define MHU_SHM_OFFSET		0x3800
> +#define TRAMPOLINE_OFFSET	0x3c00
> +#define RESET_OFFSET		(TRAMPOLINE_OFFSET + 0x3fc)
> +
> +static arch_spinlock_t mb86s7x_pm_lock = __ARCH_SPIN_LOCK_UNLOCKED;
> +static int mb86s7x_pm_use_count[S7X_MAX_CLUSTER][S7X_MAX_CPU];
> +
> +struct mb86s7x_cpu_gate {
> +	u32 payload_size;
> +	u32 cluster_class;
> +	u32 cluster_id;
> +	u32 cpu_id;
> +#define SCB_CPU_STATE_OFF	0x0
> +#define SCB_CPU_STATE_ON	0x1
> +#define SCB_CPU_STATE_SUSP	0x2
> +	u32 cpu_state;
> +};
> +
> +static int mb86s7x_pm_power_up(unsigned int cpu, unsigned int cluster)
> +{
> +	int ret = 0;
> +
> +	if (cluster >= S7X_MAX_CLUSTER || cpu >= S7X_MAX_CPU)
> +		return -EINVAL;
> +
> +	pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
> +
> +	local_irq_disable();
> +	arch_spin_lock(&mb86s7x_pm_lock);
> +
> +	mb86s7x_pm_use_count[cluster][cpu]++;
> +
> +	if (mb86s7x_pm_use_count[cluster][cpu] == 1) {
> +		struct mb86s7x_cpu_gate cmd;
> +
> +		mb86s7x_set_wficolor(cluster, cpu, AT_WFI_DO_NOTHING);
> +		arch_spin_unlock(&mb86s7x_pm_lock);
> +		local_irq_enable();
> +
> +		cmd.payload_size = sizeof(cmd);
> +		cmd.cluster_class = 0;
> +		cmd.cluster_id = cluster;
> +		cmd.cpu_id = cpu;
> +		cmd.cpu_state = SCB_CPU_STATE_ON;
> +
> +		pr_debug("%s:%d CMD Cl_Class-%u CL_ID-%u CPU_ID-%u STATE-%u}\n",
> +			 __func__, __LINE__, cmd.cluster_class,
> +			 cmd.cluster_id, cmd.cpu_id, cmd.cpu_state);
> +
> +		ret = mb86s7x_send_packet(CMD_CPU_CLOCK_GATE_SET_REQ,
> +					  &cmd, sizeof(cmd));
> +		if (ret < 0) {
> +			pr_err("%s:%d failed!\n", __func__, __LINE__);
> +			return ret;
> +		}
> +
> +		pr_debug("%s:%d REP Cl_Class-%u CL_ID-%u CPU_ID-%u STATE-%u}\n",
> +			 __func__, __LINE__, cmd.cluster_class,
> +			 cmd.cluster_id, cmd.cpu_id, cmd.cpu_state);
> +
> +		if (cmd.cpu_state != SCB_CPU_STATE_ON)
> +			return -ENODEV;
> +	} else if (mb86s7x_pm_use_count[cluster][cpu] == 2) {
> +		arch_spin_unlock(&mb86s7x_pm_lock);
> +		local_irq_enable();
> +	} else {
> +		/*
> +		 * The only possible values are:
> +		 * 0 = CPU down
> +		 * 1 = CPU (still) up
> +		 * 2 = CPU requested to be up before it had a chance
> +		 *     to actually make itself down.
> +		 * Any other value is a bug.
> +		 */
> +		BUG();
> +	}
> +
> +	return 0;
> +}
> +
> +static void mb86s7x_pm_suspend(u64 ignored)
> +{
> +	unsigned int mpidr, cpu, cluster;
> +	bool last_man = false, skip_wfi = false;
> +
> +	mpidr = read_cpuid_mpidr();
> +	cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
> +	cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
> +
> +	pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
> +	__mcpm_cpu_going_down(cpu, cluster);
> +
> +	arch_spin_lock(&mb86s7x_pm_lock);
> +	BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP);
> +
> +	mb86s7x_pm_use_count[cluster][cpu]--;
> +
> +	if (mb86s7x_pm_use_count[cluster][cpu] == 0) {
> +		if (!mb86s7x_pm_use_count[cluster][0] &&
> +		    !mb86s7x_pm_use_count[cluster][1])
> +			last_man = true;
> +		mb86s7x_set_wficolor(cluster, cpu, AT_WFI_DO_POWEROFF);
> +	} else if (mb86s7x_pm_use_count[cluster][cpu] == 1) {
> +		skip_wfi = true; /* Overtaken by a power up */
> +	} else {
> +		BUG();
> +	}
> +
> +	if (!skip_wfi)
> +		gic_cpu_if_down();
> +
> +	if (last_man && __mcpm_outbound_enter_critical(cpu, cluster)) {
> +		arch_spin_unlock(&mb86s7x_pm_lock);
> +
> +		if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) {
> +			/*
> +			 * On the Cortex-A15 we need to disable
> +			 * L2 prefetching before flushing the cache.
> +			 */
> +			asm volatile(
> +			"mcr p15, 1, %0, c15, c0, 3\n\t"
> +			"isb\n\t"
> +			"dsb"
> +			: : "r" (0x400));
> +		}
> +
> +		v7_exit_coherency_flush(all);
> +
> +		cci_disable_port_by_cpu(mpidr);
> +
> +		__mcpm_outbound_leave_critical(cluster, CLUSTER_DOWN);
> +	} else {
> +		arch_spin_unlock(&mb86s7x_pm_lock);
> +		v7_exit_coherency_flush(louis);
> +	}
> +
> +	__mcpm_cpu_down(cpu, cluster);
> +
> +	/* Now we are prepared for power-down, do it: */
> +	if (!skip_wfi)
> +		wfi();
> +}
> +
> +static void mb86s7x_pm_power_down(void)
> +{
> +	mb86s7x_pm_suspend(0);
> +}
> +
> +static int mb86s7x_wait_for_powerdown(unsigned int cpu, unsigned int cluster)
> +{
> +	struct mb86s7x_cpu_gate cmd;
> +	int i, ret;
> +
> +	BUG_ON(cluster >= S7X_MAX_CLUSTER || cpu >= S7X_MAX_CPU);
> +
> +	cmd.payload_size = sizeof(cmd);
> +	cmd.cluster_class = 0;
> +	cmd.cluster_id = cluster;
> +	cmd.cpu_id = cpu;
> +	cmd.cpu_state = SCB_CPU_STATE_ON;
> +
> +	for (i = 0; i < 50; i++) {
> +		ret = mb86s7x_send_packet(CMD_CPU_CLOCK_GATE_GET_REQ,
> +					  &cmd, sizeof(cmd));
> +		if (ret < 0) {
> +			pr_err("%s:%d failed to get CPU status\n",
> +			       __func__, __LINE__);
> +			return ret;
> +		}
> +
> +		pr_debug("%s:%d Cl_Class-%u CL_ID-%u CPU_ID-%u STATE-%u\n",
> +			 __func__, __LINE__,
> +			 cmd.cluster_class, cmd.cluster_id,
> +			 cmd.cpu_id, cmd.cpu_state);
> +
> +		if (cmd.cpu_state == SCB_CPU_STATE_OFF)
> +			return 0;
> +
> +		msleep(20);
> +	}
> +
> +	return -ETIMEDOUT;
> +}
> +
> +static void mb86s7x_pm_powered_up(void)
> +{
> +	unsigned int mpidr, cpu, cluster;
> +
> +	mpidr = read_cpuid_mpidr();
> +	cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
> +	cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
> +
> +	arch_spin_lock(&mb86s7x_pm_lock);
> +	if (!mb86s7x_pm_use_count[cluster][cpu])
> +		mb86s7x_pm_use_count[cluster][cpu] = 1;
> +	arch_spin_unlock(&mb86s7x_pm_lock);
> +}
> +
> +static const struct mcpm_platform_ops mb86s7x_pm_power_ops = {
> +	.power_up		= mb86s7x_pm_power_up,
> +	.power_down		= mb86s7x_pm_power_down,
> +	.wait_for_powerdown	= mb86s7x_wait_for_powerdown,
> +	.suspend		= mb86s7x_pm_suspend,
> +	.powered_up		= mb86s7x_pm_powered_up,
> +};
> +
> +/*
> + * Enable cluster-level coherency, in preparation for turning on the MMU.
> + */
> +static void __naked mb86s7x_pm_power_up_setup(unsigned int affinity_level)
> +{
> +	asm volatile ("\n"
> +"	cmp	r0, #1\n"
> +"	bxne	lr\n"
> +"	b	cci_enable_port_for_self");
> +}
> +
> +static void __init mb86s7x_cache_off(void)
> +{
> +	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) {
> +		/* disable L2 prefetching on the Cortex-A15 */
> +		asm volatile(
> +		"mcr	p15, 1, %0, c15, c0, 3\n\t"
> +		"isb\n\t"
> +		"dsb"
> +		: : "r" (0x400));
> +	}
> +	v7_exit_coherency_flush(all);
> +}
> +
> +struct mb86s7x_scb_version {
> +	u32 payload_size;
> +	u32 version;
> +	u32 config_version;
> +};
> +
> +static int __init mb86s7x_mcpm_init(void)
> +{
> +	unsigned int mpidr, cpu, cluster;
> +	struct mb86s7x_scb_version cmd;
> +	int ret;
> +
> +	if (!cci_probed())
> +		return -ENODEV;
> +
> +	mpidr = read_cpuid_mpidr();
> +	cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
> +	cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
> +
> +	pr_info("Booting on cpu_%u cluster_%u\n", cpu, cluster);
> +	mb86s7x_pm_use_count[cluster][cpu] = 1;
> +
> +	/* reset the wfi 'color' for primary cpu */
> +	mb86s7x_set_wficolor(cluster, cpu, AT_WFI_DO_NOTHING);
> +
> +	/* Do SMC to set entry address for CPUs coming online */
> +	mb86s7x_cpu_entry(virt_to_phys(mcpm_entry_point));
> +
> +	cmd.payload_size = sizeof(cmd);
> +	cmd.version = 0;
> +	cmd.config_version = 0;
> +	ret = mb86s7x_send_packet(CMD_SCB_CAPABILITY_GET_REQ,
> +				  &cmd, sizeof(cmd));
> +	if (ret < 0) /* non fatal */
> +		pr_err("%s:%d failed to get SCB version\n",
> +		       __func__, __LINE__);
> +	else
> +		pr_err("MB86S7x SCB version 0x%x:0x%x\n",
> +		       cmd.version, cmd.config_version);
> +
> +	ret = mcpm_platform_register(&mb86s7x_pm_power_ops);
> +	if (!ret)
> +		ret = mcpm_sync_init(mb86s7x_pm_power_up_setup);
> +	if (!ret)
> +		ret = mcpm_loopback(mb86s7x_cache_off); /* turn on the CCI */
> +	if (!ret)
> +		mcpm_smp_set_ops();
> +
> +	return ret;
> +}
> +early_initcall(mb86s7x_mcpm_init);
> diff --git a/arch/arm/mach-mb86s7x/smc.S b/arch/arm/mach-mb86s7x/smc.S
> new file mode 100644
> index 0000000..3ffe4f7
> --- /dev/null
> +++ b/arch/arm/mach-mb86s7x/smc.S
> @@ -0,0 +1,27 @@
> +/*
> + * SMC command interface to set secondary entry point
> + * Copyright: (C) 2013-2015 Fujitsu Semiconductor Limited
> + * Copyright: (C) 2015 Linaro Ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/linkage.h>
> +
> +.arch_extension sec
> +
> +/* void mb86s7x_cpu_entry(unsigned long secondary_entry); */
> +ENTRY(mb86s7x_cpu_entry)
> +	stmfd   sp!, {r1-r11, lr}
> +	mov r1, r0
> +	ldr r0, =1
> +	mrc p15, 0, r3, c1, c0, 0
> +	mov r4, r3
> +	and r3, #0xbfffffff
> +	mcr p15, 0, r3, c1, c0, 0
> +	smc #0
> +	mcr p15, 0, r4, c1, c0, 0
> +	ldmfd   sp!, {r1-r11, pc}
> +ENDPROC(mb86s7x_cpu_entry)
> diff --git a/drivers/soc/mb86s7x/scb_mhu.c b/drivers/soc/mb86s7x/scb_mhu.c
> index 08a3c88..a86ed0a 100644
> --- a/drivers/soc/mb86s7x/scb_mhu.c
> +++ b/drivers/soc/mb86s7x/scb_mhu.c
> @@ -89,6 +89,20 @@ static struct mhu_xfer {
>  	struct list_head node;
>  } *ax; /* stages of xfer */
>  
> +#define WFI_COLOR_OFFSET	0x3f00
> +
> +void mb86s7x_set_wficolor(unsigned clstr, unsigned cpu, unsigned clr)
> +{
> +	u8 val;
> +
> +	val = readb_relaxed(mb86s7x_shm_base
> +			    + WFI_COLOR_OFFSET + clstr * 2 + cpu);
> +	val &= ~AT_WFI_COLOR_MASK;
> +	val |= clr;
> +	writeb_relaxed(val, mb86s7x_shm_base
> +		       + WFI_COLOR_OFFSET + clstr * 2 + cpu);
> +}
> +
>  static int mhu_alloc_xfers(int n, struct list_head *list)
>  {
>  	struct mhu_xfer *x = kcalloc(n, sizeof(struct mhu_xfer), GFP_ATOMIC);
> diff --git a/include/soc/mb86s7x/scb_mhu.h b/include/soc/mb86s7x/scb_mhu.h
> index 334fa9f..f792950 100644
> --- a/include/soc/mb86s7x/scb_mhu.h
> +++ b/include/soc/mb86s7x/scb_mhu.h
> @@ -87,6 +87,14 @@ enum {
>  #define CMD_POWERDOMAIN_SET_REP		ENC_REP(CMD_POWERDOMAIN_SET_REQ)
>  #define CMD_STG_BLOCK_ERASE_REP		ENC_REP(CMD_STG_BLOCK_ERASE_REQ)
>  
> +#define AT_WFI_DO_NOTHING	0x0
> +#define AT_WFI_DO_SUSPEND	0x1
> +#define AT_WFI_DO_POWEROFF	0x2
> +#define AT_WFI_COLOR_MASK	0x3
> +
> +void mb86s7x_set_wficolor(unsigned clstr, unsigned cpu, unsigned clr);
> +void mb86s7x_cpu_entry(unsigned long secondary_entry);
> +
>  /* Helper functions to talk to remote */
>  int mb86s7x_send_packet(int cmd, void *buf, int len);
>  
> -- 
> 1.9.0
> 
> 

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v3 5/8] gpio: Add Fujitsu MB86S7x GPIO driver
  2015-01-09 11:33   ` Vincent Yang
@ 2015-01-11 22:40     ` Linus Walleij
  -1 siblings, 0 replies; 39+ messages in thread
From: Linus Walleij @ 2015-01-11 22:40 UTC (permalink / raw)
  To: Vincent Yang, Kamlakant Patel
  Cc: devicetree, linux-gpio, linux-arm-kernel, Arnd Bergmann,
	Olof Johansson, Rob Herring, Paweł Moll, Mark Rutland,
	ijc+devicetree, Kumar Gala, Grant Likely, Alexandre Courbot,
	Andy Green, Patch Tracking, Jaswinder Singh, Vincent Yang,
	Tetsuya Nuriya

On Fri, Jan 9, 2015 at 12:33 PM, Vincent Yang
<vincent.yang.fujitsu@gmail.com> wrote:

> From: Jassi Brar <jaswinder.singh@linaro.org>
>
> Driver for Fujitsu MB86S7x SoCs that have a memory mapped GPIO controller.
>
> Signed-off-by: Andy Green <andy.green@linaro.org>
> Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
> Signed-off-by: Vincent Yang <Vincent.Yang@tw.fujitsu.com>
> Signed-off-by: Tetsuya Nuriya <nuriya.tetsuya@jp.fujitsu.com>

(....)
> +++ b/Documentation/devicetree/bindings/gpio/fujitsu,mb86s70-gpio.txt

Binding looks good to me.

> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> index 633ec21..699e629 100644
> --- a/drivers/gpio/Kconfig
> +++ b/drivers/gpio/Kconfig
> @@ -197,6 +197,12 @@ config GPIO_F7188X
>           To compile this driver as a module, choose M here: the module will
>           be called f7188x-gpio.
>
> +config GPIO_MB86S7X
> +       bool "GPIO support for Fujitsu MB86S7x Platforms"
> +       depends on ARCH_MB86S7X

|| COMPILE_TEST? So we can test it on a x86_64 compile?

> diff --git a/drivers/gpio/gpio-mb86s7x.c b/drivers/gpio/gpio-mb86s7x.c
> new file mode 100644
> index 0000000..c912585
> --- /dev/null
> +++ b/drivers/gpio/gpio-mb86s7x.c
> @@ -0,0 +1,231 @@
> +/*
> + *  linux/drivers/gpio/gpio-mb86s7x.c
> + *
> + *  Copyright (C) 2015 Fujitsu Semiconductor Limited
> + *  Copyright (C) 2015 Linaro Ltd.
> + *
> + *  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, version 2 of the License.
> + *
> + *  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.
> + */
> +
> +#include <linux/io.h>
> +#include <linux/init.h>
> +#include <linux/clk.h>
> +#include <linux/gpio.h>

Nominally a modern driver should just

#include <linux/gpio/driver.h>

instead of <linux/gpio.h>

> +#include <linux/module.h>
> +#include <linux/err.h>
> +#include <linux/errno.h>
> +#include <linux/ioport.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/spinlock.h>
> +#include <linux/slab.h>
> +
> +/*
> + * Only first 8bits of a register correspond to each pin,
> + * so there are 4 registers for 32 pins.
> + */
> +#define PDR(x) (0x0 + x / 8 * 4)
> +#define DDR(x) (0x10 + x / 8 * 4)
> +#define PFR(x) (0x20 + x / 8 * 4)

Hm pins ... is this actually a pin controller hardware? Usually I
encourage the concept of "line" over "pin" to distinguish GPIO
lines from pin controller pins.

> +static int mb86s70_gpio_direction_output(struct gpio_chip *gc,
> +                                        unsigned gpio, int value)
> +{
> +       struct mb86s70_gpio_chip *gchip = chip_to_mb86s70(gc);
> +       unsigned long flags;
> +       unsigned char val;
> +
> +       spin_lock_irqsave(&gchip->lock, flags);
> +
> +       val = readl(gchip->base + PDR(gpio));
> +       if (value)
> +               val |= OFFSET(gpio);
> +       else
> +               val &= ~OFFSET(gpio);
> +       writel(val, gchip->base + PDR(gpio));
> +
> +       val = readl(gchip->base + DDR(gpio));
> +       val |= OFFSET(gpio);
> +       writel(val, gchip->base + DDR(gpio));
> +
> +       spin_unlock_irqrestore(&gchip->lock, flags);
> +
> +       return 0;
> +}

First I thought maybe this could use the generic MMIO driver
but it seems you need this double register access for setting
the direction so it won't work.

Otherwise it's sort of close ... have you looks at the option?
Kamlakant did a lot of interesting attempts to migrate some current
drivers to GPIO MMIO (generic GPIO) recently, e.g. this:
http://marc.info/?l=linux-gpio&m=141743574511640&w=2
or this:
http://marc.info/?l=linux-gpio&m=141743574211639&w=2

> +static int __init mb86s70_gpio_init(void)
> +{
> +       return platform_driver_register(&mb86s70_gpio_driver);
> +}
> +subsys_initcall(mb86s70_gpio_init);

We are trying to move away from sybsys_initcall() and rely on
deferred probe. Why do you need this here?

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v3 5/8] gpio: Add Fujitsu MB86S7x GPIO driver
@ 2015-01-11 22:40     ` Linus Walleij
  0 siblings, 0 replies; 39+ messages in thread
From: Linus Walleij @ 2015-01-11 22:40 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jan 9, 2015 at 12:33 PM, Vincent Yang
<vincent.yang.fujitsu@gmail.com> wrote:

> From: Jassi Brar <jaswinder.singh@linaro.org>
>
> Driver for Fujitsu MB86S7x SoCs that have a memory mapped GPIO controller.
>
> Signed-off-by: Andy Green <andy.green@linaro.org>
> Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
> Signed-off-by: Vincent Yang <Vincent.Yang@tw.fujitsu.com>
> Signed-off-by: Tetsuya Nuriya <nuriya.tetsuya@jp.fujitsu.com>

(....)
> +++ b/Documentation/devicetree/bindings/gpio/fujitsu,mb86s70-gpio.txt

Binding looks good to me.

> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> index 633ec21..699e629 100644
> --- a/drivers/gpio/Kconfig
> +++ b/drivers/gpio/Kconfig
> @@ -197,6 +197,12 @@ config GPIO_F7188X
>           To compile this driver as a module, choose M here: the module will
>           be called f7188x-gpio.
>
> +config GPIO_MB86S7X
> +       bool "GPIO support for Fujitsu MB86S7x Platforms"
> +       depends on ARCH_MB86S7X

|| COMPILE_TEST? So we can test it on a x86_64 compile?

> diff --git a/drivers/gpio/gpio-mb86s7x.c b/drivers/gpio/gpio-mb86s7x.c
> new file mode 100644
> index 0000000..c912585
> --- /dev/null
> +++ b/drivers/gpio/gpio-mb86s7x.c
> @@ -0,0 +1,231 @@
> +/*
> + *  linux/drivers/gpio/gpio-mb86s7x.c
> + *
> + *  Copyright (C) 2015 Fujitsu Semiconductor Limited
> + *  Copyright (C) 2015 Linaro Ltd.
> + *
> + *  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, version 2 of the License.
> + *
> + *  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.
> + */
> +
> +#include <linux/io.h>
> +#include <linux/init.h>
> +#include <linux/clk.h>
> +#include <linux/gpio.h>

Nominally a modern driver should just

#include <linux/gpio/driver.h>

instead of <linux/gpio.h>

> +#include <linux/module.h>
> +#include <linux/err.h>
> +#include <linux/errno.h>
> +#include <linux/ioport.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/spinlock.h>
> +#include <linux/slab.h>
> +
> +/*
> + * Only first 8bits of a register correspond to each pin,
> + * so there are 4 registers for 32 pins.
> + */
> +#define PDR(x) (0x0 + x / 8 * 4)
> +#define DDR(x) (0x10 + x / 8 * 4)
> +#define PFR(x) (0x20 + x / 8 * 4)

Hm pins ... is this actually a pin controller hardware? Usually I
encourage the concept of "line" over "pin" to distinguish GPIO
lines from pin controller pins.

> +static int mb86s70_gpio_direction_output(struct gpio_chip *gc,
> +                                        unsigned gpio, int value)
> +{
> +       struct mb86s70_gpio_chip *gchip = chip_to_mb86s70(gc);
> +       unsigned long flags;
> +       unsigned char val;
> +
> +       spin_lock_irqsave(&gchip->lock, flags);
> +
> +       val = readl(gchip->base + PDR(gpio));
> +       if (value)
> +               val |= OFFSET(gpio);
> +       else
> +               val &= ~OFFSET(gpio);
> +       writel(val, gchip->base + PDR(gpio));
> +
> +       val = readl(gchip->base + DDR(gpio));
> +       val |= OFFSET(gpio);
> +       writel(val, gchip->base + DDR(gpio));
> +
> +       spin_unlock_irqrestore(&gchip->lock, flags);
> +
> +       return 0;
> +}

First I thought maybe this could use the generic MMIO driver
but it seems you need this double register access for setting
the direction so it won't work.

Otherwise it's sort of close ... have you looks at the option?
Kamlakant did a lot of interesting attempts to migrate some current
drivers to GPIO MMIO (generic GPIO) recently, e.g. this:
http://marc.info/?l=linux-gpio&m=141743574511640&w=2
or this:
http://marc.info/?l=linux-gpio&m=141743574211639&w=2

> +static int __init mb86s70_gpio_init(void)
> +{
> +       return platform_driver_register(&mb86s70_gpio_driver);
> +}
> +subsys_initcall(mb86s70_gpio_init);

We are trying to move away from sybsys_initcall() and rely on
deferred probe. Why do you need this here?

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v3 5/8] gpio: Add Fujitsu MB86S7x GPIO driver
  2015-01-11 22:40     ` Linus Walleij
@ 2015-01-12  0:04       ` Linus Walleij
  -1 siblings, 0 replies; 39+ messages in thread
From: Linus Walleij @ 2015-01-12  0:04 UTC (permalink / raw)
  To: Vincent Yang, Kamlakant Patel
  Cc: devicetree, linux-gpio, linux-arm-kernel, Arnd Bergmann,
	Olof Johansson, Rob Herring, Paweł Moll, Mark Rutland,
	ijc+devicetree, Kumar Gala, Grant Likely, Alexandre Courbot,
	Andy Green, Patch Tracking, Jaswinder Singh, Vincent Yang,
	Tetsuya Nuriya

On Sun, Jan 11, 2015 at 11:40 PM, Linus Walleij
<linus.walleij@linaro.org> wrote:

> First I thought maybe this could use the generic MMIO driver
> but it seems you need this double register access for setting
> the direction so it won't work.
>
> Otherwise it's sort of close ... have you looks at the option?

Bah, sorry I saw I already asked this in the past and you explained
that the arithmetic is not simple enough. Sorry for forgetting what
I already asked. This is over all looking very good, but waiting since
you had some pending change, then I'll merge it.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v3 5/8] gpio: Add Fujitsu MB86S7x GPIO driver
@ 2015-01-12  0:04       ` Linus Walleij
  0 siblings, 0 replies; 39+ messages in thread
From: Linus Walleij @ 2015-01-12  0:04 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Jan 11, 2015 at 11:40 PM, Linus Walleij
<linus.walleij@linaro.org> wrote:

> First I thought maybe this could use the generic MMIO driver
> but it seems you need this double register access for setting
> the direction so it won't work.
>
> Otherwise it's sort of close ... have you looks at the option?

Bah, sorry I saw I already asked this in the past and you explained
that the arithmetic is not simple enough. Sorry for forgetting what
I already asked. This is over all looking very good, but waiting since
you had some pending change, then I'll merge it.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 39+ messages in thread

end of thread, other threads:[~2015-01-12  0:04 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-09 11:19 [PATCH v3 0/8] Support for Fujitsu MB86S7X SoCs Vincent Yang
2015-01-09 11:19 ` Vincent Yang
     [not found] ` <1420802369-3840-1-git-send-email-Vincent.Yang-l16TxrwUIHTQFUHtdCDX3A@public.gmane.org>
2015-01-09 11:24   ` [PATCH v3 1/8] ARM: Add platform support " Vincent Yang
2015-01-09 11:24     ` Vincent Yang
2015-01-09 11:28   ` [PATCH v3 2/8] mailbox: arm_mhu: add driver for ARM MHU controller Vincent Yang
2015-01-09 11:28     ` Vincent Yang
     [not found]     ` <1420802889-4041-1-git-send-email-Vincent.Yang-l16TxrwUIHTQFUHtdCDX3A@public.gmane.org>
2015-01-09 12:51       ` Russell King - ARM Linux
2015-01-09 12:51         ` Russell King - ARM Linux
     [not found]         ` <20150109125102.GL12302-l+eeeJia6m9vn6HldHNs0ANdhmdF6hFW@public.gmane.org>
2015-01-09 13:19           ` Jassi Brar
2015-01-09 13:19             ` Jassi Brar
2015-01-09 15:24             ` Russell King - ARM Linux
2015-01-09 15:24               ` Russell King - ARM Linux
     [not found]               ` <20150109152402.GQ12302-l+eeeJia6m9vn6HldHNs0ANdhmdF6hFW@public.gmane.org>
2015-01-09 15:29                 ` Jassi Brar
2015-01-09 15:29                   ` Jassi Brar
2015-01-09 11:29   ` [PATCH v3 4/8] clk: Add clock driver for mb86s7x Vincent Yang
2015-01-09 11:29     ` Vincent Yang
     [not found]     ` <1420802977-4126-1-git-send-email-Vincent.Yang-l16TxrwUIHTQFUHtdCDX3A@public.gmane.org>
2015-01-09 12:39       ` Russell King - ARM Linux
2015-01-09 12:39         ` Russell King - ARM Linux
     [not found]         ` <20150109123958.GJ12302-l+eeeJia6m9vn6HldHNs0ANdhmdF6hFW@public.gmane.org>
2015-01-09 13:03           ` Jassi Brar
2015-01-09 13:03             ` Jassi Brar
2015-01-09 11:35   ` [PATCH v3 7/8] of: add Fujitsu vendor prefix Vincent Yang
2015-01-09 11:35     ` Vincent Yang
2015-01-09 11:28 ` [PATCH v3 3/8] ARM: MB86S7X: Add MCPM support Vincent Yang
2015-01-09 12:41   ` Russell King - ARM Linux
2015-01-09 13:23     ` Jassi Brar
2015-01-09 20:04   ` Nicolas Pitre
2015-01-09 11:33 ` [PATCH v3 5/8] gpio: Add Fujitsu MB86S7x GPIO driver Vincent Yang
2015-01-09 11:33   ` Vincent Yang
     [not found]   ` <1420803212-4350-1-git-send-email-Vincent.Yang-l16TxrwUIHTQFUHtdCDX3A@public.gmane.org>
2015-01-09 12:52     ` Russell King - ARM Linux
2015-01-09 12:52       ` Russell King - ARM Linux
2015-01-09 13:20       ` Jassi Brar
2015-01-09 13:20         ` Jassi Brar
2015-01-11 22:40   ` Linus Walleij
2015-01-11 22:40     ` Linus Walleij
2015-01-12  0:04     ` Linus Walleij
2015-01-12  0:04       ` Linus Walleij
2015-01-09 11:34 ` [PATCH v3 6/8] dt: mb86s7x: add dt files for MB86S7x evbs Vincent Yang
2015-01-09 11:34   ` Vincent Yang
2015-01-09 11:36 ` [PATCH v3 8/8] ARM: MB86S7x: Add configs Vincent Yang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.