All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/22] firmware: ARM System Control and Management Interface(SCMI) support
@ 2017-09-28 13:11 ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

Hi all,

Let me begin admitting that we are introducing yet another protocol to
achieve same things as many existing protocols like ARM SCPI, TI SCI,
QCOM RPM, Nvidia Tegra BPMP, and so on.

All I can say is that this new ARM System Control and Management
Interface(SCMI) is more flexible and easily extensible than any of the
existing ones. Many vendors were involved in the making of this formal
specification and is now officially published[1].

There is a strong trend in the industry to provide micro-controllers in
systems to abstract various power, or other system management tasks.
These controllers usually have similar interfaces, both in terms of the
functions that are provided by them, and in terms of how requests are
communicated to them.

This specification is to standardise and avoid (any further)
fragmentation in the design of such interface by various vendors.

This patch set is intended to get feedback on the design and structure
of the code. This is not complete and not fully tested due to
non-availability of firmware with full feature set at this time.

It currently doesn't support notification, asynchronous/delayed response,
perf/power statistics region and sensor register region to name a few.
I have borrowed some of the ideas of message allocation/management from
TI SCI.


Changes:

v2[4]->v3:
	- Addressed various comments recieved so far(clock, hwmon and
	  cpufreq drivers along with scmi drivers)
	- Hwmon driver now uses core layer to create and manage sysfs
	  attributes
	- Added a shim layer to abstract the mailbox interface to support
	  any custom adaptation required by the controller driver
	- Simple ARM MHU shim layer using newly added abstraction


v1[3]->v2[4]:
	- Additional support for polling based DVFS and per protocol
	  channels
	- Dependent drivers(clock, hwmon, cpufreq and power domains)
	- Various other review comments and issued found during testing
	  addressed
	- Explicit binding for method dropped as even SMC based method
	  are adviertised as mailbox

RFC[2]->v1[3]:
	- Add generic mailbox binding for shared memory(Rob H)
	- Dropped compatibles per protocol(Suggested by Matt S)
	- Dropped lot of unnecessary pointer casting(Arnd B)
	- Dropped packing of structures(Arnd B)
	- Few other changes/additions based initial testing with firmware
	  providing SCMI interface to OSPM

--
Regards,
Sudeep

[1] http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/index.html
[2] https://marc.info/?l=linux-kernel&m=149685193627620&w=2
[3] https://marc.info/?l=linux-arm-kernel&m=149849482623492&w=2
[4] https://marc.info/?l=devicetree&m=150185763105926&w=2


Sudeep Holla (22):
  dt-bindings: mailbox: add support for mailbox client shared memory
  dt-bindings: arm: add support for ARM System Control and Management
    Interface(SCMI) protocol
  dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
  firmware: arm_scmi: add basic driver infrastructure for SCMI
  firmware: arm_scmi: add common infrastructure and support for base
    protocol
  firmware: arm_scmi: add initial support for performance protocol
  firmware: arm_scmi: add initial support for clock protocol
  firmware: arm_scmi: add initial support for power protocol
  firmware: arm_scmi: add initial support for sensor protocol
  firmware: arm_scmi: probe and initialise all the supported protocols
  firmware: arm_scmi: add support for polling based SCMI transfers
  firmware: arm_scmi: add option for polling based performance domain
    operations
  firmware: arm_scmi: refactor in preparation to support per-protocol
    channels
  firmware: arm_scmi: add per-protocol channels support using idr
    objects
  firmware: arm_scmi: abstract mailbox interface
  firmware: arm_scmi: add arm_mhu specific mailbox interface
  firmware: arm_scmi: add device power domain support using genpd
  clk: add support for clocks provided by SCMI
  hwmon: (core) Add hwmon_max to hwmon_sensor_types enumeration
  hwmon: add support for sensors exported via ARM SCMI
  cpufreq: add support for CPU DVFS based on SCMI message protocol
  cpufreq: scmi: add support for fast frequency switching

 .../devicetree/bindings/arm/arm,mhu-scmi.txt       |  19 +
 Documentation/devicetree/bindings/arm/arm,scmi.txt | 171 ++++
 .../devicetree/bindings/mailbox/mailbox.txt        |  28 +
 MAINTAINERS                                        |  11 +-
 drivers/clk/Kconfig                                |  10 +
 drivers/clk/Makefile                               |   1 +
 drivers/clk/clk-scmi.c                             | 210 +++++
 drivers/cpufreq/Kconfig.arm                        |  11 +
 drivers/cpufreq/Makefile                           |   1 +
 drivers/cpufreq/scmi-cpufreq.c                     | 287 +++++++
 drivers/firmware/Kconfig                           |  34 +
 drivers/firmware/Makefile                          |   1 +
 drivers/firmware/arm_scmi/Makefile                 |   4 +
 drivers/firmware/arm_scmi/arm_mhu_if.c             | 106 +++
 drivers/firmware/arm_scmi/base.c                   | 293 +++++++
 drivers/firmware/arm_scmi/clock.c                  | 339 ++++++++
 drivers/firmware/arm_scmi/common.h                 | 127 +++
 drivers/firmware/arm_scmi/driver.c                 | 956 +++++++++++++++++++++
 drivers/firmware/arm_scmi/mbox_if.c                |  80 ++
 drivers/firmware/arm_scmi/mbox_if.h                |  71 ++
 drivers/firmware/arm_scmi/perf.c                   | 514 +++++++++++
 drivers/firmware/arm_scmi/power.c                  | 242 ++++++
 drivers/firmware/arm_scmi/scmi_pm_domain.c         | 134 +++
 drivers/firmware/arm_scmi/sensors.c                | 287 +++++++
 drivers/hwmon/Kconfig                              |  12 +
 drivers/hwmon/Makefile                             |   1 +
 drivers/hwmon/scmi-hwmon.c                         | 235 +++++
 include/linux/hwmon.h                              |   1 +
 include/linux/scmi_protocol.h                      | 216 +++++
 29 files changed, 4397 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
 create mode 100644 Documentation/devicetree/bindings/arm/arm,scmi.txt
 create mode 100644 drivers/clk/clk-scmi.c
 create mode 100644 drivers/cpufreq/scmi-cpufreq.c
 create mode 100644 drivers/firmware/arm_scmi/Makefile
 create mode 100644 drivers/firmware/arm_scmi/arm_mhu_if.c
 create mode 100644 drivers/firmware/arm_scmi/base.c
 create mode 100644 drivers/firmware/arm_scmi/clock.c
 create mode 100644 drivers/firmware/arm_scmi/common.h
 create mode 100644 drivers/firmware/arm_scmi/driver.c
 create mode 100644 drivers/firmware/arm_scmi/mbox_if.c
 create mode 100644 drivers/firmware/arm_scmi/mbox_if.h
 create mode 100644 drivers/firmware/arm_scmi/perf.c
 create mode 100644 drivers/firmware/arm_scmi/power.c
 create mode 100644 drivers/firmware/arm_scmi/scmi_pm_domain.c
 create mode 100644 drivers/firmware/arm_scmi/sensors.c
 create mode 100644 drivers/hwmon/scmi-hwmon.c
 create mode 100644 include/linux/scmi_protocol.h

-- 
2.7.4

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

* [PATCH v3 00/22] firmware: ARM System Control and Management Interface(SCMI) support
@ 2017-09-28 13:11 ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

Hi all,

Let me begin admitting that we are introducing yet another protocol to
achieve same things as many existing protocols like ARM SCPI, TI SCI,
QCOM RPM, Nvidia Tegra BPMP, and so on.

All I can say is that this new ARM System Control and Management
Interface(SCMI) is more flexible and easily extensible than any of the
existing ones. Many vendors were involved in the making of this formal
specification and is now officially published[1].

There is a strong trend in the industry to provide micro-controllers in
systems to abstract various power, or other system management tasks.
These controllers usually have similar interfaces, both in terms of the
functions that are provided by them, and in terms of how requests are
communicated to them.

This specification is to standardise and avoid (any further)
fragmentation in the design of such interface by various vendors.

This patch set is intended to get feedback on the design and structure
of the code. This is not complete and not fully tested due to
non-availability of firmware with full feature set at this time.

It currently doesn't support notification, asynchronous/delayed response,
perf/power statistics region and sensor register region to name a few.
I have borrowed some of the ideas of message allocation/management from
TI SCI.


Changes:

v2[4]->v3:
	- Addressed various comments recieved so far(clock, hwmon and
	  cpufreq drivers along with scmi drivers)
	- Hwmon driver now uses core layer to create and manage sysfs
	  attributes
	- Added a shim layer to abstract the mailbox interface to support
	  any custom adaptation required by the controller driver
	- Simple ARM MHU shim layer using newly added abstraction


v1[3]->v2[4]:
	- Additional support for polling based DVFS and per protocol
	  channels
	- Dependent drivers(clock, hwmon, cpufreq and power domains)
	- Various other review comments and issued found during testing
	  addressed
	- Explicit binding for method dropped as even SMC based method
	  are adviertised as mailbox

RFC[2]->v1[3]:
	- Add generic mailbox binding for shared memory(Rob H)
	- Dropped compatibles per protocol(Suggested by Matt S)
	- Dropped lot of unnecessary pointer casting(Arnd B)
	- Dropped packing of structures(Arnd B)
	- Few other changes/additions based initial testing with firmware
	  providing SCMI interface to OSPM

--
Regards,
Sudeep

[1] http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/index.html
[2] https://marc.info/?l=linux-kernel&m=149685193627620&w=2
[3] https://marc.info/?l=linux-arm-kernel&m=149849482623492&w=2
[4] https://marc.info/?l=devicetree&m=150185763105926&w=2


Sudeep Holla (22):
  dt-bindings: mailbox: add support for mailbox client shared memory
  dt-bindings: arm: add support for ARM System Control and Management
    Interface(SCMI) protocol
  dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
  firmware: arm_scmi: add basic driver infrastructure for SCMI
  firmware: arm_scmi: add common infrastructure and support for base
    protocol
  firmware: arm_scmi: add initial support for performance protocol
  firmware: arm_scmi: add initial support for clock protocol
  firmware: arm_scmi: add initial support for power protocol
  firmware: arm_scmi: add initial support for sensor protocol
  firmware: arm_scmi: probe and initialise all the supported protocols
  firmware: arm_scmi: add support for polling based SCMI transfers
  firmware: arm_scmi: add option for polling based performance domain
    operations
  firmware: arm_scmi: refactor in preparation to support per-protocol
    channels
  firmware: arm_scmi: add per-protocol channels support using idr
    objects
  firmware: arm_scmi: abstract mailbox interface
  firmware: arm_scmi: add arm_mhu specific mailbox interface
  firmware: arm_scmi: add device power domain support using genpd
  clk: add support for clocks provided by SCMI
  hwmon: (core) Add hwmon_max to hwmon_sensor_types enumeration
  hwmon: add support for sensors exported via ARM SCMI
  cpufreq: add support for CPU DVFS based on SCMI message protocol
  cpufreq: scmi: add support for fast frequency switching

 .../devicetree/bindings/arm/arm,mhu-scmi.txt       |  19 +
 Documentation/devicetree/bindings/arm/arm,scmi.txt | 171 ++++
 .../devicetree/bindings/mailbox/mailbox.txt        |  28 +
 MAINTAINERS                                        |  11 +-
 drivers/clk/Kconfig                                |  10 +
 drivers/clk/Makefile                               |   1 +
 drivers/clk/clk-scmi.c                             | 210 +++++
 drivers/cpufreq/Kconfig.arm                        |  11 +
 drivers/cpufreq/Makefile                           |   1 +
 drivers/cpufreq/scmi-cpufreq.c                     | 287 +++++++
 drivers/firmware/Kconfig                           |  34 +
 drivers/firmware/Makefile                          |   1 +
 drivers/firmware/arm_scmi/Makefile                 |   4 +
 drivers/firmware/arm_scmi/arm_mhu_if.c             | 106 +++
 drivers/firmware/arm_scmi/base.c                   | 293 +++++++
 drivers/firmware/arm_scmi/clock.c                  | 339 ++++++++
 drivers/firmware/arm_scmi/common.h                 | 127 +++
 drivers/firmware/arm_scmi/driver.c                 | 956 +++++++++++++++++++++
 drivers/firmware/arm_scmi/mbox_if.c                |  80 ++
 drivers/firmware/arm_scmi/mbox_if.h                |  71 ++
 drivers/firmware/arm_scmi/perf.c                   | 514 +++++++++++
 drivers/firmware/arm_scmi/power.c                  | 242 ++++++
 drivers/firmware/arm_scmi/scmi_pm_domain.c         | 134 +++
 drivers/firmware/arm_scmi/sensors.c                | 287 +++++++
 drivers/hwmon/Kconfig                              |  12 +
 drivers/hwmon/Makefile                             |   1 +
 drivers/hwmon/scmi-hwmon.c                         | 235 +++++
 include/linux/hwmon.h                              |   1 +
 include/linux/scmi_protocol.h                      | 216 +++++
 29 files changed, 4397 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
 create mode 100644 Documentation/devicetree/bindings/arm/arm,scmi.txt
 create mode 100644 drivers/clk/clk-scmi.c
 create mode 100644 drivers/cpufreq/scmi-cpufreq.c
 create mode 100644 drivers/firmware/arm_scmi/Makefile
 create mode 100644 drivers/firmware/arm_scmi/arm_mhu_if.c
 create mode 100644 drivers/firmware/arm_scmi/base.c
 create mode 100644 drivers/firmware/arm_scmi/clock.c
 create mode 100644 drivers/firmware/arm_scmi/common.h
 create mode 100644 drivers/firmware/arm_scmi/driver.c
 create mode 100644 drivers/firmware/arm_scmi/mbox_if.c
 create mode 100644 drivers/firmware/arm_scmi/mbox_if.h
 create mode 100644 drivers/firmware/arm_scmi/perf.c
 create mode 100644 drivers/firmware/arm_scmi/power.c
 create mode 100644 drivers/firmware/arm_scmi/scmi_pm_domain.c
 create mode 100644 drivers/firmware/arm_scmi/sensors.c
 create mode 100644 drivers/hwmon/scmi-hwmon.c
 create mode 100644 include/linux/scmi_protocol.h

-- 
2.7.4

--
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] 208+ messages in thread

* [PATCH v3 00/22] firmware: ARM System Control and Management Interface(SCMI) support
@ 2017-09-28 13:11 ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

Hi all,

Let me begin admitting that we are introducing yet another protocol to
achieve same things as many existing protocols like ARM SCPI, TI SCI,
QCOM RPM, Nvidia Tegra BPMP, and so on.

All I can say is that this new ARM System Control and Management
Interface(SCMI) is more flexible and easily extensible than any of the
existing ones. Many vendors were involved in the making of this formal
specification and is now officially published[1].

There is a strong trend in the industry to provide micro-controllers in
systems to abstract various power, or other system management tasks.
These controllers usually have similar interfaces, both in terms of the
functions that are provided by them, and in terms of how requests are
communicated to them.

This specification is to standardise and avoid (any further)
fragmentation in the design of such interface by various vendors.

This patch set is intended to get feedback on the design and structure
of the code. This is not complete and not fully tested due to
non-availability of firmware with full feature set at this time.

It currently doesn't support notification, asynchronous/delayed response,
perf/power statistics region and sensor register region to name a few.
I have borrowed some of the ideas of message allocation/management from
TI SCI.


Changes:

v2[4]->v3:
	- Addressed various comments recieved so far(clock, hwmon and
	  cpufreq drivers along with scmi drivers)
	- Hwmon driver now uses core layer to create and manage sysfs
	  attributes
	- Added a shim layer to abstract the mailbox interface to support
	  any custom adaptation required by the controller driver
	- Simple ARM MHU shim layer using newly added abstraction


v1[3]->v2[4]:
	- Additional support for polling based DVFS and per protocol
	  channels
	- Dependent drivers(clock, hwmon, cpufreq and power domains)
	- Various other review comments and issued found during testing
	  addressed
	- Explicit binding for method dropped as even SMC based method
	  are adviertised as mailbox

RFC[2]->v1[3]:
	- Add generic mailbox binding for shared memory(Rob H)
	- Dropped compatibles per protocol(Suggested by Matt S)
	- Dropped lot of unnecessary pointer casting(Arnd B)
	- Dropped packing of structures(Arnd B)
	- Few other changes/additions based initial testing with firmware
	  providing SCMI interface to OSPM

--
Regards,
Sudeep

[1] http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/index.html
[2] https://marc.info/?l=linux-kernel&m=149685193627620&w=2
[3] https://marc.info/?l=linux-arm-kernel&m=149849482623492&w=2
[4] https://marc.info/?l=devicetree&m=150185763105926&w=2


Sudeep Holla (22):
  dt-bindings: mailbox: add support for mailbox client shared memory
  dt-bindings: arm: add support for ARM System Control and Management
    Interface(SCMI) protocol
  dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
  firmware: arm_scmi: add basic driver infrastructure for SCMI
  firmware: arm_scmi: add common infrastructure and support for base
    protocol
  firmware: arm_scmi: add initial support for performance protocol
  firmware: arm_scmi: add initial support for clock protocol
  firmware: arm_scmi: add initial support for power protocol
  firmware: arm_scmi: add initial support for sensor protocol
  firmware: arm_scmi: probe and initialise all the supported protocols
  firmware: arm_scmi: add support for polling based SCMI transfers
  firmware: arm_scmi: add option for polling based performance domain
    operations
  firmware: arm_scmi: refactor in preparation to support per-protocol
    channels
  firmware: arm_scmi: add per-protocol channels support using idr
    objects
  firmware: arm_scmi: abstract mailbox interface
  firmware: arm_scmi: add arm_mhu specific mailbox interface
  firmware: arm_scmi: add device power domain support using genpd
  clk: add support for clocks provided by SCMI
  hwmon: (core) Add hwmon_max to hwmon_sensor_types enumeration
  hwmon: add support for sensors exported via ARM SCMI
  cpufreq: add support for CPU DVFS based on SCMI message protocol
  cpufreq: scmi: add support for fast frequency switching

 .../devicetree/bindings/arm/arm,mhu-scmi.txt       |  19 +
 Documentation/devicetree/bindings/arm/arm,scmi.txt | 171 ++++
 .../devicetree/bindings/mailbox/mailbox.txt        |  28 +
 MAINTAINERS                                        |  11 +-
 drivers/clk/Kconfig                                |  10 +
 drivers/clk/Makefile                               |   1 +
 drivers/clk/clk-scmi.c                             | 210 +++++
 drivers/cpufreq/Kconfig.arm                        |  11 +
 drivers/cpufreq/Makefile                           |   1 +
 drivers/cpufreq/scmi-cpufreq.c                     | 287 +++++++
 drivers/firmware/Kconfig                           |  34 +
 drivers/firmware/Makefile                          |   1 +
 drivers/firmware/arm_scmi/Makefile                 |   4 +
 drivers/firmware/arm_scmi/arm_mhu_if.c             | 106 +++
 drivers/firmware/arm_scmi/base.c                   | 293 +++++++
 drivers/firmware/arm_scmi/clock.c                  | 339 ++++++++
 drivers/firmware/arm_scmi/common.h                 | 127 +++
 drivers/firmware/arm_scmi/driver.c                 | 956 +++++++++++++++++++++
 drivers/firmware/arm_scmi/mbox_if.c                |  80 ++
 drivers/firmware/arm_scmi/mbox_if.h                |  71 ++
 drivers/firmware/arm_scmi/perf.c                   | 514 +++++++++++
 drivers/firmware/arm_scmi/power.c                  | 242 ++++++
 drivers/firmware/arm_scmi/scmi_pm_domain.c         | 134 +++
 drivers/firmware/arm_scmi/sensors.c                | 287 +++++++
 drivers/hwmon/Kconfig                              |  12 +
 drivers/hwmon/Makefile                             |   1 +
 drivers/hwmon/scmi-hwmon.c                         | 235 +++++
 include/linux/hwmon.h                              |   1 +
 include/linux/scmi_protocol.h                      | 216 +++++
 29 files changed, 4397 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
 create mode 100644 Documentation/devicetree/bindings/arm/arm,scmi.txt
 create mode 100644 drivers/clk/clk-scmi.c
 create mode 100644 drivers/cpufreq/scmi-cpufreq.c
 create mode 100644 drivers/firmware/arm_scmi/Makefile
 create mode 100644 drivers/firmware/arm_scmi/arm_mhu_if.c
 create mode 100644 drivers/firmware/arm_scmi/base.c
 create mode 100644 drivers/firmware/arm_scmi/clock.c
 create mode 100644 drivers/firmware/arm_scmi/common.h
 create mode 100644 drivers/firmware/arm_scmi/driver.c
 create mode 100644 drivers/firmware/arm_scmi/mbox_if.c
 create mode 100644 drivers/firmware/arm_scmi/mbox_if.h
 create mode 100644 drivers/firmware/arm_scmi/perf.c
 create mode 100644 drivers/firmware/arm_scmi/power.c
 create mode 100644 drivers/firmware/arm_scmi/scmi_pm_domain.c
 create mode 100644 drivers/firmware/arm_scmi/sensors.c
 create mode 100644 drivers/hwmon/scmi-hwmon.c
 create mode 100644 include/linux/scmi_protocol.h

-- 
2.7.4

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

* [PATCH v3 01/22] dt-bindings: mailbox: add support for mailbox client shared memory
  2017-09-28 13:11 ` Sudeep Holla
@ 2017-09-28 13:11   ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Rob Herring, Mark Rutland

Many users of the mailbox controllers depend on the shared memory
between the two end points to exchange the main data while using simple
doorbell mechanism to alert the end points of the presence of a message.

This patch defines device tree bindings to represent such shared memory
in a generic way.

Cc: Rob Herring <robh+dt@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Acked-by: Rob Herring <robh+dt@kernel.org>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 .../devicetree/bindings/mailbox/mailbox.txt        | 28 ++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/Documentation/devicetree/bindings/mailbox/mailbox.txt b/Documentation/devicetree/bindings/mailbox/mailbox.txt
index be05b9746c69..af8ecee2ac68 100644
--- a/Documentation/devicetree/bindings/mailbox/mailbox.txt
+++ b/Documentation/devicetree/bindings/mailbox/mailbox.txt
@@ -23,6 +23,11 @@ assign appropriate mailbox channel to client drivers.
 
 Optional property:
 - mbox-names: List of identifier strings for each mailbox channel.
+- shmem : List of phandle pointing to the shared memory(SHM) area between the
+	  users of these mailboxes for IPC, one for each mailbox. This shared
+	  memory can be part of any memory reserved for the purpose of this
+	  communication between the mailbox client and the remote.
+
 
 Example:
 	pwr_cntrl: power {
@@ -30,3 +35,26 @@ assign appropriate mailbox channel to client drivers.
 		mbox-names = "pwr-ctrl", "rpc";
 		mboxes = <&mailbox 0 &mailbox 1>;
 	};
+
+Example with shared memory(shmem):
+
+	sram: sram@50000000 {
+		compatible = "mmio-sram";
+		reg = <0x50000000 0x10000>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x50000000 0x10000>;
+
+		cl_shmem: shmem@0 {
+			compatible = "client-shmem";
+			reg = <0x0 0x200>;
+		};
+	};
+
+	client@2e000000 {
+		...
+		mboxes = <&mailbox 0>;
+		shmem = <&cl_shmem>;
+		..
+	};
-- 
2.7.4

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

* [PATCH v3 01/22] dt-bindings: mailbox: add support for mailbox client shared memory
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

Many users of the mailbox controllers depend on the shared memory
between the two end points to exchange the main data while using simple
doorbell mechanism to alert the end points of the presence of a message.

This patch defines device tree bindings to represent such shared memory
in a generic way.

Cc: Rob Herring <robh+dt@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Acked-by: Rob Herring <robh+dt@kernel.org>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 .../devicetree/bindings/mailbox/mailbox.txt        | 28 ++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/Documentation/devicetree/bindings/mailbox/mailbox.txt b/Documentation/devicetree/bindings/mailbox/mailbox.txt
index be05b9746c69..af8ecee2ac68 100644
--- a/Documentation/devicetree/bindings/mailbox/mailbox.txt
+++ b/Documentation/devicetree/bindings/mailbox/mailbox.txt
@@ -23,6 +23,11 @@ assign appropriate mailbox channel to client drivers.
 
 Optional property:
 - mbox-names: List of identifier strings for each mailbox channel.
+- shmem : List of phandle pointing to the shared memory(SHM) area between the
+	  users of these mailboxes for IPC, one for each mailbox. This shared
+	  memory can be part of any memory reserved for the purpose of this
+	  communication between the mailbox client and the remote.
+
 
 Example:
 	pwr_cntrl: power {
@@ -30,3 +35,26 @@ assign appropriate mailbox channel to client drivers.
 		mbox-names = "pwr-ctrl", "rpc";
 		mboxes = <&mailbox 0 &mailbox 1>;
 	};
+
+Example with shared memory(shmem):
+
+	sram: sram at 50000000 {
+		compatible = "mmio-sram";
+		reg = <0x50000000 0x10000>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x50000000 0x10000>;
+
+		cl_shmem: shmem at 0 {
+			compatible = "client-shmem";
+			reg = <0x0 0x200>;
+		};
+	};
+
+	client at 2e000000 {
+		...
+		mboxes = <&mailbox 0>;
+		shmem = <&cl_shmem>;
+		..
+	};
-- 
2.7.4

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

* [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
  2017-09-28 13:11 ` Sudeep Holla
@ 2017-09-28 13:11   ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Rob Herring, Mark Rutland

This patch adds devicetree binding for System Control and Management
Interface (SCMI) Message Protocol used between the Application Cores(AP)
and the System Control Processor(SCP). The MHU peripheral provides a
mechanism for inter-processor communication between SCP's M3 processor
and AP.

SCP offers control and management of the core/cluster power states,
various power domain DVFS including the core/cluster, certain system
clocks configuration, thermal sensors and many others.

SCMI protocol is developed as better replacement to the existing SCPI
which is not flexible and easily extensible.

Cc: Rob Herring <robh+dt@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 Documentation/devicetree/bindings/arm/arm,scmi.txt | 171 +++++++++++++++++++++
 MAINTAINERS                                        |   4 +-
 2 files changed, 173 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/arm,scmi.txt

diff --git a/Documentation/devicetree/bindings/arm/arm,scmi.txt b/Documentation/devicetree/bindings/arm/arm,scmi.txt
new file mode 100644
index 000000000000..226ed2e9ac6a
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/arm,scmi.txt
@@ -0,0 +1,171 @@
+System Control and Management Interface (SCMI) Message Protocol
+----------------------------------------------------------
+
+The SCMI is intended to allow agents such as OSPM to manage various functions
+that are provided by the hardware platform it is running on, including power
+and performance functions.
+
+This binding is intended to define the interface the firmware implementing
+the SCMI as described in ARM document number ARM DUI 0922B ("ARM System Control
+and Management Interface Platform Design Document")[0] provide for OSPM in
+the device tree.
+
+Required properties:
+
+The scmi node with the following properties shall be under the /firmware/ node.
+
+- compatible : shall be "arm,scmi"
+- mboxes: List of phandle and mailbox channel specifiers. It should contain
+	  exactly one or two mailboxes, one for transmitting messages("tx")
+	  and another optional for receiving the notifications("rx") if
+	  supported.
+- mbox-names: shall be "tx" or "rx"
+- shmem : List of phandle pointing to the shared memory(SHM) area as per
+	  generic mailbox client binding.
+
+See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details
+about the generic mailbox controller and client driver bindings.
+
+The mailbox is the only permitted method of calling the SCMI firmware.
+Mailbox doorbell is used as a mechanism to alert the presence of a
+messages and/or notification.
+
+Each protocol supported shall have a sub-node with corresponding compatible
+as described in the following sections. If the platform supports dedicated
+communication channel for a particular protocol, the 3 properties namely:
+mboxes, mbox-names and shmem shall be present in the sub-node corresponding
+to that protocol.
+
+Clock/Performance bindings for the clocks/OPPs based on SCMI Message Protocol
+------------------------------------------------------------
+
+This binding uses the common clock binding[1].
+
+Required properties:
+- #clock-cells : Should be 1. Contains the Clock ID value used by SCMI commands.
+
+Power domain bindings for the power domains based on SCMI Message Protocol
+------------------------------------------------------------
+
+This binding for the SCMI power domain providers uses the generic power
+domain binding[2].
+
+Required properties:
+ - #power-domain-cells : Should be 1. Contains the device or the power
+			 domain ID value used by SCMI commands.
+
+Sensor bindings for the sensors based on SCMI Message Protocol
+--------------------------------------------------------------
+SCMI provides an API to access the various sensors on the SoC.
+
+Required properties:
+- #thermal-sensor-cells: should be set to 1. This property follows the
+			 thermal device tree bindings[3].
+
+			 Valid cell values are raw identifiers (Sensor ID)
+			 as used by the firmware. Refer to  platform details
+			 for your implementation for the IDs to use.
+
+SRAM and Shared Memory for SCMI
+-------------------------------
+
+A small area of SRAM is reserved for SCMI communication between application
+processors and SCP.
+
+The properties should follow the generic mmio-sram description found in [4]
+
+Each sub-node represents the reserved area for SCMI.
+
+Required sub-node properties:
+- reg : The base offset and size of the reserved area with the SRAM
+- compatible : should be "arm,scmi-shmem" for Non-secure SRAM based
+	       shared memory
+
+[0] http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/index.html
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/power/power_domain.txt
+[3] Documentation/devicetree/bindings/thermal/thermal.txt
+[4] Documentation/devicetree/bindings/sram/sram.txt
+
+Example:
+
+sram@50000000 {
+	compatible = "mmio-sram";
+	reg = <0x0 0x50000000 0x0 0x10000>;
+
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges = <0 0x0 0x50000000 0x10000>;
+
+	cpu_scp_lpri: scp-shmem@0 {
+		compatible = "arm,scmi-shmem";
+		reg = <0x0 0x200>;
+	};
+
+	cpu_scp_hpri: scp-shmem@200 {
+		compatible = "arm,scmi-shmem";
+		reg = <0x200 0x200>;
+	};
+};
+
+mailbox@40000000 {
+	....
+	#mbox-cells = <1>;
+	reg = <0x0 0x40000000 0x0 0x10000>;
+};
+
+firmware {
+
+	...
+
+	scmi {
+		compatible = "arm,scmi";
+		mboxes = <&mailbox 0 &mailbox 1>;
+		shmem = <&cpu_scp_lpri &cpu_scp_hpri>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		scmi_devpd: protocol@11 {
+			reg = <0x11>;
+			#power-domain-cells = <1>;
+		};
+
+		scmi_dvfs: protocol@13 {
+			reg = <0x13>;
+			#clock-cells = <1>;
+		};
+
+		scmi_clk: protocol@14 {
+			reg = <0x14>;
+			#clock-cells = <1>;
+		};
+
+		scmi_sensors0: protocol@15 {
+			reg = <0x15>;
+			#thermal-sensor-cells = <1>;
+		};
+	};
+};
+
+cpu@0 {
+	...
+	reg = <0 0>;
+	clocks = <&scmi_dvfs 0>;
+};
+
+hdlcd@7ff60000 {
+	...
+	reg = <0 0x7ff60000 0 0x1000>;
+	clocks = <&scmi_clk 4>;
+	power-domains = <&scmi_devpd 1>;
+};
+
+thermal-zones {
+	soc_thermal {
+		polling-delay-passive = <100>;
+		polling-delay = <1000>;
+					/* sensor ID */
+		thermal-sensors = <&scmi_sensors0 3>;
+		...
+	};
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index 6671f375f7fc..f4b5f3967725 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12936,11 +12936,11 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git
 S:	Supported
 F:	drivers/mfd/syscon.c
 
-SYSTEM CONTROL & POWER INTERFACE (SCPI) Message Protocol drivers
+SYSTEM CONTROL & POWER/MANAGEMENT INTERFACE (SCPI/SCMI) Message Protocol drivers
 M:	Sudeep Holla <sudeep.holla@arm.com>
 L:	linux-arm-kernel@lists.infradead.org
 S:	Maintained
-F:	Documentation/devicetree/bindings/arm/arm,scpi.txt
+F:	Documentation/devicetree/bindings/arm/arm,sc[mp]i.txt
 F:	drivers/clk/clk-scpi.c
 F:	drivers/cpufreq/scpi-cpufreq.c
 F:	drivers/firmware/arm_scpi.c
-- 
2.7.4

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

* [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds devicetree binding for System Control and Management
Interface (SCMI) Message Protocol used between the Application Cores(AP)
and the System Control Processor(SCP). The MHU peripheral provides a
mechanism for inter-processor communication between SCP's M3 processor
and AP.

SCP offers control and management of the core/cluster power states,
various power domain DVFS including the core/cluster, certain system
clocks configuration, thermal sensors and many others.

SCMI protocol is developed as better replacement to the existing SCPI
which is not flexible and easily extensible.

Cc: Rob Herring <robh+dt@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 Documentation/devicetree/bindings/arm/arm,scmi.txt | 171 +++++++++++++++++++++
 MAINTAINERS                                        |   4 +-
 2 files changed, 173 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/arm,scmi.txt

diff --git a/Documentation/devicetree/bindings/arm/arm,scmi.txt b/Documentation/devicetree/bindings/arm/arm,scmi.txt
new file mode 100644
index 000000000000..226ed2e9ac6a
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/arm,scmi.txt
@@ -0,0 +1,171 @@
+System Control and Management Interface (SCMI) Message Protocol
+----------------------------------------------------------
+
+The SCMI is intended to allow agents such as OSPM to manage various functions
+that are provided by the hardware platform it is running on, including power
+and performance functions.
+
+This binding is intended to define the interface the firmware implementing
+the SCMI as described in ARM document number ARM DUI 0922B ("ARM System Control
+and Management Interface Platform Design Document")[0] provide for OSPM in
+the device tree.
+
+Required properties:
+
+The scmi node with the following properties shall be under the /firmware/ node.
+
+- compatible : shall be "arm,scmi"
+- mboxes: List of phandle and mailbox channel specifiers. It should contain
+	  exactly one or two mailboxes, one for transmitting messages("tx")
+	  and another optional for receiving the notifications("rx") if
+	  supported.
+- mbox-names: shall be "tx" or "rx"
+- shmem : List of phandle pointing to the shared memory(SHM) area as per
+	  generic mailbox client binding.
+
+See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details
+about the generic mailbox controller and client driver bindings.
+
+The mailbox is the only permitted method of calling the SCMI firmware.
+Mailbox doorbell is used as a mechanism to alert the presence of a
+messages and/or notification.
+
+Each protocol supported shall have a sub-node with corresponding compatible
+as described in the following sections. If the platform supports dedicated
+communication channel for a particular protocol, the 3 properties namely:
+mboxes, mbox-names and shmem shall be present in the sub-node corresponding
+to that protocol.
+
+Clock/Performance bindings for the clocks/OPPs based on SCMI Message Protocol
+------------------------------------------------------------
+
+This binding uses the common clock binding[1].
+
+Required properties:
+- #clock-cells : Should be 1. Contains the Clock ID value used by SCMI commands.
+
+Power domain bindings for the power domains based on SCMI Message Protocol
+------------------------------------------------------------
+
+This binding for the SCMI power domain providers uses the generic power
+domain binding[2].
+
+Required properties:
+ - #power-domain-cells : Should be 1. Contains the device or the power
+			 domain ID value used by SCMI commands.
+
+Sensor bindings for the sensors based on SCMI Message Protocol
+--------------------------------------------------------------
+SCMI provides an API to access the various sensors on the SoC.
+
+Required properties:
+- #thermal-sensor-cells: should be set to 1. This property follows the
+			 thermal device tree bindings[3].
+
+			 Valid cell values are raw identifiers (Sensor ID)
+			 as used by the firmware. Refer to  platform details
+			 for your implementation for the IDs to use.
+
+SRAM and Shared Memory for SCMI
+-------------------------------
+
+A small area of SRAM is reserved for SCMI communication between application
+processors and SCP.
+
+The properties should follow the generic mmio-sram description found in [4]
+
+Each sub-node represents the reserved area for SCMI.
+
+Required sub-node properties:
+- reg : The base offset and size of the reserved area with the SRAM
+- compatible : should be "arm,scmi-shmem" for Non-secure SRAM based
+	       shared memory
+
+[0] http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/index.html
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/power/power_domain.txt
+[3] Documentation/devicetree/bindings/thermal/thermal.txt
+[4] Documentation/devicetree/bindings/sram/sram.txt
+
+Example:
+
+sram at 50000000 {
+	compatible = "mmio-sram";
+	reg = <0x0 0x50000000 0x0 0x10000>;
+
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges = <0 0x0 0x50000000 0x10000>;
+
+	cpu_scp_lpri: scp-shmem at 0 {
+		compatible = "arm,scmi-shmem";
+		reg = <0x0 0x200>;
+	};
+
+	cpu_scp_hpri: scp-shmem at 200 {
+		compatible = "arm,scmi-shmem";
+		reg = <0x200 0x200>;
+	};
+};
+
+mailbox at 40000000 {
+	....
+	#mbox-cells = <1>;
+	reg = <0x0 0x40000000 0x0 0x10000>;
+};
+
+firmware {
+
+	...
+
+	scmi {
+		compatible = "arm,scmi";
+		mboxes = <&mailbox 0 &mailbox 1>;
+		shmem = <&cpu_scp_lpri &cpu_scp_hpri>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		scmi_devpd: protocol at 11 {
+			reg = <0x11>;
+			#power-domain-cells = <1>;
+		};
+
+		scmi_dvfs: protocol at 13 {
+			reg = <0x13>;
+			#clock-cells = <1>;
+		};
+
+		scmi_clk: protocol at 14 {
+			reg = <0x14>;
+			#clock-cells = <1>;
+		};
+
+		scmi_sensors0: protocol at 15 {
+			reg = <0x15>;
+			#thermal-sensor-cells = <1>;
+		};
+	};
+};
+
+cpu at 0 {
+	...
+	reg = <0 0>;
+	clocks = <&scmi_dvfs 0>;
+};
+
+hdlcd at 7ff60000 {
+	...
+	reg = <0 0x7ff60000 0 0x1000>;
+	clocks = <&scmi_clk 4>;
+	power-domains = <&scmi_devpd 1>;
+};
+
+thermal-zones {
+	soc_thermal {
+		polling-delay-passive = <100>;
+		polling-delay = <1000>;
+					/* sensor ID */
+		thermal-sensors = <&scmi_sensors0 3>;
+		...
+	};
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index 6671f375f7fc..f4b5f3967725 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12936,11 +12936,11 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git
 S:	Supported
 F:	drivers/mfd/syscon.c
 
-SYSTEM CONTROL & POWER INTERFACE (SCPI) Message Protocol drivers
+SYSTEM CONTROL & POWER/MANAGEMENT INTERFACE (SCPI/SCMI) Message Protocol drivers
 M:	Sudeep Holla <sudeep.holla@arm.com>
 L:	linux-arm-kernel at lists.infradead.org
 S:	Maintained
-F:	Documentation/devicetree/bindings/arm/arm,scpi.txt
+F:	Documentation/devicetree/bindings/arm/arm,sc[mp]i.txt
 F:	drivers/clk/clk-scpi.c
 F:	drivers/cpufreq/scpi-cpufreq.c
 F:	drivers/firmware/arm_scpi.c
-- 
2.7.4

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

* [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Rob Herring, Mark Rutland

This patch adds ARM MHU specific mailbox client bindings to support
SCMI. Since SCMI specification just requires doorbell mechanism from
mailbox controllers, we add mailbox data to specify the doorbell bit(s).

Cc: Rob Herring <robh+dt@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 .../devicetree/bindings/arm/arm,mhu-scmi.txt          | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt

diff --git a/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
new file mode 100644
index 000000000000..8c106f1cdeb8
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
@@ -0,0 +1,19 @@
+ARM MHU mailbox client bindings for SCMI Message Protocol
+----------------------------------------------------------
+
+This binding is intended to define the ARM MHU specific extensions to
+the generic SCMI bindings[2].
+
+Required properties:
+
+The scmi node with the following properties shall be under the /firmware/ node.
+
+- compatible : shall be "arm,scmi" and "arm,mhu-scmi"
+- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
+	      data as expected by the mailbox controller
+
+See [1] for details on all other required/optional properties of the generic
+mailbox controller and [2] for generic SCMI bindings.
+
+[1] Documentation/devicetree/bindings/mailbox/mailbox.txt
+[2] Documentation/devicetree/bindings/arm/arm,scmi.txt
-- 
2.7.4

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

* [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Rob Herring, Mark Rutland

This patch adds ARM MHU specific mailbox client bindings to support
SCMI. Since SCMI specification just requires doorbell mechanism from
mailbox controllers, we add mailbox data to specify the doorbell bit(s).

Cc: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Cc: Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>
Signed-off-by: Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org>
---
 .../devicetree/bindings/arm/arm,mhu-scmi.txt          | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt

diff --git a/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
new file mode 100644
index 000000000000..8c106f1cdeb8
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
@@ -0,0 +1,19 @@
+ARM MHU mailbox client bindings for SCMI Message Protocol
+----------------------------------------------------------
+
+This binding is intended to define the ARM MHU specific extensions to
+the generic SCMI bindings[2].
+
+Required properties:
+
+The scmi node with the following properties shall be under the /firmware/ node.
+
+- compatible : shall be "arm,scmi" and "arm,mhu-scmi"
+- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
+	      data as expected by the mailbox controller
+
+See [1] for details on all other required/optional properties of the generic
+mailbox controller and [2] for generic SCMI bindings.
+
+[1] Documentation/devicetree/bindings/mailbox/mailbox.txt
+[2] Documentation/devicetree/bindings/arm/arm,scmi.txt
-- 
2.7.4

--
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] 208+ messages in thread

* [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds ARM MHU specific mailbox client bindings to support
SCMI. Since SCMI specification just requires doorbell mechanism from
mailbox controllers, we add mailbox data to specify the doorbell bit(s).

Cc: Rob Herring <robh+dt@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 .../devicetree/bindings/arm/arm,mhu-scmi.txt          | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt

diff --git a/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
new file mode 100644
index 000000000000..8c106f1cdeb8
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
@@ -0,0 +1,19 @@
+ARM MHU mailbox client bindings for SCMI Message Protocol
+----------------------------------------------------------
+
+This binding is intended to define the ARM MHU specific extensions to
+the generic SCMI bindings[2].
+
+Required properties:
+
+The scmi node with the following properties shall be under the /firmware/ node.
+
+- compatible : shall be "arm,scmi" and "arm,mhu-scmi"
+- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
+	      data as expected by the mailbox controller
+
+See [1] for details on all other required/optional properties of the generic
+mailbox controller and [2] for generic SCMI bindings.
+
+[1] Documentation/devicetree/bindings/mailbox/mailbox.txt
+[2] Documentation/devicetree/bindings/arm/arm,scmi.txt
-- 
2.7.4

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

* [PATCH v3 04/22] firmware: arm_scmi: add basic driver infrastructure for SCMI
  2017-09-28 13:11 ` Sudeep Holla
@ 2017-09-28 13:11   ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

The SCMI is intended to allow OSPM to manage various functions that are
provided by the hardware platform it is running on, including power and
performance functions. SCMI provides two levels of abstraction, protocols
and transports. Protocols define individual groups of system control and
management messages. A protocol specification describes the messages
that it supports. Transports describe the method by which protocol
messages are communicated between agents and the platform.

This patch adds basic infrastructure to manage the message allocation,
initialisation, packing/unpacking and shared memory management.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 MAINTAINERS                        |   3 +-
 drivers/firmware/Kconfig           |  21 +
 drivers/firmware/Makefile          |   1 +
 drivers/firmware/arm_scmi/Makefile |   2 +
 drivers/firmware/arm_scmi/common.h |  75 ++++
 drivers/firmware/arm_scmi/driver.c | 769 +++++++++++++++++++++++++++++++++++++
 include/linux/scmi_protocol.h      |  48 +++
 7 files changed, 918 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/arm_scmi/Makefile
 create mode 100644 drivers/firmware/arm_scmi/common.h
 create mode 100644 drivers/firmware/arm_scmi/driver.c
 create mode 100644 include/linux/scmi_protocol.h

diff --git a/MAINTAINERS b/MAINTAINERS
index f4b5f3967725..23ec3471f542 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12944,7 +12944,8 @@ F:	Documentation/devicetree/bindings/arm/arm,sc[mp]i.txt
 F:	drivers/clk/clk-scpi.c
 F:	drivers/cpufreq/scpi-cpufreq.c
 F:	drivers/firmware/arm_scpi.c
-F:	include/linux/scpi_protocol.h
+F:	drivers/firmware/arm_scmi/
+F:	include/linux/sc[mp]i_protocol.h
 
 SYSTEM RESET/SHUTDOWN DRIVERS
 M:	Sebastian Reichel <sre@kernel.org>
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 6e4ed5a9c6fd..c3d1a12763ce 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -19,6 +19,27 @@ config ARM_PSCI_CHECKER
 	  on and off through hotplug, so for now torture tests and PSCI checker
 	  are mutually exclusive.
 
+config ARM_SCMI_PROTOCOL
+	tristate "ARM System Control and Management Interface (SCMI) Message Protocol"
+	depends on ARM || ARM64 || COMPILE_TEST
+	depends on MAILBOX
+	help
+	  ARM System Control and Management Interface (SCMI) protocol is a
+	  set of operating system-independent software interfaces that are
+	  used in system management. SCMI is extensible and currently provides
+	  interfaces for: Discovery and self-description of the interfaces
+	  it supports, Power domain management which is the ability to place
+	  a given device or domain into the various power-saving states that
+	  it supports, Performance management which is the ability to control
+	  the performance of a domain that is composed of compute engines
+	  such as application processors and other accelerators, Clock
+	  management which is the ability to set and inquire rates on platform
+	  managed clocks and Sensor management which is the ability to read
+	  sensor data, and be notified of sensor value.
+
+	  This protocol library provides interface for all the client drivers
+	  making use of the features offered by the SCMI.
+
 config ARM_SCPI_PROTOCOL
 	tristate "ARM System Control and Power Interface (SCPI) Message Protocol"
 	depends on ARM || ARM64 || COMPILE_TEST
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index a37f12e8d137..91d3ff62c653 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_QCOM_SCM_32)	+= qcom_scm-32.o
 CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQUIRES_SEC=1) -march=armv7-a
 obj-$(CONFIG_TI_SCI_PROTOCOL)	+= ti_sci.o
 
+obj-$(CONFIG_ARM_SCMI_PROTOCOL)	+= arm_scmi/
 obj-y				+= broadcom/
 obj-y				+= meson/
 obj-$(CONFIG_GOOGLE_FIRMWARE)	+= google/
diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
new file mode 100644
index 000000000000..58e94c95e523
--- /dev/null
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_ARM_SCMI_PROTOCOL)	= arm_scmi.o
+arm_scmi-y = driver.o
diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
new file mode 100644
index 000000000000..344b234d4e64
--- /dev/null
+++ b/drivers/firmware/arm_scmi/common.h
@@ -0,0 +1,75 @@
+/*
+ * System Control and Management Interface (SCMI) Message Protocol
+ * driver common header file containing some definitions, structures
+ * and function prototypes used in all the different SCMI protocols.
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/completion.h>
+#include <linux/scmi_protocol.h>
+#include <linux/types.h>
+
+/**
+ * struct scmi_msg_hdr - Message(Tx/Rx) header
+ *
+ * @id: The identifier of the command being sent
+ * @protocol_id: The identifier of the protocol used to send @id command
+ * @seq: The token to identify the message. when a message/command returns,
+ *       the platform returns the whole message header unmodified including
+ *	 the token.
+ */
+struct scmi_msg_hdr {
+	u8 id;
+	u8 protocol_id;
+	u16 seq;
+	u32 status;
+	bool poll_completion;
+};
+
+/**
+ * struct scmi_msg - Message(Tx/Rx) structure
+ *
+ * @buf: Buffer pointer
+ * @len: Length of data in the Buffer
+ */
+struct scmi_msg {
+	void *buf;
+	size_t len;
+};
+
+/**
+ * struct scmi_xfer - Structure representing a message flow
+ *
+ * @hdr: Transmit message header
+ * @tx: Transmit message
+ * @rx: Receive message, the buffer should be pre-allocated to store
+ *	message. If request-ACK protocol is used, we can reuse the same
+ *	buffer for the rx path as we use for the tx path.
+ * @done: completion event
+ */
+
+struct scmi_xfer {
+	void *con_priv;
+	struct scmi_msg_hdr hdr;
+	struct scmi_msg tx;
+	struct scmi_msg rx;
+	struct completion done;
+};
+
+void scmi_one_xfer_put(const struct scmi_handle *h, struct scmi_xfer *xfer);
+int scmi_do_xfer(const struct scmi_handle *h, struct scmi_xfer *xfer);
+int scmi_one_xfer_init(const struct scmi_handle *h, u8 msg_id, u8 prot_id,
+		       size_t tx_size, size_t rx_size, struct scmi_xfer **p);
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
new file mode 100644
index 000000000000..1d556a928de9
--- /dev/null
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -0,0 +1,769 @@
+/*
+ * System Control and Management Interface (SCMI) Message Protocol driver
+ *
+ * SCMI Message Protocol is used between the System Control Processor(SCP)
+ * and the Application Processors(AP). The Message Handling Unit(MHU)
+ * provides a mechanism for inter-processor communication between SCP's
+ * Cortex M3 and AP.
+ *
+ * SCP offers control and management of the core/cluster power states,
+ * various power domain DVFS including the core/cluster, certain system
+ * clocks configuration, thermal sensors and many others.
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/bitmap.h>
+#include <linux/export.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_client.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/semaphore.h>
+#include <linux/slab.h>
+
+#include "common.h"
+
+#define MSG_ID_SHIFT		0
+#define MSG_ID_MASK		0xff
+#define MSG_TYPE_SHIFT		8
+#define MSG_TYPE_MASK		0x3
+#define MSG_PROTOCOL_ID_SHIFT	10
+#define MSG_PROTOCOL_ID_MASK	0xff
+#define MSG_TOKEN_ID_SHIFT	18
+#define MSG_TOKEN_ID_MASK	0x3ff
+#define MSG_XTRACT_TOKEN(header)	\
+	(((header) >> MSG_TOKEN_ID_SHIFT) & MSG_TOKEN_ID_MASK)
+
+enum scmi_error_codes {
+	SCMI_SUCCESS = 0,	/* Success */
+	SCMI_ERR_SUPPORT = -1,	/* Not supported */
+	SCMI_ERR_PARAMS = -2,	/* Invalid Parameters */
+	SCMI_ERR_ACCESS = -3,	/* Invalid access/permission denied */
+	SCMI_ERR_ENTRY = -4,	/* Not found */
+	SCMI_ERR_RANGE = -5,	/* Value out of range */
+	SCMI_ERR_BUSY = -6,	/* Device busy */
+	SCMI_ERR_COMMS = -7,	/* Communication Error */
+	SCMI_ERR_GENERIC = -8,	/* Generic Error */
+	SCMI_ERR_HARDWARE = -9,	/* Hardware Error */
+	SCMI_ERR_PROTOCOL = -10,/* Protocol Error */
+	SCMI_ERR_MAX
+};
+
+/* List of all  SCMI devices active in system */
+static LIST_HEAD(scmi_list);
+/* Protection for the entire list */
+static DEFINE_MUTEX(scmi_list_mutex);
+
+/**
+ * struct scmi_xfers_info - Structure to manage transfer information
+ *
+ * @sem_xfer_count: Counting Semaphore for managing max simultaneous
+ *	Messages.
+ * @xfer_block: Preallocated Message array
+ * @xfer_alloc_table: Bitmap table for allocated messages.
+ *	Index of this bitmap table is also used for message
+ *	sequence identifier.
+ * @xfer_lock: Protection for message allocation
+ */
+struct scmi_xfers_info {
+	struct semaphore sem_xfer_count;
+	struct scmi_xfer *xfer_block;
+	unsigned long *xfer_alloc_table;
+	/* protect transfer allocation */
+	spinlock_t xfer_lock;
+};
+
+/**
+ * struct scmi_desc - Description of SoC integration
+ *
+ * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds)
+ * @max_msg: Maximum number of messages that can be pending
+ *	simultaneously in the system
+ * @max_msg_size: Maximum size of data per message that can be handled.
+ */
+struct scmi_desc {
+	int max_rx_timeout_ms;
+	int max_msg;
+	int max_msg_size;
+};
+
+/**
+ * struct scmi_info - Structure representing a  SCMI instance
+ *
+ * @dev: Device pointer
+ * @desc: SoC description for this instance
+ * @handle: Instance of SCMI handle to send to clients
+ * @cl: Mailbox Client
+ * @tx_chan: Transmit mailbox channel
+ * @tx_payload: Transmit mailbox channel payload area
+ * @minfo: Message info
+ * @node: list head
+ * @users: Number of users of this instance
+ */
+struct scmi_info {
+	struct device *dev;
+	const struct scmi_desc *desc;
+	struct scmi_handle handle;
+	struct mbox_client cl;
+	struct mbox_chan *tx_chan;
+	void __iomem *tx_payload;
+	struct scmi_xfers_info minfo;
+	struct list_head node;
+	int users;
+};
+
+#define client_to_scmi_info(c)	container_of(c, struct scmi_info, cl)
+#define handle_to_scmi_info(h)	container_of(h, struct scmi_info, handle)
+
+/*
+ * The SCP firmware providing SCM interface to OSPM and other agents must
+ * execute only in little-endian mode as per SCMI specification, so any buffers
+ * shared through SCMI should have their contents converted to little-endian
+ */
+struct scmi_shared_mem {
+	__le32 reserved;
+	__le32 channel_status;
+#define SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR	BIT(1)
+#define SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE	BIT(0)
+	__le32 reserved1[2];
+	__le32 flags;
+#define SCMI_SHMEM_FLAG_INTR_ENABLED	BIT(0)
+	__le32 length;
+	__le32 msg_header;
+	u8 msg_payload[0];
+};
+
+static int scmi_linux_errmap[] = {
+	/* better than switch case as long as return value is continuous */
+	0,			/* SCMI_SUCCESS */
+	-EOPNOTSUPP,		/* SCMI_ERR_SUPPORT */
+	-EINVAL,		/* SCMI_ERR_PARAM */
+	-EACCES,		/* SCMI_ERR_ACCESS */
+	-ENOENT,		/* SCMI_ERR_ENTRY */
+	-ERANGE,		/* SCMI_ERR_RANGE */
+	-EBUSY,			/* SCMI_ERR_BUSY */
+	-ECOMM,			/* SCMI_ERR_COMMS */
+	-EIO,			/* SCMI_ERR_GENERIC */
+	-EREMOTEIO,		/* SCMI_ERR_HARDWARE */
+	-EPROTO,		/* SCMI_ERR_PROTOCOL */
+};
+
+static inline int scmi_to_linux_errno(int errno)
+{
+	if (errno < SCMI_SUCCESS && errno > SCMI_ERR_MAX)
+		return scmi_linux_errmap[-errno];
+	return -EIO;
+}
+
+/**
+ * scmi_dump_header_dbg() - Helper to dump a message header.
+ *
+ * @dev: Device pointer corresponding to the SCMI entity
+ * @hdr: pointer to header.
+ */
+static inline void scmi_dump_header_dbg(struct device *dev,
+					struct scmi_msg_hdr *hdr)
+{
+	dev_dbg(dev, "Command ID: %x Sequence ID: %x Protocol: %x\n",
+		hdr->id, hdr->seq, hdr->protocol_id);
+}
+
+static void scmi_fetch_response(struct scmi_xfer *xfer,
+				struct scmi_shared_mem *mem)
+{
+	xfer->hdr.status = le32_to_cpu(*(__le32 *)mem->msg_payload);
+	/* Skip the length of header and statues in payload area i.e 8 bytes*/
+	xfer->rx.len = min_t(size_t, xfer->rx.len,
+			     le32_to_cpu(mem->length) - 8);
+
+	/* Take a copy to the rx buffer.. */
+	memcpy_fromio(xfer->rx.buf, mem->msg_payload + 4, xfer->rx.len);
+}
+
+/**
+ * scmi_rx_callback() - mailbox client callback for receive messages
+ *
+ * @cl: client pointer
+ * @m: mailbox message
+ *
+ * Processes one received message to appropriate transfer information and
+ * signals completion of the transfer.
+ *
+ * NOTE: This function will be invoked in IRQ context, hence should be
+ * as optimal as possible.
+ */
+static void scmi_rx_callback(struct mbox_client *cl, void *m)
+{
+	u16 xfer_id;
+	struct scmi_xfer *xfer;
+	struct scmi_info *info = client_to_scmi_info(cl);
+	struct scmi_xfers_info *minfo = &info->minfo;
+	struct device *dev = info->dev;
+	struct scmi_shared_mem *mem = info->tx_payload;
+
+	xfer_id = MSG_XTRACT_TOKEN(le32_to_cpu(mem->msg_header));
+
+	/*
+	 * Are we even expecting this?
+	 */
+	if (!test_bit(xfer_id, minfo->xfer_alloc_table)) {
+		dev_err(dev, "message for %d is not expected!\n", xfer_id);
+		return;
+	}
+
+	xfer = &minfo->xfer_block[xfer_id];
+
+	scmi_dump_header_dbg(dev, &xfer->hdr);
+	/* Is the message of valid length? */
+	if (xfer->rx.len > info->desc->max_msg_size) {
+		dev_err(dev, "unable to handle %zu xfer(max %d)\n",
+			xfer->rx.len, info->desc->max_msg_size);
+		return;
+	}
+
+	scmi_fetch_response(xfer, mem);
+	complete(&xfer->done);
+}
+
+/**
+ * pack_scmi_header() - packs and returns 32-bit header
+ *
+ * @hdr: pointer to header containing all the information on message id,
+ *	protocol id and sequence id.
+ */
+static inline u32 pack_scmi_header(struct scmi_msg_hdr *hdr)
+{
+	return ((hdr->id & MSG_ID_MASK) << MSG_ID_SHIFT) |
+	   ((hdr->seq & MSG_TOKEN_ID_MASK) << MSG_TOKEN_ID_SHIFT) |
+	   ((hdr->protocol_id & MSG_PROTOCOL_ID_MASK) << MSG_PROTOCOL_ID_SHIFT);
+}
+
+/**
+ * scmi_tx_prepare() - mailbox client callback to prepare for the transfer
+ *
+ * @cl: client pointer
+ * @m: mailbox message
+ *
+ * This function prepares the shared memory which contains the header and the
+ * payload.
+ */
+static void scmi_tx_prepare(struct mbox_client *cl, void *m)
+{
+	struct scmi_xfer *t = m;
+	struct scmi_info *info = client_to_scmi_info(cl);
+	struct scmi_shared_mem *mem = info->tx_payload;
+
+	mem->channel_status = 0x0; /* Mark channel busy + clear error */
+	mem->flags = t->hdr.poll_completion ? 0 :
+			cpu_to_le32(SCMI_SHMEM_FLAG_INTR_ENABLED);
+	mem->length = cpu_to_le32(sizeof(mem->msg_header) + t->tx.len);
+	mem->msg_header = cpu_to_le32(pack_scmi_header(&t->hdr));
+	if (t->tx.buf)
+		memcpy_toio(mem->msg_payload, t->tx.buf, t->tx.len);
+}
+
+/**
+ * scmi_one_xfer_get() - Allocate one message
+ *
+ * @handle: SCMI entity handle
+ *
+ * Helper function which is used by various command functions that are
+ * exposed to clients of this driver for allocating a message traffic event.
+ *
+ * This function can sleep depending on pending requests already in the system
+ * for the SCMI entity. Further, this also holds a spinlock to maintain
+ * integrity of internal data structures.
+ *
+ * Return: 0 if all went fine, else corresponding error.
+ */
+static struct scmi_xfer *scmi_one_xfer_get(const struct scmi_handle *handle)
+{
+	u16 xfer_id;
+	int ret, timeout;
+	struct scmi_xfer *xfer;
+	unsigned long flags, bit_pos;
+	struct scmi_info *info = handle_to_scmi_info(handle);
+	struct scmi_xfers_info *minfo = &info->minfo;
+
+	/*
+	 * Ensure we have only controlled number of pending messages.
+	 * Ideally, we might just have to wait a single message, be
+	 * conservative and wait 5 times that..
+	 */
+	timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms) * 5;
+	ret = down_timeout(&minfo->sem_xfer_count, timeout);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	/* Keep the locked section as small as possible */
+	spin_lock_irqsave(&minfo->xfer_lock, flags);
+	bit_pos = find_first_zero_bit(minfo->xfer_alloc_table,
+				      info->desc->max_msg);
+	if (bit_pos == info->desc->max_msg) {
+		spin_unlock_irqrestore(&minfo->xfer_lock, flags);
+		return ERR_PTR(-ENOMEM);
+	}
+	set_bit(bit_pos, minfo->xfer_alloc_table);
+	spin_unlock_irqrestore(&minfo->xfer_lock, flags);
+
+	xfer_id = bit_pos;
+
+	xfer = &minfo->xfer_block[xfer_id];
+	xfer->hdr.seq = xfer_id;
+	reinit_completion(&xfer->done);
+
+	return xfer;
+}
+
+/**
+ * scmi_one_xfer_put() - Release a message
+ *
+ * @minfo: transfer info pointer
+ * @xfer: message that was reserved by scmi_one_xfer_get
+ *
+ * This holds a spinlock to maintain integrity of internal data structures.
+ */
+void scmi_one_xfer_put(const struct scmi_handle *handle, struct scmi_xfer *xfer)
+{
+	unsigned long flags;
+	struct scmi_info *info = handle_to_scmi_info(handle);
+	struct scmi_xfers_info *minfo = &info->minfo;
+
+	/*
+	 * Keep the locked section as small as possible
+	 * NOTE: we might escape with smp_mb and no lock here..
+	 * but just be conservative and symmetric.
+	 */
+	spin_lock_irqsave(&minfo->xfer_lock, flags);
+	clear_bit(xfer->hdr.seq, minfo->xfer_alloc_table);
+	spin_unlock_irqrestore(&minfo->xfer_lock, flags);
+
+	/* Increment the count for the next user to get through */
+	up(&minfo->sem_xfer_count);
+}
+
+/**
+ * scmi_do_xfer() - Do one transfer
+ *
+ * @info: Pointer to SCMI entity information
+ * @xfer: Transfer to initiate and wait for response
+ *
+ * Return: -ETIMEDOUT in case of no response, if transmit error,
+ *   return corresponding error, else if all goes well,
+ *   return 0.
+ */
+int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
+{
+	int ret;
+	int timeout;
+	struct scmi_info *info = handle_to_scmi_info(handle);
+	struct device *dev = info->dev;
+
+	ret = mbox_send_message(info->tx_chan, xfer);
+	if (ret < 0) {
+		dev_dbg(dev, "mbox send fail %d\n", ret);
+		return ret;
+	}
+
+	/* mbox_send_message returns non-negative value on success, so reset */
+	ret = 0;
+
+	/* And we wait for the response. */
+	timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms);
+	if (!wait_for_completion_timeout(&xfer->done, timeout)) {
+		dev_err(dev, "mbox timed out in resp(caller: %pF)\n",
+			(void *)_RET_IP_);
+		ret = -ETIMEDOUT;
+	} else if (xfer->hdr.status) {
+		ret = scmi_to_linux_errno(xfer->hdr.status);
+	}
+	/*
+	 * NOTE: we might prefer not to need the mailbox ticker to manage the
+	 * transfer queueing since the protocol layer queues things by itself.
+	 * Unfortunately, we have to kick the mailbox framework after we have
+	 * received our message.
+	 */
+	mbox_client_txdone(info->tx_chan, ret);
+
+	return ret;
+}
+
+/**
+ * scmi_one_xfer_init() - Allocate and initialise one message
+ *
+ * @handle: SCMI entity handle
+ * @msg_id: Message identifier
+ * @msg_prot_id: Protocol identifier for the message
+ * @tx_size: transmit message size
+ * @rx_size: receive message size
+ * @p: pointer to the allocated and initialised message
+ *
+ * This function allocates the message using @scmi_one_xfer_get and
+ * initialise the header.
+ *
+ * Return: 0 if all went fine with @p pointing to message, else
+ *	corresponding error.
+ */
+int scmi_one_xfer_init(const struct scmi_handle *handle, u8 msg_id, u8 prot_id,
+		       size_t tx_size, size_t rx_size, struct scmi_xfer **p)
+{
+	int ret;
+	struct scmi_xfer *xfer;
+	struct scmi_info *info = handle_to_scmi_info(handle);
+	struct device *dev = info->dev;
+
+	/* Ensure we have sane transfer sizes */
+	if (rx_size > info->desc->max_msg_size ||
+	    tx_size > info->desc->max_msg_size)
+		return -ERANGE;
+
+	xfer = scmi_one_xfer_get(handle);
+	if (IS_ERR(xfer)) {
+		ret = PTR_ERR(xfer);
+		dev_err(dev, "failed to get free message slot(%d)\n", ret);
+		return ret;
+	}
+
+	xfer->tx.len = tx_size;
+	xfer->rx.len = rx_size ? : info->desc->max_msg_size;
+	xfer->hdr.id = msg_id;
+	xfer->hdr.protocol_id = prot_id;
+	xfer->hdr.poll_completion = false;
+
+	*p = xfer;
+	return 0;
+}
+
+/**
+ * scmi_handle_get() - Get the  SCMI handle for a device
+ *
+ * @dev: pointer to device for which we want SCMI handle
+ *
+ * NOTE: The function does not track individual clients of the framework
+ * and is expected to be maintained by caller of  SCMI protocol library.
+ * scmi_handle_put must be balanced with successful scmi_handle_get
+ *
+ * Return: pointer to handle if successful, else:
+ *	-EPROBE_DEFER if the instance is not ready
+ *	-ENODEV if the required node handler is missing
+ *	-EINVAL if invalid conditions are encountered.
+ */
+const struct scmi_handle *scmi_handle_get(struct device *dev)
+{
+	struct list_head *p;
+	struct scmi_info *info;
+	struct scmi_handle *handle = NULL;
+
+	if (!dev || !dev->parent) {
+		pr_err("missing device or parent pointer\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	mutex_lock(&scmi_list_mutex);
+	list_for_each(p, &scmi_list) {
+		info = list_entry(p, struct scmi_info, node);
+		if (dev->parent == info->dev) {
+			handle = &info->handle;
+			info->users++;
+			break;
+		}
+	}
+	mutex_unlock(&scmi_list_mutex);
+
+	if (!handle)
+		return ERR_PTR(-EPROBE_DEFER);
+
+	return handle;
+}
+EXPORT_SYMBOL_GPL(scmi_handle_get);
+
+/**
+ * scmi_handle_put() - Release the handle acquired by scmi_handle_get
+ *
+ * @handle: handle acquired by scmi_handle_get
+ *
+ * NOTE: The function does not track individual clients of the framework
+ * and is expected to be maintained by caller of  SCMI protocol library.
+ * scmi_handle_put must be balanced with successful scmi_handle_get
+ *
+ * Return: 0 is successfully released
+ *	if an error pointer was passed, it returns the error value back,
+ *	if null was passed, it returns -EINVAL;
+ */
+int scmi_handle_put(const struct scmi_handle *handle)
+{
+	struct scmi_info *info;
+
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	if (!handle)
+		return -EINVAL;
+
+	info = handle_to_scmi_info(handle);
+	mutex_lock(&scmi_list_mutex);
+	if (!WARN_ON(!info->users))
+		info->users--;
+	mutex_unlock(&scmi_list_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(scmi_handle_put);
+
+static void devm_scmi_release(struct device *dev, void *res)
+{
+	const struct scmi_handle **ptr = res;
+	const struct scmi_handle *handle = *ptr;
+	int ret;
+
+	ret = scmi_handle_put(handle);
+	if (ret)
+		dev_err(dev, "failed to put handle %d\n", ret);
+}
+
+/**
+ * devm_scmi_handle_get() - Managed get handle
+ * @dev: device for which we want SCMI handle for.
+ *
+ * NOTE: This releases the handle once the device resources are
+ * no longer needed. MUST NOT BE released with scmi_handle_put.
+ * The function does not track individual clients of the framework
+ * and is expected to be maintained by caller of  SCMI protocol library.
+ *
+ * Return: 0 if all went fine, else corresponding error.
+ */
+const struct scmi_handle *devm_scmi_handle_get(struct device *dev)
+{
+	const struct scmi_handle **ptr;
+	const struct scmi_handle *handle;
+
+	ptr = devres_alloc(devm_scmi_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+	handle = scmi_handle_get(dev);
+
+	if (!IS_ERR(handle)) {
+		*ptr = handle;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return handle;
+}
+EXPORT_SYMBOL_GPL(devm_scmi_handle_get);
+
+static const struct scmi_desc scmi_generic_desc = {
+	.max_rx_timeout_ms = 30,	/* we may increase this if required */
+	.max_msg = 20,		/* Limited by MBOX_TX_QUEUE_LEN */
+	.max_msg_size = 128,
+};
+
+/* Each compatible listed below must have descriptor associated with it */
+static const struct of_device_id scmi_of_match[] = {
+	{ .compatible = "arm,scmi", .data = &scmi_generic_desc },
+	{ /* Sentinel */ },
+};
+
+MODULE_DEVICE_TABLE(of, scmi_of_match);
+
+static int scmi_xfer_info_init(struct scmi_info *sinfo)
+{
+	int i;
+	struct scmi_xfer *xfer;
+	struct device *dev = sinfo->dev;
+	const struct scmi_desc *desc = sinfo->desc;
+	struct scmi_xfers_info *info = &sinfo->minfo;
+
+	/* Pre-allocated messages, no more than what hdr.seq can support */
+	if (WARN_ON(desc->max_msg >= (MSG_TOKEN_ID_MASK + 1))) {
+		dev_err(dev, "Maximum message of %d exceeds supported %d\n",
+			desc->max_msg, MSG_TOKEN_ID_MASK + 1);
+		return -EINVAL;
+	}
+
+	info->xfer_block = devm_kcalloc(dev, desc->max_msg,
+					sizeof(*info->xfer_block), GFP_KERNEL);
+	if (!info->xfer_block)
+		return -ENOMEM;
+
+	info->xfer_alloc_table = devm_kcalloc(dev, BITS_TO_LONGS(desc->max_msg),
+					      sizeof(long), GFP_KERNEL);
+	if (!info->xfer_alloc_table)
+		return -ENOMEM;
+
+	bitmap_zero(info->xfer_alloc_table, desc->max_msg);
+
+	/* Pre-initialize the buffer pointer to pre-allocated buffers */
+	for (i = 0, xfer = info->xfer_block; i < desc->max_msg; i++, xfer++) {
+		xfer->rx.buf = devm_kcalloc(dev, sizeof(u8), desc->max_msg_size,
+					    GFP_KERNEL);
+		if (!xfer->rx.buf)
+			return -ENOMEM;
+
+		xfer->tx.buf = xfer->rx.buf;
+		init_completion(&xfer->done);
+	}
+
+	spin_lock_init(&info->xfer_lock);
+
+	sema_init(&info->sem_xfer_count, desc->max_msg);
+
+	return 0;
+}
+
+static int scmi_mailbox_check(struct device_node *np)
+{
+	struct of_phandle_args arg;
+
+	return of_parse_phandle_with_args(np, "mboxes", "#mbox-cells", 0, &arg);
+}
+
+static int scmi_mbox_free_channel(struct scmi_info *info)
+{
+	if (!IS_ERR_OR_NULL(info->tx_chan)) {
+		mbox_free_channel(info->tx_chan);
+		info->tx_chan = NULL;
+	}
+
+	return 0;
+}
+
+static int scmi_remove(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct scmi_info *info = platform_get_drvdata(pdev);
+
+	of_platform_depopulate(&pdev->dev);
+
+	mutex_lock(&scmi_list_mutex);
+	if (info->users)
+		ret = -EBUSY;
+	else
+		list_del(&info->node);
+	mutex_unlock(&scmi_list_mutex);
+
+	if (!ret)
+		/* Safe to free channels since no more users */
+		return scmi_mbox_free_channel(info);
+
+	return ret;
+}
+
+static inline int scmi_mbox_chan_setup(struct scmi_info *info)
+{
+	int ret;
+	struct resource res;
+	resource_size_t size;
+	struct device *dev = info->dev;
+	struct device_node *shmem, *np = dev->of_node;
+	struct mbox_client *cl;
+
+	cl = &info->cl;
+	cl->dev = dev;
+	cl->rx_callback = scmi_rx_callback;
+	cl->tx_prepare = scmi_tx_prepare;
+	cl->tx_block = false;
+	cl->knows_txdone = true;
+
+	shmem = of_parse_phandle(np, "shmem", 0);
+	ret = of_address_to_resource(shmem, 0, &res);
+	of_node_put(shmem);
+	if (ret) {
+		dev_err(dev, "failed to get SCMI Tx payload mem resource\n");
+		return ret;
+	}
+
+	size = resource_size(&res);
+	info->tx_payload = devm_ioremap(dev, res.start, size);
+	if (!info->tx_payload) {
+		dev_err(dev, "failed to ioremap SCMI Tx payload\n");
+		return -EADDRNOTAVAIL;
+	}
+
+	/* Transmit channel is first entry i.e. index 0 */
+	info->tx_chan = mbox_request_channel(cl, 0);
+	if (IS_ERR(info->tx_chan)) {
+		ret = PTR_ERR(info->tx_chan);
+		if (ret != -EPROBE_DEFER)
+			dev_err(dev, "failed to request SCMI Tx mailbox\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int scmi_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct scmi_handle *handle;
+	const struct scmi_desc *desc;
+	struct scmi_info *info;
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+
+	/* Only mailbox method supported, check for the presence of one */
+	if (scmi_mailbox_check(np)) {
+		dev_err(dev, "no mailbox found in %pOF\n", np);
+		return -EINVAL;
+	}
+
+	desc = of_match_device(scmi_of_match, dev)->data;
+
+	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->dev = dev;
+	info->desc = desc;
+	INIT_LIST_HEAD(&info->node);
+
+	ret = scmi_xfer_info_init(info);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, info);
+
+	handle = &info->handle;
+	handle->dev = info->dev;
+
+	ret = scmi_mbox_chan_setup(info);
+	if (ret)
+		return ret;
+
+	mutex_lock(&scmi_list_mutex);
+	list_add_tail(&info->node, &scmi_list);
+	mutex_unlock(&scmi_list_mutex);
+
+	return 0;
+}
+
+static struct platform_driver scmi_driver = {
+	.driver = {
+		   .name = "arm-scmi",
+		   .of_match_table = of_match_ptr(scmi_of_match),
+		   },
+	.probe = scmi_probe,
+	.remove = scmi_remove,
+};
+
+module_platform_driver(scmi_driver);
+
+MODULE_ALIAS("platform: arm-scmi");
+MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
+MODULE_DESCRIPTION("ARM SCMI protocol driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
new file mode 100644
index 000000000000..fbe80fa1ec9f
--- /dev/null
+++ b/include/linux/scmi_protocol.h
@@ -0,0 +1,48 @@
+/*
+ * SCMI Message Protocol driver header
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/types.h>
+
+/**
+ * struct scmi_handle - Handle returned to ARM SCMI clients for usage.
+ *
+ * @dev: pointer to the SCMI device
+ */
+struct scmi_handle {
+	struct device *dev;
+};
+
+#if IS_REACHABLE(CONFIG_ARM_SCMI_PROTOCOL)
+int scmi_handle_put(const struct scmi_handle *handle);
+const struct scmi_handle *scmi_handle_get(struct device *dev);
+const struct scmi_handle *devm_scmi_handle_get(struct device *dev);
+#else
+static inline int scmi_handle_put(const struct scmi_handle *handle)
+{
+	return 0;
+}
+
+static inline const struct scmi_handle *scmi_handle_get(struct device *dev)
+{
+	return NULL;
+}
+
+static inline const struct scmi_handle *devm_scmi_handle_get(struct device *dev)
+{
+	return NULL;
+}
+#endif /* CONFIG_ARM_SCMI_PROTOCOL */
-- 
2.7.4

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

* [PATCH v3 04/22] firmware: arm_scmi: add basic driver infrastructure for SCMI
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

The SCMI is intended to allow OSPM to manage various functions that are
provided by the hardware platform it is running on, including power and
performance functions. SCMI provides two levels of abstraction, protocols
and transports. Protocols define individual groups of system control and
management messages. A protocol specification describes the messages
that it supports. Transports describe the method by which protocol
messages are communicated between agents and the platform.

This patch adds basic infrastructure to manage the message allocation,
initialisation, packing/unpacking and shared memory management.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 MAINTAINERS                        |   3 +-
 drivers/firmware/Kconfig           |  21 +
 drivers/firmware/Makefile          |   1 +
 drivers/firmware/arm_scmi/Makefile |   2 +
 drivers/firmware/arm_scmi/common.h |  75 ++++
 drivers/firmware/arm_scmi/driver.c | 769 +++++++++++++++++++++++++++++++++++++
 include/linux/scmi_protocol.h      |  48 +++
 7 files changed, 918 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/arm_scmi/Makefile
 create mode 100644 drivers/firmware/arm_scmi/common.h
 create mode 100644 drivers/firmware/arm_scmi/driver.c
 create mode 100644 include/linux/scmi_protocol.h

diff --git a/MAINTAINERS b/MAINTAINERS
index f4b5f3967725..23ec3471f542 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12944,7 +12944,8 @@ F:	Documentation/devicetree/bindings/arm/arm,sc[mp]i.txt
 F:	drivers/clk/clk-scpi.c
 F:	drivers/cpufreq/scpi-cpufreq.c
 F:	drivers/firmware/arm_scpi.c
-F:	include/linux/scpi_protocol.h
+F:	drivers/firmware/arm_scmi/
+F:	include/linux/sc[mp]i_protocol.h
 
 SYSTEM RESET/SHUTDOWN DRIVERS
 M:	Sebastian Reichel <sre@kernel.org>
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 6e4ed5a9c6fd..c3d1a12763ce 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -19,6 +19,27 @@ config ARM_PSCI_CHECKER
 	  on and off through hotplug, so for now torture tests and PSCI checker
 	  are mutually exclusive.
 
+config ARM_SCMI_PROTOCOL
+	tristate "ARM System Control and Management Interface (SCMI) Message Protocol"
+	depends on ARM || ARM64 || COMPILE_TEST
+	depends on MAILBOX
+	help
+	  ARM System Control and Management Interface (SCMI) protocol is a
+	  set of operating system-independent software interfaces that are
+	  used in system management. SCMI is extensible and currently provides
+	  interfaces for: Discovery and self-description of the interfaces
+	  it supports, Power domain management which is the ability to place
+	  a given device or domain into the various power-saving states that
+	  it supports, Performance management which is the ability to control
+	  the performance of a domain that is composed of compute engines
+	  such as application processors and other accelerators, Clock
+	  management which is the ability to set and inquire rates on platform
+	  managed clocks and Sensor management which is the ability to read
+	  sensor data, and be notified of sensor value.
+
+	  This protocol library provides interface for all the client drivers
+	  making use of the features offered by the SCMI.
+
 config ARM_SCPI_PROTOCOL
 	tristate "ARM System Control and Power Interface (SCPI) Message Protocol"
 	depends on ARM || ARM64 || COMPILE_TEST
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index a37f12e8d137..91d3ff62c653 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_QCOM_SCM_32)	+= qcom_scm-32.o
 CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQUIRES_SEC=1) -march=armv7-a
 obj-$(CONFIG_TI_SCI_PROTOCOL)	+= ti_sci.o
 
+obj-$(CONFIG_ARM_SCMI_PROTOCOL)	+= arm_scmi/
 obj-y				+= broadcom/
 obj-y				+= meson/
 obj-$(CONFIG_GOOGLE_FIRMWARE)	+= google/
diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
new file mode 100644
index 000000000000..58e94c95e523
--- /dev/null
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_ARM_SCMI_PROTOCOL)	= arm_scmi.o
+arm_scmi-y = driver.o
diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
new file mode 100644
index 000000000000..344b234d4e64
--- /dev/null
+++ b/drivers/firmware/arm_scmi/common.h
@@ -0,0 +1,75 @@
+/*
+ * System Control and Management Interface (SCMI) Message Protocol
+ * driver common header file containing some definitions, structures
+ * and function prototypes used in all the different SCMI protocols.
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/completion.h>
+#include <linux/scmi_protocol.h>
+#include <linux/types.h>
+
+/**
+ * struct scmi_msg_hdr - Message(Tx/Rx) header
+ *
+ * @id: The identifier of the command being sent
+ * @protocol_id: The identifier of the protocol used to send @id command
+ * @seq: The token to identify the message. when a message/command returns,
+ *       the platform returns the whole message header unmodified including
+ *	 the token.
+ */
+struct scmi_msg_hdr {
+	u8 id;
+	u8 protocol_id;
+	u16 seq;
+	u32 status;
+	bool poll_completion;
+};
+
+/**
+ * struct scmi_msg - Message(Tx/Rx) structure
+ *
+ * @buf: Buffer pointer
+ * @len: Length of data in the Buffer
+ */
+struct scmi_msg {
+	void *buf;
+	size_t len;
+};
+
+/**
+ * struct scmi_xfer - Structure representing a message flow
+ *
+ * @hdr: Transmit message header
+ * @tx: Transmit message
+ * @rx: Receive message, the buffer should be pre-allocated to store
+ *	message. If request-ACK protocol is used, we can reuse the same
+ *	buffer for the rx path as we use for the tx path.
+ * @done: completion event
+ */
+
+struct scmi_xfer {
+	void *con_priv;
+	struct scmi_msg_hdr hdr;
+	struct scmi_msg tx;
+	struct scmi_msg rx;
+	struct completion done;
+};
+
+void scmi_one_xfer_put(const struct scmi_handle *h, struct scmi_xfer *xfer);
+int scmi_do_xfer(const struct scmi_handle *h, struct scmi_xfer *xfer);
+int scmi_one_xfer_init(const struct scmi_handle *h, u8 msg_id, u8 prot_id,
+		       size_t tx_size, size_t rx_size, struct scmi_xfer **p);
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
new file mode 100644
index 000000000000..1d556a928de9
--- /dev/null
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -0,0 +1,769 @@
+/*
+ * System Control and Management Interface (SCMI) Message Protocol driver
+ *
+ * SCMI Message Protocol is used between the System Control Processor(SCP)
+ * and the Application Processors(AP). The Message Handling Unit(MHU)
+ * provides a mechanism for inter-processor communication between SCP's
+ * Cortex M3 and AP.
+ *
+ * SCP offers control and management of the core/cluster power states,
+ * various power domain DVFS including the core/cluster, certain system
+ * clocks configuration, thermal sensors and many others.
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/bitmap.h>
+#include <linux/export.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_client.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/semaphore.h>
+#include <linux/slab.h>
+
+#include "common.h"
+
+#define MSG_ID_SHIFT		0
+#define MSG_ID_MASK		0xff
+#define MSG_TYPE_SHIFT		8
+#define MSG_TYPE_MASK		0x3
+#define MSG_PROTOCOL_ID_SHIFT	10
+#define MSG_PROTOCOL_ID_MASK	0xff
+#define MSG_TOKEN_ID_SHIFT	18
+#define MSG_TOKEN_ID_MASK	0x3ff
+#define MSG_XTRACT_TOKEN(header)	\
+	(((header) >> MSG_TOKEN_ID_SHIFT) & MSG_TOKEN_ID_MASK)
+
+enum scmi_error_codes {
+	SCMI_SUCCESS = 0,	/* Success */
+	SCMI_ERR_SUPPORT = -1,	/* Not supported */
+	SCMI_ERR_PARAMS = -2,	/* Invalid Parameters */
+	SCMI_ERR_ACCESS = -3,	/* Invalid access/permission denied */
+	SCMI_ERR_ENTRY = -4,	/* Not found */
+	SCMI_ERR_RANGE = -5,	/* Value out of range */
+	SCMI_ERR_BUSY = -6,	/* Device busy */
+	SCMI_ERR_COMMS = -7,	/* Communication Error */
+	SCMI_ERR_GENERIC = -8,	/* Generic Error */
+	SCMI_ERR_HARDWARE = -9,	/* Hardware Error */
+	SCMI_ERR_PROTOCOL = -10,/* Protocol Error */
+	SCMI_ERR_MAX
+};
+
+/* List of all  SCMI devices active in system */
+static LIST_HEAD(scmi_list);
+/* Protection for the entire list */
+static DEFINE_MUTEX(scmi_list_mutex);
+
+/**
+ * struct scmi_xfers_info - Structure to manage transfer information
+ *
+ * @sem_xfer_count: Counting Semaphore for managing max simultaneous
+ *	Messages.
+ * @xfer_block: Preallocated Message array
+ * @xfer_alloc_table: Bitmap table for allocated messages.
+ *	Index of this bitmap table is also used for message
+ *	sequence identifier.
+ * @xfer_lock: Protection for message allocation
+ */
+struct scmi_xfers_info {
+	struct semaphore sem_xfer_count;
+	struct scmi_xfer *xfer_block;
+	unsigned long *xfer_alloc_table;
+	/* protect transfer allocation */
+	spinlock_t xfer_lock;
+};
+
+/**
+ * struct scmi_desc - Description of SoC integration
+ *
+ * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds)
+ * @max_msg: Maximum number of messages that can be pending
+ *	simultaneously in the system
+ * @max_msg_size: Maximum size of data per message that can be handled.
+ */
+struct scmi_desc {
+	int max_rx_timeout_ms;
+	int max_msg;
+	int max_msg_size;
+};
+
+/**
+ * struct scmi_info - Structure representing a  SCMI instance
+ *
+ * @dev: Device pointer
+ * @desc: SoC description for this instance
+ * @handle: Instance of SCMI handle to send to clients
+ * @cl: Mailbox Client
+ * @tx_chan: Transmit mailbox channel
+ * @tx_payload: Transmit mailbox channel payload area
+ * @minfo: Message info
+ * @node: list head
+ * @users: Number of users of this instance
+ */
+struct scmi_info {
+	struct device *dev;
+	const struct scmi_desc *desc;
+	struct scmi_handle handle;
+	struct mbox_client cl;
+	struct mbox_chan *tx_chan;
+	void __iomem *tx_payload;
+	struct scmi_xfers_info minfo;
+	struct list_head node;
+	int users;
+};
+
+#define client_to_scmi_info(c)	container_of(c, struct scmi_info, cl)
+#define handle_to_scmi_info(h)	container_of(h, struct scmi_info, handle)
+
+/*
+ * The SCP firmware providing SCM interface to OSPM and other agents must
+ * execute only in little-endian mode as per SCMI specification, so any buffers
+ * shared through SCMI should have their contents converted to little-endian
+ */
+struct scmi_shared_mem {
+	__le32 reserved;
+	__le32 channel_status;
+#define SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR	BIT(1)
+#define SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE	BIT(0)
+	__le32 reserved1[2];
+	__le32 flags;
+#define SCMI_SHMEM_FLAG_INTR_ENABLED	BIT(0)
+	__le32 length;
+	__le32 msg_header;
+	u8 msg_payload[0];
+};
+
+static int scmi_linux_errmap[] = {
+	/* better than switch case as long as return value is continuous */
+	0,			/* SCMI_SUCCESS */
+	-EOPNOTSUPP,		/* SCMI_ERR_SUPPORT */
+	-EINVAL,		/* SCMI_ERR_PARAM */
+	-EACCES,		/* SCMI_ERR_ACCESS */
+	-ENOENT,		/* SCMI_ERR_ENTRY */
+	-ERANGE,		/* SCMI_ERR_RANGE */
+	-EBUSY,			/* SCMI_ERR_BUSY */
+	-ECOMM,			/* SCMI_ERR_COMMS */
+	-EIO,			/* SCMI_ERR_GENERIC */
+	-EREMOTEIO,		/* SCMI_ERR_HARDWARE */
+	-EPROTO,		/* SCMI_ERR_PROTOCOL */
+};
+
+static inline int scmi_to_linux_errno(int errno)
+{
+	if (errno < SCMI_SUCCESS && errno > SCMI_ERR_MAX)
+		return scmi_linux_errmap[-errno];
+	return -EIO;
+}
+
+/**
+ * scmi_dump_header_dbg() - Helper to dump a message header.
+ *
+ * @dev: Device pointer corresponding to the SCMI entity
+ * @hdr: pointer to header.
+ */
+static inline void scmi_dump_header_dbg(struct device *dev,
+					struct scmi_msg_hdr *hdr)
+{
+	dev_dbg(dev, "Command ID: %x Sequence ID: %x Protocol: %x\n",
+		hdr->id, hdr->seq, hdr->protocol_id);
+}
+
+static void scmi_fetch_response(struct scmi_xfer *xfer,
+				struct scmi_shared_mem *mem)
+{
+	xfer->hdr.status = le32_to_cpu(*(__le32 *)mem->msg_payload);
+	/* Skip the length of header and statues in payload area i.e 8 bytes*/
+	xfer->rx.len = min_t(size_t, xfer->rx.len,
+			     le32_to_cpu(mem->length) - 8);
+
+	/* Take a copy to the rx buffer.. */
+	memcpy_fromio(xfer->rx.buf, mem->msg_payload + 4, xfer->rx.len);
+}
+
+/**
+ * scmi_rx_callback() - mailbox client callback for receive messages
+ *
+ * @cl: client pointer
+ * @m: mailbox message
+ *
+ * Processes one received message to appropriate transfer information and
+ * signals completion of the transfer.
+ *
+ * NOTE: This function will be invoked in IRQ context, hence should be
+ * as optimal as possible.
+ */
+static void scmi_rx_callback(struct mbox_client *cl, void *m)
+{
+	u16 xfer_id;
+	struct scmi_xfer *xfer;
+	struct scmi_info *info = client_to_scmi_info(cl);
+	struct scmi_xfers_info *minfo = &info->minfo;
+	struct device *dev = info->dev;
+	struct scmi_shared_mem *mem = info->tx_payload;
+
+	xfer_id = MSG_XTRACT_TOKEN(le32_to_cpu(mem->msg_header));
+
+	/*
+	 * Are we even expecting this?
+	 */
+	if (!test_bit(xfer_id, minfo->xfer_alloc_table)) {
+		dev_err(dev, "message for %d is not expected!\n", xfer_id);
+		return;
+	}
+
+	xfer = &minfo->xfer_block[xfer_id];
+
+	scmi_dump_header_dbg(dev, &xfer->hdr);
+	/* Is the message of valid length? */
+	if (xfer->rx.len > info->desc->max_msg_size) {
+		dev_err(dev, "unable to handle %zu xfer(max %d)\n",
+			xfer->rx.len, info->desc->max_msg_size);
+		return;
+	}
+
+	scmi_fetch_response(xfer, mem);
+	complete(&xfer->done);
+}
+
+/**
+ * pack_scmi_header() - packs and returns 32-bit header
+ *
+ * @hdr: pointer to header containing all the information on message id,
+ *	protocol id and sequence id.
+ */
+static inline u32 pack_scmi_header(struct scmi_msg_hdr *hdr)
+{
+	return ((hdr->id & MSG_ID_MASK) << MSG_ID_SHIFT) |
+	   ((hdr->seq & MSG_TOKEN_ID_MASK) << MSG_TOKEN_ID_SHIFT) |
+	   ((hdr->protocol_id & MSG_PROTOCOL_ID_MASK) << MSG_PROTOCOL_ID_SHIFT);
+}
+
+/**
+ * scmi_tx_prepare() - mailbox client callback to prepare for the transfer
+ *
+ * @cl: client pointer
+ * @m: mailbox message
+ *
+ * This function prepares the shared memory which contains the header and the
+ * payload.
+ */
+static void scmi_tx_prepare(struct mbox_client *cl, void *m)
+{
+	struct scmi_xfer *t = m;
+	struct scmi_info *info = client_to_scmi_info(cl);
+	struct scmi_shared_mem *mem = info->tx_payload;
+
+	mem->channel_status = 0x0; /* Mark channel busy + clear error */
+	mem->flags = t->hdr.poll_completion ? 0 :
+			cpu_to_le32(SCMI_SHMEM_FLAG_INTR_ENABLED);
+	mem->length = cpu_to_le32(sizeof(mem->msg_header) + t->tx.len);
+	mem->msg_header = cpu_to_le32(pack_scmi_header(&t->hdr));
+	if (t->tx.buf)
+		memcpy_toio(mem->msg_payload, t->tx.buf, t->tx.len);
+}
+
+/**
+ * scmi_one_xfer_get() - Allocate one message
+ *
+ * @handle: SCMI entity handle
+ *
+ * Helper function which is used by various command functions that are
+ * exposed to clients of this driver for allocating a message traffic event.
+ *
+ * This function can sleep depending on pending requests already in the system
+ * for the SCMI entity. Further, this also holds a spinlock to maintain
+ * integrity of internal data structures.
+ *
+ * Return: 0 if all went fine, else corresponding error.
+ */
+static struct scmi_xfer *scmi_one_xfer_get(const struct scmi_handle *handle)
+{
+	u16 xfer_id;
+	int ret, timeout;
+	struct scmi_xfer *xfer;
+	unsigned long flags, bit_pos;
+	struct scmi_info *info = handle_to_scmi_info(handle);
+	struct scmi_xfers_info *minfo = &info->minfo;
+
+	/*
+	 * Ensure we have only controlled number of pending messages.
+	 * Ideally, we might just have to wait a single message, be
+	 * conservative and wait 5 times that..
+	 */
+	timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms) * 5;
+	ret = down_timeout(&minfo->sem_xfer_count, timeout);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	/* Keep the locked section as small as possible */
+	spin_lock_irqsave(&minfo->xfer_lock, flags);
+	bit_pos = find_first_zero_bit(minfo->xfer_alloc_table,
+				      info->desc->max_msg);
+	if (bit_pos == info->desc->max_msg) {
+		spin_unlock_irqrestore(&minfo->xfer_lock, flags);
+		return ERR_PTR(-ENOMEM);
+	}
+	set_bit(bit_pos, minfo->xfer_alloc_table);
+	spin_unlock_irqrestore(&minfo->xfer_lock, flags);
+
+	xfer_id = bit_pos;
+
+	xfer = &minfo->xfer_block[xfer_id];
+	xfer->hdr.seq = xfer_id;
+	reinit_completion(&xfer->done);
+
+	return xfer;
+}
+
+/**
+ * scmi_one_xfer_put() - Release a message
+ *
+ * @minfo: transfer info pointer
+ * @xfer: message that was reserved by scmi_one_xfer_get
+ *
+ * This holds a spinlock to maintain integrity of internal data structures.
+ */
+void scmi_one_xfer_put(const struct scmi_handle *handle, struct scmi_xfer *xfer)
+{
+	unsigned long flags;
+	struct scmi_info *info = handle_to_scmi_info(handle);
+	struct scmi_xfers_info *minfo = &info->minfo;
+
+	/*
+	 * Keep the locked section as small as possible
+	 * NOTE: we might escape with smp_mb and no lock here..
+	 * but just be conservative and symmetric.
+	 */
+	spin_lock_irqsave(&minfo->xfer_lock, flags);
+	clear_bit(xfer->hdr.seq, minfo->xfer_alloc_table);
+	spin_unlock_irqrestore(&minfo->xfer_lock, flags);
+
+	/* Increment the count for the next user to get through */
+	up(&minfo->sem_xfer_count);
+}
+
+/**
+ * scmi_do_xfer() - Do one transfer
+ *
+ * @info: Pointer to SCMI entity information
+ * @xfer: Transfer to initiate and wait for response
+ *
+ * Return: -ETIMEDOUT in case of no response, if transmit error,
+ *   return corresponding error, else if all goes well,
+ *   return 0.
+ */
+int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
+{
+	int ret;
+	int timeout;
+	struct scmi_info *info = handle_to_scmi_info(handle);
+	struct device *dev = info->dev;
+
+	ret = mbox_send_message(info->tx_chan, xfer);
+	if (ret < 0) {
+		dev_dbg(dev, "mbox send fail %d\n", ret);
+		return ret;
+	}
+
+	/* mbox_send_message returns non-negative value on success, so reset */
+	ret = 0;
+
+	/* And we wait for the response. */
+	timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms);
+	if (!wait_for_completion_timeout(&xfer->done, timeout)) {
+		dev_err(dev, "mbox timed out in resp(caller: %pF)\n",
+			(void *)_RET_IP_);
+		ret = -ETIMEDOUT;
+	} else if (xfer->hdr.status) {
+		ret = scmi_to_linux_errno(xfer->hdr.status);
+	}
+	/*
+	 * NOTE: we might prefer not to need the mailbox ticker to manage the
+	 * transfer queueing since the protocol layer queues things by itself.
+	 * Unfortunately, we have to kick the mailbox framework after we have
+	 * received our message.
+	 */
+	mbox_client_txdone(info->tx_chan, ret);
+
+	return ret;
+}
+
+/**
+ * scmi_one_xfer_init() - Allocate and initialise one message
+ *
+ * @handle: SCMI entity handle
+ * @msg_id: Message identifier
+ * @msg_prot_id: Protocol identifier for the message
+ * @tx_size: transmit message size
+ * @rx_size: receive message size
+ * @p: pointer to the allocated and initialised message
+ *
+ * This function allocates the message using @scmi_one_xfer_get and
+ * initialise the header.
+ *
+ * Return: 0 if all went fine with @p pointing to message, else
+ *	corresponding error.
+ */
+int scmi_one_xfer_init(const struct scmi_handle *handle, u8 msg_id, u8 prot_id,
+		       size_t tx_size, size_t rx_size, struct scmi_xfer **p)
+{
+	int ret;
+	struct scmi_xfer *xfer;
+	struct scmi_info *info = handle_to_scmi_info(handle);
+	struct device *dev = info->dev;
+
+	/* Ensure we have sane transfer sizes */
+	if (rx_size > info->desc->max_msg_size ||
+	    tx_size > info->desc->max_msg_size)
+		return -ERANGE;
+
+	xfer = scmi_one_xfer_get(handle);
+	if (IS_ERR(xfer)) {
+		ret = PTR_ERR(xfer);
+		dev_err(dev, "failed to get free message slot(%d)\n", ret);
+		return ret;
+	}
+
+	xfer->tx.len = tx_size;
+	xfer->rx.len = rx_size ? : info->desc->max_msg_size;
+	xfer->hdr.id = msg_id;
+	xfer->hdr.protocol_id = prot_id;
+	xfer->hdr.poll_completion = false;
+
+	*p = xfer;
+	return 0;
+}
+
+/**
+ * scmi_handle_get() - Get the  SCMI handle for a device
+ *
+ * @dev: pointer to device for which we want SCMI handle
+ *
+ * NOTE: The function does not track individual clients of the framework
+ * and is expected to be maintained by caller of  SCMI protocol library.
+ * scmi_handle_put must be balanced with successful scmi_handle_get
+ *
+ * Return: pointer to handle if successful, else:
+ *	-EPROBE_DEFER if the instance is not ready
+ *	-ENODEV if the required node handler is missing
+ *	-EINVAL if invalid conditions are encountered.
+ */
+const struct scmi_handle *scmi_handle_get(struct device *dev)
+{
+	struct list_head *p;
+	struct scmi_info *info;
+	struct scmi_handle *handle = NULL;
+
+	if (!dev || !dev->parent) {
+		pr_err("missing device or parent pointer\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	mutex_lock(&scmi_list_mutex);
+	list_for_each(p, &scmi_list) {
+		info = list_entry(p, struct scmi_info, node);
+		if (dev->parent == info->dev) {
+			handle = &info->handle;
+			info->users++;
+			break;
+		}
+	}
+	mutex_unlock(&scmi_list_mutex);
+
+	if (!handle)
+		return ERR_PTR(-EPROBE_DEFER);
+
+	return handle;
+}
+EXPORT_SYMBOL_GPL(scmi_handle_get);
+
+/**
+ * scmi_handle_put() - Release the handle acquired by scmi_handle_get
+ *
+ * @handle: handle acquired by scmi_handle_get
+ *
+ * NOTE: The function does not track individual clients of the framework
+ * and is expected to be maintained by caller of  SCMI protocol library.
+ * scmi_handle_put must be balanced with successful scmi_handle_get
+ *
+ * Return: 0 is successfully released
+ *	if an error pointer was passed, it returns the error value back,
+ *	if null was passed, it returns -EINVAL;
+ */
+int scmi_handle_put(const struct scmi_handle *handle)
+{
+	struct scmi_info *info;
+
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	if (!handle)
+		return -EINVAL;
+
+	info = handle_to_scmi_info(handle);
+	mutex_lock(&scmi_list_mutex);
+	if (!WARN_ON(!info->users))
+		info->users--;
+	mutex_unlock(&scmi_list_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(scmi_handle_put);
+
+static void devm_scmi_release(struct device *dev, void *res)
+{
+	const struct scmi_handle **ptr = res;
+	const struct scmi_handle *handle = *ptr;
+	int ret;
+
+	ret = scmi_handle_put(handle);
+	if (ret)
+		dev_err(dev, "failed to put handle %d\n", ret);
+}
+
+/**
+ * devm_scmi_handle_get() - Managed get handle
+ * @dev: device for which we want SCMI handle for.
+ *
+ * NOTE: This releases the handle once the device resources are
+ * no longer needed. MUST NOT BE released with scmi_handle_put.
+ * The function does not track individual clients of the framework
+ * and is expected to be maintained by caller of  SCMI protocol library.
+ *
+ * Return: 0 if all went fine, else corresponding error.
+ */
+const struct scmi_handle *devm_scmi_handle_get(struct device *dev)
+{
+	const struct scmi_handle **ptr;
+	const struct scmi_handle *handle;
+
+	ptr = devres_alloc(devm_scmi_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+	handle = scmi_handle_get(dev);
+
+	if (!IS_ERR(handle)) {
+		*ptr = handle;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return handle;
+}
+EXPORT_SYMBOL_GPL(devm_scmi_handle_get);
+
+static const struct scmi_desc scmi_generic_desc = {
+	.max_rx_timeout_ms = 30,	/* we may increase this if required */
+	.max_msg = 20,		/* Limited by MBOX_TX_QUEUE_LEN */
+	.max_msg_size = 128,
+};
+
+/* Each compatible listed below must have descriptor associated with it */
+static const struct of_device_id scmi_of_match[] = {
+	{ .compatible = "arm,scmi", .data = &scmi_generic_desc },
+	{ /* Sentinel */ },
+};
+
+MODULE_DEVICE_TABLE(of, scmi_of_match);
+
+static int scmi_xfer_info_init(struct scmi_info *sinfo)
+{
+	int i;
+	struct scmi_xfer *xfer;
+	struct device *dev = sinfo->dev;
+	const struct scmi_desc *desc = sinfo->desc;
+	struct scmi_xfers_info *info = &sinfo->minfo;
+
+	/* Pre-allocated messages, no more than what hdr.seq can support */
+	if (WARN_ON(desc->max_msg >= (MSG_TOKEN_ID_MASK + 1))) {
+		dev_err(dev, "Maximum message of %d exceeds supported %d\n",
+			desc->max_msg, MSG_TOKEN_ID_MASK + 1);
+		return -EINVAL;
+	}
+
+	info->xfer_block = devm_kcalloc(dev, desc->max_msg,
+					sizeof(*info->xfer_block), GFP_KERNEL);
+	if (!info->xfer_block)
+		return -ENOMEM;
+
+	info->xfer_alloc_table = devm_kcalloc(dev, BITS_TO_LONGS(desc->max_msg),
+					      sizeof(long), GFP_KERNEL);
+	if (!info->xfer_alloc_table)
+		return -ENOMEM;
+
+	bitmap_zero(info->xfer_alloc_table, desc->max_msg);
+
+	/* Pre-initialize the buffer pointer to pre-allocated buffers */
+	for (i = 0, xfer = info->xfer_block; i < desc->max_msg; i++, xfer++) {
+		xfer->rx.buf = devm_kcalloc(dev, sizeof(u8), desc->max_msg_size,
+					    GFP_KERNEL);
+		if (!xfer->rx.buf)
+			return -ENOMEM;
+
+		xfer->tx.buf = xfer->rx.buf;
+		init_completion(&xfer->done);
+	}
+
+	spin_lock_init(&info->xfer_lock);
+
+	sema_init(&info->sem_xfer_count, desc->max_msg);
+
+	return 0;
+}
+
+static int scmi_mailbox_check(struct device_node *np)
+{
+	struct of_phandle_args arg;
+
+	return of_parse_phandle_with_args(np, "mboxes", "#mbox-cells", 0, &arg);
+}
+
+static int scmi_mbox_free_channel(struct scmi_info *info)
+{
+	if (!IS_ERR_OR_NULL(info->tx_chan)) {
+		mbox_free_channel(info->tx_chan);
+		info->tx_chan = NULL;
+	}
+
+	return 0;
+}
+
+static int scmi_remove(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct scmi_info *info = platform_get_drvdata(pdev);
+
+	of_platform_depopulate(&pdev->dev);
+
+	mutex_lock(&scmi_list_mutex);
+	if (info->users)
+		ret = -EBUSY;
+	else
+		list_del(&info->node);
+	mutex_unlock(&scmi_list_mutex);
+
+	if (!ret)
+		/* Safe to free channels since no more users */
+		return scmi_mbox_free_channel(info);
+
+	return ret;
+}
+
+static inline int scmi_mbox_chan_setup(struct scmi_info *info)
+{
+	int ret;
+	struct resource res;
+	resource_size_t size;
+	struct device *dev = info->dev;
+	struct device_node *shmem, *np = dev->of_node;
+	struct mbox_client *cl;
+
+	cl = &info->cl;
+	cl->dev = dev;
+	cl->rx_callback = scmi_rx_callback;
+	cl->tx_prepare = scmi_tx_prepare;
+	cl->tx_block = false;
+	cl->knows_txdone = true;
+
+	shmem = of_parse_phandle(np, "shmem", 0);
+	ret = of_address_to_resource(shmem, 0, &res);
+	of_node_put(shmem);
+	if (ret) {
+		dev_err(dev, "failed to get SCMI Tx payload mem resource\n");
+		return ret;
+	}
+
+	size = resource_size(&res);
+	info->tx_payload = devm_ioremap(dev, res.start, size);
+	if (!info->tx_payload) {
+		dev_err(dev, "failed to ioremap SCMI Tx payload\n");
+		return -EADDRNOTAVAIL;
+	}
+
+	/* Transmit channel is first entry i.e. index 0 */
+	info->tx_chan = mbox_request_channel(cl, 0);
+	if (IS_ERR(info->tx_chan)) {
+		ret = PTR_ERR(info->tx_chan);
+		if (ret != -EPROBE_DEFER)
+			dev_err(dev, "failed to request SCMI Tx mailbox\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int scmi_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct scmi_handle *handle;
+	const struct scmi_desc *desc;
+	struct scmi_info *info;
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+
+	/* Only mailbox method supported, check for the presence of one */
+	if (scmi_mailbox_check(np)) {
+		dev_err(dev, "no mailbox found in %pOF\n", np);
+		return -EINVAL;
+	}
+
+	desc = of_match_device(scmi_of_match, dev)->data;
+
+	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->dev = dev;
+	info->desc = desc;
+	INIT_LIST_HEAD(&info->node);
+
+	ret = scmi_xfer_info_init(info);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, info);
+
+	handle = &info->handle;
+	handle->dev = info->dev;
+
+	ret = scmi_mbox_chan_setup(info);
+	if (ret)
+		return ret;
+
+	mutex_lock(&scmi_list_mutex);
+	list_add_tail(&info->node, &scmi_list);
+	mutex_unlock(&scmi_list_mutex);
+
+	return 0;
+}
+
+static struct platform_driver scmi_driver = {
+	.driver = {
+		   .name = "arm-scmi",
+		   .of_match_table = of_match_ptr(scmi_of_match),
+		   },
+	.probe = scmi_probe,
+	.remove = scmi_remove,
+};
+
+module_platform_driver(scmi_driver);
+
+MODULE_ALIAS("platform: arm-scmi");
+MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
+MODULE_DESCRIPTION("ARM SCMI protocol driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
new file mode 100644
index 000000000000..fbe80fa1ec9f
--- /dev/null
+++ b/include/linux/scmi_protocol.h
@@ -0,0 +1,48 @@
+/*
+ * SCMI Message Protocol driver header
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/types.h>
+
+/**
+ * struct scmi_handle - Handle returned to ARM SCMI clients for usage.
+ *
+ * @dev: pointer to the SCMI device
+ */
+struct scmi_handle {
+	struct device *dev;
+};
+
+#if IS_REACHABLE(CONFIG_ARM_SCMI_PROTOCOL)
+int scmi_handle_put(const struct scmi_handle *handle);
+const struct scmi_handle *scmi_handle_get(struct device *dev);
+const struct scmi_handle *devm_scmi_handle_get(struct device *dev);
+#else
+static inline int scmi_handle_put(const struct scmi_handle *handle)
+{
+	return 0;
+}
+
+static inline const struct scmi_handle *scmi_handle_get(struct device *dev)
+{
+	return NULL;
+}
+
+static inline const struct scmi_handle *devm_scmi_handle_get(struct device *dev)
+{
+	return NULL;
+}
+#endif /* CONFIG_ARM_SCMI_PROTOCOL */
-- 
2.7.4

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

* [PATCH v3 05/22] firmware: arm_scmi: add common infrastructure and support for base protocol
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

The base protocol describes the properties of the implementation and
provide generic error management. The base protocol provides commands
to describe protocol version, discover implementation specific
attributes and vendor/sub-vendor identification, list of protocols
implemented and the various agents are in the system including OSPM
and the platform. It also supports registering for notifications of
platform errors.

This protocol is mandatory. This patch adds support for the same along
with some basic infrastructure to add support for other protocols.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scmi/Makefile |   2 +-
 drivers/firmware/arm_scmi/base.c   | 293 +++++++++++++++++++++++++++++++++++++
 drivers/firmware/arm_scmi/common.h |  46 ++++++
 drivers/firmware/arm_scmi/driver.c |  68 +++++++++
 include/linux/scmi_protocol.h      |  28 ++++
 5 files changed, 436 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/arm_scmi/base.c

diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index 58e94c95e523..21d01d1d6b9c 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_ARM_SCMI_PROTOCOL)	= arm_scmi.o
-arm_scmi-y = driver.o
+arm_scmi-y = base.o driver.o
diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c
new file mode 100644
index 000000000000..2b5fbb724899
--- /dev/null
+++ b/drivers/firmware/arm_scmi/base.c
@@ -0,0 +1,293 @@
+/*
+ * System Control and Management Interface (SCMI) Base Protocol
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "common.h"
+
+enum scmi_base_protocol_cmd {
+	BASE_DISCOVER_VENDOR = 0x3,
+	BASE_DISCOVER_SUB_VENDOR = 0x4,
+	BASE_DISCOVER_IMPLEMENT_VERSION = 0x5,
+	BASE_DISCOVER_LIST_PROTOCOLS = 0x6,
+	BASE_DISCOVER_AGENT = 0x7,
+	BASE_NOTIFY_ERRORS = 0x8,
+};
+
+struct scmi_msg_resp_base_attributes {
+	    u8 num_protocols;
+	    u8 num_agents;
+	__le16 reserved;
+};
+
+/**
+ * scmi_base_attributes_get() - gets the implementation details
+ *	that are associated with the base protocol.
+ *
+ * @handle - SCMI entity handle
+ *
+ * Return: 0 on success, else appropriate SCMI error.
+ */
+static int scmi_base_attributes_get(const struct scmi_handle *handle)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_msg_resp_base_attributes *attr_info;
+	struct scmi_revision_info *rev = handle->version;
+
+	ret = scmi_one_xfer_init(handle, PROTOCOL_ATTRIBUTES,
+				 SCMI_PROTOCOL_BASE, 0, sizeof(*attr_info), &t);
+	if (ret)
+		return ret;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		attr_info = t->rx.buf;
+		rev->num_protocols = attr_info->num_protocols;
+		rev->num_agents = attr_info->num_agents;
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+/**
+ * scmi_base_vendor_id_get() - gets vendor/subvendor identifier ASCII string.
+ *
+ * @handle - SCMI entity handle
+ * @sub_vendor - specify true if sub-vendor ID is needed
+ *
+ * Return: 0 on success, else appropriate SCMI error.
+ */
+static int
+scmi_base_vendor_id_get(const struct scmi_handle *handle, bool sub_vendor)
+{
+	u8 cmd;
+	int ret, size;
+	char *vendor_id;
+	struct scmi_xfer *t;
+	struct scmi_revision_info *rev = handle->version;
+
+	if (sub_vendor) {
+		cmd = BASE_DISCOVER_SUB_VENDOR;
+		vendor_id = rev->sub_vendor_id;
+		size = ARRAY_SIZE(rev->sub_vendor_id);
+	} else {
+		cmd = BASE_DISCOVER_VENDOR;
+		vendor_id = rev->vendor_id;
+		size = ARRAY_SIZE(rev->vendor_id);
+	}
+
+	ret = scmi_one_xfer_init(handle, cmd, SCMI_PROTOCOL_BASE, 0, size, &t);
+	if (ret)
+		return ret;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret)
+		memcpy(vendor_id, t->rx.buf, size);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+/**
+ * scmi_base_implementation_version_get() - gets a vendor-specific
+ *	implementation 32-bit version. The format of the version number is
+ *	vendor-specific
+ *
+ * @handle - SCMI entity handle
+ *
+ * Return: 0 on success, else appropriate SCMI error.
+ */
+static int
+scmi_base_implementation_version_get(const struct scmi_handle *handle)
+{
+	int ret;
+	__le32 *impl_ver;
+	struct scmi_xfer *t;
+	struct scmi_revision_info *rev = handle->version;
+
+	ret = scmi_one_xfer_init(handle, BASE_DISCOVER_IMPLEMENT_VERSION,
+				 SCMI_PROTOCOL_BASE, 0, sizeof(*impl_ver), &t);
+	if (ret)
+		return ret;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		impl_ver = t->rx.buf;
+		rev->impl_ver = le32_to_cpu(*impl_ver);
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+/**
+ * scmi_base_implementation_list_get() - gets the list of protocols it is
+ *	OSPM is allowed to access
+ *
+ * @handle - SCMI entity handle
+ * @protocols_imp - pointer to hold the list of protocol identifiers
+ *
+ * Return: 0 on success, else appropriate SCMI error.
+ */
+static int scmi_base_implementation_list_get(const struct scmi_handle *handle,
+					     u8 *protocols_imp)
+{
+	u8 *list;
+	int ret, loop;
+	struct scmi_xfer *t;
+	__le32 *num_skip, *num_ret;
+	u32 tot_num_ret = 0, loop_num_ret;
+	struct device *dev = handle->dev;
+
+	ret = scmi_one_xfer_init(handle, BASE_DISCOVER_LIST_PROTOCOLS,
+				 SCMI_PROTOCOL_BASE, sizeof(*num_skip), 0, &t);
+	if (ret)
+		return ret;
+
+	num_skip = t->tx.buf;
+	num_ret = t->rx.buf;
+	list = t->rx.buf + sizeof(*num_ret);
+
+	do {
+		/* Set the number of protocols to be skipped/already read */
+		*num_skip = cpu_to_le32(tot_num_ret);
+
+		ret = scmi_do_xfer(handle, t);
+		if (ret)
+			break;
+
+		loop_num_ret = le32_to_cpu(*num_ret);
+		if (tot_num_ret + loop_num_ret > MAX_PROTOCOLS_IMP) {
+			dev_err(dev, "No. of Protocol > MAX_PROTOCOLS_IMP");
+			break;
+		}
+
+		for (loop = 0; loop < loop_num_ret; loop++)
+			protocols_imp[tot_num_ret + loop] = *(list + loop);
+
+		tot_num_ret += loop_num_ret;
+	} while (loop_num_ret);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+/**
+ * scmi_base_discover_agent_get() - discover the name of an agent
+ *
+ * @handle - SCMI entity handle
+ * @id - Agent identifier
+ * @name - Agent identifier ASCII string
+ *
+ * An agent id of 0 is reserved to identify the platform itself.
+ * Generally operating system is represented as "OSPM"
+ *
+ * Return: 0 on success, else appropriate SCMI error.
+ */
+static int scmi_base_discover_agent_get(const struct scmi_handle *handle,
+					int id, char *name)
+{
+	int ret;
+	struct scmi_xfer *t;
+
+	ret = scmi_one_xfer_init(handle, BASE_DISCOVER_AGENT,
+				 SCMI_PROTOCOL_BASE, sizeof(__le32),
+				 SCMI_MAX_STR_SIZE, &t);
+	if (ret)
+		return ret;
+
+	*(__le32 *)t->tx.buf = cpu_to_le32(id);
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret)
+		memcpy(name, t->rx.buf, SCMI_MAX_STR_SIZE);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+/**
+ * scmi_base_error_notifications_enable() - register/unregister for
+ *	notifications of errors in the platform
+ *
+ * @handle - SCMI entity handle
+ * @enable - Enable/Disable the notification
+ *
+ * Return: 0 on success, else appropriate SCMI error.
+ */
+static int
+scmi_base_error_notifications_enable(const struct scmi_handle *handle, bool en)
+{
+	int ret;
+	struct scmi_xfer *t;
+
+	ret = scmi_one_xfer_init(handle, BASE_NOTIFY_ERRORS, SCMI_PROTOCOL_BASE,
+				 sizeof(__le32), 0, &t);
+	if (ret)
+		return ret;
+
+	*(__le32 *)t->tx.buf = cpu_to_le32(en & BIT(0));
+
+	ret = scmi_do_xfer(handle, t);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+int scmi_base_protocol_init(struct scmi_handle *h)
+{
+	int id, ret;
+	u8 *prot_imp;
+	u32 version;
+	char name[SCMI_MAX_STR_SIZE];
+	const struct scmi_handle *handle = h;
+	struct device *dev = handle->dev;
+	struct scmi_revision_info *rev = handle->version;
+
+	ret = scmi_version_get(handle, SCMI_PROTOCOL_BASE, &version);
+	if (ret)
+		return ret;
+
+	prot_imp = devm_kcalloc(dev, MAX_PROTOCOLS_IMP, sizeof(u8), GFP_KERNEL);
+	if (!prot_imp)
+		return -ENOMEM;
+
+	rev->major_ver = PROTOCOL_REV_MAJOR(version),
+	rev->minor_ver = PROTOCOL_REV_MINOR(version);
+
+	scmi_base_attributes_get(handle);
+	scmi_base_vendor_id_get(handle, false);
+	scmi_base_vendor_id_get(handle, true);
+	scmi_base_implementation_version_get(handle);
+	scmi_base_implementation_list_get(handle, prot_imp);
+	scmi_base_error_notifications_enable(handle, true);
+	scmi_setup_protocol_implemented(handle, prot_imp);
+
+	dev_info(dev, "SCMI Protocol v%d.%d '%s:%s' Firmware version 0x%x\n",
+		 rev->major_ver, rev->minor_ver, rev->vendor_id,
+		 rev->sub_vendor_id, rev->impl_ver);
+	dev_dbg(dev, "Found %d protocol(s) %d agent(s)\n", rev->num_protocols,
+		rev->num_agents);
+
+	for (id = 0; id < rev->num_agents; id++) {
+		scmi_base_discover_agent_get(handle, id, name);
+		dev_dbg(dev, "Agent %d: %s\n", id, name);
+	}
+
+	return 0;
+}
diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index 344b234d4e64..7a30a517a10b 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -19,9 +19,50 @@
  */
 
 #include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
 #include <linux/scmi_protocol.h>
 #include <linux/types.h>
 
+#define PROTOCOL_REV_MINOR_BITS	16
+#define PROTOCOL_REV_MINOR_MASK	((1U << PROTOCOL_REV_MINOR_BITS) - 1)
+#define PROTOCOL_REV_MAJOR(x)	((x) >> PROTOCOL_REV_MINOR_BITS)
+#define PROTOCOL_REV_MINOR(x)	((x) & PROTOCOL_REV_MINOR_MASK)
+#define MAX_PROTOCOLS_IMP	16
+
+enum scmi_std_protocol {
+	SCMI_PROTOCOL_BASE = 0x10,
+	SCMI_PROTOCOL_POWER = 0x11,
+	SCMI_PROTOCOL_SYSTEM = 0x12,
+	SCMI_PROTOCOL_PERF = 0x13,
+	SCMI_PROTOCOL_CLOCK = 0x14,
+	SCMI_PROTOCOL_SENSOR = 0x15,
+};
+
+enum scmi_common_cmd {
+	PROTOCOL_VERSION = 0x0,
+	PROTOCOL_ATTRIBUTES = 0x1,
+	PROTOCOL_MESSAGE_ATTRIBUTES = 0x2,
+};
+
+/**
+ * struct scmi_msg_resp_prot_version - Response for a message
+ *
+ * @major_version: Major version of the ABI that firmware supports
+ * @minor_version: Minor version of the ABI that firmware supports
+ *
+ * In general, ABI version changes follow the rule that minor version increments
+ * are backward compatible. Major revision changes in ABI may not be
+ * backward compatible.
+ *
+ * Response to a generic message with message type SCMI_MSG_VERSION
+ */
+struct scmi_msg_resp_prot_version {
+	__le16 minor_version;
+	__le16 major_version;
+};
+
 /**
  * struct scmi_msg_hdr - Message(Tx/Rx) header
  *
@@ -73,3 +114,8 @@ void scmi_one_xfer_put(const struct scmi_handle *h, struct scmi_xfer *xfer);
 int scmi_do_xfer(const struct scmi_handle *h, struct scmi_xfer *xfer);
 int scmi_one_xfer_init(const struct scmi_handle *h, u8 msg_id, u8 prot_id,
 		       size_t tx_size, size_t rx_size, struct scmi_xfer **p);
+int scmi_version_get(const struct scmi_handle *h, u8 protocol, u32 *version);
+void scmi_setup_protocol_implemented(const struct scmi_handle *handle,
+				     u8 *prot_imp);
+
+int scmi_base_protocol_init(struct scmi_handle *h);
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 1d556a928de9..5df76512a291 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -108,21 +108,27 @@ struct scmi_desc {
  * @dev: Device pointer
  * @desc: SoC description for this instance
  * @handle: Instance of SCMI handle to send to clients
+ * @version: SCMI revision information containing protocol version,
+ *	implementation version and (sub-)vendor identification.
  * @cl: Mailbox Client
  * @tx_chan: Transmit mailbox channel
  * @tx_payload: Transmit mailbox channel payload area
  * @minfo: Message info
+ * @protocols_imp: list of protocols implemented, currently maximum of
+ *	MAX_PROTOCOLS_IMP elements allocated by the base protocol
  * @node: list head
  * @users: Number of users of this instance
  */
 struct scmi_info {
 	struct device *dev;
 	const struct scmi_desc *desc;
+	struct scmi_revision_info version;
 	struct scmi_handle handle;
 	struct mbox_client cl;
 	struct mbox_chan *tx_chan;
 	void __iomem *tx_payload;
 	struct scmi_xfers_info minfo;
+	u8 *protocols_imp;
 	struct list_head node;
 	int users;
 };
@@ -450,6 +456,60 @@ int scmi_one_xfer_init(const struct scmi_handle *handle, u8 msg_id, u8 prot_id,
 }
 
 /**
+ * scmi_version_get() - command to get the revision of the SCMI entity
+ *
+ * @handle: Handle to SCMI entity information
+ *
+ * Updates the SCMI information in the internal data structure.
+ *
+ * Return: 0 if all went fine, else return appropriate error.
+ */
+int scmi_version_get(const struct scmi_handle *handle, u8 protocol,
+		     u32 *version)
+{
+	int ret;
+	__le32 *rev_info;
+	struct scmi_xfer *t;
+
+	ret = scmi_one_xfer_init(handle, PROTOCOL_VERSION, protocol, 0,
+				 sizeof(*version), &t);
+	if (ret)
+		return ret;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		rev_info = t->rx.buf;
+		*version = le32_to_cpu(*rev_info);
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+void scmi_setup_protocol_implemented(const struct scmi_handle *handle,
+				     u8 *prot_imp)
+{
+	struct scmi_info *info = handle_to_scmi_info(handle);
+
+	info->protocols_imp = prot_imp;
+}
+
+static bool
+scmi_is_protocol_implemented(const struct scmi_handle *handle, u8 prot_id)
+{
+	int i;
+	struct scmi_info *info = handle_to_scmi_info(handle);
+
+	if (!info->protocols_imp)
+		return false;
+
+	for (i = 0; i < MAX_PROTOCOLS_IMP; i++)
+		if (info->protocols_imp[i] == prot_id)
+			return true;
+	return false;
+}
+
+/**
  * scmi_handle_get() - Get the  SCMI handle for a device
  *
  * @dev: pointer to device for which we want SCMI handle
@@ -740,11 +800,19 @@ static int scmi_probe(struct platform_device *pdev)
 
 	handle = &info->handle;
 	handle->dev = info->dev;
+	handle->version = &info->version;
 
 	ret = scmi_mbox_chan_setup(info);
 	if (ret)
 		return ret;
 
+	ret = scmi_base_protocol_init(handle);
+	if (ret) {
+		dev_err(dev, "unable to communicate with SCMI(%d)\n", ret);
+		scmi_mbox_free_channel(info);
+		return ret;
+	}
+
 	mutex_lock(&scmi_list_mutex);
 	list_add_tail(&info->node, &scmi_list);
 	mutex_unlock(&scmi_list_mutex);
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index fbe80fa1ec9f..3ef2d48f03c2 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -17,13 +17,41 @@
  */
 #include <linux/types.h>
 
+#define SCMI_MAX_STR_SIZE	16
+
+/**
+ * struct scmi_revision_info - version information structure
+ *
+ * @major_ver: Major ABI version. Change here implies risk of backward
+ *	compatibility break.
+ * @minor_ver: Minor ABI version. Change here implies new feature addition,
+ *	or compatible change in ABI.
+ * @num_protocols: Number of protocols that are implemented, excluding the
+ *	base protocol.
+ * @num_agents: Number of agents in the system.
+ * @impl_ver: A vendor-specific implementation version.
+ * @vendor_id: A vendor identifier(Null terminated ASCII string)
+ * @sub_vendor_id: A sub-vendor identifier(Null terminated ASCII string)
+ */
+struct scmi_revision_info {
+	u16 major_ver;
+	u16 minor_ver;
+	u8 num_protocols;
+	u8 num_agents;
+	u32 impl_ver;
+	char vendor_id[SCMI_MAX_STR_SIZE];
+	char sub_vendor_id[SCMI_MAX_STR_SIZE];
+};
+
 /**
  * struct scmi_handle - Handle returned to ARM SCMI clients for usage.
  *
  * @dev: pointer to the SCMI device
+ * @version: pointer to the structure containing SCMI version information
  */
 struct scmi_handle {
 	struct device *dev;
+	struct scmi_revision_info *version;
 };
 
 #if IS_REACHABLE(CONFIG_ARM_SCMI_PROTOCOL)
-- 
2.7.4

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

* [PATCH v3 05/22] firmware: arm_scmi: add common infrastructure and support for base protocol
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

The base protocol describes the properties of the implementation and
provide generic error management. The base protocol provides commands
to describe protocol version, discover implementation specific
attributes and vendor/sub-vendor identification, list of protocols
implemented and the various agents are in the system including OSPM
and the platform. It also supports registering for notifications of
platform errors.

This protocol is mandatory. This patch adds support for the same along
with some basic infrastructure to add support for other protocols.

Cc: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
Signed-off-by: Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org>
---
 drivers/firmware/arm_scmi/Makefile |   2 +-
 drivers/firmware/arm_scmi/base.c   | 293 +++++++++++++++++++++++++++++++++++++
 drivers/firmware/arm_scmi/common.h |  46 ++++++
 drivers/firmware/arm_scmi/driver.c |  68 +++++++++
 include/linux/scmi_protocol.h      |  28 ++++
 5 files changed, 436 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/arm_scmi/base.c

diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index 58e94c95e523..21d01d1d6b9c 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_ARM_SCMI_PROTOCOL)	= arm_scmi.o
-arm_scmi-y = driver.o
+arm_scmi-y = base.o driver.o
diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c
new file mode 100644
index 000000000000..2b5fbb724899
--- /dev/null
+++ b/drivers/firmware/arm_scmi/base.c
@@ -0,0 +1,293 @@
+/*
+ * System Control and Management Interface (SCMI) Base Protocol
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "common.h"
+
+enum scmi_base_protocol_cmd {
+	BASE_DISCOVER_VENDOR = 0x3,
+	BASE_DISCOVER_SUB_VENDOR = 0x4,
+	BASE_DISCOVER_IMPLEMENT_VERSION = 0x5,
+	BASE_DISCOVER_LIST_PROTOCOLS = 0x6,
+	BASE_DISCOVER_AGENT = 0x7,
+	BASE_NOTIFY_ERRORS = 0x8,
+};
+
+struct scmi_msg_resp_base_attributes {
+	    u8 num_protocols;
+	    u8 num_agents;
+	__le16 reserved;
+};
+
+/**
+ * scmi_base_attributes_get() - gets the implementation details
+ *	that are associated with the base protocol.
+ *
+ * @handle - SCMI entity handle
+ *
+ * Return: 0 on success, else appropriate SCMI error.
+ */
+static int scmi_base_attributes_get(const struct scmi_handle *handle)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_msg_resp_base_attributes *attr_info;
+	struct scmi_revision_info *rev = handle->version;
+
+	ret = scmi_one_xfer_init(handle, PROTOCOL_ATTRIBUTES,
+				 SCMI_PROTOCOL_BASE, 0, sizeof(*attr_info), &t);
+	if (ret)
+		return ret;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		attr_info = t->rx.buf;
+		rev->num_protocols = attr_info->num_protocols;
+		rev->num_agents = attr_info->num_agents;
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+/**
+ * scmi_base_vendor_id_get() - gets vendor/subvendor identifier ASCII string.
+ *
+ * @handle - SCMI entity handle
+ * @sub_vendor - specify true if sub-vendor ID is needed
+ *
+ * Return: 0 on success, else appropriate SCMI error.
+ */
+static int
+scmi_base_vendor_id_get(const struct scmi_handle *handle, bool sub_vendor)
+{
+	u8 cmd;
+	int ret, size;
+	char *vendor_id;
+	struct scmi_xfer *t;
+	struct scmi_revision_info *rev = handle->version;
+
+	if (sub_vendor) {
+		cmd = BASE_DISCOVER_SUB_VENDOR;
+		vendor_id = rev->sub_vendor_id;
+		size = ARRAY_SIZE(rev->sub_vendor_id);
+	} else {
+		cmd = BASE_DISCOVER_VENDOR;
+		vendor_id = rev->vendor_id;
+		size = ARRAY_SIZE(rev->vendor_id);
+	}
+
+	ret = scmi_one_xfer_init(handle, cmd, SCMI_PROTOCOL_BASE, 0, size, &t);
+	if (ret)
+		return ret;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret)
+		memcpy(vendor_id, t->rx.buf, size);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+/**
+ * scmi_base_implementation_version_get() - gets a vendor-specific
+ *	implementation 32-bit version. The format of the version number is
+ *	vendor-specific
+ *
+ * @handle - SCMI entity handle
+ *
+ * Return: 0 on success, else appropriate SCMI error.
+ */
+static int
+scmi_base_implementation_version_get(const struct scmi_handle *handle)
+{
+	int ret;
+	__le32 *impl_ver;
+	struct scmi_xfer *t;
+	struct scmi_revision_info *rev = handle->version;
+
+	ret = scmi_one_xfer_init(handle, BASE_DISCOVER_IMPLEMENT_VERSION,
+				 SCMI_PROTOCOL_BASE, 0, sizeof(*impl_ver), &t);
+	if (ret)
+		return ret;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		impl_ver = t->rx.buf;
+		rev->impl_ver = le32_to_cpu(*impl_ver);
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+/**
+ * scmi_base_implementation_list_get() - gets the list of protocols it is
+ *	OSPM is allowed to access
+ *
+ * @handle - SCMI entity handle
+ * @protocols_imp - pointer to hold the list of protocol identifiers
+ *
+ * Return: 0 on success, else appropriate SCMI error.
+ */
+static int scmi_base_implementation_list_get(const struct scmi_handle *handle,
+					     u8 *protocols_imp)
+{
+	u8 *list;
+	int ret, loop;
+	struct scmi_xfer *t;
+	__le32 *num_skip, *num_ret;
+	u32 tot_num_ret = 0, loop_num_ret;
+	struct device *dev = handle->dev;
+
+	ret = scmi_one_xfer_init(handle, BASE_DISCOVER_LIST_PROTOCOLS,
+				 SCMI_PROTOCOL_BASE, sizeof(*num_skip), 0, &t);
+	if (ret)
+		return ret;
+
+	num_skip = t->tx.buf;
+	num_ret = t->rx.buf;
+	list = t->rx.buf + sizeof(*num_ret);
+
+	do {
+		/* Set the number of protocols to be skipped/already read */
+		*num_skip = cpu_to_le32(tot_num_ret);
+
+		ret = scmi_do_xfer(handle, t);
+		if (ret)
+			break;
+
+		loop_num_ret = le32_to_cpu(*num_ret);
+		if (tot_num_ret + loop_num_ret > MAX_PROTOCOLS_IMP) {
+			dev_err(dev, "No. of Protocol > MAX_PROTOCOLS_IMP");
+			break;
+		}
+
+		for (loop = 0; loop < loop_num_ret; loop++)
+			protocols_imp[tot_num_ret + loop] = *(list + loop);
+
+		tot_num_ret += loop_num_ret;
+	} while (loop_num_ret);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+/**
+ * scmi_base_discover_agent_get() - discover the name of an agent
+ *
+ * @handle - SCMI entity handle
+ * @id - Agent identifier
+ * @name - Agent identifier ASCII string
+ *
+ * An agent id of 0 is reserved to identify the platform itself.
+ * Generally operating system is represented as "OSPM"
+ *
+ * Return: 0 on success, else appropriate SCMI error.
+ */
+static int scmi_base_discover_agent_get(const struct scmi_handle *handle,
+					int id, char *name)
+{
+	int ret;
+	struct scmi_xfer *t;
+
+	ret = scmi_one_xfer_init(handle, BASE_DISCOVER_AGENT,
+				 SCMI_PROTOCOL_BASE, sizeof(__le32),
+				 SCMI_MAX_STR_SIZE, &t);
+	if (ret)
+		return ret;
+
+	*(__le32 *)t->tx.buf = cpu_to_le32(id);
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret)
+		memcpy(name, t->rx.buf, SCMI_MAX_STR_SIZE);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+/**
+ * scmi_base_error_notifications_enable() - register/unregister for
+ *	notifications of errors in the platform
+ *
+ * @handle - SCMI entity handle
+ * @enable - Enable/Disable the notification
+ *
+ * Return: 0 on success, else appropriate SCMI error.
+ */
+static int
+scmi_base_error_notifications_enable(const struct scmi_handle *handle, bool en)
+{
+	int ret;
+	struct scmi_xfer *t;
+
+	ret = scmi_one_xfer_init(handle, BASE_NOTIFY_ERRORS, SCMI_PROTOCOL_BASE,
+				 sizeof(__le32), 0, &t);
+	if (ret)
+		return ret;
+
+	*(__le32 *)t->tx.buf = cpu_to_le32(en & BIT(0));
+
+	ret = scmi_do_xfer(handle, t);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+int scmi_base_protocol_init(struct scmi_handle *h)
+{
+	int id, ret;
+	u8 *prot_imp;
+	u32 version;
+	char name[SCMI_MAX_STR_SIZE];
+	const struct scmi_handle *handle = h;
+	struct device *dev = handle->dev;
+	struct scmi_revision_info *rev = handle->version;
+
+	ret = scmi_version_get(handle, SCMI_PROTOCOL_BASE, &version);
+	if (ret)
+		return ret;
+
+	prot_imp = devm_kcalloc(dev, MAX_PROTOCOLS_IMP, sizeof(u8), GFP_KERNEL);
+	if (!prot_imp)
+		return -ENOMEM;
+
+	rev->major_ver = PROTOCOL_REV_MAJOR(version),
+	rev->minor_ver = PROTOCOL_REV_MINOR(version);
+
+	scmi_base_attributes_get(handle);
+	scmi_base_vendor_id_get(handle, false);
+	scmi_base_vendor_id_get(handle, true);
+	scmi_base_implementation_version_get(handle);
+	scmi_base_implementation_list_get(handle, prot_imp);
+	scmi_base_error_notifications_enable(handle, true);
+	scmi_setup_protocol_implemented(handle, prot_imp);
+
+	dev_info(dev, "SCMI Protocol v%d.%d '%s:%s' Firmware version 0x%x\n",
+		 rev->major_ver, rev->minor_ver, rev->vendor_id,
+		 rev->sub_vendor_id, rev->impl_ver);
+	dev_dbg(dev, "Found %d protocol(s) %d agent(s)\n", rev->num_protocols,
+		rev->num_agents);
+
+	for (id = 0; id < rev->num_agents; id++) {
+		scmi_base_discover_agent_get(handle, id, name);
+		dev_dbg(dev, "Agent %d: %s\n", id, name);
+	}
+
+	return 0;
+}
diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index 344b234d4e64..7a30a517a10b 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -19,9 +19,50 @@
  */
 
 #include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
 #include <linux/scmi_protocol.h>
 #include <linux/types.h>
 
+#define PROTOCOL_REV_MINOR_BITS	16
+#define PROTOCOL_REV_MINOR_MASK	((1U << PROTOCOL_REV_MINOR_BITS) - 1)
+#define PROTOCOL_REV_MAJOR(x)	((x) >> PROTOCOL_REV_MINOR_BITS)
+#define PROTOCOL_REV_MINOR(x)	((x) & PROTOCOL_REV_MINOR_MASK)
+#define MAX_PROTOCOLS_IMP	16
+
+enum scmi_std_protocol {
+	SCMI_PROTOCOL_BASE = 0x10,
+	SCMI_PROTOCOL_POWER = 0x11,
+	SCMI_PROTOCOL_SYSTEM = 0x12,
+	SCMI_PROTOCOL_PERF = 0x13,
+	SCMI_PROTOCOL_CLOCK = 0x14,
+	SCMI_PROTOCOL_SENSOR = 0x15,
+};
+
+enum scmi_common_cmd {
+	PROTOCOL_VERSION = 0x0,
+	PROTOCOL_ATTRIBUTES = 0x1,
+	PROTOCOL_MESSAGE_ATTRIBUTES = 0x2,
+};
+
+/**
+ * struct scmi_msg_resp_prot_version - Response for a message
+ *
+ * @major_version: Major version of the ABI that firmware supports
+ * @minor_version: Minor version of the ABI that firmware supports
+ *
+ * In general, ABI version changes follow the rule that minor version increments
+ * are backward compatible. Major revision changes in ABI may not be
+ * backward compatible.
+ *
+ * Response to a generic message with message type SCMI_MSG_VERSION
+ */
+struct scmi_msg_resp_prot_version {
+	__le16 minor_version;
+	__le16 major_version;
+};
+
 /**
  * struct scmi_msg_hdr - Message(Tx/Rx) header
  *
@@ -73,3 +114,8 @@ void scmi_one_xfer_put(const struct scmi_handle *h, struct scmi_xfer *xfer);
 int scmi_do_xfer(const struct scmi_handle *h, struct scmi_xfer *xfer);
 int scmi_one_xfer_init(const struct scmi_handle *h, u8 msg_id, u8 prot_id,
 		       size_t tx_size, size_t rx_size, struct scmi_xfer **p);
+int scmi_version_get(const struct scmi_handle *h, u8 protocol, u32 *version);
+void scmi_setup_protocol_implemented(const struct scmi_handle *handle,
+				     u8 *prot_imp);
+
+int scmi_base_protocol_init(struct scmi_handle *h);
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 1d556a928de9..5df76512a291 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -108,21 +108,27 @@ struct scmi_desc {
  * @dev: Device pointer
  * @desc: SoC description for this instance
  * @handle: Instance of SCMI handle to send to clients
+ * @version: SCMI revision information containing protocol version,
+ *	implementation version and (sub-)vendor identification.
  * @cl: Mailbox Client
  * @tx_chan: Transmit mailbox channel
  * @tx_payload: Transmit mailbox channel payload area
  * @minfo: Message info
+ * @protocols_imp: list of protocols implemented, currently maximum of
+ *	MAX_PROTOCOLS_IMP elements allocated by the base protocol
  * @node: list head
  * @users: Number of users of this instance
  */
 struct scmi_info {
 	struct device *dev;
 	const struct scmi_desc *desc;
+	struct scmi_revision_info version;
 	struct scmi_handle handle;
 	struct mbox_client cl;
 	struct mbox_chan *tx_chan;
 	void __iomem *tx_payload;
 	struct scmi_xfers_info minfo;
+	u8 *protocols_imp;
 	struct list_head node;
 	int users;
 };
@@ -450,6 +456,60 @@ int scmi_one_xfer_init(const struct scmi_handle *handle, u8 msg_id, u8 prot_id,
 }
 
 /**
+ * scmi_version_get() - command to get the revision of the SCMI entity
+ *
+ * @handle: Handle to SCMI entity information
+ *
+ * Updates the SCMI information in the internal data structure.
+ *
+ * Return: 0 if all went fine, else return appropriate error.
+ */
+int scmi_version_get(const struct scmi_handle *handle, u8 protocol,
+		     u32 *version)
+{
+	int ret;
+	__le32 *rev_info;
+	struct scmi_xfer *t;
+
+	ret = scmi_one_xfer_init(handle, PROTOCOL_VERSION, protocol, 0,
+				 sizeof(*version), &t);
+	if (ret)
+		return ret;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		rev_info = t->rx.buf;
+		*version = le32_to_cpu(*rev_info);
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+void scmi_setup_protocol_implemented(const struct scmi_handle *handle,
+				     u8 *prot_imp)
+{
+	struct scmi_info *info = handle_to_scmi_info(handle);
+
+	info->protocols_imp = prot_imp;
+}
+
+static bool
+scmi_is_protocol_implemented(const struct scmi_handle *handle, u8 prot_id)
+{
+	int i;
+	struct scmi_info *info = handle_to_scmi_info(handle);
+
+	if (!info->protocols_imp)
+		return false;
+
+	for (i = 0; i < MAX_PROTOCOLS_IMP; i++)
+		if (info->protocols_imp[i] == prot_id)
+			return true;
+	return false;
+}
+
+/**
  * scmi_handle_get() - Get the  SCMI handle for a device
  *
  * @dev: pointer to device for which we want SCMI handle
@@ -740,11 +800,19 @@ static int scmi_probe(struct platform_device *pdev)
 
 	handle = &info->handle;
 	handle->dev = info->dev;
+	handle->version = &info->version;
 
 	ret = scmi_mbox_chan_setup(info);
 	if (ret)
 		return ret;
 
+	ret = scmi_base_protocol_init(handle);
+	if (ret) {
+		dev_err(dev, "unable to communicate with SCMI(%d)\n", ret);
+		scmi_mbox_free_channel(info);
+		return ret;
+	}
+
 	mutex_lock(&scmi_list_mutex);
 	list_add_tail(&info->node, &scmi_list);
 	mutex_unlock(&scmi_list_mutex);
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index fbe80fa1ec9f..3ef2d48f03c2 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -17,13 +17,41 @@
  */
 #include <linux/types.h>
 
+#define SCMI_MAX_STR_SIZE	16
+
+/**
+ * struct scmi_revision_info - version information structure
+ *
+ * @major_ver: Major ABI version. Change here implies risk of backward
+ *	compatibility break.
+ * @minor_ver: Minor ABI version. Change here implies new feature addition,
+ *	or compatible change in ABI.
+ * @num_protocols: Number of protocols that are implemented, excluding the
+ *	base protocol.
+ * @num_agents: Number of agents in the system.
+ * @impl_ver: A vendor-specific implementation version.
+ * @vendor_id: A vendor identifier(Null terminated ASCII string)
+ * @sub_vendor_id: A sub-vendor identifier(Null terminated ASCII string)
+ */
+struct scmi_revision_info {
+	u16 major_ver;
+	u16 minor_ver;
+	u8 num_protocols;
+	u8 num_agents;
+	u32 impl_ver;
+	char vendor_id[SCMI_MAX_STR_SIZE];
+	char sub_vendor_id[SCMI_MAX_STR_SIZE];
+};
+
 /**
  * struct scmi_handle - Handle returned to ARM SCMI clients for usage.
  *
  * @dev: pointer to the SCMI device
+ * @version: pointer to the structure containing SCMI version information
  */
 struct scmi_handle {
 	struct device *dev;
+	struct scmi_revision_info *version;
 };
 
 #if IS_REACHABLE(CONFIG_ARM_SCMI_PROTOCOL)
-- 
2.7.4

--
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] 208+ messages in thread

* [PATCH v3 05/22] firmware: arm_scmi: add common infrastructure and support for base protocol
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

The base protocol describes the properties of the implementation and
provide generic error management. The base protocol provides commands
to describe protocol version, discover implementation specific
attributes and vendor/sub-vendor identification, list of protocols
implemented and the various agents are in the system including OSPM
and the platform. It also supports registering for notifications of
platform errors.

This protocol is mandatory. This patch adds support for the same along
with some basic infrastructure to add support for other protocols.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scmi/Makefile |   2 +-
 drivers/firmware/arm_scmi/base.c   | 293 +++++++++++++++++++++++++++++++++++++
 drivers/firmware/arm_scmi/common.h |  46 ++++++
 drivers/firmware/arm_scmi/driver.c |  68 +++++++++
 include/linux/scmi_protocol.h      |  28 ++++
 5 files changed, 436 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/arm_scmi/base.c

diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index 58e94c95e523..21d01d1d6b9c 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_ARM_SCMI_PROTOCOL)	= arm_scmi.o
-arm_scmi-y = driver.o
+arm_scmi-y = base.o driver.o
diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c
new file mode 100644
index 000000000000..2b5fbb724899
--- /dev/null
+++ b/drivers/firmware/arm_scmi/base.c
@@ -0,0 +1,293 @@
+/*
+ * System Control and Management Interface (SCMI) Base Protocol
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "common.h"
+
+enum scmi_base_protocol_cmd {
+	BASE_DISCOVER_VENDOR = 0x3,
+	BASE_DISCOVER_SUB_VENDOR = 0x4,
+	BASE_DISCOVER_IMPLEMENT_VERSION = 0x5,
+	BASE_DISCOVER_LIST_PROTOCOLS = 0x6,
+	BASE_DISCOVER_AGENT = 0x7,
+	BASE_NOTIFY_ERRORS = 0x8,
+};
+
+struct scmi_msg_resp_base_attributes {
+	    u8 num_protocols;
+	    u8 num_agents;
+	__le16 reserved;
+};
+
+/**
+ * scmi_base_attributes_get() - gets the implementation details
+ *	that are associated with the base protocol.
+ *
+ * @handle - SCMI entity handle
+ *
+ * Return: 0 on success, else appropriate SCMI error.
+ */
+static int scmi_base_attributes_get(const struct scmi_handle *handle)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_msg_resp_base_attributes *attr_info;
+	struct scmi_revision_info *rev = handle->version;
+
+	ret = scmi_one_xfer_init(handle, PROTOCOL_ATTRIBUTES,
+				 SCMI_PROTOCOL_BASE, 0, sizeof(*attr_info), &t);
+	if (ret)
+		return ret;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		attr_info = t->rx.buf;
+		rev->num_protocols = attr_info->num_protocols;
+		rev->num_agents = attr_info->num_agents;
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+/**
+ * scmi_base_vendor_id_get() - gets vendor/subvendor identifier ASCII string.
+ *
+ * @handle - SCMI entity handle
+ * @sub_vendor - specify true if sub-vendor ID is needed
+ *
+ * Return: 0 on success, else appropriate SCMI error.
+ */
+static int
+scmi_base_vendor_id_get(const struct scmi_handle *handle, bool sub_vendor)
+{
+	u8 cmd;
+	int ret, size;
+	char *vendor_id;
+	struct scmi_xfer *t;
+	struct scmi_revision_info *rev = handle->version;
+
+	if (sub_vendor) {
+		cmd = BASE_DISCOVER_SUB_VENDOR;
+		vendor_id = rev->sub_vendor_id;
+		size = ARRAY_SIZE(rev->sub_vendor_id);
+	} else {
+		cmd = BASE_DISCOVER_VENDOR;
+		vendor_id = rev->vendor_id;
+		size = ARRAY_SIZE(rev->vendor_id);
+	}
+
+	ret = scmi_one_xfer_init(handle, cmd, SCMI_PROTOCOL_BASE, 0, size, &t);
+	if (ret)
+		return ret;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret)
+		memcpy(vendor_id, t->rx.buf, size);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+/**
+ * scmi_base_implementation_version_get() - gets a vendor-specific
+ *	implementation 32-bit version. The format of the version number is
+ *	vendor-specific
+ *
+ * @handle - SCMI entity handle
+ *
+ * Return: 0 on success, else appropriate SCMI error.
+ */
+static int
+scmi_base_implementation_version_get(const struct scmi_handle *handle)
+{
+	int ret;
+	__le32 *impl_ver;
+	struct scmi_xfer *t;
+	struct scmi_revision_info *rev = handle->version;
+
+	ret = scmi_one_xfer_init(handle, BASE_DISCOVER_IMPLEMENT_VERSION,
+				 SCMI_PROTOCOL_BASE, 0, sizeof(*impl_ver), &t);
+	if (ret)
+		return ret;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		impl_ver = t->rx.buf;
+		rev->impl_ver = le32_to_cpu(*impl_ver);
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+/**
+ * scmi_base_implementation_list_get() - gets the list of protocols it is
+ *	OSPM is allowed to access
+ *
+ * @handle - SCMI entity handle
+ * @protocols_imp - pointer to hold the list of protocol identifiers
+ *
+ * Return: 0 on success, else appropriate SCMI error.
+ */
+static int scmi_base_implementation_list_get(const struct scmi_handle *handle,
+					     u8 *protocols_imp)
+{
+	u8 *list;
+	int ret, loop;
+	struct scmi_xfer *t;
+	__le32 *num_skip, *num_ret;
+	u32 tot_num_ret = 0, loop_num_ret;
+	struct device *dev = handle->dev;
+
+	ret = scmi_one_xfer_init(handle, BASE_DISCOVER_LIST_PROTOCOLS,
+				 SCMI_PROTOCOL_BASE, sizeof(*num_skip), 0, &t);
+	if (ret)
+		return ret;
+
+	num_skip = t->tx.buf;
+	num_ret = t->rx.buf;
+	list = t->rx.buf + sizeof(*num_ret);
+
+	do {
+		/* Set the number of protocols to be skipped/already read */
+		*num_skip = cpu_to_le32(tot_num_ret);
+
+		ret = scmi_do_xfer(handle, t);
+		if (ret)
+			break;
+
+		loop_num_ret = le32_to_cpu(*num_ret);
+		if (tot_num_ret + loop_num_ret > MAX_PROTOCOLS_IMP) {
+			dev_err(dev, "No. of Protocol > MAX_PROTOCOLS_IMP");
+			break;
+		}
+
+		for (loop = 0; loop < loop_num_ret; loop++)
+			protocols_imp[tot_num_ret + loop] = *(list + loop);
+
+		tot_num_ret += loop_num_ret;
+	} while (loop_num_ret);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+/**
+ * scmi_base_discover_agent_get() - discover the name of an agent
+ *
+ * @handle - SCMI entity handle
+ * @id - Agent identifier
+ * @name - Agent identifier ASCII string
+ *
+ * An agent id of 0 is reserved to identify the platform itself.
+ * Generally operating system is represented as "OSPM"
+ *
+ * Return: 0 on success, else appropriate SCMI error.
+ */
+static int scmi_base_discover_agent_get(const struct scmi_handle *handle,
+					int id, char *name)
+{
+	int ret;
+	struct scmi_xfer *t;
+
+	ret = scmi_one_xfer_init(handle, BASE_DISCOVER_AGENT,
+				 SCMI_PROTOCOL_BASE, sizeof(__le32),
+				 SCMI_MAX_STR_SIZE, &t);
+	if (ret)
+		return ret;
+
+	*(__le32 *)t->tx.buf = cpu_to_le32(id);
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret)
+		memcpy(name, t->rx.buf, SCMI_MAX_STR_SIZE);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+/**
+ * scmi_base_error_notifications_enable() - register/unregister for
+ *	notifications of errors in the platform
+ *
+ * @handle - SCMI entity handle
+ * @enable - Enable/Disable the notification
+ *
+ * Return: 0 on success, else appropriate SCMI error.
+ */
+static int
+scmi_base_error_notifications_enable(const struct scmi_handle *handle, bool en)
+{
+	int ret;
+	struct scmi_xfer *t;
+
+	ret = scmi_one_xfer_init(handle, BASE_NOTIFY_ERRORS, SCMI_PROTOCOL_BASE,
+				 sizeof(__le32), 0, &t);
+	if (ret)
+		return ret;
+
+	*(__le32 *)t->tx.buf = cpu_to_le32(en & BIT(0));
+
+	ret = scmi_do_xfer(handle, t);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+int scmi_base_protocol_init(struct scmi_handle *h)
+{
+	int id, ret;
+	u8 *prot_imp;
+	u32 version;
+	char name[SCMI_MAX_STR_SIZE];
+	const struct scmi_handle *handle = h;
+	struct device *dev = handle->dev;
+	struct scmi_revision_info *rev = handle->version;
+
+	ret = scmi_version_get(handle, SCMI_PROTOCOL_BASE, &version);
+	if (ret)
+		return ret;
+
+	prot_imp = devm_kcalloc(dev, MAX_PROTOCOLS_IMP, sizeof(u8), GFP_KERNEL);
+	if (!prot_imp)
+		return -ENOMEM;
+
+	rev->major_ver = PROTOCOL_REV_MAJOR(version),
+	rev->minor_ver = PROTOCOL_REV_MINOR(version);
+
+	scmi_base_attributes_get(handle);
+	scmi_base_vendor_id_get(handle, false);
+	scmi_base_vendor_id_get(handle, true);
+	scmi_base_implementation_version_get(handle);
+	scmi_base_implementation_list_get(handle, prot_imp);
+	scmi_base_error_notifications_enable(handle, true);
+	scmi_setup_protocol_implemented(handle, prot_imp);
+
+	dev_info(dev, "SCMI Protocol v%d.%d '%s:%s' Firmware version 0x%x\n",
+		 rev->major_ver, rev->minor_ver, rev->vendor_id,
+		 rev->sub_vendor_id, rev->impl_ver);
+	dev_dbg(dev, "Found %d protocol(s) %d agent(s)\n", rev->num_protocols,
+		rev->num_agents);
+
+	for (id = 0; id < rev->num_agents; id++) {
+		scmi_base_discover_agent_get(handle, id, name);
+		dev_dbg(dev, "Agent %d: %s\n", id, name);
+	}
+
+	return 0;
+}
diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index 344b234d4e64..7a30a517a10b 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -19,9 +19,50 @@
  */
 
 #include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
 #include <linux/scmi_protocol.h>
 #include <linux/types.h>
 
+#define PROTOCOL_REV_MINOR_BITS	16
+#define PROTOCOL_REV_MINOR_MASK	((1U << PROTOCOL_REV_MINOR_BITS) - 1)
+#define PROTOCOL_REV_MAJOR(x)	((x) >> PROTOCOL_REV_MINOR_BITS)
+#define PROTOCOL_REV_MINOR(x)	((x) & PROTOCOL_REV_MINOR_MASK)
+#define MAX_PROTOCOLS_IMP	16
+
+enum scmi_std_protocol {
+	SCMI_PROTOCOL_BASE = 0x10,
+	SCMI_PROTOCOL_POWER = 0x11,
+	SCMI_PROTOCOL_SYSTEM = 0x12,
+	SCMI_PROTOCOL_PERF = 0x13,
+	SCMI_PROTOCOL_CLOCK = 0x14,
+	SCMI_PROTOCOL_SENSOR = 0x15,
+};
+
+enum scmi_common_cmd {
+	PROTOCOL_VERSION = 0x0,
+	PROTOCOL_ATTRIBUTES = 0x1,
+	PROTOCOL_MESSAGE_ATTRIBUTES = 0x2,
+};
+
+/**
+ * struct scmi_msg_resp_prot_version - Response for a message
+ *
+ * @major_version: Major version of the ABI that firmware supports
+ * @minor_version: Minor version of the ABI that firmware supports
+ *
+ * In general, ABI version changes follow the rule that minor version increments
+ * are backward compatible. Major revision changes in ABI may not be
+ * backward compatible.
+ *
+ * Response to a generic message with message type SCMI_MSG_VERSION
+ */
+struct scmi_msg_resp_prot_version {
+	__le16 minor_version;
+	__le16 major_version;
+};
+
 /**
  * struct scmi_msg_hdr - Message(Tx/Rx) header
  *
@@ -73,3 +114,8 @@ void scmi_one_xfer_put(const struct scmi_handle *h, struct scmi_xfer *xfer);
 int scmi_do_xfer(const struct scmi_handle *h, struct scmi_xfer *xfer);
 int scmi_one_xfer_init(const struct scmi_handle *h, u8 msg_id, u8 prot_id,
 		       size_t tx_size, size_t rx_size, struct scmi_xfer **p);
+int scmi_version_get(const struct scmi_handle *h, u8 protocol, u32 *version);
+void scmi_setup_protocol_implemented(const struct scmi_handle *handle,
+				     u8 *prot_imp);
+
+int scmi_base_protocol_init(struct scmi_handle *h);
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 1d556a928de9..5df76512a291 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -108,21 +108,27 @@ struct scmi_desc {
  * @dev: Device pointer
  * @desc: SoC description for this instance
  * @handle: Instance of SCMI handle to send to clients
+ * @version: SCMI revision information containing protocol version,
+ *	implementation version and (sub-)vendor identification.
  * @cl: Mailbox Client
  * @tx_chan: Transmit mailbox channel
  * @tx_payload: Transmit mailbox channel payload area
  * @minfo: Message info
+ * @protocols_imp: list of protocols implemented, currently maximum of
+ *	MAX_PROTOCOLS_IMP elements allocated by the base protocol
  * @node: list head
  * @users: Number of users of this instance
  */
 struct scmi_info {
 	struct device *dev;
 	const struct scmi_desc *desc;
+	struct scmi_revision_info version;
 	struct scmi_handle handle;
 	struct mbox_client cl;
 	struct mbox_chan *tx_chan;
 	void __iomem *tx_payload;
 	struct scmi_xfers_info minfo;
+	u8 *protocols_imp;
 	struct list_head node;
 	int users;
 };
@@ -450,6 +456,60 @@ int scmi_one_xfer_init(const struct scmi_handle *handle, u8 msg_id, u8 prot_id,
 }
 
 /**
+ * scmi_version_get() - command to get the revision of the SCMI entity
+ *
+ * @handle: Handle to SCMI entity information
+ *
+ * Updates the SCMI information in the internal data structure.
+ *
+ * Return: 0 if all went fine, else return appropriate error.
+ */
+int scmi_version_get(const struct scmi_handle *handle, u8 protocol,
+		     u32 *version)
+{
+	int ret;
+	__le32 *rev_info;
+	struct scmi_xfer *t;
+
+	ret = scmi_one_xfer_init(handle, PROTOCOL_VERSION, protocol, 0,
+				 sizeof(*version), &t);
+	if (ret)
+		return ret;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		rev_info = t->rx.buf;
+		*version = le32_to_cpu(*rev_info);
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+void scmi_setup_protocol_implemented(const struct scmi_handle *handle,
+				     u8 *prot_imp)
+{
+	struct scmi_info *info = handle_to_scmi_info(handle);
+
+	info->protocols_imp = prot_imp;
+}
+
+static bool
+scmi_is_protocol_implemented(const struct scmi_handle *handle, u8 prot_id)
+{
+	int i;
+	struct scmi_info *info = handle_to_scmi_info(handle);
+
+	if (!info->protocols_imp)
+		return false;
+
+	for (i = 0; i < MAX_PROTOCOLS_IMP; i++)
+		if (info->protocols_imp[i] == prot_id)
+			return true;
+	return false;
+}
+
+/**
  * scmi_handle_get() - Get the  SCMI handle for a device
  *
  * @dev: pointer to device for which we want SCMI handle
@@ -740,11 +800,19 @@ static int scmi_probe(struct platform_device *pdev)
 
 	handle = &info->handle;
 	handle->dev = info->dev;
+	handle->version = &info->version;
 
 	ret = scmi_mbox_chan_setup(info);
 	if (ret)
 		return ret;
 
+	ret = scmi_base_protocol_init(handle);
+	if (ret) {
+		dev_err(dev, "unable to communicate with SCMI(%d)\n", ret);
+		scmi_mbox_free_channel(info);
+		return ret;
+	}
+
 	mutex_lock(&scmi_list_mutex);
 	list_add_tail(&info->node, &scmi_list);
 	mutex_unlock(&scmi_list_mutex);
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index fbe80fa1ec9f..3ef2d48f03c2 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -17,13 +17,41 @@
  */
 #include <linux/types.h>
 
+#define SCMI_MAX_STR_SIZE	16
+
+/**
+ * struct scmi_revision_info - version information structure
+ *
+ * @major_ver: Major ABI version. Change here implies risk of backward
+ *	compatibility break.
+ * @minor_ver: Minor ABI version. Change here implies new feature addition,
+ *	or compatible change in ABI.
+ * @num_protocols: Number of protocols that are implemented, excluding the
+ *	base protocol.
+ * @num_agents: Number of agents in the system.
+ * @impl_ver: A vendor-specific implementation version.
+ * @vendor_id: A vendor identifier(Null terminated ASCII string)
+ * @sub_vendor_id: A sub-vendor identifier(Null terminated ASCII string)
+ */
+struct scmi_revision_info {
+	u16 major_ver;
+	u16 minor_ver;
+	u8 num_protocols;
+	u8 num_agents;
+	u32 impl_ver;
+	char vendor_id[SCMI_MAX_STR_SIZE];
+	char sub_vendor_id[SCMI_MAX_STR_SIZE];
+};
+
 /**
  * struct scmi_handle - Handle returned to ARM SCMI clients for usage.
  *
  * @dev: pointer to the SCMI device
+ * @version: pointer to the structure containing SCMI version information
  */
 struct scmi_handle {
 	struct device *dev;
+	struct scmi_revision_info *version;
 };
 
 #if IS_REACHABLE(CONFIG_ARM_SCMI_PROTOCOL)
-- 
2.7.4

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

* [PATCH v3 06/22] firmware: arm_scmi: add initial support for performance protocol
  2017-09-28 13:11 ` Sudeep Holla
@ 2017-09-28 13:11   ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

The performance protocol is intended for the performance management of
group(s) of device(s) that run in the same performance domain. It
includes even the CPUs. A performance domain is defined by a set of
devices that always have to run at the same performance level.
For example, a set of CPUs that share a voltage domain, and have a
common frequency control, is said to be in the same performance domain.

The commands in this protocol provide functionality to describe the
protocol version, describe various attribute flags, set and get the
performance level of a domain. It also supports discovery of the list
of performance levels supported by a performance domain, and the
properties of each performance level.

This patch adds basic support for the performance protocol.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scmi/Makefile |   2 +-
 drivers/firmware/arm_scmi/common.h |   1 +
 drivers/firmware/arm_scmi/perf.c   | 511 +++++++++++++++++++++++++++++++++++++
 include/linux/scmi_protocol.h      |  31 +++
 4 files changed, 544 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/arm_scmi/perf.c

diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index 21d01d1d6b9c..159de726ee45 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_ARM_SCMI_PROTOCOL)	= arm_scmi.o
-arm_scmi-y = base.o driver.o
+arm_scmi-y = base.o driver.o perf.o
diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index 7a30a517a10b..0df52905ba48 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -30,6 +30,7 @@
 #define PROTOCOL_REV_MAJOR(x)	((x) >> PROTOCOL_REV_MINOR_BITS)
 #define PROTOCOL_REV_MINOR(x)	((x) & PROTOCOL_REV_MINOR_MASK)
 #define MAX_PROTOCOLS_IMP	16
+#define MAX_OPPS		16
 
 enum scmi_std_protocol {
 	SCMI_PROTOCOL_BASE = 0x10,
diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c
new file mode 100644
index 000000000000..13d84d829201
--- /dev/null
+++ b/drivers/firmware/arm_scmi/perf.c
@@ -0,0 +1,511 @@
+/*
+ * System Control and Management Interface (SCMI) Performance Protocol
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+#include <linux/sort.h>
+
+#include "common.h"
+
+enum scmi_performance_protocol_cmd {
+	PERF_DOMAIN_ATTRIBUTES = 0x3,
+	PERF_DESCRIBE_LEVELS = 0x4,
+	PERF_LIMITS_SET = 0x5,
+	PERF_LIMITS_GET = 0x6,
+	PERF_LEVEL_SET = 0x7,
+	PERF_LEVEL_GET = 0x8,
+	PERF_NOTIFY_LIMITS = 0x9,
+	PERF_NOTIFY_LEVEL = 0xa,
+};
+
+struct scmi_opp {
+	u32 perf;
+	u32 power;
+	u32 trans_latency_us;
+};
+
+struct scmi_msg_resp_perf_attributes {
+	__le16 num_domains;
+	__le16 flags;
+#define POWER_SCALE_IN_MILLIWATT(x)	((x) & BIT(0))
+	__le32 stats_addr_low;
+	__le32 stats_addr_high;
+	__le32 stats_size;
+};
+
+struct scmi_msg_resp_perf_domain_attributes {
+	__le32 flags;
+#define SUPPORTS_SET_LIMITS(x)		((x) & BIT(31))
+#define SUPPORTS_SET_PERF_LVL(x)	((x) & BIT(30))
+#define SUPPORTS_PERF_LIMIT_NOTIFY(x)	((x) & BIT(29))
+#define SUPPORTS_PERF_LEVEL_NOTIFY(x)	((x) & BIT(28))
+	__le32 rate_limit_us;
+	__le32 sustained_freq_khz;
+	__le32 sustained_perf_level;
+	    u8 name[SCMI_MAX_STR_SIZE];
+};
+
+struct scmi_msg_perf_describe_levels {
+	__le32 domain;
+	__le32 level_index;
+};
+
+struct scmi_perf_set_limits {
+	__le32 domain;
+	__le32 max_level;
+	__le32 min_level;
+};
+
+struct scmi_perf_get_limits {
+	__le32 max_level;
+	__le32 min_level;
+};
+
+struct scmi_perf_set_level {
+	__le32 domain;
+	__le32 level;
+};
+
+struct scmi_perf_notify_level_or_limits {
+	__le32 domain;
+	__le32 notify_enable;
+};
+
+struct scmi_msg_resp_perf_describe_levels {
+	__le16 num_returned;
+	__le16 num_remaining;
+	struct {
+		__le32 perf_val;
+		__le32 power;
+		__le16 transition_latency_us;
+		__le16 reserved;
+	} opp[0];
+};
+
+struct perf_dom_info {
+	bool set_limits;
+	bool set_perf;
+	bool perf_limit_notify;
+	bool perf_level_notify;
+	u32 opp_count;
+	u32 sustained_freq_khz;
+	u32 sustained_perf_level;
+	u32 mult_factor;
+	char name[SCMI_MAX_STR_SIZE];
+	struct scmi_opp opp[MAX_OPPS];
+};
+
+struct scmi_perf_info {
+	int num_domains;
+	bool power_scale_mw;
+	u64 stats_addr;
+	u32 stats_size;
+	struct perf_dom_info *dom_info;
+};
+
+static struct scmi_perf_info perf_info;
+
+static int scmi_perf_attributes_get(const struct scmi_handle *handle,
+				    struct scmi_perf_info *perf_info)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_msg_resp_perf_attributes *attr;
+
+	ret = scmi_one_xfer_init(handle, PROTOCOL_ATTRIBUTES,
+				 SCMI_PROTOCOL_PERF, 0, sizeof(*attr), &t);
+	if (ret)
+		return ret;
+
+	attr = t->rx.buf;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		u16 flags = le16_to_cpu(attr->flags);
+
+		perf_info->num_domains = le16_to_cpu(attr->num_domains);
+		perf_info->power_scale_mw = POWER_SCALE_IN_MILLIWATT(flags);
+		perf_info->stats_addr = le32_to_cpu(attr->stats_addr_low) |
+				(u64)le32_to_cpu(attr->stats_addr_high) << 32;
+		perf_info->stats_size = le32_to_cpu(attr->stats_size);
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int
+scmi_perf_domain_attributes_get(const struct scmi_handle *handle, u32 domain,
+				struct perf_dom_info *dom_info)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_msg_resp_perf_domain_attributes *attr;
+
+	ret = scmi_one_xfer_init(handle, PERF_DOMAIN_ATTRIBUTES,
+				 SCMI_PROTOCOL_PERF, sizeof(domain),
+				 sizeof(*attr), &t);
+	if (ret)
+		return ret;
+
+	*(__le32 *)t->tx.buf = cpu_to_le32(domain);
+	attr = t->rx.buf;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		u32 flags = le32_to_cpu(attr->flags);
+
+		dom_info->set_limits = SUPPORTS_SET_LIMITS(flags);
+		dom_info->set_perf = SUPPORTS_SET_PERF_LVL(flags);
+		dom_info->perf_limit_notify = SUPPORTS_PERF_LIMIT_NOTIFY(flags);
+		dom_info->perf_level_notify = SUPPORTS_PERF_LEVEL_NOTIFY(flags);
+		dom_info->sustained_freq_khz =
+					le32_to_cpu(attr->sustained_freq_khz);
+		dom_info->sustained_perf_level =
+					le32_to_cpu(attr->sustained_perf_level);
+		dom_info->mult_factor =	(dom_info->sustained_freq_khz * 1000) /
+					dom_info->sustained_perf_level;
+		memcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE);
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int opp_cmp_func(const void *opp1, const void *opp2)
+{
+	const struct scmi_opp *t1 = opp1, *t2 = opp2;
+
+	return t1->perf - t2->perf;
+}
+
+static int
+scmi_perf_describe_levels_get(const struct scmi_handle *handle, u32 domain,
+			      struct perf_dom_info *perf_dom)
+{
+	int ret, cnt;
+	u32 tot_opp_cnt = 0;
+	u16 num_returned, num_remaining;
+	struct scmi_xfer *t;
+	struct scmi_opp *opp;
+	struct scmi_msg_perf_describe_levels *dom_info;
+	struct scmi_msg_resp_perf_describe_levels *level_info;
+
+	ret = scmi_one_xfer_init(handle, PERF_DESCRIBE_LEVELS,
+				 SCMI_PROTOCOL_PERF, sizeof(*dom_info), 0, &t);
+	if (ret)
+		return ret;
+
+	dom_info = t->tx.buf;
+	level_info = t->rx.buf;
+
+	do {
+		dom_info->domain = cpu_to_le32(domain);
+		/* Set the number of OPPs to be skipped/already read */
+		dom_info->level_index = cpu_to_le32(tot_opp_cnt);
+
+		ret = scmi_do_xfer(handle, t);
+		if (ret)
+			break;
+
+		num_returned = le16_to_cpu(level_info->num_returned);
+		num_remaining = le16_to_cpu(level_info->num_remaining);
+		if (tot_opp_cnt + num_returned > MAX_OPPS) {
+			dev_err(handle->dev, "No. of OPPs exceeded MAX_OPPS");
+			break;
+		}
+
+		opp = &perf_dom->opp[tot_opp_cnt];
+		for (cnt = 0; cnt < num_returned; cnt++, opp++) {
+			opp->perf = le32_to_cpu(level_info->opp[cnt].perf_val);
+			opp->power = le32_to_cpu(level_info->opp[cnt].power);
+			opp->trans_latency_us = le16_to_cpu(
+				level_info->opp[cnt].transition_latency_us);
+
+			dev_dbg(handle->dev, "Level %d Power %d Latency %dus\n",
+				opp->perf, opp->power, opp->trans_latency_us);
+		}
+
+		tot_opp_cnt += num_returned;
+		/*
+		 * check for both returned and remaining to avoid infinite
+		 * loop due to buggy firmware
+		 */
+	} while (num_returned && num_remaining);
+
+	perf_dom->opp_count = tot_opp_cnt;
+	scmi_one_xfer_put(handle, t);
+
+	sort(perf_dom->opp, tot_opp_cnt, sizeof(*opp), opp_cmp_func, NULL);
+	return ret;
+}
+
+static int scmi_perf_limits_set(const struct scmi_handle *handle, u32 domain,
+				u32 max_perf, u32 min_perf)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_perf_set_limits *limits;
+
+	ret = scmi_one_xfer_init(handle, PERF_LIMITS_SET, SCMI_PROTOCOL_PERF,
+				 sizeof(*limits), 0, &t);
+	if (ret)
+		return ret;
+
+	limits = t->tx.buf;
+	limits->domain = cpu_to_le32(domain);
+	limits->max_level = cpu_to_le32(max_perf);
+	limits->min_level = cpu_to_le32(min_perf);
+
+	ret = scmi_do_xfer(handle, t);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int scmi_perf_limits_get(const struct scmi_handle *handle, u32 domain,
+				u32 *max_perf, u32 *min_perf)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_perf_get_limits *limits;
+
+	ret = scmi_one_xfer_init(handle, PERF_LIMITS_GET, SCMI_PROTOCOL_PERF,
+				 sizeof(__le32), 0, &t);
+	if (ret)
+		return ret;
+
+	*(__le32 *)t->tx.buf = cpu_to_le32(domain);
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		limits = t->rx.buf;
+
+		*max_perf = le32_to_cpu(limits->max_level);
+		*min_perf = le32_to_cpu(limits->min_level);
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int
+scmi_perf_level_set(const struct scmi_handle *handle, u32 domain, u32 level)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_perf_set_level *lvl;
+
+	ret = scmi_one_xfer_init(handle, PERF_LEVEL_SET, SCMI_PROTOCOL_PERF,
+				 sizeof(*lvl), 0, &t);
+	if (ret)
+		return ret;
+
+	lvl = t->tx.buf;
+	lvl->domain = cpu_to_le32(domain);
+	lvl->level = cpu_to_le32(level);
+
+	ret = scmi_do_xfer(handle, t);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int
+scmi_perf_level_get(const struct scmi_handle *handle, u32 domain, u32 *level)
+{
+	int ret;
+	struct scmi_xfer *t;
+
+	ret = scmi_one_xfer_init(handle, PERF_LEVEL_GET, SCMI_PROTOCOL_PERF,
+				 sizeof(u32), sizeof(u32), &t);
+	if (ret)
+		return ret;
+
+	*(__le32 *)t->tx.buf = cpu_to_le32(domain);
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret)
+		*level = le32_to_cpu(*(__le32 *)t->rx.buf);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int __scmi_perf_notify_enable(const struct scmi_handle *handle, u32 cmd,
+				     u32 domain, bool enable)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_perf_notify_level_or_limits *notify;
+
+	ret = scmi_one_xfer_init(handle, cmd, SCMI_PROTOCOL_PERF,
+				 sizeof(*notify), 0, &t);
+	if (ret)
+		return ret;
+
+	notify = t->tx.buf;
+	notify->domain = cpu_to_le32(domain);
+	notify->notify_enable = cpu_to_le32(enable & BIT(0));
+
+	ret = scmi_do_xfer(handle, t);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int scmi_perf_limits_notify_enable(const struct scmi_handle *handle,
+					  u32 domain, bool enable)
+{
+	return __scmi_perf_notify_enable(handle, PERF_NOTIFY_LIMITS,
+					 domain, enable);
+}
+
+static int scmi_perf_level_notify_enable(const struct scmi_handle *handle,
+					 u32 domain, bool enable)
+{
+	return __scmi_perf_notify_enable(handle, PERF_NOTIFY_LEVEL,
+					 domain, enable);
+}
+
+/* Device specific ops */
+static int scmi_dev_domain_id(struct device *dev)
+{
+	struct of_phandle_args clkspec;
+
+	if (of_parse_phandle_with_args(dev->of_node, "clocks", "#clock-cells",
+				       0, &clkspec))
+		return -EINVAL;
+
+	return clkspec.args[0];
+}
+
+static int scmi_dvfs_add_opps_to_device(struct device *dev)
+{
+	int idx, ret, domain;
+	unsigned long freq;
+	struct scmi_opp *opp;
+	struct perf_dom_info *dom;
+
+	domain = scmi_dev_domain_id(dev);
+	if (domain < 0)
+		return domain;
+
+	dom = perf_info.dom_info + domain;
+	if (!dom)
+		return -EIO;
+
+	for (opp = dom->opp, idx = 0; idx < dom->opp_count; idx++, opp++) {
+		freq = opp->perf * dom->mult_factor;
+
+		ret = dev_pm_opp_add(dev, freq, opp->power);
+		if (ret) {
+			dev_warn(dev, "failed to add opp %luHz %umV\n",
+				 freq, opp->power);
+
+			while (idx-- > 0) {
+				freq = (--opp)->perf * dom->mult_factor;
+				dev_pm_opp_remove(dev, freq);
+			}
+			return ret;
+		}
+	}
+	return 0;
+}
+
+static int scmi_dvfs_get_transition_latency(struct device *dev)
+{
+	struct perf_dom_info *dom;
+	int domain = scmi_dev_domain_id(dev);
+
+	if (domain < 0)
+		return domain;
+
+	dom = perf_info.dom_info + domain;
+	if (!dom)
+		return -EIO;
+
+	return dom->opp[dom->opp_count - 1].trans_latency_us;
+}
+
+static int scmi_dvfs_freq_set(const struct scmi_handle *handle, u32 domain,
+			      unsigned long freq)
+{
+	struct perf_dom_info *dom = perf_info.dom_info + domain;
+
+	return scmi_perf_level_set(handle, domain, freq / dom->mult_factor);
+}
+
+static int scmi_dvfs_freq_get(const struct scmi_handle *handle, u32 domain,
+			      unsigned long *freq)
+{
+	int ret;
+	u32 level;
+	struct perf_dom_info *dom = perf_info.dom_info + domain;
+
+	ret = scmi_perf_level_get(handle, domain, &level);
+	if (!ret)
+		*freq = level * dom->mult_factor;
+
+	return ret;
+}
+
+static struct scmi_perf_ops perf_ops = {
+	.limits_set = scmi_perf_limits_set,
+	.limits_get = scmi_perf_limits_get,
+	.level_set = scmi_perf_level_set,
+	.level_get = scmi_perf_level_get,
+	.limits_notify_enable = scmi_perf_limits_notify_enable,
+	.level_notify_enable = scmi_perf_level_notify_enable,
+	.device_domain_id = scmi_dev_domain_id,
+	.get_transition_latency = scmi_dvfs_get_transition_latency,
+	.add_opps_to_device = scmi_dvfs_add_opps_to_device,
+	.freq_set = scmi_dvfs_freq_set,
+	.freq_get = scmi_dvfs_freq_get,
+};
+
+int scmi_perf_protocol_init(struct scmi_handle *handle)
+{
+	int domain;
+	u32 version;
+
+	scmi_version_get(handle, SCMI_PROTOCOL_PERF, &version);
+
+	dev_dbg(handle->dev, "Performance Version %d.%d\n",
+		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
+
+	scmi_perf_attributes_get(handle, &perf_info);
+
+	perf_info.dom_info = devm_kcalloc(handle->dev, perf_info.num_domains,
+					  sizeof(struct perf_dom_info),
+					  GFP_KERNEL);
+	if (!perf_info.dom_info)
+		return -ENOMEM;
+
+	for (domain = 0; domain < perf_info.num_domains; domain++) {
+		struct perf_dom_info *dom = perf_info.dom_info + domain;
+
+		scmi_perf_domain_attributes_get(handle, domain, dom);
+		scmi_perf_describe_levels_get(handle, domain, dom);
+	}
+
+	handle->perf_ops = &perf_ops;
+
+	return 0;
+}
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 3ef2d48f03c2..c9f97e69444a 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -43,15 +43,46 @@ struct scmi_revision_info {
 	char sub_vendor_id[SCMI_MAX_STR_SIZE];
 };
 
+struct scmi_handle;
+
+/**
+ * struct scmi_perf_ops - represents the various operations provided
+ *	by SCMI Performance Protocol
+ *
+ * @limits_set: sets limits on the performance level of a domain
+ * @limits_get: gets limits on the performance level of a domain
+ * @level_set: sets the performance level of a domain
+ * @level_get: gets the performance level of a domain
+ * @limits_notify_enable: requests notifications from the platform for changes
+ *	in the allowed maximum and minimum performance levels
+ * @level_notify_enable: requests notifications from the platform when the
+ *	performance level for a domain changes in value
+ */
+struct scmi_perf_ops {
+	int (*limits_set)(const struct scmi_handle *, u32, u32, u32);
+	int (*limits_get)(const struct scmi_handle *, u32, u32 *, u32 *);
+	int (*level_set)(const struct scmi_handle *, u32, u32);
+	int (*level_get)(const struct scmi_handle *, u32, u32 *);
+	int (*limits_notify_enable)(const struct scmi_handle *, u32, bool);
+	int (*level_notify_enable)(const struct scmi_handle *, u32, bool);
+	int (*device_domain_id)(struct device *);
+	int (*get_transition_latency)(struct device *);
+	int (*add_opps_to_device)(struct device *);
+	int (*freq_set)(const struct scmi_handle *, u32, unsigned long);
+	int (*freq_get)(const struct scmi_handle *, u32, unsigned long *);
+};
+
 /**
  * struct scmi_handle - Handle returned to ARM SCMI clients for usage.
  *
  * @dev: pointer to the SCMI device
  * @version: pointer to the structure containing SCMI version information
+ * @perf_ops: pointer to set of performance protocol operations
  */
 struct scmi_handle {
 	struct device *dev;
 	struct scmi_revision_info *version;
+	struct scmi_perf_ops *perf_ops;
 };
 
 #if IS_REACHABLE(CONFIG_ARM_SCMI_PROTOCOL)
-- 
2.7.4

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

* [PATCH v3 06/22] firmware: arm_scmi: add initial support for performance protocol
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

The performance protocol is intended for the performance management of
group(s) of device(s) that run in the same performance domain. It
includes even the CPUs. A performance domain is defined by a set of
devices that always have to run at the same performance level.
For example, a set of CPUs that share a voltage domain, and have a
common frequency control, is said to be in the same performance domain.

The commands in this protocol provide functionality to describe the
protocol version, describe various attribute flags, set and get the
performance level of a domain. It also supports discovery of the list
of performance levels supported by a performance domain, and the
properties of each performance level.

This patch adds basic support for the performance protocol.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scmi/Makefile |   2 +-
 drivers/firmware/arm_scmi/common.h |   1 +
 drivers/firmware/arm_scmi/perf.c   | 511 +++++++++++++++++++++++++++++++++++++
 include/linux/scmi_protocol.h      |  31 +++
 4 files changed, 544 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/arm_scmi/perf.c

diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index 21d01d1d6b9c..159de726ee45 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_ARM_SCMI_PROTOCOL)	= arm_scmi.o
-arm_scmi-y = base.o driver.o
+arm_scmi-y = base.o driver.o perf.o
diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index 7a30a517a10b..0df52905ba48 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -30,6 +30,7 @@
 #define PROTOCOL_REV_MAJOR(x)	((x) >> PROTOCOL_REV_MINOR_BITS)
 #define PROTOCOL_REV_MINOR(x)	((x) & PROTOCOL_REV_MINOR_MASK)
 #define MAX_PROTOCOLS_IMP	16
+#define MAX_OPPS		16
 
 enum scmi_std_protocol {
 	SCMI_PROTOCOL_BASE = 0x10,
diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c
new file mode 100644
index 000000000000..13d84d829201
--- /dev/null
+++ b/drivers/firmware/arm_scmi/perf.c
@@ -0,0 +1,511 @@
+/*
+ * System Control and Management Interface (SCMI) Performance Protocol
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+#include <linux/sort.h>
+
+#include "common.h"
+
+enum scmi_performance_protocol_cmd {
+	PERF_DOMAIN_ATTRIBUTES = 0x3,
+	PERF_DESCRIBE_LEVELS = 0x4,
+	PERF_LIMITS_SET = 0x5,
+	PERF_LIMITS_GET = 0x6,
+	PERF_LEVEL_SET = 0x7,
+	PERF_LEVEL_GET = 0x8,
+	PERF_NOTIFY_LIMITS = 0x9,
+	PERF_NOTIFY_LEVEL = 0xa,
+};
+
+struct scmi_opp {
+	u32 perf;
+	u32 power;
+	u32 trans_latency_us;
+};
+
+struct scmi_msg_resp_perf_attributes {
+	__le16 num_domains;
+	__le16 flags;
+#define POWER_SCALE_IN_MILLIWATT(x)	((x) & BIT(0))
+	__le32 stats_addr_low;
+	__le32 stats_addr_high;
+	__le32 stats_size;
+};
+
+struct scmi_msg_resp_perf_domain_attributes {
+	__le32 flags;
+#define SUPPORTS_SET_LIMITS(x)		((x) & BIT(31))
+#define SUPPORTS_SET_PERF_LVL(x)	((x) & BIT(30))
+#define SUPPORTS_PERF_LIMIT_NOTIFY(x)	((x) & BIT(29))
+#define SUPPORTS_PERF_LEVEL_NOTIFY(x)	((x) & BIT(28))
+	__le32 rate_limit_us;
+	__le32 sustained_freq_khz;
+	__le32 sustained_perf_level;
+	    u8 name[SCMI_MAX_STR_SIZE];
+};
+
+struct scmi_msg_perf_describe_levels {
+	__le32 domain;
+	__le32 level_index;
+};
+
+struct scmi_perf_set_limits {
+	__le32 domain;
+	__le32 max_level;
+	__le32 min_level;
+};
+
+struct scmi_perf_get_limits {
+	__le32 max_level;
+	__le32 min_level;
+};
+
+struct scmi_perf_set_level {
+	__le32 domain;
+	__le32 level;
+};
+
+struct scmi_perf_notify_level_or_limits {
+	__le32 domain;
+	__le32 notify_enable;
+};
+
+struct scmi_msg_resp_perf_describe_levels {
+	__le16 num_returned;
+	__le16 num_remaining;
+	struct {
+		__le32 perf_val;
+		__le32 power;
+		__le16 transition_latency_us;
+		__le16 reserved;
+	} opp[0];
+};
+
+struct perf_dom_info {
+	bool set_limits;
+	bool set_perf;
+	bool perf_limit_notify;
+	bool perf_level_notify;
+	u32 opp_count;
+	u32 sustained_freq_khz;
+	u32 sustained_perf_level;
+	u32 mult_factor;
+	char name[SCMI_MAX_STR_SIZE];
+	struct scmi_opp opp[MAX_OPPS];
+};
+
+struct scmi_perf_info {
+	int num_domains;
+	bool power_scale_mw;
+	u64 stats_addr;
+	u32 stats_size;
+	struct perf_dom_info *dom_info;
+};
+
+static struct scmi_perf_info perf_info;
+
+static int scmi_perf_attributes_get(const struct scmi_handle *handle,
+				    struct scmi_perf_info *perf_info)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_msg_resp_perf_attributes *attr;
+
+	ret = scmi_one_xfer_init(handle, PROTOCOL_ATTRIBUTES,
+				 SCMI_PROTOCOL_PERF, 0, sizeof(*attr), &t);
+	if (ret)
+		return ret;
+
+	attr = t->rx.buf;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		u16 flags = le16_to_cpu(attr->flags);
+
+		perf_info->num_domains = le16_to_cpu(attr->num_domains);
+		perf_info->power_scale_mw = POWER_SCALE_IN_MILLIWATT(flags);
+		perf_info->stats_addr = le32_to_cpu(attr->stats_addr_low) |
+				(u64)le32_to_cpu(attr->stats_addr_high) << 32;
+		perf_info->stats_size = le32_to_cpu(attr->stats_size);
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int
+scmi_perf_domain_attributes_get(const struct scmi_handle *handle, u32 domain,
+				struct perf_dom_info *dom_info)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_msg_resp_perf_domain_attributes *attr;
+
+	ret = scmi_one_xfer_init(handle, PERF_DOMAIN_ATTRIBUTES,
+				 SCMI_PROTOCOL_PERF, sizeof(domain),
+				 sizeof(*attr), &t);
+	if (ret)
+		return ret;
+
+	*(__le32 *)t->tx.buf = cpu_to_le32(domain);
+	attr = t->rx.buf;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		u32 flags = le32_to_cpu(attr->flags);
+
+		dom_info->set_limits = SUPPORTS_SET_LIMITS(flags);
+		dom_info->set_perf = SUPPORTS_SET_PERF_LVL(flags);
+		dom_info->perf_limit_notify = SUPPORTS_PERF_LIMIT_NOTIFY(flags);
+		dom_info->perf_level_notify = SUPPORTS_PERF_LEVEL_NOTIFY(flags);
+		dom_info->sustained_freq_khz =
+					le32_to_cpu(attr->sustained_freq_khz);
+		dom_info->sustained_perf_level =
+					le32_to_cpu(attr->sustained_perf_level);
+		dom_info->mult_factor =	(dom_info->sustained_freq_khz * 1000) /
+					dom_info->sustained_perf_level;
+		memcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE);
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int opp_cmp_func(const void *opp1, const void *opp2)
+{
+	const struct scmi_opp *t1 = opp1, *t2 = opp2;
+
+	return t1->perf - t2->perf;
+}
+
+static int
+scmi_perf_describe_levels_get(const struct scmi_handle *handle, u32 domain,
+			      struct perf_dom_info *perf_dom)
+{
+	int ret, cnt;
+	u32 tot_opp_cnt = 0;
+	u16 num_returned, num_remaining;
+	struct scmi_xfer *t;
+	struct scmi_opp *opp;
+	struct scmi_msg_perf_describe_levels *dom_info;
+	struct scmi_msg_resp_perf_describe_levels *level_info;
+
+	ret = scmi_one_xfer_init(handle, PERF_DESCRIBE_LEVELS,
+				 SCMI_PROTOCOL_PERF, sizeof(*dom_info), 0, &t);
+	if (ret)
+		return ret;
+
+	dom_info = t->tx.buf;
+	level_info = t->rx.buf;
+
+	do {
+		dom_info->domain = cpu_to_le32(domain);
+		/* Set the number of OPPs to be skipped/already read */
+		dom_info->level_index = cpu_to_le32(tot_opp_cnt);
+
+		ret = scmi_do_xfer(handle, t);
+		if (ret)
+			break;
+
+		num_returned = le16_to_cpu(level_info->num_returned);
+		num_remaining = le16_to_cpu(level_info->num_remaining);
+		if (tot_opp_cnt + num_returned > MAX_OPPS) {
+			dev_err(handle->dev, "No. of OPPs exceeded MAX_OPPS");
+			break;
+		}
+
+		opp = &perf_dom->opp[tot_opp_cnt];
+		for (cnt = 0; cnt < num_returned; cnt++, opp++) {
+			opp->perf = le32_to_cpu(level_info->opp[cnt].perf_val);
+			opp->power = le32_to_cpu(level_info->opp[cnt].power);
+			opp->trans_latency_us = le16_to_cpu(
+				level_info->opp[cnt].transition_latency_us);
+
+			dev_dbg(handle->dev, "Level %d Power %d Latency %dus\n",
+				opp->perf, opp->power, opp->trans_latency_us);
+		}
+
+		tot_opp_cnt += num_returned;
+		/*
+		 * check for both returned and remaining to avoid infinite
+		 * loop due to buggy firmware
+		 */
+	} while (num_returned && num_remaining);
+
+	perf_dom->opp_count = tot_opp_cnt;
+	scmi_one_xfer_put(handle, t);
+
+	sort(perf_dom->opp, tot_opp_cnt, sizeof(*opp), opp_cmp_func, NULL);
+	return ret;
+}
+
+static int scmi_perf_limits_set(const struct scmi_handle *handle, u32 domain,
+				u32 max_perf, u32 min_perf)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_perf_set_limits *limits;
+
+	ret = scmi_one_xfer_init(handle, PERF_LIMITS_SET, SCMI_PROTOCOL_PERF,
+				 sizeof(*limits), 0, &t);
+	if (ret)
+		return ret;
+
+	limits = t->tx.buf;
+	limits->domain = cpu_to_le32(domain);
+	limits->max_level = cpu_to_le32(max_perf);
+	limits->min_level = cpu_to_le32(min_perf);
+
+	ret = scmi_do_xfer(handle, t);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int scmi_perf_limits_get(const struct scmi_handle *handle, u32 domain,
+				u32 *max_perf, u32 *min_perf)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_perf_get_limits *limits;
+
+	ret = scmi_one_xfer_init(handle, PERF_LIMITS_GET, SCMI_PROTOCOL_PERF,
+				 sizeof(__le32), 0, &t);
+	if (ret)
+		return ret;
+
+	*(__le32 *)t->tx.buf = cpu_to_le32(domain);
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		limits = t->rx.buf;
+
+		*max_perf = le32_to_cpu(limits->max_level);
+		*min_perf = le32_to_cpu(limits->min_level);
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int
+scmi_perf_level_set(const struct scmi_handle *handle, u32 domain, u32 level)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_perf_set_level *lvl;
+
+	ret = scmi_one_xfer_init(handle, PERF_LEVEL_SET, SCMI_PROTOCOL_PERF,
+				 sizeof(*lvl), 0, &t);
+	if (ret)
+		return ret;
+
+	lvl = t->tx.buf;
+	lvl->domain = cpu_to_le32(domain);
+	lvl->level = cpu_to_le32(level);
+
+	ret = scmi_do_xfer(handle, t);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int
+scmi_perf_level_get(const struct scmi_handle *handle, u32 domain, u32 *level)
+{
+	int ret;
+	struct scmi_xfer *t;
+
+	ret = scmi_one_xfer_init(handle, PERF_LEVEL_GET, SCMI_PROTOCOL_PERF,
+				 sizeof(u32), sizeof(u32), &t);
+	if (ret)
+		return ret;
+
+	*(__le32 *)t->tx.buf = cpu_to_le32(domain);
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret)
+		*level = le32_to_cpu(*(__le32 *)t->rx.buf);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int __scmi_perf_notify_enable(const struct scmi_handle *handle, u32 cmd,
+				     u32 domain, bool enable)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_perf_notify_level_or_limits *notify;
+
+	ret = scmi_one_xfer_init(handle, cmd, SCMI_PROTOCOL_PERF,
+				 sizeof(*notify), 0, &t);
+	if (ret)
+		return ret;
+
+	notify = t->tx.buf;
+	notify->domain = cpu_to_le32(domain);
+	notify->notify_enable = cpu_to_le32(enable & BIT(0));
+
+	ret = scmi_do_xfer(handle, t);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int scmi_perf_limits_notify_enable(const struct scmi_handle *handle,
+					  u32 domain, bool enable)
+{
+	return __scmi_perf_notify_enable(handle, PERF_NOTIFY_LIMITS,
+					 domain, enable);
+}
+
+static int scmi_perf_level_notify_enable(const struct scmi_handle *handle,
+					 u32 domain, bool enable)
+{
+	return __scmi_perf_notify_enable(handle, PERF_NOTIFY_LEVEL,
+					 domain, enable);
+}
+
+/* Device specific ops */
+static int scmi_dev_domain_id(struct device *dev)
+{
+	struct of_phandle_args clkspec;
+
+	if (of_parse_phandle_with_args(dev->of_node, "clocks", "#clock-cells",
+				       0, &clkspec))
+		return -EINVAL;
+
+	return clkspec.args[0];
+}
+
+static int scmi_dvfs_add_opps_to_device(struct device *dev)
+{
+	int idx, ret, domain;
+	unsigned long freq;
+	struct scmi_opp *opp;
+	struct perf_dom_info *dom;
+
+	domain = scmi_dev_domain_id(dev);
+	if (domain < 0)
+		return domain;
+
+	dom = perf_info.dom_info + domain;
+	if (!dom)
+		return -EIO;
+
+	for (opp = dom->opp, idx = 0; idx < dom->opp_count; idx++, opp++) {
+		freq = opp->perf * dom->mult_factor;
+
+		ret = dev_pm_opp_add(dev, freq, opp->power);
+		if (ret) {
+			dev_warn(dev, "failed to add opp %luHz %umV\n",
+				 freq, opp->power);
+
+			while (idx-- > 0) {
+				freq = (--opp)->perf * dom->mult_factor;
+				dev_pm_opp_remove(dev, freq);
+			}
+			return ret;
+		}
+	}
+	return 0;
+}
+
+static int scmi_dvfs_get_transition_latency(struct device *dev)
+{
+	struct perf_dom_info *dom;
+	int domain = scmi_dev_domain_id(dev);
+
+	if (domain < 0)
+		return domain;
+
+	dom = perf_info.dom_info + domain;
+	if (!dom)
+		return -EIO;
+
+	return dom->opp[dom->opp_count - 1].trans_latency_us;
+}
+
+static int scmi_dvfs_freq_set(const struct scmi_handle *handle, u32 domain,
+			      unsigned long freq)
+{
+	struct perf_dom_info *dom = perf_info.dom_info + domain;
+
+	return scmi_perf_level_set(handle, domain, freq / dom->mult_factor);
+}
+
+static int scmi_dvfs_freq_get(const struct scmi_handle *handle, u32 domain,
+			      unsigned long *freq)
+{
+	int ret;
+	u32 level;
+	struct perf_dom_info *dom = perf_info.dom_info + domain;
+
+	ret = scmi_perf_level_get(handle, domain, &level);
+	if (!ret)
+		*freq = level * dom->mult_factor;
+
+	return ret;
+}
+
+static struct scmi_perf_ops perf_ops = {
+	.limits_set = scmi_perf_limits_set,
+	.limits_get = scmi_perf_limits_get,
+	.level_set = scmi_perf_level_set,
+	.level_get = scmi_perf_level_get,
+	.limits_notify_enable = scmi_perf_limits_notify_enable,
+	.level_notify_enable = scmi_perf_level_notify_enable,
+	.device_domain_id = scmi_dev_domain_id,
+	.get_transition_latency = scmi_dvfs_get_transition_latency,
+	.add_opps_to_device = scmi_dvfs_add_opps_to_device,
+	.freq_set = scmi_dvfs_freq_set,
+	.freq_get = scmi_dvfs_freq_get,
+};
+
+int scmi_perf_protocol_init(struct scmi_handle *handle)
+{
+	int domain;
+	u32 version;
+
+	scmi_version_get(handle, SCMI_PROTOCOL_PERF, &version);
+
+	dev_dbg(handle->dev, "Performance Version %d.%d\n",
+		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
+
+	scmi_perf_attributes_get(handle, &perf_info);
+
+	perf_info.dom_info = devm_kcalloc(handle->dev, perf_info.num_domains,
+					  sizeof(struct perf_dom_info),
+					  GFP_KERNEL);
+	if (!perf_info.dom_info)
+		return -ENOMEM;
+
+	for (domain = 0; domain < perf_info.num_domains; domain++) {
+		struct perf_dom_info *dom = perf_info.dom_info + domain;
+
+		scmi_perf_domain_attributes_get(handle, domain, dom);
+		scmi_perf_describe_levels_get(handle, domain, dom);
+	}
+
+	handle->perf_ops = &perf_ops;
+
+	return 0;
+}
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 3ef2d48f03c2..c9f97e69444a 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -43,15 +43,46 @@ struct scmi_revision_info {
 	char sub_vendor_id[SCMI_MAX_STR_SIZE];
 };
 
+struct scmi_handle;
+
+/**
+ * struct scmi_perf_ops - represents the various operations provided
+ *	by SCMI Performance Protocol
+ *
+ * @limits_set: sets limits on the performance level of a domain
+ * @limits_get: gets limits on the performance level of a domain
+ * @level_set: sets the performance level of a domain
+ * @level_get: gets the performance level of a domain
+ * @limits_notify_enable: requests notifications from the platform for changes
+ *	in the allowed maximum and minimum performance levels
+ * @level_notify_enable: requests notifications from the platform when the
+ *	performance level for a domain changes in value
+ */
+struct scmi_perf_ops {
+	int (*limits_set)(const struct scmi_handle *, u32, u32, u32);
+	int (*limits_get)(const struct scmi_handle *, u32, u32 *, u32 *);
+	int (*level_set)(const struct scmi_handle *, u32, u32);
+	int (*level_get)(const struct scmi_handle *, u32, u32 *);
+	int (*limits_notify_enable)(const struct scmi_handle *, u32, bool);
+	int (*level_notify_enable)(const struct scmi_handle *, u32, bool);
+	int (*device_domain_id)(struct device *);
+	int (*get_transition_latency)(struct device *);
+	int (*add_opps_to_device)(struct device *);
+	int (*freq_set)(const struct scmi_handle *, u32, unsigned long);
+	int (*freq_get)(const struct scmi_handle *, u32, unsigned long *);
+};
+
 /**
  * struct scmi_handle - Handle returned to ARM SCMI clients for usage.
  *
  * @dev: pointer to the SCMI device
  * @version: pointer to the structure containing SCMI version information
+ * @perf_ops: pointer to set of performance protocol operations
  */
 struct scmi_handle {
 	struct device *dev;
 	struct scmi_revision_info *version;
+	struct scmi_perf_ops *perf_ops;
 };
 
 #if IS_REACHABLE(CONFIG_ARM_SCMI_PROTOCOL)
-- 
2.7.4

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

* [PATCH v3 07/22] firmware: arm_scmi: add initial support for clock protocol
  2017-09-28 13:11 ` Sudeep Holla
@ 2017-09-28 13:11   ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

The clock protocol is intended for management of clocks. It is used to
enable or disable clocks, and to set and get the clock rates. This
protocol provides commands to describe the protocol version, discover
various implementation specific attributes, describe a clock, enable
and disable a clock and get/set the rate of the clock synchronously or
asynchronously.

This patch adds initial support for the clock protocol.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scmi/Makefile |   2 +-
 drivers/firmware/arm_scmi/clock.c  | 339 +++++++++++++++++++++++++++++++++++++
 include/linux/scmi_protocol.h      |  40 +++++
 3 files changed, 380 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/arm_scmi/clock.c

diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index 159de726ee45..6836b1f38f7f 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_ARM_SCMI_PROTOCOL)	= arm_scmi.o
-arm_scmi-y = base.o driver.o perf.o
+arm_scmi-y = base.o clock.o driver.o perf.o
diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c
new file mode 100644
index 000000000000..87d0befab07d
--- /dev/null
+++ b/drivers/firmware/arm_scmi/clock.c
@@ -0,0 +1,339 @@
+/*
+ * System Control and Management Interface (SCMI) Clock Protocol
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "common.h"
+
+enum scmi_clock_protocol_cmd {
+	CLOCK_ATTRIBUTES = 0x3,
+	CLOCK_DESCRIBE_RATES = 0x4,
+	CLOCK_RATE_SET = 0x5,
+	CLOCK_RATE_GET = 0x6,
+	CLOCK_CONFIG_SET = 0x7,
+};
+
+struct scmi_msg_resp_clock_protocol_attributes {
+	__le16 num_clocks;
+	    u8 max_async_req;
+	    u8 reserved;
+};
+
+struct scmi_msg_resp_clock_attributes {
+	__le32 attributes;
+#define	CLOCK_ENABLE	BIT(0)
+	    u8 name[SCMI_MAX_STR_SIZE];
+};
+
+struct scmi_clock_set_config {
+	__le32 id;
+	__le32 attributes;
+};
+
+struct scmi_msg_clock_describe_rates {
+	__le32 id;
+	__le32 rate_index;
+};
+
+struct scmi_msg_resp_clock_describe_rates {
+	__le32 num_rates_flags;
+#define NUM_RETURNED(x)		((x) & 0xfff)
+#define RATE_DISCRETE(x)	!((x) & BIT(12))
+#define NUM_REMAINING(x)	((x) >> 16)
+	struct {
+		__le32 value_low;
+		__le32 value_high;
+	} rate[0];
+#define RATE_TO_U64(X)		\
+({				\
+	typeof(X) x = (X);	\
+	le32_to_cpu((x).value_low) | (u64)le32_to_cpu((x).value_high) << 32; \
+})
+};
+
+struct scmi_clock_set_rate {
+	__le32 flags;
+#define CLOCK_SET_ASYNC		BIT(0)
+#define CLOCK_SET_DELAYED	BIT(1)
+#define CLOCK_SET_ROUND_UP	BIT(2)
+#define CLOCK_SET_ROUND_AUTO	BIT(3)
+	__le32 id;
+	__le32 value_low;
+	__le32 value_high;
+};
+
+struct clock_info {
+	int num_clocks;
+	int max_async_req;
+	struct scmi_clock_info *clk;
+};
+
+static struct clock_info clocks;
+
+static int scmi_clock_protocol_attributes_get(const struct scmi_handle *handle,
+					      struct clock_info *clocks)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_msg_resp_clock_protocol_attributes *attr;
+
+	ret = scmi_one_xfer_init(handle, PROTOCOL_ATTRIBUTES,
+				 SCMI_PROTOCOL_CLOCK, 0, sizeof(*attr), &t);
+	if (ret)
+		return ret;
+
+	attr = t->rx.buf;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		clocks->num_clocks = le16_to_cpu(attr->num_clocks);
+		clocks->max_async_req = attr->max_async_req;
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int scmi_clock_attributes_get(const struct scmi_handle *handle,
+				     u32 clk_id, struct scmi_clock_info *clk)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_msg_resp_clock_attributes *attr;
+
+	ret = scmi_one_xfer_init(handle, CLOCK_ATTRIBUTES, SCMI_PROTOCOL_CLOCK,
+				 sizeof(clk_id), sizeof(*attr), &t);
+	if (ret)
+		return ret;
+
+	*(__le32 *)t->tx.buf = cpu_to_le32(clk_id);
+	attr = t->rx.buf;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret)
+		memcpy(clk->name, attr->name, SCMI_MAX_STR_SIZE);
+	else
+		clk->name[0] = '\0';
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int
+scmi_clock_describe_rates_get(const struct scmi_handle *handle, u32 clk_id,
+			      struct scmi_clock_info *clk)
+{
+	u64 *rate;
+	int ret, cnt;
+	bool rate_discrete;
+	u32 tot_rate_cnt = 0, rates_flag;
+	u16 num_returned, num_remaining;
+	struct scmi_xfer *t;
+	struct scmi_msg_clock_describe_rates *clk_desc;
+	struct scmi_msg_resp_clock_describe_rates *rlist;
+
+	ret = scmi_one_xfer_init(handle, CLOCK_DESCRIBE_RATES,
+				 SCMI_PROTOCOL_CLOCK, sizeof(*clk_desc), 0, &t);
+	if (ret)
+		return ret;
+
+	clk_desc = t->tx.buf;
+	rlist = t->rx.buf;
+
+	do {
+		clk_desc->id = cpu_to_le32(clk_id);
+		/* Set the number of rates to be skipped/already read */
+		clk_desc->rate_index = cpu_to_le32(tot_rate_cnt);
+
+		ret = scmi_do_xfer(handle, t);
+		if (ret)
+			break;
+
+		rates_flag = le32_to_cpu(rlist->num_rates_flags);
+		num_remaining = NUM_REMAINING(rates_flag);
+		rate_discrete = RATE_DISCRETE(rates_flag);
+		num_returned = NUM_RETURNED(rates_flag);
+
+		if (tot_rate_cnt + num_returned > SCMI_MAX_NUM_RATES) {
+			dev_err(handle->dev, "No. of rates > MAX_NUM_RATES");
+			break;
+		}
+
+		if (!rate_discrete) {
+			clk->range.min_rate = RATE_TO_U64(rlist->rate[0]);
+			clk->range.max_rate = RATE_TO_U64(rlist->rate[1]);
+			clk->range.step_size = RATE_TO_U64(rlist->rate[2]);
+			dev_dbg(handle->dev, "Min %llu Max %llu Step %llu Hz\n",
+				clk->range.min_rate, clk->range.max_rate,
+				clk->range.step_size);
+			break;
+		}
+
+		rate = &clk->list.rates[tot_rate_cnt];
+		for (cnt = 0; cnt < num_returned; cnt++, rate++) {
+			*rate = RATE_TO_U64(rlist->rate[cnt]);
+			dev_dbg(handle->dev, "Rate %llu Hz\n", *rate);
+		}
+
+		tot_rate_cnt += num_returned;
+		/*
+		 * check for both returned and remaining to avoid infinite
+		 * loop due to buggy firmware
+		 */
+	} while (num_returned && num_remaining);
+
+	if (rate_discrete)
+		clk->list.num_rates = tot_rate_cnt;
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int
+scmi_clock_rate_get(const struct scmi_handle *handle, u32 clk_id, u64 *value)
+{
+	int ret;
+	struct scmi_xfer *t;
+
+	ret = scmi_one_xfer_init(handle, CLOCK_RATE_GET, SCMI_PROTOCOL_CLOCK,
+				 sizeof(__le32), sizeof(u64), &t);
+	if (ret)
+		return ret;
+
+	*(__le32 *)t->tx.buf = cpu_to_le32(clk_id);
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		__le32 *pval = t->rx.buf;
+
+		*value = le32_to_cpu(*pval);
+		*value |= (u64)le32_to_cpu(*(pval + 1)) << 32;
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int scmi_clock_rate_set(const struct scmi_handle *handle, u32 clk_id,
+			       u32 config, u64 rate)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_clock_set_rate *cfg;
+
+	ret = scmi_one_xfer_init(handle, CLOCK_RATE_SET, SCMI_PROTOCOL_CLOCK,
+				 sizeof(*cfg), 0, &t);
+	if (ret)
+		return ret;
+
+	cfg = t->tx.buf;
+	cfg->flags = cpu_to_le32(config);
+	cfg->id = cpu_to_le32(clk_id);
+	cfg->value_low = cpu_to_le32(rate & 0xffffffff);
+	cfg->value_high = cpu_to_le32(rate >> 32);
+
+	ret = scmi_do_xfer(handle, t);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int
+scmi_clock_config_set(const struct scmi_handle *handle, u32 clk_id, u32 config)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_clock_set_config *cfg;
+
+	ret = scmi_one_xfer_init(handle, CLOCK_CONFIG_SET, SCMI_PROTOCOL_CLOCK,
+				 sizeof(*cfg), 0, &t);
+	if (ret)
+		return ret;
+
+	cfg = t->tx.buf;
+	cfg->id = cpu_to_le32(clk_id);
+	cfg->attributes = cpu_to_le32(config);
+
+	ret = scmi_do_xfer(handle, t);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int scmi_clock_enable(const struct scmi_handle *handle, u32 clk_id)
+{
+	return scmi_clock_config_set(handle, clk_id, CLOCK_ENABLE);
+}
+
+static int scmi_clock_disable(const struct scmi_handle *handle, u32 clk_id)
+{
+	return scmi_clock_config_set(handle, clk_id, 0);
+}
+
+static int scmi_clock_count_get(const struct scmi_handle *handle)
+{
+	return clocks.num_clocks;
+}
+
+static const struct scmi_clock_info *
+scmi_clock_info_get(const struct scmi_handle *handle, u32 clk_id)
+{
+	struct scmi_clock_info *clk = clocks.clk + clk_id;
+
+	if (!clk->name || !clk->name[0])
+		return NULL;
+
+	return clk;
+}
+
+static struct scmi_clk_ops clk_ops = {
+	.count_get = scmi_clock_count_get,
+	.info_get = scmi_clock_info_get,
+	.rate_get = scmi_clock_rate_get,
+	.rate_set = scmi_clock_rate_set,
+	.enable = scmi_clock_enable,
+	.disable = scmi_clock_disable,
+};
+
+int scmi_clock_protocol_init(struct scmi_handle *handle)
+{
+	int clkid, ret;
+	u32 version;
+
+	scmi_version_get(handle, SCMI_PROTOCOL_CLOCK, &version);
+
+	dev_dbg(handle->dev, "Clock Version %d.%d\n",
+		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
+
+	scmi_clock_protocol_attributes_get(handle, &clocks);
+
+	clocks.clk = devm_kcalloc(handle->dev, clocks.num_clocks,
+				  sizeof(struct scmi_clock_info), GFP_KERNEL);
+	if (!clocks.clk)
+		return -ENOMEM;
+
+	for (clkid = 0; clkid < clocks.num_clocks; clkid++) {
+		struct scmi_clock_info *clk = clocks.clk + clkid;
+
+		ret = scmi_clock_attributes_get(handle, clkid, clk);
+		if (!ret)
+			scmi_clock_describe_rates_get(handle, clkid, clk);
+	}
+
+	handle->clk_ops = &clk_ops;
+
+	return 0;
+}
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index c9f97e69444a..c15f37c86025 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -18,6 +18,7 @@
 #include <linux/types.h>
 
 #define SCMI_MAX_STR_SIZE	16
+#define SCMI_MAX_NUM_RATES	16
 
 /**
  * struct scmi_revision_info - version information structure
@@ -43,9 +44,46 @@ struct scmi_revision_info {
 	char sub_vendor_id[SCMI_MAX_STR_SIZE];
 };
 
+struct scmi_clock_info {
+	char name[SCMI_MAX_STR_SIZE];
+	bool rate_discrete;
+	union {
+		struct {
+			int num_rates;
+			u64 rates[SCMI_MAX_NUM_RATES];
+		} list;
+		struct {
+			u64 min_rate;
+			u64 max_rate;
+			u64 step_size;
+		} range;
+	};
+};
+
 struct scmi_handle;
 
 /**
+ * struct scmi_clk_ops - represents the various operations provided
+ *	by SCMI Clock Protocol
+ *
+ * @count_get: get the count of clocks provided by SCMI
+ * @info_get: get the information of the specified clock
+ * @rate_get: request the current clock rate of a clock
+ * @rate_set: set the clock rate of a clock
+ * @enable: enables the specified clock
+ * @disable: disables the specified clock
+ */
+struct scmi_clk_ops {
+	int (*count_get)(const struct scmi_handle *);
+	const struct scmi_clock_info *(*info_get)(const struct scmi_handle *,
+						  u32);
+	int (*rate_get)(const struct scmi_handle *, u32, u64*);
+	int (*rate_set)(const struct scmi_handle *, u32, u32, u64);
+	int (*enable)(const struct scmi_handle *, u32);
+	int (*disable)(const struct scmi_handle *, u32);
+};
+
+/**
  * struct scmi_perf_ops - represents the various operations provided
  *	by SCMI Performance Protocol
  *
@@ -78,11 +116,13 @@ struct scmi_perf_ops {
  * @dev: pointer to the SCMI device
  * @version: pointer to the structure containing SCMI version information
  * @perf_ops: pointer to set of performance protocol operations
+ * @clk_ops: pointer to set of clock protocol operations
  */
 struct scmi_handle {
 	struct device *dev;
 	struct scmi_revision_info *version;
 	struct scmi_perf_ops *perf_ops;
+	struct scmi_clk_ops *clk_ops;
 };
 
 #if IS_REACHABLE(CONFIG_ARM_SCMI_PROTOCOL)
-- 
2.7.4

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

* [PATCH v3 07/22] firmware: arm_scmi: add initial support for clock protocol
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

The clock protocol is intended for management of clocks. It is used to
enable or disable clocks, and to set and get the clock rates. This
protocol provides commands to describe the protocol version, discover
various implementation specific attributes, describe a clock, enable
and disable a clock and get/set the rate of the clock synchronously or
asynchronously.

This patch adds initial support for the clock protocol.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scmi/Makefile |   2 +-
 drivers/firmware/arm_scmi/clock.c  | 339 +++++++++++++++++++++++++++++++++++++
 include/linux/scmi_protocol.h      |  40 +++++
 3 files changed, 380 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/arm_scmi/clock.c

diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index 159de726ee45..6836b1f38f7f 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_ARM_SCMI_PROTOCOL)	= arm_scmi.o
-arm_scmi-y = base.o driver.o perf.o
+arm_scmi-y = base.o clock.o driver.o perf.o
diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c
new file mode 100644
index 000000000000..87d0befab07d
--- /dev/null
+++ b/drivers/firmware/arm_scmi/clock.c
@@ -0,0 +1,339 @@
+/*
+ * System Control and Management Interface (SCMI) Clock Protocol
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "common.h"
+
+enum scmi_clock_protocol_cmd {
+	CLOCK_ATTRIBUTES = 0x3,
+	CLOCK_DESCRIBE_RATES = 0x4,
+	CLOCK_RATE_SET = 0x5,
+	CLOCK_RATE_GET = 0x6,
+	CLOCK_CONFIG_SET = 0x7,
+};
+
+struct scmi_msg_resp_clock_protocol_attributes {
+	__le16 num_clocks;
+	    u8 max_async_req;
+	    u8 reserved;
+};
+
+struct scmi_msg_resp_clock_attributes {
+	__le32 attributes;
+#define	CLOCK_ENABLE	BIT(0)
+	    u8 name[SCMI_MAX_STR_SIZE];
+};
+
+struct scmi_clock_set_config {
+	__le32 id;
+	__le32 attributes;
+};
+
+struct scmi_msg_clock_describe_rates {
+	__le32 id;
+	__le32 rate_index;
+};
+
+struct scmi_msg_resp_clock_describe_rates {
+	__le32 num_rates_flags;
+#define NUM_RETURNED(x)		((x) & 0xfff)
+#define RATE_DISCRETE(x)	!((x) & BIT(12))
+#define NUM_REMAINING(x)	((x) >> 16)
+	struct {
+		__le32 value_low;
+		__le32 value_high;
+	} rate[0];
+#define RATE_TO_U64(X)		\
+({				\
+	typeof(X) x = (X);	\
+	le32_to_cpu((x).value_low) | (u64)le32_to_cpu((x).value_high) << 32; \
+})
+};
+
+struct scmi_clock_set_rate {
+	__le32 flags;
+#define CLOCK_SET_ASYNC		BIT(0)
+#define CLOCK_SET_DELAYED	BIT(1)
+#define CLOCK_SET_ROUND_UP	BIT(2)
+#define CLOCK_SET_ROUND_AUTO	BIT(3)
+	__le32 id;
+	__le32 value_low;
+	__le32 value_high;
+};
+
+struct clock_info {
+	int num_clocks;
+	int max_async_req;
+	struct scmi_clock_info *clk;
+};
+
+static struct clock_info clocks;
+
+static int scmi_clock_protocol_attributes_get(const struct scmi_handle *handle,
+					      struct clock_info *clocks)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_msg_resp_clock_protocol_attributes *attr;
+
+	ret = scmi_one_xfer_init(handle, PROTOCOL_ATTRIBUTES,
+				 SCMI_PROTOCOL_CLOCK, 0, sizeof(*attr), &t);
+	if (ret)
+		return ret;
+
+	attr = t->rx.buf;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		clocks->num_clocks = le16_to_cpu(attr->num_clocks);
+		clocks->max_async_req = attr->max_async_req;
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int scmi_clock_attributes_get(const struct scmi_handle *handle,
+				     u32 clk_id, struct scmi_clock_info *clk)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_msg_resp_clock_attributes *attr;
+
+	ret = scmi_one_xfer_init(handle, CLOCK_ATTRIBUTES, SCMI_PROTOCOL_CLOCK,
+				 sizeof(clk_id), sizeof(*attr), &t);
+	if (ret)
+		return ret;
+
+	*(__le32 *)t->tx.buf = cpu_to_le32(clk_id);
+	attr = t->rx.buf;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret)
+		memcpy(clk->name, attr->name, SCMI_MAX_STR_SIZE);
+	else
+		clk->name[0] = '\0';
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int
+scmi_clock_describe_rates_get(const struct scmi_handle *handle, u32 clk_id,
+			      struct scmi_clock_info *clk)
+{
+	u64 *rate;
+	int ret, cnt;
+	bool rate_discrete;
+	u32 tot_rate_cnt = 0, rates_flag;
+	u16 num_returned, num_remaining;
+	struct scmi_xfer *t;
+	struct scmi_msg_clock_describe_rates *clk_desc;
+	struct scmi_msg_resp_clock_describe_rates *rlist;
+
+	ret = scmi_one_xfer_init(handle, CLOCK_DESCRIBE_RATES,
+				 SCMI_PROTOCOL_CLOCK, sizeof(*clk_desc), 0, &t);
+	if (ret)
+		return ret;
+
+	clk_desc = t->tx.buf;
+	rlist = t->rx.buf;
+
+	do {
+		clk_desc->id = cpu_to_le32(clk_id);
+		/* Set the number of rates to be skipped/already read */
+		clk_desc->rate_index = cpu_to_le32(tot_rate_cnt);
+
+		ret = scmi_do_xfer(handle, t);
+		if (ret)
+			break;
+
+		rates_flag = le32_to_cpu(rlist->num_rates_flags);
+		num_remaining = NUM_REMAINING(rates_flag);
+		rate_discrete = RATE_DISCRETE(rates_flag);
+		num_returned = NUM_RETURNED(rates_flag);
+
+		if (tot_rate_cnt + num_returned > SCMI_MAX_NUM_RATES) {
+			dev_err(handle->dev, "No. of rates > MAX_NUM_RATES");
+			break;
+		}
+
+		if (!rate_discrete) {
+			clk->range.min_rate = RATE_TO_U64(rlist->rate[0]);
+			clk->range.max_rate = RATE_TO_U64(rlist->rate[1]);
+			clk->range.step_size = RATE_TO_U64(rlist->rate[2]);
+			dev_dbg(handle->dev, "Min %llu Max %llu Step %llu Hz\n",
+				clk->range.min_rate, clk->range.max_rate,
+				clk->range.step_size);
+			break;
+		}
+
+		rate = &clk->list.rates[tot_rate_cnt];
+		for (cnt = 0; cnt < num_returned; cnt++, rate++) {
+			*rate = RATE_TO_U64(rlist->rate[cnt]);
+			dev_dbg(handle->dev, "Rate %llu Hz\n", *rate);
+		}
+
+		tot_rate_cnt += num_returned;
+		/*
+		 * check for both returned and remaining to avoid infinite
+		 * loop due to buggy firmware
+		 */
+	} while (num_returned && num_remaining);
+
+	if (rate_discrete)
+		clk->list.num_rates = tot_rate_cnt;
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int
+scmi_clock_rate_get(const struct scmi_handle *handle, u32 clk_id, u64 *value)
+{
+	int ret;
+	struct scmi_xfer *t;
+
+	ret = scmi_one_xfer_init(handle, CLOCK_RATE_GET, SCMI_PROTOCOL_CLOCK,
+				 sizeof(__le32), sizeof(u64), &t);
+	if (ret)
+		return ret;
+
+	*(__le32 *)t->tx.buf = cpu_to_le32(clk_id);
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		__le32 *pval = t->rx.buf;
+
+		*value = le32_to_cpu(*pval);
+		*value |= (u64)le32_to_cpu(*(pval + 1)) << 32;
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int scmi_clock_rate_set(const struct scmi_handle *handle, u32 clk_id,
+			       u32 config, u64 rate)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_clock_set_rate *cfg;
+
+	ret = scmi_one_xfer_init(handle, CLOCK_RATE_SET, SCMI_PROTOCOL_CLOCK,
+				 sizeof(*cfg), 0, &t);
+	if (ret)
+		return ret;
+
+	cfg = t->tx.buf;
+	cfg->flags = cpu_to_le32(config);
+	cfg->id = cpu_to_le32(clk_id);
+	cfg->value_low = cpu_to_le32(rate & 0xffffffff);
+	cfg->value_high = cpu_to_le32(rate >> 32);
+
+	ret = scmi_do_xfer(handle, t);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int
+scmi_clock_config_set(const struct scmi_handle *handle, u32 clk_id, u32 config)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_clock_set_config *cfg;
+
+	ret = scmi_one_xfer_init(handle, CLOCK_CONFIG_SET, SCMI_PROTOCOL_CLOCK,
+				 sizeof(*cfg), 0, &t);
+	if (ret)
+		return ret;
+
+	cfg = t->tx.buf;
+	cfg->id = cpu_to_le32(clk_id);
+	cfg->attributes = cpu_to_le32(config);
+
+	ret = scmi_do_xfer(handle, t);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int scmi_clock_enable(const struct scmi_handle *handle, u32 clk_id)
+{
+	return scmi_clock_config_set(handle, clk_id, CLOCK_ENABLE);
+}
+
+static int scmi_clock_disable(const struct scmi_handle *handle, u32 clk_id)
+{
+	return scmi_clock_config_set(handle, clk_id, 0);
+}
+
+static int scmi_clock_count_get(const struct scmi_handle *handle)
+{
+	return clocks.num_clocks;
+}
+
+static const struct scmi_clock_info *
+scmi_clock_info_get(const struct scmi_handle *handle, u32 clk_id)
+{
+	struct scmi_clock_info *clk = clocks.clk + clk_id;
+
+	if (!clk->name || !clk->name[0])
+		return NULL;
+
+	return clk;
+}
+
+static struct scmi_clk_ops clk_ops = {
+	.count_get = scmi_clock_count_get,
+	.info_get = scmi_clock_info_get,
+	.rate_get = scmi_clock_rate_get,
+	.rate_set = scmi_clock_rate_set,
+	.enable = scmi_clock_enable,
+	.disable = scmi_clock_disable,
+};
+
+int scmi_clock_protocol_init(struct scmi_handle *handle)
+{
+	int clkid, ret;
+	u32 version;
+
+	scmi_version_get(handle, SCMI_PROTOCOL_CLOCK, &version);
+
+	dev_dbg(handle->dev, "Clock Version %d.%d\n",
+		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
+
+	scmi_clock_protocol_attributes_get(handle, &clocks);
+
+	clocks.clk = devm_kcalloc(handle->dev, clocks.num_clocks,
+				  sizeof(struct scmi_clock_info), GFP_KERNEL);
+	if (!clocks.clk)
+		return -ENOMEM;
+
+	for (clkid = 0; clkid < clocks.num_clocks; clkid++) {
+		struct scmi_clock_info *clk = clocks.clk + clkid;
+
+		ret = scmi_clock_attributes_get(handle, clkid, clk);
+		if (!ret)
+			scmi_clock_describe_rates_get(handle, clkid, clk);
+	}
+
+	handle->clk_ops = &clk_ops;
+
+	return 0;
+}
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index c9f97e69444a..c15f37c86025 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -18,6 +18,7 @@
 #include <linux/types.h>
 
 #define SCMI_MAX_STR_SIZE	16
+#define SCMI_MAX_NUM_RATES	16
 
 /**
  * struct scmi_revision_info - version information structure
@@ -43,9 +44,46 @@ struct scmi_revision_info {
 	char sub_vendor_id[SCMI_MAX_STR_SIZE];
 };
 
+struct scmi_clock_info {
+	char name[SCMI_MAX_STR_SIZE];
+	bool rate_discrete;
+	union {
+		struct {
+			int num_rates;
+			u64 rates[SCMI_MAX_NUM_RATES];
+		} list;
+		struct {
+			u64 min_rate;
+			u64 max_rate;
+			u64 step_size;
+		} range;
+	};
+};
+
 struct scmi_handle;
 
 /**
+ * struct scmi_clk_ops - represents the various operations provided
+ *	by SCMI Clock Protocol
+ *
+ * @count_get: get the count of clocks provided by SCMI
+ * @info_get: get the information of the specified clock
+ * @rate_get: request the current clock rate of a clock
+ * @rate_set: set the clock rate of a clock
+ * @enable: enables the specified clock
+ * @disable: disables the specified clock
+ */
+struct scmi_clk_ops {
+	int (*count_get)(const struct scmi_handle *);
+	const struct scmi_clock_info *(*info_get)(const struct scmi_handle *,
+						  u32);
+	int (*rate_get)(const struct scmi_handle *, u32, u64*);
+	int (*rate_set)(const struct scmi_handle *, u32, u32, u64);
+	int (*enable)(const struct scmi_handle *, u32);
+	int (*disable)(const struct scmi_handle *, u32);
+};
+
+/**
  * struct scmi_perf_ops - represents the various operations provided
  *	by SCMI Performance Protocol
  *
@@ -78,11 +116,13 @@ struct scmi_perf_ops {
  * @dev: pointer to the SCMI device
  * @version: pointer to the structure containing SCMI version information
  * @perf_ops: pointer to set of performance protocol operations
+ * @clk_ops: pointer to set of clock protocol operations
  */
 struct scmi_handle {
 	struct device *dev;
 	struct scmi_revision_info *version;
 	struct scmi_perf_ops *perf_ops;
+	struct scmi_clk_ops *clk_ops;
 };
 
 #if IS_REACHABLE(CONFIG_ARM_SCMI_PROTOCOL)
-- 
2.7.4

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

* [PATCH v3 08/22] firmware: arm_scmi: add initial support for power protocol
  2017-09-28 13:11 ` Sudeep Holla
@ 2017-09-28 13:11   ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

The power protocol is intended for management of power states of various
power domains. The power domain management protocol provides commands to
describe the protocol version, discover the implementation specific
attributes, set and get the power state of a domain.

This patch adds support for the above mention features of the protocol.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
--
 drivers/firmware/arm_scmi/Makefile |   2 +-
 drivers/firmware/arm_scmi/power.c  | 242 +++++++++++++++++++++++++++++++++++++
 include/linux/scmi_protocol.h      |  28 +++++
 3 files changed, 271 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/arm_scmi/power.c
---
 drivers/firmware/arm_scmi/Makefile |   2 +-
 drivers/firmware/arm_scmi/power.c  | 242 +++++++++++++++++++++++++++++++++++++
 include/linux/scmi_protocol.h      |  28 +++++
 3 files changed, 271 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/arm_scmi/power.c

diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index 6836b1f38f7f..52ecc08556a2 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_ARM_SCMI_PROTOCOL)	= arm_scmi.o
-arm_scmi-y = base.o clock.o driver.o perf.o
+arm_scmi-y = base.o clock.o driver.o perf.o power.o
diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c
new file mode 100644
index 000000000000..34c45f101abb
--- /dev/null
+++ b/drivers/firmware/arm_scmi/power.c
@@ -0,0 +1,242 @@
+/*
+ * System Control and Management Interface (SCMI) Power Protocol
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "common.h"
+
+enum scmi_power_protocol_cmd {
+	POWER_DOMAIN_ATTRIBUTES = 0x3,
+	POWER_STATE_SET = 0x4,
+	POWER_STATE_GET = 0x5,
+	POWER_STATE_NOTIFY = 0x6,
+};
+
+struct scmi_msg_resp_power_attributes {
+	__le16 num_domains;
+	__le16 reserved;
+	__le32 stats_addr_low;
+	__le32 stats_addr_high;
+	__le32 stats_size;
+};
+
+struct scmi_msg_resp_power_domain_attributes {
+	__le32 flags;
+#define SUPPORTS_STATE_SET_NOTIFY(x)	((x) & BIT(31))
+#define SUPPORTS_STATE_SET_ASYNC(x)	((x) & BIT(30))
+#define SUPPORTS_STATE_SET_SYNC(x)	((x) & BIT(29))
+	    u8 name[SCMI_MAX_STR_SIZE];
+};
+
+struct scmi_power_set_state {
+	__le32 flags;
+#define STATE_SET_ASYNC		BIT(0)
+	__le32 domain;
+	__le32 state;
+};
+
+struct scmi_power_state_notify {
+	__le32 domain;
+	__le32 notify_enable;
+};
+
+struct power_dom_info {
+	bool state_set_sync;
+	bool state_set_async;
+	bool state_set_notify;
+	char name[SCMI_MAX_STR_SIZE];
+};
+
+struct scmi_power_info {
+	int num_domains;
+	u64 stats_addr;
+	u32 stats_size;
+	struct power_dom_info *dom_info;
+};
+
+static struct scmi_power_info power_info;
+
+static int scmi_power_attributes_get(const struct scmi_handle *handle,
+				     struct scmi_power_info *power_info)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_msg_resp_power_attributes *attr;
+
+	ret = scmi_one_xfer_init(handle, PROTOCOL_ATTRIBUTES,
+				 SCMI_PROTOCOL_POWER, 0, sizeof(*attr), &t);
+	if (ret)
+		return ret;
+
+	attr = t->rx.buf;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		power_info->num_domains = le16_to_cpu(attr->num_domains);
+		power_info->stats_addr = le32_to_cpu(attr->stats_addr_low) |
+				(u64)le32_to_cpu(attr->stats_addr_high) << 32;
+		power_info->stats_size = le32_to_cpu(attr->stats_size);
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int
+scmi_power_domain_attributes_get(const struct scmi_handle *handle, u32 domain,
+				 struct power_dom_info *dom_info)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_msg_resp_power_domain_attributes *attr;
+
+	ret = scmi_one_xfer_init(handle, POWER_DOMAIN_ATTRIBUTES,
+				 SCMI_PROTOCOL_POWER, sizeof(domain),
+				 sizeof(*attr), &t);
+	if (ret)
+		return ret;
+
+	*(__le32 *)t->tx.buf = cpu_to_le32(domain);
+	attr = t->rx.buf;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		u32 flags = le32_to_cpu(attr->flags);
+
+		dom_info->state_set_notify = SUPPORTS_STATE_SET_NOTIFY(flags);
+		dom_info->state_set_async = SUPPORTS_STATE_SET_ASYNC(flags);
+		dom_info->state_set_sync = SUPPORTS_STATE_SET_SYNC(flags);
+		memcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE);
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int
+scmi_power_state_set(const struct scmi_handle *handle, u32 domain, u32 state)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_power_set_state *st;
+
+	ret = scmi_one_xfer_init(handle, POWER_STATE_SET, SCMI_PROTOCOL_POWER,
+				 sizeof(*st), 0, &t);
+	if (ret)
+		return ret;
+
+	st = t->tx.buf;
+	st->flags = cpu_to_le32(0);
+	st->domain = cpu_to_le32(domain);
+	st->state = cpu_to_le32(state);
+
+	ret = scmi_do_xfer(handle, t);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int
+scmi_power_state_get(const struct scmi_handle *handle, u32 domain, u32 *state)
+{
+	int ret;
+	struct scmi_xfer *t;
+
+	ret = scmi_one_xfer_init(handle, POWER_STATE_GET, SCMI_PROTOCOL_POWER,
+				 sizeof(u32), sizeof(u32), &t);
+	if (ret)
+		return ret;
+
+	*(__le32 *)t->tx.buf = cpu_to_le32(domain);
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret)
+		*state = le32_to_cpu(*(__le32 *)t->rx.buf);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int scmi_power_state_notify_enable(const struct scmi_handle *handle,
+					  u32 domain, bool enable)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_power_state_notify *notify;
+
+	ret = scmi_one_xfer_init(handle, POWER_STATE_NOTIFY,
+				 SCMI_PROTOCOL_POWER, sizeof(*notify), 0, &t);
+	if (ret)
+		return ret;
+
+	notify = t->tx.buf;
+	notify->domain = cpu_to_le32(domain);
+	notify->notify_enable = cpu_to_le32(enable & BIT(0));
+
+	ret = scmi_do_xfer(handle, t);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int scmi_power_num_domains_get(const struct scmi_handle *handle)
+{
+	return power_info.num_domains;
+}
+
+static char *scmi_power_name_get(const struct scmi_handle *handle, u32 domain)
+{
+	struct power_dom_info *dom = power_info.dom_info + domain;
+
+	return dom->name;
+}
+
+static struct scmi_power_ops power_ops = {
+	.num_domains_get = scmi_power_num_domains_get,
+	.name_get = scmi_power_name_get,
+	.state_set = scmi_power_state_set,
+	.state_get = scmi_power_state_get,
+	.state_notify_enable = scmi_power_state_notify_enable,
+};
+
+int scmi_power_protocol_init(struct scmi_handle *handle)
+{
+	u32 version;
+	int domain;
+
+	scmi_version_get(handle, SCMI_PROTOCOL_POWER, &version);
+
+	dev_dbg(handle->dev, "Power Version %d.%d\n",
+		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
+
+	scmi_power_attributes_get(handle, &power_info);
+
+	power_info.dom_info = devm_kcalloc(handle->dev, power_info.num_domains,
+					   sizeof(struct power_dom_info),
+					   GFP_KERNEL);
+	if (!power_info.dom_info)
+		return -ENOMEM;
+
+	for (domain = 0; domain < power_info.num_domains; domain++) {
+		struct power_dom_info *dom = power_info.dom_info + domain;
+
+		scmi_power_domain_attributes_get(handle, domain, dom);
+	}
+
+	handle->power_ops = &power_ops;
+
+	return 0;
+}
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index c15f37c86025..e5a80511f88c 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -111,16 +111,44 @@ struct scmi_perf_ops {
 };
 
 /**
+ * struct scmi_power_ops - represents the various operations provided
+ *	by SCMI Power Protocol
+ *
+ * @num_domains_get: get the count of power domains provided by SCMI
+ * @name_get: gets the name of a power domain
+ * @state_set: sets the power state of a power domain
+ * @state_get: gets the power state of a power domain
+ * @state_notify_enable: request notifications from the platform for
+ *	state changes in a specific power domain
+ */
+struct scmi_power_ops {
+	int (*num_domains_get)(const struct scmi_handle *);
+	char *(*name_get)(const struct scmi_handle *, u32);
+#define SCMI_POWER_STATE_TYPE_SHIFT	30
+#define SCMI_POWER_STATE_ID_MASK	(BIT(28) - 1)
+#define SCMI_POWER_STATE_PARAM(type, id) \
+	((((type) & BIT(0)) << SCMI_POWER_STATE_TYPE_SHIFT) | \
+		((id) & SCMI_POWER_STATE_ID_MASK))
+#define SCMI_POWER_STATE_GENERIC_ON	SCMI_POWER_STATE_PARAM(0, 0)
+#define SCMI_POWER_STATE_GENERIC_OFF	SCMI_POWER_STATE_PARAM(1, 0)
+	int (*state_set)(const struct scmi_handle *, u32, u32);
+	int (*state_get)(const struct scmi_handle *, u32, u32 *);
+	int (*state_notify_enable)(const struct scmi_handle *, u32, bool);
+};
+
+/**
  * struct scmi_handle - Handle returned to ARM SCMI clients for usage.
  *
  * @dev: pointer to the SCMI device
  * @version: pointer to the structure containing SCMI version information
+ * @power_ops: pointer to set of power protocol operations
  * @perf_ops: pointer to set of performance protocol operations
  * @clk_ops: pointer to set of clock protocol operations
  */
 struct scmi_handle {
 	struct device *dev;
 	struct scmi_revision_info *version;
+	struct scmi_power_ops *power_ops;
 	struct scmi_perf_ops *perf_ops;
 	struct scmi_clk_ops *clk_ops;
 };
-- 
2.7.4

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

* [PATCH v3 08/22] firmware: arm_scmi: add initial support for power protocol
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

The power protocol is intended for management of power states of various
power domains. The power domain management protocol provides commands to
describe the protocol version, discover the implementation specific
attributes, set and get the power state of a domain.

This patch adds support for the above mention features of the protocol.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
--
 drivers/firmware/arm_scmi/Makefile |   2 +-
 drivers/firmware/arm_scmi/power.c  | 242 +++++++++++++++++++++++++++++++++++++
 include/linux/scmi_protocol.h      |  28 +++++
 3 files changed, 271 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/arm_scmi/power.c
---
 drivers/firmware/arm_scmi/Makefile |   2 +-
 drivers/firmware/arm_scmi/power.c  | 242 +++++++++++++++++++++++++++++++++++++
 include/linux/scmi_protocol.h      |  28 +++++
 3 files changed, 271 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/arm_scmi/power.c

diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index 6836b1f38f7f..52ecc08556a2 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_ARM_SCMI_PROTOCOL)	= arm_scmi.o
-arm_scmi-y = base.o clock.o driver.o perf.o
+arm_scmi-y = base.o clock.o driver.o perf.o power.o
diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c
new file mode 100644
index 000000000000..34c45f101abb
--- /dev/null
+++ b/drivers/firmware/arm_scmi/power.c
@@ -0,0 +1,242 @@
+/*
+ * System Control and Management Interface (SCMI) Power Protocol
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "common.h"
+
+enum scmi_power_protocol_cmd {
+	POWER_DOMAIN_ATTRIBUTES = 0x3,
+	POWER_STATE_SET = 0x4,
+	POWER_STATE_GET = 0x5,
+	POWER_STATE_NOTIFY = 0x6,
+};
+
+struct scmi_msg_resp_power_attributes {
+	__le16 num_domains;
+	__le16 reserved;
+	__le32 stats_addr_low;
+	__le32 stats_addr_high;
+	__le32 stats_size;
+};
+
+struct scmi_msg_resp_power_domain_attributes {
+	__le32 flags;
+#define SUPPORTS_STATE_SET_NOTIFY(x)	((x) & BIT(31))
+#define SUPPORTS_STATE_SET_ASYNC(x)	((x) & BIT(30))
+#define SUPPORTS_STATE_SET_SYNC(x)	((x) & BIT(29))
+	    u8 name[SCMI_MAX_STR_SIZE];
+};
+
+struct scmi_power_set_state {
+	__le32 flags;
+#define STATE_SET_ASYNC		BIT(0)
+	__le32 domain;
+	__le32 state;
+};
+
+struct scmi_power_state_notify {
+	__le32 domain;
+	__le32 notify_enable;
+};
+
+struct power_dom_info {
+	bool state_set_sync;
+	bool state_set_async;
+	bool state_set_notify;
+	char name[SCMI_MAX_STR_SIZE];
+};
+
+struct scmi_power_info {
+	int num_domains;
+	u64 stats_addr;
+	u32 stats_size;
+	struct power_dom_info *dom_info;
+};
+
+static struct scmi_power_info power_info;
+
+static int scmi_power_attributes_get(const struct scmi_handle *handle,
+				     struct scmi_power_info *power_info)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_msg_resp_power_attributes *attr;
+
+	ret = scmi_one_xfer_init(handle, PROTOCOL_ATTRIBUTES,
+				 SCMI_PROTOCOL_POWER, 0, sizeof(*attr), &t);
+	if (ret)
+		return ret;
+
+	attr = t->rx.buf;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		power_info->num_domains = le16_to_cpu(attr->num_domains);
+		power_info->stats_addr = le32_to_cpu(attr->stats_addr_low) |
+				(u64)le32_to_cpu(attr->stats_addr_high) << 32;
+		power_info->stats_size = le32_to_cpu(attr->stats_size);
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int
+scmi_power_domain_attributes_get(const struct scmi_handle *handle, u32 domain,
+				 struct power_dom_info *dom_info)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_msg_resp_power_domain_attributes *attr;
+
+	ret = scmi_one_xfer_init(handle, POWER_DOMAIN_ATTRIBUTES,
+				 SCMI_PROTOCOL_POWER, sizeof(domain),
+				 sizeof(*attr), &t);
+	if (ret)
+		return ret;
+
+	*(__le32 *)t->tx.buf = cpu_to_le32(domain);
+	attr = t->rx.buf;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		u32 flags = le32_to_cpu(attr->flags);
+
+		dom_info->state_set_notify = SUPPORTS_STATE_SET_NOTIFY(flags);
+		dom_info->state_set_async = SUPPORTS_STATE_SET_ASYNC(flags);
+		dom_info->state_set_sync = SUPPORTS_STATE_SET_SYNC(flags);
+		memcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE);
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int
+scmi_power_state_set(const struct scmi_handle *handle, u32 domain, u32 state)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_power_set_state *st;
+
+	ret = scmi_one_xfer_init(handle, POWER_STATE_SET, SCMI_PROTOCOL_POWER,
+				 sizeof(*st), 0, &t);
+	if (ret)
+		return ret;
+
+	st = t->tx.buf;
+	st->flags = cpu_to_le32(0);
+	st->domain = cpu_to_le32(domain);
+	st->state = cpu_to_le32(state);
+
+	ret = scmi_do_xfer(handle, t);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int
+scmi_power_state_get(const struct scmi_handle *handle, u32 domain, u32 *state)
+{
+	int ret;
+	struct scmi_xfer *t;
+
+	ret = scmi_one_xfer_init(handle, POWER_STATE_GET, SCMI_PROTOCOL_POWER,
+				 sizeof(u32), sizeof(u32), &t);
+	if (ret)
+		return ret;
+
+	*(__le32 *)t->tx.buf = cpu_to_le32(domain);
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret)
+		*state = le32_to_cpu(*(__le32 *)t->rx.buf);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int scmi_power_state_notify_enable(const struct scmi_handle *handle,
+					  u32 domain, bool enable)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_power_state_notify *notify;
+
+	ret = scmi_one_xfer_init(handle, POWER_STATE_NOTIFY,
+				 SCMI_PROTOCOL_POWER, sizeof(*notify), 0, &t);
+	if (ret)
+		return ret;
+
+	notify = t->tx.buf;
+	notify->domain = cpu_to_le32(domain);
+	notify->notify_enable = cpu_to_le32(enable & BIT(0));
+
+	ret = scmi_do_xfer(handle, t);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int scmi_power_num_domains_get(const struct scmi_handle *handle)
+{
+	return power_info.num_domains;
+}
+
+static char *scmi_power_name_get(const struct scmi_handle *handle, u32 domain)
+{
+	struct power_dom_info *dom = power_info.dom_info + domain;
+
+	return dom->name;
+}
+
+static struct scmi_power_ops power_ops = {
+	.num_domains_get = scmi_power_num_domains_get,
+	.name_get = scmi_power_name_get,
+	.state_set = scmi_power_state_set,
+	.state_get = scmi_power_state_get,
+	.state_notify_enable = scmi_power_state_notify_enable,
+};
+
+int scmi_power_protocol_init(struct scmi_handle *handle)
+{
+	u32 version;
+	int domain;
+
+	scmi_version_get(handle, SCMI_PROTOCOL_POWER, &version);
+
+	dev_dbg(handle->dev, "Power Version %d.%d\n",
+		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
+
+	scmi_power_attributes_get(handle, &power_info);
+
+	power_info.dom_info = devm_kcalloc(handle->dev, power_info.num_domains,
+					   sizeof(struct power_dom_info),
+					   GFP_KERNEL);
+	if (!power_info.dom_info)
+		return -ENOMEM;
+
+	for (domain = 0; domain < power_info.num_domains; domain++) {
+		struct power_dom_info *dom = power_info.dom_info + domain;
+
+		scmi_power_domain_attributes_get(handle, domain, dom);
+	}
+
+	handle->power_ops = &power_ops;
+
+	return 0;
+}
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index c15f37c86025..e5a80511f88c 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -111,16 +111,44 @@ struct scmi_perf_ops {
 };
 
 /**
+ * struct scmi_power_ops - represents the various operations provided
+ *	by SCMI Power Protocol
+ *
+ * @num_domains_get: get the count of power domains provided by SCMI
+ * @name_get: gets the name of a power domain
+ * @state_set: sets the power state of a power domain
+ * @state_get: gets the power state of a power domain
+ * @state_notify_enable: request notifications from the platform for
+ *	state changes in a specific power domain
+ */
+struct scmi_power_ops {
+	int (*num_domains_get)(const struct scmi_handle *);
+	char *(*name_get)(const struct scmi_handle *, u32);
+#define SCMI_POWER_STATE_TYPE_SHIFT	30
+#define SCMI_POWER_STATE_ID_MASK	(BIT(28) - 1)
+#define SCMI_POWER_STATE_PARAM(type, id) \
+	((((type) & BIT(0)) << SCMI_POWER_STATE_TYPE_SHIFT) | \
+		((id) & SCMI_POWER_STATE_ID_MASK))
+#define SCMI_POWER_STATE_GENERIC_ON	SCMI_POWER_STATE_PARAM(0, 0)
+#define SCMI_POWER_STATE_GENERIC_OFF	SCMI_POWER_STATE_PARAM(1, 0)
+	int (*state_set)(const struct scmi_handle *, u32, u32);
+	int (*state_get)(const struct scmi_handle *, u32, u32 *);
+	int (*state_notify_enable)(const struct scmi_handle *, u32, bool);
+};
+
+/**
  * struct scmi_handle - Handle returned to ARM SCMI clients for usage.
  *
  * @dev: pointer to the SCMI device
  * @version: pointer to the structure containing SCMI version information
+ * @power_ops: pointer to set of power protocol operations
  * @perf_ops: pointer to set of performance protocol operations
  * @clk_ops: pointer to set of clock protocol operations
  */
 struct scmi_handle {
 	struct device *dev;
 	struct scmi_revision_info *version;
+	struct scmi_power_ops *power_ops;
 	struct scmi_perf_ops *perf_ops;
 	struct scmi_clk_ops *clk_ops;
 };
-- 
2.7.4

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

* [PATCH v3 09/22] firmware: arm_scmi: add initial support for sensor protocol
  2017-09-28 13:11 ` Sudeep Holla
@ 2017-09-28 13:11   ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

The sensor protocol provides functions to manage platform sensors, and
provides the commands to describe the protocol version and the various
attribute flags. It also provides commands to discover various sensors
implemented and managed by the platform, read any sensor synchronously
or asynchronously as allowed by the platform, program sensor attributes
and/or configurations, if applicable.

This patch adds support for most of the above features.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scmi/Makefile  |   2 +-
 drivers/firmware/arm_scmi/sensors.c | 287 ++++++++++++++++++++++++++++++++++++
 include/linux/scmi_protocol.h       |  41 ++++++
 3 files changed, 329 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/arm_scmi/sensors.c

diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index 52ecc08556a2..f9dee5ad0aa0 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_ARM_SCMI_PROTOCOL)	= arm_scmi.o
-arm_scmi-y = base.o clock.o driver.o perf.o power.o
+arm_scmi-y = base.o clock.o driver.o perf.o power.o sensors.o
diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c
new file mode 100644
index 000000000000..c868ccb7d6a3
--- /dev/null
+++ b/drivers/firmware/arm_scmi/sensors.c
@@ -0,0 +1,287 @@
+/*
+ * System Control and Management Interface (SCMI) Sensor Protocol
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "common.h"
+
+enum scmi_sensor_protocol_cmd {
+	SENSOR_DESCRIPTION_GET = 0x3,
+	SENSOR_CONFIG_SET = 0x4,
+	SENSOR_TRIP_POINT_SET = 0x5,
+	SENSOR_READING_GET = 0x6,
+};
+
+struct scmi_msg_resp_sensor_attributes {
+	__le16 num_sensors;
+	    u8 max_requests;
+	    u8 reserved;
+	__le32 reg_addr_low;
+	__le32 reg_addr_high;
+	__le32 reg_size;
+};
+
+struct scmi_msg_resp_sensor_description {
+	__le16 num_returned;
+	__le16 num_remaining;
+	struct {
+		__le32 id;
+		__le32 attributes_low;
+#define SUPPORTS_ASYNC_READ(x)	((x) & BIT(31))
+#define NUM_TRIP_POINTS(x)	(((x) >> 4) & 0xff)
+		__le32 attributes_high;
+#define SENSOR_TYPE(x)		((x) & 0xff)
+#define SENSOR_SCALE(x)		(((x) >> 11) & 0x3f)
+#define SENSOR_UPDATE_SCALE(x)	(((x) >> 22) & 0x1f)
+#define SENSOR_UPDATE_BASE(x)	(((x) >> 27) & 0x1f)
+		    u8 name[SCMI_MAX_STR_SIZE];
+	} desc[0];
+};
+
+struct scmi_msg_set_sensor_config {
+	__le32 id;
+	__le32 event_control;
+};
+
+struct scmi_msg_set_sensor_trip_point {
+	__le32 id;
+	__le32 event_control;
+#define SENSOR_TP_EVENT_MASK	(0x3)
+#define SENSOR_TP_DISABLED	0x0
+#define SENSOR_TP_POSITIVE	0x1
+#define SENSOR_TP_NEGATIVE	0x2
+#define SENSOR_TP_BOTH		0x3
+#define SENSOR_TP_ID(x)		(((x) & 0xff) << 4)
+	__le32 value_low;
+	__le32 value_high;
+};
+
+struct scmi_msg_sensor_reading_get {
+	__le32 id;
+	__le32 flags;
+#define SENSOR_READ_ASYNC	BIT(0)
+};
+
+struct sensors_info {
+	int num_sensors;
+	int max_requests;
+	u64 reg_addr;
+	u32 reg_size;
+	struct scmi_sensor_info *sensors;
+};
+
+static struct sensors_info sensor_info;
+
+static int scmi_sensor_attributes_get(const struct scmi_handle *handle,
+				      struct sensors_info *sensor_info)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_msg_resp_sensor_attributes *attr;
+
+	ret = scmi_one_xfer_init(handle, PROTOCOL_ATTRIBUTES,
+				 SCMI_PROTOCOL_SENSOR, 0, sizeof(*attr), &t);
+	if (ret)
+		return ret;
+
+	attr = t->rx.buf;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		sensor_info->num_sensors = le16_to_cpu(attr->num_sensors);
+		sensor_info->max_requests = attr->max_requests;
+		sensor_info->reg_addr = le32_to_cpu(attr->reg_addr_low) |
+				(u64)le32_to_cpu(attr->reg_addr_high) << 32;
+		sensor_info->reg_size = le32_to_cpu(attr->reg_size);
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int scmi_sensor_description_get(const struct scmi_handle *handle)
+{
+	int ret, cnt;
+	u32 desc_index = 0;
+	u16 num_returned, num_remaining;
+	struct scmi_xfer *t;
+	struct scmi_msg_resp_sensor_description *buf;
+
+	ret = scmi_one_xfer_init(handle, SENSOR_DESCRIPTION_GET,
+				 SCMI_PROTOCOL_SENSOR, sizeof(__le32), 0, &t);
+	if (ret)
+		return ret;
+
+	buf = t->rx.buf;
+
+	do {
+		/* Set the number of sensors to be skipped/already read */
+		*(__le32 *)t->tx.buf = cpu_to_le32(desc_index);
+
+		ret = scmi_do_xfer(handle, t);
+		if (ret)
+			break;
+
+		num_returned = le16_to_cpu(buf->num_returned);
+		num_remaining = le16_to_cpu(buf->num_remaining);
+
+		if (desc_index + num_returned > sensor_info.num_sensors) {
+			dev_err(handle->dev, "No. of sensors can't exceed %d",
+				sensor_info.num_sensors);
+			break;
+		}
+
+		for (cnt = 0; cnt < num_returned; cnt++) {
+			u32 attrh;
+			struct scmi_sensor_info *s;
+
+			attrh = le32_to_cpu(buf->desc[cnt].attributes_high);
+			s = &sensor_info.sensors[desc_index + cnt];
+			s->id = le32_to_cpu(buf->desc[cnt].id);
+			s->type = SENSOR_TYPE(attrh);
+			memcpy(s->name, buf->desc[cnt].name, SCMI_MAX_STR_SIZE);
+		}
+
+		desc_index += num_returned;
+		/*
+		 * check for both returned and remaining to avoid infinite
+		 * loop due to buggy firmware
+		 */
+	} while (num_returned && num_remaining);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int
+scmi_sensor_configuration_set(const struct scmi_handle *handle, u32 sensor_id)
+{
+	int ret;
+	u32 evt_cntl = BIT(0);
+	struct scmi_xfer *t;
+	struct scmi_msg_set_sensor_config *cfg;
+
+	ret = scmi_one_xfer_init(handle, SENSOR_CONFIG_SET,
+				 SCMI_PROTOCOL_SENSOR, sizeof(*cfg), 0, &t);
+	if (ret)
+		return ret;
+
+	cfg = t->tx.buf;
+	cfg->id = cpu_to_le32(sensor_id);
+	cfg->event_control = cpu_to_le32(evt_cntl);
+
+	ret = scmi_do_xfer(handle, t);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int scmi_sensor_trip_point_set(const struct scmi_handle *handle,
+				      u32 sensor_id, u8 trip_id, u64 trip_value)
+{
+	int ret;
+	u32 evt_cntl = SENSOR_TP_BOTH;
+	struct scmi_xfer *t;
+	struct scmi_msg_set_sensor_trip_point *trip;
+
+	ret = scmi_one_xfer_init(handle, SENSOR_TRIP_POINT_SET,
+				 SCMI_PROTOCOL_SENSOR, sizeof(*trip), 0, &t);
+	if (ret)
+		return ret;
+
+	trip = t->tx.buf;
+	trip->id = cpu_to_le32(sensor_id);
+	trip->event_control = cpu_to_le32(evt_cntl | SENSOR_TP_ID(trip_id));
+	trip->value_low = cpu_to_le32(trip_value & 0xffffffff);
+	trip->value_high = cpu_to_le32(trip_value >> 32);
+
+	ret = scmi_do_xfer(handle, t);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int scmi_sensor_reading_get(const struct scmi_handle *handle,
+				   u32 sensor_id, bool async, u64 *value)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_msg_sensor_reading_get *sensor;
+
+	ret = scmi_one_xfer_init(handle, SENSOR_READING_GET,
+				 SCMI_PROTOCOL_SENSOR, sizeof(*sensor),
+				 sizeof(u64), &t);
+	if (ret)
+		return ret;
+
+	sensor = t->tx.buf;
+	sensor->id = cpu_to_le32(sensor_id);
+	sensor->flags = cpu_to_le32(async ? SENSOR_READ_ASYNC : 0);
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		__le32 *pval = t->rx.buf;
+
+		*value = le32_to_cpu(*pval);
+		*value |= (u64)le32_to_cpu(*(pval + 1)) << 32;
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static const struct scmi_sensor_info *
+scmi_sensor_info_get(const struct scmi_handle *handle, u32 sensor_id)
+{
+	return sensor_info.sensors + sensor_id;
+}
+
+static int scmi_sensor_count_get(const struct scmi_handle *handle)
+{
+	return sensor_info.num_sensors;
+}
+
+static struct scmi_sensor_ops sensor_ops = {
+	.count_get = scmi_sensor_count_get,
+	.info_get = scmi_sensor_info_get,
+	.configuration_set = scmi_sensor_configuration_set,
+	.trip_point_set = scmi_sensor_trip_point_set,
+	.reading_get = scmi_sensor_reading_get,
+};
+
+int scmi_sensors_protocol_init(struct scmi_handle *handle)
+{
+	u32 version;
+
+	scmi_version_get(handle, SCMI_PROTOCOL_SENSOR, &version);
+
+	dev_dbg(handle->dev, "Sensor Version %d.%d\n",
+		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
+
+	scmi_sensor_attributes_get(handle, &sensor_info);
+
+	sensor_info.sensors = devm_kcalloc(handle->dev, sensor_info.num_sensors,
+					   sizeof(struct scmi_sensor_info),
+					   GFP_KERNEL);
+	if (!sensor_info.sensors)
+		return -ENOMEM;
+
+	scmi_sensor_description_get(handle);
+
+	handle->sensor_ops = &sensor_ops;
+
+	return 0;
+}
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index e5a80511f88c..5e29394b5cc9 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -136,6 +136,45 @@ struct scmi_power_ops {
 	int (*state_notify_enable)(const struct scmi_handle *, u32, bool);
 };
 
+struct scmi_sensor_info {
+	u32 id;
+	u8 type;
+	char name[SCMI_MAX_STR_SIZE];
+};
+
+/*
+ * Partial list from Distributed Management Task Force (DMTF) specification:
+ * DSP0249 (Platform Level Data Model specification)
+ */
+enum scmi_sensor_class {
+	NONE = 0x0,
+	TEMPERATURE_C = 0x2,
+	VOLTAGE = 0x5,
+	CURRENT = 0x6,
+	POWER = 0x7,
+	ENERGY = 0x8,
+};
+
+/**
+ * struct scmi_sensor_ops - represents the various operations provided
+ *	by SCMI Sensor Protocol
+ *
+ * @count_get: get the count of sensors provided by SCMI
+ * @info_get: get the information of the specified sensor
+ * @configuration_set: control notifications on cross-over events for
+ *	the trip-points
+ * @trip_point_set: selects and configures a trip-point of interest
+ * @reading_get: gets the current value of the sensor
+ */
+struct scmi_sensor_ops {
+	int (*count_get)(const struct scmi_handle *);
+	const struct scmi_sensor_info *(*info_get)(const struct scmi_handle *,
+						   u32);
+	int (*configuration_set)(const struct scmi_handle *, u32);
+	int (*trip_point_set)(const struct scmi_handle *, u32, u8, u64);
+	int (*reading_get)(const struct scmi_handle *, u32, bool, u64 *);
+};
+
 /**
  * struct scmi_handle - Handle returned to ARM SCMI clients for usage.
  *
@@ -144,6 +183,7 @@ struct scmi_power_ops {
  * @power_ops: pointer to set of power protocol operations
  * @perf_ops: pointer to set of performance protocol operations
  * @clk_ops: pointer to set of clock protocol operations
+ * @sensor_ops: pointer to set of sensor protocol operations
  */
 struct scmi_handle {
 	struct device *dev;
@@ -151,6 +191,7 @@ struct scmi_handle {
 	struct scmi_power_ops *power_ops;
 	struct scmi_perf_ops *perf_ops;
 	struct scmi_clk_ops *clk_ops;
+	struct scmi_sensor_ops *sensor_ops;
 };
 
 #if IS_REACHABLE(CONFIG_ARM_SCMI_PROTOCOL)
-- 
2.7.4

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

* [PATCH v3 09/22] firmware: arm_scmi: add initial support for sensor protocol
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

The sensor protocol provides functions to manage platform sensors, and
provides the commands to describe the protocol version and the various
attribute flags. It also provides commands to discover various sensors
implemented and managed by the platform, read any sensor synchronously
or asynchronously as allowed by the platform, program sensor attributes
and/or configurations, if applicable.

This patch adds support for most of the above features.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scmi/Makefile  |   2 +-
 drivers/firmware/arm_scmi/sensors.c | 287 ++++++++++++++++++++++++++++++++++++
 include/linux/scmi_protocol.h       |  41 ++++++
 3 files changed, 329 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/arm_scmi/sensors.c

diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index 52ecc08556a2..f9dee5ad0aa0 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_ARM_SCMI_PROTOCOL)	= arm_scmi.o
-arm_scmi-y = base.o clock.o driver.o perf.o power.o
+arm_scmi-y = base.o clock.o driver.o perf.o power.o sensors.o
diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c
new file mode 100644
index 000000000000..c868ccb7d6a3
--- /dev/null
+++ b/drivers/firmware/arm_scmi/sensors.c
@@ -0,0 +1,287 @@
+/*
+ * System Control and Management Interface (SCMI) Sensor Protocol
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "common.h"
+
+enum scmi_sensor_protocol_cmd {
+	SENSOR_DESCRIPTION_GET = 0x3,
+	SENSOR_CONFIG_SET = 0x4,
+	SENSOR_TRIP_POINT_SET = 0x5,
+	SENSOR_READING_GET = 0x6,
+};
+
+struct scmi_msg_resp_sensor_attributes {
+	__le16 num_sensors;
+	    u8 max_requests;
+	    u8 reserved;
+	__le32 reg_addr_low;
+	__le32 reg_addr_high;
+	__le32 reg_size;
+};
+
+struct scmi_msg_resp_sensor_description {
+	__le16 num_returned;
+	__le16 num_remaining;
+	struct {
+		__le32 id;
+		__le32 attributes_low;
+#define SUPPORTS_ASYNC_READ(x)	((x) & BIT(31))
+#define NUM_TRIP_POINTS(x)	(((x) >> 4) & 0xff)
+		__le32 attributes_high;
+#define SENSOR_TYPE(x)		((x) & 0xff)
+#define SENSOR_SCALE(x)		(((x) >> 11) & 0x3f)
+#define SENSOR_UPDATE_SCALE(x)	(((x) >> 22) & 0x1f)
+#define SENSOR_UPDATE_BASE(x)	(((x) >> 27) & 0x1f)
+		    u8 name[SCMI_MAX_STR_SIZE];
+	} desc[0];
+};
+
+struct scmi_msg_set_sensor_config {
+	__le32 id;
+	__le32 event_control;
+};
+
+struct scmi_msg_set_sensor_trip_point {
+	__le32 id;
+	__le32 event_control;
+#define SENSOR_TP_EVENT_MASK	(0x3)
+#define SENSOR_TP_DISABLED	0x0
+#define SENSOR_TP_POSITIVE	0x1
+#define SENSOR_TP_NEGATIVE	0x2
+#define SENSOR_TP_BOTH		0x3
+#define SENSOR_TP_ID(x)		(((x) & 0xff) << 4)
+	__le32 value_low;
+	__le32 value_high;
+};
+
+struct scmi_msg_sensor_reading_get {
+	__le32 id;
+	__le32 flags;
+#define SENSOR_READ_ASYNC	BIT(0)
+};
+
+struct sensors_info {
+	int num_sensors;
+	int max_requests;
+	u64 reg_addr;
+	u32 reg_size;
+	struct scmi_sensor_info *sensors;
+};
+
+static struct sensors_info sensor_info;
+
+static int scmi_sensor_attributes_get(const struct scmi_handle *handle,
+				      struct sensors_info *sensor_info)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_msg_resp_sensor_attributes *attr;
+
+	ret = scmi_one_xfer_init(handle, PROTOCOL_ATTRIBUTES,
+				 SCMI_PROTOCOL_SENSOR, 0, sizeof(*attr), &t);
+	if (ret)
+		return ret;
+
+	attr = t->rx.buf;
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		sensor_info->num_sensors = le16_to_cpu(attr->num_sensors);
+		sensor_info->max_requests = attr->max_requests;
+		sensor_info->reg_addr = le32_to_cpu(attr->reg_addr_low) |
+				(u64)le32_to_cpu(attr->reg_addr_high) << 32;
+		sensor_info->reg_size = le32_to_cpu(attr->reg_size);
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int scmi_sensor_description_get(const struct scmi_handle *handle)
+{
+	int ret, cnt;
+	u32 desc_index = 0;
+	u16 num_returned, num_remaining;
+	struct scmi_xfer *t;
+	struct scmi_msg_resp_sensor_description *buf;
+
+	ret = scmi_one_xfer_init(handle, SENSOR_DESCRIPTION_GET,
+				 SCMI_PROTOCOL_SENSOR, sizeof(__le32), 0, &t);
+	if (ret)
+		return ret;
+
+	buf = t->rx.buf;
+
+	do {
+		/* Set the number of sensors to be skipped/already read */
+		*(__le32 *)t->tx.buf = cpu_to_le32(desc_index);
+
+		ret = scmi_do_xfer(handle, t);
+		if (ret)
+			break;
+
+		num_returned = le16_to_cpu(buf->num_returned);
+		num_remaining = le16_to_cpu(buf->num_remaining);
+
+		if (desc_index + num_returned > sensor_info.num_sensors) {
+			dev_err(handle->dev, "No. of sensors can't exceed %d",
+				sensor_info.num_sensors);
+			break;
+		}
+
+		for (cnt = 0; cnt < num_returned; cnt++) {
+			u32 attrh;
+			struct scmi_sensor_info *s;
+
+			attrh = le32_to_cpu(buf->desc[cnt].attributes_high);
+			s = &sensor_info.sensors[desc_index + cnt];
+			s->id = le32_to_cpu(buf->desc[cnt].id);
+			s->type = SENSOR_TYPE(attrh);
+			memcpy(s->name, buf->desc[cnt].name, SCMI_MAX_STR_SIZE);
+		}
+
+		desc_index += num_returned;
+		/*
+		 * check for both returned and remaining to avoid infinite
+		 * loop due to buggy firmware
+		 */
+	} while (num_returned && num_remaining);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int
+scmi_sensor_configuration_set(const struct scmi_handle *handle, u32 sensor_id)
+{
+	int ret;
+	u32 evt_cntl = BIT(0);
+	struct scmi_xfer *t;
+	struct scmi_msg_set_sensor_config *cfg;
+
+	ret = scmi_one_xfer_init(handle, SENSOR_CONFIG_SET,
+				 SCMI_PROTOCOL_SENSOR, sizeof(*cfg), 0, &t);
+	if (ret)
+		return ret;
+
+	cfg = t->tx.buf;
+	cfg->id = cpu_to_le32(sensor_id);
+	cfg->event_control = cpu_to_le32(evt_cntl);
+
+	ret = scmi_do_xfer(handle, t);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int scmi_sensor_trip_point_set(const struct scmi_handle *handle,
+				      u32 sensor_id, u8 trip_id, u64 trip_value)
+{
+	int ret;
+	u32 evt_cntl = SENSOR_TP_BOTH;
+	struct scmi_xfer *t;
+	struct scmi_msg_set_sensor_trip_point *trip;
+
+	ret = scmi_one_xfer_init(handle, SENSOR_TRIP_POINT_SET,
+				 SCMI_PROTOCOL_SENSOR, sizeof(*trip), 0, &t);
+	if (ret)
+		return ret;
+
+	trip = t->tx.buf;
+	trip->id = cpu_to_le32(sensor_id);
+	trip->event_control = cpu_to_le32(evt_cntl | SENSOR_TP_ID(trip_id));
+	trip->value_low = cpu_to_le32(trip_value & 0xffffffff);
+	trip->value_high = cpu_to_le32(trip_value >> 32);
+
+	ret = scmi_do_xfer(handle, t);
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static int scmi_sensor_reading_get(const struct scmi_handle *handle,
+				   u32 sensor_id, bool async, u64 *value)
+{
+	int ret;
+	struct scmi_xfer *t;
+	struct scmi_msg_sensor_reading_get *sensor;
+
+	ret = scmi_one_xfer_init(handle, SENSOR_READING_GET,
+				 SCMI_PROTOCOL_SENSOR, sizeof(*sensor),
+				 sizeof(u64), &t);
+	if (ret)
+		return ret;
+
+	sensor = t->tx.buf;
+	sensor->id = cpu_to_le32(sensor_id);
+	sensor->flags = cpu_to_le32(async ? SENSOR_READ_ASYNC : 0);
+
+	ret = scmi_do_xfer(handle, t);
+	if (!ret) {
+		__le32 *pval = t->rx.buf;
+
+		*value = le32_to_cpu(*pval);
+		*value |= (u64)le32_to_cpu(*(pval + 1)) << 32;
+	}
+
+	scmi_one_xfer_put(handle, t);
+	return ret;
+}
+
+static const struct scmi_sensor_info *
+scmi_sensor_info_get(const struct scmi_handle *handle, u32 sensor_id)
+{
+	return sensor_info.sensors + sensor_id;
+}
+
+static int scmi_sensor_count_get(const struct scmi_handle *handle)
+{
+	return sensor_info.num_sensors;
+}
+
+static struct scmi_sensor_ops sensor_ops = {
+	.count_get = scmi_sensor_count_get,
+	.info_get = scmi_sensor_info_get,
+	.configuration_set = scmi_sensor_configuration_set,
+	.trip_point_set = scmi_sensor_trip_point_set,
+	.reading_get = scmi_sensor_reading_get,
+};
+
+int scmi_sensors_protocol_init(struct scmi_handle *handle)
+{
+	u32 version;
+
+	scmi_version_get(handle, SCMI_PROTOCOL_SENSOR, &version);
+
+	dev_dbg(handle->dev, "Sensor Version %d.%d\n",
+		PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
+
+	scmi_sensor_attributes_get(handle, &sensor_info);
+
+	sensor_info.sensors = devm_kcalloc(handle->dev, sensor_info.num_sensors,
+					   sizeof(struct scmi_sensor_info),
+					   GFP_KERNEL);
+	if (!sensor_info.sensors)
+		return -ENOMEM;
+
+	scmi_sensor_description_get(handle);
+
+	handle->sensor_ops = &sensor_ops;
+
+	return 0;
+}
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index e5a80511f88c..5e29394b5cc9 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -136,6 +136,45 @@ struct scmi_power_ops {
 	int (*state_notify_enable)(const struct scmi_handle *, u32, bool);
 };
 
+struct scmi_sensor_info {
+	u32 id;
+	u8 type;
+	char name[SCMI_MAX_STR_SIZE];
+};
+
+/*
+ * Partial list from Distributed Management Task Force (DMTF) specification:
+ * DSP0249 (Platform Level Data Model specification)
+ */
+enum scmi_sensor_class {
+	NONE = 0x0,
+	TEMPERATURE_C = 0x2,
+	VOLTAGE = 0x5,
+	CURRENT = 0x6,
+	POWER = 0x7,
+	ENERGY = 0x8,
+};
+
+/**
+ * struct scmi_sensor_ops - represents the various operations provided
+ *	by SCMI Sensor Protocol
+ *
+ * @count_get: get the count of sensors provided by SCMI
+ * @info_get: get the information of the specified sensor
+ * @configuration_set: control notifications on cross-over events for
+ *	the trip-points
+ * @trip_point_set: selects and configures a trip-point of interest
+ * @reading_get: gets the current value of the sensor
+ */
+struct scmi_sensor_ops {
+	int (*count_get)(const struct scmi_handle *);
+	const struct scmi_sensor_info *(*info_get)(const struct scmi_handle *,
+						   u32);
+	int (*configuration_set)(const struct scmi_handle *, u32);
+	int (*trip_point_set)(const struct scmi_handle *, u32, u8, u64);
+	int (*reading_get)(const struct scmi_handle *, u32, bool, u64 *);
+};
+
 /**
  * struct scmi_handle - Handle returned to ARM SCMI clients for usage.
  *
@@ -144,6 +183,7 @@ struct scmi_power_ops {
  * @power_ops: pointer to set of power protocol operations
  * @perf_ops: pointer to set of performance protocol operations
  * @clk_ops: pointer to set of clock protocol operations
+ * @sensor_ops: pointer to set of sensor protocol operations
  */
 struct scmi_handle {
 	struct device *dev;
@@ -151,6 +191,7 @@ struct scmi_handle {
 	struct scmi_power_ops *power_ops;
 	struct scmi_perf_ops *perf_ops;
 	struct scmi_clk_ops *clk_ops;
+	struct scmi_sensor_ops *sensor_ops;
 };
 
 #if IS_REACHABLE(CONFIG_ARM_SCMI_PROTOCOL)
-- 
2.7.4

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

* [PATCH v3 10/22] firmware: arm_scmi: probe and initialise all the supported protocols
  2017-09-28 13:11 ` Sudeep Holla
@ 2017-09-28 13:11   ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

Now that we have basic support for all the protocols in the
specification, let's probe them individually and initialise them.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scmi/common.h |  5 +++
 drivers/firmware/arm_scmi/driver.c | 82 +++++++++++++++++++++++++++++++++++++-
 2 files changed, 86 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index 0df52905ba48..07acddf5c060 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -119,4 +119,9 @@ int scmi_version_get(const struct scmi_handle *h, u8 protocol, u32 *version);
 void scmi_setup_protocol_implemented(const struct scmi_handle *handle,
 				     u8 *prot_imp);
 
+typedef int (*scmi_prot_init_fn_t)(struct scmi_handle *);
 int scmi_base_protocol_init(struct scmi_handle *h);
+int scmi_perf_protocol_init(struct scmi_handle *h);
+int scmi_sensors_protocol_init(struct scmi_handle *h);
+int scmi_power_protocol_init(struct scmi_handle *h);
+int scmi_clock_protocol_init(struct scmi_handle *h);
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 5df76512a291..a1abcf2049ca 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -154,6 +154,12 @@ struct scmi_shared_mem {
 	u8 msg_payload[0];
 };
 
+struct scmi_protocol_match {
+	u8 protocol_id;
+	scmi_prot_init_fn_t fn;
+	char name[32];
+};
+
 static int scmi_linux_errmap[] = {
 	/* better than switch case as long as return value is continuous */
 	0,			/* SCMI_SUCCESS */
@@ -686,6 +692,39 @@ static int scmi_xfer_info_init(struct scmi_info *sinfo)
 	return 0;
 }
 
+static const struct scmi_protocol_match scmi_protocols[] = {
+	{
+		.protocol_id = SCMI_PROTOCOL_PERF,
+		.fn = scmi_perf_protocol_init,
+		.name = "scmi-cpufreq",
+	}, {
+		.protocol_id = SCMI_PROTOCOL_CLOCK,
+		.fn = scmi_clock_protocol_init,
+		.name = "scmi-clocks",
+	}, {
+		.protocol_id = SCMI_PROTOCOL_POWER,
+		.fn = scmi_power_protocol_init,
+		.name = "scmi-power-domain",
+	}, {
+		.protocol_id = SCMI_PROTOCOL_SENSOR,
+		.fn = scmi_sensors_protocol_init,
+		.name = "scmi-hwmon",
+	},
+	{}
+};
+
+static const struct scmi_protocol_match *scmi_protocol_match_get(u8 protocol_id)
+{
+	int i;
+	const struct scmi_protocol_match *loop = scmi_protocols;
+
+	for (i = 0; i < ARRAY_SIZE(scmi_protocols); i++, loop++)
+		if (loop->protocol_id == protocol_id)
+			return loop;
+
+	return NULL;
+}
+
 static int scmi_mailbox_check(struct device_node *np)
 {
 	struct of_phandle_args arg;
@@ -767,6 +806,27 @@ static inline int scmi_mbox_chan_setup(struct scmi_info *info)
 	return 0;
 }
 
+static inline void
+scmi_create_protocol_device(struct device_node *np, struct scmi_info *info,
+			    const struct scmi_protocol_match *match)
+{
+	int init_ret;
+	struct platform_device *cdev;
+
+	cdev = of_platform_device_create(np, match->name, info->dev);
+	if (!cdev) {
+		dev_err(info->dev, "failed to create %s device\n", match->name);
+		return;
+	}
+
+	init_ret = match->fn(&info->handle);
+	if (init_ret) {
+		dev_err(info->dev, "SCMI protocol %d init error %d\n",
+			match->protocol_id, init_ret);
+		of_platform_device_destroy(&cdev->dev, NULL);
+	}
+}
+
 static int scmi_probe(struct platform_device *pdev)
 {
 	int ret;
@@ -774,7 +834,7 @@ static int scmi_probe(struct platform_device *pdev)
 	const struct scmi_desc *desc;
 	struct scmi_info *info;
 	struct device *dev = &pdev->dev;
-	struct device_node *np = dev->of_node;
+	struct device_node *child, *np = dev->of_node;
 
 	/* Only mailbox method supported, check for the presence of one */
 	if (scmi_mailbox_check(np)) {
@@ -813,6 +873,26 @@ static int scmi_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	for_each_available_child_of_node(np, child) {
+		u32 prot_id;
+		const struct scmi_protocol_match *match;
+
+		if (of_property_read_u32(child, "reg", &prot_id))
+			continue;
+
+		prot_id &= MSG_PROTOCOL_ID_MASK;
+
+		if (!scmi_is_protocol_implemented(handle, prot_id)) {
+			dev_err(dev, "SCMI protocol %d not implemented\n",
+				prot_id);
+			continue;
+		}
+
+		match = scmi_protocol_match_get(prot_id);
+		if (match)
+			scmi_create_protocol_device(child, info, match);
+	}
+
 	mutex_lock(&scmi_list_mutex);
 	list_add_tail(&info->node, &scmi_list);
 	mutex_unlock(&scmi_list_mutex);
-- 
2.7.4

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

* [PATCH v3 10/22] firmware: arm_scmi: probe and initialise all the supported protocols
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

Now that we have basic support for all the protocols in the
specification, let's probe them individually and initialise them.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scmi/common.h |  5 +++
 drivers/firmware/arm_scmi/driver.c | 82 +++++++++++++++++++++++++++++++++++++-
 2 files changed, 86 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index 0df52905ba48..07acddf5c060 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -119,4 +119,9 @@ int scmi_version_get(const struct scmi_handle *h, u8 protocol, u32 *version);
 void scmi_setup_protocol_implemented(const struct scmi_handle *handle,
 				     u8 *prot_imp);
 
+typedef int (*scmi_prot_init_fn_t)(struct scmi_handle *);
 int scmi_base_protocol_init(struct scmi_handle *h);
+int scmi_perf_protocol_init(struct scmi_handle *h);
+int scmi_sensors_protocol_init(struct scmi_handle *h);
+int scmi_power_protocol_init(struct scmi_handle *h);
+int scmi_clock_protocol_init(struct scmi_handle *h);
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 5df76512a291..a1abcf2049ca 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -154,6 +154,12 @@ struct scmi_shared_mem {
 	u8 msg_payload[0];
 };
 
+struct scmi_protocol_match {
+	u8 protocol_id;
+	scmi_prot_init_fn_t fn;
+	char name[32];
+};
+
 static int scmi_linux_errmap[] = {
 	/* better than switch case as long as return value is continuous */
 	0,			/* SCMI_SUCCESS */
@@ -686,6 +692,39 @@ static int scmi_xfer_info_init(struct scmi_info *sinfo)
 	return 0;
 }
 
+static const struct scmi_protocol_match scmi_protocols[] = {
+	{
+		.protocol_id = SCMI_PROTOCOL_PERF,
+		.fn = scmi_perf_protocol_init,
+		.name = "scmi-cpufreq",
+	}, {
+		.protocol_id = SCMI_PROTOCOL_CLOCK,
+		.fn = scmi_clock_protocol_init,
+		.name = "scmi-clocks",
+	}, {
+		.protocol_id = SCMI_PROTOCOL_POWER,
+		.fn = scmi_power_protocol_init,
+		.name = "scmi-power-domain",
+	}, {
+		.protocol_id = SCMI_PROTOCOL_SENSOR,
+		.fn = scmi_sensors_protocol_init,
+		.name = "scmi-hwmon",
+	},
+	{}
+};
+
+static const struct scmi_protocol_match *scmi_protocol_match_get(u8 protocol_id)
+{
+	int i;
+	const struct scmi_protocol_match *loop = scmi_protocols;
+
+	for (i = 0; i < ARRAY_SIZE(scmi_protocols); i++, loop++)
+		if (loop->protocol_id == protocol_id)
+			return loop;
+
+	return NULL;
+}
+
 static int scmi_mailbox_check(struct device_node *np)
 {
 	struct of_phandle_args arg;
@@ -767,6 +806,27 @@ static inline int scmi_mbox_chan_setup(struct scmi_info *info)
 	return 0;
 }
 
+static inline void
+scmi_create_protocol_device(struct device_node *np, struct scmi_info *info,
+			    const struct scmi_protocol_match *match)
+{
+	int init_ret;
+	struct platform_device *cdev;
+
+	cdev = of_platform_device_create(np, match->name, info->dev);
+	if (!cdev) {
+		dev_err(info->dev, "failed to create %s device\n", match->name);
+		return;
+	}
+
+	init_ret = match->fn(&info->handle);
+	if (init_ret) {
+		dev_err(info->dev, "SCMI protocol %d init error %d\n",
+			match->protocol_id, init_ret);
+		of_platform_device_destroy(&cdev->dev, NULL);
+	}
+}
+
 static int scmi_probe(struct platform_device *pdev)
 {
 	int ret;
@@ -774,7 +834,7 @@ static int scmi_probe(struct platform_device *pdev)
 	const struct scmi_desc *desc;
 	struct scmi_info *info;
 	struct device *dev = &pdev->dev;
-	struct device_node *np = dev->of_node;
+	struct device_node *child, *np = dev->of_node;
 
 	/* Only mailbox method supported, check for the presence of one */
 	if (scmi_mailbox_check(np)) {
@@ -813,6 +873,26 @@ static int scmi_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	for_each_available_child_of_node(np, child) {
+		u32 prot_id;
+		const struct scmi_protocol_match *match;
+
+		if (of_property_read_u32(child, "reg", &prot_id))
+			continue;
+
+		prot_id &= MSG_PROTOCOL_ID_MASK;
+
+		if (!scmi_is_protocol_implemented(handle, prot_id)) {
+			dev_err(dev, "SCMI protocol %d not implemented\n",
+				prot_id);
+			continue;
+		}
+
+		match = scmi_protocol_match_get(prot_id);
+		if (match)
+			scmi_create_protocol_device(child, info, match);
+	}
+
 	mutex_lock(&scmi_list_mutex);
 	list_add_tail(&info->node, &scmi_list);
 	mutex_unlock(&scmi_list_mutex);
-- 
2.7.4

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

* [PATCH v3 11/22] firmware: arm_scmi: add support for polling based SCMI transfers
  2017-09-28 13:11 ` Sudeep Holla
@ 2017-09-28 13:11   ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

It would be useful to have options to perform some SCMI transfers
atomically by polling for the completion flag instead of interrupt
driven. The SCMI specification has option to disable the interrupt and
poll for the completion flag in the shared memory.

This patch adds support for polling based SCMI transfers using that
option. This might be used for uninterrupted/atomic DVFS operations
from the scheduler context.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scmi/driver.c | 41 ++++++++++++++++++++++++++++++--------
 1 file changed, 33 insertions(+), 8 deletions(-)

diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index a1abcf2049ca..e1abedf15cb0 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -26,6 +26,7 @@
  */
 
 #include <linux/bitmap.h>
+#include <linux/delay.h>
 #include <linux/export.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
@@ -369,6 +370,20 @@ void scmi_one_xfer_put(const struct scmi_handle *handle, struct scmi_xfer *xfer)
 	up(&minfo->sem_xfer_count);
 }
 
+static bool
+scmi_xfer_poll_done(const struct scmi_info *info, struct scmi_xfer *xfer)
+{
+	struct scmi_shared_mem *mem = info->tx_payload;
+	u16 xfer_id = MSG_XTRACT_TOKEN(le32_to_cpu(mem->msg_header));
+
+	if (xfer->hdr.seq != xfer_id)
+		return false;
+
+	return le32_to_cpu(mem->channel_status) &
+		(SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR |
+		SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE);
+}
+
 /**
  * scmi_do_xfer() - Do one transfer
  *
@@ -395,14 +410,24 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
 	/* mbox_send_message returns non-negative value on success, so reset */
 	ret = 0;
 
-	/* And we wait for the response. */
-	timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms);
-	if (!wait_for_completion_timeout(&xfer->done, timeout)) {
-		dev_err(dev, "mbox timed out in resp(caller: %pF)\n",
-			(void *)_RET_IP_);
-		ret = -ETIMEDOUT;
-	} else if (xfer->hdr.status) {
-		ret = scmi_to_linux_errno(xfer->hdr.status);
+	if (xfer->hdr.poll_completion) {
+		timeout = info->desc->max_rx_timeout_ms * 100;
+		while (!scmi_xfer_poll_done(info, xfer) && timeout--)
+			udelay(10);
+		if (timeout)
+			scmi_fetch_response(xfer, info->tx_payload);
+		else
+			ret = -ETIMEDOUT;
+	} else {
+		/* And we wait for the response. */
+		timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms);
+		if (!wait_for_completion_timeout(&xfer->done, timeout)) {
+			dev_err(dev, "mbox timed out in resp(caller: %pF)\n",
+				(void *)_RET_IP_);
+			ret = -ETIMEDOUT;
+		} else if (xfer->hdr.status) {
+			ret = scmi_to_linux_errno(xfer->hdr.status);
+		}
 	}
 	/*
 	 * NOTE: we might prefer not to need the mailbox ticker to manage the
-- 
2.7.4

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

* [PATCH v3 11/22] firmware: arm_scmi: add support for polling based SCMI transfers
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

It would be useful to have options to perform some SCMI transfers
atomically by polling for the completion flag instead of interrupt
driven. The SCMI specification has option to disable the interrupt and
poll for the completion flag in the shared memory.

This patch adds support for polling based SCMI transfers using that
option. This might be used for uninterrupted/atomic DVFS operations
from the scheduler context.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scmi/driver.c | 41 ++++++++++++++++++++++++++++++--------
 1 file changed, 33 insertions(+), 8 deletions(-)

diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index a1abcf2049ca..e1abedf15cb0 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -26,6 +26,7 @@
  */
 
 #include <linux/bitmap.h>
+#include <linux/delay.h>
 #include <linux/export.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
@@ -369,6 +370,20 @@ void scmi_one_xfer_put(const struct scmi_handle *handle, struct scmi_xfer *xfer)
 	up(&minfo->sem_xfer_count);
 }
 
+static bool
+scmi_xfer_poll_done(const struct scmi_info *info, struct scmi_xfer *xfer)
+{
+	struct scmi_shared_mem *mem = info->tx_payload;
+	u16 xfer_id = MSG_XTRACT_TOKEN(le32_to_cpu(mem->msg_header));
+
+	if (xfer->hdr.seq != xfer_id)
+		return false;
+
+	return le32_to_cpu(mem->channel_status) &
+		(SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR |
+		SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE);
+}
+
 /**
  * scmi_do_xfer() - Do one transfer
  *
@@ -395,14 +410,24 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
 	/* mbox_send_message returns non-negative value on success, so reset */
 	ret = 0;
 
-	/* And we wait for the response. */
-	timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms);
-	if (!wait_for_completion_timeout(&xfer->done, timeout)) {
-		dev_err(dev, "mbox timed out in resp(caller: %pF)\n",
-			(void *)_RET_IP_);
-		ret = -ETIMEDOUT;
-	} else if (xfer->hdr.status) {
-		ret = scmi_to_linux_errno(xfer->hdr.status);
+	if (xfer->hdr.poll_completion) {
+		timeout = info->desc->max_rx_timeout_ms * 100;
+		while (!scmi_xfer_poll_done(info, xfer) && timeout--)
+			udelay(10);
+		if (timeout)
+			scmi_fetch_response(xfer, info->tx_payload);
+		else
+			ret = -ETIMEDOUT;
+	} else {
+		/* And we wait for the response. */
+		timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms);
+		if (!wait_for_completion_timeout(&xfer->done, timeout)) {
+			dev_err(dev, "mbox timed out in resp(caller: %pF)\n",
+				(void *)_RET_IP_);
+			ret = -ETIMEDOUT;
+		} else if (xfer->hdr.status) {
+			ret = scmi_to_linux_errno(xfer->hdr.status);
+		}
 	}
 	/*
 	 * NOTE: we might prefer not to need the mailbox ticker to manage the
-- 
2.7.4

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

* [PATCH v3 12/22] firmware: arm_scmi: add option for polling based performance domain operations
  2017-09-28 13:11 ` Sudeep Holla
@ 2017-09-28 13:11   ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

In order to implement fast CPU DVFS switching, we need to perform all
DVFS operations atomically. Since SCMI transfer already provide option
to choose between pooling vs interrupt driven(default), we can opt for
polling based transfers for set,get performance domain operations.

This patch adds option to choose between polling vs interrupt driven
SCMI transfers for set,get performance level operations.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scmi/perf.c | 19 +++++++++++--------
 include/linux/scmi_protocol.h    |  8 ++++----
 2 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c
index 13d84d829201..334e8ec321ed 100644
--- a/drivers/firmware/arm_scmi/perf.c
+++ b/drivers/firmware/arm_scmi/perf.c
@@ -305,8 +305,8 @@ static int scmi_perf_limits_get(const struct scmi_handle *handle, u32 domain,
 	return ret;
 }
 
-static int
-scmi_perf_level_set(const struct scmi_handle *handle, u32 domain, u32 level)
+static int scmi_perf_level_set(const struct scmi_handle *handle, u32 domain,
+			       u32 level, bool poll)
 {
 	int ret;
 	struct scmi_xfer *t;
@@ -317,6 +317,7 @@ scmi_perf_level_set(const struct scmi_handle *handle, u32 domain, u32 level)
 	if (ret)
 		return ret;
 
+	t->hdr.poll_completion = poll;
 	lvl = t->tx.buf;
 	lvl->domain = cpu_to_le32(domain);
 	lvl->level = cpu_to_le32(level);
@@ -327,8 +328,8 @@ scmi_perf_level_set(const struct scmi_handle *handle, u32 domain, u32 level)
 	return ret;
 }
 
-static int
-scmi_perf_level_get(const struct scmi_handle *handle, u32 domain, u32 *level)
+static int scmi_perf_level_get(const struct scmi_handle *handle, u32 domain,
+			       u32 *level, bool poll)
 {
 	int ret;
 	struct scmi_xfer *t;
@@ -338,6 +339,7 @@ scmi_perf_level_get(const struct scmi_handle *handle, u32 domain, u32 *level)
 	if (ret)
 		return ret;
 
+	t->hdr.poll_completion = poll;
 	*(__le32 *)t->tx.buf = cpu_to_le32(domain);
 
 	ret = scmi_do_xfer(handle, t);
@@ -445,21 +447,22 @@ static int scmi_dvfs_get_transition_latency(struct device *dev)
 }
 
 static int scmi_dvfs_freq_set(const struct scmi_handle *handle, u32 domain,
-			      unsigned long freq)
+			      unsigned long freq, bool poll)
 {
 	struct perf_dom_info *dom = perf_info.dom_info + domain;
 
-	return scmi_perf_level_set(handle, domain, freq / dom->mult_factor);
+	return scmi_perf_level_set(handle, domain, freq / dom->mult_factor,
+				   poll);
 }
 
 static int scmi_dvfs_freq_get(const struct scmi_handle *handle, u32 domain,
-			      unsigned long *freq)
+			      unsigned long *freq, bool poll)
 {
 	int ret;
 	u32 level;
 	struct perf_dom_info *dom = perf_info.dom_info + domain;
 
-	ret = scmi_perf_level_get(handle, domain, &level);
+	ret = scmi_perf_level_get(handle, domain, &level, poll);
 	if (!ret)
 		*freq = level * dom->mult_factor;
 
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 5e29394b5cc9..ac1a4a096314 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -99,15 +99,15 @@ struct scmi_clk_ops {
 struct scmi_perf_ops {
 	int (*limits_set)(const struct scmi_handle *, u32, u32, u32);
 	int (*limits_get)(const struct scmi_handle *, u32, u32 *, u32 *);
-	int (*level_set)(const struct scmi_handle *, u32, u32);
-	int (*level_get)(const struct scmi_handle *, u32, u32 *);
+	int (*level_set)(const struct scmi_handle *, u32, u32, bool);
+	int (*level_get)(const struct scmi_handle *, u32, u32 *, bool);
 	int (*limits_notify_enable)(const struct scmi_handle *, u32, bool);
 	int (*level_notify_enable)(const struct scmi_handle *, u32, bool);
 	int (*device_domain_id)(struct device *);
 	int (*get_transition_latency)(struct device *);
 	int (*add_opps_to_device)(struct device *);
-	int (*freq_set)(const struct scmi_handle *, u32, unsigned long);
-	int (*freq_get)(const struct scmi_handle *, u32, unsigned long *);
+	int (*freq_set)(const struct scmi_handle *, u32, unsigned long, bool);
+	int (*freq_get)(const struct scmi_handle *, u32, unsigned long *, bool);
 };
 
 /**
-- 
2.7.4

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

* [PATCH v3 12/22] firmware: arm_scmi: add option for polling based performance domain operations
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

In order to implement fast CPU DVFS switching, we need to perform all
DVFS operations atomically. Since SCMI transfer already provide option
to choose between pooling vs interrupt driven(default), we can opt for
polling based transfers for set,get performance domain operations.

This patch adds option to choose between polling vs interrupt driven
SCMI transfers for set,get performance level operations.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scmi/perf.c | 19 +++++++++++--------
 include/linux/scmi_protocol.h    |  8 ++++----
 2 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c
index 13d84d829201..334e8ec321ed 100644
--- a/drivers/firmware/arm_scmi/perf.c
+++ b/drivers/firmware/arm_scmi/perf.c
@@ -305,8 +305,8 @@ static int scmi_perf_limits_get(const struct scmi_handle *handle, u32 domain,
 	return ret;
 }
 
-static int
-scmi_perf_level_set(const struct scmi_handle *handle, u32 domain, u32 level)
+static int scmi_perf_level_set(const struct scmi_handle *handle, u32 domain,
+			       u32 level, bool poll)
 {
 	int ret;
 	struct scmi_xfer *t;
@@ -317,6 +317,7 @@ scmi_perf_level_set(const struct scmi_handle *handle, u32 domain, u32 level)
 	if (ret)
 		return ret;
 
+	t->hdr.poll_completion = poll;
 	lvl = t->tx.buf;
 	lvl->domain = cpu_to_le32(domain);
 	lvl->level = cpu_to_le32(level);
@@ -327,8 +328,8 @@ scmi_perf_level_set(const struct scmi_handle *handle, u32 domain, u32 level)
 	return ret;
 }
 
-static int
-scmi_perf_level_get(const struct scmi_handle *handle, u32 domain, u32 *level)
+static int scmi_perf_level_get(const struct scmi_handle *handle, u32 domain,
+			       u32 *level, bool poll)
 {
 	int ret;
 	struct scmi_xfer *t;
@@ -338,6 +339,7 @@ scmi_perf_level_get(const struct scmi_handle *handle, u32 domain, u32 *level)
 	if (ret)
 		return ret;
 
+	t->hdr.poll_completion = poll;
 	*(__le32 *)t->tx.buf = cpu_to_le32(domain);
 
 	ret = scmi_do_xfer(handle, t);
@@ -445,21 +447,22 @@ static int scmi_dvfs_get_transition_latency(struct device *dev)
 }
 
 static int scmi_dvfs_freq_set(const struct scmi_handle *handle, u32 domain,
-			      unsigned long freq)
+			      unsigned long freq, bool poll)
 {
 	struct perf_dom_info *dom = perf_info.dom_info + domain;
 
-	return scmi_perf_level_set(handle, domain, freq / dom->mult_factor);
+	return scmi_perf_level_set(handle, domain, freq / dom->mult_factor,
+				   poll);
 }
 
 static int scmi_dvfs_freq_get(const struct scmi_handle *handle, u32 domain,
-			      unsigned long *freq)
+			      unsigned long *freq, bool poll)
 {
 	int ret;
 	u32 level;
 	struct perf_dom_info *dom = perf_info.dom_info + domain;
 
-	ret = scmi_perf_level_get(handle, domain, &level);
+	ret = scmi_perf_level_get(handle, domain, &level, poll);
 	if (!ret)
 		*freq = level * dom->mult_factor;
 
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 5e29394b5cc9..ac1a4a096314 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -99,15 +99,15 @@ struct scmi_clk_ops {
 struct scmi_perf_ops {
 	int (*limits_set)(const struct scmi_handle *, u32, u32, u32);
 	int (*limits_get)(const struct scmi_handle *, u32, u32 *, u32 *);
-	int (*level_set)(const struct scmi_handle *, u32, u32);
-	int (*level_get)(const struct scmi_handle *, u32, u32 *);
+	int (*level_set)(const struct scmi_handle *, u32, u32, bool);
+	int (*level_get)(const struct scmi_handle *, u32, u32 *, bool);
 	int (*limits_notify_enable)(const struct scmi_handle *, u32, bool);
 	int (*level_notify_enable)(const struct scmi_handle *, u32, bool);
 	int (*device_domain_id)(struct device *);
 	int (*get_transition_latency)(struct device *);
 	int (*add_opps_to_device)(struct device *);
-	int (*freq_set)(const struct scmi_handle *, u32, unsigned long);
-	int (*freq_get)(const struct scmi_handle *, u32, unsigned long *);
+	int (*freq_set)(const struct scmi_handle *, u32, unsigned long, bool);
+	int (*freq_get)(const struct scmi_handle *, u32, unsigned long *, bool);
 };
 
 /**
-- 
2.7.4

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

* [PATCH v3 13/22] firmware: arm_scmi: refactor in preparation to support per-protocol channels
  2017-09-28 13:11 ` Sudeep Holla
@ 2017-09-28 13:11   ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

In order to support per-protocol channels if available, we need to
factor out all the mailbox channel information(Tx/Rx payload and
channel handle) out of the main SCMI instance information structure.

This patch refactors the existing channel information into a separate
chan_info structure.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scmi/driver.c | 84 ++++++++++++++++++++++++--------------
 1 file changed, 54 insertions(+), 30 deletions(-)

diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index e1abedf15cb0..93b3bd8d437f 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -104,6 +104,22 @@ struct scmi_desc {
 };
 
 /**
+ * struct scmi_chan_info - Structure representing a SCMI channel informfation
+ *
+ * @cl: Mailbox Client
+ * @chan: Transmit/Receive mailbox channel
+ * @payload: Transmit/Receive mailbox channel payload area
+ * @dev: Reference to device in the SCMI hierarchy corresponding to this
+ *	 channel
+ */
+struct scmi_chan_info {
+	struct mbox_client cl;
+	struct mbox_chan *chan;
+	void __iomem *payload;
+	struct device *dev;
+};
+
+/**
  * struct scmi_info - Structure representing a  SCMI instance
  *
  * @dev: Device pointer
@@ -111,10 +127,8 @@ struct scmi_desc {
  * @handle: Instance of SCMI handle to send to clients
  * @version: SCMI revision information containing protocol version,
  *	implementation version and (sub-)vendor identification.
- * @cl: Mailbox Client
- * @tx_chan: Transmit mailbox channel
- * @tx_payload: Transmit mailbox channel payload area
  * @minfo: Message info
+ * @tx_cinfo: Reference to SCMI channel information
  * @protocols_imp: list of protocols implemented, currently maximum of
  *	MAX_PROTOCOLS_IMP elements allocated by the base protocol
  * @node: list head
@@ -125,16 +139,14 @@ struct scmi_info {
 	const struct scmi_desc *desc;
 	struct scmi_revision_info version;
 	struct scmi_handle handle;
-	struct mbox_client cl;
-	struct mbox_chan *tx_chan;
-	void __iomem *tx_payload;
 	struct scmi_xfers_info minfo;
+	struct scmi_chan_info *tx_cinfo;
 	u8 *protocols_imp;
 	struct list_head node;
 	int users;
 };
 
-#define client_to_scmi_info(c)	container_of(c, struct scmi_info, cl)
+#define client_to_scmi_chan_info(c) container_of(c, struct scmi_chan_info, cl)
 #define handle_to_scmi_info(h)	container_of(h, struct scmi_info, handle)
 
 /*
@@ -224,10 +236,11 @@ static void scmi_rx_callback(struct mbox_client *cl, void *m)
 {
 	u16 xfer_id;
 	struct scmi_xfer *xfer;
-	struct scmi_info *info = client_to_scmi_info(cl);
+	struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
+	struct device *dev = cinfo->dev;
+	struct scmi_info *info = dev_get_drvdata(dev);
 	struct scmi_xfers_info *minfo = &info->minfo;
-	struct device *dev = info->dev;
-	struct scmi_shared_mem *mem = info->tx_payload;
+	struct scmi_shared_mem *mem = cinfo->payload;
 
 	xfer_id = MSG_XTRACT_TOKEN(le32_to_cpu(mem->msg_header));
 
@@ -278,8 +291,8 @@ static inline u32 pack_scmi_header(struct scmi_msg_hdr *hdr)
 static void scmi_tx_prepare(struct mbox_client *cl, void *m)
 {
 	struct scmi_xfer *t = m;
-	struct scmi_info *info = client_to_scmi_info(cl);
-	struct scmi_shared_mem *mem = info->tx_payload;
+	struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
+	struct scmi_shared_mem *mem = cinfo->payload;
 
 	mem->channel_status = 0x0; /* Mark channel busy + clear error */
 	mem->flags = t->hdr.poll_completion ? 0 :
@@ -371,9 +384,9 @@ void scmi_one_xfer_put(const struct scmi_handle *handle, struct scmi_xfer *xfer)
 }
 
 static bool
-scmi_xfer_poll_done(const struct scmi_info *info, struct scmi_xfer *xfer)
+scmi_xfer_poll_done(const struct scmi_chan_info *cinfo, struct scmi_xfer *xfer)
 {
-	struct scmi_shared_mem *mem = info->tx_payload;
+	struct scmi_shared_mem *mem = cinfo->payload;
 	u16 xfer_id = MSG_XTRACT_TOKEN(le32_to_cpu(mem->msg_header));
 
 	if (xfer->hdr.seq != xfer_id)
@@ -400,8 +413,9 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
 	int timeout;
 	struct scmi_info *info = handle_to_scmi_info(handle);
 	struct device *dev = info->dev;
+	struct scmi_chan_info *cinfo = info->tx_cinfo;
 
-	ret = mbox_send_message(info->tx_chan, xfer);
+	ret = mbox_send_message(cinfo->chan, xfer);
 	if (ret < 0) {
 		dev_dbg(dev, "mbox send fail %d\n", ret);
 		return ret;
@@ -412,10 +426,10 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
 
 	if (xfer->hdr.poll_completion) {
 		timeout = info->desc->max_rx_timeout_ms * 100;
-		while (!scmi_xfer_poll_done(info, xfer) && timeout--)
+		while (!scmi_xfer_poll_done(cinfo, xfer) && timeout--)
 			udelay(10);
 		if (timeout)
-			scmi_fetch_response(xfer, info->tx_payload);
+			scmi_fetch_response(xfer, cinfo->payload);
 		else
 			ret = -ETIMEDOUT;
 	} else {
@@ -435,7 +449,7 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
 	 * Unfortunately, we have to kick the mailbox framework after we have
 	 * received our message.
 	 */
-	mbox_client_txdone(info->tx_chan, ret);
+	mbox_client_txdone(cinfo->chan, ret);
 
 	return ret;
 }
@@ -757,11 +771,11 @@ static int scmi_mailbox_check(struct device_node *np)
 	return of_parse_phandle_with_args(np, "mboxes", "#mbox-cells", 0, &arg);
 }
 
-static int scmi_mbox_free_channel(struct scmi_info *info)
+static int scmi_mbox_free_channel(struct scmi_chan_info *cinfo)
 {
-	if (!IS_ERR_OR_NULL(info->tx_chan)) {
-		mbox_free_channel(info->tx_chan);
-		info->tx_chan = NULL;
+	if (!IS_ERR_OR_NULL(cinfo->chan)) {
+		mbox_free_channel(cinfo->chan);
+		cinfo->chan = NULL;
 	}
 
 	return 0;
@@ -783,7 +797,7 @@ static int scmi_remove(struct platform_device *pdev)
 
 	if (!ret)
 		/* Safe to free channels since no more users */
-		return scmi_mbox_free_channel(info);
+		return scmi_mbox_free_channel(info->tx_cinfo);
 
 	return ret;
 }
@@ -795,9 +809,17 @@ static inline int scmi_mbox_chan_setup(struct scmi_info *info)
 	resource_size_t size;
 	struct device *dev = info->dev;
 	struct device_node *shmem, *np = dev->of_node;
+	struct scmi_chan_info *cinfo;
 	struct mbox_client *cl;
 
-	cl = &info->cl;
+	cinfo = devm_kzalloc(info->dev, sizeof(*cinfo), GFP_KERNEL);
+	if (!cinfo)
+		return -ENOMEM;
+
+	info->tx_cinfo = cinfo;
+	cinfo->dev = dev;
+
+	cl = &cinfo->cl;
 	cl->dev = dev;
 	cl->rx_callback = scmi_rx_callback;
 	cl->tx_prepare = scmi_tx_prepare;
@@ -813,16 +835,16 @@ static inline int scmi_mbox_chan_setup(struct scmi_info *info)
 	}
 
 	size = resource_size(&res);
-	info->tx_payload = devm_ioremap(dev, res.start, size);
-	if (!info->tx_payload) {
+	cinfo->payload = devm_ioremap(info->dev, res.start, size);
+	if (!cinfo->payload) {
 		dev_err(dev, "failed to ioremap SCMI Tx payload\n");
 		return -EADDRNOTAVAIL;
 	}
 
 	/* Transmit channel is first entry i.e. index 0 */
-	info->tx_chan = mbox_request_channel(cl, 0);
-	if (IS_ERR(info->tx_chan)) {
-		ret = PTR_ERR(info->tx_chan);
+	cinfo->chan = mbox_request_channel(cl, 0);
+	if (IS_ERR(cinfo->chan)) {
+		ret = PTR_ERR(cinfo->chan);
 		if (ret != -EPROBE_DEFER)
 			dev_err(dev, "failed to request SCMI Tx mailbox\n");
 		return ret;
@@ -844,6 +866,8 @@ scmi_create_protocol_device(struct device_node *np, struct scmi_info *info,
 		return;
 	}
 
+	platform_set_drvdata(cdev, info);
+
 	init_ret = match->fn(&info->handle);
 	if (init_ret) {
 		dev_err(info->dev, "SCMI protocol %d init error %d\n",
@@ -894,7 +918,7 @@ static int scmi_probe(struct platform_device *pdev)
 	ret = scmi_base_protocol_init(handle);
 	if (ret) {
 		dev_err(dev, "unable to communicate with SCMI(%d)\n", ret);
-		scmi_mbox_free_channel(info);
+		scmi_mbox_free_channel(info->tx_cinfo);
 		return ret;
 	}
 
-- 
2.7.4

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

* [PATCH v3 13/22] firmware: arm_scmi: refactor in preparation to support per-protocol channels
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

In order to support per-protocol channels if available, we need to
factor out all the mailbox channel information(Tx/Rx payload and
channel handle) out of the main SCMI instance information structure.

This patch refactors the existing channel information into a separate
chan_info structure.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scmi/driver.c | 84 ++++++++++++++++++++++++--------------
 1 file changed, 54 insertions(+), 30 deletions(-)

diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index e1abedf15cb0..93b3bd8d437f 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -104,6 +104,22 @@ struct scmi_desc {
 };
 
 /**
+ * struct scmi_chan_info - Structure representing a SCMI channel informfation
+ *
+ * @cl: Mailbox Client
+ * @chan: Transmit/Receive mailbox channel
+ * @payload: Transmit/Receive mailbox channel payload area
+ * @dev: Reference to device in the SCMI hierarchy corresponding to this
+ *	 channel
+ */
+struct scmi_chan_info {
+	struct mbox_client cl;
+	struct mbox_chan *chan;
+	void __iomem *payload;
+	struct device *dev;
+};
+
+/**
  * struct scmi_info - Structure representing a  SCMI instance
  *
  * @dev: Device pointer
@@ -111,10 +127,8 @@ struct scmi_desc {
  * @handle: Instance of SCMI handle to send to clients
  * @version: SCMI revision information containing protocol version,
  *	implementation version and (sub-)vendor identification.
- * @cl: Mailbox Client
- * @tx_chan: Transmit mailbox channel
- * @tx_payload: Transmit mailbox channel payload area
  * @minfo: Message info
+ * @tx_cinfo: Reference to SCMI channel information
  * @protocols_imp: list of protocols implemented, currently maximum of
  *	MAX_PROTOCOLS_IMP elements allocated by the base protocol
  * @node: list head
@@ -125,16 +139,14 @@ struct scmi_info {
 	const struct scmi_desc *desc;
 	struct scmi_revision_info version;
 	struct scmi_handle handle;
-	struct mbox_client cl;
-	struct mbox_chan *tx_chan;
-	void __iomem *tx_payload;
 	struct scmi_xfers_info minfo;
+	struct scmi_chan_info *tx_cinfo;
 	u8 *protocols_imp;
 	struct list_head node;
 	int users;
 };
 
-#define client_to_scmi_info(c)	container_of(c, struct scmi_info, cl)
+#define client_to_scmi_chan_info(c) container_of(c, struct scmi_chan_info, cl)
 #define handle_to_scmi_info(h)	container_of(h, struct scmi_info, handle)
 
 /*
@@ -224,10 +236,11 @@ static void scmi_rx_callback(struct mbox_client *cl, void *m)
 {
 	u16 xfer_id;
 	struct scmi_xfer *xfer;
-	struct scmi_info *info = client_to_scmi_info(cl);
+	struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
+	struct device *dev = cinfo->dev;
+	struct scmi_info *info = dev_get_drvdata(dev);
 	struct scmi_xfers_info *minfo = &info->minfo;
-	struct device *dev = info->dev;
-	struct scmi_shared_mem *mem = info->tx_payload;
+	struct scmi_shared_mem *mem = cinfo->payload;
 
 	xfer_id = MSG_XTRACT_TOKEN(le32_to_cpu(mem->msg_header));
 
@@ -278,8 +291,8 @@ static inline u32 pack_scmi_header(struct scmi_msg_hdr *hdr)
 static void scmi_tx_prepare(struct mbox_client *cl, void *m)
 {
 	struct scmi_xfer *t = m;
-	struct scmi_info *info = client_to_scmi_info(cl);
-	struct scmi_shared_mem *mem = info->tx_payload;
+	struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
+	struct scmi_shared_mem *mem = cinfo->payload;
 
 	mem->channel_status = 0x0; /* Mark channel busy + clear error */
 	mem->flags = t->hdr.poll_completion ? 0 :
@@ -371,9 +384,9 @@ void scmi_one_xfer_put(const struct scmi_handle *handle, struct scmi_xfer *xfer)
 }
 
 static bool
-scmi_xfer_poll_done(const struct scmi_info *info, struct scmi_xfer *xfer)
+scmi_xfer_poll_done(const struct scmi_chan_info *cinfo, struct scmi_xfer *xfer)
 {
-	struct scmi_shared_mem *mem = info->tx_payload;
+	struct scmi_shared_mem *mem = cinfo->payload;
 	u16 xfer_id = MSG_XTRACT_TOKEN(le32_to_cpu(mem->msg_header));
 
 	if (xfer->hdr.seq != xfer_id)
@@ -400,8 +413,9 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
 	int timeout;
 	struct scmi_info *info = handle_to_scmi_info(handle);
 	struct device *dev = info->dev;
+	struct scmi_chan_info *cinfo = info->tx_cinfo;
 
-	ret = mbox_send_message(info->tx_chan, xfer);
+	ret = mbox_send_message(cinfo->chan, xfer);
 	if (ret < 0) {
 		dev_dbg(dev, "mbox send fail %d\n", ret);
 		return ret;
@@ -412,10 +426,10 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
 
 	if (xfer->hdr.poll_completion) {
 		timeout = info->desc->max_rx_timeout_ms * 100;
-		while (!scmi_xfer_poll_done(info, xfer) && timeout--)
+		while (!scmi_xfer_poll_done(cinfo, xfer) && timeout--)
 			udelay(10);
 		if (timeout)
-			scmi_fetch_response(xfer, info->tx_payload);
+			scmi_fetch_response(xfer, cinfo->payload);
 		else
 			ret = -ETIMEDOUT;
 	} else {
@@ -435,7 +449,7 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
 	 * Unfortunately, we have to kick the mailbox framework after we have
 	 * received our message.
 	 */
-	mbox_client_txdone(info->tx_chan, ret);
+	mbox_client_txdone(cinfo->chan, ret);
 
 	return ret;
 }
@@ -757,11 +771,11 @@ static int scmi_mailbox_check(struct device_node *np)
 	return of_parse_phandle_with_args(np, "mboxes", "#mbox-cells", 0, &arg);
 }
 
-static int scmi_mbox_free_channel(struct scmi_info *info)
+static int scmi_mbox_free_channel(struct scmi_chan_info *cinfo)
 {
-	if (!IS_ERR_OR_NULL(info->tx_chan)) {
-		mbox_free_channel(info->tx_chan);
-		info->tx_chan = NULL;
+	if (!IS_ERR_OR_NULL(cinfo->chan)) {
+		mbox_free_channel(cinfo->chan);
+		cinfo->chan = NULL;
 	}
 
 	return 0;
@@ -783,7 +797,7 @@ static int scmi_remove(struct platform_device *pdev)
 
 	if (!ret)
 		/* Safe to free channels since no more users */
-		return scmi_mbox_free_channel(info);
+		return scmi_mbox_free_channel(info->tx_cinfo);
 
 	return ret;
 }
@@ -795,9 +809,17 @@ static inline int scmi_mbox_chan_setup(struct scmi_info *info)
 	resource_size_t size;
 	struct device *dev = info->dev;
 	struct device_node *shmem, *np = dev->of_node;
+	struct scmi_chan_info *cinfo;
 	struct mbox_client *cl;
 
-	cl = &info->cl;
+	cinfo = devm_kzalloc(info->dev, sizeof(*cinfo), GFP_KERNEL);
+	if (!cinfo)
+		return -ENOMEM;
+
+	info->tx_cinfo = cinfo;
+	cinfo->dev = dev;
+
+	cl = &cinfo->cl;
 	cl->dev = dev;
 	cl->rx_callback = scmi_rx_callback;
 	cl->tx_prepare = scmi_tx_prepare;
@@ -813,16 +835,16 @@ static inline int scmi_mbox_chan_setup(struct scmi_info *info)
 	}
 
 	size = resource_size(&res);
-	info->tx_payload = devm_ioremap(dev, res.start, size);
-	if (!info->tx_payload) {
+	cinfo->payload = devm_ioremap(info->dev, res.start, size);
+	if (!cinfo->payload) {
 		dev_err(dev, "failed to ioremap SCMI Tx payload\n");
 		return -EADDRNOTAVAIL;
 	}
 
 	/* Transmit channel is first entry i.e. index 0 */
-	info->tx_chan = mbox_request_channel(cl, 0);
-	if (IS_ERR(info->tx_chan)) {
-		ret = PTR_ERR(info->tx_chan);
+	cinfo->chan = mbox_request_channel(cl, 0);
+	if (IS_ERR(cinfo->chan)) {
+		ret = PTR_ERR(cinfo->chan);
 		if (ret != -EPROBE_DEFER)
 			dev_err(dev, "failed to request SCMI Tx mailbox\n");
 		return ret;
@@ -844,6 +866,8 @@ scmi_create_protocol_device(struct device_node *np, struct scmi_info *info,
 		return;
 	}
 
+	platform_set_drvdata(cdev, info);
+
 	init_ret = match->fn(&info->handle);
 	if (init_ret) {
 		dev_err(info->dev, "SCMI protocol %d init error %d\n",
@@ -894,7 +918,7 @@ static int scmi_probe(struct platform_device *pdev)
 	ret = scmi_base_protocol_init(handle);
 	if (ret) {
 		dev_err(dev, "unable to communicate with SCMI(%d)\n", ret);
-		scmi_mbox_free_channel(info);
+		scmi_mbox_free_channel(info->tx_cinfo);
 		return ret;
 	}
 
-- 
2.7.4

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

* [PATCH v3 14/22] firmware: arm_scmi: add per-protocol channels support using idr objects
  2017-09-28 13:11 ` Sudeep Holla
@ 2017-09-28 13:11   ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

In order to maintain the channel information per protocol, we need
some sort of list or hashtable to hold all this information. IDR
provides sparse array mapping of small integer ID numbers onto arbitrary
pointers. In this case the arbitrary pointers can be pointers to the
channel information.

This patch adds support for per-protocol channels using those idr
objects.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scmi/driver.c | 47 +++++++++++++++++++++++++++++---------
 1 file changed, 36 insertions(+), 11 deletions(-)

diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 93b3bd8d437f..92ef21d6aa5a 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -128,7 +128,7 @@ struct scmi_chan_info {
  * @version: SCMI revision information containing protocol version,
  *	implementation version and (sub-)vendor identification.
  * @minfo: Message info
- * @tx_cinfo: Reference to SCMI channel information
+ * @tx_idr: IDR object to map protocol id to channel info pointer
  * @protocols_imp: list of protocols implemented, currently maximum of
  *	MAX_PROTOCOLS_IMP elements allocated by the base protocol
  * @node: list head
@@ -140,7 +140,7 @@ struct scmi_info {
 	struct scmi_revision_info version;
 	struct scmi_handle handle;
 	struct scmi_xfers_info minfo;
-	struct scmi_chan_info *tx_cinfo;
+	struct idr tx_idr;
 	u8 *protocols_imp;
 	struct list_head node;
 	int users;
@@ -413,7 +413,11 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
 	int timeout;
 	struct scmi_info *info = handle_to_scmi_info(handle);
 	struct device *dev = info->dev;
-	struct scmi_chan_info *cinfo = info->tx_cinfo;
+	struct scmi_chan_info *cinfo;
+
+	cinfo = idr_find(&info->tx_idr, xfer->hdr.protocol_id);
+	if (unlikely(!cinfo))
+		return -EINVAL;
 
 	ret = mbox_send_message(cinfo->chan, xfer);
 	if (ret < 0) {
@@ -771,13 +775,18 @@ static int scmi_mailbox_check(struct device_node *np)
 	return of_parse_phandle_with_args(np, "mboxes", "#mbox-cells", 0, &arg);
 }
 
-static int scmi_mbox_free_channel(struct scmi_chan_info *cinfo)
+static int scmi_mbox_free_channel(int id, void *p, void *data)
 {
+	struct scmi_chan_info *cinfo = p;
+	struct idr *idr = data;
+
 	if (!IS_ERR_OR_NULL(cinfo->chan)) {
 		mbox_free_channel(cinfo->chan);
 		cinfo->chan = NULL;
 	}
 
+	idr_remove(idr, id);
+
 	return 0;
 }
 
@@ -785,6 +794,7 @@ static int scmi_remove(struct platform_device *pdev)
 {
 	int ret = 0;
 	struct scmi_info *info = platform_get_drvdata(pdev);
+	struct idr *idr = &info->tx_idr;
 
 	of_platform_depopulate(&pdev->dev);
 
@@ -795,28 +805,34 @@ static int scmi_remove(struct platform_device *pdev)
 		list_del(&info->node);
 	mutex_unlock(&scmi_list_mutex);
 
-	if (!ret)
+	if (!ret) {
 		/* Safe to free channels since no more users */
-		return scmi_mbox_free_channel(info->tx_cinfo);
+		ret = idr_for_each(idr, scmi_mbox_free_channel, idr);
+		idr_destroy(&info->tx_idr);
+	}
 
 	return ret;
 }
 
-static inline int scmi_mbox_chan_setup(struct scmi_info *info)
+static inline int
+scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, int prot_id)
 {
 	int ret;
 	struct resource res;
 	resource_size_t size;
-	struct device *dev = info->dev;
 	struct device_node *shmem, *np = dev->of_node;
 	struct scmi_chan_info *cinfo;
 	struct mbox_client *cl;
 
+	if (scmi_mailbox_check(np)) {
+		cinfo = idr_find(&info->tx_idr, SCMI_PROTOCOL_BASE);
+		goto idr_alloc;
+	}
+
 	cinfo = devm_kzalloc(info->dev, sizeof(*cinfo), GFP_KERNEL);
 	if (!cinfo)
 		return -ENOMEM;
 
-	info->tx_cinfo = cinfo;
 	cinfo->dev = dev;
 
 	cl = &cinfo->cl;
@@ -850,6 +866,13 @@ static inline int scmi_mbox_chan_setup(struct scmi_info *info)
 		return ret;
 	}
 
+idr_alloc:
+	ret = idr_alloc(&info->tx_idr, cinfo, prot_id, prot_id + 1, GFP_KERNEL);
+	if (ret != prot_id) {
+		dev_err(dev, "unable to allocate SCMI idr slot err %d\n", ret);
+		return ret;
+	}
+
 	return 0;
 }
 
@@ -868,6 +891,8 @@ scmi_create_protocol_device(struct device_node *np, struct scmi_info *info,
 
 	platform_set_drvdata(cdev, info);
 
+	scmi_mbox_chan_setup(info, &cdev->dev, match->protocol_id);
+
 	init_ret = match->fn(&info->handle);
 	if (init_ret) {
 		dev_err(info->dev, "SCMI protocol %d init error %d\n",
@@ -906,19 +931,19 @@ static int scmi_probe(struct platform_device *pdev)
 		return ret;
 
 	platform_set_drvdata(pdev, info);
+	idr_init(&info->tx_idr);
 
 	handle = &info->handle;
 	handle->dev = info->dev;
 	handle->version = &info->version;
 
-	ret = scmi_mbox_chan_setup(info);
+	ret = scmi_mbox_chan_setup(info, dev, SCMI_PROTOCOL_BASE);
 	if (ret)
 		return ret;
 
 	ret = scmi_base_protocol_init(handle);
 	if (ret) {
 		dev_err(dev, "unable to communicate with SCMI(%d)\n", ret);
-		scmi_mbox_free_channel(info->tx_cinfo);
 		return ret;
 	}
 
-- 
2.7.4

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

* [PATCH v3 14/22] firmware: arm_scmi: add per-protocol channels support using idr objects
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

In order to maintain the channel information per protocol, we need
some sort of list or hashtable to hold all this information. IDR
provides sparse array mapping of small integer ID numbers onto arbitrary
pointers. In this case the arbitrary pointers can be pointers to the
channel information.

This patch adds support for per-protocol channels using those idr
objects.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scmi/driver.c | 47 +++++++++++++++++++++++++++++---------
 1 file changed, 36 insertions(+), 11 deletions(-)

diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 93b3bd8d437f..92ef21d6aa5a 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -128,7 +128,7 @@ struct scmi_chan_info {
  * @version: SCMI revision information containing protocol version,
  *	implementation version and (sub-)vendor identification.
  * @minfo: Message info
- * @tx_cinfo: Reference to SCMI channel information
+ * @tx_idr: IDR object to map protocol id to channel info pointer
  * @protocols_imp: list of protocols implemented, currently maximum of
  *	MAX_PROTOCOLS_IMP elements allocated by the base protocol
  * @node: list head
@@ -140,7 +140,7 @@ struct scmi_info {
 	struct scmi_revision_info version;
 	struct scmi_handle handle;
 	struct scmi_xfers_info minfo;
-	struct scmi_chan_info *tx_cinfo;
+	struct idr tx_idr;
 	u8 *protocols_imp;
 	struct list_head node;
 	int users;
@@ -413,7 +413,11 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
 	int timeout;
 	struct scmi_info *info = handle_to_scmi_info(handle);
 	struct device *dev = info->dev;
-	struct scmi_chan_info *cinfo = info->tx_cinfo;
+	struct scmi_chan_info *cinfo;
+
+	cinfo = idr_find(&info->tx_idr, xfer->hdr.protocol_id);
+	if (unlikely(!cinfo))
+		return -EINVAL;
 
 	ret = mbox_send_message(cinfo->chan, xfer);
 	if (ret < 0) {
@@ -771,13 +775,18 @@ static int scmi_mailbox_check(struct device_node *np)
 	return of_parse_phandle_with_args(np, "mboxes", "#mbox-cells", 0, &arg);
 }
 
-static int scmi_mbox_free_channel(struct scmi_chan_info *cinfo)
+static int scmi_mbox_free_channel(int id, void *p, void *data)
 {
+	struct scmi_chan_info *cinfo = p;
+	struct idr *idr = data;
+
 	if (!IS_ERR_OR_NULL(cinfo->chan)) {
 		mbox_free_channel(cinfo->chan);
 		cinfo->chan = NULL;
 	}
 
+	idr_remove(idr, id);
+
 	return 0;
 }
 
@@ -785,6 +794,7 @@ static int scmi_remove(struct platform_device *pdev)
 {
 	int ret = 0;
 	struct scmi_info *info = platform_get_drvdata(pdev);
+	struct idr *idr = &info->tx_idr;
 
 	of_platform_depopulate(&pdev->dev);
 
@@ -795,28 +805,34 @@ static int scmi_remove(struct platform_device *pdev)
 		list_del(&info->node);
 	mutex_unlock(&scmi_list_mutex);
 
-	if (!ret)
+	if (!ret) {
 		/* Safe to free channels since no more users */
-		return scmi_mbox_free_channel(info->tx_cinfo);
+		ret = idr_for_each(idr, scmi_mbox_free_channel, idr);
+		idr_destroy(&info->tx_idr);
+	}
 
 	return ret;
 }
 
-static inline int scmi_mbox_chan_setup(struct scmi_info *info)
+static inline int
+scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, int prot_id)
 {
 	int ret;
 	struct resource res;
 	resource_size_t size;
-	struct device *dev = info->dev;
 	struct device_node *shmem, *np = dev->of_node;
 	struct scmi_chan_info *cinfo;
 	struct mbox_client *cl;
 
+	if (scmi_mailbox_check(np)) {
+		cinfo = idr_find(&info->tx_idr, SCMI_PROTOCOL_BASE);
+		goto idr_alloc;
+	}
+
 	cinfo = devm_kzalloc(info->dev, sizeof(*cinfo), GFP_KERNEL);
 	if (!cinfo)
 		return -ENOMEM;
 
-	info->tx_cinfo = cinfo;
 	cinfo->dev = dev;
 
 	cl = &cinfo->cl;
@@ -850,6 +866,13 @@ static inline int scmi_mbox_chan_setup(struct scmi_info *info)
 		return ret;
 	}
 
+idr_alloc:
+	ret = idr_alloc(&info->tx_idr, cinfo, prot_id, prot_id + 1, GFP_KERNEL);
+	if (ret != prot_id) {
+		dev_err(dev, "unable to allocate SCMI idr slot err %d\n", ret);
+		return ret;
+	}
+
 	return 0;
 }
 
@@ -868,6 +891,8 @@ scmi_create_protocol_device(struct device_node *np, struct scmi_info *info,
 
 	platform_set_drvdata(cdev, info);
 
+	scmi_mbox_chan_setup(info, &cdev->dev, match->protocol_id);
+
 	init_ret = match->fn(&info->handle);
 	if (init_ret) {
 		dev_err(info->dev, "SCMI protocol %d init error %d\n",
@@ -906,19 +931,19 @@ static int scmi_probe(struct platform_device *pdev)
 		return ret;
 
 	platform_set_drvdata(pdev, info);
+	idr_init(&info->tx_idr);
 
 	handle = &info->handle;
 	handle->dev = info->dev;
 	handle->version = &info->version;
 
-	ret = scmi_mbox_chan_setup(info);
+	ret = scmi_mbox_chan_setup(info, dev, SCMI_PROTOCOL_BASE);
 	if (ret)
 		return ret;
 
 	ret = scmi_base_protocol_init(handle);
 	if (ret) {
 		dev_err(dev, "unable to communicate with SCMI(%d)\n", ret);
-		scmi_mbox_free_channel(info->tx_cinfo);
 		return ret;
 	}
 
-- 
2.7.4

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

* [PATCH v3 15/22] firmware: arm_scmi: abstract mailbox interface
  2017-09-28 13:11 ` Sudeep Holla
@ 2017-09-28 13:11   ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

Some of the mailbox controller expects controller specific data in order
to implement simple doorbell mechanism as expected by SCMI specification.

This patch creates a shim layer to abstract the mailbox interface so
that it can support any mailbox controller. It also provides default
implementation which maps to standard mailbox client APIs, so that
controllers implementing doorbell mechanism need not require any
additional layer.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scmi/Makefile  |  2 +-
 drivers/firmware/arm_scmi/driver.c  | 84 ++++++++++---------------------------
 drivers/firmware/arm_scmi/mbox_if.c | 80 +++++++++++++++++++++++++++++++++++
 drivers/firmware/arm_scmi/mbox_if.h | 68 ++++++++++++++++++++++++++++++
 4 files changed, 172 insertions(+), 62 deletions(-)
 create mode 100644 drivers/firmware/arm_scmi/mbox_if.c
 create mode 100644 drivers/firmware/arm_scmi/mbox_if.h

diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index f9dee5ad0aa0..733157c5b4e2 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_ARM_SCMI_PROTOCOL)	= arm_scmi.o
-arm_scmi-y = base.o clock.o driver.o perf.o power.o sensors.o
+arm_scmi-y = base.o clock.o driver.o mbox_if.o perf.o power.o sensors.o
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 92ef21d6aa5a..97285a22dfaa 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -30,7 +30,6 @@
 #include <linux/export.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
-#include <linux/mailbox_client.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
@@ -38,6 +37,7 @@
 #include <linux/slab.h>
 
 #include "common.h"
+#include "mbox_if.h"
 
 #define MSG_ID_SHIFT		0
 #define MSG_ID_MASK		0xff
@@ -90,36 +90,6 @@ struct scmi_xfers_info {
 };
 
 /**
- * struct scmi_desc - Description of SoC integration
- *
- * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds)
- * @max_msg: Maximum number of messages that can be pending
- *	simultaneously in the system
- * @max_msg_size: Maximum size of data per message that can be handled.
- */
-struct scmi_desc {
-	int max_rx_timeout_ms;
-	int max_msg;
-	int max_msg_size;
-};
-
-/**
- * struct scmi_chan_info - Structure representing a SCMI channel informfation
- *
- * @cl: Mailbox Client
- * @chan: Transmit/Receive mailbox channel
- * @payload: Transmit/Receive mailbox channel payload area
- * @dev: Reference to device in the SCMI hierarchy corresponding to this
- *	 channel
- */
-struct scmi_chan_info {
-	struct mbox_client cl;
-	struct mbox_chan *chan;
-	void __iomem *payload;
-	struct device *dev;
-};
-
-/**
  * struct scmi_info - Structure representing a  SCMI instance
  *
  * @dev: Device pointer
@@ -137,6 +107,7 @@ struct scmi_chan_info {
 struct scmi_info {
 	struct device *dev;
 	const struct scmi_desc *desc;
+	struct scmi_mbox_ops *mbox_ops;
 	struct scmi_revision_info version;
 	struct scmi_handle handle;
 	struct scmi_xfers_info minfo;
@@ -146,7 +117,6 @@ struct scmi_info {
 	int users;
 };
 
-#define client_to_scmi_chan_info(c) container_of(c, struct scmi_chan_info, cl)
 #define handle_to_scmi_info(h)	container_of(h, struct scmi_info, handle)
 
 /*
@@ -221,10 +191,10 @@ static void scmi_fetch_response(struct scmi_xfer *xfer,
 }
 
 /**
- * scmi_rx_callback() - mailbox client callback for receive messages
+ * scmi_generic_rx_callback() -generic mailbox client callback for receive
+ * messages
  *
- * @cl: client pointer
- * @m: mailbox message
+ * @cinfo: pointer to structure with SCMI mailbox channels information
  *
  * Processes one received message to appropriate transfer information and
  * signals completion of the transfer.
@@ -232,11 +202,10 @@ static void scmi_fetch_response(struct scmi_xfer *xfer,
  * NOTE: This function will be invoked in IRQ context, hence should be
  * as optimal as possible.
  */
-static void scmi_rx_callback(struct mbox_client *cl, void *m)
+void scmi_generic_rx_callback(struct scmi_chan_info *cinfo)
 {
 	u16 xfer_id;
 	struct scmi_xfer *xfer;
-	struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
 	struct device *dev = cinfo->dev;
 	struct scmi_info *info = dev_get_drvdata(dev);
 	struct scmi_xfers_info *minfo = &info->minfo;
@@ -280,18 +249,18 @@ static inline u32 pack_scmi_header(struct scmi_msg_hdr *hdr)
 }
 
 /**
- * scmi_tx_prepare() - mailbox client callback to prepare for the transfer
+ * scmi_generic_tx_prepare() - generic mailbox client callback to prepare for
+ * the transfer
  *
- * @cl: client pointer
+ * @cinfo: pointer to structure with SCMI mailbox channels information
  * @m: mailbox message
  *
  * This function prepares the shared memory which contains the header and the
  * payload.
  */
-static void scmi_tx_prepare(struct mbox_client *cl, void *m)
+void scmi_generic_tx_prepare(struct scmi_chan_info *cinfo, void *m)
 {
 	struct scmi_xfer *t = m;
-	struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
 	struct scmi_shared_mem *mem = cinfo->payload;
 
 	mem->channel_status = 0x0; /* Mark channel busy + clear error */
@@ -384,9 +353,8 @@ void scmi_one_xfer_put(const struct scmi_handle *handle, struct scmi_xfer *xfer)
 }
 
 static bool
-scmi_xfer_poll_done(const struct scmi_chan_info *cinfo, struct scmi_xfer *xfer)
+scmi_xfer_poll_done(struct scmi_shared_mem *mem, struct scmi_xfer *xfer)
 {
-	struct scmi_shared_mem *mem = cinfo->payload;
 	u16 xfer_id = MSG_XTRACT_TOKEN(le32_to_cpu(mem->msg_header));
 
 	if (xfer->hdr.seq != xfer_id)
@@ -419,7 +387,7 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
 	if (unlikely(!cinfo))
 		return -EINVAL;
 
-	ret = mbox_send_message(cinfo->chan, xfer);
+	ret = info->mbox_ops->send_message(cinfo, xfer);
 	if (ret < 0) {
 		dev_dbg(dev, "mbox send fail %d\n", ret);
 		return ret;
@@ -430,7 +398,8 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
 
 	if (xfer->hdr.poll_completion) {
 		timeout = info->desc->max_rx_timeout_ms * 100;
-		while (!scmi_xfer_poll_done(cinfo, xfer) && timeout--)
+		while (!scmi_xfer_poll_done(cinfo->payload, xfer) &&
+		       timeout--)
 			udelay(10);
 		if (timeout)
 			scmi_fetch_response(xfer, cinfo->payload);
@@ -676,12 +645,6 @@ const struct scmi_handle *devm_scmi_handle_get(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(devm_scmi_handle_get);
 
-static const struct scmi_desc scmi_generic_desc = {
-	.max_rx_timeout_ms = 30,	/* we may increase this if required */
-	.max_msg = 20,		/* Limited by MBOX_TX_QUEUE_LEN */
-	.max_msg_size = 128,
-};
-
 /* Each compatible listed below must have descriptor associated with it */
 static const struct of_device_id scmi_of_match[] = {
 	{ .compatible = "arm,scmi", .data = &scmi_generic_desc },
@@ -775,13 +738,14 @@ static int scmi_mailbox_check(struct device_node *np)
 	return of_parse_phandle_with_args(np, "mboxes", "#mbox-cells", 0, &arg);
 }
 
-static int scmi_mbox_free_channel(int id, void *p, void *data)
+static int scmi_free_channel(int id, void *p, void *data)
 {
-	struct scmi_chan_info *cinfo = p;
 	struct idr *idr = data;
+	struct scmi_chan_info *cinfo = p;
+	struct scmi_info *info = dev_get_drvdata(cinfo->dev);
 
 	if (!IS_ERR_OR_NULL(cinfo->chan)) {
-		mbox_free_channel(cinfo->chan);
+		info->mbox_ops->free_channel(cinfo);
 		cinfo->chan = NULL;
 	}
 
@@ -807,7 +771,7 @@ static int scmi_remove(struct platform_device *pdev)
 
 	if (!ret) {
 		/* Safe to free channels since no more users */
-		ret = idr_for_each(idr, scmi_mbox_free_channel, idr);
+		ret = idr_for_each(idr, scmi_free_channel, idr);
 		idr_destroy(&info->tx_idr);
 	}
 
@@ -834,11 +798,8 @@ scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, int prot_id)
 		return -ENOMEM;
 
 	cinfo->dev = dev;
-
 	cl = &cinfo->cl;
 	cl->dev = dev;
-	cl->rx_callback = scmi_rx_callback;
-	cl->tx_prepare = scmi_tx_prepare;
 	cl->tx_block = false;
 	cl->knows_txdone = true;
 
@@ -858,9 +819,8 @@ scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, int prot_id)
 	}
 
 	/* Transmit channel is first entry i.e. index 0 */
-	cinfo->chan = mbox_request_channel(cl, 0);
-	if (IS_ERR(cinfo->chan)) {
-		ret = PTR_ERR(cinfo->chan);
+	ret = info->mbox_ops->request_channel(cinfo, 0);
+	if (ret) {
 		if (ret != -EPROBE_DEFER)
 			dev_err(dev, "failed to request SCMI Tx mailbox\n");
 		return ret;
@@ -924,6 +884,8 @@ static int scmi_probe(struct platform_device *pdev)
 
 	info->dev = dev;
 	info->desc = desc;
+	/* set up mailbox operations */
+	info->mbox_ops = desc->mbox_ops;
 	INIT_LIST_HEAD(&info->node);
 
 	ret = scmi_xfer_info_init(info);
diff --git a/drivers/firmware/arm_scmi/mbox_if.c b/drivers/firmware/arm_scmi/mbox_if.c
new file mode 100644
index 000000000000..dc2bcc060f30
--- /dev/null
+++ b/drivers/firmware/arm_scmi/mbox_if.c
@@ -0,0 +1,80 @@
+/*
+ * System Control and Management Interface (SCMI) default mailbox interface
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "mbox_if.h"
+
+static void scmi_tx_prepare(struct mbox_client *cl, void *m)
+{
+	struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
+
+	scmi_generic_tx_prepare(cinfo, m);
+}
+
+static void scmi_rx_callback(struct mbox_client *cl, void *m)
+{
+	struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
+
+	scmi_generic_rx_callback(cinfo);
+}
+
+static int scmi_mbox_request_channel(struct scmi_chan_info *cinfo, int index)
+{
+	int ret = 0;
+	struct mbox_client *cl = &cinfo->cl;
+
+	cl->rx_callback = scmi_rx_callback;
+	cl->tx_prepare = scmi_tx_prepare;
+
+	cinfo->chan = mbox_request_channel(cl, index);
+	if (IS_ERR(cinfo->chan))
+		ret = PTR_ERR(cinfo->chan);
+
+	return ret;
+}
+
+static int scmi_mbox_send_message(struct scmi_chan_info *cinfo, void *msg)
+{
+	return mbox_send_message(cinfo->chan, msg);
+}
+
+static void scmi_mbox_client_txdone(struct scmi_chan_info *cinfo, int r)
+{
+	mbox_client_txdone(cinfo->chan, r);
+}
+
+static void scmi_mbox_free_channel(struct scmi_chan_info *cinfo)
+{
+	mbox_free_channel(cinfo->chan);
+}
+
+static struct scmi_mbox_ops scmi_default_mbox_ops = {
+	.request_channel = scmi_mbox_request_channel,
+	.send_message = scmi_mbox_send_message,
+	.client_txdone = scmi_mbox_client_txdone,
+	.free_channel = scmi_mbox_free_channel,
+};
+
+const struct scmi_desc scmi_generic_desc = {
+	.max_rx_timeout_ms = 30,	/* we may increase this if required */
+	.max_msg = 20,		/* Limited by MBOX_TX_QUEUE_LEN */
+	.max_msg_size = 128,
+	.mbox_ops = &scmi_default_mbox_ops,
+};
diff --git a/drivers/firmware/arm_scmi/mbox_if.h b/drivers/firmware/arm_scmi/mbox_if.h
new file mode 100644
index 000000000000..02baa73e8613
--- /dev/null
+++ b/drivers/firmware/arm_scmi/mbox_if.h
@@ -0,0 +1,68 @@
+/*
+ * System Control and Management Interface (SCMI) mailbox interface header
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/mailbox_client.h>
+
+/**
+ * struct scmi_chan_info - Structure representing a SCMI channel informfation
+ *
+ * @cl: Mailbox Client
+ * @tx_chan: Transmit mailbox channel
+ * @rx_chan: Receive mailbox channel
+ * @tx_payload: Transmit mailbox channel payload area
+ * @rx_payload: Receive mailbox channel payload area
+ * @dev: Reference to device in the SCMI hierarchy corresponding to this
+ *	 channel
+ */
+struct scmi_chan_info {
+	struct mbox_client cl;
+	struct mbox_chan *chan;
+	void __iomem *payload;
+	struct device *dev;
+	void *priv;
+};
+
+#define client_to_scmi_chan_info(c) container_of(c, struct scmi_chan_info, cl)
+
+struct scmi_mbox_ops {
+	int (*request_channel)(struct scmi_chan_info *cinfo, int index);
+	int (*send_message)(struct scmi_chan_info *cinfo, void *msg);
+	void (*client_txdone)(struct scmi_chan_info *cinfo, int r);
+	void (*free_channel)(struct scmi_chan_info *cinfo);
+};
+
+/**
+ * struct scmi_desc - Description of SoC integration
+ *
+ * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds)
+ * @max_msg: Maximum number of messages that can be pending
+ *	simultaneously in the system
+ * @max_msg_size: Maximum size of data per message that can be handled.
+ * @mbox_ops: Function to initialise the mailbox operations
+ */
+struct scmi_desc {
+	int max_rx_timeout_ms;
+	int max_msg;
+	int max_msg_size;
+	struct scmi_mbox_ops *mbox_ops;
+};
+
+void scmi_generic_rx_callback(struct scmi_chan_info *cinfo);
+void scmi_generic_tx_prepare(struct scmi_chan_info *cinfo, void *m);
+
+extern const struct scmi_desc scmi_generic_desc;
-- 
2.7.4

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

* [PATCH v3 15/22] firmware: arm_scmi: abstract mailbox interface
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

Some of the mailbox controller expects controller specific data in order
to implement simple doorbell mechanism as expected by SCMI specification.

This patch creates a shim layer to abstract the mailbox interface so
that it can support any mailbox controller. It also provides default
implementation which maps to standard mailbox client APIs, so that
controllers implementing doorbell mechanism need not require any
additional layer.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scmi/Makefile  |  2 +-
 drivers/firmware/arm_scmi/driver.c  | 84 ++++++++++---------------------------
 drivers/firmware/arm_scmi/mbox_if.c | 80 +++++++++++++++++++++++++++++++++++
 drivers/firmware/arm_scmi/mbox_if.h | 68 ++++++++++++++++++++++++++++++
 4 files changed, 172 insertions(+), 62 deletions(-)
 create mode 100644 drivers/firmware/arm_scmi/mbox_if.c
 create mode 100644 drivers/firmware/arm_scmi/mbox_if.h

diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index f9dee5ad0aa0..733157c5b4e2 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_ARM_SCMI_PROTOCOL)	= arm_scmi.o
-arm_scmi-y = base.o clock.o driver.o perf.o power.o sensors.o
+arm_scmi-y = base.o clock.o driver.o mbox_if.o perf.o power.o sensors.o
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 92ef21d6aa5a..97285a22dfaa 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -30,7 +30,6 @@
 #include <linux/export.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
-#include <linux/mailbox_client.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
@@ -38,6 +37,7 @@
 #include <linux/slab.h>
 
 #include "common.h"
+#include "mbox_if.h"
 
 #define MSG_ID_SHIFT		0
 #define MSG_ID_MASK		0xff
@@ -90,36 +90,6 @@ struct scmi_xfers_info {
 };
 
 /**
- * struct scmi_desc - Description of SoC integration
- *
- * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds)
- * @max_msg: Maximum number of messages that can be pending
- *	simultaneously in the system
- * @max_msg_size: Maximum size of data per message that can be handled.
- */
-struct scmi_desc {
-	int max_rx_timeout_ms;
-	int max_msg;
-	int max_msg_size;
-};
-
-/**
- * struct scmi_chan_info - Structure representing a SCMI channel informfation
- *
- * @cl: Mailbox Client
- * @chan: Transmit/Receive mailbox channel
- * @payload: Transmit/Receive mailbox channel payload area
- * @dev: Reference to device in the SCMI hierarchy corresponding to this
- *	 channel
- */
-struct scmi_chan_info {
-	struct mbox_client cl;
-	struct mbox_chan *chan;
-	void __iomem *payload;
-	struct device *dev;
-};
-
-/**
  * struct scmi_info - Structure representing a  SCMI instance
  *
  * @dev: Device pointer
@@ -137,6 +107,7 @@ struct scmi_chan_info {
 struct scmi_info {
 	struct device *dev;
 	const struct scmi_desc *desc;
+	struct scmi_mbox_ops *mbox_ops;
 	struct scmi_revision_info version;
 	struct scmi_handle handle;
 	struct scmi_xfers_info minfo;
@@ -146,7 +117,6 @@ struct scmi_info {
 	int users;
 };
 
-#define client_to_scmi_chan_info(c) container_of(c, struct scmi_chan_info, cl)
 #define handle_to_scmi_info(h)	container_of(h, struct scmi_info, handle)
 
 /*
@@ -221,10 +191,10 @@ static void scmi_fetch_response(struct scmi_xfer *xfer,
 }
 
 /**
- * scmi_rx_callback() - mailbox client callback for receive messages
+ * scmi_generic_rx_callback() -generic mailbox client callback for receive
+ * messages
  *
- * @cl: client pointer
- * @m: mailbox message
+ * @cinfo: pointer to structure with SCMI mailbox channels information
  *
  * Processes one received message to appropriate transfer information and
  * signals completion of the transfer.
@@ -232,11 +202,10 @@ static void scmi_fetch_response(struct scmi_xfer *xfer,
  * NOTE: This function will be invoked in IRQ context, hence should be
  * as optimal as possible.
  */
-static void scmi_rx_callback(struct mbox_client *cl, void *m)
+void scmi_generic_rx_callback(struct scmi_chan_info *cinfo)
 {
 	u16 xfer_id;
 	struct scmi_xfer *xfer;
-	struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
 	struct device *dev = cinfo->dev;
 	struct scmi_info *info = dev_get_drvdata(dev);
 	struct scmi_xfers_info *minfo = &info->minfo;
@@ -280,18 +249,18 @@ static inline u32 pack_scmi_header(struct scmi_msg_hdr *hdr)
 }
 
 /**
- * scmi_tx_prepare() - mailbox client callback to prepare for the transfer
+ * scmi_generic_tx_prepare() - generic mailbox client callback to prepare for
+ * the transfer
  *
- * @cl: client pointer
+ * @cinfo: pointer to structure with SCMI mailbox channels information
  * @m: mailbox message
  *
  * This function prepares the shared memory which contains the header and the
  * payload.
  */
-static void scmi_tx_prepare(struct mbox_client *cl, void *m)
+void scmi_generic_tx_prepare(struct scmi_chan_info *cinfo, void *m)
 {
 	struct scmi_xfer *t = m;
-	struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
 	struct scmi_shared_mem *mem = cinfo->payload;
 
 	mem->channel_status = 0x0; /* Mark channel busy + clear error */
@@ -384,9 +353,8 @@ void scmi_one_xfer_put(const struct scmi_handle *handle, struct scmi_xfer *xfer)
 }
 
 static bool
-scmi_xfer_poll_done(const struct scmi_chan_info *cinfo, struct scmi_xfer *xfer)
+scmi_xfer_poll_done(struct scmi_shared_mem *mem, struct scmi_xfer *xfer)
 {
-	struct scmi_shared_mem *mem = cinfo->payload;
 	u16 xfer_id = MSG_XTRACT_TOKEN(le32_to_cpu(mem->msg_header));
 
 	if (xfer->hdr.seq != xfer_id)
@@ -419,7 +387,7 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
 	if (unlikely(!cinfo))
 		return -EINVAL;
 
-	ret = mbox_send_message(cinfo->chan, xfer);
+	ret = info->mbox_ops->send_message(cinfo, xfer);
 	if (ret < 0) {
 		dev_dbg(dev, "mbox send fail %d\n", ret);
 		return ret;
@@ -430,7 +398,8 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
 
 	if (xfer->hdr.poll_completion) {
 		timeout = info->desc->max_rx_timeout_ms * 100;
-		while (!scmi_xfer_poll_done(cinfo, xfer) && timeout--)
+		while (!scmi_xfer_poll_done(cinfo->payload, xfer) &&
+		       timeout--)
 			udelay(10);
 		if (timeout)
 			scmi_fetch_response(xfer, cinfo->payload);
@@ -676,12 +645,6 @@ const struct scmi_handle *devm_scmi_handle_get(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(devm_scmi_handle_get);
 
-static const struct scmi_desc scmi_generic_desc = {
-	.max_rx_timeout_ms = 30,	/* we may increase this if required */
-	.max_msg = 20,		/* Limited by MBOX_TX_QUEUE_LEN */
-	.max_msg_size = 128,
-};
-
 /* Each compatible listed below must have descriptor associated with it */
 static const struct of_device_id scmi_of_match[] = {
 	{ .compatible = "arm,scmi", .data = &scmi_generic_desc },
@@ -775,13 +738,14 @@ static int scmi_mailbox_check(struct device_node *np)
 	return of_parse_phandle_with_args(np, "mboxes", "#mbox-cells", 0, &arg);
 }
 
-static int scmi_mbox_free_channel(int id, void *p, void *data)
+static int scmi_free_channel(int id, void *p, void *data)
 {
-	struct scmi_chan_info *cinfo = p;
 	struct idr *idr = data;
+	struct scmi_chan_info *cinfo = p;
+	struct scmi_info *info = dev_get_drvdata(cinfo->dev);
 
 	if (!IS_ERR_OR_NULL(cinfo->chan)) {
-		mbox_free_channel(cinfo->chan);
+		info->mbox_ops->free_channel(cinfo);
 		cinfo->chan = NULL;
 	}
 
@@ -807,7 +771,7 @@ static int scmi_remove(struct platform_device *pdev)
 
 	if (!ret) {
 		/* Safe to free channels since no more users */
-		ret = idr_for_each(idr, scmi_mbox_free_channel, idr);
+		ret = idr_for_each(idr, scmi_free_channel, idr);
 		idr_destroy(&info->tx_idr);
 	}
 
@@ -834,11 +798,8 @@ scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, int prot_id)
 		return -ENOMEM;
 
 	cinfo->dev = dev;
-
 	cl = &cinfo->cl;
 	cl->dev = dev;
-	cl->rx_callback = scmi_rx_callback;
-	cl->tx_prepare = scmi_tx_prepare;
 	cl->tx_block = false;
 	cl->knows_txdone = true;
 
@@ -858,9 +819,8 @@ scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, int prot_id)
 	}
 
 	/* Transmit channel is first entry i.e. index 0 */
-	cinfo->chan = mbox_request_channel(cl, 0);
-	if (IS_ERR(cinfo->chan)) {
-		ret = PTR_ERR(cinfo->chan);
+	ret = info->mbox_ops->request_channel(cinfo, 0);
+	if (ret) {
 		if (ret != -EPROBE_DEFER)
 			dev_err(dev, "failed to request SCMI Tx mailbox\n");
 		return ret;
@@ -924,6 +884,8 @@ static int scmi_probe(struct platform_device *pdev)
 
 	info->dev = dev;
 	info->desc = desc;
+	/* set up mailbox operations */
+	info->mbox_ops = desc->mbox_ops;
 	INIT_LIST_HEAD(&info->node);
 
 	ret = scmi_xfer_info_init(info);
diff --git a/drivers/firmware/arm_scmi/mbox_if.c b/drivers/firmware/arm_scmi/mbox_if.c
new file mode 100644
index 000000000000..dc2bcc060f30
--- /dev/null
+++ b/drivers/firmware/arm_scmi/mbox_if.c
@@ -0,0 +1,80 @@
+/*
+ * System Control and Management Interface (SCMI) default mailbox interface
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "mbox_if.h"
+
+static void scmi_tx_prepare(struct mbox_client *cl, void *m)
+{
+	struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
+
+	scmi_generic_tx_prepare(cinfo, m);
+}
+
+static void scmi_rx_callback(struct mbox_client *cl, void *m)
+{
+	struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
+
+	scmi_generic_rx_callback(cinfo);
+}
+
+static int scmi_mbox_request_channel(struct scmi_chan_info *cinfo, int index)
+{
+	int ret = 0;
+	struct mbox_client *cl = &cinfo->cl;
+
+	cl->rx_callback = scmi_rx_callback;
+	cl->tx_prepare = scmi_tx_prepare;
+
+	cinfo->chan = mbox_request_channel(cl, index);
+	if (IS_ERR(cinfo->chan))
+		ret = PTR_ERR(cinfo->chan);
+
+	return ret;
+}
+
+static int scmi_mbox_send_message(struct scmi_chan_info *cinfo, void *msg)
+{
+	return mbox_send_message(cinfo->chan, msg);
+}
+
+static void scmi_mbox_client_txdone(struct scmi_chan_info *cinfo, int r)
+{
+	mbox_client_txdone(cinfo->chan, r);
+}
+
+static void scmi_mbox_free_channel(struct scmi_chan_info *cinfo)
+{
+	mbox_free_channel(cinfo->chan);
+}
+
+static struct scmi_mbox_ops scmi_default_mbox_ops = {
+	.request_channel = scmi_mbox_request_channel,
+	.send_message = scmi_mbox_send_message,
+	.client_txdone = scmi_mbox_client_txdone,
+	.free_channel = scmi_mbox_free_channel,
+};
+
+const struct scmi_desc scmi_generic_desc = {
+	.max_rx_timeout_ms = 30,	/* we may increase this if required */
+	.max_msg = 20,		/* Limited by MBOX_TX_QUEUE_LEN */
+	.max_msg_size = 128,
+	.mbox_ops = &scmi_default_mbox_ops,
+};
diff --git a/drivers/firmware/arm_scmi/mbox_if.h b/drivers/firmware/arm_scmi/mbox_if.h
new file mode 100644
index 000000000000..02baa73e8613
--- /dev/null
+++ b/drivers/firmware/arm_scmi/mbox_if.h
@@ -0,0 +1,68 @@
+/*
+ * System Control and Management Interface (SCMI) mailbox interface header
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/mailbox_client.h>
+
+/**
+ * struct scmi_chan_info - Structure representing a SCMI channel informfation
+ *
+ * @cl: Mailbox Client
+ * @tx_chan: Transmit mailbox channel
+ * @rx_chan: Receive mailbox channel
+ * @tx_payload: Transmit mailbox channel payload area
+ * @rx_payload: Receive mailbox channel payload area
+ * @dev: Reference to device in the SCMI hierarchy corresponding to this
+ *	 channel
+ */
+struct scmi_chan_info {
+	struct mbox_client cl;
+	struct mbox_chan *chan;
+	void __iomem *payload;
+	struct device *dev;
+	void *priv;
+};
+
+#define client_to_scmi_chan_info(c) container_of(c, struct scmi_chan_info, cl)
+
+struct scmi_mbox_ops {
+	int (*request_channel)(struct scmi_chan_info *cinfo, int index);
+	int (*send_message)(struct scmi_chan_info *cinfo, void *msg);
+	void (*client_txdone)(struct scmi_chan_info *cinfo, int r);
+	void (*free_channel)(struct scmi_chan_info *cinfo);
+};
+
+/**
+ * struct scmi_desc - Description of SoC integration
+ *
+ * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds)
+ * @max_msg: Maximum number of messages that can be pending
+ *	simultaneously in the system
+ * @max_msg_size: Maximum size of data per message that can be handled.
+ * @mbox_ops: Function to initialise the mailbox operations
+ */
+struct scmi_desc {
+	int max_rx_timeout_ms;
+	int max_msg;
+	int max_msg_size;
+	struct scmi_mbox_ops *mbox_ops;
+};
+
+void scmi_generic_rx_callback(struct scmi_chan_info *cinfo);
+void scmi_generic_tx_prepare(struct scmi_chan_info *cinfo, void *m);
+
+extern const struct scmi_desc scmi_generic_desc;
-- 
2.7.4

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

* [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

This patch adds ARM MHU specific mailbox interface for SCMI.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scmi/Makefile     |   1 +
 drivers/firmware/arm_scmi/arm_mhu_if.c | 106 +++++++++++++++++++++++++++++++++
 drivers/firmware/arm_scmi/driver.c     |   3 +
 drivers/firmware/arm_scmi/mbox_if.h    |   3 +
 4 files changed, 113 insertions(+)
 create mode 100644 drivers/firmware/arm_scmi/arm_mhu_if.c

diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index 733157c5b4e2..7fb026c71833 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_ARM_SCMI_PROTOCOL)	= arm_scmi.o
 arm_scmi-y = base.o clock.o driver.o mbox_if.o perf.o power.o sensors.o
+arm_scmi-$(CONFIG_ARM_MHU) += arm_mhu_if.o
diff --git a/drivers/firmware/arm_scmi/arm_mhu_if.c b/drivers/firmware/arm_scmi/arm_mhu_if.c
new file mode 100644
index 000000000000..2271a4811378
--- /dev/null
+++ b/drivers/firmware/arm_scmi/arm_mhu_if.c
@@ -0,0 +1,106 @@
+/*
+ * System Control and Management Interface (SCMI) MHU mailbox interface
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "common.h"
+#include "mbox_if.h"
+
+union mhu_data {
+	void *ptr;
+	u32 val;
+};
+
+static void mhu_tx_prepare(struct mbox_client *cl, void *m)
+{
+	struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
+	union mhu_data tmp;
+
+	scmi_generic_tx_prepare(cinfo, m);
+
+	/* clear only the relavant bit */
+	tmp.ptr = cinfo->priv;
+	*(u32 *)m &= tmp.val;
+}
+
+static void mhu_rx_callback(struct mbox_client *cl, void *m)
+{
+	struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
+
+	scmi_generic_rx_callback(cinfo);
+}
+
+static int mhu_mbox_request_channel(struct scmi_chan_info *cinfo, int index)
+{
+	int ret = 0;
+	struct mbox_client *cl = &cinfo->cl;
+	struct device_node *np = cl->dev->of_node;
+	union mhu_data tmp = {0};
+
+	if (index != 0 && index != 1) /* Tx = 0, Rx =1 */
+		return -EINVAL;
+
+	cl->rx_callback = mhu_rx_callback;
+	cl->tx_prepare = mhu_tx_prepare;
+
+	ret = of_property_read_u32_index(np, "mbox-data", index, &tmp.val);
+	if (ret)
+		return ret;
+
+	cinfo->chan = mbox_request_channel(cl, index);
+	if (IS_ERR(cinfo->chan))
+		ret = PTR_ERR(cinfo->chan);
+
+	cinfo->priv = tmp.ptr;
+
+	return ret;
+}
+
+static int mhu_mbox_send_message(struct scmi_chan_info *cinfo, void *msg)
+{
+	struct scmi_xfer *t = msg;
+
+	t->con_priv = cinfo->priv;
+
+	return mbox_send_message(cinfo->chan, msg);
+}
+
+static void mhu_mbox_client_txdone(struct scmi_chan_info *cinfo, int r)
+{
+	mbox_client_txdone(cinfo->chan, r);
+}
+
+static void mhu_mbox_free_channel(struct scmi_chan_info *cinfo)
+{
+	mbox_free_channel(cinfo->chan);
+}
+
+static struct scmi_mbox_ops arm_mhu_mbox_ops = {
+	.request_channel = mhu_mbox_request_channel,
+	.send_message = mhu_mbox_send_message,
+	.client_txdone = mhu_mbox_client_txdone,
+	.free_channel = mhu_mbox_free_channel,
+};
+
+const struct scmi_desc mhu_scmi_desc = {
+	.max_rx_timeout_ms = 30,
+	.max_msg = 20,
+	.max_msg_size = 128,
+	.mbox_ops = &arm_mhu_mbox_ops,
+};
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 97285a22dfaa..bdc9c566e6c1 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -648,6 +648,9 @@ EXPORT_SYMBOL_GPL(devm_scmi_handle_get);
 /* Each compatible listed below must have descriptor associated with it */
 static const struct of_device_id scmi_of_match[] = {
 	{ .compatible = "arm,scmi", .data = &scmi_generic_desc },
+#if IS_REACHABLE(CONFIG_ARM_MHU)
+	{ .compatible = "arm,mhu-scmi", .data = &mhu_scmi_desc },
+#endif
 	{ /* Sentinel */ },
 };
 
diff --git a/drivers/firmware/arm_scmi/mbox_if.h b/drivers/firmware/arm_scmi/mbox_if.h
index 02baa73e8613..a23fc6d7a91f 100644
--- a/drivers/firmware/arm_scmi/mbox_if.h
+++ b/drivers/firmware/arm_scmi/mbox_if.h
@@ -66,3 +66,6 @@ void scmi_generic_rx_callback(struct scmi_chan_info *cinfo);
 void scmi_generic_tx_prepare(struct scmi_chan_info *cinfo, void *m);
 
 extern const struct scmi_desc scmi_generic_desc;
+#if IS_REACHABLE(CONFIG_ARM_MHU)
+extern const struct scmi_desc mhu_scmi_desc;
+#endif
-- 
2.7.4

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

* [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

This patch adds ARM MHU specific mailbox interface for SCMI.

Cc: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
Signed-off-by: Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org>
---
 drivers/firmware/arm_scmi/Makefile     |   1 +
 drivers/firmware/arm_scmi/arm_mhu_if.c | 106 +++++++++++++++++++++++++++++++++
 drivers/firmware/arm_scmi/driver.c     |   3 +
 drivers/firmware/arm_scmi/mbox_if.h    |   3 +
 4 files changed, 113 insertions(+)
 create mode 100644 drivers/firmware/arm_scmi/arm_mhu_if.c

diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index 733157c5b4e2..7fb026c71833 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_ARM_SCMI_PROTOCOL)	= arm_scmi.o
 arm_scmi-y = base.o clock.o driver.o mbox_if.o perf.o power.o sensors.o
+arm_scmi-$(CONFIG_ARM_MHU) += arm_mhu_if.o
diff --git a/drivers/firmware/arm_scmi/arm_mhu_if.c b/drivers/firmware/arm_scmi/arm_mhu_if.c
new file mode 100644
index 000000000000..2271a4811378
--- /dev/null
+++ b/drivers/firmware/arm_scmi/arm_mhu_if.c
@@ -0,0 +1,106 @@
+/*
+ * System Control and Management Interface (SCMI) MHU mailbox interface
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "common.h"
+#include "mbox_if.h"
+
+union mhu_data {
+	void *ptr;
+	u32 val;
+};
+
+static void mhu_tx_prepare(struct mbox_client *cl, void *m)
+{
+	struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
+	union mhu_data tmp;
+
+	scmi_generic_tx_prepare(cinfo, m);
+
+	/* clear only the relavant bit */
+	tmp.ptr = cinfo->priv;
+	*(u32 *)m &= tmp.val;
+}
+
+static void mhu_rx_callback(struct mbox_client *cl, void *m)
+{
+	struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
+
+	scmi_generic_rx_callback(cinfo);
+}
+
+static int mhu_mbox_request_channel(struct scmi_chan_info *cinfo, int index)
+{
+	int ret = 0;
+	struct mbox_client *cl = &cinfo->cl;
+	struct device_node *np = cl->dev->of_node;
+	union mhu_data tmp = {0};
+
+	if (index != 0 && index != 1) /* Tx = 0, Rx =1 */
+		return -EINVAL;
+
+	cl->rx_callback = mhu_rx_callback;
+	cl->tx_prepare = mhu_tx_prepare;
+
+	ret = of_property_read_u32_index(np, "mbox-data", index, &tmp.val);
+	if (ret)
+		return ret;
+
+	cinfo->chan = mbox_request_channel(cl, index);
+	if (IS_ERR(cinfo->chan))
+		ret = PTR_ERR(cinfo->chan);
+
+	cinfo->priv = tmp.ptr;
+
+	return ret;
+}
+
+static int mhu_mbox_send_message(struct scmi_chan_info *cinfo, void *msg)
+{
+	struct scmi_xfer *t = msg;
+
+	t->con_priv = cinfo->priv;
+
+	return mbox_send_message(cinfo->chan, msg);
+}
+
+static void mhu_mbox_client_txdone(struct scmi_chan_info *cinfo, int r)
+{
+	mbox_client_txdone(cinfo->chan, r);
+}
+
+static void mhu_mbox_free_channel(struct scmi_chan_info *cinfo)
+{
+	mbox_free_channel(cinfo->chan);
+}
+
+static struct scmi_mbox_ops arm_mhu_mbox_ops = {
+	.request_channel = mhu_mbox_request_channel,
+	.send_message = mhu_mbox_send_message,
+	.client_txdone = mhu_mbox_client_txdone,
+	.free_channel = mhu_mbox_free_channel,
+};
+
+const struct scmi_desc mhu_scmi_desc = {
+	.max_rx_timeout_ms = 30,
+	.max_msg = 20,
+	.max_msg_size = 128,
+	.mbox_ops = &arm_mhu_mbox_ops,
+};
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 97285a22dfaa..bdc9c566e6c1 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -648,6 +648,9 @@ EXPORT_SYMBOL_GPL(devm_scmi_handle_get);
 /* Each compatible listed below must have descriptor associated with it */
 static const struct of_device_id scmi_of_match[] = {
 	{ .compatible = "arm,scmi", .data = &scmi_generic_desc },
+#if IS_REACHABLE(CONFIG_ARM_MHU)
+	{ .compatible = "arm,mhu-scmi", .data = &mhu_scmi_desc },
+#endif
 	{ /* Sentinel */ },
 };
 
diff --git a/drivers/firmware/arm_scmi/mbox_if.h b/drivers/firmware/arm_scmi/mbox_if.h
index 02baa73e8613..a23fc6d7a91f 100644
--- a/drivers/firmware/arm_scmi/mbox_if.h
+++ b/drivers/firmware/arm_scmi/mbox_if.h
@@ -66,3 +66,6 @@ void scmi_generic_rx_callback(struct scmi_chan_info *cinfo);
 void scmi_generic_tx_prepare(struct scmi_chan_info *cinfo, void *m);
 
 extern const struct scmi_desc scmi_generic_desc;
+#if IS_REACHABLE(CONFIG_ARM_MHU)
+extern const struct scmi_desc mhu_scmi_desc;
+#endif
-- 
2.7.4

--
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] 208+ messages in thread

* [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds ARM MHU specific mailbox interface for SCMI.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/arm_scmi/Makefile     |   1 +
 drivers/firmware/arm_scmi/arm_mhu_if.c | 106 +++++++++++++++++++++++++++++++++
 drivers/firmware/arm_scmi/driver.c     |   3 +
 drivers/firmware/arm_scmi/mbox_if.h    |   3 +
 4 files changed, 113 insertions(+)
 create mode 100644 drivers/firmware/arm_scmi/arm_mhu_if.c

diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index 733157c5b4e2..7fb026c71833 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_ARM_SCMI_PROTOCOL)	= arm_scmi.o
 arm_scmi-y = base.o clock.o driver.o mbox_if.o perf.o power.o sensors.o
+arm_scmi-$(CONFIG_ARM_MHU) += arm_mhu_if.o
diff --git a/drivers/firmware/arm_scmi/arm_mhu_if.c b/drivers/firmware/arm_scmi/arm_mhu_if.c
new file mode 100644
index 000000000000..2271a4811378
--- /dev/null
+++ b/drivers/firmware/arm_scmi/arm_mhu_if.c
@@ -0,0 +1,106 @@
+/*
+ * System Control and Management Interface (SCMI) MHU mailbox interface
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "common.h"
+#include "mbox_if.h"
+
+union mhu_data {
+	void *ptr;
+	u32 val;
+};
+
+static void mhu_tx_prepare(struct mbox_client *cl, void *m)
+{
+	struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
+	union mhu_data tmp;
+
+	scmi_generic_tx_prepare(cinfo, m);
+
+	/* clear only the relavant bit */
+	tmp.ptr = cinfo->priv;
+	*(u32 *)m &= tmp.val;
+}
+
+static void mhu_rx_callback(struct mbox_client *cl, void *m)
+{
+	struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
+
+	scmi_generic_rx_callback(cinfo);
+}
+
+static int mhu_mbox_request_channel(struct scmi_chan_info *cinfo, int index)
+{
+	int ret = 0;
+	struct mbox_client *cl = &cinfo->cl;
+	struct device_node *np = cl->dev->of_node;
+	union mhu_data tmp = {0};
+
+	if (index != 0 && index != 1) /* Tx = 0, Rx =1 */
+		return -EINVAL;
+
+	cl->rx_callback = mhu_rx_callback;
+	cl->tx_prepare = mhu_tx_prepare;
+
+	ret = of_property_read_u32_index(np, "mbox-data", index, &tmp.val);
+	if (ret)
+		return ret;
+
+	cinfo->chan = mbox_request_channel(cl, index);
+	if (IS_ERR(cinfo->chan))
+		ret = PTR_ERR(cinfo->chan);
+
+	cinfo->priv = tmp.ptr;
+
+	return ret;
+}
+
+static int mhu_mbox_send_message(struct scmi_chan_info *cinfo, void *msg)
+{
+	struct scmi_xfer *t = msg;
+
+	t->con_priv = cinfo->priv;
+
+	return mbox_send_message(cinfo->chan, msg);
+}
+
+static void mhu_mbox_client_txdone(struct scmi_chan_info *cinfo, int r)
+{
+	mbox_client_txdone(cinfo->chan, r);
+}
+
+static void mhu_mbox_free_channel(struct scmi_chan_info *cinfo)
+{
+	mbox_free_channel(cinfo->chan);
+}
+
+static struct scmi_mbox_ops arm_mhu_mbox_ops = {
+	.request_channel = mhu_mbox_request_channel,
+	.send_message = mhu_mbox_send_message,
+	.client_txdone = mhu_mbox_client_txdone,
+	.free_channel = mhu_mbox_free_channel,
+};
+
+const struct scmi_desc mhu_scmi_desc = {
+	.max_rx_timeout_ms = 30,
+	.max_msg = 20,
+	.max_msg_size = 128,
+	.mbox_ops = &arm_mhu_mbox_ops,
+};
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 97285a22dfaa..bdc9c566e6c1 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -648,6 +648,9 @@ EXPORT_SYMBOL_GPL(devm_scmi_handle_get);
 /* Each compatible listed below must have descriptor associated with it */
 static const struct of_device_id scmi_of_match[] = {
 	{ .compatible = "arm,scmi", .data = &scmi_generic_desc },
+#if IS_REACHABLE(CONFIG_ARM_MHU)
+	{ .compatible = "arm,mhu-scmi", .data = &mhu_scmi_desc },
+#endif
 	{ /* Sentinel */ },
 };
 
diff --git a/drivers/firmware/arm_scmi/mbox_if.h b/drivers/firmware/arm_scmi/mbox_if.h
index 02baa73e8613..a23fc6d7a91f 100644
--- a/drivers/firmware/arm_scmi/mbox_if.h
+++ b/drivers/firmware/arm_scmi/mbox_if.h
@@ -66,3 +66,6 @@ void scmi_generic_rx_callback(struct scmi_chan_info *cinfo);
 void scmi_generic_tx_prepare(struct scmi_chan_info *cinfo, void *m);
 
 extern const struct scmi_desc scmi_generic_desc;
+#if IS_REACHABLE(CONFIG_ARM_MHU)
+extern const struct scmi_desc mhu_scmi_desc;
+#endif
-- 
2.7.4

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

* [PATCH v3 17/22] firmware: arm_scmi: add device power domain support using genpd
  2017-09-28 13:11 ` Sudeep Holla
@ 2017-09-28 13:11   ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Kevin Hilman, Ulf Hansson

This patch hooks up the support for device power domain provided by
SCMI using the Linux generic power domain infrastructure.

Cc: Kevin Hilman <khilman@baylibre.com>
Cc: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/Kconfig                   |  13 +++
 drivers/firmware/arm_scmi/Makefile         |   1 +
 drivers/firmware/arm_scmi/scmi_pm_domain.c | 134 +++++++++++++++++++++++++++++
 3 files changed, 148 insertions(+)
 create mode 100644 drivers/firmware/arm_scmi/scmi_pm_domain.c

diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index c3d1a12763ce..a4462bc661c8 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -40,6 +40,19 @@ config ARM_SCMI_PROTOCOL
 	  This protocol library provides interface for all the client drivers
 	  making use of the features offered by the SCMI.
 
+config ARM_SCMI_POWER_DOMAIN
+	tristate "SCMI power domain driver"
+	depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
+	default y
+	select PM_GENERIC_DOMAINS if PM
+	help
+	  This enables support for the SCMI power domains which can be
+	  enabled or disabled via the SCP firmware
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called scmi_pm_domain. Note this may needed early in boot
+	  before rootfs may be available.
+
 config ARM_SCPI_PROTOCOL
 	tristate "ARM System Control and Power Interface (SCPI) Message Protocol"
 	depends on ARM || ARM64 || COMPILE_TEST
diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index 7fb026c71833..289e9e5a4764 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_ARM_SCMI_PROTOCOL)	= arm_scmi.o
 arm_scmi-y = base.o clock.o driver.o mbox_if.o perf.o power.o sensors.o
 arm_scmi-$(CONFIG_ARM_MHU) += arm_mhu_if.o
+obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
diff --git a/drivers/firmware/arm_scmi/scmi_pm_domain.c b/drivers/firmware/arm_scmi/scmi_pm_domain.c
new file mode 100644
index 000000000000..e53aa9d0af6e
--- /dev/null
+++ b/drivers/firmware/arm_scmi/scmi_pm_domain.c
@@ -0,0 +1,134 @@
+/*
+ * SCMI Generic power domain support.
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/pm_domain.h>
+#include <linux/scmi_protocol.h>
+
+struct scmi_pm_domain {
+	struct generic_pm_domain genpd;
+	const struct scmi_handle *handle;
+	const char *name;
+	u32 domain;
+};
+
+#define to_scmi_pd(gpd) container_of(gpd, struct scmi_pm_domain, genpd)
+
+static int scmi_pd_power(struct generic_pm_domain *domain, bool power_on)
+{
+	int ret;
+	u32 state, ret_state;
+	struct scmi_pm_domain *pd = to_scmi_pd(domain);
+	const struct scmi_power_ops *ops = pd->handle->power_ops;
+
+	if (power_on)
+		state = SCMI_POWER_STATE_GENERIC_ON;
+	else
+		state = SCMI_POWER_STATE_GENERIC_OFF;
+
+	ret = ops->state_set(pd->handle, pd->domain, state);
+	if (!ret)
+		ret = ops->state_get(pd->handle, pd->domain, &ret_state);
+	if (!ret && state != ret_state)
+		return -EIO;
+
+	return ret;
+}
+
+static int scmi_pd_power_on(struct generic_pm_domain *domain)
+{
+	return scmi_pd_power(domain, true);
+}
+
+static int scmi_pd_power_off(struct generic_pm_domain *domain)
+{
+	return scmi_pd_power(domain, false);
+}
+
+static int scmi_pm_domain_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct scmi_pm_domain *scmi_pd;
+	struct genpd_onecell_data *scmi_pd_data;
+	struct generic_pm_domain **domains;
+	int num_domains, i;
+	const struct scmi_handle *handle = devm_scmi_handle_get(dev);
+
+	if (IS_ERR_OR_NULL(handle) || !handle->power_ops)
+		return -EPROBE_DEFER;
+
+	num_domains = handle->power_ops->num_domains_get(handle);
+	if (num_domains < 0) {
+		dev_err(dev, "number of domains not found\n");
+		return num_domains;
+	}
+
+	scmi_pd = devm_kcalloc(dev, num_domains, sizeof(*scmi_pd), GFP_KERNEL);
+	if (!scmi_pd)
+		return -ENOMEM;
+
+	scmi_pd_data = devm_kzalloc(dev, sizeof(*scmi_pd_data), GFP_KERNEL);
+	if (!scmi_pd_data)
+		return -ENOMEM;
+
+	domains = devm_kcalloc(dev, num_domains, sizeof(*domains), GFP_KERNEL);
+	if (!domains)
+		return -ENOMEM;
+
+	for (i = 0; i < num_domains; i++, scmi_pd++) {
+		domains[i] = &scmi_pd->genpd;
+
+		scmi_pd->domain = i;
+		scmi_pd->handle = handle;
+		scmi_pd->name = handle->power_ops->name_get(handle, i);
+		scmi_pd->genpd.name = scmi_pd->name;
+		scmi_pd->genpd.power_off = scmi_pd_power_off;
+		scmi_pd->genpd.power_on = scmi_pd_power_on;
+
+		/*
+		 * Treat all power domains as off at boot.
+		 *
+		 * The SCP firmware itself may have switched on some domains,
+		 * but for reference counting purpose, keep it this way.
+		 */
+		pm_genpd_init(&scmi_pd->genpd, NULL, true);
+	}
+
+	scmi_pd_data->domains = domains;
+	scmi_pd_data->num_domains = num_domains;
+
+	of_genpd_add_provider_onecell(np, scmi_pd_data);
+
+	return 0;
+}
+
+static struct platform_driver scmi_power_domain_driver = {
+	.driver	= {
+		.name = "scmi-power-domain",
+	},
+	.probe = scmi_pm_domain_probe,
+};
+module_platform_driver(scmi_power_domain_driver);
+
+MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
+MODULE_DESCRIPTION("ARM SCMI power domain driver");
+MODULE_LICENSE("GPL v2");
-- 
2.7.4

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

* [PATCH v3 17/22] firmware: arm_scmi: add device power domain support using genpd
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

This patch hooks up the support for device power domain provided by
SCMI using the Linux generic power domain infrastructure.

Cc: Kevin Hilman <khilman@baylibre.com>
Cc: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/Kconfig                   |  13 +++
 drivers/firmware/arm_scmi/Makefile         |   1 +
 drivers/firmware/arm_scmi/scmi_pm_domain.c | 134 +++++++++++++++++++++++++++++
 3 files changed, 148 insertions(+)
 create mode 100644 drivers/firmware/arm_scmi/scmi_pm_domain.c

diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index c3d1a12763ce..a4462bc661c8 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -40,6 +40,19 @@ config ARM_SCMI_PROTOCOL
 	  This protocol library provides interface for all the client drivers
 	  making use of the features offered by the SCMI.
 
+config ARM_SCMI_POWER_DOMAIN
+	tristate "SCMI power domain driver"
+	depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
+	default y
+	select PM_GENERIC_DOMAINS if PM
+	help
+	  This enables support for the SCMI power domains which can be
+	  enabled or disabled via the SCP firmware
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called scmi_pm_domain. Note this may needed early in boot
+	  before rootfs may be available.
+
 config ARM_SCPI_PROTOCOL
 	tristate "ARM System Control and Power Interface (SCPI) Message Protocol"
 	depends on ARM || ARM64 || COMPILE_TEST
diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index 7fb026c71833..289e9e5a4764 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_ARM_SCMI_PROTOCOL)	= arm_scmi.o
 arm_scmi-y = base.o clock.o driver.o mbox_if.o perf.o power.o sensors.o
 arm_scmi-$(CONFIG_ARM_MHU) += arm_mhu_if.o
+obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
diff --git a/drivers/firmware/arm_scmi/scmi_pm_domain.c b/drivers/firmware/arm_scmi/scmi_pm_domain.c
new file mode 100644
index 000000000000..e53aa9d0af6e
--- /dev/null
+++ b/drivers/firmware/arm_scmi/scmi_pm_domain.c
@@ -0,0 +1,134 @@
+/*
+ * SCMI Generic power domain support.
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/pm_domain.h>
+#include <linux/scmi_protocol.h>
+
+struct scmi_pm_domain {
+	struct generic_pm_domain genpd;
+	const struct scmi_handle *handle;
+	const char *name;
+	u32 domain;
+};
+
+#define to_scmi_pd(gpd) container_of(gpd, struct scmi_pm_domain, genpd)
+
+static int scmi_pd_power(struct generic_pm_domain *domain, bool power_on)
+{
+	int ret;
+	u32 state, ret_state;
+	struct scmi_pm_domain *pd = to_scmi_pd(domain);
+	const struct scmi_power_ops *ops = pd->handle->power_ops;
+
+	if (power_on)
+		state = SCMI_POWER_STATE_GENERIC_ON;
+	else
+		state = SCMI_POWER_STATE_GENERIC_OFF;
+
+	ret = ops->state_set(pd->handle, pd->domain, state);
+	if (!ret)
+		ret = ops->state_get(pd->handle, pd->domain, &ret_state);
+	if (!ret && state != ret_state)
+		return -EIO;
+
+	return ret;
+}
+
+static int scmi_pd_power_on(struct generic_pm_domain *domain)
+{
+	return scmi_pd_power(domain, true);
+}
+
+static int scmi_pd_power_off(struct generic_pm_domain *domain)
+{
+	return scmi_pd_power(domain, false);
+}
+
+static int scmi_pm_domain_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct scmi_pm_domain *scmi_pd;
+	struct genpd_onecell_data *scmi_pd_data;
+	struct generic_pm_domain **domains;
+	int num_domains, i;
+	const struct scmi_handle *handle = devm_scmi_handle_get(dev);
+
+	if (IS_ERR_OR_NULL(handle) || !handle->power_ops)
+		return -EPROBE_DEFER;
+
+	num_domains = handle->power_ops->num_domains_get(handle);
+	if (num_domains < 0) {
+		dev_err(dev, "number of domains not found\n");
+		return num_domains;
+	}
+
+	scmi_pd = devm_kcalloc(dev, num_domains, sizeof(*scmi_pd), GFP_KERNEL);
+	if (!scmi_pd)
+		return -ENOMEM;
+
+	scmi_pd_data = devm_kzalloc(dev, sizeof(*scmi_pd_data), GFP_KERNEL);
+	if (!scmi_pd_data)
+		return -ENOMEM;
+
+	domains = devm_kcalloc(dev, num_domains, sizeof(*domains), GFP_KERNEL);
+	if (!domains)
+		return -ENOMEM;
+
+	for (i = 0; i < num_domains; i++, scmi_pd++) {
+		domains[i] = &scmi_pd->genpd;
+
+		scmi_pd->domain = i;
+		scmi_pd->handle = handle;
+		scmi_pd->name = handle->power_ops->name_get(handle, i);
+		scmi_pd->genpd.name = scmi_pd->name;
+		scmi_pd->genpd.power_off = scmi_pd_power_off;
+		scmi_pd->genpd.power_on = scmi_pd_power_on;
+
+		/*
+		 * Treat all power domains as off at boot.
+		 *
+		 * The SCP firmware itself may have switched on some domains,
+		 * but for reference counting purpose, keep it this way.
+		 */
+		pm_genpd_init(&scmi_pd->genpd, NULL, true);
+	}
+
+	scmi_pd_data->domains = domains;
+	scmi_pd_data->num_domains = num_domains;
+
+	of_genpd_add_provider_onecell(np, scmi_pd_data);
+
+	return 0;
+}
+
+static struct platform_driver scmi_power_domain_driver = {
+	.driver	= {
+		.name = "scmi-power-domain",
+	},
+	.probe = scmi_pm_domain_probe,
+};
+module_platform_driver(scmi_power_domain_driver);
+
+MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
+MODULE_DESCRIPTION("ARM SCMI power domain driver");
+MODULE_LICENSE("GPL v2");
-- 
2.7.4

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

* [PATCH v3 18/22] clk: add support for clocks provided by SCMI
  2017-09-28 13:11 ` Sudeep Holla
@ 2017-09-28 13:11   ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Michael Turquette, Stephen Boyd, linux-clk

On some ARM based systems, a separate Cortex-M based System Control
Processor(SCP) provides the overall power, clock, reset and system
control. System Control and Management Interface(SCMI) Message Protocol
is defined for the communication between the Application Cores(AP)
and the SCP.

This patch adds support for the clocks provided by SCP using SCMI
protocol.

Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Stephen Boyd <sboyd@codeaurora.org>
Cc: linux-clk@vger.kernel.org
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 MAINTAINERS            |   2 +-
 drivers/clk/Kconfig    |  10 +++
 drivers/clk/Makefile   |   1 +
 drivers/clk/clk-scmi.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 222 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/clk-scmi.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 23ec3471f542..32c184391aee 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12941,7 +12941,7 @@ M:	Sudeep Holla <sudeep.holla@arm.com>
 L:	linux-arm-kernel@lists.infradead.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/arm/arm,sc[mp]i.txt
-F:	drivers/clk/clk-scpi.c
+F:	drivers/clk/clk-sc[mp]i.c
 F:	drivers/cpufreq/scpi-cpufreq.c
 F:	drivers/firmware/arm_scpi.c
 F:	drivers/firmware/arm_scmi/
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 1c4e1aa6767e..57c66b22eab8 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -62,6 +62,16 @@ config COMMON_CLK_HI655X
 	  multi-function device has one fixed-rate oscillator, clocked
 	  at 32KHz.
 
+config COMMON_CLK_SCMI
+	tristate "Clock driver controlled via SCMI interface"
+	depends on ARM_SCMI_PROTOCOL || COMPILE_TEST
+	  ---help---
+	  This driver provides support for clocks that are controlled
+	  by firmware that implements the SCMI interface.
+
+	  This driver uses SCMI Message Protocol to interact with the
+	  firmware providing all the clock controls.
+
 config COMMON_CLK_SCPI
 	tristate "Clock driver controlled via SCPI interface"
 	depends on ARM_SCPI_PROTOCOL || COMPILE_TEST
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index c99f363826f0..46ad2f2b686a 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_CLK_QORIQ)			+= clk-qoriq.o
 obj-$(CONFIG_COMMON_CLK_RK808)		+= clk-rk808.o
 obj-$(CONFIG_COMMON_CLK_HI655X)		+= clk-hi655x.o
 obj-$(CONFIG_COMMON_CLK_S2MPS11)	+= clk-s2mps11.o
+obj-$(CONFIG_COMMON_CLK_SCMI)           += clk-scmi.o
 obj-$(CONFIG_COMMON_CLK_SCPI)           += clk-scpi.o
 obj-$(CONFIG_COMMON_CLK_SI5351)		+= clk-si5351.o
 obj-$(CONFIG_COMMON_CLK_SI514)		+= clk-si514.o
diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c
new file mode 100644
index 000000000000..bd546a9cdf37
--- /dev/null
+++ b/drivers/clk/clk-scmi.c
@@ -0,0 +1,210 @@
+/*
+ * System Control and Power Interface (SCMI) Protocol based clock driver
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/scmi_protocol.h>
+#include <asm/div64.h>
+
+struct scmi_clk {
+	u32 id;
+	struct clk_hw hw;
+	const struct scmi_clock_info *info;
+	const struct scmi_handle *handle;
+};
+
+#define to_scmi_clk(clk) container_of(clk, struct scmi_clk, hw)
+
+static unsigned long scmi_clk_recalc_rate(struct clk_hw *hw,
+					  unsigned long parent_rate)
+{
+	int ret;
+	u64 rate;
+	struct scmi_clk *clk = to_scmi_clk(hw);
+
+	ret = clk->handle->clk_ops->rate_get(clk->handle, clk->id, &rate);
+	if (ret)
+		return 0;
+	return rate;
+}
+
+static long scmi_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *parent_rate)
+{
+	int step;
+	u64 fmin, fmax, ftmp;
+	struct scmi_clk *clk = to_scmi_clk(hw);
+
+	/*
+	 * We can't figure out what rate it will be, so just return the
+	 * rate back to the caller. scmi_clk_recalc_rate() will be called
+	 * after the rate is set and we'll know what rate the clock is
+	 * running at then.
+	 */
+	if (clk->info->rate_discrete)
+		return rate;
+
+	fmin = clk->info->range.min_rate;
+	fmax = clk->info->range.max_rate;
+	if (rate <= fmin)
+		return fmin;
+	else if (rate >= fmax)
+		return fmax;
+
+	ftmp = rate - fmin;
+	ftmp += clk->info->range.step_size - 1; /* to round up */
+	step = do_div(ftmp, clk->info->range.step_size);
+
+	return step * clk->info->range.step_size + fmin;
+}
+
+static int scmi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+			     unsigned long parent_rate)
+{
+	struct scmi_clk *clk = to_scmi_clk(hw);
+
+	return clk->handle->clk_ops->rate_set(clk->handle, clk->id, 0, rate);
+}
+
+static int scmi_clk_enable(struct clk_hw *hw)
+{
+	struct scmi_clk *clk = to_scmi_clk(hw);
+
+	return clk->handle->clk_ops->enable(clk->handle, clk->id);
+}
+
+static void scmi_clk_disable(struct clk_hw *hw)
+{
+	struct scmi_clk *clk = to_scmi_clk(hw);
+
+	clk->handle->clk_ops->disable(clk->handle, clk->id);
+}
+
+static const struct clk_ops scmi_clk_ops = {
+	.recalc_rate = scmi_clk_recalc_rate,
+	.round_rate = scmi_clk_round_rate,
+	.set_rate = scmi_clk_set_rate,
+	/*
+	 * We can't provide enable/disable callback as we can't perform the same
+	 * in atomic context. Since the clock framework provides standard API
+	 * clk_prepare_enable that helps cases using clk_enable in non-atomic
+	 * context, it should be fine providing prepare/unprepare.
+	 */
+	.prepare = scmi_clk_enable,
+	.unprepare = scmi_clk_disable,
+};
+
+static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk)
+{
+	int ret;
+	struct clk_init_data init = {
+		.flags = CLK_GET_RATE_NOCACHE,
+		.num_parents = 0,
+		.ops = &scmi_clk_ops,
+		.name = sclk->info->name,
+	};
+
+	sclk->hw.init = &init;
+	ret = devm_clk_hw_register(dev, &sclk->hw);
+	if (!ret)
+		clk_hw_set_rate_range(&sclk->hw, sclk->info->range.min_rate,
+				      sclk->info->range.max_rate);
+	return ret;
+}
+
+static int scmi_clocks_probe(struct platform_device *pdev)
+{
+	int idx, count, err;
+	struct clk_hw **hws;
+	struct clk_hw_onecell_data *clk_data;
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	const struct scmi_handle *handle = devm_scmi_handle_get(dev);
+
+	if (IS_ERR_OR_NULL(handle) || !handle->clk_ops)
+		return -EPROBE_DEFER;
+
+	count = handle->clk_ops->count_get(handle);
+	if (count < 0) {
+		dev_err(dev, "%s: invalid clock output count\n", np->name);
+		return -EINVAL;
+	}
+
+	clk_data = devm_kzalloc(dev, sizeof(*clk_data) +
+				sizeof(*clk_data->hws) * count, GFP_KERNEL);
+	if (!clk_data)
+		return -ENOMEM;
+
+	clk_data->num = count;
+	hws = clk_data->hws;
+
+	for (idx = 0; idx < count; idx++) {
+		struct scmi_clk *sclk;
+
+		sclk = devm_kzalloc(dev, sizeof(*sclk), GFP_KERNEL);
+		if (!sclk)
+			return -ENOMEM;
+
+		sclk->info = handle->clk_ops->info_get(handle, idx);
+		if (!sclk->info) {
+			dev_dbg(dev, "invalid clock info for idx %d\n", idx);
+			continue;
+		}
+
+		sclk->id = idx;
+		sclk->handle = handle;
+
+		err = scmi_clk_ops_init(dev, sclk);
+		if (err) {
+			dev_err(dev, "failed to register clock %d\n", idx);
+			devm_kfree(dev, sclk);
+			hws[idx] = NULL;
+		} else {
+			dev_dbg(dev, "Registered clock:%s\n", sclk->info->name);
+			hws[idx] = &sclk->hw;
+		}
+	}
+
+	return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
+}
+
+static int scmi_clocks_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+
+	of_clk_del_provider(np);
+	return 0;
+}
+
+static struct platform_driver scmi_clocks_driver = {
+	.driver	= {
+		.name = "scmi-clocks",
+	},
+	.probe = scmi_clocks_probe,
+	.remove = scmi_clocks_remove,
+};
+module_platform_driver(scmi_clocks_driver);
+
+MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
+MODULE_DESCRIPTION("ARM SCMI clock driver");
+MODULE_LICENSE("GPL v2");
-- 
2.7.4

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

* [PATCH v3 18/22] clk: add support for clocks provided by SCMI
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

On some ARM based systems, a separate Cortex-M based System Control
Processor(SCP) provides the overall power, clock, reset and system
control. System Control and Management Interface(SCMI) Message Protocol
is defined for the communication between the Application Cores(AP)
and the SCP.

This patch adds support for the clocks provided by SCP using SCMI
protocol.

Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Stephen Boyd <sboyd@codeaurora.org>
Cc: linux-clk at vger.kernel.org
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 MAINTAINERS            |   2 +-
 drivers/clk/Kconfig    |  10 +++
 drivers/clk/Makefile   |   1 +
 drivers/clk/clk-scmi.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 222 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/clk-scmi.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 23ec3471f542..32c184391aee 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12941,7 +12941,7 @@ M:	Sudeep Holla <sudeep.holla@arm.com>
 L:	linux-arm-kernel at lists.infradead.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/arm/arm,sc[mp]i.txt
-F:	drivers/clk/clk-scpi.c
+F:	drivers/clk/clk-sc[mp]i.c
 F:	drivers/cpufreq/scpi-cpufreq.c
 F:	drivers/firmware/arm_scpi.c
 F:	drivers/firmware/arm_scmi/
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 1c4e1aa6767e..57c66b22eab8 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -62,6 +62,16 @@ config COMMON_CLK_HI655X
 	  multi-function device has one fixed-rate oscillator, clocked
 	  at 32KHz.
 
+config COMMON_CLK_SCMI
+	tristate "Clock driver controlled via SCMI interface"
+	depends on ARM_SCMI_PROTOCOL || COMPILE_TEST
+	  ---help---
+	  This driver provides support for clocks that are controlled
+	  by firmware that implements the SCMI interface.
+
+	  This driver uses SCMI Message Protocol to interact with the
+	  firmware providing all the clock controls.
+
 config COMMON_CLK_SCPI
 	tristate "Clock driver controlled via SCPI interface"
 	depends on ARM_SCPI_PROTOCOL || COMPILE_TEST
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index c99f363826f0..46ad2f2b686a 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_CLK_QORIQ)			+= clk-qoriq.o
 obj-$(CONFIG_COMMON_CLK_RK808)		+= clk-rk808.o
 obj-$(CONFIG_COMMON_CLK_HI655X)		+= clk-hi655x.o
 obj-$(CONFIG_COMMON_CLK_S2MPS11)	+= clk-s2mps11.o
+obj-$(CONFIG_COMMON_CLK_SCMI)           += clk-scmi.o
 obj-$(CONFIG_COMMON_CLK_SCPI)           += clk-scpi.o
 obj-$(CONFIG_COMMON_CLK_SI5351)		+= clk-si5351.o
 obj-$(CONFIG_COMMON_CLK_SI514)		+= clk-si514.o
diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c
new file mode 100644
index 000000000000..bd546a9cdf37
--- /dev/null
+++ b/drivers/clk/clk-scmi.c
@@ -0,0 +1,210 @@
+/*
+ * System Control and Power Interface (SCMI) Protocol based clock driver
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/scmi_protocol.h>
+#include <asm/div64.h>
+
+struct scmi_clk {
+	u32 id;
+	struct clk_hw hw;
+	const struct scmi_clock_info *info;
+	const struct scmi_handle *handle;
+};
+
+#define to_scmi_clk(clk) container_of(clk, struct scmi_clk, hw)
+
+static unsigned long scmi_clk_recalc_rate(struct clk_hw *hw,
+					  unsigned long parent_rate)
+{
+	int ret;
+	u64 rate;
+	struct scmi_clk *clk = to_scmi_clk(hw);
+
+	ret = clk->handle->clk_ops->rate_get(clk->handle, clk->id, &rate);
+	if (ret)
+		return 0;
+	return rate;
+}
+
+static long scmi_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *parent_rate)
+{
+	int step;
+	u64 fmin, fmax, ftmp;
+	struct scmi_clk *clk = to_scmi_clk(hw);
+
+	/*
+	 * We can't figure out what rate it will be, so just return the
+	 * rate back to the caller. scmi_clk_recalc_rate() will be called
+	 * after the rate is set and we'll know what rate the clock is
+	 * running at then.
+	 */
+	if (clk->info->rate_discrete)
+		return rate;
+
+	fmin = clk->info->range.min_rate;
+	fmax = clk->info->range.max_rate;
+	if (rate <= fmin)
+		return fmin;
+	else if (rate >= fmax)
+		return fmax;
+
+	ftmp = rate - fmin;
+	ftmp += clk->info->range.step_size - 1; /* to round up */
+	step = do_div(ftmp, clk->info->range.step_size);
+
+	return step * clk->info->range.step_size + fmin;
+}
+
+static int scmi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+			     unsigned long parent_rate)
+{
+	struct scmi_clk *clk = to_scmi_clk(hw);
+
+	return clk->handle->clk_ops->rate_set(clk->handle, clk->id, 0, rate);
+}
+
+static int scmi_clk_enable(struct clk_hw *hw)
+{
+	struct scmi_clk *clk = to_scmi_clk(hw);
+
+	return clk->handle->clk_ops->enable(clk->handle, clk->id);
+}
+
+static void scmi_clk_disable(struct clk_hw *hw)
+{
+	struct scmi_clk *clk = to_scmi_clk(hw);
+
+	clk->handle->clk_ops->disable(clk->handle, clk->id);
+}
+
+static const struct clk_ops scmi_clk_ops = {
+	.recalc_rate = scmi_clk_recalc_rate,
+	.round_rate = scmi_clk_round_rate,
+	.set_rate = scmi_clk_set_rate,
+	/*
+	 * We can't provide enable/disable callback as we can't perform the same
+	 * in atomic context. Since the clock framework provides standard API
+	 * clk_prepare_enable that helps cases using clk_enable in non-atomic
+	 * context, it should be fine providing prepare/unprepare.
+	 */
+	.prepare = scmi_clk_enable,
+	.unprepare = scmi_clk_disable,
+};
+
+static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk)
+{
+	int ret;
+	struct clk_init_data init = {
+		.flags = CLK_GET_RATE_NOCACHE,
+		.num_parents = 0,
+		.ops = &scmi_clk_ops,
+		.name = sclk->info->name,
+	};
+
+	sclk->hw.init = &init;
+	ret = devm_clk_hw_register(dev, &sclk->hw);
+	if (!ret)
+		clk_hw_set_rate_range(&sclk->hw, sclk->info->range.min_rate,
+				      sclk->info->range.max_rate);
+	return ret;
+}
+
+static int scmi_clocks_probe(struct platform_device *pdev)
+{
+	int idx, count, err;
+	struct clk_hw **hws;
+	struct clk_hw_onecell_data *clk_data;
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	const struct scmi_handle *handle = devm_scmi_handle_get(dev);
+
+	if (IS_ERR_OR_NULL(handle) || !handle->clk_ops)
+		return -EPROBE_DEFER;
+
+	count = handle->clk_ops->count_get(handle);
+	if (count < 0) {
+		dev_err(dev, "%s: invalid clock output count\n", np->name);
+		return -EINVAL;
+	}
+
+	clk_data = devm_kzalloc(dev, sizeof(*clk_data) +
+				sizeof(*clk_data->hws) * count, GFP_KERNEL);
+	if (!clk_data)
+		return -ENOMEM;
+
+	clk_data->num = count;
+	hws = clk_data->hws;
+
+	for (idx = 0; idx < count; idx++) {
+		struct scmi_clk *sclk;
+
+		sclk = devm_kzalloc(dev, sizeof(*sclk), GFP_KERNEL);
+		if (!sclk)
+			return -ENOMEM;
+
+		sclk->info = handle->clk_ops->info_get(handle, idx);
+		if (!sclk->info) {
+			dev_dbg(dev, "invalid clock info for idx %d\n", idx);
+			continue;
+		}
+
+		sclk->id = idx;
+		sclk->handle = handle;
+
+		err = scmi_clk_ops_init(dev, sclk);
+		if (err) {
+			dev_err(dev, "failed to register clock %d\n", idx);
+			devm_kfree(dev, sclk);
+			hws[idx] = NULL;
+		} else {
+			dev_dbg(dev, "Registered clock:%s\n", sclk->info->name);
+			hws[idx] = &sclk->hw;
+		}
+	}
+
+	return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
+}
+
+static int scmi_clocks_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+
+	of_clk_del_provider(np);
+	return 0;
+}
+
+static struct platform_driver scmi_clocks_driver = {
+	.driver	= {
+		.name = "scmi-clocks",
+	},
+	.probe = scmi_clocks_probe,
+	.remove = scmi_clocks_remove,
+};
+module_platform_driver(scmi_clocks_driver);
+
+MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
+MODULE_DESCRIPTION("ARM SCMI clock driver");
+MODULE_LICENSE("GPL v2");
-- 
2.7.4

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

* [PATCH v3 19/22] hwmon: (core) Add hwmon_max to hwmon_sensor_types enumeration
  2017-09-28 13:11 ` Sudeep Holla
@ 2017-09-28 13:11   ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Guenter Roeck, linux-hwmon

It's useful to know the maximum types of sensor supported by hwmon
framework. It can be used to allocate some data structures when sorting
the monitors based on their type.

This will be used by scmi hwmon support.

Cc: Guenter Roeck <linux@roeck-us.net>
Cc: linux-hwmon@vger.kernel.org
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 include/linux/hwmon.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/hwmon.h b/include/linux/hwmon.h
index ceb751987c40..e5fd2707b6df 100644
--- a/include/linux/hwmon.h
+++ b/include/linux/hwmon.h
@@ -29,6 +29,7 @@ enum hwmon_sensor_types {
 	hwmon_humidity,
 	hwmon_fan,
 	hwmon_pwm,
+	hwmon_max,
 };
 
 enum hwmon_chip_attributes {
-- 
2.7.4

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

* [PATCH v3 19/22] hwmon: (core) Add hwmon_max to hwmon_sensor_types enumeration
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

It's useful to know the maximum types of sensor supported by hwmon
framework. It can be used to allocate some data structures when sorting
the monitors based on their type.

This will be used by scmi hwmon support.

Cc: Guenter Roeck <linux@roeck-us.net>
Cc: linux-hwmon at vger.kernel.org
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 include/linux/hwmon.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/hwmon.h b/include/linux/hwmon.h
index ceb751987c40..e5fd2707b6df 100644
--- a/include/linux/hwmon.h
+++ b/include/linux/hwmon.h
@@ -29,6 +29,7 @@ enum hwmon_sensor_types {
 	hwmon_humidity,
 	hwmon_fan,
 	hwmon_pwm,
+	hwmon_max,
 };
 
 enum hwmon_chip_attributes {
-- 
2.7.4

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

* [PATCH v3 20/22] hwmon: add support for sensors exported via ARM SCMI
  2017-09-28 13:11 ` Sudeep Holla
@ 2017-09-28 13:11   ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Guenter Roeck, linux-hwmon

Create a driver to add support for SoC sensors exported by the System
Control Processor (SCP) via the System Control and Management Interface
(SCMI). The supported sensor types is one of voltage, temperature,
current, and power.

The sensor labels and values provided by the SCP are exported via the
hwmon sysfs interface.

Cc: Guenter Roeck <linux@roeck-us.net>
Cc: linux-hwmon@vger.kernel.org
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/hwmon/Kconfig      |  12 +++
 drivers/hwmon/Makefile     |   1 +
 drivers/hwmon/scmi-hwmon.c | 235 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 248 insertions(+)
 create mode 100644 drivers/hwmon/scmi-hwmon.c

diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index d65431417b17..0b75e9a89463 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -321,6 +321,18 @@ config SENSORS_APPLESMC
 	  Say Y here if you have an applicable laptop and want to experience
 	  the awesome power of applesmc.
 
+config SENSORS_ARM_SCMI
+	tristate "ARM SCMI Sensors"
+	depends on ARM_SCMI_PROTOCOL
+	depends on THERMAL || !THERMAL_OF
+	help
+	  This driver provides support for temperature, voltage, current
+	  and power sensors available on SCMI based platforms. The actual
+	  number and type of sensors exported depend on the platform.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called scmi-hwmon.
+
 config SENSORS_ARM_SCPI
 	tristate "ARM SCPI Sensors"
 	depends on ARM_SCPI_PROTOCOL
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index c84d9784be98..a51c2dcef11c 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_SENSORS_ADT7462)	+= adt7462.o
 obj-$(CONFIG_SENSORS_ADT7470)	+= adt7470.o
 obj-$(CONFIG_SENSORS_ADT7475)	+= adt7475.o
 obj-$(CONFIG_SENSORS_APPLESMC)	+= applesmc.o
+obj-$(CONFIG_SENSORS_ARM_SCMI)	+= scmi-hwmon.o
 obj-$(CONFIG_SENSORS_ARM_SCPI)	+= scpi-hwmon.o
 obj-$(CONFIG_SENSORS_ASC7621)	+= asc7621.o
 obj-$(CONFIG_SENSORS_ASPEED)	+= aspeed-pwm-tacho.o
diff --git a/drivers/hwmon/scmi-hwmon.c b/drivers/hwmon/scmi-hwmon.c
new file mode 100644
index 000000000000..0a8c0e8dc5d1
--- /dev/null
+++ b/drivers/hwmon/scmi-hwmon.c
@@ -0,0 +1,235 @@
+/*
+ * System Control and Management Interface(SCMI) based hwmon sensor driver
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ * Sudeep Holla <sudeep.holla@arm.com>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/hwmon.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/scmi_protocol.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/thermal.h>
+
+struct scmi_sensors {
+	const struct scmi_handle *handle;
+	const struct scmi_sensor_info **info[hwmon_max];
+};
+
+static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
+			   u32 attr, int channel, long *val)
+{
+	int ret;
+	u64 value;
+	const struct scmi_sensor_info *sensor;
+	struct scmi_sensors *scmi_sensors = dev_get_drvdata(dev);
+	const struct scmi_handle *h = scmi_sensors->handle;
+
+	sensor = *(scmi_sensors->info[type] + channel);
+	ret = h->sensor_ops->reading_get(h, sensor->id, false, &value);
+	if (!ret)
+		*val = value;
+
+	return ret;
+}
+
+static int
+scmi_hwmon_read_string(struct device *dev, enum hwmon_sensor_types type,
+		       u32 attr, int channel, const char **str)
+{
+	const struct scmi_sensor_info *sensor;
+	struct scmi_sensors *scmi_sensors = dev_get_drvdata(dev);
+
+	sensor = *(scmi_sensors->info[type] + channel);
+	*str = sensor->name;
+
+	return 0;
+}
+
+static umode_t
+scmi_hwmon_is_visible(const void *drvdata, enum hwmon_sensor_types type,
+		      u32 attr, int channel)
+{
+	const struct scmi_sensor_info *sensor;
+	const struct scmi_sensors *scmi_sensors = drvdata;
+
+	sensor = *(scmi_sensors->info[type] + channel);
+	if (sensor && sensor->name)
+		return S_IRUGO;
+
+	return 0;
+}
+
+static const struct hwmon_ops scmi_hwmon_ops = {
+	.is_visible = scmi_hwmon_is_visible,
+	.read = scmi_hwmon_read,
+	.read_string = scmi_hwmon_read_string,
+};
+
+static struct hwmon_chip_info scmi_chip_info = {
+	.ops = &scmi_hwmon_ops,
+	.info = NULL,
+};
+
+static int scmi_hwmon_add_chan_info(struct hwmon_channel_info *scmi_hwmon_chan,
+				    struct device *dev, int num,
+				    enum hwmon_sensor_types type, u32 config)
+{
+	int i;
+	u32 *cfg = devm_kcalloc(dev, num + 1, sizeof(*cfg), GFP_KERNEL);
+
+	if (!cfg)
+		return -ENOMEM;
+
+	scmi_hwmon_chan->type = type;
+	scmi_hwmon_chan->config = cfg;
+	for (i = 0; i < num; i++, cfg++)
+		*cfg = config;
+
+	return 0;
+}
+
+static enum hwmon_sensor_types scmi_types[] = {
+	[TEMPERATURE_C] = hwmon_temp,
+	[VOLTAGE] = hwmon_in,
+	[CURRENT] = hwmon_curr,
+	[POWER] = hwmon_power,
+	[ENERGY] = hwmon_energy,
+};
+
+static u32 hwmon_attributes[] = {
+	[hwmon_chip] = HWMON_C_REGISTER_TZ,
+	[hwmon_temp] = HWMON_T_INPUT | HWMON_T_LABEL,
+	[hwmon_in] = HWMON_I_INPUT | HWMON_I_LABEL,
+	[hwmon_curr] = HWMON_C_INPUT | HWMON_C_LABEL,
+	[hwmon_power] = HWMON_P_INPUT | HWMON_P_LABEL,
+	[hwmon_energy] = HWMON_E_INPUT | HWMON_E_LABEL,
+};
+
+static int scmi_hwmon_probe(struct platform_device *pdev)
+{
+	int i, idx;
+	u16 nr_sensors;
+	enum hwmon_sensor_types type;
+	struct scmi_sensors *scmi_sensors;
+	const struct scmi_sensor_info *sensor;
+	int nr_count[hwmon_max] = {0}, nr_types = 0;
+	const struct hwmon_chip_info *chip_info;
+	struct device *hwdev, *dev = &pdev->dev;
+	struct hwmon_channel_info *scmi_hwmon_chan;
+	const struct hwmon_channel_info **ptr_scmi_ci;
+	const struct scmi_handle *handle = devm_scmi_handle_get(dev);
+
+	if (IS_ERR_OR_NULL(handle) || !handle->sensor_ops)
+		return -EPROBE_DEFER;
+
+	nr_sensors = handle->sensor_ops->count_get(handle);
+	if (!nr_sensors)
+		return -EIO;
+
+	scmi_sensors = devm_kzalloc(dev, sizeof(*scmi_sensors), GFP_KERNEL);
+	if (!scmi_sensors)
+		return -ENOMEM;
+
+	scmi_sensors->handle = handle;
+
+	for (i = 0; i < nr_sensors; i++) {
+		sensor = handle->sensor_ops->info_get(handle, i);
+		if (!sensor)
+			return PTR_ERR(sensor);
+
+		switch (sensor->type) {
+		case TEMPERATURE_C:
+		case VOLTAGE:
+		case CURRENT:
+		case POWER:
+		case ENERGY:
+			type = scmi_types[sensor->type];
+			if (!nr_count[type])
+				nr_types++;
+			nr_count[type]++;
+			break;
+		}
+	}
+
+	if (nr_count[hwmon_temp])
+		nr_count[hwmon_chip]++, nr_types++;
+
+	scmi_hwmon_chan = devm_kcalloc(dev, nr_types, sizeof(*scmi_hwmon_chan),
+				       GFP_KERNEL);
+	if (!scmi_hwmon_chan)
+		return -ENOMEM;
+
+	ptr_scmi_ci = devm_kcalloc(dev, nr_types + 1, sizeof(*ptr_scmi_ci),
+				   GFP_KERNEL);
+	if (!ptr_scmi_ci)
+		return -ENOMEM;
+
+	scmi_chip_info.info = ptr_scmi_ci;
+	chip_info = &scmi_chip_info;
+
+	for (type = 0; type < hwmon_max && nr_count[type]; type++) {
+		scmi_hwmon_add_chan_info(scmi_hwmon_chan, dev, nr_count[type],
+					 type, hwmon_attributes[type]);
+		*ptr_scmi_ci++ = scmi_hwmon_chan++;
+
+		scmi_sensors->info[type] =
+			devm_kcalloc(dev, nr_count[type],
+				     sizeof(*scmi_sensors->info), GFP_KERNEL);
+		if (!scmi_sensors->info[type])
+			return -ENOMEM;
+	}
+
+	*ptr_scmi_ci = NULL;
+	platform_set_drvdata(pdev, scmi_sensors);
+
+	for (i = nr_sensors - 1; i >= 0 ; i--) {
+		sensor = handle->sensor_ops->info_get(handle, i);
+		if (!sensor)
+			continue;
+
+		switch (sensor->type) {
+		case TEMPERATURE_C:
+		case VOLTAGE:
+		case CURRENT:
+		case POWER:
+		case ENERGY:
+			type = scmi_types[sensor->type];
+			idx = --nr_count[type];
+			*(scmi_sensors->info[type] + idx) = sensor;
+			break;
+		}
+	}
+
+	hwdev = devm_hwmon_device_register_with_info(dev, "scmi_sensors",
+						     scmi_sensors, chip_info,
+						     NULL);
+
+	if (IS_ERR(hwdev))
+		return PTR_ERR(hwdev);
+
+	return 0;
+}
+
+static struct platform_driver scmi_hwmon_platdrv = {
+	.driver = {
+		.name	= "scmi-hwmon",
+	},
+	.probe		= scmi_hwmon_probe,
+};
+module_platform_driver(scmi_hwmon_platdrv);
+
+MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
+MODULE_DESCRIPTION("ARM SCMI HWMON interface driver");
+MODULE_LICENSE("GPL v2");
-- 
2.7.4

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

* [PATCH v3 20/22] hwmon: add support for sensors exported via ARM SCMI
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

Create a driver to add support for SoC sensors exported by the System
Control Processor (SCP) via the System Control and Management Interface
(SCMI). The supported sensor types is one of voltage, temperature,
current, and power.

The sensor labels and values provided by the SCP are exported via the
hwmon sysfs interface.

Cc: Guenter Roeck <linux@roeck-us.net>
Cc: linux-hwmon at vger.kernel.org
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/hwmon/Kconfig      |  12 +++
 drivers/hwmon/Makefile     |   1 +
 drivers/hwmon/scmi-hwmon.c | 235 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 248 insertions(+)
 create mode 100644 drivers/hwmon/scmi-hwmon.c

diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index d65431417b17..0b75e9a89463 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -321,6 +321,18 @@ config SENSORS_APPLESMC
 	  Say Y here if you have an applicable laptop and want to experience
 	  the awesome power of applesmc.
 
+config SENSORS_ARM_SCMI
+	tristate "ARM SCMI Sensors"
+	depends on ARM_SCMI_PROTOCOL
+	depends on THERMAL || !THERMAL_OF
+	help
+	  This driver provides support for temperature, voltage, current
+	  and power sensors available on SCMI based platforms. The actual
+	  number and type of sensors exported depend on the platform.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called scmi-hwmon.
+
 config SENSORS_ARM_SCPI
 	tristate "ARM SCPI Sensors"
 	depends on ARM_SCPI_PROTOCOL
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index c84d9784be98..a51c2dcef11c 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_SENSORS_ADT7462)	+= adt7462.o
 obj-$(CONFIG_SENSORS_ADT7470)	+= adt7470.o
 obj-$(CONFIG_SENSORS_ADT7475)	+= adt7475.o
 obj-$(CONFIG_SENSORS_APPLESMC)	+= applesmc.o
+obj-$(CONFIG_SENSORS_ARM_SCMI)	+= scmi-hwmon.o
 obj-$(CONFIG_SENSORS_ARM_SCPI)	+= scpi-hwmon.o
 obj-$(CONFIG_SENSORS_ASC7621)	+= asc7621.o
 obj-$(CONFIG_SENSORS_ASPEED)	+= aspeed-pwm-tacho.o
diff --git a/drivers/hwmon/scmi-hwmon.c b/drivers/hwmon/scmi-hwmon.c
new file mode 100644
index 000000000000..0a8c0e8dc5d1
--- /dev/null
+++ b/drivers/hwmon/scmi-hwmon.c
@@ -0,0 +1,235 @@
+/*
+ * System Control and Management Interface(SCMI) based hwmon sensor driver
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ * Sudeep Holla <sudeep.holla@arm.com>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/hwmon.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/scmi_protocol.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/thermal.h>
+
+struct scmi_sensors {
+	const struct scmi_handle *handle;
+	const struct scmi_sensor_info **info[hwmon_max];
+};
+
+static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
+			   u32 attr, int channel, long *val)
+{
+	int ret;
+	u64 value;
+	const struct scmi_sensor_info *sensor;
+	struct scmi_sensors *scmi_sensors = dev_get_drvdata(dev);
+	const struct scmi_handle *h = scmi_sensors->handle;
+
+	sensor = *(scmi_sensors->info[type] + channel);
+	ret = h->sensor_ops->reading_get(h, sensor->id, false, &value);
+	if (!ret)
+		*val = value;
+
+	return ret;
+}
+
+static int
+scmi_hwmon_read_string(struct device *dev, enum hwmon_sensor_types type,
+		       u32 attr, int channel, const char **str)
+{
+	const struct scmi_sensor_info *sensor;
+	struct scmi_sensors *scmi_sensors = dev_get_drvdata(dev);
+
+	sensor = *(scmi_sensors->info[type] + channel);
+	*str = sensor->name;
+
+	return 0;
+}
+
+static umode_t
+scmi_hwmon_is_visible(const void *drvdata, enum hwmon_sensor_types type,
+		      u32 attr, int channel)
+{
+	const struct scmi_sensor_info *sensor;
+	const struct scmi_sensors *scmi_sensors = drvdata;
+
+	sensor = *(scmi_sensors->info[type] + channel);
+	if (sensor && sensor->name)
+		return S_IRUGO;
+
+	return 0;
+}
+
+static const struct hwmon_ops scmi_hwmon_ops = {
+	.is_visible = scmi_hwmon_is_visible,
+	.read = scmi_hwmon_read,
+	.read_string = scmi_hwmon_read_string,
+};
+
+static struct hwmon_chip_info scmi_chip_info = {
+	.ops = &scmi_hwmon_ops,
+	.info = NULL,
+};
+
+static int scmi_hwmon_add_chan_info(struct hwmon_channel_info *scmi_hwmon_chan,
+				    struct device *dev, int num,
+				    enum hwmon_sensor_types type, u32 config)
+{
+	int i;
+	u32 *cfg = devm_kcalloc(dev, num + 1, sizeof(*cfg), GFP_KERNEL);
+
+	if (!cfg)
+		return -ENOMEM;
+
+	scmi_hwmon_chan->type = type;
+	scmi_hwmon_chan->config = cfg;
+	for (i = 0; i < num; i++, cfg++)
+		*cfg = config;
+
+	return 0;
+}
+
+static enum hwmon_sensor_types scmi_types[] = {
+	[TEMPERATURE_C] = hwmon_temp,
+	[VOLTAGE] = hwmon_in,
+	[CURRENT] = hwmon_curr,
+	[POWER] = hwmon_power,
+	[ENERGY] = hwmon_energy,
+};
+
+static u32 hwmon_attributes[] = {
+	[hwmon_chip] = HWMON_C_REGISTER_TZ,
+	[hwmon_temp] = HWMON_T_INPUT | HWMON_T_LABEL,
+	[hwmon_in] = HWMON_I_INPUT | HWMON_I_LABEL,
+	[hwmon_curr] = HWMON_C_INPUT | HWMON_C_LABEL,
+	[hwmon_power] = HWMON_P_INPUT | HWMON_P_LABEL,
+	[hwmon_energy] = HWMON_E_INPUT | HWMON_E_LABEL,
+};
+
+static int scmi_hwmon_probe(struct platform_device *pdev)
+{
+	int i, idx;
+	u16 nr_sensors;
+	enum hwmon_sensor_types type;
+	struct scmi_sensors *scmi_sensors;
+	const struct scmi_sensor_info *sensor;
+	int nr_count[hwmon_max] = {0}, nr_types = 0;
+	const struct hwmon_chip_info *chip_info;
+	struct device *hwdev, *dev = &pdev->dev;
+	struct hwmon_channel_info *scmi_hwmon_chan;
+	const struct hwmon_channel_info **ptr_scmi_ci;
+	const struct scmi_handle *handle = devm_scmi_handle_get(dev);
+
+	if (IS_ERR_OR_NULL(handle) || !handle->sensor_ops)
+		return -EPROBE_DEFER;
+
+	nr_sensors = handle->sensor_ops->count_get(handle);
+	if (!nr_sensors)
+		return -EIO;
+
+	scmi_sensors = devm_kzalloc(dev, sizeof(*scmi_sensors), GFP_KERNEL);
+	if (!scmi_sensors)
+		return -ENOMEM;
+
+	scmi_sensors->handle = handle;
+
+	for (i = 0; i < nr_sensors; i++) {
+		sensor = handle->sensor_ops->info_get(handle, i);
+		if (!sensor)
+			return PTR_ERR(sensor);
+
+		switch (sensor->type) {
+		case TEMPERATURE_C:
+		case VOLTAGE:
+		case CURRENT:
+		case POWER:
+		case ENERGY:
+			type = scmi_types[sensor->type];
+			if (!nr_count[type])
+				nr_types++;
+			nr_count[type]++;
+			break;
+		}
+	}
+
+	if (nr_count[hwmon_temp])
+		nr_count[hwmon_chip]++, nr_types++;
+
+	scmi_hwmon_chan = devm_kcalloc(dev, nr_types, sizeof(*scmi_hwmon_chan),
+				       GFP_KERNEL);
+	if (!scmi_hwmon_chan)
+		return -ENOMEM;
+
+	ptr_scmi_ci = devm_kcalloc(dev, nr_types + 1, sizeof(*ptr_scmi_ci),
+				   GFP_KERNEL);
+	if (!ptr_scmi_ci)
+		return -ENOMEM;
+
+	scmi_chip_info.info = ptr_scmi_ci;
+	chip_info = &scmi_chip_info;
+
+	for (type = 0; type < hwmon_max && nr_count[type]; type++) {
+		scmi_hwmon_add_chan_info(scmi_hwmon_chan, dev, nr_count[type],
+					 type, hwmon_attributes[type]);
+		*ptr_scmi_ci++ = scmi_hwmon_chan++;
+
+		scmi_sensors->info[type] =
+			devm_kcalloc(dev, nr_count[type],
+				     sizeof(*scmi_sensors->info), GFP_KERNEL);
+		if (!scmi_sensors->info[type])
+			return -ENOMEM;
+	}
+
+	*ptr_scmi_ci = NULL;
+	platform_set_drvdata(pdev, scmi_sensors);
+
+	for (i = nr_sensors - 1; i >= 0 ; i--) {
+		sensor = handle->sensor_ops->info_get(handle, i);
+		if (!sensor)
+			continue;
+
+		switch (sensor->type) {
+		case TEMPERATURE_C:
+		case VOLTAGE:
+		case CURRENT:
+		case POWER:
+		case ENERGY:
+			type = scmi_types[sensor->type];
+			idx = --nr_count[type];
+			*(scmi_sensors->info[type] + idx) = sensor;
+			break;
+		}
+	}
+
+	hwdev = devm_hwmon_device_register_with_info(dev, "scmi_sensors",
+						     scmi_sensors, chip_info,
+						     NULL);
+
+	if (IS_ERR(hwdev))
+		return PTR_ERR(hwdev);
+
+	return 0;
+}
+
+static struct platform_driver scmi_hwmon_platdrv = {
+	.driver = {
+		.name	= "scmi-hwmon",
+	},
+	.probe		= scmi_hwmon_probe,
+};
+module_platform_driver(scmi_hwmon_platdrv);
+
+MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
+MODULE_DESCRIPTION("ARM SCMI HWMON interface driver");
+MODULE_LICENSE("GPL v2");
-- 
2.7.4

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

* [PATCH v3 21/22] cpufreq: add support for CPU DVFS based on SCMI message protocol
  2017-09-28 13:11 ` Sudeep Holla
@ 2017-09-28 13:11   ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Rafael J. Wysocki, Viresh Kumar, linux-pm

On some ARM based systems, a separate Cortex-M based System Control
Processor(SCP) provides the overall power, clock, reset and system
control including CPU DVFS. SCMI Message Protocol is used to
communicate with the SCP.

This patch adds a cpufreq driver for such systems using SCMI interface
to drive CPU DVFS.

Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: linux-pm@vger.kernel.org
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 MAINTAINERS                    |   2 +-
 drivers/cpufreq/Kconfig.arm    |  11 ++
 drivers/cpufreq/Makefile       |   1 +
 drivers/cpufreq/scmi-cpufreq.c | 271 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 284 insertions(+), 1 deletion(-)
 create mode 100644 drivers/cpufreq/scmi-cpufreq.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 32c184391aee..1733813c52d9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12942,7 +12942,7 @@ L:	linux-arm-kernel@lists.infradead.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/arm/arm,sc[mp]i.txt
 F:	drivers/clk/clk-sc[mp]i.c
-F:	drivers/cpufreq/scpi-cpufreq.c
+F:	drivers/cpufreq/sc[mp]i-cpufreq.c
 F:	drivers/firmware/arm_scpi.c
 F:	drivers/firmware/arm_scmi/
 F:	include/linux/sc[mp]i_protocol.h
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index bdce4488ded1..e21f84cbd9b4 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -205,6 +205,17 @@ config ARM_SA1100_CPUFREQ
 config ARM_SA1110_CPUFREQ
 	bool
 
+config ARM_SCMI_CPUFREQ
+	tristate "SCMI based CPUfreq driver"
+	depends on ARM_SCMI_PROTOCOL || COMPILE_TEST
+	select PM_OPP
+	help
+	  This adds the CPUfreq driver support for ARM platforms using SCMI
+	  protocol for CPU power management.
+
+	  This driver uses SCMI Message Protocol driver to interact with the
+	  firmware providing the CPU DVFS functionality.
+
 config ARM_SCPI_CPUFREQ
         tristate "SCPI based CPUfreq driver"
 	depends on ARM_BIG_LITTLE_CPUFREQ && ARM_SCPI_PROTOCOL && COMMON_CLK_SCPI
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index c7af9b2a255e..1206207f9b62 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -71,6 +71,7 @@ obj-$(CONFIG_ARM_S3C64XX_CPUFREQ)	+= s3c64xx-cpufreq.o
 obj-$(CONFIG_ARM_S5PV210_CPUFREQ)	+= s5pv210-cpufreq.o
 obj-$(CONFIG_ARM_SA1100_CPUFREQ)	+= sa1100-cpufreq.o
 obj-$(CONFIG_ARM_SA1110_CPUFREQ)	+= sa1110-cpufreq.o
+obj-$(CONFIG_ARM_SCMI_CPUFREQ)		+= scmi-cpufreq.o
 obj-$(CONFIG_ARM_SCPI_CPUFREQ)		+= scpi-cpufreq.o
 obj-$(CONFIG_ARM_SPEAR_CPUFREQ)		+= spear-cpufreq.o
 obj-$(CONFIG_ARM_STI_CPUFREQ)		+= sti-cpufreq.o
diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c
new file mode 100644
index 000000000000..bc5385638eb4
--- /dev/null
+++ b/drivers/cpufreq/scmi-cpufreq.c
@@ -0,0 +1,271 @@
+/*
+ * System Control and Power Interface (SCMI) based CPUFreq Interface driver
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ * Sudeep Holla <sudeep.holla@arm.com>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/cpu.h>
+#include <linux/cpufreq.h>
+#include <linux/cpumask.h>
+#include <linux/cpu_cooling.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+#include <linux/slab.h>
+#include <linux/scmi_protocol.h>
+#include <linux/types.h>
+
+struct scmi_data {
+	int domain_id;
+	struct device *cpu_dev;
+	struct thermal_cooling_device *cdev;
+};
+
+static const struct scmi_handle *handle;
+
+unsigned int scmi_cpufreq_get_rate(unsigned int cpu)
+{
+	struct cpufreq_policy *policy = cpufreq_cpu_get_raw(cpu);
+	struct scmi_perf_ops *perf_ops = handle->perf_ops;
+	struct scmi_data *priv = policy->driver_data;
+	unsigned long rate;
+	int ret;
+
+	ret = perf_ops->freq_get(handle, priv->domain_id, &rate, false);
+	if (ret)
+		return 0;
+	return rate / 1000;
+}
+
+/*
+ * perf_ops->freq_set is not a synchronous, the actual OPP change will
+ * happen asynchronously and can get notified if the events are
+ * subscribed for by the SCMI firmware
+ */
+static int
+scmi_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index)
+{
+	struct scmi_data *priv = policy->driver_data;
+	struct scmi_perf_ops *perf_ops = handle->perf_ops;
+	u64 freq = policy->freq_table[index].frequency * 1000;
+
+	return perf_ops->freq_set(handle, priv->domain_id, freq, false);
+}
+
+static int
+scmi_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
+{
+	int cpu, domain, tdomain;
+	struct device *tcpu_dev;
+
+	domain = handle->perf_ops->device_domain_id(cpu_dev);
+	if (domain < 0)
+		return domain;
+
+	for_each_possible_cpu(cpu) {
+		if (cpu == cpu_dev->id)
+			continue;
+
+		tcpu_dev = get_cpu_device(cpu);
+		if (!tcpu_dev)
+			continue;
+
+		tdomain = handle->perf_ops->device_domain_id(tcpu_dev);
+		if (tdomain == domain)
+			cpumask_set_cpu(cpu, cpumask);
+	}
+
+	return 0;
+}
+
+static int scmi_cpufreq_init(struct cpufreq_policy *policy)
+{
+	int ret;
+	unsigned int latency;
+	struct device *cpu_dev;
+	struct scmi_data *priv;
+	struct cpufreq_frequency_table *freq_table;
+
+	cpu_dev = get_cpu_device(policy->cpu);
+	if (!cpu_dev) {
+		pr_err("failed to get cpu%d device\n", policy->cpu);
+		return -ENODEV;
+	}
+
+	ret = handle->perf_ops->add_opps_to_device(cpu_dev);
+	if (ret) {
+		dev_warn(cpu_dev, "failed to add opps to the device\n");
+		return ret;
+	}
+
+	ret = scmi_get_sharing_cpus(cpu_dev, policy->cpus);
+	if (ret) {
+		dev_warn(cpu_dev, "failed to get sharing cpumask\n");
+		return ret;
+	}
+
+	ret = dev_pm_opp_set_sharing_cpus(cpu_dev, policy->cpus);
+	if (ret) {
+		dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	/*
+	 * We need OPP table to function and since OPPs are added by the
+	 * platform, let's wait for the same.
+	 */
+	ret = dev_pm_opp_get_opp_count(cpu_dev);
+	if (ret <= 0) {
+		dev_dbg(cpu_dev, "OPP table is not ready, deferring probe\n");
+		ret = -EPROBE_DEFER;
+		goto out_free_opp;
+	}
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		ret = -ENOMEM;
+		goto out_free_opp;
+	}
+
+	ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
+	if (ret) {
+		dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
+		goto out_free_priv;
+	}
+
+	priv->cpu_dev = cpu_dev;
+	priv->domain_id = handle->perf_ops->device_domain_id(cpu_dev);
+
+	policy->driver_data = priv;
+
+	ret = cpufreq_table_validate_and_show(policy, freq_table);
+	if (ret) {
+		dev_err(cpu_dev, "%s: invalid frequency table: %d\n", __func__,
+			ret);
+		goto out_free_cpufreq_table;
+	}
+
+	/* SCMI allows DVFS request for any domain from any CPU */
+	policy->dvfs_possible_from_any_cpu = true;
+
+	latency = handle->perf_ops->get_transition_latency(cpu_dev);
+	if (!latency)
+		latency = CPUFREQ_ETERNAL;
+
+	policy->cpuinfo.transition_latency = latency;
+
+	return 0;
+
+out_free_cpufreq_table:
+	dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
+out_free_priv:
+	kfree(priv);
+out_free_opp:
+	dev_pm_opp_cpumask_remove_table(policy->cpus);
+
+	return ret;
+}
+
+static int scmi_cpufreq_exit(struct cpufreq_policy *policy)
+{
+	struct scmi_data *priv = policy->driver_data;
+
+	cpufreq_cooling_unregister(priv->cdev);
+	dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
+	kfree(priv);
+	dev_pm_opp_cpumask_remove_table(policy->related_cpus);
+
+	return 0;
+}
+
+static void scmi_cpufreq_ready(struct cpufreq_policy *policy)
+{
+	struct scmi_data *priv = policy->driver_data;
+	struct device_node *np = of_node_get(priv->cpu_dev->of_node);
+
+	if (WARN_ON(!np))
+		return;
+
+	if (of_find_property(np, "#cooling-cells", NULL)) {
+		u32 pcoeff = 0;
+
+		of_property_read_u32(np, "dynamic-power-coefficient",
+				     &pcoeff);
+
+		priv->cdev = of_cpufreq_power_cooling_register(np, policy,
+							       pcoeff, NULL);
+		if (IS_ERR(priv->cdev)) {
+			dev_err(priv->cpu_dev,
+				"running cpufreq without cooling device: %ld\n",
+				PTR_ERR(priv->cdev));
+
+			priv->cdev = NULL;
+		}
+	}
+
+	of_node_put(np);
+}
+
+static struct cpufreq_driver scmi_cpufreq_driver = {
+	.name	= "scmi",
+	.flags	= CPUFREQ_STICKY | CPUFREQ_HAVE_GOVERNOR_PER_POLICY |
+		  CPUFREQ_NEED_INITIAL_FREQ_CHECK,
+	.verify	= cpufreq_generic_frequency_table_verify,
+	.attr	= cpufreq_generic_attr,
+	.target_index	= scmi_cpufreq_set_target,
+	.get	= scmi_cpufreq_get_rate,
+	.init	= scmi_cpufreq_init,
+	.exit	= scmi_cpufreq_exit,
+	.ready	= scmi_cpufreq_ready,
+};
+
+static int scmi_cpufreq_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	handle = devm_scmi_handle_get(&pdev->dev);
+
+	if (IS_ERR_OR_NULL(handle) || !handle->perf_ops)
+		return -EPROBE_DEFER;
+
+	ret = cpufreq_register_driver(&scmi_cpufreq_driver);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: registering cpufreq failed, err: %d\n",
+			__func__, ret);
+	}
+
+	return ret;
+}
+
+static int scmi_cpufreq_remove(struct platform_device *pdev)
+{
+	cpufreq_unregister_driver(&scmi_cpufreq_driver);
+	return 0;
+}
+
+static struct platform_driver scmi_cpufreq_platdrv = {
+	.driver = {
+		.name	= "scmi-cpufreq",
+	},
+	.probe		= scmi_cpufreq_probe,
+	.remove		= scmi_cpufreq_remove,
+};
+module_platform_driver(scmi_cpufreq_platdrv);
+
+MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
+MODULE_DESCRIPTION("ARM SCMI CPUFreq interface driver");
+MODULE_LICENSE("GPL v2");
-- 
2.7.4

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

* [PATCH v3 21/22] cpufreq: add support for CPU DVFS based on SCMI message protocol
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

On some ARM based systems, a separate Cortex-M based System Control
Processor(SCP) provides the overall power, clock, reset and system
control including CPU DVFS. SCMI Message Protocol is used to
communicate with the SCP.

This patch adds a cpufreq driver for such systems using SCMI interface
to drive CPU DVFS.

Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: linux-pm at vger.kernel.org
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 MAINTAINERS                    |   2 +-
 drivers/cpufreq/Kconfig.arm    |  11 ++
 drivers/cpufreq/Makefile       |   1 +
 drivers/cpufreq/scmi-cpufreq.c | 271 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 284 insertions(+), 1 deletion(-)
 create mode 100644 drivers/cpufreq/scmi-cpufreq.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 32c184391aee..1733813c52d9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12942,7 +12942,7 @@ L:	linux-arm-kernel at lists.infradead.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/arm/arm,sc[mp]i.txt
 F:	drivers/clk/clk-sc[mp]i.c
-F:	drivers/cpufreq/scpi-cpufreq.c
+F:	drivers/cpufreq/sc[mp]i-cpufreq.c
 F:	drivers/firmware/arm_scpi.c
 F:	drivers/firmware/arm_scmi/
 F:	include/linux/sc[mp]i_protocol.h
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index bdce4488ded1..e21f84cbd9b4 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -205,6 +205,17 @@ config ARM_SA1100_CPUFREQ
 config ARM_SA1110_CPUFREQ
 	bool
 
+config ARM_SCMI_CPUFREQ
+	tristate "SCMI based CPUfreq driver"
+	depends on ARM_SCMI_PROTOCOL || COMPILE_TEST
+	select PM_OPP
+	help
+	  This adds the CPUfreq driver support for ARM platforms using SCMI
+	  protocol for CPU power management.
+
+	  This driver uses SCMI Message Protocol driver to interact with the
+	  firmware providing the CPU DVFS functionality.
+
 config ARM_SCPI_CPUFREQ
         tristate "SCPI based CPUfreq driver"
 	depends on ARM_BIG_LITTLE_CPUFREQ && ARM_SCPI_PROTOCOL && COMMON_CLK_SCPI
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index c7af9b2a255e..1206207f9b62 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -71,6 +71,7 @@ obj-$(CONFIG_ARM_S3C64XX_CPUFREQ)	+= s3c64xx-cpufreq.o
 obj-$(CONFIG_ARM_S5PV210_CPUFREQ)	+= s5pv210-cpufreq.o
 obj-$(CONFIG_ARM_SA1100_CPUFREQ)	+= sa1100-cpufreq.o
 obj-$(CONFIG_ARM_SA1110_CPUFREQ)	+= sa1110-cpufreq.o
+obj-$(CONFIG_ARM_SCMI_CPUFREQ)		+= scmi-cpufreq.o
 obj-$(CONFIG_ARM_SCPI_CPUFREQ)		+= scpi-cpufreq.o
 obj-$(CONFIG_ARM_SPEAR_CPUFREQ)		+= spear-cpufreq.o
 obj-$(CONFIG_ARM_STI_CPUFREQ)		+= sti-cpufreq.o
diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c
new file mode 100644
index 000000000000..bc5385638eb4
--- /dev/null
+++ b/drivers/cpufreq/scmi-cpufreq.c
@@ -0,0 +1,271 @@
+/*
+ * System Control and Power Interface (SCMI) based CPUFreq Interface driver
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ * Sudeep Holla <sudeep.holla@arm.com>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/cpu.h>
+#include <linux/cpufreq.h>
+#include <linux/cpumask.h>
+#include <linux/cpu_cooling.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+#include <linux/slab.h>
+#include <linux/scmi_protocol.h>
+#include <linux/types.h>
+
+struct scmi_data {
+	int domain_id;
+	struct device *cpu_dev;
+	struct thermal_cooling_device *cdev;
+};
+
+static const struct scmi_handle *handle;
+
+unsigned int scmi_cpufreq_get_rate(unsigned int cpu)
+{
+	struct cpufreq_policy *policy = cpufreq_cpu_get_raw(cpu);
+	struct scmi_perf_ops *perf_ops = handle->perf_ops;
+	struct scmi_data *priv = policy->driver_data;
+	unsigned long rate;
+	int ret;
+
+	ret = perf_ops->freq_get(handle, priv->domain_id, &rate, false);
+	if (ret)
+		return 0;
+	return rate / 1000;
+}
+
+/*
+ * perf_ops->freq_set is not a synchronous, the actual OPP change will
+ * happen asynchronously and can get notified if the events are
+ * subscribed for by the SCMI firmware
+ */
+static int
+scmi_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index)
+{
+	struct scmi_data *priv = policy->driver_data;
+	struct scmi_perf_ops *perf_ops = handle->perf_ops;
+	u64 freq = policy->freq_table[index].frequency * 1000;
+
+	return perf_ops->freq_set(handle, priv->domain_id, freq, false);
+}
+
+static int
+scmi_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
+{
+	int cpu, domain, tdomain;
+	struct device *tcpu_dev;
+
+	domain = handle->perf_ops->device_domain_id(cpu_dev);
+	if (domain < 0)
+		return domain;
+
+	for_each_possible_cpu(cpu) {
+		if (cpu == cpu_dev->id)
+			continue;
+
+		tcpu_dev = get_cpu_device(cpu);
+		if (!tcpu_dev)
+			continue;
+
+		tdomain = handle->perf_ops->device_domain_id(tcpu_dev);
+		if (tdomain == domain)
+			cpumask_set_cpu(cpu, cpumask);
+	}
+
+	return 0;
+}
+
+static int scmi_cpufreq_init(struct cpufreq_policy *policy)
+{
+	int ret;
+	unsigned int latency;
+	struct device *cpu_dev;
+	struct scmi_data *priv;
+	struct cpufreq_frequency_table *freq_table;
+
+	cpu_dev = get_cpu_device(policy->cpu);
+	if (!cpu_dev) {
+		pr_err("failed to get cpu%d device\n", policy->cpu);
+		return -ENODEV;
+	}
+
+	ret = handle->perf_ops->add_opps_to_device(cpu_dev);
+	if (ret) {
+		dev_warn(cpu_dev, "failed to add opps to the device\n");
+		return ret;
+	}
+
+	ret = scmi_get_sharing_cpus(cpu_dev, policy->cpus);
+	if (ret) {
+		dev_warn(cpu_dev, "failed to get sharing cpumask\n");
+		return ret;
+	}
+
+	ret = dev_pm_opp_set_sharing_cpus(cpu_dev, policy->cpus);
+	if (ret) {
+		dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	/*
+	 * We need OPP table to function and since OPPs are added by the
+	 * platform, let's wait for the same.
+	 */
+	ret = dev_pm_opp_get_opp_count(cpu_dev);
+	if (ret <= 0) {
+		dev_dbg(cpu_dev, "OPP table is not ready, deferring probe\n");
+		ret = -EPROBE_DEFER;
+		goto out_free_opp;
+	}
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		ret = -ENOMEM;
+		goto out_free_opp;
+	}
+
+	ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
+	if (ret) {
+		dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
+		goto out_free_priv;
+	}
+
+	priv->cpu_dev = cpu_dev;
+	priv->domain_id = handle->perf_ops->device_domain_id(cpu_dev);
+
+	policy->driver_data = priv;
+
+	ret = cpufreq_table_validate_and_show(policy, freq_table);
+	if (ret) {
+		dev_err(cpu_dev, "%s: invalid frequency table: %d\n", __func__,
+			ret);
+		goto out_free_cpufreq_table;
+	}
+
+	/* SCMI allows DVFS request for any domain from any CPU */
+	policy->dvfs_possible_from_any_cpu = true;
+
+	latency = handle->perf_ops->get_transition_latency(cpu_dev);
+	if (!latency)
+		latency = CPUFREQ_ETERNAL;
+
+	policy->cpuinfo.transition_latency = latency;
+
+	return 0;
+
+out_free_cpufreq_table:
+	dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
+out_free_priv:
+	kfree(priv);
+out_free_opp:
+	dev_pm_opp_cpumask_remove_table(policy->cpus);
+
+	return ret;
+}
+
+static int scmi_cpufreq_exit(struct cpufreq_policy *policy)
+{
+	struct scmi_data *priv = policy->driver_data;
+
+	cpufreq_cooling_unregister(priv->cdev);
+	dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
+	kfree(priv);
+	dev_pm_opp_cpumask_remove_table(policy->related_cpus);
+
+	return 0;
+}
+
+static void scmi_cpufreq_ready(struct cpufreq_policy *policy)
+{
+	struct scmi_data *priv = policy->driver_data;
+	struct device_node *np = of_node_get(priv->cpu_dev->of_node);
+
+	if (WARN_ON(!np))
+		return;
+
+	if (of_find_property(np, "#cooling-cells", NULL)) {
+		u32 pcoeff = 0;
+
+		of_property_read_u32(np, "dynamic-power-coefficient",
+				     &pcoeff);
+
+		priv->cdev = of_cpufreq_power_cooling_register(np, policy,
+							       pcoeff, NULL);
+		if (IS_ERR(priv->cdev)) {
+			dev_err(priv->cpu_dev,
+				"running cpufreq without cooling device: %ld\n",
+				PTR_ERR(priv->cdev));
+
+			priv->cdev = NULL;
+		}
+	}
+
+	of_node_put(np);
+}
+
+static struct cpufreq_driver scmi_cpufreq_driver = {
+	.name	= "scmi",
+	.flags	= CPUFREQ_STICKY | CPUFREQ_HAVE_GOVERNOR_PER_POLICY |
+		  CPUFREQ_NEED_INITIAL_FREQ_CHECK,
+	.verify	= cpufreq_generic_frequency_table_verify,
+	.attr	= cpufreq_generic_attr,
+	.target_index	= scmi_cpufreq_set_target,
+	.get	= scmi_cpufreq_get_rate,
+	.init	= scmi_cpufreq_init,
+	.exit	= scmi_cpufreq_exit,
+	.ready	= scmi_cpufreq_ready,
+};
+
+static int scmi_cpufreq_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	handle = devm_scmi_handle_get(&pdev->dev);
+
+	if (IS_ERR_OR_NULL(handle) || !handle->perf_ops)
+		return -EPROBE_DEFER;
+
+	ret = cpufreq_register_driver(&scmi_cpufreq_driver);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: registering cpufreq failed, err: %d\n",
+			__func__, ret);
+	}
+
+	return ret;
+}
+
+static int scmi_cpufreq_remove(struct platform_device *pdev)
+{
+	cpufreq_unregister_driver(&scmi_cpufreq_driver);
+	return 0;
+}
+
+static struct platform_driver scmi_cpufreq_platdrv = {
+	.driver = {
+		.name	= "scmi-cpufreq",
+	},
+	.probe		= scmi_cpufreq_probe,
+	.remove		= scmi_cpufreq_remove,
+};
+module_platform_driver(scmi_cpufreq_platdrv);
+
+MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
+MODULE_DESCRIPTION("ARM SCMI CPUFreq interface driver");
+MODULE_LICENSE("GPL v2");
-- 
2.7.4

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

* [PATCH v3 22/22] cpufreq: scmi: add support for fast frequency switching
  2017-09-28 13:11 ` Sudeep Holla
@ 2017-09-28 13:11   ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: ALKML, LKML, DTML
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Rafael J. Wysocki, Viresh Kumar, linux-pm

The cpufreq core provides option for drivers to implement fast_switch
callback which is invoked for frequency switching from interrupt context.

This patch adds support for fast_switch callback in SCMI cpufreq driver
by making use of polling based SCMI transfer. It also sets the flag
fast_switch_possible.

Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: linux-pm@vger.kernel.org
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/cpufreq/scmi-cpufreq.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c
index bc5385638eb4..067a39bd5167 100644
--- a/drivers/cpufreq/scmi-cpufreq.c
+++ b/drivers/cpufreq/scmi-cpufreq.c
@@ -65,6 +65,19 @@ scmi_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index)
 	return perf_ops->freq_set(handle, priv->domain_id, freq, false);
 }
 
+static unsigned int scmi_cpufreq_fast_switch(struct cpufreq_policy *policy,
+					     unsigned int target_freq)
+{
+	struct scmi_data *priv = policy->driver_data;
+	struct scmi_perf_ops *perf_ops = handle->perf_ops;
+
+	if (!perf_ops->freq_set(handle, priv->domain_id,
+				target_freq * 1000, true))
+		return target_freq;
+
+	return 0;
+}
+
 static int
 scmi_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
 {
@@ -168,6 +181,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
 
 	policy->cpuinfo.transition_latency = latency;
 
+	policy->fast_switch_possible = true;
 	return 0;
 
 out_free_cpufreq_table:
@@ -184,6 +198,7 @@ static int scmi_cpufreq_exit(struct cpufreq_policy *policy)
 {
 	struct scmi_data *priv = policy->driver_data;
 
+	policy->fast_switch_possible = false;
 	cpufreq_cooling_unregister(priv->cdev);
 	dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
 	kfree(priv);
@@ -227,6 +242,7 @@ static struct cpufreq_driver scmi_cpufreq_driver = {
 	.verify	= cpufreq_generic_frequency_table_verify,
 	.attr	= cpufreq_generic_attr,
 	.target_index	= scmi_cpufreq_set_target,
+	.fast_switch	= scmi_cpufreq_fast_switch,
 	.get	= scmi_cpufreq_get_rate,
 	.init	= scmi_cpufreq_init,
 	.exit	= scmi_cpufreq_exit,
-- 
2.7.4

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

* [PATCH v3 22/22] cpufreq: scmi: add support for fast frequency switching
@ 2017-09-28 13:11   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-28 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

The cpufreq core provides option for drivers to implement fast_switch
callback which is invoked for frequency switching from interrupt context.

This patch adds support for fast_switch callback in SCMI cpufreq driver
by making use of polling based SCMI transfer. It also sets the flag
fast_switch_possible.

Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: linux-pm at vger.kernel.org
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/cpufreq/scmi-cpufreq.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c
index bc5385638eb4..067a39bd5167 100644
--- a/drivers/cpufreq/scmi-cpufreq.c
+++ b/drivers/cpufreq/scmi-cpufreq.c
@@ -65,6 +65,19 @@ scmi_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index)
 	return perf_ops->freq_set(handle, priv->domain_id, freq, false);
 }
 
+static unsigned int scmi_cpufreq_fast_switch(struct cpufreq_policy *policy,
+					     unsigned int target_freq)
+{
+	struct scmi_data *priv = policy->driver_data;
+	struct scmi_perf_ops *perf_ops = handle->perf_ops;
+
+	if (!perf_ops->freq_set(handle, priv->domain_id,
+				target_freq * 1000, true))
+		return target_freq;
+
+	return 0;
+}
+
 static int
 scmi_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
 {
@@ -168,6 +181,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
 
 	policy->cpuinfo.transition_latency = latency;
 
+	policy->fast_switch_possible = true;
 	return 0;
 
 out_free_cpufreq_table:
@@ -184,6 +198,7 @@ static int scmi_cpufreq_exit(struct cpufreq_policy *policy)
 {
 	struct scmi_data *priv = policy->driver_data;
 
+	policy->fast_switch_possible = false;
 	cpufreq_cooling_unregister(priv->cdev);
 	dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
 	kfree(priv);
@@ -227,6 +242,7 @@ static struct cpufreq_driver scmi_cpufreq_driver = {
 	.verify	= cpufreq_generic_frequency_table_verify,
 	.attr	= cpufreq_generic_attr,
 	.target_index	= scmi_cpufreq_set_target,
+	.fast_switch	= scmi_cpufreq_fast_switch,
 	.get	= scmi_cpufreq_get_rate,
 	.init	= scmi_cpufreq_init,
 	.exit	= scmi_cpufreq_exit,
-- 
2.7.4

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

* Re: [PATCH v3 17/22] firmware: arm_scmi: add device power domain support using genpd
  2017-09-28 13:11   ` Sudeep Holla
@ 2017-09-28 21:18     ` Ulf Hansson
  -1 siblings, 0 replies; 208+ messages in thread
From: Ulf Hansson @ 2017-09-28 21:18 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Kevin Hilman

On 28 September 2017 at 15:11, Sudeep Holla <sudeep.holla@arm.com> wrote:
> This patch hooks up the support for device power domain provided by
> SCMI using the Linux generic power domain infrastructure.
>
> Cc: Kevin Hilman <khilman@baylibre.com>
> Cc: Ulf Hansson <ulf.hansson@linaro.org>
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> ---
>  drivers/firmware/Kconfig                   |  13 +++
>  drivers/firmware/arm_scmi/Makefile         |   1 +
>  drivers/firmware/arm_scmi/scmi_pm_domain.c | 134 +++++++++++++++++++++++++++++
>  3 files changed, 148 insertions(+)
>  create mode 100644 drivers/firmware/arm_scmi/scmi_pm_domain.c
>
> diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
> index c3d1a12763ce..a4462bc661c8 100644
> --- a/drivers/firmware/Kconfig
> +++ b/drivers/firmware/Kconfig
> @@ -40,6 +40,19 @@ config ARM_SCMI_PROTOCOL
>           This protocol library provides interface for all the client drivers
>           making use of the features offered by the SCMI.
>
> +config ARM_SCMI_POWER_DOMAIN
> +       tristate "SCMI power domain driver"
> +       depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
> +       default y
> +       select PM_GENERIC_DOMAINS if PM
> +       help
> +         This enables support for the SCMI power domains which can be
> +         enabled or disabled via the SCP firmware
> +
> +         This driver can also be built as a module.  If so, the module
> +         will be called scmi_pm_domain. Note this may needed early in boot
> +         before rootfs may be available.
> +
>  config ARM_SCPI_PROTOCOL
>         tristate "ARM System Control and Power Interface (SCPI) Message Protocol"
>         depends on ARM || ARM64 || COMPILE_TEST
> diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
> index 7fb026c71833..289e9e5a4764 100644
> --- a/drivers/firmware/arm_scmi/Makefile
> +++ b/drivers/firmware/arm_scmi/Makefile
> @@ -1,3 +1,4 @@
>  obj-$(CONFIG_ARM_SCMI_PROTOCOL)        = arm_scmi.o
>  arm_scmi-y = base.o clock.o driver.o mbox_if.o perf.o power.o sensors.o
>  arm_scmi-$(CONFIG_ARM_MHU) += arm_mhu_if.o
> +obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
> diff --git a/drivers/firmware/arm_scmi/scmi_pm_domain.c b/drivers/firmware/arm_scmi/scmi_pm_domain.c
> new file mode 100644
> index 000000000000..e53aa9d0af6e
> --- /dev/null
> +++ b/drivers/firmware/arm_scmi/scmi_pm_domain.c
> @@ -0,0 +1,134 @@
> +/*
> + * SCMI Generic power domain support.
> + *
> + * Copyright (C) 2017 ARM Ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of_platform.h>
> +#include <linux/pm_domain.h>
> +#include <linux/scmi_protocol.h>
> +
> +struct scmi_pm_domain {
> +       struct generic_pm_domain genpd;
> +       const struct scmi_handle *handle;
> +       const char *name;
> +       u32 domain;
> +};
> +
> +#define to_scmi_pd(gpd) container_of(gpd, struct scmi_pm_domain, genpd)
> +
> +static int scmi_pd_power(struct generic_pm_domain *domain, bool power_on)
> +{
> +       int ret;
> +       u32 state, ret_state;
> +       struct scmi_pm_domain *pd = to_scmi_pd(domain);
> +       const struct scmi_power_ops *ops = pd->handle->power_ops;
> +
> +       if (power_on)
> +               state = SCMI_POWER_STATE_GENERIC_ON;
> +       else
> +               state = SCMI_POWER_STATE_GENERIC_OFF;
> +
> +       ret = ops->state_set(pd->handle, pd->domain, state);
> +       if (!ret)
> +               ret = ops->state_get(pd->handle, pd->domain, &ret_state);
> +       if (!ret && state != ret_state)
> +               return -EIO;
> +
> +       return ret;
> +}
> +
> +static int scmi_pd_power_on(struct generic_pm_domain *domain)
> +{
> +       return scmi_pd_power(domain, true);
> +}
> +
> +static int scmi_pd_power_off(struct generic_pm_domain *domain)
> +{
> +       return scmi_pd_power(domain, false);
> +}
> +
> +static int scmi_pm_domain_probe(struct platform_device *pdev)
> +{
> +       struct device *dev = &pdev->dev;
> +       struct device_node *np = dev->of_node;
> +       struct scmi_pm_domain *scmi_pd;
> +       struct genpd_onecell_data *scmi_pd_data;
> +       struct generic_pm_domain **domains;
> +       int num_domains, i;
> +       const struct scmi_handle *handle = devm_scmi_handle_get(dev);
> +
> +       if (IS_ERR_OR_NULL(handle) || !handle->power_ops)
> +               return -EPROBE_DEFER;
> +
> +       num_domains = handle->power_ops->num_domains_get(handle);
> +       if (num_domains < 0) {
> +               dev_err(dev, "number of domains not found\n");
> +               return num_domains;
> +       }
> +
> +       scmi_pd = devm_kcalloc(dev, num_domains, sizeof(*scmi_pd), GFP_KERNEL);
> +       if (!scmi_pd)
> +               return -ENOMEM;
> +
> +       scmi_pd_data = devm_kzalloc(dev, sizeof(*scmi_pd_data), GFP_KERNEL);
> +       if (!scmi_pd_data)
> +               return -ENOMEM;
> +
> +       domains = devm_kcalloc(dev, num_domains, sizeof(*domains), GFP_KERNEL);
> +       if (!domains)
> +               return -ENOMEM;
> +
> +       for (i = 0; i < num_domains; i++, scmi_pd++) {
> +               domains[i] = &scmi_pd->genpd;
> +
> +               scmi_pd->domain = i;
> +               scmi_pd->handle = handle;
> +               scmi_pd->name = handle->power_ops->name_get(handle, i);
> +               scmi_pd->genpd.name = scmi_pd->name;
> +               scmi_pd->genpd.power_off = scmi_pd_power_off;
> +               scmi_pd->genpd.power_on = scmi_pd_power_on;
> +
> +               /*
> +                * Treat all power domains as off at boot.
> +                *
> +                * The SCP firmware itself may have switched on some domains,
> +                * but for reference counting purpose, keep it this way.
> +                */

I think it would be better to give the correct information about the
state of the PM domain. Otherwise genpd may end up thinking a PM
domain is off, while in fact it's on - thus wasting power.

> +               pm_genpd_init(&scmi_pd->genpd, NULL, true);
> +       }
> +
> +       scmi_pd_data->domains = domains;
> +       scmi_pd_data->num_domains = num_domains;
> +
> +       of_genpd_add_provider_onecell(np, scmi_pd_data);
> +
> +       return 0;
> +}
> +
> +static struct platform_driver scmi_power_domain_driver = {
> +       .driver = {
> +               .name = "scmi-power-domain",
> +       },
> +       .probe = scmi_pm_domain_probe,
> +};
> +module_platform_driver(scmi_power_domain_driver);
> +
> +MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
> +MODULE_DESCRIPTION("ARM SCMI power domain driver");
> +MODULE_LICENSE("GPL v2");
> --
> 2.7.4
>

Otherwise this looks good to me.

Kind regards
Uffe

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

* [PATCH v3 17/22] firmware: arm_scmi: add device power domain support using genpd
@ 2017-09-28 21:18     ` Ulf Hansson
  0 siblings, 0 replies; 208+ messages in thread
From: Ulf Hansson @ 2017-09-28 21:18 UTC (permalink / raw)
  To: linux-arm-kernel

On 28 September 2017 at 15:11, Sudeep Holla <sudeep.holla@arm.com> wrote:
> This patch hooks up the support for device power domain provided by
> SCMI using the Linux generic power domain infrastructure.
>
> Cc: Kevin Hilman <khilman@baylibre.com>
> Cc: Ulf Hansson <ulf.hansson@linaro.org>
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> ---
>  drivers/firmware/Kconfig                   |  13 +++
>  drivers/firmware/arm_scmi/Makefile         |   1 +
>  drivers/firmware/arm_scmi/scmi_pm_domain.c | 134 +++++++++++++++++++++++++++++
>  3 files changed, 148 insertions(+)
>  create mode 100644 drivers/firmware/arm_scmi/scmi_pm_domain.c
>
> diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
> index c3d1a12763ce..a4462bc661c8 100644
> --- a/drivers/firmware/Kconfig
> +++ b/drivers/firmware/Kconfig
> @@ -40,6 +40,19 @@ config ARM_SCMI_PROTOCOL
>           This protocol library provides interface for all the client drivers
>           making use of the features offered by the SCMI.
>
> +config ARM_SCMI_POWER_DOMAIN
> +       tristate "SCMI power domain driver"
> +       depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
> +       default y
> +       select PM_GENERIC_DOMAINS if PM
> +       help
> +         This enables support for the SCMI power domains which can be
> +         enabled or disabled via the SCP firmware
> +
> +         This driver can also be built as a module.  If so, the module
> +         will be called scmi_pm_domain. Note this may needed early in boot
> +         before rootfs may be available.
> +
>  config ARM_SCPI_PROTOCOL
>         tristate "ARM System Control and Power Interface (SCPI) Message Protocol"
>         depends on ARM || ARM64 || COMPILE_TEST
> diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
> index 7fb026c71833..289e9e5a4764 100644
> --- a/drivers/firmware/arm_scmi/Makefile
> +++ b/drivers/firmware/arm_scmi/Makefile
> @@ -1,3 +1,4 @@
>  obj-$(CONFIG_ARM_SCMI_PROTOCOL)        = arm_scmi.o
>  arm_scmi-y = base.o clock.o driver.o mbox_if.o perf.o power.o sensors.o
>  arm_scmi-$(CONFIG_ARM_MHU) += arm_mhu_if.o
> +obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
> diff --git a/drivers/firmware/arm_scmi/scmi_pm_domain.c b/drivers/firmware/arm_scmi/scmi_pm_domain.c
> new file mode 100644
> index 000000000000..e53aa9d0af6e
> --- /dev/null
> +++ b/drivers/firmware/arm_scmi/scmi_pm_domain.c
> @@ -0,0 +1,134 @@
> +/*
> + * SCMI Generic power domain support.
> + *
> + * Copyright (C) 2017 ARM Ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of_platform.h>
> +#include <linux/pm_domain.h>
> +#include <linux/scmi_protocol.h>
> +
> +struct scmi_pm_domain {
> +       struct generic_pm_domain genpd;
> +       const struct scmi_handle *handle;
> +       const char *name;
> +       u32 domain;
> +};
> +
> +#define to_scmi_pd(gpd) container_of(gpd, struct scmi_pm_domain, genpd)
> +
> +static int scmi_pd_power(struct generic_pm_domain *domain, bool power_on)
> +{
> +       int ret;
> +       u32 state, ret_state;
> +       struct scmi_pm_domain *pd = to_scmi_pd(domain);
> +       const struct scmi_power_ops *ops = pd->handle->power_ops;
> +
> +       if (power_on)
> +               state = SCMI_POWER_STATE_GENERIC_ON;
> +       else
> +               state = SCMI_POWER_STATE_GENERIC_OFF;
> +
> +       ret = ops->state_set(pd->handle, pd->domain, state);
> +       if (!ret)
> +               ret = ops->state_get(pd->handle, pd->domain, &ret_state);
> +       if (!ret && state != ret_state)
> +               return -EIO;
> +
> +       return ret;
> +}
> +
> +static int scmi_pd_power_on(struct generic_pm_domain *domain)
> +{
> +       return scmi_pd_power(domain, true);
> +}
> +
> +static int scmi_pd_power_off(struct generic_pm_domain *domain)
> +{
> +       return scmi_pd_power(domain, false);
> +}
> +
> +static int scmi_pm_domain_probe(struct platform_device *pdev)
> +{
> +       struct device *dev = &pdev->dev;
> +       struct device_node *np = dev->of_node;
> +       struct scmi_pm_domain *scmi_pd;
> +       struct genpd_onecell_data *scmi_pd_data;
> +       struct generic_pm_domain **domains;
> +       int num_domains, i;
> +       const struct scmi_handle *handle = devm_scmi_handle_get(dev);
> +
> +       if (IS_ERR_OR_NULL(handle) || !handle->power_ops)
> +               return -EPROBE_DEFER;
> +
> +       num_domains = handle->power_ops->num_domains_get(handle);
> +       if (num_domains < 0) {
> +               dev_err(dev, "number of domains not found\n");
> +               return num_domains;
> +       }
> +
> +       scmi_pd = devm_kcalloc(dev, num_domains, sizeof(*scmi_pd), GFP_KERNEL);
> +       if (!scmi_pd)
> +               return -ENOMEM;
> +
> +       scmi_pd_data = devm_kzalloc(dev, sizeof(*scmi_pd_data), GFP_KERNEL);
> +       if (!scmi_pd_data)
> +               return -ENOMEM;
> +
> +       domains = devm_kcalloc(dev, num_domains, sizeof(*domains), GFP_KERNEL);
> +       if (!domains)
> +               return -ENOMEM;
> +
> +       for (i = 0; i < num_domains; i++, scmi_pd++) {
> +               domains[i] = &scmi_pd->genpd;
> +
> +               scmi_pd->domain = i;
> +               scmi_pd->handle = handle;
> +               scmi_pd->name = handle->power_ops->name_get(handle, i);
> +               scmi_pd->genpd.name = scmi_pd->name;
> +               scmi_pd->genpd.power_off = scmi_pd_power_off;
> +               scmi_pd->genpd.power_on = scmi_pd_power_on;
> +
> +               /*
> +                * Treat all power domains as off at boot.
> +                *
> +                * The SCP firmware itself may have switched on some domains,
> +                * but for reference counting purpose, keep it this way.
> +                */

I think it would be better to give the correct information about the
state of the PM domain. Otherwise genpd may end up thinking a PM
domain is off, while in fact it's on - thus wasting power.

> +               pm_genpd_init(&scmi_pd->genpd, NULL, true);
> +       }
> +
> +       scmi_pd_data->domains = domains;
> +       scmi_pd_data->num_domains = num_domains;
> +
> +       of_genpd_add_provider_onecell(np, scmi_pd_data);
> +
> +       return 0;
> +}
> +
> +static struct platform_driver scmi_power_domain_driver = {
> +       .driver = {
> +               .name = "scmi-power-domain",
> +       },
> +       .probe = scmi_pm_domain_probe,
> +};
> +module_platform_driver(scmi_power_domain_driver);
> +
> +MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
> +MODULE_DESCRIPTION("ARM SCMI power domain driver");
> +MODULE_LICENSE("GPL v2");
> --
> 2.7.4
>

Otherwise this looks good to me.

Kind regards
Uffe

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

* Re: [PATCH v3 17/22] firmware: arm_scmi: add device power domain support using genpd
@ 2017-09-29 13:40       ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-29 13:40 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Arnd Bergmann, Loc Ho, Alexey Klimov,
	Ryan Harkin, Jassi Brar, Kevin Hilman



On 28/09/17 22:18, Ulf Hansson wrote:
> On 28 September 2017 at 15:11, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> This patch hooks up the support for device power domain provided by
>> SCMI using the Linux generic power domain infrastructure.
>>
>> Cc: Kevin Hilman <khilman@baylibre.com>
>> Cc: Ulf Hansson <ulf.hansson@linaro.org>
>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>> ---
>>  drivers/firmware/Kconfig                   |  13 +++
>>  drivers/firmware/arm_scmi/Makefile         |   1 +
>>  drivers/firmware/arm_scmi/scmi_pm_domain.c | 134 +++++++++++++++++++++++++++++
>>  3 files changed, 148 insertions(+)
>>  create mode 100644 drivers/firmware/arm_scmi/scmi_pm_domain.c
>>

[...]

>> +       for (i = 0; i < num_domains; i++, scmi_pd++) {
>> +               domains[i] = &scmi_pd->genpd;
>> +
>> +               scmi_pd->domain = i;
>> +               scmi_pd->handle = handle;
>> +               scmi_pd->name = handle->power_ops->name_get(handle, i);
>> +               scmi_pd->genpd.name = scmi_pd->name;
>> +               scmi_pd->genpd.power_off = scmi_pd_power_off;
>> +               scmi_pd->genpd.power_on = scmi_pd_power_on;
>> +
>> +               /*
>> +                * Treat all power domains as off at boot.
>> +                *
>> +                * The SCP firmware itself may have switched on some domains,
>> +                * but for reference counting purpose, keep it this way.
>> +                */
> 
> I think it would be better to give the correct information about the
> state of the PM domain. Otherwise genpd may end up thinking a PM
> domain is off, while in fact it's on - thus wasting power.
> 

Agreed, I missed to notice that. I will fixup and send the update.

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 17/22] firmware: arm_scmi: add device power domain support using genpd
@ 2017-09-29 13:40       ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-29 13:40 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Arnd Bergmann, Loc Ho, Alexey Klimov,
	Ryan Harkin, Jassi Brar, Kevin Hilman



On 28/09/17 22:18, Ulf Hansson wrote:
> On 28 September 2017 at 15:11, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
>> This patch hooks up the support for device power domain provided by
>> SCMI using the Linux generic power domain infrastructure.
>>
>> Cc: Kevin Hilman <khilman-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
>> Cc: Ulf Hansson <ulf.hansson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>> Signed-off-by: Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org>
>> ---
>>  drivers/firmware/Kconfig                   |  13 +++
>>  drivers/firmware/arm_scmi/Makefile         |   1 +
>>  drivers/firmware/arm_scmi/scmi_pm_domain.c | 134 +++++++++++++++++++++++++++++
>>  3 files changed, 148 insertions(+)
>>  create mode 100644 drivers/firmware/arm_scmi/scmi_pm_domain.c
>>

[...]

>> +       for (i = 0; i < num_domains; i++, scmi_pd++) {
>> +               domains[i] = &scmi_pd->genpd;
>> +
>> +               scmi_pd->domain = i;
>> +               scmi_pd->handle = handle;
>> +               scmi_pd->name = handle->power_ops->name_get(handle, i);
>> +               scmi_pd->genpd.name = scmi_pd->name;
>> +               scmi_pd->genpd.power_off = scmi_pd_power_off;
>> +               scmi_pd->genpd.power_on = scmi_pd_power_on;
>> +
>> +               /*
>> +                * Treat all power domains as off at boot.
>> +                *
>> +                * The SCP firmware itself may have switched on some domains,
>> +                * but for reference counting purpose, keep it this way.
>> +                */
> 
> I think it would be better to give the correct information about the
> state of the PM domain. Otherwise genpd may end up thinking a PM
> domain is off, while in fact it's on - thus wasting power.
> 

Agreed, I missed to notice that. I will fixup and send the update.

-- 
Regards,
Sudeep
--
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] 208+ messages in thread

* [PATCH v3 17/22] firmware: arm_scmi: add device power domain support using genpd
@ 2017-09-29 13:40       ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-29 13:40 UTC (permalink / raw)
  To: linux-arm-kernel



On 28/09/17 22:18, Ulf Hansson wrote:
> On 28 September 2017 at 15:11, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> This patch hooks up the support for device power domain provided by
>> SCMI using the Linux generic power domain infrastructure.
>>
>> Cc: Kevin Hilman <khilman@baylibre.com>
>> Cc: Ulf Hansson <ulf.hansson@linaro.org>
>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>> ---
>>  drivers/firmware/Kconfig                   |  13 +++
>>  drivers/firmware/arm_scmi/Makefile         |   1 +
>>  drivers/firmware/arm_scmi/scmi_pm_domain.c | 134 +++++++++++++++++++++++++++++
>>  3 files changed, 148 insertions(+)
>>  create mode 100644 drivers/firmware/arm_scmi/scmi_pm_domain.c
>>

[...]

>> +       for (i = 0; i < num_domains; i++, scmi_pd++) {
>> +               domains[i] = &scmi_pd->genpd;
>> +
>> +               scmi_pd->domain = i;
>> +               scmi_pd->handle = handle;
>> +               scmi_pd->name = handle->power_ops->name_get(handle, i);
>> +               scmi_pd->genpd.name = scmi_pd->name;
>> +               scmi_pd->genpd.power_off = scmi_pd_power_off;
>> +               scmi_pd->genpd.power_on = scmi_pd_power_on;
>> +
>> +               /*
>> +                * Treat all power domains as off at boot.
>> +                *
>> +                * The SCP firmware itself may have switched on some domains,
>> +                * but for reference counting purpose, keep it this way.
>> +                */
> 
> I think it would be better to give the correct information about the
> state of the PM domain. Otherwise genpd may end up thinking a PM
> domain is off, while in fact it's on - thus wasting power.
> 

Agreed, I missed to notice that. I will fixup and send the update.

-- 
Regards,
Sudeep

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

* [PATCH v3 17/22][UPDATE] firmware: arm_scmi: add device power domain support genpd
@ 2017-09-29 13:42     ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-29 13:42 UTC (permalink / raw)
  To: ALKML, LKML, DTML, Ulf Hansson
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Kevin Hilman

This patch hooks up the support for device power domain provided by
SCMI using the Linux generic power domain infrastructure.

Cc: Kevin Hilman <khilman@baylibre.com>
Cc: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/Kconfig                   |  13 +++
 drivers/firmware/arm_scmi/Makefile         |   1 +
 drivers/firmware/arm_scmi/scmi_pm_domain.c | 136 +++++++++++++++++++++++++++++
 3 files changed, 150 insertions(+)
 create mode 100644 drivers/firmware/arm_scmi/scmi_pm_domain.c

- updated to read the initial state instead of assuming off as
  suggested by Ulf

diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index c3d1a12763ce..a4462bc661c8 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -40,6 +40,19 @@ config ARM_SCMI_PROTOCOL
 	  This protocol library provides interface for all the client drivers
 	  making use of the features offered by the SCMI.

+config ARM_SCMI_POWER_DOMAIN
+	tristate "SCMI power domain driver"
+	depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
+	default y
+	select PM_GENERIC_DOMAINS if PM
+	help
+	  This enables support for the SCMI power domains which can be
+	  enabled or disabled via the SCP firmware
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called scmi_pm_domain. Note this may needed early in boot
+	  before rootfs may be available.
+
 config ARM_SCPI_PROTOCOL
 	tristate "ARM System Control and Power Interface (SCPI) Message Protocol"
 	depends on ARM || ARM64 || COMPILE_TEST
diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index 7fb026c71833..289e9e5a4764 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_ARM_SCMI_PROTOCOL)	= arm_scmi.o
 arm_scmi-y = base.o clock.o driver.o mbox_if.o perf.o power.o sensors.o
 arm_scmi-$(CONFIG_ARM_MHU) += arm_mhu_if.o
+obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
diff --git a/drivers/firmware/arm_scmi/scmi_pm_domain.c b/drivers/firmware/arm_scmi/scmi_pm_domain.c
new file mode 100644
index 000000000000..f105f7d5c660
--- /dev/null
+++ b/drivers/firmware/arm_scmi/scmi_pm_domain.c
@@ -0,0 +1,136 @@
+/*
+ * SCMI Generic power domain support.
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/pm_domain.h>
+#include <linux/scmi_protocol.h>
+
+struct scmi_pm_domain {
+	struct generic_pm_domain genpd;
+	const struct scmi_handle *handle;
+	const char *name;
+	u32 domain;
+};
+
+#define to_scmi_pd(gpd) container_of(gpd, struct scmi_pm_domain, genpd)
+
+static int scmi_pd_power(struct generic_pm_domain *domain, bool power_on)
+{
+	int ret;
+	u32 state, ret_state;
+	struct scmi_pm_domain *pd = to_scmi_pd(domain);
+	const struct scmi_power_ops *ops = pd->handle->power_ops;
+
+	if (power_on)
+		state = SCMI_POWER_STATE_GENERIC_ON;
+	else
+		state = SCMI_POWER_STATE_GENERIC_OFF;
+
+	ret = ops->state_set(pd->handle, pd->domain, state);
+	if (!ret)
+		ret = ops->state_get(pd->handle, pd->domain, &ret_state);
+	if (!ret && state != ret_state)
+		return -EIO;
+
+	return ret;
+}
+
+static int scmi_pd_power_on(struct generic_pm_domain *domain)
+{
+	return scmi_pd_power(domain, true);
+}
+
+static int scmi_pd_power_off(struct generic_pm_domain *domain)
+{
+	return scmi_pd_power(domain, false);
+}
+
+static int scmi_pm_domain_probe(struct platform_device *pdev)
+{
+	int num_domains, i;
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct scmi_pm_domain *scmi_pd;
+	struct genpd_onecell_data *scmi_pd_data;
+	struct generic_pm_domain **domains;
+	const struct scmi_handle *handle = devm_scmi_handle_get(dev);
+
+	if (IS_ERR_OR_NULL(handle) || !handle->power_ops)
+		return -EPROBE_DEFER;
+
+	num_domains = handle->power_ops->num_domains_get(handle);
+	if (num_domains < 0) {
+		dev_err(dev, "number of domains not found\n");
+		return num_domains;
+	}
+
+	scmi_pd = devm_kcalloc(dev, num_domains, sizeof(*scmi_pd), GFP_KERNEL);
+	if (!scmi_pd)
+		return -ENOMEM;
+
+	scmi_pd_data = devm_kzalloc(dev, sizeof(*scmi_pd_data), GFP_KERNEL);
+	if (!scmi_pd_data)
+		return -ENOMEM;
+
+	domains = devm_kcalloc(dev, num_domains, sizeof(*domains), GFP_KERNEL);
+	if (!domains)
+		return -ENOMEM;
+
+	for (i = 0; i < num_domains; i++, scmi_pd++) {
+		u32 state;
+
+		domains[i] = &scmi_pd->genpd;
+
+		scmi_pd->domain = i;
+		scmi_pd->handle = handle;
+		scmi_pd->name = handle->power_ops->name_get(handle, i);
+		scmi_pd->genpd.name = scmi_pd->name;
+		scmi_pd->genpd.power_off = scmi_pd_power_off;
+		scmi_pd->genpd.power_on = scmi_pd_power_on;
+
+		if (handle->power_ops->state_get(handle, i, &state)) {
+			dev_dbg(dev, "failed to get state for domain %d\n", i);
+			continue;
+		}
+
+		pm_genpd_init(&scmi_pd->genpd, NULL,
+			      state == SCMI_POWER_STATE_GENERIC_OFF);
+	}
+
+	scmi_pd_data->domains = domains;
+	scmi_pd_data->num_domains = num_domains;
+
+	of_genpd_add_provider_onecell(np, scmi_pd_data);
+
+	return 0;
+}
+
+static struct platform_driver scmi_power_domain_driver = {
+	.driver	= {
+		.name = "scmi-power-domain",
+	},
+	.probe = scmi_pm_domain_probe,
+};
+module_platform_driver(scmi_power_domain_driver);
+
+MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
+MODULE_DESCRIPTION("ARM SCMI power domain driver");
+MODULE_LICENSE("GPL v2");
--
2.7.4

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

* [PATCH v3 17/22][UPDATE] firmware: arm_scmi: add device power domain support genpd
@ 2017-09-29 13:42     ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-29 13:42 UTC (permalink / raw)
  To: ALKML, LKML, DTML, Ulf Hansson
  Cc: Sudeep Holla, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Kevin Hilman

This patch hooks up the support for device power domain provided by
SCMI using the Linux generic power domain infrastructure.

Cc: Kevin Hilman <khilman-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
Cc: Ulf Hansson <ulf.hansson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Signed-off-by: Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org>
---
 drivers/firmware/Kconfig                   |  13 +++
 drivers/firmware/arm_scmi/Makefile         |   1 +
 drivers/firmware/arm_scmi/scmi_pm_domain.c | 136 +++++++++++++++++++++++++++++
 3 files changed, 150 insertions(+)
 create mode 100644 drivers/firmware/arm_scmi/scmi_pm_domain.c

- updated to read the initial state instead of assuming off as
  suggested by Ulf

diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index c3d1a12763ce..a4462bc661c8 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -40,6 +40,19 @@ config ARM_SCMI_PROTOCOL
 	  This protocol library provides interface for all the client drivers
 	  making use of the features offered by the SCMI.

+config ARM_SCMI_POWER_DOMAIN
+	tristate "SCMI power domain driver"
+	depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
+	default y
+	select PM_GENERIC_DOMAINS if PM
+	help
+	  This enables support for the SCMI power domains which can be
+	  enabled or disabled via the SCP firmware
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called scmi_pm_domain. Note this may needed early in boot
+	  before rootfs may be available.
+
 config ARM_SCPI_PROTOCOL
 	tristate "ARM System Control and Power Interface (SCPI) Message Protocol"
 	depends on ARM || ARM64 || COMPILE_TEST
diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index 7fb026c71833..289e9e5a4764 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_ARM_SCMI_PROTOCOL)	= arm_scmi.o
 arm_scmi-y = base.o clock.o driver.o mbox_if.o perf.o power.o sensors.o
 arm_scmi-$(CONFIG_ARM_MHU) += arm_mhu_if.o
+obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
diff --git a/drivers/firmware/arm_scmi/scmi_pm_domain.c b/drivers/firmware/arm_scmi/scmi_pm_domain.c
new file mode 100644
index 000000000000..f105f7d5c660
--- /dev/null
+++ b/drivers/firmware/arm_scmi/scmi_pm_domain.c
@@ -0,0 +1,136 @@
+/*
+ * SCMI Generic power domain support.
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/pm_domain.h>
+#include <linux/scmi_protocol.h>
+
+struct scmi_pm_domain {
+	struct generic_pm_domain genpd;
+	const struct scmi_handle *handle;
+	const char *name;
+	u32 domain;
+};
+
+#define to_scmi_pd(gpd) container_of(gpd, struct scmi_pm_domain, genpd)
+
+static int scmi_pd_power(struct generic_pm_domain *domain, bool power_on)
+{
+	int ret;
+	u32 state, ret_state;
+	struct scmi_pm_domain *pd = to_scmi_pd(domain);
+	const struct scmi_power_ops *ops = pd->handle->power_ops;
+
+	if (power_on)
+		state = SCMI_POWER_STATE_GENERIC_ON;
+	else
+		state = SCMI_POWER_STATE_GENERIC_OFF;
+
+	ret = ops->state_set(pd->handle, pd->domain, state);
+	if (!ret)
+		ret = ops->state_get(pd->handle, pd->domain, &ret_state);
+	if (!ret && state != ret_state)
+		return -EIO;
+
+	return ret;
+}
+
+static int scmi_pd_power_on(struct generic_pm_domain *domain)
+{
+	return scmi_pd_power(domain, true);
+}
+
+static int scmi_pd_power_off(struct generic_pm_domain *domain)
+{
+	return scmi_pd_power(domain, false);
+}
+
+static int scmi_pm_domain_probe(struct platform_device *pdev)
+{
+	int num_domains, i;
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct scmi_pm_domain *scmi_pd;
+	struct genpd_onecell_data *scmi_pd_data;
+	struct generic_pm_domain **domains;
+	const struct scmi_handle *handle = devm_scmi_handle_get(dev);
+
+	if (IS_ERR_OR_NULL(handle) || !handle->power_ops)
+		return -EPROBE_DEFER;
+
+	num_domains = handle->power_ops->num_domains_get(handle);
+	if (num_domains < 0) {
+		dev_err(dev, "number of domains not found\n");
+		return num_domains;
+	}
+
+	scmi_pd = devm_kcalloc(dev, num_domains, sizeof(*scmi_pd), GFP_KERNEL);
+	if (!scmi_pd)
+		return -ENOMEM;
+
+	scmi_pd_data = devm_kzalloc(dev, sizeof(*scmi_pd_data), GFP_KERNEL);
+	if (!scmi_pd_data)
+		return -ENOMEM;
+
+	domains = devm_kcalloc(dev, num_domains, sizeof(*domains), GFP_KERNEL);
+	if (!domains)
+		return -ENOMEM;
+
+	for (i = 0; i < num_domains; i++, scmi_pd++) {
+		u32 state;
+
+		domains[i] = &scmi_pd->genpd;
+
+		scmi_pd->domain = i;
+		scmi_pd->handle = handle;
+		scmi_pd->name = handle->power_ops->name_get(handle, i);
+		scmi_pd->genpd.name = scmi_pd->name;
+		scmi_pd->genpd.power_off = scmi_pd_power_off;
+		scmi_pd->genpd.power_on = scmi_pd_power_on;
+
+		if (handle->power_ops->state_get(handle, i, &state)) {
+			dev_dbg(dev, "failed to get state for domain %d\n", i);
+			continue;
+		}
+
+		pm_genpd_init(&scmi_pd->genpd, NULL,
+			      state == SCMI_POWER_STATE_GENERIC_OFF);
+	}
+
+	scmi_pd_data->domains = domains;
+	scmi_pd_data->num_domains = num_domains;
+
+	of_genpd_add_provider_onecell(np, scmi_pd_data);
+
+	return 0;
+}
+
+static struct platform_driver scmi_power_domain_driver = {
+	.driver	= {
+		.name = "scmi-power-domain",
+	},
+	.probe = scmi_pm_domain_probe,
+};
+module_platform_driver(scmi_power_domain_driver);
+
+MODULE_AUTHOR("Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org>");
+MODULE_DESCRIPTION("ARM SCMI power domain driver");
+MODULE_LICENSE("GPL v2");
--
2.7.4

--
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] 208+ messages in thread

* [PATCH v3 17/22][UPDATE] firmware: arm_scmi: add device power domain support genpd
@ 2017-09-29 13:42     ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-09-29 13:42 UTC (permalink / raw)
  To: linux-arm-kernel

This patch hooks up the support for device power domain provided by
SCMI using the Linux generic power domain infrastructure.

Cc: Kevin Hilman <khilman@baylibre.com>
Cc: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
 drivers/firmware/Kconfig                   |  13 +++
 drivers/firmware/arm_scmi/Makefile         |   1 +
 drivers/firmware/arm_scmi/scmi_pm_domain.c | 136 +++++++++++++++++++++++++++++
 3 files changed, 150 insertions(+)
 create mode 100644 drivers/firmware/arm_scmi/scmi_pm_domain.c

- updated to read the initial state instead of assuming off as
  suggested by Ulf

diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index c3d1a12763ce..a4462bc661c8 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -40,6 +40,19 @@ config ARM_SCMI_PROTOCOL
 	  This protocol library provides interface for all the client drivers
 	  making use of the features offered by the SCMI.

+config ARM_SCMI_POWER_DOMAIN
+	tristate "SCMI power domain driver"
+	depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
+	default y
+	select PM_GENERIC_DOMAINS if PM
+	help
+	  This enables support for the SCMI power domains which can be
+	  enabled or disabled via the SCP firmware
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called scmi_pm_domain. Note this may needed early in boot
+	  before rootfs may be available.
+
 config ARM_SCPI_PROTOCOL
 	tristate "ARM System Control and Power Interface (SCPI) Message Protocol"
 	depends on ARM || ARM64 || COMPILE_TEST
diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index 7fb026c71833..289e9e5a4764 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_ARM_SCMI_PROTOCOL)	= arm_scmi.o
 arm_scmi-y = base.o clock.o driver.o mbox_if.o perf.o power.o sensors.o
 arm_scmi-$(CONFIG_ARM_MHU) += arm_mhu_if.o
+obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
diff --git a/drivers/firmware/arm_scmi/scmi_pm_domain.c b/drivers/firmware/arm_scmi/scmi_pm_domain.c
new file mode 100644
index 000000000000..f105f7d5c660
--- /dev/null
+++ b/drivers/firmware/arm_scmi/scmi_pm_domain.c
@@ -0,0 +1,136 @@
+/*
+ * SCMI Generic power domain support.
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/pm_domain.h>
+#include <linux/scmi_protocol.h>
+
+struct scmi_pm_domain {
+	struct generic_pm_domain genpd;
+	const struct scmi_handle *handle;
+	const char *name;
+	u32 domain;
+};
+
+#define to_scmi_pd(gpd) container_of(gpd, struct scmi_pm_domain, genpd)
+
+static int scmi_pd_power(struct generic_pm_domain *domain, bool power_on)
+{
+	int ret;
+	u32 state, ret_state;
+	struct scmi_pm_domain *pd = to_scmi_pd(domain);
+	const struct scmi_power_ops *ops = pd->handle->power_ops;
+
+	if (power_on)
+		state = SCMI_POWER_STATE_GENERIC_ON;
+	else
+		state = SCMI_POWER_STATE_GENERIC_OFF;
+
+	ret = ops->state_set(pd->handle, pd->domain, state);
+	if (!ret)
+		ret = ops->state_get(pd->handle, pd->domain, &ret_state);
+	if (!ret && state != ret_state)
+		return -EIO;
+
+	return ret;
+}
+
+static int scmi_pd_power_on(struct generic_pm_domain *domain)
+{
+	return scmi_pd_power(domain, true);
+}
+
+static int scmi_pd_power_off(struct generic_pm_domain *domain)
+{
+	return scmi_pd_power(domain, false);
+}
+
+static int scmi_pm_domain_probe(struct platform_device *pdev)
+{
+	int num_domains, i;
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct scmi_pm_domain *scmi_pd;
+	struct genpd_onecell_data *scmi_pd_data;
+	struct generic_pm_domain **domains;
+	const struct scmi_handle *handle = devm_scmi_handle_get(dev);
+
+	if (IS_ERR_OR_NULL(handle) || !handle->power_ops)
+		return -EPROBE_DEFER;
+
+	num_domains = handle->power_ops->num_domains_get(handle);
+	if (num_domains < 0) {
+		dev_err(dev, "number of domains not found\n");
+		return num_domains;
+	}
+
+	scmi_pd = devm_kcalloc(dev, num_domains, sizeof(*scmi_pd), GFP_KERNEL);
+	if (!scmi_pd)
+		return -ENOMEM;
+
+	scmi_pd_data = devm_kzalloc(dev, sizeof(*scmi_pd_data), GFP_KERNEL);
+	if (!scmi_pd_data)
+		return -ENOMEM;
+
+	domains = devm_kcalloc(dev, num_domains, sizeof(*domains), GFP_KERNEL);
+	if (!domains)
+		return -ENOMEM;
+
+	for (i = 0; i < num_domains; i++, scmi_pd++) {
+		u32 state;
+
+		domains[i] = &scmi_pd->genpd;
+
+		scmi_pd->domain = i;
+		scmi_pd->handle = handle;
+		scmi_pd->name = handle->power_ops->name_get(handle, i);
+		scmi_pd->genpd.name = scmi_pd->name;
+		scmi_pd->genpd.power_off = scmi_pd_power_off;
+		scmi_pd->genpd.power_on = scmi_pd_power_on;
+
+		if (handle->power_ops->state_get(handle, i, &state)) {
+			dev_dbg(dev, "failed to get state for domain %d\n", i);
+			continue;
+		}
+
+		pm_genpd_init(&scmi_pd->genpd, NULL,
+			      state == SCMI_POWER_STATE_GENERIC_OFF);
+	}
+
+	scmi_pd_data->domains = domains;
+	scmi_pd_data->num_domains = num_domains;
+
+	of_genpd_add_provider_onecell(np, scmi_pd_data);
+
+	return 0;
+}
+
+static struct platform_driver scmi_power_domain_driver = {
+	.driver	= {
+		.name = "scmi-power-domain",
+	},
+	.probe = scmi_pm_domain_probe,
+};
+module_platform_driver(scmi_power_domain_driver);
+
+MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
+MODULE_DESCRIPTION("ARM SCMI power domain driver");
+MODULE_LICENSE("GPL v2");
--
2.7.4

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

* Re: [v3, 19/22] hwmon: (core) Add hwmon_max to hwmon_sensor_types enumeration
  2017-09-28 13:11   ` Sudeep Holla
@ 2017-10-01 14:21     ` Guenter Roeck
  -1 siblings, 0 replies; 208+ messages in thread
From: Guenter Roeck @ 2017-10-01 14:21 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	linux-hwmon

On Thu, Sep 28, 2017 at 02:11:43PM +0100, Sudeep Holla wrote:
> It's useful to know the maximum types of sensor supported by hwmon
> framework. It can be used to allocate some data structures when sorting
> the monitors based on their type.
> 
> This will be used by scmi hwmon support.
> 
> Cc: Guenter Roeck <linux@roeck-us.net>
> Cc: linux-hwmon@vger.kernel.org
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>

Acked-by: Guenter Roeck <linux@roeck-us.net>

> ---
>  include/linux/hwmon.h | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/include/linux/hwmon.h b/include/linux/hwmon.h
> index ceb751987c40..e5fd2707b6df 100644
> --- a/include/linux/hwmon.h
> +++ b/include/linux/hwmon.h
> @@ -29,6 +29,7 @@ enum hwmon_sensor_types {
>  	hwmon_humidity,
>  	hwmon_fan,
>  	hwmon_pwm,
> +	hwmon_max,
>  };
>  
>  enum hwmon_chip_attributes {

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

* [v3, 19/22] hwmon: (core) Add hwmon_max to hwmon_sensor_types enumeration
@ 2017-10-01 14:21     ` Guenter Roeck
  0 siblings, 0 replies; 208+ messages in thread
From: Guenter Roeck @ 2017-10-01 14:21 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 28, 2017 at 02:11:43PM +0100, Sudeep Holla wrote:
> It's useful to know the maximum types of sensor supported by hwmon
> framework. It can be used to allocate some data structures when sorting
> the monitors based on their type.
> 
> This will be used by scmi hwmon support.
> 
> Cc: Guenter Roeck <linux@roeck-us.net>
> Cc: linux-hwmon at vger.kernel.org
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>

Acked-by: Guenter Roeck <linux@roeck-us.net>

> ---
>  include/linux/hwmon.h | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/include/linux/hwmon.h b/include/linux/hwmon.h
> index ceb751987c40..e5fd2707b6df 100644
> --- a/include/linux/hwmon.h
> +++ b/include/linux/hwmon.h
> @@ -29,6 +29,7 @@ enum hwmon_sensor_types {
>  	hwmon_humidity,
>  	hwmon_fan,
>  	hwmon_pwm,
> +	hwmon_max,
>  };
>  
>  enum hwmon_chip_attributes {

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

* Re: [v3,20/22] hwmon: add support for sensors exported via ARM SCMI
  2017-09-28 13:11   ` Sudeep Holla
@ 2017-10-01 14:26     ` Guenter Roeck
  -1 siblings, 0 replies; 208+ messages in thread
From: Guenter Roeck @ 2017-10-01 14:26 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	linux-hwmon

On Thu, Sep 28, 2017 at 02:11:44PM +0100, Sudeep Holla wrote:
> Create a driver to add support for SoC sensors exported by the System
> Control Processor (SCP) via the System Control and Management Interface
> (SCMI). The supported sensor types is one of voltage, temperature,
> current, and power.
> 
> The sensor labels and values provided by the SCP are exported via the
> hwmon sysfs interface.
> 
> Cc: Guenter Roeck <linux@roeck-us.net>
> Cc: linux-hwmon@vger.kernel.org
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>

Couple of minor comments. With those addressed,

Acked-by: Guenter Roeck <linux@roeck-us.net>

> ---
>  drivers/hwmon/Kconfig      |  12 +++
>  drivers/hwmon/Makefile     |   1 +
>  drivers/hwmon/scmi-hwmon.c | 235 +++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 248 insertions(+)
>  create mode 100644 drivers/hwmon/scmi-hwmon.c
> 
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index d65431417b17..0b75e9a89463 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -321,6 +321,18 @@ config SENSORS_APPLESMC
>  	  Say Y here if you have an applicable laptop and want to experience
>  	  the awesome power of applesmc.
>  
> +config SENSORS_ARM_SCMI
> +	tristate "ARM SCMI Sensors"
> +	depends on ARM_SCMI_PROTOCOL
> +	depends on THERMAL || !THERMAL_OF
> +	help
> +	  This driver provides support for temperature, voltage, current
> +	  and power sensors available on SCMI based platforms. The actual
> +	  number and type of sensors exported depend on the platform.
> +
> +	  This driver can also be built as a module.  If so, the module
> +	  will be called scmi-hwmon.
> +
>  config SENSORS_ARM_SCPI
>  	tristate "ARM SCPI Sensors"
>  	depends on ARM_SCPI_PROTOCOL
> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> index c84d9784be98..a51c2dcef11c 100644
> --- a/drivers/hwmon/Makefile
> +++ b/drivers/hwmon/Makefile
> @@ -44,6 +44,7 @@ obj-$(CONFIG_SENSORS_ADT7462)	+= adt7462.o
>  obj-$(CONFIG_SENSORS_ADT7470)	+= adt7470.o
>  obj-$(CONFIG_SENSORS_ADT7475)	+= adt7475.o
>  obj-$(CONFIG_SENSORS_APPLESMC)	+= applesmc.o
> +obj-$(CONFIG_SENSORS_ARM_SCMI)	+= scmi-hwmon.o
>  obj-$(CONFIG_SENSORS_ARM_SCPI)	+= scpi-hwmon.o
>  obj-$(CONFIG_SENSORS_ASC7621)	+= asc7621.o
>  obj-$(CONFIG_SENSORS_ASPEED)	+= aspeed-pwm-tacho.o
> diff --git a/drivers/hwmon/scmi-hwmon.c b/drivers/hwmon/scmi-hwmon.c
> new file mode 100644
> index 000000000000..0a8c0e8dc5d1
> --- /dev/null
> +++ b/drivers/hwmon/scmi-hwmon.c
> @@ -0,0 +1,235 @@
> +/*
> + * System Control and Management Interface(SCMI) based hwmon sensor driver
> + *
> + * Copyright (C) 2017 ARM Ltd.
> + * Sudeep Holla <sudeep.holla@arm.com>
> + *
> + * 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.
> + *
> + * This program is distributed "as is" WITHOUT ANY WARRANTY of any
> + * kind, whether express or implied; without even the implied warranty
> + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/hwmon.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/scmi_protocol.h>
> +#include <linux/slab.h>
> +#include <linux/sysfs.h>
> +#include <linux/thermal.h>
> +
> +struct scmi_sensors {
> +	const struct scmi_handle *handle;
> +	const struct scmi_sensor_info **info[hwmon_max];
> +};
> +
> +static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
> +			   u32 attr, int channel, long *val)
> +{
> +	int ret;
> +	u64 value;
> +	const struct scmi_sensor_info *sensor;
> +	struct scmi_sensors *scmi_sensors = dev_get_drvdata(dev);
> +	const struct scmi_handle *h = scmi_sensors->handle;
> +
> +	sensor = *(scmi_sensors->info[type] + channel);
> +	ret = h->sensor_ops->reading_get(h, sensor->id, false, &value);
> +	if (!ret)
> +		*val = value;
> +
> +	return ret;
> +}
> +
> +static int
> +scmi_hwmon_read_string(struct device *dev, enum hwmon_sensor_types type,
> +		       u32 attr, int channel, const char **str)
> +{
> +	const struct scmi_sensor_info *sensor;
> +	struct scmi_sensors *scmi_sensors = dev_get_drvdata(dev);
> +
> +	sensor = *(scmi_sensors->info[type] + channel);
> +	*str = sensor->name;
> +
> +	return 0;
> +}
> +
> +static umode_t
> +scmi_hwmon_is_visible(const void *drvdata, enum hwmon_sensor_types type,
> +		      u32 attr, int channel)
> +{
> +	const struct scmi_sensor_info *sensor;
> +	const struct scmi_sensors *scmi_sensors = drvdata;
> +
> +	sensor = *(scmi_sensors->info[type] + channel);
> +	if (sensor && sensor->name)
> +		return S_IRUGO;
> +
> +	return 0;
> +}
> +
> +static const struct hwmon_ops scmi_hwmon_ops = {
> +	.is_visible = scmi_hwmon_is_visible,
> +	.read = scmi_hwmon_read,
> +	.read_string = scmi_hwmon_read_string,
> +};
> +
> +static struct hwmon_chip_info scmi_chip_info = {
> +	.ops = &scmi_hwmon_ops,
> +	.info = NULL,
> +};
> +
> +static int scmi_hwmon_add_chan_info(struct hwmon_channel_info *scmi_hwmon_chan,
> +				    struct device *dev, int num,
> +				    enum hwmon_sensor_types type, u32 config)
> +{
> +	int i;
> +	u32 *cfg = devm_kcalloc(dev, num + 1, sizeof(*cfg), GFP_KERNEL);
> +
> +	if (!cfg)
> +		return -ENOMEM;
> +
> +	scmi_hwmon_chan->type = type;
> +	scmi_hwmon_chan->config = cfg;
> +	for (i = 0; i < num; i++, cfg++)
> +		*cfg = config;
> +
> +	return 0;
> +}
> +
> +static enum hwmon_sensor_types scmi_types[] = {
> +	[TEMPERATURE_C] = hwmon_temp,
> +	[VOLTAGE] = hwmon_in,
> +	[CURRENT] = hwmon_curr,
> +	[POWER] = hwmon_power,
> +	[ENERGY] = hwmon_energy,
> +};
> +
> +static u32 hwmon_attributes[] = {
> +	[hwmon_chip] = HWMON_C_REGISTER_TZ,
> +	[hwmon_temp] = HWMON_T_INPUT | HWMON_T_LABEL,
> +	[hwmon_in] = HWMON_I_INPUT | HWMON_I_LABEL,
> +	[hwmon_curr] = HWMON_C_INPUT | HWMON_C_LABEL,
> +	[hwmon_power] = HWMON_P_INPUT | HWMON_P_LABEL,
> +	[hwmon_energy] = HWMON_E_INPUT | HWMON_E_LABEL,
> +};
> +
> +static int scmi_hwmon_probe(struct platform_device *pdev)
> +{
> +	int i, idx;
> +	u16 nr_sensors;
> +	enum hwmon_sensor_types type;
> +	struct scmi_sensors *scmi_sensors;
> +	const struct scmi_sensor_info *sensor;
> +	int nr_count[hwmon_max] = {0}, nr_types = 0;
> +	const struct hwmon_chip_info *chip_info;
> +	struct device *hwdev, *dev = &pdev->dev;
> +	struct hwmon_channel_info *scmi_hwmon_chan;
> +	const struct hwmon_channel_info **ptr_scmi_ci;
> +	const struct scmi_handle *handle = devm_scmi_handle_get(dev);
> +
> +	if (IS_ERR_OR_NULL(handle) || !handle->sensor_ops)
> +		return -EPROBE_DEFER;
> +
> +	nr_sensors = handle->sensor_ops->count_get(handle);
> +	if (!nr_sensors)
> +		return -EIO;
> +
> +	scmi_sensors = devm_kzalloc(dev, sizeof(*scmi_sensors), GFP_KERNEL);
> +	if (!scmi_sensors)
> +		return -ENOMEM;
> +
> +	scmi_sensors->handle = handle;
> +
> +	for (i = 0; i < nr_sensors; i++) {
> +		sensor = handle->sensor_ops->info_get(handle, i);
> +		if (!sensor)
> +			return PTR_ERR(sensor);
> +
> +		switch (sensor->type) {
> +		case TEMPERATURE_C:
> +		case VOLTAGE:
> +		case CURRENT:
> +		case POWER:
> +		case ENERGY:
> +			type = scmi_types[sensor->type];
> +			if (!nr_count[type])
> +				nr_types++;
> +			nr_count[type]++;
> +			break;
> +		}
> +	}
> +
> +	if (nr_count[hwmon_temp])
> +		nr_count[hwmon_chip]++, nr_types++;
> +
> +	scmi_hwmon_chan = devm_kcalloc(dev, nr_types, sizeof(*scmi_hwmon_chan),
> +				       GFP_KERNEL);
> +	if (!scmi_hwmon_chan)
> +		return -ENOMEM;
> +
> +	ptr_scmi_ci = devm_kcalloc(dev, nr_types + 1, sizeof(*ptr_scmi_ci),
> +				   GFP_KERNEL);
> +	if (!ptr_scmi_ci)
> +		return -ENOMEM;
> +
> +	scmi_chip_info.info = ptr_scmi_ci;
> +	chip_info = &scmi_chip_info;
> +
> +	for (type = 0; type < hwmon_max && nr_count[type]; type++) {
> +		scmi_hwmon_add_chan_info(scmi_hwmon_chan, dev, nr_count[type],
> +					 type, hwmon_attributes[type]);
> +		*ptr_scmi_ci++ = scmi_hwmon_chan++;
> +
> +		scmi_sensors->info[type] =
> +			devm_kcalloc(dev, nr_count[type],
> +				     sizeof(*scmi_sensors->info), GFP_KERNEL);
> +		if (!scmi_sensors->info[type])
> +			return -ENOMEM;
> +	}
> +
> +	*ptr_scmi_ci = NULL;

Unnecessary; devm_kcalloc() clears out the allocated memory.

> +	platform_set_drvdata(pdev, scmi_sensors);
> +
> +	for (i = nr_sensors - 1; i >= 0 ; i--) {
> +		sensor = handle->sensor_ops->info_get(handle, i);
> +		if (!sensor)
> +			continue;
> +
> +		switch (sensor->type) {
> +		case TEMPERATURE_C:
> +		case VOLTAGE:
> +		case CURRENT:
> +		case POWER:
> +		case ENERGY:
> +			type = scmi_types[sensor->type];
> +			idx = --nr_count[type];
> +			*(scmi_sensors->info[type] + idx) = sensor;
> +			break;
> +		}
> +	}
> +
> +	hwdev = devm_hwmon_device_register_with_info(dev, "scmi_sensors",
> +						     scmi_sensors, chip_info,
> +						     NULL);
> +
> +	if (IS_ERR(hwdev))
> +		return PTR_ERR(hwdev);
> +
> +	return 0;

	return PTR_ERR_OR_ZERO(hwdev);

> +}
> +
> +static struct platform_driver scmi_hwmon_platdrv = {
> +	.driver = {
> +		.name	= "scmi-hwmon",
> +	},
> +	.probe		= scmi_hwmon_probe,
> +};
> +module_platform_driver(scmi_hwmon_platdrv);
> +
> +MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
> +MODULE_DESCRIPTION("ARM SCMI HWMON interface driver");
> +MODULE_LICENSE("GPL v2");

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

* [v3,20/22] hwmon: add support for sensors exported via ARM SCMI
@ 2017-10-01 14:26     ` Guenter Roeck
  0 siblings, 0 replies; 208+ messages in thread
From: Guenter Roeck @ 2017-10-01 14:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 28, 2017 at 02:11:44PM +0100, Sudeep Holla wrote:
> Create a driver to add support for SoC sensors exported by the System
> Control Processor (SCP) via the System Control and Management Interface
> (SCMI). The supported sensor types is one of voltage, temperature,
> current, and power.
> 
> The sensor labels and values provided by the SCP are exported via the
> hwmon sysfs interface.
> 
> Cc: Guenter Roeck <linux@roeck-us.net>
> Cc: linux-hwmon at vger.kernel.org
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>

Couple of minor comments. With those addressed,

Acked-by: Guenter Roeck <linux@roeck-us.net>

> ---
>  drivers/hwmon/Kconfig      |  12 +++
>  drivers/hwmon/Makefile     |   1 +
>  drivers/hwmon/scmi-hwmon.c | 235 +++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 248 insertions(+)
>  create mode 100644 drivers/hwmon/scmi-hwmon.c
> 
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index d65431417b17..0b75e9a89463 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -321,6 +321,18 @@ config SENSORS_APPLESMC
>  	  Say Y here if you have an applicable laptop and want to experience
>  	  the awesome power of applesmc.
>  
> +config SENSORS_ARM_SCMI
> +	tristate "ARM SCMI Sensors"
> +	depends on ARM_SCMI_PROTOCOL
> +	depends on THERMAL || !THERMAL_OF
> +	help
> +	  This driver provides support for temperature, voltage, current
> +	  and power sensors available on SCMI based platforms. The actual
> +	  number and type of sensors exported depend on the platform.
> +
> +	  This driver can also be built as a module.  If so, the module
> +	  will be called scmi-hwmon.
> +
>  config SENSORS_ARM_SCPI
>  	tristate "ARM SCPI Sensors"
>  	depends on ARM_SCPI_PROTOCOL
> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> index c84d9784be98..a51c2dcef11c 100644
> --- a/drivers/hwmon/Makefile
> +++ b/drivers/hwmon/Makefile
> @@ -44,6 +44,7 @@ obj-$(CONFIG_SENSORS_ADT7462)	+= adt7462.o
>  obj-$(CONFIG_SENSORS_ADT7470)	+= adt7470.o
>  obj-$(CONFIG_SENSORS_ADT7475)	+= adt7475.o
>  obj-$(CONFIG_SENSORS_APPLESMC)	+= applesmc.o
> +obj-$(CONFIG_SENSORS_ARM_SCMI)	+= scmi-hwmon.o
>  obj-$(CONFIG_SENSORS_ARM_SCPI)	+= scpi-hwmon.o
>  obj-$(CONFIG_SENSORS_ASC7621)	+= asc7621.o
>  obj-$(CONFIG_SENSORS_ASPEED)	+= aspeed-pwm-tacho.o
> diff --git a/drivers/hwmon/scmi-hwmon.c b/drivers/hwmon/scmi-hwmon.c
> new file mode 100644
> index 000000000000..0a8c0e8dc5d1
> --- /dev/null
> +++ b/drivers/hwmon/scmi-hwmon.c
> @@ -0,0 +1,235 @@
> +/*
> + * System Control and Management Interface(SCMI) based hwmon sensor driver
> + *
> + * Copyright (C) 2017 ARM Ltd.
> + * Sudeep Holla <sudeep.holla@arm.com>
> + *
> + * 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.
> + *
> + * This program is distributed "as is" WITHOUT ANY WARRANTY of any
> + * kind, whether express or implied; without even the implied warranty
> + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/hwmon.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/scmi_protocol.h>
> +#include <linux/slab.h>
> +#include <linux/sysfs.h>
> +#include <linux/thermal.h>
> +
> +struct scmi_sensors {
> +	const struct scmi_handle *handle;
> +	const struct scmi_sensor_info **info[hwmon_max];
> +};
> +
> +static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
> +			   u32 attr, int channel, long *val)
> +{
> +	int ret;
> +	u64 value;
> +	const struct scmi_sensor_info *sensor;
> +	struct scmi_sensors *scmi_sensors = dev_get_drvdata(dev);
> +	const struct scmi_handle *h = scmi_sensors->handle;
> +
> +	sensor = *(scmi_sensors->info[type] + channel);
> +	ret = h->sensor_ops->reading_get(h, sensor->id, false, &value);
> +	if (!ret)
> +		*val = value;
> +
> +	return ret;
> +}
> +
> +static int
> +scmi_hwmon_read_string(struct device *dev, enum hwmon_sensor_types type,
> +		       u32 attr, int channel, const char **str)
> +{
> +	const struct scmi_sensor_info *sensor;
> +	struct scmi_sensors *scmi_sensors = dev_get_drvdata(dev);
> +
> +	sensor = *(scmi_sensors->info[type] + channel);
> +	*str = sensor->name;
> +
> +	return 0;
> +}
> +
> +static umode_t
> +scmi_hwmon_is_visible(const void *drvdata, enum hwmon_sensor_types type,
> +		      u32 attr, int channel)
> +{
> +	const struct scmi_sensor_info *sensor;
> +	const struct scmi_sensors *scmi_sensors = drvdata;
> +
> +	sensor = *(scmi_sensors->info[type] + channel);
> +	if (sensor && sensor->name)
> +		return S_IRUGO;
> +
> +	return 0;
> +}
> +
> +static const struct hwmon_ops scmi_hwmon_ops = {
> +	.is_visible = scmi_hwmon_is_visible,
> +	.read = scmi_hwmon_read,
> +	.read_string = scmi_hwmon_read_string,
> +};
> +
> +static struct hwmon_chip_info scmi_chip_info = {
> +	.ops = &scmi_hwmon_ops,
> +	.info = NULL,
> +};
> +
> +static int scmi_hwmon_add_chan_info(struct hwmon_channel_info *scmi_hwmon_chan,
> +				    struct device *dev, int num,
> +				    enum hwmon_sensor_types type, u32 config)
> +{
> +	int i;
> +	u32 *cfg = devm_kcalloc(dev, num + 1, sizeof(*cfg), GFP_KERNEL);
> +
> +	if (!cfg)
> +		return -ENOMEM;
> +
> +	scmi_hwmon_chan->type = type;
> +	scmi_hwmon_chan->config = cfg;
> +	for (i = 0; i < num; i++, cfg++)
> +		*cfg = config;
> +
> +	return 0;
> +}
> +
> +static enum hwmon_sensor_types scmi_types[] = {
> +	[TEMPERATURE_C] = hwmon_temp,
> +	[VOLTAGE] = hwmon_in,
> +	[CURRENT] = hwmon_curr,
> +	[POWER] = hwmon_power,
> +	[ENERGY] = hwmon_energy,
> +};
> +
> +static u32 hwmon_attributes[] = {
> +	[hwmon_chip] = HWMON_C_REGISTER_TZ,
> +	[hwmon_temp] = HWMON_T_INPUT | HWMON_T_LABEL,
> +	[hwmon_in] = HWMON_I_INPUT | HWMON_I_LABEL,
> +	[hwmon_curr] = HWMON_C_INPUT | HWMON_C_LABEL,
> +	[hwmon_power] = HWMON_P_INPUT | HWMON_P_LABEL,
> +	[hwmon_energy] = HWMON_E_INPUT | HWMON_E_LABEL,
> +};
> +
> +static int scmi_hwmon_probe(struct platform_device *pdev)
> +{
> +	int i, idx;
> +	u16 nr_sensors;
> +	enum hwmon_sensor_types type;
> +	struct scmi_sensors *scmi_sensors;
> +	const struct scmi_sensor_info *sensor;
> +	int nr_count[hwmon_max] = {0}, nr_types = 0;
> +	const struct hwmon_chip_info *chip_info;
> +	struct device *hwdev, *dev = &pdev->dev;
> +	struct hwmon_channel_info *scmi_hwmon_chan;
> +	const struct hwmon_channel_info **ptr_scmi_ci;
> +	const struct scmi_handle *handle = devm_scmi_handle_get(dev);
> +
> +	if (IS_ERR_OR_NULL(handle) || !handle->sensor_ops)
> +		return -EPROBE_DEFER;
> +
> +	nr_sensors = handle->sensor_ops->count_get(handle);
> +	if (!nr_sensors)
> +		return -EIO;
> +
> +	scmi_sensors = devm_kzalloc(dev, sizeof(*scmi_sensors), GFP_KERNEL);
> +	if (!scmi_sensors)
> +		return -ENOMEM;
> +
> +	scmi_sensors->handle = handle;
> +
> +	for (i = 0; i < nr_sensors; i++) {
> +		sensor = handle->sensor_ops->info_get(handle, i);
> +		if (!sensor)
> +			return PTR_ERR(sensor);
> +
> +		switch (sensor->type) {
> +		case TEMPERATURE_C:
> +		case VOLTAGE:
> +		case CURRENT:
> +		case POWER:
> +		case ENERGY:
> +			type = scmi_types[sensor->type];
> +			if (!nr_count[type])
> +				nr_types++;
> +			nr_count[type]++;
> +			break;
> +		}
> +	}
> +
> +	if (nr_count[hwmon_temp])
> +		nr_count[hwmon_chip]++, nr_types++;
> +
> +	scmi_hwmon_chan = devm_kcalloc(dev, nr_types, sizeof(*scmi_hwmon_chan),
> +				       GFP_KERNEL);
> +	if (!scmi_hwmon_chan)
> +		return -ENOMEM;
> +
> +	ptr_scmi_ci = devm_kcalloc(dev, nr_types + 1, sizeof(*ptr_scmi_ci),
> +				   GFP_KERNEL);
> +	if (!ptr_scmi_ci)
> +		return -ENOMEM;
> +
> +	scmi_chip_info.info = ptr_scmi_ci;
> +	chip_info = &scmi_chip_info;
> +
> +	for (type = 0; type < hwmon_max && nr_count[type]; type++) {
> +		scmi_hwmon_add_chan_info(scmi_hwmon_chan, dev, nr_count[type],
> +					 type, hwmon_attributes[type]);
> +		*ptr_scmi_ci++ = scmi_hwmon_chan++;
> +
> +		scmi_sensors->info[type] =
> +			devm_kcalloc(dev, nr_count[type],
> +				     sizeof(*scmi_sensors->info), GFP_KERNEL);
> +		if (!scmi_sensors->info[type])
> +			return -ENOMEM;
> +	}
> +
> +	*ptr_scmi_ci = NULL;

Unnecessary; devm_kcalloc() clears out the allocated memory.

> +	platform_set_drvdata(pdev, scmi_sensors);
> +
> +	for (i = nr_sensors - 1; i >= 0 ; i--) {
> +		sensor = handle->sensor_ops->info_get(handle, i);
> +		if (!sensor)
> +			continue;
> +
> +		switch (sensor->type) {
> +		case TEMPERATURE_C:
> +		case VOLTAGE:
> +		case CURRENT:
> +		case POWER:
> +		case ENERGY:
> +			type = scmi_types[sensor->type];
> +			idx = --nr_count[type];
> +			*(scmi_sensors->info[type] + idx) = sensor;
> +			break;
> +		}
> +	}
> +
> +	hwdev = devm_hwmon_device_register_with_info(dev, "scmi_sensors",
> +						     scmi_sensors, chip_info,
> +						     NULL);
> +
> +	if (IS_ERR(hwdev))
> +		return PTR_ERR(hwdev);
> +
> +	return 0;

	return PTR_ERR_OR_ZERO(hwdev);

> +}
> +
> +static struct platform_driver scmi_hwmon_platdrv = {
> +	.driver = {
> +		.name	= "scmi-hwmon",
> +	},
> +	.probe		= scmi_hwmon_probe,
> +};
> +module_platform_driver(scmi_hwmon_platdrv);
> +
> +MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
> +MODULE_DESCRIPTION("ARM SCMI HWMON interface driver");
> +MODULE_LICENSE("GPL v2");

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

* Re: [v3,20/22] hwmon: add support for sensors exported via ARM SCMI
  2017-10-01 14:26     ` Guenter Roeck
@ 2017-10-02  9:25       ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-02  9:25 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Arnd Bergmann, Loc Ho, Alexey Klimov,
	Ryan Harkin, Jassi Brar, linux-hwmon



On 01/10/17 15:26, Guenter Roeck wrote:
> On Thu, Sep 28, 2017 at 02:11:44PM +0100, Sudeep Holla wrote:
>> Create a driver to add support for SoC sensors exported by the System
>> Control Processor (SCP) via the System Control and Management Interface
>> (SCMI). The supported sensor types is one of voltage, temperature,
>> current, and power.
>>
>> The sensor labels and values provided by the SCP are exported via the
>> hwmon sysfs interface.
>>
>> Cc: Guenter Roeck <linux@roeck-us.net>
>> Cc: linux-hwmon@vger.kernel.org
>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> 
> Couple of minor comments. With those addressed,
> 

Yes, I have fixed them locally now.

> Acked-by: Guenter Roeck <linux@roeck-us.net>

Thanks.

-- 
Regards,
Sudeep

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

* [v3,20/22] hwmon: add support for sensors exported via ARM SCMI
@ 2017-10-02  9:25       ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-02  9:25 UTC (permalink / raw)
  To: linux-arm-kernel



On 01/10/17 15:26, Guenter Roeck wrote:
> On Thu, Sep 28, 2017 at 02:11:44PM +0100, Sudeep Holla wrote:
>> Create a driver to add support for SoC sensors exported by the System
>> Control Processor (SCP) via the System Control and Management Interface
>> (SCMI). The supported sensor types is one of voltage, temperature,
>> current, and power.
>>
>> The sensor labels and values provided by the SCP are exported via the
>> hwmon sysfs interface.
>>
>> Cc: Guenter Roeck <linux@roeck-us.net>
>> Cc: linux-hwmon at vger.kernel.org
>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> 
> Couple of minor comments. With those addressed,
> 

Yes, I have fixed them locally now.

> Acked-by: Guenter Roeck <linux@roeck-us.net>

Thanks.

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-10-04 10:50     ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 10:50 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar, Rob Herring,
	Mark Rutland

On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> +
> +The SCMI is intended to allow agents such as OSPM to manage various functions
> +that are provided by the hardware platform it is running on, including power
> +and performance functions.
> +
> +This binding is intended to define the interface the firmware implementing
> +the SCMI as described in ARM document number ARM DUI 0922B ("ARM System Control
> +and Management Interface Platform Design Document")[0] provide for OSPM in
> +the device tree.
> +
> +Required properties:
> +
> +The scmi node with the following properties shall be under the /firmware/ node.
> +
> +- compatible : shall be "arm,scmi"
> +- mboxes: List of phandle and mailbox channel specifiers. It should contain
> +         exactly one or two mailboxes, one for transmitting messages("tx")
> +         and another optional for receiving the notifications("rx") if
> +         supported.
> +- mbox-names: shall be "tx" or "rx"

The example below does not have the mbox-names property. If you require
exactly two mailboxes, why do you need the names anyway?

However, your example does have a #addresss-cells/#size-cells
property that are not documented here. Please add them here as either
optional or required, and describe what the permitted values are and
how the address is interpreted.

> +- shmem : List of phandle pointing to the shared memory(SHM) area as per
> +         generic mailbox client binding.
> +
> +See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details
> +about the generic mailbox controller and client driver bindings.
> +
> +The mailbox is the only permitted method of calling the SCMI firmware.
> +Mailbox doorbell is used as a mechanism to alert the presence of a
> +messages and/or notification.

This looks odd: why not make the message itself part of the mailbox
protocol here, and leave the shmem as a implementation detail of the
mailbox driver?

> +Each protocol supported shall have a sub-node with corresponding compatible
> +as described in the following sections. If the platform supports dedicated
> +communication channel for a particular protocol, the 3 properties namely:
> +mboxes, mbox-names and shmem shall be present in the sub-node corresponding
> +to that protocol.
> +
> +Clock/Performance bindings for the clocks/OPPs based on SCMI Message Protocol
> +------------------------------------------------------------
> +
> +This binding uses the common clock binding[1].
> +
> +Required properties:
> +- #clock-cells : Should be 1. Contains the Clock ID value used by SCMI commands.
> +

How does the OS identify the fact that a subnode uses the clock binding?
Do you need to look for the #clock-cells property, or is this based on the
unit address?

          Arnd

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

* Re: [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-10-04 10:50     ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 10:50 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar, Rob Herring,
	Mark Rutland

On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
> +
> +The SCMI is intended to allow agents such as OSPM to manage various functions
> +that are provided by the hardware platform it is running on, including power
> +and performance functions.
> +
> +This binding is intended to define the interface the firmware implementing
> +the SCMI as described in ARM document number ARM DUI 0922B ("ARM System Control
> +and Management Interface Platform Design Document")[0] provide for OSPM in
> +the device tree.
> +
> +Required properties:
> +
> +The scmi node with the following properties shall be under the /firmware/ node.
> +
> +- compatible : shall be "arm,scmi"
> +- mboxes: List of phandle and mailbox channel specifiers. It should contain
> +         exactly one or two mailboxes, one for transmitting messages("tx")
> +         and another optional for receiving the notifications("rx") if
> +         supported.
> +- mbox-names: shall be "tx" or "rx"

The example below does not have the mbox-names property. If you require
exactly two mailboxes, why do you need the names anyway?

However, your example does have a #addresss-cells/#size-cells
property that are not documented here. Please add them here as either
optional or required, and describe what the permitted values are and
how the address is interpreted.

> +- shmem : List of phandle pointing to the shared memory(SHM) area as per
> +         generic mailbox client binding.
> +
> +See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details
> +about the generic mailbox controller and client driver bindings.
> +
> +The mailbox is the only permitted method of calling the SCMI firmware.
> +Mailbox doorbell is used as a mechanism to alert the presence of a
> +messages and/or notification.

This looks odd: why not make the message itself part of the mailbox
protocol here, and leave the shmem as a implementation detail of the
mailbox driver?

> +Each protocol supported shall have a sub-node with corresponding compatible
> +as described in the following sections. If the platform supports dedicated
> +communication channel for a particular protocol, the 3 properties namely:
> +mboxes, mbox-names and shmem shall be present in the sub-node corresponding
> +to that protocol.
> +
> +Clock/Performance bindings for the clocks/OPPs based on SCMI Message Protocol
> +------------------------------------------------------------
> +
> +This binding uses the common clock binding[1].
> +
> +Required properties:
> +- #clock-cells : Should be 1. Contains the Clock ID value used by SCMI commands.
> +

How does the OS identify the fact that a subnode uses the clock binding?
Do you need to look for the #clock-cells property, or is this based on the
unit address?

          Arnd
--
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] 208+ messages in thread

* [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-10-04 10:50     ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 10:50 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> +
> +The SCMI is intended to allow agents such as OSPM to manage various functions
> +that are provided by the hardware platform it is running on, including power
> +and performance functions.
> +
> +This binding is intended to define the interface the firmware implementing
> +the SCMI as described in ARM document number ARM DUI 0922B ("ARM System Control
> +and Management Interface Platform Design Document")[0] provide for OSPM in
> +the device tree.
> +
> +Required properties:
> +
> +The scmi node with the following properties shall be under the /firmware/ node.
> +
> +- compatible : shall be "arm,scmi"
> +- mboxes: List of phandle and mailbox channel specifiers. It should contain
> +         exactly one or two mailboxes, one for transmitting messages("tx")
> +         and another optional for receiving the notifications("rx") if
> +         supported.
> +- mbox-names: shall be "tx" or "rx"

The example below does not have the mbox-names property. If you require
exactly two mailboxes, why do you need the names anyway?

However, your example does have a #addresss-cells/#size-cells
property that are not documented here. Please add them here as either
optional or required, and describe what the permitted values are and
how the address is interpreted.

> +- shmem : List of phandle pointing to the shared memory(SHM) area as per
> +         generic mailbox client binding.
> +
> +See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details
> +about the generic mailbox controller and client driver bindings.
> +
> +The mailbox is the only permitted method of calling the SCMI firmware.
> +Mailbox doorbell is used as a mechanism to alert the presence of a
> +messages and/or notification.

This looks odd: why not make the message itself part of the mailbox
protocol here, and leave the shmem as a implementation detail of the
mailbox driver?

> +Each protocol supported shall have a sub-node with corresponding compatible
> +as described in the following sections. If the platform supports dedicated
> +communication channel for a particular protocol, the 3 properties namely:
> +mboxes, mbox-names and shmem shall be present in the sub-node corresponding
> +to that protocol.
> +
> +Clock/Performance bindings for the clocks/OPPs based on SCMI Message Protocol
> +------------------------------------------------------------
> +
> +This binding uses the common clock binding[1].
> +
> +Required properties:
> +- #clock-cells : Should be 1. Contains the Clock ID value used by SCMI commands.
> +

How does the OS identify the fact that a subnode uses the clock binding?
Do you need to look for the #clock-cells property, or is this based on the
unit address?

          Arnd

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

* Re: [PATCH v3 04/22] firmware: arm_scmi: add basic driver infrastructure for SCMI
@ 2017-10-04 10:59     ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 10:59 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:

> +/**
> + * struct scmi_msg_hdr - Message(Tx/Rx) header
> + *
> + * @id: The identifier of the command being sent
> + * @protocol_id: The identifier of the protocol used to send @id command
> + * @seq: The token to identify the message. when a message/command returns,
> + *       the platform returns the whole message header unmodified including
> + *      the token.
> + */
> +struct scmi_msg_hdr {
> +       u8 id;
> +       u8 protocol_id;
> +       u16 seq;
> +       u32 status;
> +       bool poll_completion;
> +};

Is this structure part of the protocol, or just part of the linux
implementation?
If this is in the protocol, you should not have a 'bool' member in there, which
does not have a well-defined binary representation across architectures.

> +/*
> + * The SCP firmware providing SCM interface to OSPM and other agents must
> + * execute only in little-endian mode as per SCMI specification, so any buffers
> + * shared through SCMI should have their contents converted to little-endian
> + */

That is a very odd thing to put into a specification, are you sure it requires
a specific runtime endian-mode? I would bet that it only requires the protocol
to use little-endian data, so better describe it like that.

> +struct scmi_shared_mem {
> +       __le32 reserved;
> +       __le32 channel_status;
> +#define SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR     BIT(1)
> +#define SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE      BIT(0)
> +       __le32 reserved1[2];
> +       __le32 flags;
> +#define SCMI_SHMEM_FLAG_INTR_ENABLED   BIT(0)
> +       __le32 length;
> +       __le32 msg_header;
> +       u8 msg_payload[0];
> +};
> +
> +static int scmi_linux_errmap[] = {
> +       /* better than switch case as long as return value is continuous */
> +       0,                      /* SCMI_SUCCESS */
> +       -EOPNOTSUPP,            /* SCMI_ERR_SUPPORT */
> +       -EINVAL,                /* SCMI_ERR_PARAM */
> +       -EACCES,                /* SCMI_ERR_ACCESS */
> +       -ENOENT,                /* SCMI_ERR_ENTRY */
> +       -ERANGE,                /* SCMI_ERR_RANGE */
> +       -EBUSY,                 /* SCMI_ERR_BUSY */
> +       -ECOMM,                 /* SCMI_ERR_COMMS */
> +       -EIO,                   /* SCMI_ERR_GENERIC */
> +       -EREMOTEIO,             /* SCMI_ERR_HARDWARE */
> +       -EPROTO,                /* SCMI_ERR_PROTOCOL */
> +};

maybe make this 'const'.

> +static struct platform_driver scmi_driver = {
> +       .driver = {
> +                  .name = "arm-scmi",
> +                  .of_match_table = of_match_ptr(scmi_of_match),
> +                  },
> +       .probe = scmi_probe,
> +       .remove = scmi_remove,
> +};

The 'of_match_ptr' annotation probably causes an 'unused variable'
warning, better just drop that.

> +#if IS_REACHABLE(CONFIG_ARM_SCMI_PROTOCOL)
> +int scmi_handle_put(const struct scmi_handle *handle);
> +const struct scmi_handle *scmi_handle_get(struct device *dev);
> +const struct scmi_handle *devm_scmi_handle_get(struct device *dev);

IS_REACHABLE() can easily lead to confusion when the driver is
a loadable module but never gets used by a built-in driver. Maybe use
IS_ENABLED() here, and add a Kconfig symbol that other drivers
can depend on if you want them to optionally use it, like:

config MAYBE_ARM_SCMI_PROTOCOL
        default y if ARM_SCMI_PROTOCOL=n
        default ARM_SCMI_PROTOCOL

     Arnd

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

* Re: [PATCH v3 04/22] firmware: arm_scmi: add basic driver infrastructure for SCMI
@ 2017-10-04 10:59     ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 10:59 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:

> +/**
> + * struct scmi_msg_hdr - Message(Tx/Rx) header
> + *
> + * @id: The identifier of the command being sent
> + * @protocol_id: The identifier of the protocol used to send @id command
> + * @seq: The token to identify the message. when a message/command returns,
> + *       the platform returns the whole message header unmodified including
> + *      the token.
> + */
> +struct scmi_msg_hdr {
> +       u8 id;
> +       u8 protocol_id;
> +       u16 seq;
> +       u32 status;
> +       bool poll_completion;
> +};

Is this structure part of the protocol, or just part of the linux
implementation?
If this is in the protocol, you should not have a 'bool' member in there, which
does not have a well-defined binary representation across architectures.

> +/*
> + * The SCP firmware providing SCM interface to OSPM and other agents must
> + * execute only in little-endian mode as per SCMI specification, so any buffers
> + * shared through SCMI should have their contents converted to little-endian
> + */

That is a very odd thing to put into a specification, are you sure it requires
a specific runtime endian-mode? I would bet that it only requires the protocol
to use little-endian data, so better describe it like that.

> +struct scmi_shared_mem {
> +       __le32 reserved;
> +       __le32 channel_status;
> +#define SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR     BIT(1)
> +#define SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE      BIT(0)
> +       __le32 reserved1[2];
> +       __le32 flags;
> +#define SCMI_SHMEM_FLAG_INTR_ENABLED   BIT(0)
> +       __le32 length;
> +       __le32 msg_header;
> +       u8 msg_payload[0];
> +};
> +
> +static int scmi_linux_errmap[] = {
> +       /* better than switch case as long as return value is continuous */
> +       0,                      /* SCMI_SUCCESS */
> +       -EOPNOTSUPP,            /* SCMI_ERR_SUPPORT */
> +       -EINVAL,                /* SCMI_ERR_PARAM */
> +       -EACCES,                /* SCMI_ERR_ACCESS */
> +       -ENOENT,                /* SCMI_ERR_ENTRY */
> +       -ERANGE,                /* SCMI_ERR_RANGE */
> +       -EBUSY,                 /* SCMI_ERR_BUSY */
> +       -ECOMM,                 /* SCMI_ERR_COMMS */
> +       -EIO,                   /* SCMI_ERR_GENERIC */
> +       -EREMOTEIO,             /* SCMI_ERR_HARDWARE */
> +       -EPROTO,                /* SCMI_ERR_PROTOCOL */
> +};

maybe make this 'const'.

> +static struct platform_driver scmi_driver = {
> +       .driver = {
> +                  .name = "arm-scmi",
> +                  .of_match_table = of_match_ptr(scmi_of_match),
> +                  },
> +       .probe = scmi_probe,
> +       .remove = scmi_remove,
> +};

The 'of_match_ptr' annotation probably causes an 'unused variable'
warning, better just drop that.

> +#if IS_REACHABLE(CONFIG_ARM_SCMI_PROTOCOL)
> +int scmi_handle_put(const struct scmi_handle *handle);
> +const struct scmi_handle *scmi_handle_get(struct device *dev);
> +const struct scmi_handle *devm_scmi_handle_get(struct device *dev);

IS_REACHABLE() can easily lead to confusion when the driver is
a loadable module but never gets used by a built-in driver. Maybe use
IS_ENABLED() here, and add a Kconfig symbol that other drivers
can depend on if you want them to optionally use it, like:

config MAYBE_ARM_SCMI_PROTOCOL
        default y if ARM_SCMI_PROTOCOL=n
        default ARM_SCMI_PROTOCOL

     Arnd
--
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] 208+ messages in thread

* [PATCH v3 04/22] firmware: arm_scmi: add basic driver infrastructure for SCMI
@ 2017-10-04 10:59     ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 10:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:

> +/**
> + * struct scmi_msg_hdr - Message(Tx/Rx) header
> + *
> + * @id: The identifier of the command being sent
> + * @protocol_id: The identifier of the protocol used to send @id command
> + * @seq: The token to identify the message. when a message/command returns,
> + *       the platform returns the whole message header unmodified including
> + *      the token.
> + */
> +struct scmi_msg_hdr {
> +       u8 id;
> +       u8 protocol_id;
> +       u16 seq;
> +       u32 status;
> +       bool poll_completion;
> +};

Is this structure part of the protocol, or just part of the linux
implementation?
If this is in the protocol, you should not have a 'bool' member in there, which
does not have a well-defined binary representation across architectures.

> +/*
> + * The SCP firmware providing SCM interface to OSPM and other agents must
> + * execute only in little-endian mode as per SCMI specification, so any buffers
> + * shared through SCMI should have their contents converted to little-endian
> + */

That is a very odd thing to put into a specification, are you sure it requires
a specific runtime endian-mode? I would bet that it only requires the protocol
to use little-endian data, so better describe it like that.

> +struct scmi_shared_mem {
> +       __le32 reserved;
> +       __le32 channel_status;
> +#define SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR     BIT(1)
> +#define SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE      BIT(0)
> +       __le32 reserved1[2];
> +       __le32 flags;
> +#define SCMI_SHMEM_FLAG_INTR_ENABLED   BIT(0)
> +       __le32 length;
> +       __le32 msg_header;
> +       u8 msg_payload[0];
> +};
> +
> +static int scmi_linux_errmap[] = {
> +       /* better than switch case as long as return value is continuous */
> +       0,                      /* SCMI_SUCCESS */
> +       -EOPNOTSUPP,            /* SCMI_ERR_SUPPORT */
> +       -EINVAL,                /* SCMI_ERR_PARAM */
> +       -EACCES,                /* SCMI_ERR_ACCESS */
> +       -ENOENT,                /* SCMI_ERR_ENTRY */
> +       -ERANGE,                /* SCMI_ERR_RANGE */
> +       -EBUSY,                 /* SCMI_ERR_BUSY */
> +       -ECOMM,                 /* SCMI_ERR_COMMS */
> +       -EIO,                   /* SCMI_ERR_GENERIC */
> +       -EREMOTEIO,             /* SCMI_ERR_HARDWARE */
> +       -EPROTO,                /* SCMI_ERR_PROTOCOL */
> +};

maybe make this 'const'.

> +static struct platform_driver scmi_driver = {
> +       .driver = {
> +                  .name = "arm-scmi",
> +                  .of_match_table = of_match_ptr(scmi_of_match),
> +                  },
> +       .probe = scmi_probe,
> +       .remove = scmi_remove,
> +};

The 'of_match_ptr' annotation probably causes an 'unused variable'
warning, better just drop that.

> +#if IS_REACHABLE(CONFIG_ARM_SCMI_PROTOCOL)
> +int scmi_handle_put(const struct scmi_handle *handle);
> +const struct scmi_handle *scmi_handle_get(struct device *dev);
> +const struct scmi_handle *devm_scmi_handle_get(struct device *dev);

IS_REACHABLE() can easily lead to confusion when the driver is
a loadable module but never gets used by a built-in driver. Maybe use
IS_ENABLED() here, and add a Kconfig symbol that other drivers
can depend on if you want them to optionally use it, like:

config MAYBE_ARM_SCMI_PROTOCOL
        default y if ARM_SCMI_PROTOCOL=n
        default ARM_SCMI_PROTOCOL

     Arnd

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

* Re: [PATCH v3 10/22] firmware: arm_scmi: probe and initialise all the supported protocols
@ 2017-10-04 11:06     ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 11:06 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> +static const struct scmi_protocol_match scmi_protocols[] = {
> +       {
> +               .protocol_id = SCMI_PROTOCOL_PERF,
> +               .fn = scmi_perf_protocol_init,
> +               .name = "scmi-cpufreq",
> +       }, {
> +               .protocol_id = SCMI_PROTOCOL_CLOCK,
> +               .fn = scmi_clock_protocol_init,
> +               .name = "scmi-clocks",
> +       }, {
> +               .protocol_id = SCMI_PROTOCOL_POWER,
> +               .fn = scmi_power_protocol_init,
> +               .name = "scmi-power-domain",
> +       }, {
> +               .protocol_id = SCMI_PROTOCOL_SENSOR,
> +               .fn = scmi_sensors_protocol_init,
> +               .name = "scmi-hwmon",
> +       },
> +       {}
> +};

This looks backwards from what we do elsewhere in the kernel,
and could be considered a layering violation: it requires a generic
part of of the driver to know about all the more specific ones,
and it means that we have to modify the global table here each
time we add another protocol.

Can you rewrite this to allow dynamic registration of the protocols?

       Arnd

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

* Re: [PATCH v3 10/22] firmware: arm_scmi: probe and initialise all the supported protocols
@ 2017-10-04 11:06     ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 11:06 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
> +static const struct scmi_protocol_match scmi_protocols[] = {
> +       {
> +               .protocol_id = SCMI_PROTOCOL_PERF,
> +               .fn = scmi_perf_protocol_init,
> +               .name = "scmi-cpufreq",
> +       }, {
> +               .protocol_id = SCMI_PROTOCOL_CLOCK,
> +               .fn = scmi_clock_protocol_init,
> +               .name = "scmi-clocks",
> +       }, {
> +               .protocol_id = SCMI_PROTOCOL_POWER,
> +               .fn = scmi_power_protocol_init,
> +               .name = "scmi-power-domain",
> +       }, {
> +               .protocol_id = SCMI_PROTOCOL_SENSOR,
> +               .fn = scmi_sensors_protocol_init,
> +               .name = "scmi-hwmon",
> +       },
> +       {}
> +};

This looks backwards from what we do elsewhere in the kernel,
and could be considered a layering violation: it requires a generic
part of of the driver to know about all the more specific ones,
and it means that we have to modify the global table here each
time we add another protocol.

Can you rewrite this to allow dynamic registration of the protocols?

       Arnd
--
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] 208+ messages in thread

* [PATCH v3 10/22] firmware: arm_scmi: probe and initialise all the supported protocols
@ 2017-10-04 11:06     ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 11:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> +static const struct scmi_protocol_match scmi_protocols[] = {
> +       {
> +               .protocol_id = SCMI_PROTOCOL_PERF,
> +               .fn = scmi_perf_protocol_init,
> +               .name = "scmi-cpufreq",
> +       }, {
> +               .protocol_id = SCMI_PROTOCOL_CLOCK,
> +               .fn = scmi_clock_protocol_init,
> +               .name = "scmi-clocks",
> +       }, {
> +               .protocol_id = SCMI_PROTOCOL_POWER,
> +               .fn = scmi_power_protocol_init,
> +               .name = "scmi-power-domain",
> +       }, {
> +               .protocol_id = SCMI_PROTOCOL_SENSOR,
> +               .fn = scmi_sensors_protocol_init,
> +               .name = "scmi-hwmon",
> +       },
> +       {}
> +};

This looks backwards from what we do elsewhere in the kernel,
and could be considered a layering violation: it requires a generic
part of of the driver to know about all the more specific ones,
and it means that we have to modify the global table here each
time we add another protocol.

Can you rewrite this to allow dynamic registration of the protocols?

       Arnd

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

* Re: [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-10-04 11:07       ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-04 11:07 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Rob Herring, Mark Rutland

Hi Arnd,

Thanks for taking a look at this.

On 04/10/17 11:50, Arnd Bergmann wrote:
> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> +
>> +The SCMI is intended to allow agents such as OSPM to manage various functions
>> +that are provided by the hardware platform it is running on, including power
>> +and performance functions.
>> +
>> +This binding is intended to define the interface the firmware implementing
>> +the SCMI as described in ARM document number ARM DUI 0922B ("ARM System Control
>> +and Management Interface Platform Design Document")[0] provide for OSPM in
>> +the device tree.
>> +
>> +Required properties:
>> +
>> +The scmi node with the following properties shall be under the /firmware/ node.
>> +
>> +- compatible : shall be "arm,scmi"
>> +- mboxes: List of phandle and mailbox channel specifiers. It should contain
>> +         exactly one or two mailboxes, one for transmitting messages("tx")
>> +         and another optional for receiving the notifications("rx") if
>> +         supported.
>> +- mbox-names: shall be "tx" or "rx"
> 
> The example below does not have the mbox-names property. If you require
> exactly two mailboxes, why do you need the names anyway?
> 

Good question. I can drop it, but would like to keep in case we need to
extend it in future. We can always use then to identify.

> However, your example does have a #addresss-cells/#size-cells
> property that are not documented here. Please add them here as either
> optional or required, and describe what the permitted values are and
> how the address is interpreted.
> 

Ah right, I didn't notice that. I will add it. It was added to provide
the protocol number in "reg" property.

>> +- shmem : List of phandle pointing to the shared memory(SHM) area as per
>> +         generic mailbox client binding.
>> +
>> +See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details
>> +about the generic mailbox controller and client driver bindings.
>> +
>> +The mailbox is the only permitted method of calling the SCMI firmware.
>> +Mailbox doorbell is used as a mechanism to alert the presence of a
>> +messages and/or notification.
> 
> This looks odd: why not make the message itself part of the mailbox
> protocol here, and leave the shmem as a implementation detail of the
> mailbox driver?
> 

I am not sure if I follow you here. But generally shmem can be memory
carved out of anything in the system and it's dependent on the protocol
and the remote firmware rather than the mailbox hardware itself.

>> +Each protocol supported shall have a sub-node with corresponding compatible
>> +as described in the following sections. If the platform supports dedicated
>> +communication channel for a particular protocol, the 3 properties namely:
>> +mboxes, mbox-names and shmem shall be present in the sub-node corresponding
>> +to that protocol.
>> +
>> +Clock/Performance bindings for the clocks/OPPs based on SCMI Message Protocol
>> +------------------------------------------------------------
>> +
>> +This binding uses the common clock binding[1].
>> +
>> +Required properties:
>> +- #clock-cells : Should be 1. Contains the Clock ID value used by SCMI commands.
>> +
> 
> How does the OS identify the fact that a subnode uses the clock binding?
> Do you need to look for the #clock-cells property, or is this based on the
> unit address?
> 

Yes it depends on #clock-cells property. That's the main reason for
adding #clock-cells
-- 
Regards,
Sudeep

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

* Re: [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-10-04 11:07       ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-04 11:07 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Rob Herring, Mark Rutland

Hi Arnd,

Thanks for taking a look at this.

On 04/10/17 11:50, Arnd Bergmann wrote:
> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
>> +
>> +The SCMI is intended to allow agents such as OSPM to manage various functions
>> +that are provided by the hardware platform it is running on, including power
>> +and performance functions.
>> +
>> +This binding is intended to define the interface the firmware implementing
>> +the SCMI as described in ARM document number ARM DUI 0922B ("ARM System Control
>> +and Management Interface Platform Design Document")[0] provide for OSPM in
>> +the device tree.
>> +
>> +Required properties:
>> +
>> +The scmi node with the following properties shall be under the /firmware/ node.
>> +
>> +- compatible : shall be "arm,scmi"
>> +- mboxes: List of phandle and mailbox channel specifiers. It should contain
>> +         exactly one or two mailboxes, one for transmitting messages("tx")
>> +         and another optional for receiving the notifications("rx") if
>> +         supported.
>> +- mbox-names: shall be "tx" or "rx"
> 
> The example below does not have the mbox-names property. If you require
> exactly two mailboxes, why do you need the names anyway?
> 

Good question. I can drop it, but would like to keep in case we need to
extend it in future. We can always use then to identify.

> However, your example does have a #addresss-cells/#size-cells
> property that are not documented here. Please add them here as either
> optional or required, and describe what the permitted values are and
> how the address is interpreted.
> 

Ah right, I didn't notice that. I will add it. It was added to provide
the protocol number in "reg" property.

>> +- shmem : List of phandle pointing to the shared memory(SHM) area as per
>> +         generic mailbox client binding.
>> +
>> +See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details
>> +about the generic mailbox controller and client driver bindings.
>> +
>> +The mailbox is the only permitted method of calling the SCMI firmware.
>> +Mailbox doorbell is used as a mechanism to alert the presence of a
>> +messages and/or notification.
> 
> This looks odd: why not make the message itself part of the mailbox
> protocol here, and leave the shmem as a implementation detail of the
> mailbox driver?
> 

I am not sure if I follow you here. But generally shmem can be memory
carved out of anything in the system and it's dependent on the protocol
and the remote firmware rather than the mailbox hardware itself.

>> +Each protocol supported shall have a sub-node with corresponding compatible
>> +as described in the following sections. If the platform supports dedicated
>> +communication channel for a particular protocol, the 3 properties namely:
>> +mboxes, mbox-names and shmem shall be present in the sub-node corresponding
>> +to that protocol.
>> +
>> +Clock/Performance bindings for the clocks/OPPs based on SCMI Message Protocol
>> +------------------------------------------------------------
>> +
>> +This binding uses the common clock binding[1].
>> +
>> +Required properties:
>> +- #clock-cells : Should be 1. Contains the Clock ID value used by SCMI commands.
>> +
> 
> How does the OS identify the fact that a subnode uses the clock binding?
> Do you need to look for the #clock-cells property, or is this based on the
> unit address?
> 

Yes it depends on #clock-cells property. That's the main reason for
adding #clock-cells
-- 
Regards,
Sudeep
--
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] 208+ messages in thread

* [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-10-04 11:07       ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-04 11:07 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Arnd,

Thanks for taking a look at this.

On 04/10/17 11:50, Arnd Bergmann wrote:
> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> +
>> +The SCMI is intended to allow agents such as OSPM to manage various functions
>> +that are provided by the hardware platform it is running on, including power
>> +and performance functions.
>> +
>> +This binding is intended to define the interface the firmware implementing
>> +the SCMI as described in ARM document number ARM DUI 0922B ("ARM System Control
>> +and Management Interface Platform Design Document")[0] provide for OSPM in
>> +the device tree.
>> +
>> +Required properties:
>> +
>> +The scmi node with the following properties shall be under the /firmware/ node.
>> +
>> +- compatible : shall be "arm,scmi"
>> +- mboxes: List of phandle and mailbox channel specifiers. It should contain
>> +         exactly one or two mailboxes, one for transmitting messages("tx")
>> +         and another optional for receiving the notifications("rx") if
>> +         supported.
>> +- mbox-names: shall be "tx" or "rx"
> 
> The example below does not have the mbox-names property. If you require
> exactly two mailboxes, why do you need the names anyway?
> 

Good question. I can drop it, but would like to keep in case we need to
extend it in future. We can always use then to identify.

> However, your example does have a #addresss-cells/#size-cells
> property that are not documented here. Please add them here as either
> optional or required, and describe what the permitted values are and
> how the address is interpreted.
> 

Ah right, I didn't notice that. I will add it. It was added to provide
the protocol number in "reg" property.

>> +- shmem : List of phandle pointing to the shared memory(SHM) area as per
>> +         generic mailbox client binding.
>> +
>> +See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details
>> +about the generic mailbox controller and client driver bindings.
>> +
>> +The mailbox is the only permitted method of calling the SCMI firmware.
>> +Mailbox doorbell is used as a mechanism to alert the presence of a
>> +messages and/or notification.
> 
> This looks odd: why not make the message itself part of the mailbox
> protocol here, and leave the shmem as a implementation detail of the
> mailbox driver?
> 

I am not sure if I follow you here. But generally shmem can be memory
carved out of anything in the system and it's dependent on the protocol
and the remote firmware rather than the mailbox hardware itself.

>> +Each protocol supported shall have a sub-node with corresponding compatible
>> +as described in the following sections. If the platform supports dedicated
>> +communication channel for a particular protocol, the 3 properties namely:
>> +mboxes, mbox-names and shmem shall be present in the sub-node corresponding
>> +to that protocol.
>> +
>> +Clock/Performance bindings for the clocks/OPPs based on SCMI Message Protocol
>> +------------------------------------------------------------
>> +
>> +This binding uses the common clock binding[1].
>> +
>> +Required properties:
>> +- #clock-cells : Should be 1. Contains the Clock ID value used by SCMI commands.
>> +
> 
> How does the OS identify the fact that a subnode uses the clock binding?
> Do you need to look for the #clock-cells property, or is this based on the
> unit address?
> 

Yes it depends on #clock-cells property. That's the main reason for
adding #clock-cells
-- 
Regards,
Sudeep

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

* Re: [PATCH v3 11/22] firmware: arm_scmi: add support for polling based SCMI transfers
@ 2017-10-04 11:13     ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 11:13 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> It would be useful to have options to perform some SCMI transfers
> atomically by polling for the completion flag instead of interrupt
> driven. The SCMI specification has option to disable the interrupt and
> poll for the completion flag in the shared memory.
>
> This patch adds support for polling based SCMI transfers using that
> option. This might be used for uninterrupted/atomic DVFS operations
> from the scheduler context.

multi-millisecond timeouts from inside the scheduler sound like a
really bad idea. Could this maybe get changed to an asynchronous
operation?

> +       if (xfer->hdr.poll_completion) {
> +               timeout = info->desc->max_rx_timeout_ms * 100;
> +               while (!scmi_xfer_poll_done(info, xfer) && timeout--)
> +                       udelay(10);

The timeout calculation is bad as well, since both the
scmi_xfer_poll_done() call and udelay() can take much longer
than the 10 microsecond delay that you use for the calculation.

If you want to do a timeout check like this, it should generally
be done using ktime_get()/ktime_add()/ktime_before().

       Arnd

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

* Re: [PATCH v3 11/22] firmware: arm_scmi: add support for polling based SCMI transfers
@ 2017-10-04 11:13     ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 11:13 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
> It would be useful to have options to perform some SCMI transfers
> atomically by polling for the completion flag instead of interrupt
> driven. The SCMI specification has option to disable the interrupt and
> poll for the completion flag in the shared memory.
>
> This patch adds support for polling based SCMI transfers using that
> option. This might be used for uninterrupted/atomic DVFS operations
> from the scheduler context.

multi-millisecond timeouts from inside the scheduler sound like a
really bad idea. Could this maybe get changed to an asynchronous
operation?

> +       if (xfer->hdr.poll_completion) {
> +               timeout = info->desc->max_rx_timeout_ms * 100;
> +               while (!scmi_xfer_poll_done(info, xfer) && timeout--)
> +                       udelay(10);

The timeout calculation is bad as well, since both the
scmi_xfer_poll_done() call and udelay() can take much longer
than the 10 microsecond delay that you use for the calculation.

If you want to do a timeout check like this, it should generally
be done using ktime_get()/ktime_add()/ktime_before().

       Arnd
--
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] 208+ messages in thread

* [PATCH v3 11/22] firmware: arm_scmi: add support for polling based SCMI transfers
@ 2017-10-04 11:13     ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 11:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> It would be useful to have options to perform some SCMI transfers
> atomically by polling for the completion flag instead of interrupt
> driven. The SCMI specification has option to disable the interrupt and
> poll for the completion flag in the shared memory.
>
> This patch adds support for polling based SCMI transfers using that
> option. This might be used for uninterrupted/atomic DVFS operations
> from the scheduler context.

multi-millisecond timeouts from inside the scheduler sound like a
really bad idea. Could this maybe get changed to an asynchronous
operation?

> +       if (xfer->hdr.poll_completion) {
> +               timeout = info->desc->max_rx_timeout_ms * 100;
> +               while (!scmi_xfer_poll_done(info, xfer) && timeout--)
> +                       udelay(10);

The timeout calculation is bad as well, since both the
scmi_xfer_poll_done() call and udelay() can take much longer
than the 10 microsecond delay that you use for the calculation.

If you want to do a timeout check like this, it should generally
be done using ktime_get()/ktime_add()/ktime_before().

       Arnd

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

* Re: [PATCH v3 11/22] firmware: arm_scmi: add support for polling based SCMI transfers
  2017-10-04 11:13     ` Arnd Bergmann
@ 2017-10-04 11:18       ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-04 11:18 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar



On 04/10/17 12:13, Arnd Bergmann wrote:
> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> It would be useful to have options to perform some SCMI transfers
>> atomically by polling for the completion flag instead of interrupt
>> driven. The SCMI specification has option to disable the interrupt and
>> poll for the completion flag in the shared memory.
>>
>> This patch adds support for polling based SCMI transfers using that
>> option. This might be used for uninterrupted/atomic DVFS operations
>> from the scheduler context.
> 
> multi-millisecond timeouts from inside the scheduler sound like a
> really bad idea. Could this maybe get changed to an asynchronous
> operation?
> 

We already support asynchronous version. This is mainly to support fast
DVFS switching done at context switch. I can reduce the timeouts to
few uS as the whole idea of fast dvfs is we can't return or schedule out
of this function. Typically the remote should see the request in < 10 uS
and acknowledge it.

>> +       if (xfer->hdr.poll_completion) {
>> +               timeout = info->desc->max_rx_timeout_ms * 100;
>> +               while (!scmi_xfer_poll_done(info, xfer) && timeout--)
>> +                       udelay(10);
> 
> The timeout calculation is bad as well, since both the
> scmi_xfer_poll_done() call and udelay() can take much longer
> than the 10 microsecond delay that you use for the calculation.
> 

Ah, agreed. I will change it to few uS as that's what is expected.

> If you want to do a timeout check like this, it should generally
> be done using ktime_get()/ktime_add()/ktime_before().
> 

Good idea, will try to use that.

-- 
Regards,
Sudeep

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

* [PATCH v3 11/22] firmware: arm_scmi: add support for polling based SCMI transfers
@ 2017-10-04 11:18       ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-04 11:18 UTC (permalink / raw)
  To: linux-arm-kernel



On 04/10/17 12:13, Arnd Bergmann wrote:
> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> It would be useful to have options to perform some SCMI transfers
>> atomically by polling for the completion flag instead of interrupt
>> driven. The SCMI specification has option to disable the interrupt and
>> poll for the completion flag in the shared memory.
>>
>> This patch adds support for polling based SCMI transfers using that
>> option. This might be used for uninterrupted/atomic DVFS operations
>> from the scheduler context.
> 
> multi-millisecond timeouts from inside the scheduler sound like a
> really bad idea. Could this maybe get changed to an asynchronous
> operation?
> 

We already support asynchronous version. This is mainly to support fast
DVFS switching done at context switch. I can reduce the timeouts to
few uS as the whole idea of fast dvfs is we can't return or schedule out
of this function. Typically the remote should see the request in < 10 uS
and acknowledge it.

>> +       if (xfer->hdr.poll_completion) {
>> +               timeout = info->desc->max_rx_timeout_ms * 100;
>> +               while (!scmi_xfer_poll_done(info, xfer) && timeout--)
>> +                       udelay(10);
> 
> The timeout calculation is bad as well, since both the
> scmi_xfer_poll_done() call and udelay() can take much longer
> than the 10 microsecond delay that you use for the calculation.
> 

Ah, agreed. I will change it to few uS as that's what is expected.

> If you want to do a timeout check like this, it should generally
> be done using ktime_get()/ktime_add()/ktime_before().
> 

Good idea, will try to use that.

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 04/22] firmware: arm_scmi: add basic driver infrastructure for SCMI
@ 2017-10-04 11:19     ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 11:19 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:

> +static int scmi_mbox_free_channel(struct scmi_info *info)
> +{
> +       if (!IS_ERR_OR_NULL(info->tx_chan)) {
> +               mbox_free_channel(info->tx_chan);
> +               info->tx_chan = NULL;
> +       }
> +
> +       return 0;
> +}

Any use of IS_ERR_OR_NULL() tends to be an indication of a bad API
design. Please make a decision about what you want to store in
info->tx_chan and stick with it.

Usually, we don't store error pointers in permanent data structures.
If you can deal with tx_chan being absent here, then you can just
store NULL into it when you don't have one, otherwise you should
make sure you never call this and fail the probe function earlier.

      Arnd

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

* Re: [PATCH v3 04/22] firmware: arm_scmi: add basic driver infrastructure for SCMI
@ 2017-10-04 11:19     ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 11:19 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:

> +static int scmi_mbox_free_channel(struct scmi_info *info)
> +{
> +       if (!IS_ERR_OR_NULL(info->tx_chan)) {
> +               mbox_free_channel(info->tx_chan);
> +               info->tx_chan = NULL;
> +       }
> +
> +       return 0;
> +}

Any use of IS_ERR_OR_NULL() tends to be an indication of a bad API
design. Please make a decision about what you want to store in
info->tx_chan and stick with it.

Usually, we don't store error pointers in permanent data structures.
If you can deal with tx_chan being absent here, then you can just
store NULL into it when you don't have one, otherwise you should
make sure you never call this and fail the probe function earlier.

      Arnd
--
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] 208+ messages in thread

* [PATCH v3 04/22] firmware: arm_scmi: add basic driver infrastructure for SCMI
@ 2017-10-04 11:19     ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 11:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:

> +static int scmi_mbox_free_channel(struct scmi_info *info)
> +{
> +       if (!IS_ERR_OR_NULL(info->tx_chan)) {
> +               mbox_free_channel(info->tx_chan);
> +               info->tx_chan = NULL;
> +       }
> +
> +       return 0;
> +}

Any use of IS_ERR_OR_NULL() tends to be an indication of a bad API
design. Please make a decision about what you want to store in
info->tx_chan and stick with it.

Usually, we don't store error pointers in permanent data structures.
If you can deal with tx_chan being absent here, then you can just
store NULL into it when you don't have one, otherwise you should
make sure you never call this and fail the probe function earlier.

      Arnd

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

* Re: [PATCH v3 15/22] firmware: arm_scmi: abstract mailbox interface
@ 2017-10-04 11:24     ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 11:24 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> Some of the mailbox controller expects controller specific data in order
> to implement simple doorbell mechanism as expected by SCMI specification.
>
> This patch creates a shim layer to abstract the mailbox interface so
> that it can support any mailbox controller. It also provides default
> implementation which maps to standard mailbox client APIs, so that
> controllers implementing doorbell mechanism need not require any
> additional layer.
>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>

Another level? Now we have three levels of stacked mailboxes, with
the highest level being the combined mailbox/memory, then the shim,
and below it the hardware mailbox.

Can you try to come up with a way to do this with fewer abstractions?

Maybe you could assume that the mailbox itself can take variable-length
data packets, and then use the shim here for those that require
something else?

        Arnd

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

* Re: [PATCH v3 15/22] firmware: arm_scmi: abstract mailbox interface
@ 2017-10-04 11:24     ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 11:24 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
> Some of the mailbox controller expects controller specific data in order
> to implement simple doorbell mechanism as expected by SCMI specification.
>
> This patch creates a shim layer to abstract the mailbox interface so
> that it can support any mailbox controller. It also provides default
> implementation which maps to standard mailbox client APIs, so that
> controllers implementing doorbell mechanism need not require any
> additional layer.
>
> Cc: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
> Signed-off-by: Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org>

Another level? Now we have three levels of stacked mailboxes, with
the highest level being the combined mailbox/memory, then the shim,
and below it the hardware mailbox.

Can you try to come up with a way to do this with fewer abstractions?

Maybe you could assume that the mailbox itself can take variable-length
data packets, and then use the shim here for those that require
something else?

        Arnd
--
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] 208+ messages in thread

* [PATCH v3 15/22] firmware: arm_scmi: abstract mailbox interface
@ 2017-10-04 11:24     ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 11:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> Some of the mailbox controller expects controller specific data in order
> to implement simple doorbell mechanism as expected by SCMI specification.
>
> This patch creates a shim layer to abstract the mailbox interface so
> that it can support any mailbox controller. It also provides default
> implementation which maps to standard mailbox client APIs, so that
> controllers implementing doorbell mechanism need not require any
> additional layer.
>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>

Another level? Now we have three levels of stacked mailboxes, with
the highest level being the combined mailbox/memory, then the shim,
and below it the hardware mailbox.

Can you try to come up with a way to do this with fewer abstractions?

Maybe you could assume that the mailbox itself can take variable-length
data packets, and then use the shim here for those that require
something else?

        Arnd

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

* Re: [PATCH v3 21/22] cpufreq: add support for CPU DVFS based on SCMI message protocol
@ 2017-10-04 11:30     ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 11:30 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Rafael J. Wysocki, Viresh Kumar, linux-pm

> +static int scmi_cpufreq_probe(struct platform_device *pdev)
> +{
> +       int ret;
> +
> +       handle = devm_scmi_handle_get(&pdev->dev);
> +
> +       if (IS_ERR_OR_NULL(handle) || !handle->perf_ops)
> +               return -EPROBE_DEFER;

As mentioned before, never create an interface that needs to use
IS_ERR_OR_NULL(), make it return either NULL on error, or always
have an error code.

> +
> +static struct platform_driver scmi_cpufreq_platdrv = {
> +       .driver = {
> +               .name   = "scmi-cpufreq",
> +       },
> +       .probe          = scmi_cpufreq_probe,
> +       .remove         = scmi_cpufreq_remove,
> +};

You appear to have split this driver into the 'cpufreq' side and
the 'protocol' handler in a different file. I already commented that
the way the main scmi driver knows about all the protocols looks
bad, here we can see another aspect of the same problem.

Rather than manually register a platform_device for the purpose
of connecting it to the cpufreq driver, there should be a way
to dynamically register the protocol from the cpufreq driver
and then have both in the same file.

      Arnd

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

* Re: [PATCH v3 21/22] cpufreq: add support for CPU DVFS based on SCMI message protocol
@ 2017-10-04 11:30     ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 11:30 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Rafael J. Wysocki, Viresh Kumar, linux-pm-u79uwXL29TY76Z2rM5mHXA

> +static int scmi_cpufreq_probe(struct platform_device *pdev)
> +{
> +       int ret;
> +
> +       handle = devm_scmi_handle_get(&pdev->dev);
> +
> +       if (IS_ERR_OR_NULL(handle) || !handle->perf_ops)
> +               return -EPROBE_DEFER;

As mentioned before, never create an interface that needs to use
IS_ERR_OR_NULL(), make it return either NULL on error, or always
have an error code.

> +
> +static struct platform_driver scmi_cpufreq_platdrv = {
> +       .driver = {
> +               .name   = "scmi-cpufreq",
> +       },
> +       .probe          = scmi_cpufreq_probe,
> +       .remove         = scmi_cpufreq_remove,
> +};

You appear to have split this driver into the 'cpufreq' side and
the 'protocol' handler in a different file. I already commented that
the way the main scmi driver knows about all the protocols looks
bad, here we can see another aspect of the same problem.

Rather than manually register a platform_device for the purpose
of connecting it to the cpufreq driver, there should be a way
to dynamically register the protocol from the cpufreq driver
and then have both in the same file.

      Arnd
--
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] 208+ messages in thread

* [PATCH v3 21/22] cpufreq: add support for CPU DVFS based on SCMI message protocol
@ 2017-10-04 11:30     ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 11:30 UTC (permalink / raw)
  To: linux-arm-kernel

> +static int scmi_cpufreq_probe(struct platform_device *pdev)
> +{
> +       int ret;
> +
> +       handle = devm_scmi_handle_get(&pdev->dev);
> +
> +       if (IS_ERR_OR_NULL(handle) || !handle->perf_ops)
> +               return -EPROBE_DEFER;

As mentioned before, never create an interface that needs to use
IS_ERR_OR_NULL(), make it return either NULL on error, or always
have an error code.

> +
> +static struct platform_driver scmi_cpufreq_platdrv = {
> +       .driver = {
> +               .name   = "scmi-cpufreq",
> +       },
> +       .probe          = scmi_cpufreq_probe,
> +       .remove         = scmi_cpufreq_remove,
> +};

You appear to have split this driver into the 'cpufreq' side and
the 'protocol' handler in a different file. I already commented that
the way the main scmi driver knows about all the protocols looks
bad, here we can see another aspect of the same problem.

Rather than manually register a platform_device for the purpose
of connecting it to the cpufreq driver, there should be a way
to dynamically register the protocol from the cpufreq driver
and then have both in the same file.

      Arnd

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

* Re: [PATCH v3 15/22] firmware: arm_scmi: abstract mailbox interface
@ 2017-10-04 11:32       ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-04 11:32 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar



On 04/10/17 12:24, Arnd Bergmann wrote:
> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> Some of the mailbox controller expects controller specific data in order
>> to implement simple doorbell mechanism as expected by SCMI specification.
>>
>> This patch creates a shim layer to abstract the mailbox interface so
>> that it can support any mailbox controller. It also provides default
>> implementation which maps to standard mailbox client APIs, so that
>> controllers implementing doorbell mechanism need not require any
>> additional layer.
>>
>> Cc: Arnd Bergmann <arnd@arndb.de>
>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> 
> Another level? Now we have three levels of stacked mailboxes, with
> the highest level being the combined mailbox/memory, then the shim,
> and below it the hardware mailbox.
> 
> Can you try to come up with a way to do this with fewer abstractions?
> 

I completely agree with you. I was against this but Jassi recommended
this. I just wanted this SCMI to work with mailbox controllers that
support simple doorbell mechanism as specified in the specification but
Jassi disagrees with that.

> Maybe you could assume that the mailbox itself can take variable-length
> data packets, and then use the shim here for those that require
> something else?
> 

As per SCMI specification, we pass all the data in shared memory and it
just expects to use a simple doorbell feature from hardware mailbox
controllers. It's done that way intentionally to avoid dependency on h/w
and we for sure will have variety of it and that defeats the purpose
of this standard specification.

Also, I have added shim only for specific controllers that need them.
E.g. ARM MHU as Jassi disagreed to add doorbell mechanism to that.
mbox_if provides default implementation that just calls direct mailbox
APIs.

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 15/22] firmware: arm_scmi: abstract mailbox interface
@ 2017-10-04 11:32       ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-04 11:32 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar



On 04/10/17 12:24, Arnd Bergmann wrote:
> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
>> Some of the mailbox controller expects controller specific data in order
>> to implement simple doorbell mechanism as expected by SCMI specification.
>>
>> This patch creates a shim layer to abstract the mailbox interface so
>> that it can support any mailbox controller. It also provides default
>> implementation which maps to standard mailbox client APIs, so that
>> controllers implementing doorbell mechanism need not require any
>> additional layer.
>>
>> Cc: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
>> Signed-off-by: Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org>
> 
> Another level? Now we have three levels of stacked mailboxes, with
> the highest level being the combined mailbox/memory, then the shim,
> and below it the hardware mailbox.
> 
> Can you try to come up with a way to do this with fewer abstractions?
> 

I completely agree with you. I was against this but Jassi recommended
this. I just wanted this SCMI to work with mailbox controllers that
support simple doorbell mechanism as specified in the specification but
Jassi disagrees with that.

> Maybe you could assume that the mailbox itself can take variable-length
> data packets, and then use the shim here for those that require
> something else?
> 

As per SCMI specification, we pass all the data in shared memory and it
just expects to use a simple doorbell feature from hardware mailbox
controllers. It's done that way intentionally to avoid dependency on h/w
and we for sure will have variety of it and that defeats the purpose
of this standard specification.

Also, I have added shim only for specific controllers that need them.
E.g. ARM MHU as Jassi disagreed to add doorbell mechanism to that.
mbox_if provides default implementation that just calls direct mailbox
APIs.

-- 
Regards,
Sudeep
--
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] 208+ messages in thread

* [PATCH v3 15/22] firmware: arm_scmi: abstract mailbox interface
@ 2017-10-04 11:32       ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-04 11:32 UTC (permalink / raw)
  To: linux-arm-kernel



On 04/10/17 12:24, Arnd Bergmann wrote:
> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> Some of the mailbox controller expects controller specific data in order
>> to implement simple doorbell mechanism as expected by SCMI specification.
>>
>> This patch creates a shim layer to abstract the mailbox interface so
>> that it can support any mailbox controller. It also provides default
>> implementation which maps to standard mailbox client APIs, so that
>> controllers implementing doorbell mechanism need not require any
>> additional layer.
>>
>> Cc: Arnd Bergmann <arnd@arndb.de>
>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> 
> Another level? Now we have three levels of stacked mailboxes, with
> the highest level being the combined mailbox/memory, then the shim,
> and below it the hardware mailbox.
> 
> Can you try to come up with a way to do this with fewer abstractions?
> 

I completely agree with you. I was against this but Jassi recommended
this. I just wanted this SCMI to work with mailbox controllers that
support simple doorbell mechanism as specified in the specification but
Jassi disagrees with that.

> Maybe you could assume that the mailbox itself can take variable-length
> data packets, and then use the shim here for those that require
> something else?
> 

As per SCMI specification, we pass all the data in shared memory and it
just expects to use a simple doorbell feature from hardware mailbox
controllers. It's done that way intentionally to avoid dependency on h/w
and we for sure will have variety of it and that defeats the purpose
of this standard specification.

Also, I have added shim only for specific controllers that need them.
E.g. ARM MHU as Jassi disagreed to add doorbell mechanism to that.
mbox_if provides default implementation that just calls direct mailbox
APIs.

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
  2017-09-28 13:11   ` Sudeep Holla
@ 2017-10-04 11:36     ` Arnd Bergmann
  -1 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 11:36 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> This patch adds ARM MHU specific mailbox interface for SCMI.
>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>

This clearly needs an explanation why we need another driver.

> +union mhu_data {
> +       void *ptr;
> +       u32 val;
> +};
> +
> +static void mhu_tx_prepare(struct mbox_client *cl, void *m)
> +{
> +       struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
> +       union mhu_data tmp;
> +
> +       scmi_generic_tx_prepare(cinfo, m);
> +
> +       /* clear only the relavant bit */
> +       tmp.ptr = cinfo->priv;
> +       *(u32 *)m &= tmp.val;
> +}

Why do you use the first 32 bits of the pointer here? That doesn't
seem to make any sense, in particular on big-endian 64-bit
architectures.

> diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
> index 97285a22dfaa..bdc9c566e6c1 100644
> --- a/drivers/firmware/arm_scmi/driver.c
> +++ b/drivers/firmware/arm_scmi/driver.c
> @@ -648,6 +648,9 @@ EXPORT_SYMBOL_GPL(devm_scmi_handle_get);
>  /* Each compatible listed below must have descriptor associated with it */
>  static const struct of_device_id scmi_of_match[] = {
>         { .compatible = "arm,scmi", .data = &scmi_generic_desc },
> +#if IS_REACHABLE(CONFIG_ARM_MHU)
> +       { .compatible = "arm,mhu-scmi", .data = &mhu_scmi_desc },
> +#endif
>         { /* Sentinel */ },
>  };
>

This again is a bad abstraction, if the main part needs to know about
each mailbox that it could use.

Turn the registration around so rather than referring to an exported
symbol from mhu_scmi_desc.c in the main driver, you export
a symbol to register the operations and make the mhu
part its own module.

       Arnd

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

* [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-04 11:36     ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 11:36 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> This patch adds ARM MHU specific mailbox interface for SCMI.
>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>

This clearly needs an explanation why we need another driver.

> +union mhu_data {
> +       void *ptr;
> +       u32 val;
> +};
> +
> +static void mhu_tx_prepare(struct mbox_client *cl, void *m)
> +{
> +       struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
> +       union mhu_data tmp;
> +
> +       scmi_generic_tx_prepare(cinfo, m);
> +
> +       /* clear only the relavant bit */
> +       tmp.ptr = cinfo->priv;
> +       *(u32 *)m &= tmp.val;
> +}

Why do you use the first 32 bits of the pointer here? That doesn't
seem to make any sense, in particular on big-endian 64-bit
architectures.

> diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
> index 97285a22dfaa..bdc9c566e6c1 100644
> --- a/drivers/firmware/arm_scmi/driver.c
> +++ b/drivers/firmware/arm_scmi/driver.c
> @@ -648,6 +648,9 @@ EXPORT_SYMBOL_GPL(devm_scmi_handle_get);
>  /* Each compatible listed below must have descriptor associated with it */
>  static const struct of_device_id scmi_of_match[] = {
>         { .compatible = "arm,scmi", .data = &scmi_generic_desc },
> +#if IS_REACHABLE(CONFIG_ARM_MHU)
> +       { .compatible = "arm,mhu-scmi", .data = &mhu_scmi_desc },
> +#endif
>         { /* Sentinel */ },
>  };
>

This again is a bad abstraction, if the main part needs to know about
each mailbox that it could use.

Turn the registration around so rather than referring to an exported
symbol from mhu_scmi_desc.c in the main driver, you export
a symbol to register the operations and make the mhu
part its own module.

       Arnd

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

* Re: [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-04 11:48       ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-04 11:48 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar



On 04/10/17 12:36, Arnd Bergmann wrote:
> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> This patch adds ARM MHU specific mailbox interface for SCMI.
>>
>> Cc: Arnd Bergmann <arnd@arndb.de>
>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> 
> This clearly needs an explanation why we need another driver.
> 
Yes, I understand. I myself is not convinced that we need one. Jassi
disagrees to add support to use each bit as doorbell in the ARM MHU
driver though the MHU specification states it clearly(3.4.4 Message
Handling Unit (MHU) of Juno TRM)[1].

This shim was added to deal with that with I agree is wrong IMO but
Jassi thinks that's right way to deal with it.

-- 
Regards,
Sudeep


[1]
http://infocenter.arm.com/help/topic/com.arm.doc.ddi0515f/DDI0515F_juno_arm_development_platform_soc_trm.pdf

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

* Re: [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-04 11:48       ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-04 11:48 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar



On 04/10/17 12:36, Arnd Bergmann wrote:
> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
>> This patch adds ARM MHU specific mailbox interface for SCMI.
>>
>> Cc: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
>> Signed-off-by: Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org>
> 
> This clearly needs an explanation why we need another driver.
> 
Yes, I understand. I myself is not convinced that we need one. Jassi
disagrees to add support to use each bit as doorbell in the ARM MHU
driver though the MHU specification states it clearly(3.4.4 Message
Handling Unit (MHU) of Juno TRM)[1].

This shim was added to deal with that with I agree is wrong IMO but
Jassi thinks that's right way to deal with it.

-- 
Regards,
Sudeep


[1]
http://infocenter.arm.com/help/topic/com.arm.doc.ddi0515f/DDI0515F_juno_arm_development_platform_soc_trm.pdf
--
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] 208+ messages in thread

* [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-04 11:48       ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-04 11:48 UTC (permalink / raw)
  To: linux-arm-kernel



On 04/10/17 12:36, Arnd Bergmann wrote:
> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> This patch adds ARM MHU specific mailbox interface for SCMI.
>>
>> Cc: Arnd Bergmann <arnd@arndb.de>
>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> 
> This clearly needs an explanation why we need another driver.
> 
Yes, I understand. I myself is not convinced that we need one. Jassi
disagrees to add support to use each bit as doorbell in the ARM MHU
driver though the MHU specification states it clearly(3.4.4 Message
Handling Unit (MHU) of Juno TRM)[1].

This shim was added to deal with that with I agree is wrong IMO but
Jassi thinks that's right way to deal with it.

-- 
Regards,
Sudeep


[1]
http://infocenter.arm.com/help/topic/com.arm.doc.ddi0515f/DDI0515F_juno_arm_development_platform_soc_trm.pdf

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

* Re: [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-10-04 12:35         ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 12:35 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar, Rob Herring,
	Mark Rutland

On Wed, Oct 4, 2017 at 1:07 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> Hi Arnd,
>
> Thanks for taking a look at this.
>
> On 04/10/17 11:50, Arnd Bergmann wrote:
>> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>> +
>>> +The SCMI is intended to allow agents such as OSPM to manage various functions
>>> +that are provided by the hardware platform it is running on, including power
>>> +and performance functions.
>>> +
>>> +This binding is intended to define the interface the firmware implementing
>>> +the SCMI as described in ARM document number ARM DUI 0922B ("ARM System Control
>>> +and Management Interface Platform Design Document")[0] provide for OSPM in
>>> +the device tree.
>>> +
>>> +Required properties:
>>> +
>>> +The scmi node with the following properties shall be under the /firmware/ node.
>>> +
>>> +- compatible : shall be "arm,scmi"
>>> +- mboxes: List of phandle and mailbox channel specifiers. It should contain
>>> +         exactly one or two mailboxes, one for transmitting messages("tx")
>>> +         and another optional for receiving the notifications("rx") if
>>> +         supported.
>>> +- mbox-names: shall be "tx" or "rx"
>>
>> The example below does not have the mbox-names property. If you require
>> exactly two mailboxes, why do you need the names anyway?
>>
>
> Good question. I can drop it, but would like to keep in case we need to
> extend it in future. We can always use then to identify.

I don't think it's necessary, as long you always need to have the first two,
but it doesn't hurt either.

Just make the description match the example.

>> However, your example does have a #addresss-cells/#size-cells
>> property that are not documented here. Please add them here as either
>> optional or required, and describe what the permitted values are and
>> how the address is interpreted.
>>
>
> Ah right, I didn't notice that. I will add it. It was added to provide
> the protocol number in "reg" property.
...
>> How does the OS identify the fact that a subnode uses the clock binding?
>> Do you need to look for the #clock-cells property, or is this based on the
>> unit address?
>>
>
> Yes it depends on #clock-cells property. That's the main reason for
> adding #clock-cells

I'm still unclear on this. Do you mean we look for a subnode with
reg=<0x14> and then assume it's a clock node and require the
 #clock-cells to be there, or do we look through the sub-nodes to
find one with the #clock-cells property and then look up the 'reg'
property to find out which protocol number to use?

>>> +- shmem : List of phandle pointing to the shared memory(SHM) area as per
>>> +         generic mailbox client binding.
>>> +
>>> +See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details
>>> +about the generic mailbox controller and client driver bindings.
>>> +
>>> +The mailbox is the only permitted method of calling the SCMI firmware.
>>> +Mailbox doorbell is used as a mechanism to alert the presence of a
>>> +messages and/or notification.
>>
>> This looks odd: why not make the message itself part of the mailbox
>> protocol here, and leave the shmem as a implementation detail of the
>> mailbox driver?
>>
>
> I am not sure if I follow you here. But generally shmem can be memory
> carved out of anything in the system and it's dependent on the protocol
> and the remote firmware rather than the mailbox hardware itself.

I think the problem is the way we use the mailbox API in Linux, which
is completely abstract at the moment: it could be a pure doorbell, a
single-register for a data, some structured memory, or a
variable-length message. The assumption today is that the mailbox
user and the mailbox driver agree on the interpretation of that
void pointer.

This breaks down here, as you require the message to be a
variable-length message in a fixed physical location, but assume that
the mailbox serves only as a doorbell.

The solution might be to extend the mailbox API slightly, to
have explicit support for variable-length messages, and implement
support for that in either mailbox drivers or as an abstraction
on top of doorbell-type mailboxes.

      Arnd

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

* Re: [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-10-04 12:35         ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 12:35 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar, Rob Herring,
	Mark Rutland

On Wed, Oct 4, 2017 at 1:07 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
> Hi Arnd,
>
> Thanks for taking a look at this.
>
> On 04/10/17 11:50, Arnd Bergmann wrote:
>> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
>>> +
>>> +The SCMI is intended to allow agents such as OSPM to manage various functions
>>> +that are provided by the hardware platform it is running on, including power
>>> +and performance functions.
>>> +
>>> +This binding is intended to define the interface the firmware implementing
>>> +the SCMI as described in ARM document number ARM DUI 0922B ("ARM System Control
>>> +and Management Interface Platform Design Document")[0] provide for OSPM in
>>> +the device tree.
>>> +
>>> +Required properties:
>>> +
>>> +The scmi node with the following properties shall be under the /firmware/ node.
>>> +
>>> +- compatible : shall be "arm,scmi"
>>> +- mboxes: List of phandle and mailbox channel specifiers. It should contain
>>> +         exactly one or two mailboxes, one for transmitting messages("tx")
>>> +         and another optional for receiving the notifications("rx") if
>>> +         supported.
>>> +- mbox-names: shall be "tx" or "rx"
>>
>> The example below does not have the mbox-names property. If you require
>> exactly two mailboxes, why do you need the names anyway?
>>
>
> Good question. I can drop it, but would like to keep in case we need to
> extend it in future. We can always use then to identify.

I don't think it's necessary, as long you always need to have the first two,
but it doesn't hurt either.

Just make the description match the example.

>> However, your example does have a #addresss-cells/#size-cells
>> property that are not documented here. Please add them here as either
>> optional or required, and describe what the permitted values are and
>> how the address is interpreted.
>>
>
> Ah right, I didn't notice that. I will add it. It was added to provide
> the protocol number in "reg" property.
...
>> How does the OS identify the fact that a subnode uses the clock binding?
>> Do you need to look for the #clock-cells property, or is this based on the
>> unit address?
>>
>
> Yes it depends on #clock-cells property. That's the main reason for
> adding #clock-cells

I'm still unclear on this. Do you mean we look for a subnode with
reg=<0x14> and then assume it's a clock node and require the
 #clock-cells to be there, or do we look through the sub-nodes to
find one with the #clock-cells property and then look up the 'reg'
property to find out which protocol number to use?

>>> +- shmem : List of phandle pointing to the shared memory(SHM) area as per
>>> +         generic mailbox client binding.
>>> +
>>> +See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details
>>> +about the generic mailbox controller and client driver bindings.
>>> +
>>> +The mailbox is the only permitted method of calling the SCMI firmware.
>>> +Mailbox doorbell is used as a mechanism to alert the presence of a
>>> +messages and/or notification.
>>
>> This looks odd: why not make the message itself part of the mailbox
>> protocol here, and leave the shmem as a implementation detail of the
>> mailbox driver?
>>
>
> I am not sure if I follow you here. But generally shmem can be memory
> carved out of anything in the system and it's dependent on the protocol
> and the remote firmware rather than the mailbox hardware itself.

I think the problem is the way we use the mailbox API in Linux, which
is completely abstract at the moment: it could be a pure doorbell, a
single-register for a data, some structured memory, or a
variable-length message. The assumption today is that the mailbox
user and the mailbox driver agree on the interpretation of that
void pointer.

This breaks down here, as you require the message to be a
variable-length message in a fixed physical location, but assume that
the mailbox serves only as a doorbell.

The solution might be to extend the mailbox API slightly, to
have explicit support for variable-length messages, and implement
support for that in either mailbox drivers or as an abstraction
on top of doorbell-type mailboxes.

      Arnd
--
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] 208+ messages in thread

* [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-10-04 12:35         ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 12:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Oct 4, 2017 at 1:07 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> Hi Arnd,
>
> Thanks for taking a look at this.
>
> On 04/10/17 11:50, Arnd Bergmann wrote:
>> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>> +
>>> +The SCMI is intended to allow agents such as OSPM to manage various functions
>>> +that are provided by the hardware platform it is running on, including power
>>> +and performance functions.
>>> +
>>> +This binding is intended to define the interface the firmware implementing
>>> +the SCMI as described in ARM document number ARM DUI 0922B ("ARM System Control
>>> +and Management Interface Platform Design Document")[0] provide for OSPM in
>>> +the device tree.
>>> +
>>> +Required properties:
>>> +
>>> +The scmi node with the following properties shall be under the /firmware/ node.
>>> +
>>> +- compatible : shall be "arm,scmi"
>>> +- mboxes: List of phandle and mailbox channel specifiers. It should contain
>>> +         exactly one or two mailboxes, one for transmitting messages("tx")
>>> +         and another optional for receiving the notifications("rx") if
>>> +         supported.
>>> +- mbox-names: shall be "tx" or "rx"
>>
>> The example below does not have the mbox-names property. If you require
>> exactly two mailboxes, why do you need the names anyway?
>>
>
> Good question. I can drop it, but would like to keep in case we need to
> extend it in future. We can always use then to identify.

I don't think it's necessary, as long you always need to have the first two,
but it doesn't hurt either.

Just make the description match the example.

>> However, your example does have a #addresss-cells/#size-cells
>> property that are not documented here. Please add them here as either
>> optional or required, and describe what the permitted values are and
>> how the address is interpreted.
>>
>
> Ah right, I didn't notice that. I will add it. It was added to provide
> the protocol number in "reg" property.
...
>> How does the OS identify the fact that a subnode uses the clock binding?
>> Do you need to look for the #clock-cells property, or is this based on the
>> unit address?
>>
>
> Yes it depends on #clock-cells property. That's the main reason for
> adding #clock-cells

I'm still unclear on this. Do you mean we look for a subnode with
reg=<0x14> and then assume it's a clock node and require the
 #clock-cells to be there, or do we look through the sub-nodes to
find one with the #clock-cells property and then look up the 'reg'
property to find out which protocol number to use?

>>> +- shmem : List of phandle pointing to the shared memory(SHM) area as per
>>> +         generic mailbox client binding.
>>> +
>>> +See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details
>>> +about the generic mailbox controller and client driver bindings.
>>> +
>>> +The mailbox is the only permitted method of calling the SCMI firmware.
>>> +Mailbox doorbell is used as a mechanism to alert the presence of a
>>> +messages and/or notification.
>>
>> This looks odd: why not make the message itself part of the mailbox
>> protocol here, and leave the shmem as a implementation detail of the
>> mailbox driver?
>>
>
> I am not sure if I follow you here. But generally shmem can be memory
> carved out of anything in the system and it's dependent on the protocol
> and the remote firmware rather than the mailbox hardware itself.

I think the problem is the way we use the mailbox API in Linux, which
is completely abstract at the moment: it could be a pure doorbell, a
single-register for a data, some structured memory, or a
variable-length message. The assumption today is that the mailbox
user and the mailbox driver agree on the interpretation of that
void pointer.

This breaks down here, as you require the message to be a
variable-length message in a fixed physical location, but assume that
the mailbox serves only as a doorbell.

The solution might be to extend the mailbox API slightly, to
have explicit support for variable-length messages, and implement
support for that in either mailbox drivers or as an abstraction
on top of doorbell-type mailboxes.

      Arnd

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

* Re: [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-10-04 13:53           ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-04 13:53 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Rob Herring, Mark Rutland



On 04/10/17 13:35, Arnd Bergmann wrote:
> On Wed, Oct 4, 2017 at 1:07 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> Hi Arnd,
>>
>> Thanks for taking a look at this.
>>
>> On 04/10/17 11:50, Arnd Bergmann wrote:
>>> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>>> +
>>>> +The SCMI is intended to allow agents such as OSPM to manage various functions
>>>> +that are provided by the hardware platform it is running on, including power
>>>> +and performance functions.
>>>> +
>>>> +This binding is intended to define the interface the firmware implementing
>>>> +the SCMI as described in ARM document number ARM DUI 0922B ("ARM System Control
>>>> +and Management Interface Platform Design Document")[0] provide for OSPM in
>>>> +the device tree.
>>>> +
>>>> +Required properties:
>>>> +
>>>> +The scmi node with the following properties shall be under the /firmware/ node.
>>>> +
>>>> +- compatible : shall be "arm,scmi"
>>>> +- mboxes: List of phandle and mailbox channel specifiers. It should contain
>>>> +         exactly one or two mailboxes, one for transmitting messages("tx")
>>>> +         and another optional for receiving the notifications("rx") if
>>>> +         supported.
>>>> +- mbox-names: shall be "tx" or "rx"
>>>
>>> The example below does not have the mbox-names property. If you require
>>> exactly two mailboxes, why do you need the names anyway?
>>>
>>
>> Good question. I can drop it, but would like to keep in case we need to
>> extend it in future. We can always use then to identify.
> 
> I don't think it's necessary, as long you always need to have the first two,
> but it doesn't hurt either.
>
> Just make the description match the example.
> 

Sure.

>>> However, your example does have a #addresss-cells/#size-cells
>>> property that are not documented here. Please add them here as either
>>> optional or required, and describe what the permitted values are and
>>> how the address is interpreted.
>>>
>>
>> Ah right, I didn't notice that. I will add it. It was added to provide
>> the protocol number in "reg" property.
> ...
>>> How does the OS identify the fact that a subnode uses the clock binding?
>>> Do you need to look for the #clock-cells property, or is this based on the
>>> unit address?
>>>
>>
>> Yes it depends on #clock-cells property. That's the main reason for
>> adding #clock-cells
> 
> I'm still unclear on this. Do you mean we look for a subnode with
> reg=<0x14> and then assume it's a clock node and require the
>  #clock-cells to be there, 

Yes that's how it's used. Presence of subnode with reg=0x14 indicates
clock protocol and #clock-cells to indicate that it's clock provider
expecting 1 parameter from consumer which is the clock identifier.

or do we look through the sub-nodes to
> find one with the #clock-cells property and then look up the 'reg'
> property to find out which protocol number to use?
> 

Not this way. Do you see any issues ?

>>>> +- shmem : List of phandle pointing to the shared memory(SHM) area as per
>>>> +         generic mailbox client binding.
>>>> +
>>>> +See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details
>>>> +about the generic mailbox controller and client driver bindings.
>>>> +
>>>> +The mailbox is the only permitted method of calling the SCMI firmware.
>>>> +Mailbox doorbell is used as a mechanism to alert the presence of a
>>>> +messages and/or notification.
>>>
>>> This looks odd: why not make the message itself part of the mailbox
>>> protocol here, and leave the shmem as a implementation detail of the
>>> mailbox driver?
>>>
>>
>> I am not sure if I follow you here. But generally shmem can be memory
>> carved out of anything in the system and it's dependent on the protocol
>> and the remote firmware rather than the mailbox hardware itself.
> 
> I think the problem is the way we use the mailbox API in Linux, which
> is completely abstract at the moment: it could be a pure doorbell, a
> single-register for a data, some structured memory, or a
> variable-length message. The assumption today is that the mailbox
> user and the mailbox driver agree on the interpretation of that
> void pointer.
> 

Unfortunately true.

> This breaks down here, as you require the message to be a
> variable-length message in a fixed physical location, but assume that
> the mailbox serves only as a doorbell.
> 

Yes.

> The solution might be to extend the mailbox API slightly, to
> have explicit support for variable-length messages, and implement
> support for that in either mailbox drivers or as an abstraction
> on top of doorbell-type mailboxes.
> 
I got the concept. But are you also suggesting that in bindings it shmem
should be associated with mailbox controller rather than client ?

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-10-04 13:53           ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-04 13:53 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Rob Herring, Mark Rutland



On 04/10/17 13:35, Arnd Bergmann wrote:
> On Wed, Oct 4, 2017 at 1:07 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
>> Hi Arnd,
>>
>> Thanks for taking a look at this.
>>
>> On 04/10/17 11:50, Arnd Bergmann wrote:
>>> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
>>>> +
>>>> +The SCMI is intended to allow agents such as OSPM to manage various functions
>>>> +that are provided by the hardware platform it is running on, including power
>>>> +and performance functions.
>>>> +
>>>> +This binding is intended to define the interface the firmware implementing
>>>> +the SCMI as described in ARM document number ARM DUI 0922B ("ARM System Control
>>>> +and Management Interface Platform Design Document")[0] provide for OSPM in
>>>> +the device tree.
>>>> +
>>>> +Required properties:
>>>> +
>>>> +The scmi node with the following properties shall be under the /firmware/ node.
>>>> +
>>>> +- compatible : shall be "arm,scmi"
>>>> +- mboxes: List of phandle and mailbox channel specifiers. It should contain
>>>> +         exactly one or two mailboxes, one for transmitting messages("tx")
>>>> +         and another optional for receiving the notifications("rx") if
>>>> +         supported.
>>>> +- mbox-names: shall be "tx" or "rx"
>>>
>>> The example below does not have the mbox-names property. If you require
>>> exactly two mailboxes, why do you need the names anyway?
>>>
>>
>> Good question. I can drop it, but would like to keep in case we need to
>> extend it in future. We can always use then to identify.
> 
> I don't think it's necessary, as long you always need to have the first two,
> but it doesn't hurt either.
>
> Just make the description match the example.
> 

Sure.

>>> However, your example does have a #addresss-cells/#size-cells
>>> property that are not documented here. Please add them here as either
>>> optional or required, and describe what the permitted values are and
>>> how the address is interpreted.
>>>
>>
>> Ah right, I didn't notice that. I will add it. It was added to provide
>> the protocol number in "reg" property.
> ...
>>> How does the OS identify the fact that a subnode uses the clock binding?
>>> Do you need to look for the #clock-cells property, or is this based on the
>>> unit address?
>>>
>>
>> Yes it depends on #clock-cells property. That's the main reason for
>> adding #clock-cells
> 
> I'm still unclear on this. Do you mean we look for a subnode with
> reg=<0x14> and then assume it's a clock node and require the
>  #clock-cells to be there, 

Yes that's how it's used. Presence of subnode with reg=0x14 indicates
clock protocol and #clock-cells to indicate that it's clock provider
expecting 1 parameter from consumer which is the clock identifier.

or do we look through the sub-nodes to
> find one with the #clock-cells property and then look up the 'reg'
> property to find out which protocol number to use?
> 

Not this way. Do you see any issues ?

>>>> +- shmem : List of phandle pointing to the shared memory(SHM) area as per
>>>> +         generic mailbox client binding.
>>>> +
>>>> +See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details
>>>> +about the generic mailbox controller and client driver bindings.
>>>> +
>>>> +The mailbox is the only permitted method of calling the SCMI firmware.
>>>> +Mailbox doorbell is used as a mechanism to alert the presence of a
>>>> +messages and/or notification.
>>>
>>> This looks odd: why not make the message itself part of the mailbox
>>> protocol here, and leave the shmem as a implementation detail of the
>>> mailbox driver?
>>>
>>
>> I am not sure if I follow you here. But generally shmem can be memory
>> carved out of anything in the system and it's dependent on the protocol
>> and the remote firmware rather than the mailbox hardware itself.
> 
> I think the problem is the way we use the mailbox API in Linux, which
> is completely abstract at the moment: it could be a pure doorbell, a
> single-register for a data, some structured memory, or a
> variable-length message. The assumption today is that the mailbox
> user and the mailbox driver agree on the interpretation of that
> void pointer.
> 

Unfortunately true.

> This breaks down here, as you require the message to be a
> variable-length message in a fixed physical location, but assume that
> the mailbox serves only as a doorbell.
> 

Yes.

> The solution might be to extend the mailbox API slightly, to
> have explicit support for variable-length messages, and implement
> support for that in either mailbox drivers or as an abstraction
> on top of doorbell-type mailboxes.
> 
I got the concept. But are you also suggesting that in bindings it shmem
should be associated with mailbox controller rather than client ?

-- 
Regards,
Sudeep
--
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] 208+ messages in thread

* [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-10-04 13:53           ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-04 13:53 UTC (permalink / raw)
  To: linux-arm-kernel



On 04/10/17 13:35, Arnd Bergmann wrote:
> On Wed, Oct 4, 2017 at 1:07 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> Hi Arnd,
>>
>> Thanks for taking a look at this.
>>
>> On 04/10/17 11:50, Arnd Bergmann wrote:
>>> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>>> +
>>>> +The SCMI is intended to allow agents such as OSPM to manage various functions
>>>> +that are provided by the hardware platform it is running on, including power
>>>> +and performance functions.
>>>> +
>>>> +This binding is intended to define the interface the firmware implementing
>>>> +the SCMI as described in ARM document number ARM DUI 0922B ("ARM System Control
>>>> +and Management Interface Platform Design Document")[0] provide for OSPM in
>>>> +the device tree.
>>>> +
>>>> +Required properties:
>>>> +
>>>> +The scmi node with the following properties shall be under the /firmware/ node.
>>>> +
>>>> +- compatible : shall be "arm,scmi"
>>>> +- mboxes: List of phandle and mailbox channel specifiers. It should contain
>>>> +         exactly one or two mailboxes, one for transmitting messages("tx")
>>>> +         and another optional for receiving the notifications("rx") if
>>>> +         supported.
>>>> +- mbox-names: shall be "tx" or "rx"
>>>
>>> The example below does not have the mbox-names property. If you require
>>> exactly two mailboxes, why do you need the names anyway?
>>>
>>
>> Good question. I can drop it, but would like to keep in case we need to
>> extend it in future. We can always use then to identify.
> 
> I don't think it's necessary, as long you always need to have the first two,
> but it doesn't hurt either.
>
> Just make the description match the example.
> 

Sure.

>>> However, your example does have a #addresss-cells/#size-cells
>>> property that are not documented here. Please add them here as either
>>> optional or required, and describe what the permitted values are and
>>> how the address is interpreted.
>>>
>>
>> Ah right, I didn't notice that. I will add it. It was added to provide
>> the protocol number in "reg" property.
> ...
>>> How does the OS identify the fact that a subnode uses the clock binding?
>>> Do you need to look for the #clock-cells property, or is this based on the
>>> unit address?
>>>
>>
>> Yes it depends on #clock-cells property. That's the main reason for
>> adding #clock-cells
> 
> I'm still unclear on this. Do you mean we look for a subnode with
> reg=<0x14> and then assume it's a clock node and require the
>  #clock-cells to be there, 

Yes that's how it's used. Presence of subnode with reg=0x14 indicates
clock protocol and #clock-cells to indicate that it's clock provider
expecting 1 parameter from consumer which is the clock identifier.

or do we look through the sub-nodes to
> find one with the #clock-cells property and then look up the 'reg'
> property to find out which protocol number to use?
> 

Not this way. Do you see any issues ?

>>>> +- shmem : List of phandle pointing to the shared memory(SHM) area as per
>>>> +         generic mailbox client binding.
>>>> +
>>>> +See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details
>>>> +about the generic mailbox controller and client driver bindings.
>>>> +
>>>> +The mailbox is the only permitted method of calling the SCMI firmware.
>>>> +Mailbox doorbell is used as a mechanism to alert the presence of a
>>>> +messages and/or notification.
>>>
>>> This looks odd: why not make the message itself part of the mailbox
>>> protocol here, and leave the shmem as a implementation detail of the
>>> mailbox driver?
>>>
>>
>> I am not sure if I follow you here. But generally shmem can be memory
>> carved out of anything in the system and it's dependent on the protocol
>> and the remote firmware rather than the mailbox hardware itself.
> 
> I think the problem is the way we use the mailbox API in Linux, which
> is completely abstract at the moment: it could be a pure doorbell, a
> single-register for a data, some structured memory, or a
> variable-length message. The assumption today is that the mailbox
> user and the mailbox driver agree on the interpretation of that
> void pointer.
> 

Unfortunately true.

> This breaks down here, as you require the message to be a
> variable-length message in a fixed physical location, but assume that
> the mailbox serves only as a doorbell.
> 

Yes.

> The solution might be to extend the mailbox API slightly, to
> have explicit support for variable-length messages, and implement
> support for that in either mailbox drivers or as an abstraction
> on top of doorbell-type mailboxes.
> 
I got the concept. But are you also suggesting that in bindings it shmem
should be associated with mailbox controller rather than client ?

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-10-04 14:17             ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 14:17 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar, Rob Herring,
	Mark Rutland

On Wed, Oct 4, 2017 at 3:53 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> On 04/10/17 13:35, Arnd Bergmann wrote:
>> On Wed, Oct 4, 2017 at 1:07 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:

>>>
>>> Yes it depends on #clock-cells property. That's the main reason for
>>> adding #clock-cells
>>
>> I'm still unclear on this. Do you mean we look for a subnode with
>> reg=<0x14> and then assume it's a clock node and require the
>>  #clock-cells to be there,
>
> Yes that's how it's used. Presence of subnode with reg=0x14 indicates
> clock protocol and #clock-cells to indicate that it's clock provider
> expecting 1 parameter from consumer which is the clock identifier.
>
> or do we look through the sub-nodes to
>> find one with the #clock-cells property and then look up the 'reg'
>> property to find out which protocol number to use?
>>
>
> Not this way. Do you see any issues ?

We normally don't assume that a particular unit address implies
a specific function. Conventionally that would be done by matching
the "compatible" property instead.

What you do clearly works, but it's surprising to the reader.


>> I think the problem is the way we use the mailbox API in Linux, which
>> is completely abstract at the moment: it could be a pure doorbell, a
>> single-register for a data, some structured memory, or a
>> variable-length message. The assumption today is that the mailbox
>> user and the mailbox driver agree on the interpretation of that
>> void pointer.
>>
>
> Unfortunately true.
>
>> This breaks down here, as you require the message to be a
>> variable-length message in a fixed physical location, but assume that
>> the mailbox serves only as a doorbell.
>>
>
> Yes.
>
>> The solution might be to extend the mailbox API slightly, to
>> have explicit support for variable-length messages, and implement
>> support for that in either mailbox drivers or as an abstraction
>> on top of doorbell-type mailboxes.
>>
> I got the concept. But are you also suggesting that in bindings it shmem
> should be associated with mailbox controller rather than client ?

There are probably several ways of doing this better, we should see
what the best is we can come up with.

I think generally speaking we need a way for a mailbox user to
know what it should use as the mailbox data here, so it is
able to talk to different incompatible mailbox providers.

One idea I had is to use a nested mailbox driver, that turns
a doorbell or single-register styled mailbox into a variable-length
mailbox by adding a memory region, like

    mailbox@1233000 {
        compatible = "vendor-hardware-specifc-id";
        interrupts = <34>;
        reg = <0x1233000 0x100>;
        #mbox-cells = <1>;
    };

    mailbox {
           compatible = "shmem-mailbox";
           mboxes = <&/mailbox@1233000  25>;
           #mbox-cells = <1>;
           shmem = <&cpu_scp_lpri &cpu_scp_hpri>;
    };

This would create one mailbox that only takes a register argument,
and another one that can take longer messages based on the first.
In your driver, you then refer to the second one and pass the
variable-length data into that directly.

        Arnd

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

* Re: [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-10-04 14:17             ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 14:17 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar, Rob Herring,
	Mark Rutland

On Wed, Oct 4, 2017 at 3:53 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
> On 04/10/17 13:35, Arnd Bergmann wrote:
>> On Wed, Oct 4, 2017 at 1:07 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:

>>>
>>> Yes it depends on #clock-cells property. That's the main reason for
>>> adding #clock-cells
>>
>> I'm still unclear on this. Do you mean we look for a subnode with
>> reg=<0x14> and then assume it's a clock node and require the
>>  #clock-cells to be there,
>
> Yes that's how it's used. Presence of subnode with reg=0x14 indicates
> clock protocol and #clock-cells to indicate that it's clock provider
> expecting 1 parameter from consumer which is the clock identifier.
>
> or do we look through the sub-nodes to
>> find one with the #clock-cells property and then look up the 'reg'
>> property to find out which protocol number to use?
>>
>
> Not this way. Do you see any issues ?

We normally don't assume that a particular unit address implies
a specific function. Conventionally that would be done by matching
the "compatible" property instead.

What you do clearly works, but it's surprising to the reader.


>> I think the problem is the way we use the mailbox API in Linux, which
>> is completely abstract at the moment: it could be a pure doorbell, a
>> single-register for a data, some structured memory, or a
>> variable-length message. The assumption today is that the mailbox
>> user and the mailbox driver agree on the interpretation of that
>> void pointer.
>>
>
> Unfortunately true.
>
>> This breaks down here, as you require the message to be a
>> variable-length message in a fixed physical location, but assume that
>> the mailbox serves only as a doorbell.
>>
>
> Yes.
>
>> The solution might be to extend the mailbox API slightly, to
>> have explicit support for variable-length messages, and implement
>> support for that in either mailbox drivers or as an abstraction
>> on top of doorbell-type mailboxes.
>>
> I got the concept. But are you also suggesting that in bindings it shmem
> should be associated with mailbox controller rather than client ?

There are probably several ways of doing this better, we should see
what the best is we can come up with.

I think generally speaking we need a way for a mailbox user to
know what it should use as the mailbox data here, so it is
able to talk to different incompatible mailbox providers.

One idea I had is to use a nested mailbox driver, that turns
a doorbell or single-register styled mailbox into a variable-length
mailbox by adding a memory region, like

    mailbox@1233000 {
        compatible = "vendor-hardware-specifc-id";
        interrupts = <34>;
        reg = <0x1233000 0x100>;
        #mbox-cells = <1>;
    };

    mailbox {
           compatible = "shmem-mailbox";
           mboxes = <&/mailbox@1233000  25>;
           #mbox-cells = <1>;
           shmem = <&cpu_scp_lpri &cpu_scp_hpri>;
    };

This would create one mailbox that only takes a register argument,
and another one that can take longer messages based on the first.
In your driver, you then refer to the second one and pass the
variable-length data into that directly.

        Arnd
--
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] 208+ messages in thread

* [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-10-04 14:17             ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-04 14:17 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Oct 4, 2017 at 3:53 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> On 04/10/17 13:35, Arnd Bergmann wrote:
>> On Wed, Oct 4, 2017 at 1:07 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:

>>>
>>> Yes it depends on #clock-cells property. That's the main reason for
>>> adding #clock-cells
>>
>> I'm still unclear on this. Do you mean we look for a subnode with
>> reg=<0x14> and then assume it's a clock node and require the
>>  #clock-cells to be there,
>
> Yes that's how it's used. Presence of subnode with reg=0x14 indicates
> clock protocol and #clock-cells to indicate that it's clock provider
> expecting 1 parameter from consumer which is the clock identifier.
>
> or do we look through the sub-nodes to
>> find one with the #clock-cells property and then look up the 'reg'
>> property to find out which protocol number to use?
>>
>
> Not this way. Do you see any issues ?

We normally don't assume that a particular unit address implies
a specific function. Conventionally that would be done by matching
the "compatible" property instead.

What you do clearly works, but it's surprising to the reader.


>> I think the problem is the way we use the mailbox API in Linux, which
>> is completely abstract at the moment: it could be a pure doorbell, a
>> single-register for a data, some structured memory, or a
>> variable-length message. The assumption today is that the mailbox
>> user and the mailbox driver agree on the interpretation of that
>> void pointer.
>>
>
> Unfortunately true.
>
>> This breaks down here, as you require the message to be a
>> variable-length message in a fixed physical location, but assume that
>> the mailbox serves only as a doorbell.
>>
>
> Yes.
>
>> The solution might be to extend the mailbox API slightly, to
>> have explicit support for variable-length messages, and implement
>> support for that in either mailbox drivers or as an abstraction
>> on top of doorbell-type mailboxes.
>>
> I got the concept. But are you also suggesting that in bindings it shmem
> should be associated with mailbox controller rather than client ?

There are probably several ways of doing this better, we should see
what the best is we can come up with.

I think generally speaking we need a way for a mailbox user to
know what it should use as the mailbox data here, so it is
able to talk to different incompatible mailbox providers.

One idea I had is to use a nested mailbox driver, that turns
a doorbell or single-register styled mailbox into a variable-length
mailbox by adding a memory region, like

    mailbox at 1233000 {
        compatible = "vendor-hardware-specifc-id";
        interrupts = <34>;
        reg = <0x1233000 0x100>;
        #mbox-cells = <1>;
    };

    mailbox {
           compatible = "shmem-mailbox";
           mboxes = <&/mailbox@1233000  25>;
           #mbox-cells = <1>;
           shmem = <&cpu_scp_lpri &cpu_scp_hpri>;
    };

This would create one mailbox that only takes a register argument,
and another one that can take longer messages based on the first.
In your driver, you then refer to the second one and pass the
variable-length data into that directly.

        Arnd

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

* Re: [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-10-04 14:47               ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-04 14:47 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Rob Herring, Mark Rutland



On 04/10/17 15:17, Arnd Bergmann wrote:
> On Wed, Oct 4, 2017 at 3:53 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> On 04/10/17 13:35, Arnd Bergmann wrote:
>>> On Wed, Oct 4, 2017 at 1:07 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> 
>>>>
>>>> Yes it depends on #clock-cells property. That's the main reason for
>>>> adding #clock-cells
>>>
>>> I'm still unclear on this. Do you mean we look for a subnode with
>>> reg=<0x14> and then assume it's a clock node and require the
>>>  #clock-cells to be there,
>>
>> Yes that's how it's used. Presence of subnode with reg=0x14 indicates
>> clock protocol and #clock-cells to indicate that it's clock provider
>> expecting 1 parameter from consumer which is the clock identifier.
>>
>> or do we look through the sub-nodes to
>>> find one with the #clock-cells property and then look up the 'reg'
>>> property to find out which protocol number to use?
>>>
>>
>> Not this way. Do you see any issues ?
> 
> We normally don't assume that a particular unit address implies
> a specific function. Conventionally that would be done by matching
> the "compatible" property instead.
> 
> What you do clearly works, but it's surprising to the reader.
> 
> 
>>> I think the problem is the way we use the mailbox API in Linux, which
>>> is completely abstract at the moment: it could be a pure doorbell, a
>>> single-register for a data, some structured memory, or a
>>> variable-length message. The assumption today is that the mailbox
>>> user and the mailbox driver agree on the interpretation of that
>>> void pointer.
>>>
>>
>> Unfortunately true.
>>
>>> This breaks down here, as you require the message to be a
>>> variable-length message in a fixed physical location, but assume that
>>> the mailbox serves only as a doorbell.
>>>
>>
>> Yes.
>>
>>> The solution might be to extend the mailbox API slightly, to
>>> have explicit support for variable-length messages, and implement
>>> support for that in either mailbox drivers or as an abstraction
>>> on top of doorbell-type mailboxes.
>>>
>> I got the concept. But are you also suggesting that in bindings it shmem
>> should be associated with mailbox controller rather than client ?
> 
> There are probably several ways of doing this better, we should see
> what the best is we can come up with.
> 
> I think generally speaking we need a way for a mailbox user to
> know what it should use as the mailbox data here, so it is
> able to talk to different incompatible mailbox providers.
> 
> One idea I had is to use a nested mailbox driver, that turns
> a doorbell or single-register styled mailbox into a variable-length
> mailbox by adding a memory region, like
> 
>     mailbox@1233000 {
>         compatible = "vendor-hardware-specifc-id";
>         interrupts = <34>;
>         reg = <0x1233000 0x100>;
>         #mbox-cells = <1>;
>     };
> 
>     mailbox {
>            compatible = "shmem-mailbox";
>            mboxes = <&/mailbox@1233000  25>;
>            #mbox-cells = <1>;
>            shmem = <&cpu_scp_lpri &cpu_scp_hpri>;
>     };
> 
> This would create one mailbox that only takes a register argument,
> and another one that can take longer messages based on the first.
> In your driver, you then refer to the second one and pass the
> variable-length data into that directly.

1. IIUC it was intentional not to include shmem as part of mailbox
   controller binding and was pushed to client drivers as it's generally
   not part of mailbox IP block. I am not sure if there are any other
   specific reasons for that, but I may be missing some facts.

2. I am not sure if we need nested driver/bindings (at-least to begin
   with). On a platform I don't think both/all modes will be used.
   I had  proposal for adding doorbell for ARM MHU based on extended
   bindings, but it was rejected[1]. But I really preferred that over
   the shim layer I had to add in v3.

--
Regards,
Sudeep

[1] https://patchwork.kernel.org/patch/9745683/

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

* Re: [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-10-04 14:47               ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-04 14:47 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Rob Herring, Mark Rutland



On 04/10/17 15:17, Arnd Bergmann wrote:
> On Wed, Oct 4, 2017 at 3:53 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
>> On 04/10/17 13:35, Arnd Bergmann wrote:
>>> On Wed, Oct 4, 2017 at 1:07 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
> 
>>>>
>>>> Yes it depends on #clock-cells property. That's the main reason for
>>>> adding #clock-cells
>>>
>>> I'm still unclear on this. Do you mean we look for a subnode with
>>> reg=<0x14> and then assume it's a clock node and require the
>>>  #clock-cells to be there,
>>
>> Yes that's how it's used. Presence of subnode with reg=0x14 indicates
>> clock protocol and #clock-cells to indicate that it's clock provider
>> expecting 1 parameter from consumer which is the clock identifier.
>>
>> or do we look through the sub-nodes to
>>> find one with the #clock-cells property and then look up the 'reg'
>>> property to find out which protocol number to use?
>>>
>>
>> Not this way. Do you see any issues ?
> 
> We normally don't assume that a particular unit address implies
> a specific function. Conventionally that would be done by matching
> the "compatible" property instead.
> 
> What you do clearly works, but it's surprising to the reader.
> 
> 
>>> I think the problem is the way we use the mailbox API in Linux, which
>>> is completely abstract at the moment: it could be a pure doorbell, a
>>> single-register for a data, some structured memory, or a
>>> variable-length message. The assumption today is that the mailbox
>>> user and the mailbox driver agree on the interpretation of that
>>> void pointer.
>>>
>>
>> Unfortunately true.
>>
>>> This breaks down here, as you require the message to be a
>>> variable-length message in a fixed physical location, but assume that
>>> the mailbox serves only as a doorbell.
>>>
>>
>> Yes.
>>
>>> The solution might be to extend the mailbox API slightly, to
>>> have explicit support for variable-length messages, and implement
>>> support for that in either mailbox drivers or as an abstraction
>>> on top of doorbell-type mailboxes.
>>>
>> I got the concept. But are you also suggesting that in bindings it shmem
>> should be associated with mailbox controller rather than client ?
> 
> There are probably several ways of doing this better, we should see
> what the best is we can come up with.
> 
> I think generally speaking we need a way for a mailbox user to
> know what it should use as the mailbox data here, so it is
> able to talk to different incompatible mailbox providers.
> 
> One idea I had is to use a nested mailbox driver, that turns
> a doorbell or single-register styled mailbox into a variable-length
> mailbox by adding a memory region, like
> 
>     mailbox@1233000 {
>         compatible = "vendor-hardware-specifc-id";
>         interrupts = <34>;
>         reg = <0x1233000 0x100>;
>         #mbox-cells = <1>;
>     };
> 
>     mailbox {
>            compatible = "shmem-mailbox";
>            mboxes = <&/mailbox@1233000  25>;
>            #mbox-cells = <1>;
>            shmem = <&cpu_scp_lpri &cpu_scp_hpri>;
>     };
> 
> This would create one mailbox that only takes a register argument,
> and another one that can take longer messages based on the first.
> In your driver, you then refer to the second one and pass the
> variable-length data into that directly.

1. IIUC it was intentional not to include shmem as part of mailbox
   controller binding and was pushed to client drivers as it's generally
   not part of mailbox IP block. I am not sure if there are any other
   specific reasons for that, but I may be missing some facts.

2. I am not sure if we need nested driver/bindings (at-least to begin
   with). On a platform I don't think both/all modes will be used.
   I had  proposal for adding doorbell for ARM MHU based on extended
   bindings, but it was rejected[1]. But I really preferred that over
   the shim layer I had to add in v3.

--
Regards,
Sudeep

[1] https://patchwork.kernel.org/patch/9745683/
--
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] 208+ messages in thread

* [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-10-04 14:47               ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-04 14:47 UTC (permalink / raw)
  To: linux-arm-kernel



On 04/10/17 15:17, Arnd Bergmann wrote:
> On Wed, Oct 4, 2017 at 3:53 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> On 04/10/17 13:35, Arnd Bergmann wrote:
>>> On Wed, Oct 4, 2017 at 1:07 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> 
>>>>
>>>> Yes it depends on #clock-cells property. That's the main reason for
>>>> adding #clock-cells
>>>
>>> I'm still unclear on this. Do you mean we look for a subnode with
>>> reg=<0x14> and then assume it's a clock node and require the
>>>  #clock-cells to be there,
>>
>> Yes that's how it's used. Presence of subnode with reg=0x14 indicates
>> clock protocol and #clock-cells to indicate that it's clock provider
>> expecting 1 parameter from consumer which is the clock identifier.
>>
>> or do we look through the sub-nodes to
>>> find one with the #clock-cells property and then look up the 'reg'
>>> property to find out which protocol number to use?
>>>
>>
>> Not this way. Do you see any issues ?
> 
> We normally don't assume that a particular unit address implies
> a specific function. Conventionally that would be done by matching
> the "compatible" property instead.
> 
> What you do clearly works, but it's surprising to the reader.
> 
> 
>>> I think the problem is the way we use the mailbox API in Linux, which
>>> is completely abstract at the moment: it could be a pure doorbell, a
>>> single-register for a data, some structured memory, or a
>>> variable-length message. The assumption today is that the mailbox
>>> user and the mailbox driver agree on the interpretation of that
>>> void pointer.
>>>
>>
>> Unfortunately true.
>>
>>> This breaks down here, as you require the message to be a
>>> variable-length message in a fixed physical location, but assume that
>>> the mailbox serves only as a doorbell.
>>>
>>
>> Yes.
>>
>>> The solution might be to extend the mailbox API slightly, to
>>> have explicit support for variable-length messages, and implement
>>> support for that in either mailbox drivers or as an abstraction
>>> on top of doorbell-type mailboxes.
>>>
>> I got the concept. But are you also suggesting that in bindings it shmem
>> should be associated with mailbox controller rather than client ?
> 
> There are probably several ways of doing this better, we should see
> what the best is we can come up with.
> 
> I think generally speaking we need a way for a mailbox user to
> know what it should use as the mailbox data here, so it is
> able to talk to different incompatible mailbox providers.
> 
> One idea I had is to use a nested mailbox driver, that turns
> a doorbell or single-register styled mailbox into a variable-length
> mailbox by adding a memory region, like
> 
>     mailbox at 1233000 {
>         compatible = "vendor-hardware-specifc-id";
>         interrupts = <34>;
>         reg = <0x1233000 0x100>;
>         #mbox-cells = <1>;
>     };
> 
>     mailbox {
>            compatible = "shmem-mailbox";
>            mboxes = <&/mailbox@1233000  25>;
>            #mbox-cells = <1>;
>            shmem = <&cpu_scp_lpri &cpu_scp_hpri>;
>     };
> 
> This would create one mailbox that only takes a register argument,
> and another one that can take longer messages based on the first.
> In your driver, you then refer to the second one and pass the
> variable-length data into that directly.

1. IIUC it was intentional not to include shmem as part of mailbox
   controller binding and was pushed to client drivers as it's generally
   not part of mailbox IP block. I am not sure if there are any other
   specific reasons for that, but I may be missing some facts.

2. I am not sure if we need nested driver/bindings (at-least to begin
   with). On a platform I don't think both/all modes will be used.
   I had  proposal for adding doorbell for ARM MHU based on extended
   bindings, but it was rejected[1]. But I really preferred that over
   the shim layer I had to add in v3.

--
Regards,
Sudeep

[1] https://patchwork.kernel.org/patch/9745683/

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

* Re: [PATCH v3 21/22] cpufreq: add support for CPU DVFS based on SCMI message protocol
  2017-10-04 11:30     ` Arnd Bergmann
@ 2017-10-04 15:01       ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-04 15:01 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Rafael J. Wysocki, Viresh Kumar, linux-pm



On 04/10/17 12:30, Arnd Bergmann wrote:
>> +static int scmi_cpufreq_probe(struct platform_device *pdev)
>> +{
>> +       int ret;
>> +
>> +       handle = devm_scmi_handle_get(&pdev->dev);
>> +
>> +       if (IS_ERR_OR_NULL(handle) || !handle->perf_ops)
>> +               return -EPROBE_DEFER;
> 
> As mentioned before, never create an interface that needs to use
> IS_ERR_OR_NULL(), make it return either NULL on error, or always
> have an error code.
> 

Agreed.

>> +
>> +static struct platform_driver scmi_cpufreq_platdrv = {
>> +       .driver = {
>> +               .name   = "scmi-cpufreq",
>> +       },
>> +       .probe          = scmi_cpufreq_probe,
>> +       .remove         = scmi_cpufreq_remove,
>> +};
> 
> You appear to have split this driver into the 'cpufreq' side and
> the 'protocol' handler in a different file. I already commented that
> the way the main scmi driver knows about all the protocols looks
> bad, here we can see another aspect of the same problem.
> 
> Rather than manually register a platform_device for the purpose
> of connecting it to the cpufreq driver, there should be a way
> to dynamically register the protocol from the cpufreq driver
> and then have both in the same file.
> 

I agree that should be possible. I took this approach for 2 reasons:

1. to avoid all sorts of probe ordering issues
2. we may have system with multiple instances of SCMI. E.g. a system
   may have multiple remote processors, each controlling dvfs/power mgmt
   of a subset of CPUs/devices controller in OS.

I have to admit that I haven't thought too much in details yet. That's
the main idea behind scmi_handle and restricting access to that only to
sub-nodes in it. I am open to suggestions.

-- 
Regards,
Sudeep

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

* [PATCH v3 21/22] cpufreq: add support for CPU DVFS based on SCMI message protocol
@ 2017-10-04 15:01       ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-04 15:01 UTC (permalink / raw)
  To: linux-arm-kernel



On 04/10/17 12:30, Arnd Bergmann wrote:
>> +static int scmi_cpufreq_probe(struct platform_device *pdev)
>> +{
>> +       int ret;
>> +
>> +       handle = devm_scmi_handle_get(&pdev->dev);
>> +
>> +       if (IS_ERR_OR_NULL(handle) || !handle->perf_ops)
>> +               return -EPROBE_DEFER;
> 
> As mentioned before, never create an interface that needs to use
> IS_ERR_OR_NULL(), make it return either NULL on error, or always
> have an error code.
> 

Agreed.

>> +
>> +static struct platform_driver scmi_cpufreq_platdrv = {
>> +       .driver = {
>> +               .name   = "scmi-cpufreq",
>> +       },
>> +       .probe          = scmi_cpufreq_probe,
>> +       .remove         = scmi_cpufreq_remove,
>> +};
> 
> You appear to have split this driver into the 'cpufreq' side and
> the 'protocol' handler in a different file. I already commented that
> the way the main scmi driver knows about all the protocols looks
> bad, here we can see another aspect of the same problem.
> 
> Rather than manually register a platform_device for the purpose
> of connecting it to the cpufreq driver, there should be a way
> to dynamically register the protocol from the cpufreq driver
> and then have both in the same file.
> 

I agree that should be possible. I took this approach for 2 reasons:

1. to avoid all sorts of probe ordering issues
2. we may have system with multiple instances of SCMI. E.g. a system
   may have multiple remote processors, each controlling dvfs/power mgmt
   of a subset of CPUs/devices controller in OS.

I have to admit that I haven't thought too much in details yet. That's
the main idea behind scmi_handle and restricting access to that only to
sub-nodes in it. I am open to suggestions.

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 04/22] firmware: arm_scmi: add basic driver infrastructure for SCMI
@ 2017-10-04 17:37       ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-04 17:37 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar



On 04/10/17 11:59, Arnd Bergmann wrote:
> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> 
>> +/**
>> + * struct scmi_msg_hdr - Message(Tx/Rx) header
>> + *
>> + * @id: The identifier of the command being sent
>> + * @protocol_id: The identifier of the protocol used to send @id command
>> + * @seq: The token to identify the message. when a message/command returns,
>> + *       the platform returns the whole message header unmodified including
>> + *      the token.
>> + */
>> +struct scmi_msg_hdr {
>> +       u8 id;
>> +       u8 protocol_id;
>> +       u16 seq;
>> +       u32 status;
>> +       bool poll_completion;
>> +};
> 
> Is this structure part of the protocol, or just part of the linux
> implementation?
> If this is in the protocol, you should not have a 'bool' member in there, which
> does not have a well-defined binary representation across architectures.
> 

No, it's not part of specification just linux, added to support polling
based DVFS messages.

>> +/*
>> + * The SCP firmware providing SCM interface to OSPM and other agents must
>> + * execute only in little-endian mode as per SCMI specification, so any buffers
>> + * shared through SCMI should have their contents converted to little-endian
>> + */
> 
> That is a very odd thing to put into a specification, are you sure it requires
> a specific runtime endian-mode? I would bet that it only requires the protocol
> to use little-endian data, so better describe it like that.
> 

Right, my bad. Not sure where I copied that text from, but as you
mention specification just expects data to be in LE format.

[..]

> 
>> +#if IS_REACHABLE(CONFIG_ARM_SCMI_PROTOCOL)
>> +int scmi_handle_put(const struct scmi_handle *handle);
>> +const struct scmi_handle *scmi_handle_get(struct device *dev);
>> +const struct scmi_handle *devm_scmi_handle_get(struct device *dev);
> 
> IS_REACHABLE() can easily lead to confusion when the driver is
> a loadable module but never gets used by a built-in driver. Maybe use
> IS_ENABLED() here, and add a Kconfig symbol that other drivers
> can depend on if you want them to optionally use it, like:
> 
> config MAYBE_ARM_SCMI_PROTOCOL
>         default y if ARM_SCMI_PROTOCOL=n
>         default ARM_SCMI_PROTOCOL

OK, will check, we may not need that yet.

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 04/22] firmware: arm_scmi: add basic driver infrastructure for SCMI
@ 2017-10-04 17:37       ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-04 17:37 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar



On 04/10/17 11:59, Arnd Bergmann wrote:
> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
> 
>> +/**
>> + * struct scmi_msg_hdr - Message(Tx/Rx) header
>> + *
>> + * @id: The identifier of the command being sent
>> + * @protocol_id: The identifier of the protocol used to send @id command
>> + * @seq: The token to identify the message. when a message/command returns,
>> + *       the platform returns the whole message header unmodified including
>> + *      the token.
>> + */
>> +struct scmi_msg_hdr {
>> +       u8 id;
>> +       u8 protocol_id;
>> +       u16 seq;
>> +       u32 status;
>> +       bool poll_completion;
>> +};
> 
> Is this structure part of the protocol, or just part of the linux
> implementation?
> If this is in the protocol, you should not have a 'bool' member in there, which
> does not have a well-defined binary representation across architectures.
> 

No, it's not part of specification just linux, added to support polling
based DVFS messages.

>> +/*
>> + * The SCP firmware providing SCM interface to OSPM and other agents must
>> + * execute only in little-endian mode as per SCMI specification, so any buffers
>> + * shared through SCMI should have their contents converted to little-endian
>> + */
> 
> That is a very odd thing to put into a specification, are you sure it requires
> a specific runtime endian-mode? I would bet that it only requires the protocol
> to use little-endian data, so better describe it like that.
> 

Right, my bad. Not sure where I copied that text from, but as you
mention specification just expects data to be in LE format.

[..]

> 
>> +#if IS_REACHABLE(CONFIG_ARM_SCMI_PROTOCOL)
>> +int scmi_handle_put(const struct scmi_handle *handle);
>> +const struct scmi_handle *scmi_handle_get(struct device *dev);
>> +const struct scmi_handle *devm_scmi_handle_get(struct device *dev);
> 
> IS_REACHABLE() can easily lead to confusion when the driver is
> a loadable module but never gets used by a built-in driver. Maybe use
> IS_ENABLED() here, and add a Kconfig symbol that other drivers
> can depend on if you want them to optionally use it, like:
> 
> config MAYBE_ARM_SCMI_PROTOCOL
>         default y if ARM_SCMI_PROTOCOL=n
>         default ARM_SCMI_PROTOCOL

OK, will check, we may not need that yet.

-- 
Regards,
Sudeep
--
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] 208+ messages in thread

* [PATCH v3 04/22] firmware: arm_scmi: add basic driver infrastructure for SCMI
@ 2017-10-04 17:37       ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-04 17:37 UTC (permalink / raw)
  To: linux-arm-kernel



On 04/10/17 11:59, Arnd Bergmann wrote:
> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> 
>> +/**
>> + * struct scmi_msg_hdr - Message(Tx/Rx) header
>> + *
>> + * @id: The identifier of the command being sent
>> + * @protocol_id: The identifier of the protocol used to send @id command
>> + * @seq: The token to identify the message. when a message/command returns,
>> + *       the platform returns the whole message header unmodified including
>> + *      the token.
>> + */
>> +struct scmi_msg_hdr {
>> +       u8 id;
>> +       u8 protocol_id;
>> +       u16 seq;
>> +       u32 status;
>> +       bool poll_completion;
>> +};
> 
> Is this structure part of the protocol, or just part of the linux
> implementation?
> If this is in the protocol, you should not have a 'bool' member in there, which
> does not have a well-defined binary representation across architectures.
> 

No, it's not part of specification just linux, added to support polling
based DVFS messages.

>> +/*
>> + * The SCP firmware providing SCM interface to OSPM and other agents must
>> + * execute only in little-endian mode as per SCMI specification, so any buffers
>> + * shared through SCMI should have their contents converted to little-endian
>> + */
> 
> That is a very odd thing to put into a specification, are you sure it requires
> a specific runtime endian-mode? I would bet that it only requires the protocol
> to use little-endian data, so better describe it like that.
> 

Right, my bad. Not sure where I copied that text from, but as you
mention specification just expects data to be in LE format.

[..]

> 
>> +#if IS_REACHABLE(CONFIG_ARM_SCMI_PROTOCOL)
>> +int scmi_handle_put(const struct scmi_handle *handle);
>> +const struct scmi_handle *scmi_handle_get(struct device *dev);
>> +const struct scmi_handle *devm_scmi_handle_get(struct device *dev);
> 
> IS_REACHABLE() can easily lead to confusion when the driver is
> a loadable module but never gets used by a built-in driver. Maybe use
> IS_ENABLED() here, and add a Kconfig symbol that other drivers
> can depend on if you want them to optionally use it, like:
> 
> config MAYBE_ARM_SCMI_PROTOCOL
>         default y if ARM_SCMI_PROTOCOL=n
>         default ARM_SCMI_PROTOCOL

OK, will check, we may not need that yet.

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 21/22] cpufreq: add support for CPU DVFS based on SCMI message protocol
@ 2017-10-05 11:20         ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-05 11:20 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Rafael J. Wysocki, Viresh Kumar, linux-pm

On Wed, Oct 4, 2017 at 5:01 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>> +
>>> +static struct platform_driver scmi_cpufreq_platdrv = {
>>> +       .driver = {
>>> +               .name   = "scmi-cpufreq",
>>> +       },
>>> +       .probe          = scmi_cpufreq_probe,
>>> +       .remove         = scmi_cpufreq_remove,
>>> +};
>>
>> You appear to have split this driver into the 'cpufreq' side and
>> the 'protocol' handler in a different file. I already commented that
>> the way the main scmi driver knows about all the protocols looks
>> bad, here we can see another aspect of the same problem.
>>
>> Rather than manually register a platform_device for the purpose
>> of connecting it to the cpufreq driver, there should be a way
>> to dynamically register the protocol from the cpufreq driver
>> and then have both in the same file.
>>
>
> I agree that should be possible. I took this approach for 2 reasons:
>
> 1. to avoid all sorts of probe ordering issues
> 2. we may have system with multiple instances of SCMI. E.g. a system
>    may have multiple remote processors, each controlling dvfs/power mgmt
>    of a subset of CPUs/devices controller in OS.
>
> I have to admit that I haven't thought too much in details yet. That's
> the main idea behind scmi_handle and restricting access to that only to
> sub-nodes in it. I am open to suggestions.

How about introducing a separate bus_type for protocols?
The platform_device you use here isn't really the best abstraction,
and with a new bus_type, you can handle multiple instances of
scmi as well as decoupling them from the protocol drivers.

      Arnd

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

* Re: [PATCH v3 21/22] cpufreq: add support for CPU DVFS based on SCMI message protocol
@ 2017-10-05 11:20         ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-05 11:20 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Rafael J. Wysocki, Viresh Kumar, linux-pm-u79uwXL29TY76Z2rM5mHXA

On Wed, Oct 4, 2017 at 5:01 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
>>> +
>>> +static struct platform_driver scmi_cpufreq_platdrv = {
>>> +       .driver = {
>>> +               .name   = "scmi-cpufreq",
>>> +       },
>>> +       .probe          = scmi_cpufreq_probe,
>>> +       .remove         = scmi_cpufreq_remove,
>>> +};
>>
>> You appear to have split this driver into the 'cpufreq' side and
>> the 'protocol' handler in a different file. I already commented that
>> the way the main scmi driver knows about all the protocols looks
>> bad, here we can see another aspect of the same problem.
>>
>> Rather than manually register a platform_device for the purpose
>> of connecting it to the cpufreq driver, there should be a way
>> to dynamically register the protocol from the cpufreq driver
>> and then have both in the same file.
>>
>
> I agree that should be possible. I took this approach for 2 reasons:
>
> 1. to avoid all sorts of probe ordering issues
> 2. we may have system with multiple instances of SCMI. E.g. a system
>    may have multiple remote processors, each controlling dvfs/power mgmt
>    of a subset of CPUs/devices controller in OS.
>
> I have to admit that I haven't thought too much in details yet. That's
> the main idea behind scmi_handle and restricting access to that only to
> sub-nodes in it. I am open to suggestions.

How about introducing a separate bus_type for protocols?
The platform_device you use here isn't really the best abstraction,
and with a new bus_type, you can handle multiple instances of
scmi as well as decoupling them from the protocol drivers.

      Arnd
--
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] 208+ messages in thread

* [PATCH v3 21/22] cpufreq: add support for CPU DVFS based on SCMI message protocol
@ 2017-10-05 11:20         ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-05 11:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Oct 4, 2017 at 5:01 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>> +
>>> +static struct platform_driver scmi_cpufreq_platdrv = {
>>> +       .driver = {
>>> +               .name   = "scmi-cpufreq",
>>> +       },
>>> +       .probe          = scmi_cpufreq_probe,
>>> +       .remove         = scmi_cpufreq_remove,
>>> +};
>>
>> You appear to have split this driver into the 'cpufreq' side and
>> the 'protocol' handler in a different file. I already commented that
>> the way the main scmi driver knows about all the protocols looks
>> bad, here we can see another aspect of the same problem.
>>
>> Rather than manually register a platform_device for the purpose
>> of connecting it to the cpufreq driver, there should be a way
>> to dynamically register the protocol from the cpufreq driver
>> and then have both in the same file.
>>
>
> I agree that should be possible. I took this approach for 2 reasons:
>
> 1. to avoid all sorts of probe ordering issues
> 2. we may have system with multiple instances of SCMI. E.g. a system
>    may have multiple remote processors, each controlling dvfs/power mgmt
>    of a subset of CPUs/devices controller in OS.
>
> I have to admit that I haven't thought too much in details yet. That's
> the main idea behind scmi_handle and restricting access to that only to
> sub-nodes in it. I am open to suggestions.

How about introducing a separate bus_type for protocols?
The platform_device you use here isn't really the best abstraction,
and with a new bus_type, you can handle multiple instances of
scmi as well as decoupling them from the protocol drivers.

      Arnd

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

* Re: [PATCH v3 21/22] cpufreq: add support for CPU DVFS based on SCMI message protocol
@ 2017-10-05 11:26           ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-05 11:26 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Rafael J. Wysocki, Viresh Kumar, linux-pm



On 05/10/17 12:20, Arnd Bergmann wrote:
> On Wed, Oct 4, 2017 at 5:01 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>>> +
>>>> +static struct platform_driver scmi_cpufreq_platdrv = {
>>>> +       .driver = {
>>>> +               .name   = "scmi-cpufreq",
>>>> +       },
>>>> +       .probe          = scmi_cpufreq_probe,
>>>> +       .remove         = scmi_cpufreq_remove,
>>>> +};
>>>
>>> You appear to have split this driver into the 'cpufreq' side and
>>> the 'protocol' handler in a different file. I already commented that
>>> the way the main scmi driver knows about all the protocols looks
>>> bad, here we can see another aspect of the same problem.
>>>
>>> Rather than manually register a platform_device for the purpose
>>> of connecting it to the cpufreq driver, there should be a way
>>> to dynamically register the protocol from the cpufreq driver
>>> and then have both in the same file.
>>>
>>
>> I agree that should be possible. I took this approach for 2 reasons:
>>
>> 1. to avoid all sorts of probe ordering issues
>> 2. we may have system with multiple instances of SCMI. E.g. a system
>>    may have multiple remote processors, each controlling dvfs/power mgmt
>>    of a subset of CPUs/devices controller in OS.
>>
>> I have to admit that I haven't thought too much in details yet. That's
>> the main idea behind scmi_handle and restricting access to that only to
>> sub-nodes in it. I am open to suggestions.
> 
> How about introducing a separate bus_type for protocols?
> The platform_device you use here isn't really the best abstraction,
> and with a new bus_type, you can handle multiple instances of
> scmi as well as decoupling them from the protocol drivers.
> 

Yes based on some discussion on this thread yesterday, I started
exploring and seem to have come to same conclusions. I will try to hack
and see how that evolves. Thanks for the suggestion.

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 21/22] cpufreq: add support for CPU DVFS based on SCMI message protocol
@ 2017-10-05 11:26           ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-05 11:26 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Rafael J. Wysocki, Viresh Kumar, linux-pm-u79uwXL29TY76Z2rM5mHXA



On 05/10/17 12:20, Arnd Bergmann wrote:
> On Wed, Oct 4, 2017 at 5:01 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
>>>> +
>>>> +static struct platform_driver scmi_cpufreq_platdrv = {
>>>> +       .driver = {
>>>> +               .name   = "scmi-cpufreq",
>>>> +       },
>>>> +       .probe          = scmi_cpufreq_probe,
>>>> +       .remove         = scmi_cpufreq_remove,
>>>> +};
>>>
>>> You appear to have split this driver into the 'cpufreq' side and
>>> the 'protocol' handler in a different file. I already commented that
>>> the way the main scmi driver knows about all the protocols looks
>>> bad, here we can see another aspect of the same problem.
>>>
>>> Rather than manually register a platform_device for the purpose
>>> of connecting it to the cpufreq driver, there should be a way
>>> to dynamically register the protocol from the cpufreq driver
>>> and then have both in the same file.
>>>
>>
>> I agree that should be possible. I took this approach for 2 reasons:
>>
>> 1. to avoid all sorts of probe ordering issues
>> 2. we may have system with multiple instances of SCMI. E.g. a system
>>    may have multiple remote processors, each controlling dvfs/power mgmt
>>    of a subset of CPUs/devices controller in OS.
>>
>> I have to admit that I haven't thought too much in details yet. That's
>> the main idea behind scmi_handle and restricting access to that only to
>> sub-nodes in it. I am open to suggestions.
> 
> How about introducing a separate bus_type for protocols?
> The platform_device you use here isn't really the best abstraction,
> and with a new bus_type, you can handle multiple instances of
> scmi as well as decoupling them from the protocol drivers.
> 

Yes based on some discussion on this thread yesterday, I started
exploring and seem to have come to same conclusions. I will try to hack
and see how that evolves. Thanks for the suggestion.

-- 
Regards,
Sudeep
--
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] 208+ messages in thread

* [PATCH v3 21/22] cpufreq: add support for CPU DVFS based on SCMI message protocol
@ 2017-10-05 11:26           ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-05 11:26 UTC (permalink / raw)
  To: linux-arm-kernel



On 05/10/17 12:20, Arnd Bergmann wrote:
> On Wed, Oct 4, 2017 at 5:01 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>>> +
>>>> +static struct platform_driver scmi_cpufreq_platdrv = {
>>>> +       .driver = {
>>>> +               .name   = "scmi-cpufreq",
>>>> +       },
>>>> +       .probe          = scmi_cpufreq_probe,
>>>> +       .remove         = scmi_cpufreq_remove,
>>>> +};
>>>
>>> You appear to have split this driver into the 'cpufreq' side and
>>> the 'protocol' handler in a different file. I already commented that
>>> the way the main scmi driver knows about all the protocols looks
>>> bad, here we can see another aspect of the same problem.
>>>
>>> Rather than manually register a platform_device for the purpose
>>> of connecting it to the cpufreq driver, there should be a way
>>> to dynamically register the protocol from the cpufreq driver
>>> and then have both in the same file.
>>>
>>
>> I agree that should be possible. I took this approach for 2 reasons:
>>
>> 1. to avoid all sorts of probe ordering issues
>> 2. we may have system with multiple instances of SCMI. E.g. a system
>>    may have multiple remote processors, each controlling dvfs/power mgmt
>>    of a subset of CPUs/devices controller in OS.
>>
>> I have to admit that I haven't thought too much in details yet. That's
>> the main idea behind scmi_handle and restricting access to that only to
>> sub-nodes in it. I am open to suggestions.
> 
> How about introducing a separate bus_type for protocols?
> The platform_device you use here isn't really the best abstraction,
> and with a new bus_type, you can handle multiple instances of
> scmi as well as decoupling them from the protocol drivers.
> 

Yes based on some discussion on this thread yesterday, I started
exploring and seem to have come to same conclusions. I will try to hack
and see how that evolves. Thanks for the suggestion.

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-10-05 11:56                 ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-05 11:56 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar, Rob Herring,
	Mark Rutland

On Wed, Oct 4, 2017 at 4:47 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> On 04/10/17 15:17, Arnd Bergmann wrote:
>> On Wed, Oct 4, 2017 at 3:53 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>> On 04/10/17 13:35, Arnd Bergmann wrote:
>>>> On Wed, Oct 4, 2017 at 1:07 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:

>> There are probably several ways of doing this better, we should see
>> what the best is we can come up with.
>>
>> I think generally speaking we need a way for a mailbox user to
>> know what it should use as the mailbox data here, so it is
>> able to talk to different incompatible mailbox providers.
>>
>> One idea I had is to use a nested mailbox driver, that turns
>> a doorbell or single-register styled mailbox into a variable-length
>> mailbox by adding a memory region, like
>>
>>     mailbox@1233000 {
>>         compatible = "vendor-hardware-specifc-id";
>>         interrupts = <34>;
>>         reg = <0x1233000 0x100>;
>>         #mbox-cells = <1>;
>>     };
>>
>>     mailbox {
>>            compatible = "shmem-mailbox";
>>            mboxes = <&/mailbox@1233000  25>;
>>            #mbox-cells = <1>;
>>            shmem = <&cpu_scp_lpri &cpu_scp_hpri>;
>>     };
>>
>> This would create one mailbox that only takes a register argument,
>> and another one that can take longer messages based on the first.
>> In your driver, you then refer to the second one and pass the
>> variable-length data into that directly.
>
> 1. IIUC it was intentional not to include shmem as part of mailbox
>    controller binding and was pushed to client drivers as it's generally
>    not part of mailbox IP block. I am not sure if there are any other
>    specific reasons for that, but I may be missing some facts.

Ok, I see.

> 2. I am not sure if we need nested driver/bindings (at-least to begin
>    with). On a platform I don't think both/all modes will be used.
>    I had  proposal for adding doorbell for ARM MHU based on extended
>    bindings, but it was rejected[1]. But I really preferred that over
>    the shim layer I had to add in v3.

Maybe we can come up with a more generic way to do doorbells
on top of mailboxes instead? This sounds like a problem that
would come back with other drivers, so the MHU-specific shim
will not be a permanent solution either.

       Arnd

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

* Re: [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-10-05 11:56                 ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-05 11:56 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar, Rob Herring,
	Mark Rutland

On Wed, Oct 4, 2017 at 4:47 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
> On 04/10/17 15:17, Arnd Bergmann wrote:
>> On Wed, Oct 4, 2017 at 3:53 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
>>> On 04/10/17 13:35, Arnd Bergmann wrote:
>>>> On Wed, Oct 4, 2017 at 1:07 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:

>> There are probably several ways of doing this better, we should see
>> what the best is we can come up with.
>>
>> I think generally speaking we need a way for a mailbox user to
>> know what it should use as the mailbox data here, so it is
>> able to talk to different incompatible mailbox providers.
>>
>> One idea I had is to use a nested mailbox driver, that turns
>> a doorbell or single-register styled mailbox into a variable-length
>> mailbox by adding a memory region, like
>>
>>     mailbox@1233000 {
>>         compatible = "vendor-hardware-specifc-id";
>>         interrupts = <34>;
>>         reg = <0x1233000 0x100>;
>>         #mbox-cells = <1>;
>>     };
>>
>>     mailbox {
>>            compatible = "shmem-mailbox";
>>            mboxes = <&/mailbox@1233000  25>;
>>            #mbox-cells = <1>;
>>            shmem = <&cpu_scp_lpri &cpu_scp_hpri>;
>>     };
>>
>> This would create one mailbox that only takes a register argument,
>> and another one that can take longer messages based on the first.
>> In your driver, you then refer to the second one and pass the
>> variable-length data into that directly.
>
> 1. IIUC it was intentional not to include shmem as part of mailbox
>    controller binding and was pushed to client drivers as it's generally
>    not part of mailbox IP block. I am not sure if there are any other
>    specific reasons for that, but I may be missing some facts.

Ok, I see.

> 2. I am not sure if we need nested driver/bindings (at-least to begin
>    with). On a platform I don't think both/all modes will be used.
>    I had  proposal for adding doorbell for ARM MHU based on extended
>    bindings, but it was rejected[1]. But I really preferred that over
>    the shim layer I had to add in v3.

Maybe we can come up with a more generic way to do doorbells
on top of mailboxes instead? This sounds like a problem that
would come back with other drivers, so the MHU-specific shim
will not be a permanent solution either.

       Arnd
--
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] 208+ messages in thread

* [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-10-05 11:56                 ` Arnd Bergmann
  0 siblings, 0 replies; 208+ messages in thread
From: Arnd Bergmann @ 2017-10-05 11:56 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Oct 4, 2017 at 4:47 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> On 04/10/17 15:17, Arnd Bergmann wrote:
>> On Wed, Oct 4, 2017 at 3:53 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>> On 04/10/17 13:35, Arnd Bergmann wrote:
>>>> On Wed, Oct 4, 2017 at 1:07 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:

>> There are probably several ways of doing this better, we should see
>> what the best is we can come up with.
>>
>> I think generally speaking we need a way for a mailbox user to
>> know what it should use as the mailbox data here, so it is
>> able to talk to different incompatible mailbox providers.
>>
>> One idea I had is to use a nested mailbox driver, that turns
>> a doorbell or single-register styled mailbox into a variable-length
>> mailbox by adding a memory region, like
>>
>>     mailbox at 1233000 {
>>         compatible = "vendor-hardware-specifc-id";
>>         interrupts = <34>;
>>         reg = <0x1233000 0x100>;
>>         #mbox-cells = <1>;
>>     };
>>
>>     mailbox {
>>            compatible = "shmem-mailbox";
>>            mboxes = <&/mailbox@1233000  25>;
>>            #mbox-cells = <1>;
>>            shmem = <&cpu_scp_lpri &cpu_scp_hpri>;
>>     };
>>
>> This would create one mailbox that only takes a register argument,
>> and another one that can take longer messages based on the first.
>> In your driver, you then refer to the second one and pass the
>> variable-length data into that directly.
>
> 1. IIUC it was intentional not to include shmem as part of mailbox
>    controller binding and was pushed to client drivers as it's generally
>    not part of mailbox IP block. I am not sure if there are any other
>    specific reasons for that, but I may be missing some facts.

Ok, I see.

> 2. I am not sure if we need nested driver/bindings (at-least to begin
>    with). On a platform I don't think both/all modes will be used.
>    I had  proposal for adding doorbell for ARM MHU based on extended
>    bindings, but it was rejected[1]. But I really preferred that over
>    the shim layer I had to add in v3.

Maybe we can come up with a more generic way to do doorbells
on top of mailboxes instead? This sounds like a problem that
would come back with other drivers, so the MHU-specific shim
will not be a permanent solution either.

       Arnd

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

* Re: [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
  2017-10-05 11:56                 ` Arnd Bergmann
@ 2017-10-05 12:56                   ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-05 12:56 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Rob Herring, Mark Rutland



On 05/10/17 12:56, Arnd Bergmann wrote:
> On Wed, Oct 4, 2017 at 4:47 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> On 04/10/17 15:17, Arnd Bergmann wrote:
>>> On Wed, Oct 4, 2017 at 3:53 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>>> On 04/10/17 13:35, Arnd Bergmann wrote:
>>>>> On Wed, Oct 4, 2017 at 1:07 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> 
>>> There are probably several ways of doing this better, we should see
>>> what the best is we can come up with.
>>>
>>> I think generally speaking we need a way for a mailbox user to
>>> know what it should use as the mailbox data here, so it is
>>> able to talk to different incompatible mailbox providers.
>>>
>>> One idea I had is to use a nested mailbox driver, that turns
>>> a doorbell or single-register styled mailbox into a variable-length
>>> mailbox by adding a memory region, like
>>>
>>>     mailbox@1233000 {
>>>         compatible = "vendor-hardware-specifc-id";
>>>         interrupts = <34>;
>>>         reg = <0x1233000 0x100>;
>>>         #mbox-cells = <1>;
>>>     };
>>>
>>>     mailbox {
>>>            compatible = "shmem-mailbox";
>>>            mboxes = <&/mailbox@1233000  25>;
>>>            #mbox-cells = <1>;
>>>            shmem = <&cpu_scp_lpri &cpu_scp_hpri>;
>>>     };
>>>
>>> This would create one mailbox that only takes a register argument,
>>> and another one that can take longer messages based on the first.
>>> In your driver, you then refer to the second one and pass the
>>> variable-length data into that directly.
>>
>> 1. IIUC it was intentional not to include shmem as part of mailbox
>>    controller binding and was pushed to client drivers as it's generally
>>    not part of mailbox IP block. I am not sure if there are any other
>>    specific reasons for that, but I may be missing some facts.
> 
> Ok, I see.
> 
>> 2. I am not sure if we need nested driver/bindings (at-least to begin
>>    with). On a platform I don't think both/all modes will be used.
>>    I had  proposal for adding doorbell for ARM MHU based on extended
>>    bindings, but it was rejected[1]. But I really preferred that over
>>    the shim layer I had to add in v3.
> 
> Maybe we can come up with a more generic way to do doorbells
> on top of mailboxes instead? This sounds like a problem that
> would come back with other drivers, so the MHU-specific shim
> will not be a permanent solution either.
> 

I completely agree. I have seen few drivers that just implement
doorbells in their controller. I will check them in details again.

-- 
Regards,
Sudeep

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

* [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-10-05 12:56                   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-05 12:56 UTC (permalink / raw)
  To: linux-arm-kernel



On 05/10/17 12:56, Arnd Bergmann wrote:
> On Wed, Oct 4, 2017 at 4:47 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> On 04/10/17 15:17, Arnd Bergmann wrote:
>>> On Wed, Oct 4, 2017 at 3:53 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>>> On 04/10/17 13:35, Arnd Bergmann wrote:
>>>>> On Wed, Oct 4, 2017 at 1:07 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> 
>>> There are probably several ways of doing this better, we should see
>>> what the best is we can come up with.
>>>
>>> I think generally speaking we need a way for a mailbox user to
>>> know what it should use as the mailbox data here, so it is
>>> able to talk to different incompatible mailbox providers.
>>>
>>> One idea I had is to use a nested mailbox driver, that turns
>>> a doorbell or single-register styled mailbox into a variable-length
>>> mailbox by adding a memory region, like
>>>
>>>     mailbox at 1233000 {
>>>         compatible = "vendor-hardware-specifc-id";
>>>         interrupts = <34>;
>>>         reg = <0x1233000 0x100>;
>>>         #mbox-cells = <1>;
>>>     };
>>>
>>>     mailbox {
>>>            compatible = "shmem-mailbox";
>>>            mboxes = <&/mailbox@1233000  25>;
>>>            #mbox-cells = <1>;
>>>            shmem = <&cpu_scp_lpri &cpu_scp_hpri>;
>>>     };
>>>
>>> This would create one mailbox that only takes a register argument,
>>> and another one that can take longer messages based on the first.
>>> In your driver, you then refer to the second one and pass the
>>> variable-length data into that directly.
>>
>> 1. IIUC it was intentional not to include shmem as part of mailbox
>>    controller binding and was pushed to client drivers as it's generally
>>    not part of mailbox IP block. I am not sure if there are any other
>>    specific reasons for that, but I may be missing some facts.
> 
> Ok, I see.
> 
>> 2. I am not sure if we need nested driver/bindings (at-least to begin
>>    with). On a platform I don't think both/all modes will be used.
>>    I had  proposal for adding doorbell for ARM MHU based on extended
>>    bindings, but it was rejected[1]. But I really preferred that over
>>    the shim layer I had to add in v3.
> 
> Maybe we can come up with a more generic way to do doorbells
> on top of mailboxes instead? This sounds like a problem that
> would come back with other drivers, so the MHU-specific shim
> will not be a permanent solution either.
> 

I completely agree. I have seen few drivers that just implement
doorbells in their controller. I will check them in details again.

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
  2017-10-04 12:35         ` Arnd Bergmann
@ 2017-10-05 13:20           ` Jassi Brar
  -1 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-05 13:20 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin, Rob Herring,
	Mark Rutland

On Wed, Oct 4, 2017 at 5:35 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Wed, Oct 4, 2017 at 1:07 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> On 04/10/17 11:50, Arnd Bergmann wrote:
>>> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:

>
>>>> +- shmem : List of phandle pointing to the shared memory(SHM) area as per
>>>> +         generic mailbox client binding.
>>>> +
>>>> +See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details
>>>> +about the generic mailbox controller and client driver bindings.
>>>> +
>>>> +The mailbox is the only permitted method of calling the SCMI firmware.
>>>> +Mailbox doorbell is used as a mechanism to alert the presence of a
>>>> +messages and/or notification.
>>>
>>> This looks odd: why not make the message itself part of the mailbox
>>> protocol here, and leave the shmem as a implementation detail of the
>>> mailbox driver?
>>>
>>
>> I am not sure if I follow you here. But generally shmem can be memory
>> carved out of anything in the system and it's dependent on the protocol
>> and the remote firmware rather than the mailbox hardware itself.
>
> I think the problem is the way we use the mailbox API in Linux, which
> is completely abstract at the moment: it could be a pure doorbell, a
> single-register for a data, some structured memory, or a
> variable-length message. The assumption today is that the mailbox
> user and the mailbox driver agree on the interpretation of that
> void pointer.
>
The way controllers and remote firmwares are paired there is no other
way to write reusable code.

> This breaks down here, as you require the message to be a
> variable-length message in a fixed physical location, but assume that
> the mailbox serves only as a doorbell.
>
That is a valid usecase, already supported. There's an optional
callback provided by the api to fill SHMEM
mbox_chan->mbox_client->tx_prepare()

Data passing via SHMEM is purely optional because some controllers
have deep fifos to carry data while some platforms may not have any
region of memory shared between Linux and the remote firmware.

Thanks.

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

* [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-10-05 13:20           ` Jassi Brar
  0 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-05 13:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Oct 4, 2017 at 5:35 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Wed, Oct 4, 2017 at 1:07 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> On 04/10/17 11:50, Arnd Bergmann wrote:
>>> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:

>
>>>> +- shmem : List of phandle pointing to the shared memory(SHM) area as per
>>>> +         generic mailbox client binding.
>>>> +
>>>> +See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details
>>>> +about the generic mailbox controller and client driver bindings.
>>>> +
>>>> +The mailbox is the only permitted method of calling the SCMI firmware.
>>>> +Mailbox doorbell is used as a mechanism to alert the presence of a
>>>> +messages and/or notification.
>>>
>>> This looks odd: why not make the message itself part of the mailbox
>>> protocol here, and leave the shmem as a implementation detail of the
>>> mailbox driver?
>>>
>>
>> I am not sure if I follow you here. But generally shmem can be memory
>> carved out of anything in the system and it's dependent on the protocol
>> and the remote firmware rather than the mailbox hardware itself.
>
> I think the problem is the way we use the mailbox API in Linux, which
> is completely abstract at the moment: it could be a pure doorbell, a
> single-register for a data, some structured memory, or a
> variable-length message. The assumption today is that the mailbox
> user and the mailbox driver agree on the interpretation of that
> void pointer.
>
The way controllers and remote firmwares are paired there is no other
way to write reusable code.

> This breaks down here, as you require the message to be a
> variable-length message in a fixed physical location, but assume that
> the mailbox serves only as a doorbell.
>
That is a valid usecase, already supported. There's an optional
callback provided by the api to fill SHMEM
mbox_chan->mbox_client->tx_prepare()

Data passing via SHMEM is purely optional because some controllers
have deep fifos to carry data while some platforms may not have any
region of memory shared between Linux and the remote firmware.

Thanks.

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

* Re: [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
  2017-10-05 13:20           ` Jassi Brar
@ 2017-10-05 14:10             ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-05 14:10 UTC (permalink / raw)
  To: Jassi Brar, Arnd Bergmann
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin, Rob Herring,
	Mark Rutland



On 05/10/17 14:20, Jassi Brar wrote:
> On Wed, Oct 4, 2017 at 5:35 AM, Arnd Bergmann <arnd@arndb.de> wrote:
>> On Wed, Oct 4, 2017 at 1:07 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>> On 04/10/17 11:50, Arnd Bergmann wrote:
>>>> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> 
>>
>>>>> +- shmem : List of phandle pointing to the shared memory(SHM) area as per
>>>>> +         generic mailbox client binding.
>>>>> +
>>>>> +See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details
>>>>> +about the generic mailbox controller and client driver bindings.
>>>>> +
>>>>> +The mailbox is the only permitted method of calling the SCMI firmware.
>>>>> +Mailbox doorbell is used as a mechanism to alert the presence of a
>>>>> +messages and/or notification.
>>>>
>>>> This looks odd: why not make the message itself part of the mailbox
>>>> protocol here, and leave the shmem as a implementation detail of the
>>>> mailbox driver?
>>>>
>>>
>>> I am not sure if I follow you here. But generally shmem can be memory
>>> carved out of anything in the system and it's dependent on the protocol
>>> and the remote firmware rather than the mailbox hardware itself.
>>
>> I think the problem is the way we use the mailbox API in Linux, which
>> is completely abstract at the moment: it could be a pure doorbell, a
>> single-register for a data, some structured memory, or a
>> variable-length message. The assumption today is that the mailbox
>> user and the mailbox driver agree on the interpretation of that
>> void pointer.
>>
> The way controllers and remote firmwares are paired there is no other
> way to write reusable code.
> 
>> This breaks down here, as you require the message to be a
>> variable-length message in a fixed physical location, but assume that
>> the mailbox serves only as a doorbell.
>>
> That is a valid usecase, already supported. There's an optional
> callback provided by the api to fill SHMEM
> mbox_chan->mbox_client->tx_prepare()
> 

Thanks, I missed to mention this earlier. But the point here is to avoid
the shim layer with each protocol for most common use case like doorbell.

But what I understood from Arnd's suggestion is to have another API
which just *sends signal* _rather_than_ *send data" to identify between
the two.
-- 
Regards,
Sudeep

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

* [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
@ 2017-10-05 14:10             ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-05 14:10 UTC (permalink / raw)
  To: linux-arm-kernel



On 05/10/17 14:20, Jassi Brar wrote:
> On Wed, Oct 4, 2017 at 5:35 AM, Arnd Bergmann <arnd@arndb.de> wrote:
>> On Wed, Oct 4, 2017 at 1:07 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>> On 04/10/17 11:50, Arnd Bergmann wrote:
>>>> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> 
>>
>>>>> +- shmem : List of phandle pointing to the shared memory(SHM) area as per
>>>>> +         generic mailbox client binding.
>>>>> +
>>>>> +See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details
>>>>> +about the generic mailbox controller and client driver bindings.
>>>>> +
>>>>> +The mailbox is the only permitted method of calling the SCMI firmware.
>>>>> +Mailbox doorbell is used as a mechanism to alert the presence of a
>>>>> +messages and/or notification.
>>>>
>>>> This looks odd: why not make the message itself part of the mailbox
>>>> protocol here, and leave the shmem as a implementation detail of the
>>>> mailbox driver?
>>>>
>>>
>>> I am not sure if I follow you here. But generally shmem can be memory
>>> carved out of anything in the system and it's dependent on the protocol
>>> and the remote firmware rather than the mailbox hardware itself.
>>
>> I think the problem is the way we use the mailbox API in Linux, which
>> is completely abstract at the moment: it could be a pure doorbell, a
>> single-register for a data, some structured memory, or a
>> variable-length message. The assumption today is that the mailbox
>> user and the mailbox driver agree on the interpretation of that
>> void pointer.
>>
> The way controllers and remote firmwares are paired there is no other
> way to write reusable code.
> 
>> This breaks down here, as you require the message to be a
>> variable-length message in a fixed physical location, but assume that
>> the mailbox serves only as a doorbell.
>>
> That is a valid usecase, already supported. There's an optional
> callback provided by the api to fill SHMEM
> mbox_chan->mbox_client->tx_prepare()
> 

Thanks, I missed to mention this earlier. But the point here is to avoid
the shim layer with each protocol for most common use case like doorbell.

But what I understood from Arnd's suggestion is to have another API
which just *sends signal* _rather_than_ *send data" to identify between
the two.
-- 
Regards,
Sudeep

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

* Re: [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
@ 2017-10-05 23:20     ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2017-10-05 23:20 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Mark Rutland

On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
> This patch adds ARM MHU specific mailbox client bindings to support
> SCMI. Since SCMI specification just requires doorbell mechanism from
> mailbox controllers, we add mailbox data to specify the doorbell bit(s).
> 
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> ---
>  .../devicetree/bindings/arm/arm,mhu-scmi.txt          | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
> new file mode 100644
> index 000000000000..8c106f1cdeb8
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
> @@ -0,0 +1,19 @@
> +ARM MHU mailbox client bindings for SCMI Message Protocol
> +----------------------------------------------------------
> +
> +This binding is intended to define the ARM MHU specific extensions to
> +the generic SCMI bindings[2].
> +
> +Required properties:
> +
> +The scmi node with the following properties shall be under the /firmware/ node.
> +
> +- compatible : shall be "arm,scmi" and "arm,mhu-scmi"

Most specific first.

> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
> +	      data as expected by the mailbox controller

Shouldn't that be cells as part of mboxes property?

> +
> +See [1] for details on all other required/optional properties of the generic
> +mailbox controller and [2] for generic SCMI bindings.
> +
> +[1] Documentation/devicetree/bindings/mailbox/mailbox.txt
> +[2] Documentation/devicetree/bindings/arm/arm,scmi.txt
> -- 
> 2.7.4
> 

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

* Re: [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
@ 2017-10-05 23:20     ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2017-10-05 23:20 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Mark Rutland

On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
> This patch adds ARM MHU specific mailbox client bindings to support
> SCMI. Since SCMI specification just requires doorbell mechanism from
> mailbox controllers, we add mailbox data to specify the doorbell bit(s).
> 
> Cc: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Cc: Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>
> Signed-off-by: Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org>
> ---
>  .../devicetree/bindings/arm/arm,mhu-scmi.txt          | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
> new file mode 100644
> index 000000000000..8c106f1cdeb8
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
> @@ -0,0 +1,19 @@
> +ARM MHU mailbox client bindings for SCMI Message Protocol
> +----------------------------------------------------------
> +
> +This binding is intended to define the ARM MHU specific extensions to
> +the generic SCMI bindings[2].
> +
> +Required properties:
> +
> +The scmi node with the following properties shall be under the /firmware/ node.
> +
> +- compatible : shall be "arm,scmi" and "arm,mhu-scmi"

Most specific first.

> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
> +	      data as expected by the mailbox controller

Shouldn't that be cells as part of mboxes property?

> +
> +See [1] for details on all other required/optional properties of the generic
> +mailbox controller and [2] for generic SCMI bindings.
> +
> +[1] Documentation/devicetree/bindings/mailbox/mailbox.txt
> +[2] Documentation/devicetree/bindings/arm/arm,scmi.txt
> -- 
> 2.7.4
> 
--
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] 208+ messages in thread

* [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
@ 2017-10-05 23:20     ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2017-10-05 23:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
> This patch adds ARM MHU specific mailbox client bindings to support
> SCMI. Since SCMI specification just requires doorbell mechanism from
> mailbox controllers, we add mailbox data to specify the doorbell bit(s).
> 
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> ---
>  .../devicetree/bindings/arm/arm,mhu-scmi.txt          | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
> new file mode 100644
> index 000000000000..8c106f1cdeb8
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
> @@ -0,0 +1,19 @@
> +ARM MHU mailbox client bindings for SCMI Message Protocol
> +----------------------------------------------------------
> +
> +This binding is intended to define the ARM MHU specific extensions to
> +the generic SCMI bindings[2].
> +
> +Required properties:
> +
> +The scmi node with the following properties shall be under the /firmware/ node.
> +
> +- compatible : shall be "arm,scmi" and "arm,mhu-scmi"

Most specific first.

> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
> +	      data as expected by the mailbox controller

Shouldn't that be cells as part of mboxes property?

> +
> +See [1] for details on all other required/optional properties of the generic
> +mailbox controller and [2] for generic SCMI bindings.
> +
> +[1] Documentation/devicetree/bindings/mailbox/mailbox.txt
> +[2] Documentation/devicetree/bindings/arm/arm,scmi.txt
> -- 
> 2.7.4
> 

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

* Re: [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
  2017-10-05 23:20     ` Rob Herring
@ 2017-10-06  9:42       ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-06  9:42 UTC (permalink / raw)
  To: Rob Herring
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Arnd Bergmann, Loc Ho, Alexey Klimov,
	Ryan Harkin, Jassi Brar, Mark Rutland



On 06/10/17 00:20, Rob Herring wrote:
> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
>> This patch adds ARM MHU specific mailbox client bindings to support
>> SCMI. Since SCMI specification just requires doorbell mechanism from
>> mailbox controllers, we add mailbox data to specify the doorbell bit(s).
>>
>> Cc: Rob Herring <robh+dt@kernel.org>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>> ---
>>  .../devicetree/bindings/arm/arm,mhu-scmi.txt          | 19 +++++++++++++++++++
>>  1 file changed, 19 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
>>
>> diff --git a/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
>> new file mode 100644
>> index 000000000000..8c106f1cdeb8
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
>> @@ -0,0 +1,19 @@
>> +ARM MHU mailbox client bindings for SCMI Message Protocol
>> +----------------------------------------------------------
>> +
>> +This binding is intended to define the ARM MHU specific extensions to
>> +the generic SCMI bindings[2].
>> +
>> +Required properties:
>> +
>> +The scmi node with the following properties shall be under the /firmware/ node.
>> +
>> +- compatible : shall be "arm,scmi" and "arm,mhu-scmi"
> 
> Most specific first.
> 

Ah right, sorry for missing that.

>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>> +	      data as expected by the mailbox controller
> 
> Shouldn't that be cells as part of mboxes property?
> 

Yes, that's what I proposed with my ARM MHU doorbell bindings[1]. Since
Jassi rejected that and asked to make it part client. But I agree with
you comment. Even Arnd had similar opinion.

-- 
Regards,
Sudeep

[1] https://patchwork.kernel.org/patch/9745683/

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

* [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
@ 2017-10-06  9:42       ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-06  9:42 UTC (permalink / raw)
  To: linux-arm-kernel



On 06/10/17 00:20, Rob Herring wrote:
> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
>> This patch adds ARM MHU specific mailbox client bindings to support
>> SCMI. Since SCMI specification just requires doorbell mechanism from
>> mailbox controllers, we add mailbox data to specify the doorbell bit(s).
>>
>> Cc: Rob Herring <robh+dt@kernel.org>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>> ---
>>  .../devicetree/bindings/arm/arm,mhu-scmi.txt          | 19 +++++++++++++++++++
>>  1 file changed, 19 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
>>
>> diff --git a/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
>> new file mode 100644
>> index 000000000000..8c106f1cdeb8
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
>> @@ -0,0 +1,19 @@
>> +ARM MHU mailbox client bindings for SCMI Message Protocol
>> +----------------------------------------------------------
>> +
>> +This binding is intended to define the ARM MHU specific extensions to
>> +the generic SCMI bindings[2].
>> +
>> +Required properties:
>> +
>> +The scmi node with the following properties shall be under the /firmware/ node.
>> +
>> +- compatible : shall be "arm,scmi" and "arm,mhu-scmi"
> 
> Most specific first.
> 

Ah right, sorry for missing that.

>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>> +	      data as expected by the mailbox controller
> 
> Shouldn't that be cells as part of mboxes property?
> 

Yes, that's what I proposed with my ARM MHU doorbell bindings[1]. Since
Jassi rejected that and asked to make it part client. But I agree with
you comment. Even Arnd had similar opinion.

-- 
Regards,
Sudeep

[1] https://patchwork.kernel.org/patch/9745683/

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

* Re: [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
  2017-10-05 23:20     ` Rob Herring
  (?)
@ 2017-10-06 11:01       ` Jassi Brar
  -1 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-06 11:01 UTC (permalink / raw)
  To: Rob Herring
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Arnd Bergmann, Loc Ho, Alexey Klimov,
	Ryan Harkin, Mark Rutland

On Fri, Oct 6, 2017 at 4:50 AM, Rob Herring <robh@kernel.org> wrote:
> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
>> This patch adds ARM MHU specific mailbox client bindings to support
>> SCMI. Since SCMI specification just requires doorbell mechanism from
>> mailbox controllers, we add mailbox data to specify the doorbell bit(s).
>>
>> Cc: Rob Herring <robh+dt@kernel.org>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>> ---
>>  .../devicetree/bindings/arm/arm,mhu-scmi.txt          | 19 +++++++++++++++++++
>>  1 file changed, 19 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
>>
>> diff --git a/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
>> new file mode 100644
>> index 000000000000..8c106f1cdeb8
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
>> @@ -0,0 +1,19 @@
>> +ARM MHU mailbox client bindings for SCMI Message Protocol
>> +----------------------------------------------------------
>> +
>> +This binding is intended to define the ARM MHU specific extensions to
>> +the generic SCMI bindings[2].
>> +
>> +Required properties:
>> +
>> +The scmi node with the following properties shall be under the /firmware/ node.
>> +
>> +- compatible : shall be "arm,scmi" and "arm,mhu-scmi"
>
> Most specific first.
>
>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>> +           data as expected by the mailbox controller
>
> Shouldn't that be cells as part of mboxes property?
>
A MHU client can send any number of commands (such u32 values) over a channel.
This client (SCMI) sends just one command over a channel, but other
clients may/do send two or more.

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

* Re: [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
@ 2017-10-06 11:01       ` Jassi Brar
  0 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-06 11:01 UTC (permalink / raw)
  To: Rob Herring
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Arnd Bergmann, Loc Ho, Alexey Klimov,
	Ryan Harkin, Mark Rutland

On Fri, Oct 6, 2017 at 4:50 AM, Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
>> This patch adds ARM MHU specific mailbox client bindings to support
>> SCMI. Since SCMI specification just requires doorbell mechanism from
>> mailbox controllers, we add mailbox data to specify the doorbell bit(s).
>>
>> Cc: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
>> Cc: Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>
>> Signed-off-by: Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org>
>> ---
>>  .../devicetree/bindings/arm/arm,mhu-scmi.txt          | 19 +++++++++++++++++++
>>  1 file changed, 19 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
>>
>> diff --git a/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
>> new file mode 100644
>> index 000000000000..8c106f1cdeb8
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
>> @@ -0,0 +1,19 @@
>> +ARM MHU mailbox client bindings for SCMI Message Protocol
>> +----------------------------------------------------------
>> +
>> +This binding is intended to define the ARM MHU specific extensions to
>> +the generic SCMI bindings[2].
>> +
>> +Required properties:
>> +
>> +The scmi node with the following properties shall be under the /firmware/ node.
>> +
>> +- compatible : shall be "arm,scmi" and "arm,mhu-scmi"
>
> Most specific first.
>
>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>> +           data as expected by the mailbox controller
>
> Shouldn't that be cells as part of mboxes property?
>
A MHU client can send any number of commands (such u32 values) over a channel.
This client (SCMI) sends just one command over a channel, but other
clients may/do send two or more.
--
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] 208+ messages in thread

* [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
@ 2017-10-06 11:01       ` Jassi Brar
  0 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-06 11:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 6, 2017 at 4:50 AM, Rob Herring <robh@kernel.org> wrote:
> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
>> This patch adds ARM MHU specific mailbox client bindings to support
>> SCMI. Since SCMI specification just requires doorbell mechanism from
>> mailbox controllers, we add mailbox data to specify the doorbell bit(s).
>>
>> Cc: Rob Herring <robh+dt@kernel.org>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>> ---
>>  .../devicetree/bindings/arm/arm,mhu-scmi.txt          | 19 +++++++++++++++++++
>>  1 file changed, 19 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
>>
>> diff --git a/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
>> new file mode 100644
>> index 000000000000..8c106f1cdeb8
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
>> @@ -0,0 +1,19 @@
>> +ARM MHU mailbox client bindings for SCMI Message Protocol
>> +----------------------------------------------------------
>> +
>> +This binding is intended to define the ARM MHU specific extensions to
>> +the generic SCMI bindings[2].
>> +
>> +Required properties:
>> +
>> +The scmi node with the following properties shall be under the /firmware/ node.
>> +
>> +- compatible : shall be "arm,scmi" and "arm,mhu-scmi"
>
> Most specific first.
>
>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>> +           data as expected by the mailbox controller
>
> Shouldn't that be cells as part of mboxes property?
>
A MHU client can send any number of commands (such u32 values) over a channel.
This client (SCMI) sends just one command over a channel, but other
clients may/do send two or more.

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

* Re: [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-06 11:26       ` Jassi Brar
  0 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-06 11:26 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin

On Wed, Oct 4, 2017 at 5:06 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> This patch adds ARM MHU specific mailbox interface for SCMI.
>>
>> Cc: Arnd Bergmann <arnd@arndb.de>
>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>
> This clearly needs an explanation why we need another driver.
>
Yes the patch needs explanation which is that we need a shim layer to
map SCMI requests onto what the underlying controller expects. The
alternative was to clone the controller driver (MHU now and others
later when their platforms support SCMI) and pretend SCMI is the only
client they are ever going to serve.

BTW, I haven't reviewed this patchset yet so I am not sure about this
code but I do believe we need a transport layer (this shim driver)
between generic SCMI implementation and each controller driver.

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

* Re: [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-06 11:26       ` Jassi Brar
  0 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-06 11:26 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin

On Wed, Oct 4, 2017 at 5:06 PM, Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org> wrote:
> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
>> This patch adds ARM MHU specific mailbox interface for SCMI.
>>
>> Cc: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
>> Signed-off-by: Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org>
>
> This clearly needs an explanation why we need another driver.
>
Yes the patch needs explanation which is that we need a shim layer to
map SCMI requests onto what the underlying controller expects. The
alternative was to clone the controller driver (MHU now and others
later when their platforms support SCMI) and pretend SCMI is the only
client they are ever going to serve.

BTW, I haven't reviewed this patchset yet so I am not sure about this
code but I do believe we need a transport layer (this shim driver)
between generic SCMI implementation and each controller driver.
--
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] 208+ messages in thread

* [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-06 11:26       ` Jassi Brar
  0 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-06 11:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Oct 4, 2017 at 5:06 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> This patch adds ARM MHU specific mailbox interface for SCMI.
>>
>> Cc: Arnd Bergmann <arnd@arndb.de>
>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>
> This clearly needs an explanation why we need another driver.
>
Yes the patch needs explanation which is that we need a shim layer to
map SCMI requests onto what the underlying controller expects. The
alternative was to clone the controller driver (MHU now and others
later when their platforms support SCMI) and pretend SCMI is the only
client they are ever going to serve.

BTW, I haven't reviewed this patchset yet so I am not sure about this
code but I do believe we need a transport layer (this shim driver)
between generic SCMI implementation and each controller driver.

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

* Re: [PATCH v3 15/22] firmware: arm_scmi: abstract mailbox interface
@ 2017-10-06 11:34         ` Jassi Brar
  0 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-06 11:34 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Arnd Bergmann, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin

On Wed, Oct 4, 2017 at 5:02 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:

> Also, I have added shim only for specific controllers that need them.
> E.g. ARM MHU as Jassi disagreed to add doorbell mechanism to that.
> mbox_if provides default implementation that just calls direct mailbox
> APIs.
>
Yeah you could hack away the MHU driver to make your life easy at the
cost of duplicated code and extra DT bindings, but for a moment think
what if your development platform wasn't MHU but, say, Rockchip
mailbox controller?

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

* Re: [PATCH v3 15/22] firmware: arm_scmi: abstract mailbox interface
@ 2017-10-06 11:34         ` Jassi Brar
  0 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-06 11:34 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Arnd Bergmann, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin

On Wed, Oct 4, 2017 at 5:02 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:

> Also, I have added shim only for specific controllers that need them.
> E.g. ARM MHU as Jassi disagreed to add doorbell mechanism to that.
> mbox_if provides default implementation that just calls direct mailbox
> APIs.
>
Yeah you could hack away the MHU driver to make your life easy at the
cost of duplicated code and extra DT bindings, but for a moment think
what if your development platform wasn't MHU but, say, Rockchip
mailbox controller?
--
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] 208+ messages in thread

* [PATCH v3 15/22] firmware: arm_scmi: abstract mailbox interface
@ 2017-10-06 11:34         ` Jassi Brar
  0 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-06 11:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Oct 4, 2017 at 5:02 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:

> Also, I have added shim only for specific controllers that need them.
> E.g. ARM MHU as Jassi disagreed to add doorbell mechanism to that.
> mbox_if provides default implementation that just calls direct mailbox
> APIs.
>
Yeah you could hack away the MHU driver to make your life easy at the
cost of duplicated code and extra DT bindings, but for a moment think
what if your development platform wasn't MHU but, say, Rockchip
mailbox controller?

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

* Re: [PATCH v3 15/22] firmware: arm_scmi: abstract mailbox interface
@ 2017-10-06 13:27           ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-06 13:27 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Sudeep Holla, Arnd Bergmann, ALKML, LKML, DTML, Roy Franz,
	Harb Abdulhamid, Nishanth Menon, Loc Ho, Alexey Klimov,
	Ryan Harkin



On 06/10/17 12:34, Jassi Brar wrote:
> On Wed, Oct 4, 2017 at 5:02 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> 
>> Also, I have added shim only for specific controllers that need them.
>> E.g. ARM MHU as Jassi disagreed to add doorbell mechanism to that.
>> mbox_if provides default implementation that just calls direct mailbox
>> APIs.
>>
> Yeah you could hack away the MHU driver to make your life easy at the
> cost of duplicated code and extra DT bindings, but for a moment think
> what if your development platform wasn't MHU but, say, Rockchip
> mailbox controller?
> 

As mentioned before I understand your concern. But the point is this
needs to be replicated with each protocol on that controller. So as Arnd
pointed out we can reduce that by generalizing common things like doorbell.

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 15/22] firmware: arm_scmi: abstract mailbox interface
@ 2017-10-06 13:27           ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-06 13:27 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Sudeep Holla, Arnd Bergmann, ALKML, LKML, DTML, Roy Franz,
	Harb Abdulhamid, Nishanth Menon, Loc Ho, Alexey Klimov,
	Ryan Harkin



On 06/10/17 12:34, Jassi Brar wrote:
> On Wed, Oct 4, 2017 at 5:02 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
> 
>> Also, I have added shim only for specific controllers that need them.
>> E.g. ARM MHU as Jassi disagreed to add doorbell mechanism to that.
>> mbox_if provides default implementation that just calls direct mailbox
>> APIs.
>>
> Yeah you could hack away the MHU driver to make your life easy at the
> cost of duplicated code and extra DT bindings, but for a moment think
> what if your development platform wasn't MHU but, say, Rockchip
> mailbox controller?
> 

As mentioned before I understand your concern. But the point is this
needs to be replicated with each protocol on that controller. So as Arnd
pointed out we can reduce that by generalizing common things like doorbell.

-- 
Regards,
Sudeep
--
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] 208+ messages in thread

* [PATCH v3 15/22] firmware: arm_scmi: abstract mailbox interface
@ 2017-10-06 13:27           ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-06 13:27 UTC (permalink / raw)
  To: linux-arm-kernel



On 06/10/17 12:34, Jassi Brar wrote:
> On Wed, Oct 4, 2017 at 5:02 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> 
>> Also, I have added shim only for specific controllers that need them.
>> E.g. ARM MHU as Jassi disagreed to add doorbell mechanism to that.
>> mbox_if provides default implementation that just calls direct mailbox
>> APIs.
>>
> Yeah you could hack away the MHU driver to make your life easy at the
> cost of duplicated code and extra DT bindings, but for a moment think
> what if your development platform wasn't MHU but, say, Rockchip
> mailbox controller?
> 

As mentioned before I understand your concern. But the point is this
needs to be replicated with each protocol on that controller. So as Arnd
pointed out we can reduce that by generalizing common things like doorbell.

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
  2017-10-06 11:26       ` Jassi Brar
@ 2017-10-06 13:32         ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-06 13:32 UTC (permalink / raw)
  To: Jassi Brar, Arnd Bergmann
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin



On 06/10/17 12:26, Jassi Brar wrote:
> On Wed, Oct 4, 2017 at 5:06 PM, Arnd Bergmann <arnd@arndb.de> wrote:
>> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>> This patch adds ARM MHU specific mailbox interface for SCMI.
>>>
>>> Cc: Arnd Bergmann <arnd@arndb.de>
>>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>>
>> This clearly needs an explanation why we need another driver.
>>
> Yes the patch needs explanation which is that we need a shim layer to
> map SCMI requests onto what the underlying controller expects. The
> alternative was to clone the controller driver (MHU now and others
> later when their platforms support SCMI) and pretend SCMI is the only
> client they are ever going to serve.
> 

Again that's not the point, doorbell is more common feature and that can
be supported. As SCMI expects doorbell feature in the specification, it
just need to support that class of controllers.

> BTW, I haven't reviewed this patchset yet so I am not sure about this
> code but I do believe we need a transport layer (this shim driver)
> between generic SCMI implementation and each controller driver.
> 

Again Arnd's point was to extend mailbox API instead of adding this
abstract layer which I think is more elegant. The controllers that
can provide that feature will support that.

-- 
Regards,
Sudeep

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

* [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-06 13:32         ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-06 13:32 UTC (permalink / raw)
  To: linux-arm-kernel



On 06/10/17 12:26, Jassi Brar wrote:
> On Wed, Oct 4, 2017 at 5:06 PM, Arnd Bergmann <arnd@arndb.de> wrote:
>> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>> This patch adds ARM MHU specific mailbox interface for SCMI.
>>>
>>> Cc: Arnd Bergmann <arnd@arndb.de>
>>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>>
>> This clearly needs an explanation why we need another driver.
>>
> Yes the patch needs explanation which is that we need a shim layer to
> map SCMI requests onto what the underlying controller expects. The
> alternative was to clone the controller driver (MHU now and others
> later when their platforms support SCMI) and pretend SCMI is the only
> client they are ever going to serve.
> 

Again that's not the point, doorbell is more common feature and that can
be supported. As SCMI expects doorbell feature in the specification, it
just need to support that class of controllers.

> BTW, I haven't reviewed this patchset yet so I am not sure about this
> code but I do believe we need a transport layer (this shim driver)
> between generic SCMI implementation and each controller driver.
> 

Again Arnd's point was to extend mailbox API instead of adding this
abstract layer which I think is more elegant. The controllers that
can provide that feature will support that.

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 15/22] firmware: arm_scmi: abstract mailbox interface
  2017-10-06 13:27           ` Sudeep Holla
@ 2017-10-06 13:34             ` Jassi Brar
  -1 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-06 13:34 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Arnd Bergmann, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin

On Fri, Oct 6, 2017 at 6:57 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
>
> On 06/10/17 12:34, Jassi Brar wrote:
>> On Wed, Oct 4, 2017 at 5:02 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>
>>> Also, I have added shim only for specific controllers that need them.
>>> E.g. ARM MHU as Jassi disagreed to add doorbell mechanism to that.
>>> mbox_if provides default implementation that just calls direct mailbox
>>> APIs.
>>>
>> Yeah you could hack away the MHU driver to make your life easy at the
>> cost of duplicated code and extra DT bindings, but for a moment think
>> what if your development platform wasn't MHU but, say, Rockchip
>> mailbox controller?
>>
>
> As mentioned before I understand your concern. But the point is this
> needs to be replicated with each protocol on that controller.
>
Only generic protocols need to have a platform specific transport
layer. There's no escaping that.

> So as Arnd
> pointed out we can reduce that by generalizing common things like doorbell.
>
Rockchip, and most other controllers, has no "doorbell". And yet each
is perfectly capable of supporting SCMI.
Looking forward to your "generalised doorbell".

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

* [PATCH v3 15/22] firmware: arm_scmi: abstract mailbox interface
@ 2017-10-06 13:34             ` Jassi Brar
  0 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-06 13:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 6, 2017 at 6:57 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
>
> On 06/10/17 12:34, Jassi Brar wrote:
>> On Wed, Oct 4, 2017 at 5:02 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>
>>> Also, I have added shim only for specific controllers that need them.
>>> E.g. ARM MHU as Jassi disagreed to add doorbell mechanism to that.
>>> mbox_if provides default implementation that just calls direct mailbox
>>> APIs.
>>>
>> Yeah you could hack away the MHU driver to make your life easy at the
>> cost of duplicated code and extra DT bindings, but for a moment think
>> what if your development platform wasn't MHU but, say, Rockchip
>> mailbox controller?
>>
>
> As mentioned before I understand your concern. But the point is this
> needs to be replicated with each protocol on that controller.
>
Only generic protocols need to have a platform specific transport
layer. There's no escaping that.

> So as Arnd
> pointed out we can reduce that by generalizing common things like doorbell.
>
Rockchip, and most other controllers, has no "doorbell". And yet each
is perfectly capable of supporting SCMI.
Looking forward to your "generalised doorbell".

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

* Re: [PATCH v3 15/22] firmware: arm_scmi: abstract mailbox interface
  2017-10-06 13:34             ` Jassi Brar
@ 2017-10-06 13:41               ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-06 13:41 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Sudeep Holla, Arnd Bergmann, ALKML, LKML, DTML, Roy Franz,
	Harb Abdulhamid, Nishanth Menon, Loc Ho, Alexey Klimov,
	Ryan Harkin



On 06/10/17 14:34, Jassi Brar wrote:
> On Fri, Oct 6, 2017 at 6:57 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>
>>
>> On 06/10/17 12:34, Jassi Brar wrote:
>>> On Wed, Oct 4, 2017 at 5:02 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>>
>>>> Also, I have added shim only for specific controllers that need them.
>>>> E.g. ARM MHU as Jassi disagreed to add doorbell mechanism to that.
>>>> mbox_if provides default implementation that just calls direct mailbox
>>>> APIs.
>>>>
>>> Yeah you could hack away the MHU driver to make your life easy at the
>>> cost of duplicated code and extra DT bindings, but for a moment think
>>> what if your development platform wasn't MHU but, say, Rockchip
>>> mailbox controller?
>>>
>>
>> As mentioned before I understand your concern. But the point is this
>> needs to be replicated with each protocol on that controller.
>>
> Only generic protocols need to have a platform specific transport
> layer. There's no escaping that.
> 
>> So as Arnd
>> pointed out we can reduce that by generalizing common things like doorbell.
>>
> Rockchip, and most other controllers, has no "doorbell". And yet each
> is perfectly capable of supporting SCMI.

Not sure of that, may be Linux drivers can be made to support but the
firmware needs to conform the SCMI specification. And when it does, all
we need is just notion of doorbell.

> Looking forward to your "generalised doorbell".
> 

It won't be completely generic alone. The controllers need to have some
logic. It's just that they don't use any data from client, they just
signal the remote.

-- 
Regards,
Sudeep

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

* [PATCH v3 15/22] firmware: arm_scmi: abstract mailbox interface
@ 2017-10-06 13:41               ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-06 13:41 UTC (permalink / raw)
  To: linux-arm-kernel



On 06/10/17 14:34, Jassi Brar wrote:
> On Fri, Oct 6, 2017 at 6:57 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>
>>
>> On 06/10/17 12:34, Jassi Brar wrote:
>>> On Wed, Oct 4, 2017 at 5:02 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>>
>>>> Also, I have added shim only for specific controllers that need them.
>>>> E.g. ARM MHU as Jassi disagreed to add doorbell mechanism to that.
>>>> mbox_if provides default implementation that just calls direct mailbox
>>>> APIs.
>>>>
>>> Yeah you could hack away the MHU driver to make your life easy at the
>>> cost of duplicated code and extra DT bindings, but for a moment think
>>> what if your development platform wasn't MHU but, say, Rockchip
>>> mailbox controller?
>>>
>>
>> As mentioned before I understand your concern. But the point is this
>> needs to be replicated with each protocol on that controller.
>>
> Only generic protocols need to have a platform specific transport
> layer. There's no escaping that.
> 
>> So as Arnd
>> pointed out we can reduce that by generalizing common things like doorbell.
>>
> Rockchip, and most other controllers, has no "doorbell". And yet each
> is perfectly capable of supporting SCMI.

Not sure of that, may be Linux drivers can be made to support but the
firmware needs to conform the SCMI specification. And when it does, all
we need is just notion of doorbell.

> Looking forward to your "generalised doorbell".
> 

It won't be completely generic alone. The controllers need to have some
logic. It's just that they don't use any data from client, they just
signal the remote.

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-06 13:47           ` Jassi Brar
  0 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-06 13:47 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Arnd Bergmann, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin

On Fri, Oct 6, 2017 at 7:02 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
>
> On 06/10/17 12:26, Jassi Brar wrote:
>> On Wed, Oct 4, 2017 at 5:06 PM, Arnd Bergmann <arnd@arndb.de> wrote:
>>> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>>> This patch adds ARM MHU specific mailbox interface for SCMI.
>>>>
>>>> Cc: Arnd Bergmann <arnd@arndb.de>
>>>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>>>
>>> This clearly needs an explanation why we need another driver.
>>>
>> Yes the patch needs explanation which is that we need a shim layer to
>> map SCMI requests onto what the underlying controller expects. The
>> alternative was to clone the controller driver (MHU now and others
>> later when their platforms support SCMI) and pretend SCMI is the only
>> client they are ever going to serve.
>>
>
> Again that's not the point, doorbell is more common feature and that can
> be supported. As SCMI expects doorbell feature in the specification, it
> just need to support that class of controllers.
>
NO.  All SCMI expects is SHMEM and a signal reaching the other end.
The signal mechanism need not necessarily be "doorbell".

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

* Re: [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-06 13:47           ` Jassi Brar
  0 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-06 13:47 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Arnd Bergmann, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin

On Fri, Oct 6, 2017 at 7:02 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
>
>
> On 06/10/17 12:26, Jassi Brar wrote:
>> On Wed, Oct 4, 2017 at 5:06 PM, Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org> wrote:
>>> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
>>>> This patch adds ARM MHU specific mailbox interface for SCMI.
>>>>
>>>> Cc: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
>>>> Signed-off-by: Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org>
>>>
>>> This clearly needs an explanation why we need another driver.
>>>
>> Yes the patch needs explanation which is that we need a shim layer to
>> map SCMI requests onto what the underlying controller expects. The
>> alternative was to clone the controller driver (MHU now and others
>> later when their platforms support SCMI) and pretend SCMI is the only
>> client they are ever going to serve.
>>
>
> Again that's not the point, doorbell is more common feature and that can
> be supported. As SCMI expects doorbell feature in the specification, it
> just need to support that class of controllers.
>
NO.  All SCMI expects is SHMEM and a signal reaching the other end.
The signal mechanism need not necessarily be "doorbell".
--
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] 208+ messages in thread

* [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-06 13:47           ` Jassi Brar
  0 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-06 13:47 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 6, 2017 at 7:02 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
>
> On 06/10/17 12:26, Jassi Brar wrote:
>> On Wed, Oct 4, 2017 at 5:06 PM, Arnd Bergmann <arnd@arndb.de> wrote:
>>> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>>> This patch adds ARM MHU specific mailbox interface for SCMI.
>>>>
>>>> Cc: Arnd Bergmann <arnd@arndb.de>
>>>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>>>
>>> This clearly needs an explanation why we need another driver.
>>>
>> Yes the patch needs explanation which is that we need a shim layer to
>> map SCMI requests onto what the underlying controller expects. The
>> alternative was to clone the controller driver (MHU now and others
>> later when their platforms support SCMI) and pretend SCMI is the only
>> client they are ever going to serve.
>>
>
> Again that's not the point, doorbell is more common feature and that can
> be supported. As SCMI expects doorbell feature in the specification, it
> just need to support that class of controllers.
>
NO.  All SCMI expects is SHMEM and a signal reaching the other end.
The signal mechanism need not necessarily be "doorbell".

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

* Re: [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-06 13:51             ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-06 13:51 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Sudeep Holla, Arnd Bergmann, ALKML, LKML, DTML, Roy Franz,
	Harb Abdulhamid, Nishanth Menon, Loc Ho, Alexey Klimov,
	Ryan Harkin



On 06/10/17 14:47, Jassi Brar wrote:
> On Fri, Oct 6, 2017 at 7:02 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>
>>
>> On 06/10/17 12:26, Jassi Brar wrote:
>>> On Wed, Oct 4, 2017 at 5:06 PM, Arnd Bergmann <arnd@arndb.de> wrote:
>>>> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>>>> This patch adds ARM MHU specific mailbox interface for SCMI.
>>>>>
>>>>> Cc: Arnd Bergmann <arnd@arndb.de>
>>>>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>>>>
>>>> This clearly needs an explanation why we need another driver.
>>>>
>>> Yes the patch needs explanation which is that we need a shim layer to
>>> map SCMI requests onto what the underlying controller expects. The
>>> alternative was to clone the controller driver (MHU now and others
>>> later when their platforms support SCMI) and pretend SCMI is the only
>>> client they are ever going to serve.
>>>
>>
>> Again that's not the point, doorbell is more common feature and that can
>> be supported. As SCMI expects doorbell feature in the specification, it
>> just need to support that class of controllers.
>>
> NO.  All SCMI expects is SHMEM and a signal reaching the other end.
> The signal mechanism need not necessarily be "doorbell".
> 

Agreed, but creating an abstraction ro do something as generic as
doorbell and writing shim layer for each controller to use SCMI also
sounds bad.

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-06 13:51             ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-06 13:51 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Sudeep Holla, Arnd Bergmann, ALKML, LKML, DTML, Roy Franz,
	Harb Abdulhamid, Nishanth Menon, Loc Ho, Alexey Klimov,
	Ryan Harkin



On 06/10/17 14:47, Jassi Brar wrote:
> On Fri, Oct 6, 2017 at 7:02 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
>>
>>
>> On 06/10/17 12:26, Jassi Brar wrote:
>>> On Wed, Oct 4, 2017 at 5:06 PM, Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org> wrote:
>>>> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
>>>>> This patch adds ARM MHU specific mailbox interface for SCMI.
>>>>>
>>>>> Cc: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
>>>>> Signed-off-by: Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org>
>>>>
>>>> This clearly needs an explanation why we need another driver.
>>>>
>>> Yes the patch needs explanation which is that we need a shim layer to
>>> map SCMI requests onto what the underlying controller expects. The
>>> alternative was to clone the controller driver (MHU now and others
>>> later when their platforms support SCMI) and pretend SCMI is the only
>>> client they are ever going to serve.
>>>
>>
>> Again that's not the point, doorbell is more common feature and that can
>> be supported. As SCMI expects doorbell feature in the specification, it
>> just need to support that class of controllers.
>>
> NO.  All SCMI expects is SHMEM and a signal reaching the other end.
> The signal mechanism need not necessarily be "doorbell".
> 

Agreed, but creating an abstraction ro do something as generic as
doorbell and writing shim layer for each controller to use SCMI also
sounds bad.

-- 
Regards,
Sudeep
--
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] 208+ messages in thread

* [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-06 13:51             ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-06 13:51 UTC (permalink / raw)
  To: linux-arm-kernel



On 06/10/17 14:47, Jassi Brar wrote:
> On Fri, Oct 6, 2017 at 7:02 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>
>>
>> On 06/10/17 12:26, Jassi Brar wrote:
>>> On Wed, Oct 4, 2017 at 5:06 PM, Arnd Bergmann <arnd@arndb.de> wrote:
>>>> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>>>> This patch adds ARM MHU specific mailbox interface for SCMI.
>>>>>
>>>>> Cc: Arnd Bergmann <arnd@arndb.de>
>>>>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>>>>
>>>> This clearly needs an explanation why we need another driver.
>>>>
>>> Yes the patch needs explanation which is that we need a shim layer to
>>> map SCMI requests onto what the underlying controller expects. The
>>> alternative was to clone the controller driver (MHU now and others
>>> later when their platforms support SCMI) and pretend SCMI is the only
>>> client they are ever going to serve.
>>>
>>
>> Again that's not the point, doorbell is more common feature and that can
>> be supported. As SCMI expects doorbell feature in the specification, it
>> just need to support that class of controllers.
>>
> NO.  All SCMI expects is SHMEM and a signal reaching the other end.
> The signal mechanism need not necessarily be "doorbell".
> 

Agreed, but creating an abstraction ro do something as generic as
doorbell and writing shim layer for each controller to use SCMI also
sounds bad.

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
  2017-10-06 11:01       ` Jassi Brar
@ 2017-10-06 15:54         ` Rob Herring
  -1 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2017-10-06 15:54 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Arnd Bergmann, Loc Ho, Alexey Klimov,
	Ryan Harkin, Mark Rutland

On Fri, Oct 6, 2017 at 6:01 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
> On Fri, Oct 6, 2017 at 4:50 AM, Rob Herring <robh@kernel.org> wrote:
>> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
>>> This patch adds ARM MHU specific mailbox client bindings to support
>>> SCMI. Since SCMI specification just requires doorbell mechanism from
>>> mailbox controllers, we add mailbox data to specify the doorbell bit(s).
>>>
>>> Cc: Rob Herring <robh+dt@kernel.org>
>>> Cc: Mark Rutland <mark.rutland@arm.com>
>>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>>> ---
>>>  .../devicetree/bindings/arm/arm,mhu-scmi.txt          | 19 +++++++++++++++++++
>>>  1 file changed, 19 insertions(+)
>>>  create mode 100644 Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
>>>
>>> diff --git a/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
>>> new file mode 100644
>>> index 000000000000..8c106f1cdeb8
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
>>> @@ -0,0 +1,19 @@
>>> +ARM MHU mailbox client bindings for SCMI Message Protocol
>>> +----------------------------------------------------------
>>> +
>>> +This binding is intended to define the ARM MHU specific extensions to
>>> +the generic SCMI bindings[2].
>>> +
>>> +Required properties:
>>> +
>>> +The scmi node with the following properties shall be under the /firmware/ node.
>>> +
>>> +- compatible : shall be "arm,scmi" and "arm,mhu-scmi"
>>
>> Most specific first.
>>
>>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>>> +           data as expected by the mailbox controller
>>
>> Shouldn't that be cells as part of mboxes property?
>>
> A MHU client can send any number of commands (such u32 values) over a channel.
> This client (SCMI) sends just one command over a channel, but other
> clients may/do send two or more.

Okay, then I guess I don't understand why this is in DT.

Rob

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

* [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
@ 2017-10-06 15:54         ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2017-10-06 15:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 6, 2017 at 6:01 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
> On Fri, Oct 6, 2017 at 4:50 AM, Rob Herring <robh@kernel.org> wrote:
>> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
>>> This patch adds ARM MHU specific mailbox client bindings to support
>>> SCMI. Since SCMI specification just requires doorbell mechanism from
>>> mailbox controllers, we add mailbox data to specify the doorbell bit(s).
>>>
>>> Cc: Rob Herring <robh+dt@kernel.org>
>>> Cc: Mark Rutland <mark.rutland@arm.com>
>>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>>> ---
>>>  .../devicetree/bindings/arm/arm,mhu-scmi.txt          | 19 +++++++++++++++++++
>>>  1 file changed, 19 insertions(+)
>>>  create mode 100644 Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
>>>
>>> diff --git a/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
>>> new file mode 100644
>>> index 000000000000..8c106f1cdeb8
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/arm/arm,mhu-scmi.txt
>>> @@ -0,0 +1,19 @@
>>> +ARM MHU mailbox client bindings for SCMI Message Protocol
>>> +----------------------------------------------------------
>>> +
>>> +This binding is intended to define the ARM MHU specific extensions to
>>> +the generic SCMI bindings[2].
>>> +
>>> +Required properties:
>>> +
>>> +The scmi node with the following properties shall be under the /firmware/ node.
>>> +
>>> +- compatible : shall be "arm,scmi" and "arm,mhu-scmi"
>>
>> Most specific first.
>>
>>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>>> +           data as expected by the mailbox controller
>>
>> Shouldn't that be cells as part of mboxes property?
>>
> A MHU client can send any number of commands (such u32 values) over a channel.
> This client (SCMI) sends just one command over a channel, but other
> clients may/do send two or more.

Okay, then I guess I don't understand why this is in DT.

Rob

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

* Re: [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
  2017-10-06 15:54         ` Rob Herring
@ 2017-10-07  2:26           ` Jassi Brar
  -1 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-07  2:26 UTC (permalink / raw)
  To: Rob Herring
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Arnd Bergmann, Loc Ho, Alexey Klimov,
	Ryan Harkin, Mark Rutland

On Fri, Oct 6, 2017 at 9:24 PM, Rob Herring <robh@kernel.org> wrote:
> On Fri, Oct 6, 2017 at 6:01 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>> On Fri, Oct 6, 2017 at 4:50 AM, Rob Herring <robh@kernel.org> wrote:
>>> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:

>>>
>>>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>>>> +           data as expected by the mailbox controller
>>>
>>> Shouldn't that be cells as part of mboxes property?
>>>
>> A MHU client can send any number of commands (such u32 values) over a channel.
>> This client (SCMI) sends just one command over a channel, but other
>> clients may/do send two or more.
>
> Okay, then I guess I don't understand why this is in DT.
>
Yeah the client has to provide code (u32 value) for the commands it
sends, and that value is going to be platform specific. For example,
on Juno the ITS_AN_SCMI_COMMAND may be defined as BIT(7) while on my
platform it may be 0x4567

For MHU based platforms, it becomes easy if the u32 is passed from DT.
And that should be ok since that is like a h/w parameter - a value
chosen/expected by the remote firmware.

thnx

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

* [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
@ 2017-10-07  2:26           ` Jassi Brar
  0 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-07  2:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 6, 2017 at 9:24 PM, Rob Herring <robh@kernel.org> wrote:
> On Fri, Oct 6, 2017 at 6:01 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>> On Fri, Oct 6, 2017 at 4:50 AM, Rob Herring <robh@kernel.org> wrote:
>>> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:

>>>
>>>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>>>> +           data as expected by the mailbox controller
>>>
>>> Shouldn't that be cells as part of mboxes property?
>>>
>> A MHU client can send any number of commands (such u32 values) over a channel.
>> This client (SCMI) sends just one command over a channel, but other
>> clients may/do send two or more.
>
> Okay, then I guess I don't understand why this is in DT.
>
Yeah the client has to provide code (u32 value) for the commands it
sends, and that value is going to be platform specific. For example,
on Juno the ITS_AN_SCMI_COMMAND may be defined as BIT(7) while on my
platform it may be 0x4567

For MHU based platforms, it becomes easy if the u32 is passed from DT.
And that should be ok since that is like a h/w parameter - a value
chosen/expected by the remote firmware.

thnx

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

* Re: [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
  2017-10-07  2:26           ` Jassi Brar
@ 2017-10-09 13:52             ` Rob Herring
  -1 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2017-10-09 13:52 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Arnd Bergmann, Loc Ho, Alexey Klimov,
	Ryan Harkin, Mark Rutland

On Fri, Oct 6, 2017 at 9:26 PM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
> On Fri, Oct 6, 2017 at 9:24 PM, Rob Herring <robh@kernel.org> wrote:
>> On Fri, Oct 6, 2017 at 6:01 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>>> On Fri, Oct 6, 2017 at 4:50 AM, Rob Herring <robh@kernel.org> wrote:
>>>> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
>
>>>>
>>>>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>>>>> +           data as expected by the mailbox controller
>>>>
>>>> Shouldn't that be cells as part of mboxes property?
>>>>
>>> A MHU client can send any number of commands (such u32 values) over a channel.
>>> This client (SCMI) sends just one command over a channel, but other
>>> clients may/do send two or more.

The above definition doesn't support 2 or more as it is 1-1 with channels.

>> Okay, then I guess I don't understand why this is in DT.
>>
> Yeah the client has to provide code (u32 value) for the commands it
> sends, and that value is going to be platform specific. For example,
> on Juno the ITS_AN_SCMI_COMMAND may be defined as BIT(7) while on my
> platform it may be 0x4567
>
> For MHU based platforms, it becomes easy if the u32 is passed from DT.
> And that should be ok since that is like a h/w parameter - a value
> chosen/expected by the remote firmware.

Could it ever be more than 1 cell?

I guess being in DT is fine, but I'm still not sure about the naming.
The current name suggests it is part of the mbox binding. Do we want
that or should it be SCMI specific? Then "data" is vague. Perhaps
"scmi-commands"?

Rob

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

* [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
@ 2017-10-09 13:52             ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2017-10-09 13:52 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 6, 2017 at 9:26 PM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
> On Fri, Oct 6, 2017 at 9:24 PM, Rob Herring <robh@kernel.org> wrote:
>> On Fri, Oct 6, 2017 at 6:01 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>>> On Fri, Oct 6, 2017 at 4:50 AM, Rob Herring <robh@kernel.org> wrote:
>>>> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
>
>>>>
>>>>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>>>>> +           data as expected by the mailbox controller
>>>>
>>>> Shouldn't that be cells as part of mboxes property?
>>>>
>>> A MHU client can send any number of commands (such u32 values) over a channel.
>>> This client (SCMI) sends just one command over a channel, but other
>>> clients may/do send two or more.

The above definition doesn't support 2 or more as it is 1-1 with channels.

>> Okay, then I guess I don't understand why this is in DT.
>>
> Yeah the client has to provide code (u32 value) for the commands it
> sends, and that value is going to be platform specific. For example,
> on Juno the ITS_AN_SCMI_COMMAND may be defined as BIT(7) while on my
> platform it may be 0x4567
>
> For MHU based platforms, it becomes easy if the u32 is passed from DT.
> And that should be ok since that is like a h/w parameter - a value
> chosen/expected by the remote firmware.

Could it ever be more than 1 cell?

I guess being in DT is fine, but I'm still not sure about the naming.
The current name suggests it is part of the mbox binding. Do we want
that or should it be SCMI specific? Then "data" is vague. Perhaps
"scmi-commands"?

Rob

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

* Re: [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
@ 2017-10-09 14:37               ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-09 14:37 UTC (permalink / raw)
  To: Rob Herring, Jassi Brar
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Arnd Bergmann, Loc Ho, Alexey Klimov,
	Ryan Harkin, Mark Rutland



On 09/10/17 14:52, Rob Herring wrote:
> On Fri, Oct 6, 2017 at 9:26 PM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>> On Fri, Oct 6, 2017 at 9:24 PM, Rob Herring <robh@kernel.org> wrote:
>>> On Fri, Oct 6, 2017 at 6:01 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>>>> On Fri, Oct 6, 2017 at 4:50 AM, Rob Herring <robh@kernel.org> wrote:
>>>>> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
>>
>>>>>
>>>>>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>>>>>> +           data as expected by the mailbox controller
>>>>>
>>>>> Shouldn't that be cells as part of mboxes property?
>>>>>
>>>> A MHU client can send any number of commands (such u32 values) over a channel.
>>>> This client (SCMI) sends just one command over a channel, but other
>>>> clients may/do send two or more.
> 
> The above definition doesn't support 2 or more as it is 1-1 with channels.
> 

In case of MHU, we just need one u32 per channel in SCMI context.

>>> Okay, then I guess I don't understand why this is in DT.
>>>
>> Yeah the client has to provide code (u32 value) for the commands it
>> sends, and that value is going to be platform specific. For example,
>> on Juno the ITS_AN_SCMI_COMMAND may be defined as BIT(7) while on my
>> platform it may be 0x4567
>>
>> For MHU based platforms, it becomes easy if the u32 is passed from DT.
>> And that should be ok since that is like a h/w parameter - a value
>> chosen/expected by the remote firmware.
> 
> Could it ever be more than 1 cell?
> 

No, as mentioned above.

> I guess being in DT is fine, but I'm still not sure about the naming.
> The current name suggests it is part of the mbox binding. Do we want
> that or should it be SCMI specific? Then "data" is vague. Perhaps
> "scmi-commands"?
> 

How about "scmi-mhu-commands" ? As scmi-commands sounds too generic
and part of SCMI specification. But they are rather MHU specific to
make use of each 32 bit in physical channel for a virtual channel.
IOW, it's just different way of representing the doorbell bits I
proposed previously as a 32-bit command expected by the driver.

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
@ 2017-10-09 14:37               ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-09 14:37 UTC (permalink / raw)
  To: Rob Herring, Jassi Brar
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Arnd Bergmann, Loc Ho, Alexey Klimov,
	Ryan Harkin, Mark Rutland



On 09/10/17 14:52, Rob Herring wrote:
> On Fri, Oct 6, 2017 at 9:26 PM, Jassi Brar <jassisinghbrar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> On Fri, Oct 6, 2017 at 9:24 PM, Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
>>> On Fri, Oct 6, 2017 at 6:01 AM, Jassi Brar <jassisinghbrar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>>>> On Fri, Oct 6, 2017 at 4:50 AM, Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
>>>>> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
>>
>>>>>
>>>>>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>>>>>> +           data as expected by the mailbox controller
>>>>>
>>>>> Shouldn't that be cells as part of mboxes property?
>>>>>
>>>> A MHU client can send any number of commands (such u32 values) over a channel.
>>>> This client (SCMI) sends just one command over a channel, but other
>>>> clients may/do send two or more.
> 
> The above definition doesn't support 2 or more as it is 1-1 with channels.
> 

In case of MHU, we just need one u32 per channel in SCMI context.

>>> Okay, then I guess I don't understand why this is in DT.
>>>
>> Yeah the client has to provide code (u32 value) for the commands it
>> sends, and that value is going to be platform specific. For example,
>> on Juno the ITS_AN_SCMI_COMMAND may be defined as BIT(7) while on my
>> platform it may be 0x4567
>>
>> For MHU based platforms, it becomes easy if the u32 is passed from DT.
>> And that should be ok since that is like a h/w parameter - a value
>> chosen/expected by the remote firmware.
> 
> Could it ever be more than 1 cell?
> 

No, as mentioned above.

> I guess being in DT is fine, but I'm still not sure about the naming.
> The current name suggests it is part of the mbox binding. Do we want
> that or should it be SCMI specific? Then "data" is vague. Perhaps
> "scmi-commands"?
> 

How about "scmi-mhu-commands" ? As scmi-commands sounds too generic
and part of SCMI specification. But they are rather MHU specific to
make use of each 32 bit in physical channel for a virtual channel.
IOW, it's just different way of representing the doorbell bits I
proposed previously as a 32-bit command expected by the driver.

-- 
Regards,
Sudeep
--
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] 208+ messages in thread

* [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
@ 2017-10-09 14:37               ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-09 14:37 UTC (permalink / raw)
  To: linux-arm-kernel



On 09/10/17 14:52, Rob Herring wrote:
> On Fri, Oct 6, 2017 at 9:26 PM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>> On Fri, Oct 6, 2017 at 9:24 PM, Rob Herring <robh@kernel.org> wrote:
>>> On Fri, Oct 6, 2017 at 6:01 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>>>> On Fri, Oct 6, 2017 at 4:50 AM, Rob Herring <robh@kernel.org> wrote:
>>>>> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
>>
>>>>>
>>>>>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>>>>>> +           data as expected by the mailbox controller
>>>>>
>>>>> Shouldn't that be cells as part of mboxes property?
>>>>>
>>>> A MHU client can send any number of commands (such u32 values) over a channel.
>>>> This client (SCMI) sends just one command over a channel, but other
>>>> clients may/do send two or more.
> 
> The above definition doesn't support 2 or more as it is 1-1 with channels.
> 

In case of MHU, we just need one u32 per channel in SCMI context.

>>> Okay, then I guess I don't understand why this is in DT.
>>>
>> Yeah the client has to provide code (u32 value) for the commands it
>> sends, and that value is going to be platform specific. For example,
>> on Juno the ITS_AN_SCMI_COMMAND may be defined as BIT(7) while on my
>> platform it may be 0x4567
>>
>> For MHU based platforms, it becomes easy if the u32 is passed from DT.
>> And that should be ok since that is like a h/w parameter - a value
>> chosen/expected by the remote firmware.
> 
> Could it ever be more than 1 cell?
> 

No, as mentioned above.

> I guess being in DT is fine, but I'm still not sure about the naming.
> The current name suggests it is part of the mbox binding. Do we want
> that or should it be SCMI specific? Then "data" is vague. Perhaps
> "scmi-commands"?
> 

How about "scmi-mhu-commands" ? As scmi-commands sounds too generic
and part of SCMI specification. But they are rather MHU specific to
make use of each 32 bit in physical channel for a virtual channel.
IOW, it's just different way of representing the doorbell bits I
proposed previously as a 32-bit command expected by the driver.

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
@ 2017-10-09 14:46               ` Jassi Brar
  0 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-09 14:46 UTC (permalink / raw)
  To: Rob Herring
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Arnd Bergmann, Loc Ho, Alexey Klimov,
	Ryan Harkin, Mark Rutland

On Mon, Oct 9, 2017 at 7:22 PM, Rob Herring <robh@kernel.org> wrote:
> On Fri, Oct 6, 2017 at 9:26 PM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>> On Fri, Oct 6, 2017 at 9:24 PM, Rob Herring <robh@kernel.org> wrote:
>>> On Fri, Oct 6, 2017 at 6:01 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>>>> On Fri, Oct 6, 2017 at 4:50 AM, Rob Herring <robh@kernel.org> wrote:
>>>>> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
>>
>>>>>
>>>>>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>>>>>> +           data as expected by the mailbox controller
>>>>>
>>>>> Shouldn't that be cells as part of mboxes property?
>>>>>
>>>> A MHU client can send any number of commands (such u32 values) over a channel.
>>>> This client (SCMI) sends just one command over a channel, but other
>>>> clients may/do send two or more.
>
> The above definition doesn't support 2 or more as it is 1-1 with channels.
>
I thought you suggested to make controller driver accept the command
as another cell in client's mboxes property.
Which we can't do.

>>> Okay, then I guess I don't understand why this is in DT.
>>>
>> Yeah the client has to provide code (u32 value) for the commands it
>> sends, and that value is going to be platform specific. For example,
>> on Juno the ITS_AN_SCMI_COMMAND may be defined as BIT(7) while on my
>> platform it may be 0x4567
>>
>> For MHU based platforms, it becomes easy if the u32 is passed from DT.
>> And that should be ok since that is like a h/w parameter - a value
>> chosen/expected by the remote firmware.
>
> Could it ever be more than 1 cell?
>
SCMI sends sub-commands via SHMEM, so it is always going to be 1cell for _scmi_.
However many firmwares are unlikely to use just one command over a
channel - say, the protocol is trivial or the linux and remote have no
SHMEM.

> I guess being in DT is fine, but I'm still not sure about the naming.
> The current name suggests it is part of the mbox binding. Do we want
> that or should it be SCMI specific? Then "data" is vague. Perhaps
> "scmi-commands"?
>
Sure. I have no problem with whatever we wanna call it.

thnx

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

* Re: [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
@ 2017-10-09 14:46               ` Jassi Brar
  0 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-09 14:46 UTC (permalink / raw)
  To: Rob Herring
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Arnd Bergmann, Loc Ho, Alexey Klimov,
	Ryan Harkin, Mark Rutland

On Mon, Oct 9, 2017 at 7:22 PM, Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
> On Fri, Oct 6, 2017 at 9:26 PM, Jassi Brar <jassisinghbrar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> On Fri, Oct 6, 2017 at 9:24 PM, Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
>>> On Fri, Oct 6, 2017 at 6:01 AM, Jassi Brar <jassisinghbrar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>>>> On Fri, Oct 6, 2017 at 4:50 AM, Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
>>>>> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
>>
>>>>>
>>>>>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>>>>>> +           data as expected by the mailbox controller
>>>>>
>>>>> Shouldn't that be cells as part of mboxes property?
>>>>>
>>>> A MHU client can send any number of commands (such u32 values) over a channel.
>>>> This client (SCMI) sends just one command over a channel, but other
>>>> clients may/do send two or more.
>
> The above definition doesn't support 2 or more as it is 1-1 with channels.
>
I thought you suggested to make controller driver accept the command
as another cell in client's mboxes property.
Which we can't do.

>>> Okay, then I guess I don't understand why this is in DT.
>>>
>> Yeah the client has to provide code (u32 value) for the commands it
>> sends, and that value is going to be platform specific. For example,
>> on Juno the ITS_AN_SCMI_COMMAND may be defined as BIT(7) while on my
>> platform it may be 0x4567
>>
>> For MHU based platforms, it becomes easy if the u32 is passed from DT.
>> And that should be ok since that is like a h/w parameter - a value
>> chosen/expected by the remote firmware.
>
> Could it ever be more than 1 cell?
>
SCMI sends sub-commands via SHMEM, so it is always going to be 1cell for _scmi_.
However many firmwares are unlikely to use just one command over a
channel - say, the protocol is trivial or the linux and remote have no
SHMEM.

> I guess being in DT is fine, but I'm still not sure about the naming.
> The current name suggests it is part of the mbox binding. Do we want
> that or should it be SCMI specific? Then "data" is vague. Perhaps
> "scmi-commands"?
>
Sure. I have no problem with whatever we wanna call it.

thnx
--
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] 208+ messages in thread

* [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
@ 2017-10-09 14:46               ` Jassi Brar
  0 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-09 14:46 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Oct 9, 2017 at 7:22 PM, Rob Herring <robh@kernel.org> wrote:
> On Fri, Oct 6, 2017 at 9:26 PM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>> On Fri, Oct 6, 2017 at 9:24 PM, Rob Herring <robh@kernel.org> wrote:
>>> On Fri, Oct 6, 2017 at 6:01 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>>>> On Fri, Oct 6, 2017 at 4:50 AM, Rob Herring <robh@kernel.org> wrote:
>>>>> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
>>
>>>>>
>>>>>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>>>>>> +           data as expected by the mailbox controller
>>>>>
>>>>> Shouldn't that be cells as part of mboxes property?
>>>>>
>>>> A MHU client can send any number of commands (such u32 values) over a channel.
>>>> This client (SCMI) sends just one command over a channel, but other
>>>> clients may/do send two or more.
>
> The above definition doesn't support 2 or more as it is 1-1 with channels.
>
I thought you suggested to make controller driver accept the command
as another cell in client's mboxes property.
Which we can't do.

>>> Okay, then I guess I don't understand why this is in DT.
>>>
>> Yeah the client has to provide code (u32 value) for the commands it
>> sends, and that value is going to be platform specific. For example,
>> on Juno the ITS_AN_SCMI_COMMAND may be defined as BIT(7) while on my
>> platform it may be 0x4567
>>
>> For MHU based platforms, it becomes easy if the u32 is passed from DT.
>> And that should be ok since that is like a h/w parameter - a value
>> chosen/expected by the remote firmware.
>
> Could it ever be more than 1 cell?
>
SCMI sends sub-commands via SHMEM, so it is always going to be 1cell for _scmi_.
However many firmwares are unlikely to use just one command over a
channel - say, the protocol is trivial or the linux and remote have no
SHMEM.

> I guess being in DT is fine, but I'm still not sure about the naming.
> The current name suggests it is part of the mbox binding. Do we want
> that or should it be SCMI specific? Then "data" is vague. Perhaps
> "scmi-commands"?
>
Sure. I have no problem with whatever we wanna call it.

thnx

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

* Re: [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
@ 2017-10-09 22:57                 ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2017-10-09 22:57 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Arnd Bergmann, Loc Ho, Alexey Klimov,
	Ryan Harkin, Mark Rutland

On Mon, Oct 9, 2017 at 9:46 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
> On Mon, Oct 9, 2017 at 7:22 PM, Rob Herring <robh@kernel.org> wrote:
>> On Fri, Oct 6, 2017 at 9:26 PM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>>> On Fri, Oct 6, 2017 at 9:24 PM, Rob Herring <robh@kernel.org> wrote:
>>>> On Fri, Oct 6, 2017 at 6:01 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>>>>> On Fri, Oct 6, 2017 at 4:50 AM, Rob Herring <robh@kernel.org> wrote:
>>>>>> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
>>>
>>>>>>
>>>>>>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>>>>>>> +           data as expected by the mailbox controller
>>>>>>
>>>>>> Shouldn't that be cells as part of mboxes property?
>>>>>>
>>>>> A MHU client can send any number of commands (such u32 values) over a channel.
>>>>> This client (SCMI) sends just one command over a channel, but other
>>>>> clients may/do send two or more.
>>
>> The above definition doesn't support 2 or more as it is 1-1 with channels.
>>
> I thought you suggested to make controller driver accept the command
> as another cell in client's mboxes property.
> Which we can't do.

Yes, agreed. But I'm wondering since a client may need more than one,
how would that be expressed?

>>>> Okay, then I guess I don't understand why this is in DT.
>>>>
>>> Yeah the client has to provide code (u32 value) for the commands it
>>> sends, and that value is going to be platform specific. For example,
>>> on Juno the ITS_AN_SCMI_COMMAND may be defined as BIT(7) while on my
>>> platform it may be 0x4567
>>>
>>> For MHU based platforms, it becomes easy if the u32 is passed from DT.
>>> And that should be ok since that is like a h/w parameter - a value
>>> chosen/expected by the remote firmware.
>>
>> Could it ever be more than 1 cell?
>>
> SCMI sends sub-commands via SHMEM, so it is always going to be 1cell for _scmi_.
> However many firmwares are unlikely to use just one command over a
> channel - say, the protocol is trivial or the linux and remote have no
> SHMEM.

I'd hope the normal case is not enumerating commands and sub-commands
in DT and this is special case of a "generic" protocol with platform
specific aspects. It could be solved with a specific compatible for
each platform/implementation. We'll probably regret not doing that,
but I'm going to pretend that this time SoC vendors won't mess it up.

>> I guess being in DT is fine, but I'm still not sure about the naming.
>> The current name suggests it is part of the mbox binding. Do we want
>> that or should it be SCMI specific? Then "data" is vague. Perhaps
>> "scmi-commands"?
>>
> Sure. I have no problem with whatever we wanna call it.

Okay. That should have an "arm" prefix too BTW.

Rob

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

* Re: [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
@ 2017-10-09 22:57                 ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2017-10-09 22:57 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Arnd Bergmann, Loc Ho, Alexey Klimov,
	Ryan Harkin, Mark Rutland

On Mon, Oct 9, 2017 at 9:46 AM, Jassi Brar <jassisinghbrar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> On Mon, Oct 9, 2017 at 7:22 PM, Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
>> On Fri, Oct 6, 2017 at 9:26 PM, Jassi Brar <jassisinghbrar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>>> On Fri, Oct 6, 2017 at 9:24 PM, Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
>>>> On Fri, Oct 6, 2017 at 6:01 AM, Jassi Brar <jassisinghbrar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>>>>> On Fri, Oct 6, 2017 at 4:50 AM, Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
>>>>>> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
>>>
>>>>>>
>>>>>>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>>>>>>> +           data as expected by the mailbox controller
>>>>>>
>>>>>> Shouldn't that be cells as part of mboxes property?
>>>>>>
>>>>> A MHU client can send any number of commands (such u32 values) over a channel.
>>>>> This client (SCMI) sends just one command over a channel, but other
>>>>> clients may/do send two or more.
>>
>> The above definition doesn't support 2 or more as it is 1-1 with channels.
>>
> I thought you suggested to make controller driver accept the command
> as another cell in client's mboxes property.
> Which we can't do.

Yes, agreed. But I'm wondering since a client may need more than one,
how would that be expressed?

>>>> Okay, then I guess I don't understand why this is in DT.
>>>>
>>> Yeah the client has to provide code (u32 value) for the commands it
>>> sends, and that value is going to be platform specific. For example,
>>> on Juno the ITS_AN_SCMI_COMMAND may be defined as BIT(7) while on my
>>> platform it may be 0x4567
>>>
>>> For MHU based platforms, it becomes easy if the u32 is passed from DT.
>>> And that should be ok since that is like a h/w parameter - a value
>>> chosen/expected by the remote firmware.
>>
>> Could it ever be more than 1 cell?
>>
> SCMI sends sub-commands via SHMEM, so it is always going to be 1cell for _scmi_.
> However many firmwares are unlikely to use just one command over a
> channel - say, the protocol is trivial or the linux and remote have no
> SHMEM.

I'd hope the normal case is not enumerating commands and sub-commands
in DT and this is special case of a "generic" protocol with platform
specific aspects. It could be solved with a specific compatible for
each platform/implementation. We'll probably regret not doing that,
but I'm going to pretend that this time SoC vendors won't mess it up.

>> I guess being in DT is fine, but I'm still not sure about the naming.
>> The current name suggests it is part of the mbox binding. Do we want
>> that or should it be SCMI specific? Then "data" is vague. Perhaps
>> "scmi-commands"?
>>
> Sure. I have no problem with whatever we wanna call it.

Okay. That should have an "arm" prefix too BTW.

Rob
--
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] 208+ messages in thread

* [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
@ 2017-10-09 22:57                 ` Rob Herring
  0 siblings, 0 replies; 208+ messages in thread
From: Rob Herring @ 2017-10-09 22:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Oct 9, 2017 at 9:46 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
> On Mon, Oct 9, 2017 at 7:22 PM, Rob Herring <robh@kernel.org> wrote:
>> On Fri, Oct 6, 2017 at 9:26 PM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>>> On Fri, Oct 6, 2017 at 9:24 PM, Rob Herring <robh@kernel.org> wrote:
>>>> On Fri, Oct 6, 2017 at 6:01 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>>>>> On Fri, Oct 6, 2017 at 4:50 AM, Rob Herring <robh@kernel.org> wrote:
>>>>>> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
>>>
>>>>>>
>>>>>>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>>>>>>> +           data as expected by the mailbox controller
>>>>>>
>>>>>> Shouldn't that be cells as part of mboxes property?
>>>>>>
>>>>> A MHU client can send any number of commands (such u32 values) over a channel.
>>>>> This client (SCMI) sends just one command over a channel, but other
>>>>> clients may/do send two or more.
>>
>> The above definition doesn't support 2 or more as it is 1-1 with channels.
>>
> I thought you suggested to make controller driver accept the command
> as another cell in client's mboxes property.
> Which we can't do.

Yes, agreed. But I'm wondering since a client may need more than one,
how would that be expressed?

>>>> Okay, then I guess I don't understand why this is in DT.
>>>>
>>> Yeah the client has to provide code (u32 value) for the commands it
>>> sends, and that value is going to be platform specific. For example,
>>> on Juno the ITS_AN_SCMI_COMMAND may be defined as BIT(7) while on my
>>> platform it may be 0x4567
>>>
>>> For MHU based platforms, it becomes easy if the u32 is passed from DT.
>>> And that should be ok since that is like a h/w parameter - a value
>>> chosen/expected by the remote firmware.
>>
>> Could it ever be more than 1 cell?
>>
> SCMI sends sub-commands via SHMEM, so it is always going to be 1cell for _scmi_.
> However many firmwares are unlikely to use just one command over a
> channel - say, the protocol is trivial or the linux and remote have no
> SHMEM.

I'd hope the normal case is not enumerating commands and sub-commands
in DT and this is special case of a "generic" protocol with platform
specific aspects. It could be solved with a specific compatible for
each platform/implementation. We'll probably regret not doing that,
but I'm going to pretend that this time SoC vendors won't mess it up.

>> I guess being in DT is fine, but I'm still not sure about the naming.
>> The current name suggests it is part of the mbox binding. Do we want
>> that or should it be SCMI specific? Then "data" is vague. Perhaps
>> "scmi-commands"?
>>
> Sure. I have no problem with whatever we wanna call it.

Okay. That should have an "arm" prefix too BTW.

Rob

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

* Re: [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
  2017-10-09 22:57                 ` Rob Herring
@ 2017-10-10  1:52                   ` Jassi Brar
  -1 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-10  1:52 UTC (permalink / raw)
  To: Rob Herring
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Arnd Bergmann, Loc Ho, Alexey Klimov,
	Ryan Harkin, Mark Rutland

On Tue, Oct 10, 2017 at 4:27 AM, Rob Herring <robh@kernel.org> wrote:
> On Mon, Oct 9, 2017 at 9:46 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>> On Mon, Oct 9, 2017 at 7:22 PM, Rob Herring <robh@kernel.org> wrote:
>>> On Fri, Oct 6, 2017 at 9:26 PM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>>>> On Fri, Oct 6, 2017 at 9:24 PM, Rob Herring <robh@kernel.org> wrote:
>>>>> On Fri, Oct 6, 2017 at 6:01 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>>>>>> On Fri, Oct 6, 2017 at 4:50 AM, Rob Herring <robh@kernel.org> wrote:
>>>>>>> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
>>>>
>>>>>>>
>>>>>>>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>>>>>>>> +           data as expected by the mailbox controller
>>>>>>>
>>>>>>> Shouldn't that be cells as part of mboxes property?
>>>>>>>
>>>>>> A MHU client can send any number of commands (such u32 values) over a channel.
>>>>>> This client (SCMI) sends just one command over a channel, but other
>>>>>> clients may/do send two or more.
>>>
>>> The above definition doesn't support 2 or more as it is 1-1 with channels.
>>>
>> I thought you suggested to make controller driver accept the command
>> as another cell in client's mboxes property.
>> Which we can't do.
>
> Yes, agreed. But I'm wondering since a client may need more than one,
> how would that be expressed?
>
Most (except SCMI) protocols are proprietary and can not be used
generically, so the command codes get hardcoded in the client driver.
SCMI+MHU is going to be rare case when we have a chance to get the code via DT.

>>>>> Okay, then I guess I don't understand why this is in DT.
>>>>>
>>>> Yeah the client has to provide code (u32 value) for the commands it
>>>> sends, and that value is going to be platform specific. For example,
>>>> on Juno the ITS_AN_SCMI_COMMAND may be defined as BIT(7) while on my
>>>> platform it may be 0x4567
>>>>
>>>> For MHU based platforms, it becomes easy if the u32 is passed from DT.
>>>> And that should be ok since that is like a h/w parameter - a value
>>>> chosen/expected by the remote firmware.
>>>
>>> Could it ever be more than 1 cell?
>>>
>> SCMI sends sub-commands via SHMEM, so it is always going to be 1cell for _scmi_.
>> However many firmwares are unlikely to use just one command over a
>> channel - say, the protocol is trivial or the linux and remote have no
>> SHMEM.
>
> I'd hope the normal case is not enumerating commands and sub-commands
> in DT and this is special case of a "generic" protocol with platform
> specific aspects.
>
Yes. It is only for SCMI protocol running over the variations of MHU controller.

Cheers

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

* [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
@ 2017-10-10  1:52                   ` Jassi Brar
  0 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-10  1:52 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 10, 2017 at 4:27 AM, Rob Herring <robh@kernel.org> wrote:
> On Mon, Oct 9, 2017 at 9:46 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>> On Mon, Oct 9, 2017 at 7:22 PM, Rob Herring <robh@kernel.org> wrote:
>>> On Fri, Oct 6, 2017 at 9:26 PM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>>>> On Fri, Oct 6, 2017 at 9:24 PM, Rob Herring <robh@kernel.org> wrote:
>>>>> On Fri, Oct 6, 2017 at 6:01 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>>>>>> On Fri, Oct 6, 2017 at 4:50 AM, Rob Herring <robh@kernel.org> wrote:
>>>>>>> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
>>>>
>>>>>>>
>>>>>>>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>>>>>>>> +           data as expected by the mailbox controller
>>>>>>>
>>>>>>> Shouldn't that be cells as part of mboxes property?
>>>>>>>
>>>>>> A MHU client can send any number of commands (such u32 values) over a channel.
>>>>>> This client (SCMI) sends just one command over a channel, but other
>>>>>> clients may/do send two or more.
>>>
>>> The above definition doesn't support 2 or more as it is 1-1 with channels.
>>>
>> I thought you suggested to make controller driver accept the command
>> as another cell in client's mboxes property.
>> Which we can't do.
>
> Yes, agreed. But I'm wondering since a client may need more than one,
> how would that be expressed?
>
Most (except SCMI) protocols are proprietary and can not be used
generically, so the command codes get hardcoded in the client driver.
SCMI+MHU is going to be rare case when we have a chance to get the code via DT.

>>>>> Okay, then I guess I don't understand why this is in DT.
>>>>>
>>>> Yeah the client has to provide code (u32 value) for the commands it
>>>> sends, and that value is going to be platform specific. For example,
>>>> on Juno the ITS_AN_SCMI_COMMAND may be defined as BIT(7) while on my
>>>> platform it may be 0x4567
>>>>
>>>> For MHU based platforms, it becomes easy if the u32 is passed from DT.
>>>> And that should be ok since that is like a h/w parameter - a value
>>>> chosen/expected by the remote firmware.
>>>
>>> Could it ever be more than 1 cell?
>>>
>> SCMI sends sub-commands via SHMEM, so it is always going to be 1cell for _scmi_.
>> However many firmwares are unlikely to use just one command over a
>> channel - say, the protocol is trivial or the linux and remote have no
>> SHMEM.
>
> I'd hope the normal case is not enumerating commands and sub-commands
> in DT and this is special case of a "generic" protocol with platform
> specific aspects.
>
Yes. It is only for SCMI protocol running over the variations of MHU controller.

Cheers

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

* Re: [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
  2017-10-09 22:57                 ` Rob Herring
  (?)
@ 2017-10-10 11:04                   ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-10 11:04 UTC (permalink / raw)
  To: Rob Herring, Jassi Brar
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Arnd Bergmann, Loc Ho, Alexey Klimov,
	Ryan Harkin, Mark Rutland



On 09/10/17 23:57, Rob Herring wrote:
> On Mon, Oct 9, 2017 at 9:46 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>> On Mon, Oct 9, 2017 at 7:22 PM, Rob Herring <robh@kernel.org> wrote:
>>> On Fri, Oct 6, 2017 at 9:26 PM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>>>> On Fri, Oct 6, 2017 at 9:24 PM, Rob Herring <robh@kernel.org> wrote:
>>>>> On Fri, Oct 6, 2017 at 6:01 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>>>>>> On Fri, Oct 6, 2017 at 4:50 AM, Rob Herring <robh@kernel.org> wrote:
>>>>>>> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
>>>>
>>>>>>>
>>>>>>>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>>>>>>>> +           data as expected by the mailbox controller
>>>>>>>
>>>>>>> Shouldn't that be cells as part of mboxes property?
>>>>>>>
>>>>>> A MHU client can send any number of commands (such u32 values) over a channel.
>>>>>> This client (SCMI) sends just one command over a channel, but other
>>>>>> clients may/do send two or more.
>>>
>>> The above definition doesn't support 2 or more as it is 1-1 with channels.
>>>
>> I thought you suggested to make controller driver accept the command
>> as another cell in client's mboxes property.
>> Which we can't do.
> 
> Yes, agreed. But I'm wondering since a client may need more than one,
> how would that be expressed?
> 
>>>>> Okay, then I guess I don't understand why this is in DT.
>>>>>
>>>> Yeah the client has to provide code (u32 value) for the commands it
>>>> sends, and that value is going to be platform specific. For example,
>>>> on Juno the ITS_AN_SCMI_COMMAND may be defined as BIT(7) while on my
>>>> platform it may be 0x4567
>>>>
>>>> For MHU based platforms, it becomes easy if the u32 is passed from DT.
>>>> And that should be ok since that is like a h/w parameter - a value
>>>> chosen/expected by the remote firmware.
>>>
>>> Could it ever be more than 1 cell?
>>>
>> SCMI sends sub-commands via SHMEM, so it is always going to be 1cell for _scmi_.
>> However many firmwares are unlikely to use just one command over a
>> channel - say, the protocol is trivial or the linux and remote have no
>> SHMEM.
> 
> I'd hope the normal case is not enumerating commands and sub-commands
> in DT and this is special case of a "generic" protocol with platform
> specific aspects. It could be solved with a specific compatible for
> each platform/implementation. We'll probably regret not doing that,
> but I'm going to pretend that this time SoC vendors won't mess it up.
> 

Just to align on the same page, I would like to define the terms used
above in context of SCMI:
1. commands : this is platform specific "command" to trigger/signal the
	      firmware that SCMI packet is sent. This is always platform
	      or controller specific and is not part of the
	      specification. It's just like doorbell but since MHU can
	      send 32-bit data, we need a way to specify the exact bit
	      as 32-bit data with just one bit set.

2. sub-commands : It is SCMI packet that includes the actual command
		defined in the SCMI specification. There are sent in
		SHMEM as Jassi mentioned above.
-- 
Regards,
Sudeep

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

* Re: [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
@ 2017-10-10 11:04                   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-10 11:04 UTC (permalink / raw)
  To: Rob Herring, Jassi Brar
  Cc: Nishanth Menon, DTML, Arnd Bergmann, Harb Abdulhamid,
	Mark Rutland, Ryan Harkin, LKML, Roy Franz, Loc Ho, Sudeep Holla,
	Alexey Klimov, ALKML



On 09/10/17 23:57, Rob Herring wrote:
> On Mon, Oct 9, 2017 at 9:46 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>> On Mon, Oct 9, 2017 at 7:22 PM, Rob Herring <robh@kernel.org> wrote:
>>> On Fri, Oct 6, 2017 at 9:26 PM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>>>> On Fri, Oct 6, 2017 at 9:24 PM, Rob Herring <robh@kernel.org> wrote:
>>>>> On Fri, Oct 6, 2017 at 6:01 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>>>>>> On Fri, Oct 6, 2017 at 4:50 AM, Rob Herring <robh@kernel.org> wrote:
>>>>>>> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
>>>>
>>>>>>>
>>>>>>>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>>>>>>>> +           data as expected by the mailbox controller
>>>>>>>
>>>>>>> Shouldn't that be cells as part of mboxes property?
>>>>>>>
>>>>>> A MHU client can send any number of commands (such u32 values) over a channel.
>>>>>> This client (SCMI) sends just one command over a channel, but other
>>>>>> clients may/do send two or more.
>>>
>>> The above definition doesn't support 2 or more as it is 1-1 with channels.
>>>
>> I thought you suggested to make controller driver accept the command
>> as another cell in client's mboxes property.
>> Which we can't do.
> 
> Yes, agreed. But I'm wondering since a client may need more than one,
> how would that be expressed?
> 
>>>>> Okay, then I guess I don't understand why this is in DT.
>>>>>
>>>> Yeah the client has to provide code (u32 value) for the commands it
>>>> sends, and that value is going to be platform specific. For example,
>>>> on Juno the ITS_AN_SCMI_COMMAND may be defined as BIT(7) while on my
>>>> platform it may be 0x4567
>>>>
>>>> For MHU based platforms, it becomes easy if the u32 is passed from DT.
>>>> And that should be ok since that is like a h/w parameter - a value
>>>> chosen/expected by the remote firmware.
>>>
>>> Could it ever be more than 1 cell?
>>>
>> SCMI sends sub-commands via SHMEM, so it is always going to be 1cell for _scmi_.
>> However many firmwares are unlikely to use just one command over a
>> channel - say, the protocol is trivial or the linux and remote have no
>> SHMEM.
> 
> I'd hope the normal case is not enumerating commands and sub-commands
> in DT and this is special case of a "generic" protocol with platform
> specific aspects. It could be solved with a specific compatible for
> each platform/implementation. We'll probably regret not doing that,
> but I'm going to pretend that this time SoC vendors won't mess it up.
> 

Just to align on the same page, I would like to define the terms used
above in context of SCMI:
1. commands : this is platform specific "command" to trigger/signal the
	      firmware that SCMI packet is sent. This is always platform
	      or controller specific and is not part of the
	      specification. It's just like doorbell but since MHU can
	      send 32-bit data, we need a way to specify the exact bit
	      as 32-bit data with just one bit set.

2. sub-commands : It is SCMI packet that includes the actual command
		defined in the SCMI specification. There are sent in
		SHMEM as Jassi mentioned above.
-- 
Regards,
Sudeep

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

* [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings
@ 2017-10-10 11:04                   ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-10 11:04 UTC (permalink / raw)
  To: linux-arm-kernel



On 09/10/17 23:57, Rob Herring wrote:
> On Mon, Oct 9, 2017 at 9:46 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>> On Mon, Oct 9, 2017 at 7:22 PM, Rob Herring <robh@kernel.org> wrote:
>>> On Fri, Oct 6, 2017 at 9:26 PM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>>>> On Fri, Oct 6, 2017 at 9:24 PM, Rob Herring <robh@kernel.org> wrote:
>>>>> On Fri, Oct 6, 2017 at 6:01 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>>>>>> On Fri, Oct 6, 2017 at 4:50 AM, Rob Herring <robh@kernel.org> wrote:
>>>>>>> On Thu, Sep 28, 2017 at 02:11:27PM +0100, Sudeep Holla wrote:
>>>>
>>>>>>>
>>>>>>>> +- mbox-data : For each phandle listed in mboxes property, an unsigned 32-bit
>>>>>>>> +           data as expected by the mailbox controller
>>>>>>>
>>>>>>> Shouldn't that be cells as part of mboxes property?
>>>>>>>
>>>>>> A MHU client can send any number of commands (such u32 values) over a channel.
>>>>>> This client (SCMI) sends just one command over a channel, but other
>>>>>> clients may/do send two or more.
>>>
>>> The above definition doesn't support 2 or more as it is 1-1 with channels.
>>>
>> I thought you suggested to make controller driver accept the command
>> as another cell in client's mboxes property.
>> Which we can't do.
> 
> Yes, agreed. But I'm wondering since a client may need more than one,
> how would that be expressed?
> 
>>>>> Okay, then I guess I don't understand why this is in DT.
>>>>>
>>>> Yeah the client has to provide code (u32 value) for the commands it
>>>> sends, and that value is going to be platform specific. For example,
>>>> on Juno the ITS_AN_SCMI_COMMAND may be defined as BIT(7) while on my
>>>> platform it may be 0x4567
>>>>
>>>> For MHU based platforms, it becomes easy if the u32 is passed from DT.
>>>> And that should be ok since that is like a h/w parameter - a value
>>>> chosen/expected by the remote firmware.
>>>
>>> Could it ever be more than 1 cell?
>>>
>> SCMI sends sub-commands via SHMEM, so it is always going to be 1cell for _scmi_.
>> However many firmwares are unlikely to use just one command over a
>> channel - say, the protocol is trivial or the linux and remote have no
>> SHMEM.
> 
> I'd hope the normal case is not enumerating commands and sub-commands
> in DT and this is special case of a "generic" protocol with platform
> specific aspects. It could be solved with a specific compatible for
> each platform/implementation. We'll probably regret not doing that,
> but I'm going to pretend that this time SoC vendors won't mess it up.
> 

Just to align on the same page, I would like to define the terms used
above in context of SCMI:
1. commands : this is platform specific "command" to trigger/signal the
	      firmware that SCMI packet is sent. This is always platform
	      or controller specific and is not part of the
	      specification. It's just like doorbell but since MHU can
	      send 32-bit data, we need a way to specify the exact bit
	      as 32-bit data with just one bit set.

2. sub-commands : It is SCMI packet that includes the actual command
		defined in the SCMI specification. There are sent in
		SHMEM as Jassi mentioned above.
-- 
Regards,
Sudeep

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

* Re: [PATCH v3 17/22][UPDATE] firmware: arm_scmi: add device power domain support genpd
  2017-09-29 13:42     ` Sudeep Holla
@ 2017-10-10 11:05       ` Ulf Hansson
  -1 siblings, 0 replies; 208+ messages in thread
From: Ulf Hansson @ 2017-10-10 11:05 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Kevin Hilman

On 29 September 2017 at 15:42, Sudeep Holla <sudeep.holla@arm.com> wrote:
> This patch hooks up the support for device power domain provided by
> SCMI using the Linux generic power domain infrastructure.
>
> Cc: Kevin Hilman <khilman@baylibre.com>
> Cc: Ulf Hansson <ulf.hansson@linaro.org>
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> ---
>  drivers/firmware/Kconfig                   |  13 +++
>  drivers/firmware/arm_scmi/Makefile         |   1 +
>  drivers/firmware/arm_scmi/scmi_pm_domain.c | 136 +++++++++++++++++++++++++++++
>  3 files changed, 150 insertions(+)
>  create mode 100644 drivers/firmware/arm_scmi/scmi_pm_domain.c
>
> - updated to read the initial state instead of assuming off as
>   suggested by Ulf
>
> diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
> index c3d1a12763ce..a4462bc661c8 100644
> --- a/drivers/firmware/Kconfig
> +++ b/drivers/firmware/Kconfig
> @@ -40,6 +40,19 @@ config ARM_SCMI_PROTOCOL
>           This protocol library provides interface for all the client drivers
>           making use of the features offered by the SCMI.
>
> +config ARM_SCMI_POWER_DOMAIN
> +       tristate "SCMI power domain driver"
> +       depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
> +       default y
> +       select PM_GENERIC_DOMAINS if PM
> +       help
> +         This enables support for the SCMI power domains which can be
> +         enabled or disabled via the SCP firmware
> +
> +         This driver can also be built as a module.  If so, the module
> +         will be called scmi_pm_domain. Note this may needed early in boot
> +         before rootfs may be available.
> +
>  config ARM_SCPI_PROTOCOL
>         tristate "ARM System Control and Power Interface (SCPI) Message Protocol"
>         depends on ARM || ARM64 || COMPILE_TEST
> diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
> index 7fb026c71833..289e9e5a4764 100644
> --- a/drivers/firmware/arm_scmi/Makefile
> +++ b/drivers/firmware/arm_scmi/Makefile
> @@ -1,3 +1,4 @@
>  obj-$(CONFIG_ARM_SCMI_PROTOCOL)        = arm_scmi.o
>  arm_scmi-y = base.o clock.o driver.o mbox_if.o perf.o power.o sensors.o
>  arm_scmi-$(CONFIG_ARM_MHU) += arm_mhu_if.o
> +obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
> diff --git a/drivers/firmware/arm_scmi/scmi_pm_domain.c b/drivers/firmware/arm_scmi/scmi_pm_domain.c
> new file mode 100644
> index 000000000000..f105f7d5c660
> --- /dev/null
> +++ b/drivers/firmware/arm_scmi/scmi_pm_domain.c
> @@ -0,0 +1,136 @@
> +/*
> + * SCMI Generic power domain support.
> + *
> + * Copyright (C) 2017 ARM Ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of_platform.h>
> +#include <linux/pm_domain.h>
> +#include <linux/scmi_protocol.h>
> +
> +struct scmi_pm_domain {
> +       struct generic_pm_domain genpd;
> +       const struct scmi_handle *handle;
> +       const char *name;
> +       u32 domain;
> +};
> +
> +#define to_scmi_pd(gpd) container_of(gpd, struct scmi_pm_domain, genpd)
> +
> +static int scmi_pd_power(struct generic_pm_domain *domain, bool power_on)
> +{
> +       int ret;
> +       u32 state, ret_state;
> +       struct scmi_pm_domain *pd = to_scmi_pd(domain);
> +       const struct scmi_power_ops *ops = pd->handle->power_ops;
> +
> +       if (power_on)
> +               state = SCMI_POWER_STATE_GENERIC_ON;
> +       else
> +               state = SCMI_POWER_STATE_GENERIC_OFF;
> +
> +       ret = ops->state_set(pd->handle, pd->domain, state);
> +       if (!ret)
> +               ret = ops->state_get(pd->handle, pd->domain, &ret_state);
> +       if (!ret && state != ret_state)
> +               return -EIO;
> +
> +       return ret;
> +}
> +
> +static int scmi_pd_power_on(struct generic_pm_domain *domain)
> +{
> +       return scmi_pd_power(domain, true);
> +}
> +
> +static int scmi_pd_power_off(struct generic_pm_domain *domain)
> +{
> +       return scmi_pd_power(domain, false);
> +}
> +
> +static int scmi_pm_domain_probe(struct platform_device *pdev)
> +{
> +       int num_domains, i;
> +       struct device *dev = &pdev->dev;
> +       struct device_node *np = dev->of_node;
> +       struct scmi_pm_domain *scmi_pd;
> +       struct genpd_onecell_data *scmi_pd_data;
> +       struct generic_pm_domain **domains;
> +       const struct scmi_handle *handle = devm_scmi_handle_get(dev);
> +
> +       if (IS_ERR_OR_NULL(handle) || !handle->power_ops)
> +               return -EPROBE_DEFER;
> +
> +       num_domains = handle->power_ops->num_domains_get(handle);
> +       if (num_domains < 0) {
> +               dev_err(dev, "number of domains not found\n");
> +               return num_domains;
> +       }
> +
> +       scmi_pd = devm_kcalloc(dev, num_domains, sizeof(*scmi_pd), GFP_KERNEL);
> +       if (!scmi_pd)
> +               return -ENOMEM;
> +
> +       scmi_pd_data = devm_kzalloc(dev, sizeof(*scmi_pd_data), GFP_KERNEL);
> +       if (!scmi_pd_data)
> +               return -ENOMEM;
> +
> +       domains = devm_kcalloc(dev, num_domains, sizeof(*domains), GFP_KERNEL);
> +       if (!domains)
> +               return -ENOMEM;
> +
> +       for (i = 0; i < num_domains; i++, scmi_pd++) {
> +               u32 state;
> +
> +               domains[i] = &scmi_pd->genpd;
> +
> +               scmi_pd->domain = i;
> +               scmi_pd->handle = handle;
> +               scmi_pd->name = handle->power_ops->name_get(handle, i);
> +               scmi_pd->genpd.name = scmi_pd->name;
> +               scmi_pd->genpd.power_off = scmi_pd_power_off;
> +               scmi_pd->genpd.power_on = scmi_pd_power_on;
> +
> +               if (handle->power_ops->state_get(handle, i, &state)) {
> +                       dev_dbg(dev, "failed to get state for domain %d\n", i);

Perhaps dev_warn() instead?

> +                       continue;
> +               }
> +
> +               pm_genpd_init(&scmi_pd->genpd, NULL,
> +                             state == SCMI_POWER_STATE_GENERIC_OFF);
> +       }
> +
> +       scmi_pd_data->domains = domains;
> +       scmi_pd_data->num_domains = num_domains;
> +
> +       of_genpd_add_provider_onecell(np, scmi_pd_data);
> +
> +       return 0;
> +}
> +
> +static struct platform_driver scmi_power_domain_driver = {
> +       .driver = {
> +               .name = "scmi-power-domain",
> +       },
> +       .probe = scmi_pm_domain_probe,
> +};
> +module_platform_driver(scmi_power_domain_driver);
> +
> +MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
> +MODULE_DESCRIPTION("ARM SCMI power domain driver");
> +MODULE_LICENSE("GPL v2");
> --
> 2.7.4
>

Besides the nitpick above, feel free to add:

Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>

Kind regards
Uffe

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

* [PATCH v3 17/22][UPDATE] firmware: arm_scmi: add device power domain support genpd
@ 2017-10-10 11:05       ` Ulf Hansson
  0 siblings, 0 replies; 208+ messages in thread
From: Ulf Hansson @ 2017-10-10 11:05 UTC (permalink / raw)
  To: linux-arm-kernel

On 29 September 2017 at 15:42, Sudeep Holla <sudeep.holla@arm.com> wrote:
> This patch hooks up the support for device power domain provided by
> SCMI using the Linux generic power domain infrastructure.
>
> Cc: Kevin Hilman <khilman@baylibre.com>
> Cc: Ulf Hansson <ulf.hansson@linaro.org>
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> ---
>  drivers/firmware/Kconfig                   |  13 +++
>  drivers/firmware/arm_scmi/Makefile         |   1 +
>  drivers/firmware/arm_scmi/scmi_pm_domain.c | 136 +++++++++++++++++++++++++++++
>  3 files changed, 150 insertions(+)
>  create mode 100644 drivers/firmware/arm_scmi/scmi_pm_domain.c
>
> - updated to read the initial state instead of assuming off as
>   suggested by Ulf
>
> diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
> index c3d1a12763ce..a4462bc661c8 100644
> --- a/drivers/firmware/Kconfig
> +++ b/drivers/firmware/Kconfig
> @@ -40,6 +40,19 @@ config ARM_SCMI_PROTOCOL
>           This protocol library provides interface for all the client drivers
>           making use of the features offered by the SCMI.
>
> +config ARM_SCMI_POWER_DOMAIN
> +       tristate "SCMI power domain driver"
> +       depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
> +       default y
> +       select PM_GENERIC_DOMAINS if PM
> +       help
> +         This enables support for the SCMI power domains which can be
> +         enabled or disabled via the SCP firmware
> +
> +         This driver can also be built as a module.  If so, the module
> +         will be called scmi_pm_domain. Note this may needed early in boot
> +         before rootfs may be available.
> +
>  config ARM_SCPI_PROTOCOL
>         tristate "ARM System Control and Power Interface (SCPI) Message Protocol"
>         depends on ARM || ARM64 || COMPILE_TEST
> diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
> index 7fb026c71833..289e9e5a4764 100644
> --- a/drivers/firmware/arm_scmi/Makefile
> +++ b/drivers/firmware/arm_scmi/Makefile
> @@ -1,3 +1,4 @@
>  obj-$(CONFIG_ARM_SCMI_PROTOCOL)        = arm_scmi.o
>  arm_scmi-y = base.o clock.o driver.o mbox_if.o perf.o power.o sensors.o
>  arm_scmi-$(CONFIG_ARM_MHU) += arm_mhu_if.o
> +obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
> diff --git a/drivers/firmware/arm_scmi/scmi_pm_domain.c b/drivers/firmware/arm_scmi/scmi_pm_domain.c
> new file mode 100644
> index 000000000000..f105f7d5c660
> --- /dev/null
> +++ b/drivers/firmware/arm_scmi/scmi_pm_domain.c
> @@ -0,0 +1,136 @@
> +/*
> + * SCMI Generic power domain support.
> + *
> + * Copyright (C) 2017 ARM Ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of_platform.h>
> +#include <linux/pm_domain.h>
> +#include <linux/scmi_protocol.h>
> +
> +struct scmi_pm_domain {
> +       struct generic_pm_domain genpd;
> +       const struct scmi_handle *handle;
> +       const char *name;
> +       u32 domain;
> +};
> +
> +#define to_scmi_pd(gpd) container_of(gpd, struct scmi_pm_domain, genpd)
> +
> +static int scmi_pd_power(struct generic_pm_domain *domain, bool power_on)
> +{
> +       int ret;
> +       u32 state, ret_state;
> +       struct scmi_pm_domain *pd = to_scmi_pd(domain);
> +       const struct scmi_power_ops *ops = pd->handle->power_ops;
> +
> +       if (power_on)
> +               state = SCMI_POWER_STATE_GENERIC_ON;
> +       else
> +               state = SCMI_POWER_STATE_GENERIC_OFF;
> +
> +       ret = ops->state_set(pd->handle, pd->domain, state);
> +       if (!ret)
> +               ret = ops->state_get(pd->handle, pd->domain, &ret_state);
> +       if (!ret && state != ret_state)
> +               return -EIO;
> +
> +       return ret;
> +}
> +
> +static int scmi_pd_power_on(struct generic_pm_domain *domain)
> +{
> +       return scmi_pd_power(domain, true);
> +}
> +
> +static int scmi_pd_power_off(struct generic_pm_domain *domain)
> +{
> +       return scmi_pd_power(domain, false);
> +}
> +
> +static int scmi_pm_domain_probe(struct platform_device *pdev)
> +{
> +       int num_domains, i;
> +       struct device *dev = &pdev->dev;
> +       struct device_node *np = dev->of_node;
> +       struct scmi_pm_domain *scmi_pd;
> +       struct genpd_onecell_data *scmi_pd_data;
> +       struct generic_pm_domain **domains;
> +       const struct scmi_handle *handle = devm_scmi_handle_get(dev);
> +
> +       if (IS_ERR_OR_NULL(handle) || !handle->power_ops)
> +               return -EPROBE_DEFER;
> +
> +       num_domains = handle->power_ops->num_domains_get(handle);
> +       if (num_domains < 0) {
> +               dev_err(dev, "number of domains not found\n");
> +               return num_domains;
> +       }
> +
> +       scmi_pd = devm_kcalloc(dev, num_domains, sizeof(*scmi_pd), GFP_KERNEL);
> +       if (!scmi_pd)
> +               return -ENOMEM;
> +
> +       scmi_pd_data = devm_kzalloc(dev, sizeof(*scmi_pd_data), GFP_KERNEL);
> +       if (!scmi_pd_data)
> +               return -ENOMEM;
> +
> +       domains = devm_kcalloc(dev, num_domains, sizeof(*domains), GFP_KERNEL);
> +       if (!domains)
> +               return -ENOMEM;
> +
> +       for (i = 0; i < num_domains; i++, scmi_pd++) {
> +               u32 state;
> +
> +               domains[i] = &scmi_pd->genpd;
> +
> +               scmi_pd->domain = i;
> +               scmi_pd->handle = handle;
> +               scmi_pd->name = handle->power_ops->name_get(handle, i);
> +               scmi_pd->genpd.name = scmi_pd->name;
> +               scmi_pd->genpd.power_off = scmi_pd_power_off;
> +               scmi_pd->genpd.power_on = scmi_pd_power_on;
> +
> +               if (handle->power_ops->state_get(handle, i, &state)) {
> +                       dev_dbg(dev, "failed to get state for domain %d\n", i);

Perhaps dev_warn() instead?

> +                       continue;
> +               }
> +
> +               pm_genpd_init(&scmi_pd->genpd, NULL,
> +                             state == SCMI_POWER_STATE_GENERIC_OFF);
> +       }
> +
> +       scmi_pd_data->domains = domains;
> +       scmi_pd_data->num_domains = num_domains;
> +
> +       of_genpd_add_provider_onecell(np, scmi_pd_data);
> +
> +       return 0;
> +}
> +
> +static struct platform_driver scmi_power_domain_driver = {
> +       .driver = {
> +               .name = "scmi-power-domain",
> +       },
> +       .probe = scmi_pm_domain_probe,
> +};
> +module_platform_driver(scmi_power_domain_driver);
> +
> +MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
> +MODULE_DESCRIPTION("ARM SCMI power domain driver");
> +MODULE_LICENSE("GPL v2");
> --
> 2.7.4
>

Besides the nitpick above, feel free to add:

Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>

Kind regards
Uffe

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

* Re: [PATCH v3 17/22][UPDATE] firmware: arm_scmi: add device power domain support genpd
@ 2017-10-10 13:02         ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-10 13:02 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Arnd Bergmann, Loc Ho, Alexey Klimov,
	Ryan Harkin, Jassi Brar, Kevin Hilman



On 10/10/17 12:05, Ulf Hansson wrote:
> On 29 September 2017 at 15:42, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> This patch hooks up the support for device power domain provided by
>> SCMI using the Linux generic power domain infrastructure.
>>
>> Cc: Kevin Hilman <khilman@baylibre.com>
>> Cc: Ulf Hansson <ulf.hansson@linaro.org>
>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>> ---
>>  drivers/firmware/Kconfig                   |  13 +++
>>  drivers/firmware/arm_scmi/Makefile         |   1 +
>>  drivers/firmware/arm_scmi/scmi_pm_domain.c | 136 +++++++++++++++++++++++++++++
>>  3 files changed, 150 insertions(+)
>>  create mode 100644 drivers/firmware/arm_scmi/scmi_pm_domain.c
>>
>> - updated to read the initial state instead of assuming off as
>>   suggested by Ulf
>>
>> diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
>> index c3d1a12763ce..a4462bc661c8 100644
>> --- a/drivers/firmware/Kconfig
>> +++ b/drivers/firmware/Kconfig
>> @@ -40,6 +40,19 @@ config ARM_SCMI_PROTOCOL

[..]

>> +               domains[i] = &scmi_pd->genpd;
>> +
>> +               scmi_pd->domain = i;
>> +               scmi_pd->handle = handle;
>> +               scmi_pd->name = handle->power_ops->name_get(handle, i);
>> +               scmi_pd->genpd.name = scmi_pd->name;
>> +               scmi_pd->genpd.power_off = scmi_pd_power_off;
>> +               scmi_pd->genpd.power_on = scmi_pd_power_on;
>> +
>> +               if (handle->power_ops->state_get(handle, i, &state)) {
>> +                       dev_dbg(dev, "failed to get state for domain %d\n", i);
> 
> Perhaps dev_warn() instead?
> 

Will do.

[..]

> 
> Besides the nitpick above, feel free to add:
> 
> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
> 

Thanks.

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 17/22][UPDATE] firmware: arm_scmi: add device power domain support genpd
@ 2017-10-10 13:02         ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-10 13:02 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Arnd Bergmann, Loc Ho, Alexey Klimov,
	Ryan Harkin, Jassi Brar, Kevin Hilman



On 10/10/17 12:05, Ulf Hansson wrote:
> On 29 September 2017 at 15:42, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
>> This patch hooks up the support for device power domain provided by
>> SCMI using the Linux generic power domain infrastructure.
>>
>> Cc: Kevin Hilman <khilman-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
>> Cc: Ulf Hansson <ulf.hansson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>> Signed-off-by: Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org>
>> ---
>>  drivers/firmware/Kconfig                   |  13 +++
>>  drivers/firmware/arm_scmi/Makefile         |   1 +
>>  drivers/firmware/arm_scmi/scmi_pm_domain.c | 136 +++++++++++++++++++++++++++++
>>  3 files changed, 150 insertions(+)
>>  create mode 100644 drivers/firmware/arm_scmi/scmi_pm_domain.c
>>
>> - updated to read the initial state instead of assuming off as
>>   suggested by Ulf
>>
>> diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
>> index c3d1a12763ce..a4462bc661c8 100644
>> --- a/drivers/firmware/Kconfig
>> +++ b/drivers/firmware/Kconfig
>> @@ -40,6 +40,19 @@ config ARM_SCMI_PROTOCOL

[..]

>> +               domains[i] = &scmi_pd->genpd;
>> +
>> +               scmi_pd->domain = i;
>> +               scmi_pd->handle = handle;
>> +               scmi_pd->name = handle->power_ops->name_get(handle, i);
>> +               scmi_pd->genpd.name = scmi_pd->name;
>> +               scmi_pd->genpd.power_off = scmi_pd_power_off;
>> +               scmi_pd->genpd.power_on = scmi_pd_power_on;
>> +
>> +               if (handle->power_ops->state_get(handle, i, &state)) {
>> +                       dev_dbg(dev, "failed to get state for domain %d\n", i);
> 
> Perhaps dev_warn() instead?
> 

Will do.

[..]

> 
> Besides the nitpick above, feel free to add:
> 
> Reviewed-by: Ulf Hansson <ulf.hansson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> 

Thanks.

-- 
Regards,
Sudeep
--
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] 208+ messages in thread

* [PATCH v3 17/22][UPDATE] firmware: arm_scmi: add device power domain support genpd
@ 2017-10-10 13:02         ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-10 13:02 UTC (permalink / raw)
  To: linux-arm-kernel



On 10/10/17 12:05, Ulf Hansson wrote:
> On 29 September 2017 at 15:42, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> This patch hooks up the support for device power domain provided by
>> SCMI using the Linux generic power domain infrastructure.
>>
>> Cc: Kevin Hilman <khilman@baylibre.com>
>> Cc: Ulf Hansson <ulf.hansson@linaro.org>
>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>> ---
>>  drivers/firmware/Kconfig                   |  13 +++
>>  drivers/firmware/arm_scmi/Makefile         |   1 +
>>  drivers/firmware/arm_scmi/scmi_pm_domain.c | 136 +++++++++++++++++++++++++++++
>>  3 files changed, 150 insertions(+)
>>  create mode 100644 drivers/firmware/arm_scmi/scmi_pm_domain.c
>>
>> - updated to read the initial state instead of assuming off as
>>   suggested by Ulf
>>
>> diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
>> index c3d1a12763ce..a4462bc661c8 100644
>> --- a/drivers/firmware/Kconfig
>> +++ b/drivers/firmware/Kconfig
>> @@ -40,6 +40,19 @@ config ARM_SCMI_PROTOCOL

[..]

>> +               domains[i] = &scmi_pd->genpd;
>> +
>> +               scmi_pd->domain = i;
>> +               scmi_pd->handle = handle;
>> +               scmi_pd->name = handle->power_ops->name_get(handle, i);
>> +               scmi_pd->genpd.name = scmi_pd->name;
>> +               scmi_pd->genpd.power_off = scmi_pd_power_off;
>> +               scmi_pd->genpd.power_on = scmi_pd_power_on;
>> +
>> +               if (handle->power_ops->state_get(handle, i, &state)) {
>> +                       dev_dbg(dev, "failed to get state for domain %d\n", i);
> 
> Perhaps dev_warn() instead?
> 

Will do.

[..]

> 
> Besides the nitpick above, feel free to add:
> 
> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
> 

Thanks.

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
  2017-10-06 13:51             ` Sudeep Holla
@ 2017-10-12 21:03               ` Bjorn Andersson
  -1 siblings, 0 replies; 208+ messages in thread
From: Bjorn Andersson @ 2017-10-12 21:03 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Jassi Brar, Arnd Bergmann, ALKML, LKML, DTML, Roy Franz,
	Harb Abdulhamid, Nishanth Menon, Loc Ho, Alexey Klimov,
	Ryan Harkin

On Fri, Oct 6, 2017 at 6:51 AM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
>
> On 06/10/17 14:47, Jassi Brar wrote:
>> On Fri, Oct 6, 2017 at 7:02 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
[..]
>>> Again that's not the point, doorbell is more common feature and that can
>>> be supported. As SCMI expects doorbell feature in the specification, it
>>> just need to support that class of controllers.
>>>
>> NO.  All SCMI expects is SHMEM and a signal reaching the other end.
>> The signal mechanism need not necessarily be "doorbell".
>>
>
> Agreed, but creating an abstraction ro do something as generic as
> doorbell and writing shim layer for each controller to use SCMI also
> sounds bad.
>

In the Qualcomm platform we have a single register that exposes 32
doorbells, wired to interrupts on the various processors/co-processors
in the SoC.

There is a handful of different clients each using these doorbells to
inform the other side that something has happened (often that some
piece of shared memory has been filled with data). Over the years
(platforms) this register has moved around as such multiple
implementations exists.

You can see an example of this in
drivers/mailbox/qcom-apcs-ipc-mailbox.c and e.g.
drivers/rpmsg/qcom_glink_native.c (qcom_glink_rpm.c prior to v4.14).



I'm struggling to figure out exactly how your case looks like, but if
your doorbell exists in only one instance and there is only one client
then I would suggest that it's overkill to create another driver for
it.

Regards,
Bjorn

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

* [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-12 21:03               ` Bjorn Andersson
  0 siblings, 0 replies; 208+ messages in thread
From: Bjorn Andersson @ 2017-10-12 21:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 6, 2017 at 6:51 AM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
>
> On 06/10/17 14:47, Jassi Brar wrote:
>> On Fri, Oct 6, 2017 at 7:02 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
[..]
>>> Again that's not the point, doorbell is more common feature and that can
>>> be supported. As SCMI expects doorbell feature in the specification, it
>>> just need to support that class of controllers.
>>>
>> NO.  All SCMI expects is SHMEM and a signal reaching the other end.
>> The signal mechanism need not necessarily be "doorbell".
>>
>
> Agreed, but creating an abstraction ro do something as generic as
> doorbell and writing shim layer for each controller to use SCMI also
> sounds bad.
>

In the Qualcomm platform we have a single register that exposes 32
doorbells, wired to interrupts on the various processors/co-processors
in the SoC.

There is a handful of different clients each using these doorbells to
inform the other side that something has happened (often that some
piece of shared memory has been filled with data). Over the years
(platforms) this register has moved around as such multiple
implementations exists.

You can see an example of this in
drivers/mailbox/qcom-apcs-ipc-mailbox.c and e.g.
drivers/rpmsg/qcom_glink_native.c (qcom_glink_rpm.c prior to v4.14).



I'm struggling to figure out exactly how your case looks like, but if
your doorbell exists in only one instance and there is only one client
then I would suggest that it's overkill to create another driver for
it.

Regards,
Bjorn

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

* Re: [PATCH v3 15/22] firmware: arm_scmi: abstract mailbox interface
  2017-10-04 11:32       ` Sudeep Holla
@ 2017-10-12 21:20         ` Bjorn Andersson
  -1 siblings, 0 replies; 208+ messages in thread
From: Bjorn Andersson @ 2017-10-12 21:20 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Arnd Bergmann, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar

On Wed, Oct 4, 2017 at 4:32 AM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
>
> On 04/10/17 12:24, Arnd Bergmann wrote:
>> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>> Some of the mailbox controller expects controller specific data in order
>>> to implement simple doorbell mechanism as expected by SCMI specification.
>>>
>>> This patch creates a shim layer to abstract the mailbox interface so
>>> that it can support any mailbox controller. It also provides default
>>> implementation which maps to standard mailbox client APIs, so that
>>> controllers implementing doorbell mechanism need not require any
>>> additional layer.
>>>
>>> Cc: Arnd Bergmann <arnd@arndb.de>
>>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>>
>> Another level? Now we have three levels of stacked mailboxes, with
>> the highest level being the combined mailbox/memory, then the shim,
>> and below it the hardware mailbox.
>>
>> Can you try to come up with a way to do this with fewer abstractions?
>>
>
> I completely agree with you. I was against this but Jassi recommended
> this. I just wanted this SCMI to work with mailbox controllers that
> support simple doorbell mechanism as specified in the specification but
> Jassi disagrees with that.
>
>> Maybe you could assume that the mailbox itself can take variable-length
>> data packets, and then use the shim here for those that require
>> something else?
>>
>
> As per SCMI specification, we pass all the data in shared memory and it
> just expects to use a simple doorbell feature from hardware mailbox
> controllers. It's done that way intentionally to avoid dependency on h/w
> and we for sure will have variety of it and that defeats the purpose
> of this standard specification.
>
> Also, I have added shim only for specific controllers that need them.
> E.g. ARM MHU as Jassi disagreed to add doorbell mechanism to that.
> mbox_if provides default implementation that just calls direct mailbox
> APIs.
>

drivers/mailbox is a framework for interfacing/abstracting hardware
mailboxes. If you're starting to layer mailboxes ontop of each-other
chances are very high that you're confusing it with the computer
science term "mailbox".

Abstracting a doorbell-like piece of hardware behind the mbox
framework makes a lot of sense, but the interface between your clients
and the code that fills out shared memory and then invokes said
doorbell is a higher level of "mailbox" and is probably better
implemented using a direct function call.

Regards,
Bjorn

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

* [PATCH v3 15/22] firmware: arm_scmi: abstract mailbox interface
@ 2017-10-12 21:20         ` Bjorn Andersson
  0 siblings, 0 replies; 208+ messages in thread
From: Bjorn Andersson @ 2017-10-12 21:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Oct 4, 2017 at 4:32 AM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
>
> On 04/10/17 12:24, Arnd Bergmann wrote:
>> On Thu, Sep 28, 2017 at 3:11 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>> Some of the mailbox controller expects controller specific data in order
>>> to implement simple doorbell mechanism as expected by SCMI specification.
>>>
>>> This patch creates a shim layer to abstract the mailbox interface so
>>> that it can support any mailbox controller. It also provides default
>>> implementation which maps to standard mailbox client APIs, so that
>>> controllers implementing doorbell mechanism need not require any
>>> additional layer.
>>>
>>> Cc: Arnd Bergmann <arnd@arndb.de>
>>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>>
>> Another level? Now we have three levels of stacked mailboxes, with
>> the highest level being the combined mailbox/memory, then the shim,
>> and below it the hardware mailbox.
>>
>> Can you try to come up with a way to do this with fewer abstractions?
>>
>
> I completely agree with you. I was against this but Jassi recommended
> this. I just wanted this SCMI to work with mailbox controllers that
> support simple doorbell mechanism as specified in the specification but
> Jassi disagrees with that.
>
>> Maybe you could assume that the mailbox itself can take variable-length
>> data packets, and then use the shim here for those that require
>> something else?
>>
>
> As per SCMI specification, we pass all the data in shared memory and it
> just expects to use a simple doorbell feature from hardware mailbox
> controllers. It's done that way intentionally to avoid dependency on h/w
> and we for sure will have variety of it and that defeats the purpose
> of this standard specification.
>
> Also, I have added shim only for specific controllers that need them.
> E.g. ARM MHU as Jassi disagreed to add doorbell mechanism to that.
> mbox_if provides default implementation that just calls direct mailbox
> APIs.
>

drivers/mailbox is a framework for interfacing/abstracting hardware
mailboxes. If you're starting to layer mailboxes ontop of each-other
chances are very high that you're confusing it with the computer
science term "mailbox".

Abstracting a doorbell-like piece of hardware behind the mbox
framework makes a lot of sense, but the interface between your clients
and the code that fills out shared memory and then invokes said
doorbell is a higher level of "mailbox" and is probably better
implemented using a direct function call.

Regards,
Bjorn

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

* Re: [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-13 13:42                 ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-13 13:42 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Sudeep Holla, Jassi Brar, Arnd Bergmann, ALKML, LKML, DTML,
	Roy Franz, Harb Abdulhamid, Nishanth Menon, Loc Ho,
	Alexey Klimov, Ryan Harkin


Hi Bjorn,

Thanks for taking a look at this. Much appreciated.

On 12/10/17 22:03, Bjorn Andersson wrote:
> On Fri, Oct 6, 2017 at 6:51 AM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>
>>
>> On 06/10/17 14:47, Jassi Brar wrote:
>>> On Fri, Oct 6, 2017 at 7:02 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> [..]
>>>> Again that's not the point, doorbell is more common feature and that can
>>>> be supported. As SCMI expects doorbell feature in the specification, it
>>>> just need to support that class of controllers.
>>>>
>>> NO.  All SCMI expects is SHMEM and a signal reaching the other end.
>>> The signal mechanism need not necessarily be "doorbell".
>>>
>>
>> Agreed, but creating an abstraction ro do something as generic as
>> doorbell and writing shim layer for each controller to use SCMI also
>> sounds bad.
>>
> 
> In the Qualcomm platform we have a single register that exposes 32
> doorbells, wired to interrupts on the various processors/co-processors
> in the SoC.
> 

It's exactly same even on ARM MHU controller. The hardware provides 32
independent bits in a single register termed as a single physical
channel. We may have 2 -3 instances of it in a platform(secure only,
high priority and a low priority).

However the single register is being used to pass 32-bit data on some
platforms. So we may need to support both modes.

One way to deal with that is to add doorbell support in the driver as I
tried previously. But the mailbox maintainer has expressed concerns on
that and hence I am trying to achieve that with the abstraction as in
this patch.

> There is a handful of different clients each using these doorbells to
> inform the other side that something has happened (often that some
> piece of shared memory has been filled with data). Over the years
> (platforms) this register has moved around as such multiple
> implementations exists.
> 
> You can see an example of this in
> drivers/mailbox/qcom-apcs-ipc-mailbox.c and e.g.
> drivers/rpmsg/qcom_glink_native.c (qcom_glink_rpm.c prior to v4.14).
> 
> 

Thanks for the pointer, I have already looked at these implementations.

> 
> I'm struggling to figure out exactly how your case looks like, but if
> your doorbell exists in only one instance and there is only one client
> then I would suggest that it's overkill to create another driver for
> it.
> 

While I agree with your opinion, the maintainer has concerns on trying
to make this a generic solution.
-- 
Regards,
Sudeep

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

* Re: [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-13 13:42                 ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-13 13:42 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Sudeep Holla, Jassi Brar, Arnd Bergmann, ALKML, LKML, DTML,
	Roy Franz, Harb Abdulhamid, Nishanth Menon, Loc Ho,
	Alexey Klimov, Ryan Harkin


Hi Bjorn,

Thanks for taking a look at this. Much appreciated.

On 12/10/17 22:03, Bjorn Andersson wrote:
> On Fri, Oct 6, 2017 at 6:51 AM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
>>
>>
>> On 06/10/17 14:47, Jassi Brar wrote:
>>> On Fri, Oct 6, 2017 at 7:02 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
> [..]
>>>> Again that's not the point, doorbell is more common feature and that can
>>>> be supported. As SCMI expects doorbell feature in the specification, it
>>>> just need to support that class of controllers.
>>>>
>>> NO.  All SCMI expects is SHMEM and a signal reaching the other end.
>>> The signal mechanism need not necessarily be "doorbell".
>>>
>>
>> Agreed, but creating an abstraction ro do something as generic as
>> doorbell and writing shim layer for each controller to use SCMI also
>> sounds bad.
>>
> 
> In the Qualcomm platform we have a single register that exposes 32
> doorbells, wired to interrupts on the various processors/co-processors
> in the SoC.
> 

It's exactly same even on ARM MHU controller. The hardware provides 32
independent bits in a single register termed as a single physical
channel. We may have 2 -3 instances of it in a platform(secure only,
high priority and a low priority).

However the single register is being used to pass 32-bit data on some
platforms. So we may need to support both modes.

One way to deal with that is to add doorbell support in the driver as I
tried previously. But the mailbox maintainer has expressed concerns on
that and hence I am trying to achieve that with the abstraction as in
this patch.

> There is a handful of different clients each using these doorbells to
> inform the other side that something has happened (often that some
> piece of shared memory has been filled with data). Over the years
> (platforms) this register has moved around as such multiple
> implementations exists.
> 
> You can see an example of this in
> drivers/mailbox/qcom-apcs-ipc-mailbox.c and e.g.
> drivers/rpmsg/qcom_glink_native.c (qcom_glink_rpm.c prior to v4.14).
> 
> 

Thanks for the pointer, I have already looked at these implementations.

> 
> I'm struggling to figure out exactly how your case looks like, but if
> your doorbell exists in only one instance and there is only one client
> then I would suggest that it's overkill to create another driver for
> it.
> 

While I agree with your opinion, the maintainer has concerns on trying
to make this a generic solution.
-- 
Regards,
Sudeep
--
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] 208+ messages in thread

* [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-13 13:42                 ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-13 13:42 UTC (permalink / raw)
  To: linux-arm-kernel


Hi Bjorn,

Thanks for taking a look at this. Much appreciated.

On 12/10/17 22:03, Bjorn Andersson wrote:
> On Fri, Oct 6, 2017 at 6:51 AM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>
>>
>> On 06/10/17 14:47, Jassi Brar wrote:
>>> On Fri, Oct 6, 2017 at 7:02 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> [..]
>>>> Again that's not the point, doorbell is more common feature and that can
>>>> be supported. As SCMI expects doorbell feature in the specification, it
>>>> just need to support that class of controllers.
>>>>
>>> NO.  All SCMI expects is SHMEM and a signal reaching the other end.
>>> The signal mechanism need not necessarily be "doorbell".
>>>
>>
>> Agreed, but creating an abstraction ro do something as generic as
>> doorbell and writing shim layer for each controller to use SCMI also
>> sounds bad.
>>
> 
> In the Qualcomm platform we have a single register that exposes 32
> doorbells, wired to interrupts on the various processors/co-processors
> in the SoC.
> 

It's exactly same even on ARM MHU controller. The hardware provides 32
independent bits in a single register termed as a single physical
channel. We may have 2 -3 instances of it in a platform(secure only,
high priority and a low priority).

However the single register is being used to pass 32-bit data on some
platforms. So we may need to support both modes.

One way to deal with that is to add doorbell support in the driver as I
tried previously. But the mailbox maintainer has expressed concerns on
that and hence I am trying to achieve that with the abstraction as in
this patch.

> There is a handful of different clients each using these doorbells to
> inform the other side that something has happened (often that some
> piece of shared memory has been filled with data). Over the years
> (platforms) this register has moved around as such multiple
> implementations exists.
> 
> You can see an example of this in
> drivers/mailbox/qcom-apcs-ipc-mailbox.c and e.g.
> drivers/rpmsg/qcom_glink_native.c (qcom_glink_rpm.c prior to v4.14).
> 
> 

Thanks for the pointer, I have already looked at these implementations.

> 
> I'm struggling to figure out exactly how your case looks like, but if
> your doorbell exists in only one instance and there is only one client
> then I would suggest that it's overkill to create another driver for
> it.
> 

While I agree with your opinion, the maintainer has concerns on trying
to make this a generic solution.
-- 
Regards,
Sudeep

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

* Re: [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-13 14:12                   ` Jassi Brar
  0 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-13 14:12 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Bjorn Andersson, Arnd Bergmann, ALKML, LKML, DTML, Roy Franz,
	Harb Abdulhamid, Nishanth Menon, Loc Ho, Alexey Klimov,
	Ryan Harkin

On Fri, Oct 13, 2017 at 7:12 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
> Hi Bjorn,
>
> Thanks for taking a look at this. Much appreciated.
>
> On 12/10/17 22:03, Bjorn Andersson wrote:
>> On Fri, Oct 6, 2017 at 6:51 AM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>>
>>>
>>> On 06/10/17 14:47, Jassi Brar wrote:
>>>> On Fri, Oct 6, 2017 at 7:02 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> [..]
>>>>> Again that's not the point, doorbell is more common feature and that can
>>>>> be supported. As SCMI expects doorbell feature in the specification, it
>>>>> just need to support that class of controllers.
>>>>>
>>>> NO.  All SCMI expects is SHMEM and a signal reaching the other end.
>>>> The signal mechanism need not necessarily be "doorbell".
>>>>
>>>
>>> Agreed, but creating an abstraction ro do something as generic as
>>> doorbell and writing shim layer for each controller to use SCMI also
>>> sounds bad.
>>>
>>
>> In the Qualcomm platform we have a single register that exposes 32
>> doorbells, wired to interrupts on the various processors/co-processors
>> in the SoC.
>>
>
> It's exactly same even on ARM MHU controller.
>
This has been a big problem in our communication. You start with
"exactly same..." and go on telling the difference.
And that difference is important.

In MHU the 32bits are tied together and all go to one target
processor. Whereas on QCom, each bit corresponds to independent signal
going to a different target processor.

IOW, QCom has 32 channels per register whereas MHU has one. The
current drivers reflect that reality and hence I am against any change
in MHU driver.  Not to mean even changing the MHU driver will fix the
core issue - which is https://lkml.org/lkml/2017/7/7/465 and this
patchset tries to address that.

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

* Re: [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-13 14:12                   ` Jassi Brar
  0 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-13 14:12 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Bjorn Andersson, Arnd Bergmann, ALKML, LKML, DTML, Roy Franz,
	Harb Abdulhamid, Nishanth Menon, Loc Ho, Alexey Klimov,
	Ryan Harkin

On Fri, Oct 13, 2017 at 7:12 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
>
> Hi Bjorn,
>
> Thanks for taking a look at this. Much appreciated.
>
> On 12/10/17 22:03, Bjorn Andersson wrote:
>> On Fri, Oct 6, 2017 at 6:51 AM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
>>>
>>>
>>> On 06/10/17 14:47, Jassi Brar wrote:
>>>> On Fri, Oct 6, 2017 at 7:02 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
>> [..]
>>>>> Again that's not the point, doorbell is more common feature and that can
>>>>> be supported. As SCMI expects doorbell feature in the specification, it
>>>>> just need to support that class of controllers.
>>>>>
>>>> NO.  All SCMI expects is SHMEM and a signal reaching the other end.
>>>> The signal mechanism need not necessarily be "doorbell".
>>>>
>>>
>>> Agreed, but creating an abstraction ro do something as generic as
>>> doorbell and writing shim layer for each controller to use SCMI also
>>> sounds bad.
>>>
>>
>> In the Qualcomm platform we have a single register that exposes 32
>> doorbells, wired to interrupts on the various processors/co-processors
>> in the SoC.
>>
>
> It's exactly same even on ARM MHU controller.
>
This has been a big problem in our communication. You start with
"exactly same..." and go on telling the difference.
And that difference is important.

In MHU the 32bits are tied together and all go to one target
processor. Whereas on QCom, each bit corresponds to independent signal
going to a different target processor.

IOW, QCom has 32 channels per register whereas MHU has one. The
current drivers reflect that reality and hence I am against any change
in MHU driver.  Not to mean even changing the MHU driver will fix the
core issue - which is https://lkml.org/lkml/2017/7/7/465 and this
patchset tries to address that.
--
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] 208+ messages in thread

* [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-13 14:12                   ` Jassi Brar
  0 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-13 14:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 13, 2017 at 7:12 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
> Hi Bjorn,
>
> Thanks for taking a look at this. Much appreciated.
>
> On 12/10/17 22:03, Bjorn Andersson wrote:
>> On Fri, Oct 6, 2017 at 6:51 AM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>>
>>>
>>> On 06/10/17 14:47, Jassi Brar wrote:
>>>> On Fri, Oct 6, 2017 at 7:02 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> [..]
>>>>> Again that's not the point, doorbell is more common feature and that can
>>>>> be supported. As SCMI expects doorbell feature in the specification, it
>>>>> just need to support that class of controllers.
>>>>>
>>>> NO.  All SCMI expects is SHMEM and a signal reaching the other end.
>>>> The signal mechanism need not necessarily be "doorbell".
>>>>
>>>
>>> Agreed, but creating an abstraction ro do something as generic as
>>> doorbell and writing shim layer for each controller to use SCMI also
>>> sounds bad.
>>>
>>
>> In the Qualcomm platform we have a single register that exposes 32
>> doorbells, wired to interrupts on the various processors/co-processors
>> in the SoC.
>>
>
> It's exactly same even on ARM MHU controller.
>
This has been a big problem in our communication. You start with
"exactly same..." and go on telling the difference.
And that difference is important.

In MHU the 32bits are tied together and all go to one target
processor. Whereas on QCom, each bit corresponds to independent signal
going to a different target processor.

IOW, QCom has 32 channels per register whereas MHU has one. The
current drivers reflect that reality and hence I am against any change
in MHU driver.  Not to mean even changing the MHU driver will fix the
core issue - which is https://lkml.org/lkml/2017/7/7/465 and this
patchset tries to address that.

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

* Re: [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
  2017-10-13 14:12                   ` Jassi Brar
@ 2017-10-13 14:47                     ` Sudeep Holla
  -1 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-13 14:47 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Sudeep Holla, Bjorn Andersson, Arnd Bergmann, ALKML, LKML, DTML,
	Roy Franz, Harb Abdulhamid, Nishanth Menon, Loc Ho,
	Alexey Klimov, Ryan Harkin



On 13/10/17 15:12, Jassi Brar wrote:
> On Fri, Oct 13, 2017 at 7:12 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>
>> Hi Bjorn,
>>
>> Thanks for taking a look at this. Much appreciated.
>>
>> On 12/10/17 22:03, Bjorn Andersson wrote:
>>> On Fri, Oct 6, 2017 at 6:51 AM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>>>
>>>>
>>>> On 06/10/17 14:47, Jassi Brar wrote:
>>>>> On Fri, Oct 6, 2017 at 7:02 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>> [..]
>>>>>> Again that's not the point, doorbell is more common feature and that can
>>>>>> be supported. As SCMI expects doorbell feature in the specification, it
>>>>>> just need to support that class of controllers.
>>>>>>
>>>>> NO.  All SCMI expects is SHMEM and a signal reaching the other end.
>>>>> The signal mechanism need not necessarily be "doorbell".
>>>>>
>>>>
>>>> Agreed, but creating an abstraction ro do something as generic as
>>>> doorbell and writing shim layer for each controller to use SCMI also
>>>> sounds bad.
>>>>
>>>
>>> In the Qualcomm platform we have a single register that exposes 32
>>> doorbells, wired to interrupts on the various processors/co-processors
>>> in the SoC.
>>>
>>
>> It's exactly same even on ARM MHU controller.
>>
> This has been a big problem in our communication. You start with
> "exactly same..." and go on telling the difference.
> And that difference is important.
> 

Sure and sorry for that.

> In MHU the 32bits are tied together and all go to one target
> processor. Whereas on QCom, each bit corresponds to independent signal
> going to a different target processor.
> 

I was not aware of that. Thanks for clarifying the differences.

> IOW, QCom has 32 channels per register whereas MHU has one. The

OK, that depends on how we consider it. As you said yes it just goes to
single target processor, but hardware designers consider it still 32
channels are they can be controller independently without any locking.

> current drivers reflect that reality and hence I am against any change
> in MHU driver.  Not to mean even changing the MHU driver will fix the
> core issue - which is https://lkml.org/lkml/2017/7/7/465 and this
> patchset tries to address that.
> 

Sure, that's the reason I have this abstraction now.

-- 
Regards,
Sudeep

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

* [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-13 14:47                     ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-10-13 14:47 UTC (permalink / raw)
  To: linux-arm-kernel



On 13/10/17 15:12, Jassi Brar wrote:
> On Fri, Oct 13, 2017 at 7:12 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>
>> Hi Bjorn,
>>
>> Thanks for taking a look at this. Much appreciated.
>>
>> On 12/10/17 22:03, Bjorn Andersson wrote:
>>> On Fri, Oct 6, 2017 at 6:51 AM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>>>
>>>>
>>>> On 06/10/17 14:47, Jassi Brar wrote:
>>>>> On Fri, Oct 6, 2017 at 7:02 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>> [..]
>>>>>> Again that's not the point, doorbell is more common feature and that can
>>>>>> be supported. As SCMI expects doorbell feature in the specification, it
>>>>>> just need to support that class of controllers.
>>>>>>
>>>>> NO.  All SCMI expects is SHMEM and a signal reaching the other end.
>>>>> The signal mechanism need not necessarily be "doorbell".
>>>>>
>>>>
>>>> Agreed, but creating an abstraction ro do something as generic as
>>>> doorbell and writing shim layer for each controller to use SCMI also
>>>> sounds bad.
>>>>
>>>
>>> In the Qualcomm platform we have a single register that exposes 32
>>> doorbells, wired to interrupts on the various processors/co-processors
>>> in the SoC.
>>>
>>
>> It's exactly same even on ARM MHU controller.
>>
> This has been a big problem in our communication. You start with
> "exactly same..." and go on telling the difference.
> And that difference is important.
> 

Sure and sorry for that.

> In MHU the 32bits are tied together and all go to one target
> processor. Whereas on QCom, each bit corresponds to independent signal
> going to a different target processor.
> 

I was not aware of that. Thanks for clarifying the differences.

> IOW, QCom has 32 channels per register whereas MHU has one. The

OK, that depends on how we consider it. As you said yes it just goes to
single target processor, but hardware designers consider it still 32
channels are they can be controller independently without any locking.

> current drivers reflect that reality and hence I am against any change
> in MHU driver.  Not to mean even changing the MHU driver will fix the
> core issue - which is https://lkml.org/lkml/2017/7/7/465 and this
> patchset tries to address that.
> 

Sure, that's the reason I have this abstraction now.

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-13 15:19                       ` Jassi Brar
  0 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-13 15:19 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Bjorn Andersson, Arnd Bergmann, ALKML, LKML, DTML, Roy Franz,
	Harb Abdulhamid, Nishanth Menon, Loc Ho, Alexey Klimov,
	Ryan Harkin

On Fri, Oct 13, 2017 at 8:17 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> On 13/10/17 15:12, Jassi Brar wrote:
>
>> In MHU the 32bits are tied together and all go to one target
>> processor. Whereas on QCom, each bit corresponds to independent signal
>> going to a different target processor.
>>
>
> I was not aware of that. Thanks for clarifying the differences.
>
>> IOW, QCom has 32 channels per register whereas MHU has one. The
>
> OK, that depends on how we consider it. As you said yes it just goes to
> single target processor, but hardware designers consider it still 32
> channels are they can be controller independently without any locking.
>
MHU spec says it has three channels.
Locking is not a criterion for a channel. A signal and associated data
transfer defines a channel.

cheers

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

* Re: [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-13 15:19                       ` Jassi Brar
  0 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-13 15:19 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Bjorn Andersson, Arnd Bergmann, ALKML, LKML, DTML, Roy Franz,
	Harb Abdulhamid, Nishanth Menon, Loc Ho, Alexey Klimov,
	Ryan Harkin

On Fri, Oct 13, 2017 at 8:17 PM, Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org> wrote:
> On 13/10/17 15:12, Jassi Brar wrote:
>
>> In MHU the 32bits are tied together and all go to one target
>> processor. Whereas on QCom, each bit corresponds to independent signal
>> going to a different target processor.
>>
>
> I was not aware of that. Thanks for clarifying the differences.
>
>> IOW, QCom has 32 channels per register whereas MHU has one. The
>
> OK, that depends on how we consider it. As you said yes it just goes to
> single target processor, but hardware designers consider it still 32
> channels are they can be controller independently without any locking.
>
MHU spec says it has three channels.
Locking is not a criterion for a channel. A signal and associated data
transfer defines a channel.

cheers
--
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] 208+ messages in thread

* [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific mailbox interface
@ 2017-10-13 15:19                       ` Jassi Brar
  0 siblings, 0 replies; 208+ messages in thread
From: Jassi Brar @ 2017-10-13 15:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 13, 2017 at 8:17 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> On 13/10/17 15:12, Jassi Brar wrote:
>
>> In MHU the 32bits are tied together and all go to one target
>> processor. Whereas on QCom, each bit corresponds to independent signal
>> going to a different target processor.
>>
>
> I was not aware of that. Thanks for clarifying the differences.
>
>> IOW, QCom has 32 channels per register whereas MHU has one. The
>
> OK, that depends on how we consider it. As you said yes it just goes to
> single target processor, but hardware designers consider it still 32
> channels are they can be controller independently without any locking.
>
MHU spec says it has three channels.
Locking is not a criterion for a channel. A signal and associated data
transfer defines a channel.

cheers

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

* Re: [PATCH v3 18/22] clk: add support for clocks provided by SCMI
@ 2017-11-02  7:23     ` Stephen Boyd
  0 siblings, 0 replies; 208+ messages in thread
From: Stephen Boyd @ 2017-11-02  7:23 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Michael Turquette, linux-clk

On 09/28, Sudeep Holla wrote:
> On some ARM based systems, a separate Cortex-M based System Control
> Processor(SCP) provides the overall power, clock, reset and system
> control. System Control and Management Interface(SCMI) Message Protocol
> is defined for the communication between the Application Cores(AP)
> and the SCP.
> 
> This patch adds support for the clocks provided by SCP using SCMI
> protocol.
> 
> Cc: Michael Turquette <mturquette@baylibre.com>
> Cc: Stephen Boyd <sboyd@codeaurora.org>
> Cc: linux-clk@vger.kernel.org
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> ---

Acked-by: Stephen Boyd <sboyd@codeaurora.org>

>  MAINTAINERS            |   2 +-
>  drivers/clk/Kconfig    |  10 +++
>  drivers/clk/Makefile   |   1 +
>  drivers/clk/clk-scmi.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 222 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/clk/clk-scmi.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 23ec3471f542..32c184391aee 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -12941,7 +12941,7 @@ M:	Sudeep Holla <sudeep.holla@arm.com>
>  L:	linux-arm-kernel@lists.infradead.org
>  S:	Maintained
>  F:	Documentation/devicetree/bindings/arm/arm,sc[mp]i.txt
> -F:	drivers/clk/clk-scpi.c
> +F:	drivers/clk/clk-sc[mp]i.c

Is there a lot of copy/paste going on from clk-scpi.c? Maybe it
could be consolidated?

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH v3 18/22] clk: add support for clocks provided by SCMI
@ 2017-11-02  7:23     ` Stephen Boyd
  0 siblings, 0 replies; 208+ messages in thread
From: Stephen Boyd @ 2017-11-02  7:23 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Michael Turquette, linux-clk-u79uwXL29TY76Z2rM5mHXA

On 09/28, Sudeep Holla wrote:
> On some ARM based systems, a separate Cortex-M based System Control
> Processor(SCP) provides the overall power, clock, reset and system
> control. System Control and Management Interface(SCMI) Message Protocol
> is defined for the communication between the Application Cores(AP)
> and the SCP.
> 
> This patch adds support for the clocks provided by SCP using SCMI
> protocol.
> 
> Cc: Michael Turquette <mturquette-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
> Cc: Stephen Boyd <sboyd-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Signed-off-by: Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org>
> ---

Acked-by: Stephen Boyd <sboyd-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

>  MAINTAINERS            |   2 +-
>  drivers/clk/Kconfig    |  10 +++
>  drivers/clk/Makefile   |   1 +
>  drivers/clk/clk-scmi.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 222 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/clk/clk-scmi.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 23ec3471f542..32c184391aee 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -12941,7 +12941,7 @@ M:	Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org>
>  L:	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
>  S:	Maintained
>  F:	Documentation/devicetree/bindings/arm/arm,sc[mp]i.txt
> -F:	drivers/clk/clk-scpi.c
> +F:	drivers/clk/clk-sc[mp]i.c

Is there a lot of copy/paste going on from clk-scpi.c? Maybe it
could be consolidated?

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
--
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] 208+ messages in thread

* [PATCH v3 18/22] clk: add support for clocks provided by SCMI
@ 2017-11-02  7:23     ` Stephen Boyd
  0 siblings, 0 replies; 208+ messages in thread
From: Stephen Boyd @ 2017-11-02  7:23 UTC (permalink / raw)
  To: linux-arm-kernel

On 09/28, Sudeep Holla wrote:
> On some ARM based systems, a separate Cortex-M based System Control
> Processor(SCP) provides the overall power, clock, reset and system
> control. System Control and Management Interface(SCMI) Message Protocol
> is defined for the communication between the Application Cores(AP)
> and the SCP.
> 
> This patch adds support for the clocks provided by SCP using SCMI
> protocol.
> 
> Cc: Michael Turquette <mturquette@baylibre.com>
> Cc: Stephen Boyd <sboyd@codeaurora.org>
> Cc: linux-clk at vger.kernel.org
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> ---

Acked-by: Stephen Boyd <sboyd@codeaurora.org>

>  MAINTAINERS            |   2 +-
>  drivers/clk/Kconfig    |  10 +++
>  drivers/clk/Makefile   |   1 +
>  drivers/clk/clk-scmi.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 222 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/clk/clk-scmi.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 23ec3471f542..32c184391aee 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -12941,7 +12941,7 @@ M:	Sudeep Holla <sudeep.holla@arm.com>
>  L:	linux-arm-kernel at lists.infradead.org
>  S:	Maintained
>  F:	Documentation/devicetree/bindings/arm/arm,sc[mp]i.txt
> -F:	drivers/clk/clk-scpi.c
> +F:	drivers/clk/clk-sc[mp]i.c

Is there a lot of copy/paste going on from clk-scpi.c? Maybe it
could be consolidated?

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH v3 18/22] clk: add support for clocks provided by SCMI
@ 2017-11-02 10:04       ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-11-02 10:04 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Arnd Bergmann, Loc Ho, Alexey Klimov,
	Ryan Harkin, Jassi Brar, Michael Turquette, linux-clk



On 02/11/17 07:23, Stephen Boyd wrote:
> On 09/28, Sudeep Holla wrote:
>> On some ARM based systems, a separate Cortex-M based System Control
>> Processor(SCP) provides the overall power, clock, reset and system
>> control. System Control and Management Interface(SCMI) Message Protocol
>> is defined for the communication between the Application Cores(AP)
>> and the SCP.
>>
>> This patch adds support for the clocks provided by SCP using SCMI
>> protocol.
>>
>> Cc: Michael Turquette <mturquette@baylibre.com>
>> Cc: Stephen Boyd <sboyd@codeaurora.org>
>> Cc: linux-clk@vger.kernel.org
>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>> ---
> 
> Acked-by: Stephen Boyd <sboyd@codeaurora.org>
> 

Thanks

>>  MAINTAINERS            |   2 +-
>>  drivers/clk/Kconfig    |  10 +++
>>  drivers/clk/Makefile   |   1 +
>>  drivers/clk/clk-scmi.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++
>>  4 files changed, 222 insertions(+), 1 deletion(-)
>>  create mode 100644 drivers/clk/clk-scmi.c
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 23ec3471f542..32c184391aee 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -12941,7 +12941,7 @@ M:	Sudeep Holla <sudeep.holla@arm.com>
>>  L:	linux-arm-kernel@lists.infradead.org
>>  S:	Maintained
>>  F:	Documentation/devicetree/bindings/arm/arm,sc[mp]i.txt
>> -F:	drivers/clk/clk-scpi.c
>> +F:	drivers/clk/clk-sc[mp]i.c
> 
> Is there a lot of copy/paste going on from clk-scpi.c? Maybe it
> could be consolidated?
> 

Not much apart from the usual driver skeleton. Also SCPI specification
will not be enhanced any further while SCMI will be. So they will
deviated in the feature set going further. Even I was thinking of
merging then together initially but based on some WIP changes to the
specification, I thought it may not be good idea. But if we think it can
be merged in future , I will do that for sure(for easy maintenance)

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 18/22] clk: add support for clocks provided by SCMI
@ 2017-11-02 10:04       ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-11-02 10:04 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Sudeep Holla, ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid,
	Nishanth Menon, Arnd Bergmann, Loc Ho, Alexey Klimov,
	Ryan Harkin, Jassi Brar, Michael Turquette,
	linux-clk-u79uwXL29TY76Z2rM5mHXA



On 02/11/17 07:23, Stephen Boyd wrote:
> On 09/28, Sudeep Holla wrote:
>> On some ARM based systems, a separate Cortex-M based System Control
>> Processor(SCP) provides the overall power, clock, reset and system
>> control. System Control and Management Interface(SCMI) Message Protocol
>> is defined for the communication between the Application Cores(AP)
>> and the SCP.
>>
>> This patch adds support for the clocks provided by SCP using SCMI
>> protocol.
>>
>> Cc: Michael Turquette <mturquette-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
>> Cc: Stephen Boyd <sboyd-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
>> Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>> Signed-off-by: Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org>
>> ---
> 
> Acked-by: Stephen Boyd <sboyd-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> 

Thanks

>>  MAINTAINERS            |   2 +-
>>  drivers/clk/Kconfig    |  10 +++
>>  drivers/clk/Makefile   |   1 +
>>  drivers/clk/clk-scmi.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++
>>  4 files changed, 222 insertions(+), 1 deletion(-)
>>  create mode 100644 drivers/clk/clk-scmi.c
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 23ec3471f542..32c184391aee 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -12941,7 +12941,7 @@ M:	Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org>
>>  L:	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
>>  S:	Maintained
>>  F:	Documentation/devicetree/bindings/arm/arm,sc[mp]i.txt
>> -F:	drivers/clk/clk-scpi.c
>> +F:	drivers/clk/clk-sc[mp]i.c
> 
> Is there a lot of copy/paste going on from clk-scpi.c? Maybe it
> could be consolidated?
> 

Not much apart from the usual driver skeleton. Also SCPI specification
will not be enhanced any further while SCMI will be. So they will
deviated in the feature set going further. Even I was thinking of
merging then together initially but based on some WIP changes to the
specification, I thought it may not be good idea. But if we think it can
be merged in future , I will do that for sure(for easy maintenance)

-- 
Regards,
Sudeep
--
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] 208+ messages in thread

* [PATCH v3 18/22] clk: add support for clocks provided by SCMI
@ 2017-11-02 10:04       ` Sudeep Holla
  0 siblings, 0 replies; 208+ messages in thread
From: Sudeep Holla @ 2017-11-02 10:04 UTC (permalink / raw)
  To: linux-arm-kernel



On 02/11/17 07:23, Stephen Boyd wrote:
> On 09/28, Sudeep Holla wrote:
>> On some ARM based systems, a separate Cortex-M based System Control
>> Processor(SCP) provides the overall power, clock, reset and system
>> control. System Control and Management Interface(SCMI) Message Protocol
>> is defined for the communication between the Application Cores(AP)
>> and the SCP.
>>
>> This patch adds support for the clocks provided by SCP using SCMI
>> protocol.
>>
>> Cc: Michael Turquette <mturquette@baylibre.com>
>> Cc: Stephen Boyd <sboyd@codeaurora.org>
>> Cc: linux-clk at vger.kernel.org
>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>> ---
> 
> Acked-by: Stephen Boyd <sboyd@codeaurora.org>
> 

Thanks

>>  MAINTAINERS            |   2 +-
>>  drivers/clk/Kconfig    |  10 +++
>>  drivers/clk/Makefile   |   1 +
>>  drivers/clk/clk-scmi.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++
>>  4 files changed, 222 insertions(+), 1 deletion(-)
>>  create mode 100644 drivers/clk/clk-scmi.c
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 23ec3471f542..32c184391aee 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -12941,7 +12941,7 @@ M:	Sudeep Holla <sudeep.holla@arm.com>
>>  L:	linux-arm-kernel at lists.infradead.org
>>  S:	Maintained
>>  F:	Documentation/devicetree/bindings/arm/arm,sc[mp]i.txt
>> -F:	drivers/clk/clk-scpi.c
>> +F:	drivers/clk/clk-sc[mp]i.c
> 
> Is there a lot of copy/paste going on from clk-scpi.c? Maybe it
> could be consolidated?
> 

Not much apart from the usual driver skeleton. Also SCPI specification
will not be enhanced any further while SCMI will be. So they will
deviated in the feature set going further. Even I was thinking of
merging then together initially but based on some WIP changes to the
specification, I thought it may not be good idea. But if we think it can
be merged in future , I will do that for sure(for easy maintenance)

-- 
Regards,
Sudeep

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

* Re: [PATCH v3 18/22] clk: add support for clocks provided by SCMI
@ 2017-11-03 15:12         ` Stephen Boyd
  0 siblings, 0 replies; 208+ messages in thread
From: Stephen Boyd @ 2017-11-03 15:12 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Michael Turquette, linux-clk

On 11/02, Sudeep Holla wrote:
> 
> 
> On 02/11/17 07:23, Stephen Boyd wrote:
> > Is there a lot of copy/paste going on from clk-scpi.c? Maybe it
> > could be consolidated?
> > 
> 
> Not much apart from the usual driver skeleton. Also SCPI specification
> will not be enhanced any further while SCMI will be. So they will
> deviated in the feature set going further. Even I was thinking of
> merging then together initially but based on some WIP changes to the
> specification, I thought it may not be good idea. But if we think it can
> be merged in future , I will do that for sure(for easy maintenance)
> 

Ok, no worries from me. Thanks for taking another look.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH v3 18/22] clk: add support for clocks provided by SCMI
@ 2017-11-03 15:12         ` Stephen Boyd
  0 siblings, 0 replies; 208+ messages in thread
From: Stephen Boyd @ 2017-11-03 15:12 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: ALKML, LKML, DTML, Roy Franz, Harb Abdulhamid, Nishanth Menon,
	Arnd Bergmann, Loc Ho, Alexey Klimov, Ryan Harkin, Jassi Brar,
	Michael Turquette, linux-clk-u79uwXL29TY76Z2rM5mHXA

On 11/02, Sudeep Holla wrote:
> 
> 
> On 02/11/17 07:23, Stephen Boyd wrote:
> > Is there a lot of copy/paste going on from clk-scpi.c? Maybe it
> > could be consolidated?
> > 
> 
> Not much apart from the usual driver skeleton. Also SCPI specification
> will not be enhanced any further while SCMI will be. So they will
> deviated in the feature set going further. Even I was thinking of
> merging then together initially but based on some WIP changes to the
> specification, I thought it may not be good idea. But if we think it can
> be merged in future , I will do that for sure(for easy maintenance)
> 

Ok, no worries from me. Thanks for taking another look.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
--
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] 208+ messages in thread

* [PATCH v3 18/22] clk: add support for clocks provided by SCMI
@ 2017-11-03 15:12         ` Stephen Boyd
  0 siblings, 0 replies; 208+ messages in thread
From: Stephen Boyd @ 2017-11-03 15:12 UTC (permalink / raw)
  To: linux-arm-kernel

On 11/02, Sudeep Holla wrote:
> 
> 
> On 02/11/17 07:23, Stephen Boyd wrote:
> > Is there a lot of copy/paste going on from clk-scpi.c? Maybe it
> > could be consolidated?
> > 
> 
> Not much apart from the usual driver skeleton. Also SCPI specification
> will not be enhanced any further while SCMI will be. So they will
> deviated in the feature set going further. Even I was thinking of
> merging then together initially but based on some WIP changes to the
> specification, I thought it may not be good idea. But if we think it can
> be merged in future , I will do that for sure(for easy maintenance)
> 

Ok, no worries from me. Thanks for taking another look.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

end of thread, other threads:[~2017-11-03 15:12 UTC | newest]

Thread overview: 208+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-28 13:11 [PATCH v3 00/22] firmware: ARM System Control and Management Interface(SCMI) support Sudeep Holla
2017-09-28 13:11 ` Sudeep Holla
2017-09-28 13:11 ` Sudeep Holla
2017-09-28 13:11 ` [PATCH v3 01/22] dt-bindings: mailbox: add support for mailbox client shared memory Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla
2017-09-28 13:11 ` [PATCH v3 02/22] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla
2017-10-04 10:50   ` Arnd Bergmann
2017-10-04 10:50     ` Arnd Bergmann
2017-10-04 10:50     ` Arnd Bergmann
2017-10-04 11:07     ` Sudeep Holla
2017-10-04 11:07       ` Sudeep Holla
2017-10-04 11:07       ` Sudeep Holla
2017-10-04 12:35       ` Arnd Bergmann
2017-10-04 12:35         ` Arnd Bergmann
2017-10-04 12:35         ` Arnd Bergmann
2017-10-04 13:53         ` Sudeep Holla
2017-10-04 13:53           ` Sudeep Holla
2017-10-04 13:53           ` Sudeep Holla
2017-10-04 14:17           ` Arnd Bergmann
2017-10-04 14:17             ` Arnd Bergmann
2017-10-04 14:17             ` Arnd Bergmann
2017-10-04 14:47             ` Sudeep Holla
2017-10-04 14:47               ` Sudeep Holla
2017-10-04 14:47               ` Sudeep Holla
2017-10-05 11:56               ` Arnd Bergmann
2017-10-05 11:56                 ` Arnd Bergmann
2017-10-05 11:56                 ` Arnd Bergmann
2017-10-05 12:56                 ` Sudeep Holla
2017-10-05 12:56                   ` Sudeep Holla
2017-10-05 13:20         ` Jassi Brar
2017-10-05 13:20           ` Jassi Brar
2017-10-05 14:10           ` Sudeep Holla
2017-10-05 14:10             ` Sudeep Holla
2017-09-28 13:11 ` [PATCH v3 03/22] dt-bindings: arm: scmi: add ARM MHU specific mailbox client bindings Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla
2017-10-05 23:20   ` Rob Herring
2017-10-05 23:20     ` Rob Herring
2017-10-05 23:20     ` Rob Herring
2017-10-06  9:42     ` Sudeep Holla
2017-10-06  9:42       ` Sudeep Holla
2017-10-06 11:01     ` Jassi Brar
2017-10-06 11:01       ` Jassi Brar
2017-10-06 11:01       ` Jassi Brar
2017-10-06 15:54       ` Rob Herring
2017-10-06 15:54         ` Rob Herring
2017-10-07  2:26         ` Jassi Brar
2017-10-07  2:26           ` Jassi Brar
2017-10-09 13:52           ` Rob Herring
2017-10-09 13:52             ` Rob Herring
2017-10-09 14:37             ` Sudeep Holla
2017-10-09 14:37               ` Sudeep Holla
2017-10-09 14:37               ` Sudeep Holla
2017-10-09 14:46             ` Jassi Brar
2017-10-09 14:46               ` Jassi Brar
2017-10-09 14:46               ` Jassi Brar
2017-10-09 22:57               ` Rob Herring
2017-10-09 22:57                 ` Rob Herring
2017-10-09 22:57                 ` Rob Herring
2017-10-10  1:52                 ` Jassi Brar
2017-10-10  1:52                   ` Jassi Brar
2017-10-10 11:04                 ` Sudeep Holla
2017-10-10 11:04                   ` Sudeep Holla
2017-10-10 11:04                   ` Sudeep Holla
2017-09-28 13:11 ` [PATCH v3 04/22] firmware: arm_scmi: add basic driver infrastructure for SCMI Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla
2017-10-04 10:59   ` Arnd Bergmann
2017-10-04 10:59     ` Arnd Bergmann
2017-10-04 10:59     ` Arnd Bergmann
2017-10-04 17:37     ` Sudeep Holla
2017-10-04 17:37       ` Sudeep Holla
2017-10-04 17:37       ` Sudeep Holla
2017-10-04 11:19   ` Arnd Bergmann
2017-10-04 11:19     ` Arnd Bergmann
2017-10-04 11:19     ` Arnd Bergmann
2017-09-28 13:11 ` [PATCH v3 05/22] firmware: arm_scmi: add common infrastructure and support for base protocol Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla
2017-09-28 13:11 ` [PATCH v3 06/22] firmware: arm_scmi: add initial support for performance protocol Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla
2017-09-28 13:11 ` [PATCH v3 07/22] firmware: arm_scmi: add initial support for clock protocol Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla
2017-09-28 13:11 ` [PATCH v3 08/22] firmware: arm_scmi: add initial support for power protocol Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla
2017-09-28 13:11 ` [PATCH v3 09/22] firmware: arm_scmi: add initial support for sensor protocol Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla
2017-09-28 13:11 ` [PATCH v3 10/22] firmware: arm_scmi: probe and initialise all the supported protocols Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla
2017-10-04 11:06   ` Arnd Bergmann
2017-10-04 11:06     ` Arnd Bergmann
2017-10-04 11:06     ` Arnd Bergmann
2017-09-28 13:11 ` [PATCH v3 11/22] firmware: arm_scmi: add support for polling based SCMI transfers Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla
2017-10-04 11:13   ` Arnd Bergmann
2017-10-04 11:13     ` Arnd Bergmann
2017-10-04 11:13     ` Arnd Bergmann
2017-10-04 11:18     ` Sudeep Holla
2017-10-04 11:18       ` Sudeep Holla
2017-09-28 13:11 ` [PATCH v3 12/22] firmware: arm_scmi: add option for polling based performance domain operations Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla
2017-09-28 13:11 ` [PATCH v3 13/22] firmware: arm_scmi: refactor in preparation to support per-protocol channels Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla
2017-09-28 13:11 ` [PATCH v3 14/22] firmware: arm_scmi: add per-protocol channels support using idr objects Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla
2017-09-28 13:11 ` [PATCH v3 15/22] firmware: arm_scmi: abstract mailbox interface Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla
2017-10-04 11:24   ` Arnd Bergmann
2017-10-04 11:24     ` Arnd Bergmann
2017-10-04 11:24     ` Arnd Bergmann
2017-10-04 11:32     ` Sudeep Holla
2017-10-04 11:32       ` Sudeep Holla
2017-10-04 11:32       ` Sudeep Holla
2017-10-06 11:34       ` Jassi Brar
2017-10-06 11:34         ` Jassi Brar
2017-10-06 11:34         ` Jassi Brar
2017-10-06 13:27         ` Sudeep Holla
2017-10-06 13:27           ` Sudeep Holla
2017-10-06 13:27           ` Sudeep Holla
2017-10-06 13:34           ` Jassi Brar
2017-10-06 13:34             ` Jassi Brar
2017-10-06 13:41             ` Sudeep Holla
2017-10-06 13:41               ` Sudeep Holla
2017-10-12 21:20       ` Bjorn Andersson
2017-10-12 21:20         ` Bjorn Andersson
2017-09-28 13:11 ` [PATCH v3 16/22] firmware: arm_scmi: add arm_mhu specific " Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla
2017-10-04 11:36   ` Arnd Bergmann
2017-10-04 11:36     ` Arnd Bergmann
2017-10-04 11:48     ` Sudeep Holla
2017-10-04 11:48       ` Sudeep Holla
2017-10-04 11:48       ` Sudeep Holla
2017-10-06 11:26     ` Jassi Brar
2017-10-06 11:26       ` Jassi Brar
2017-10-06 11:26       ` Jassi Brar
2017-10-06 13:32       ` Sudeep Holla
2017-10-06 13:32         ` Sudeep Holla
2017-10-06 13:47         ` Jassi Brar
2017-10-06 13:47           ` Jassi Brar
2017-10-06 13:47           ` Jassi Brar
2017-10-06 13:51           ` Sudeep Holla
2017-10-06 13:51             ` Sudeep Holla
2017-10-06 13:51             ` Sudeep Holla
2017-10-12 21:03             ` Bjorn Andersson
2017-10-12 21:03               ` Bjorn Andersson
2017-10-13 13:42               ` Sudeep Holla
2017-10-13 13:42                 ` Sudeep Holla
2017-10-13 13:42                 ` Sudeep Holla
2017-10-13 14:12                 ` Jassi Brar
2017-10-13 14:12                   ` Jassi Brar
2017-10-13 14:12                   ` Jassi Brar
2017-10-13 14:47                   ` Sudeep Holla
2017-10-13 14:47                     ` Sudeep Holla
2017-10-13 15:19                     ` Jassi Brar
2017-10-13 15:19                       ` Jassi Brar
2017-10-13 15:19                       ` Jassi Brar
2017-09-28 13:11 ` [PATCH v3 17/22] firmware: arm_scmi: add device power domain support using genpd Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla
2017-09-28 21:18   ` Ulf Hansson
2017-09-28 21:18     ` Ulf Hansson
2017-09-29 13:40     ` Sudeep Holla
2017-09-29 13:40       ` Sudeep Holla
2017-09-29 13:40       ` Sudeep Holla
2017-09-29 13:42   ` [PATCH v3 17/22][UPDATE] firmware: arm_scmi: add device power domain support genpd Sudeep Holla
2017-09-29 13:42     ` Sudeep Holla
2017-09-29 13:42     ` Sudeep Holla
2017-10-10 11:05     ` Ulf Hansson
2017-10-10 11:05       ` Ulf Hansson
2017-10-10 13:02       ` Sudeep Holla
2017-10-10 13:02         ` Sudeep Holla
2017-10-10 13:02         ` Sudeep Holla
2017-09-28 13:11 ` [PATCH v3 18/22] clk: add support for clocks provided by SCMI Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla
2017-11-02  7:23   ` Stephen Boyd
2017-11-02  7:23     ` Stephen Boyd
2017-11-02  7:23     ` Stephen Boyd
2017-11-02 10:04     ` Sudeep Holla
2017-11-02 10:04       ` Sudeep Holla
2017-11-02 10:04       ` Sudeep Holla
2017-11-03 15:12       ` Stephen Boyd
2017-11-03 15:12         ` Stephen Boyd
2017-11-03 15:12         ` Stephen Boyd
2017-09-28 13:11 ` [PATCH v3 19/22] hwmon: (core) Add hwmon_max to hwmon_sensor_types enumeration Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla
2017-10-01 14:21   ` [v3, " Guenter Roeck
2017-10-01 14:21     ` Guenter Roeck
2017-09-28 13:11 ` [PATCH v3 20/22] hwmon: add support for sensors exported via ARM SCMI Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla
2017-10-01 14:26   ` [v3,20/22] " Guenter Roeck
2017-10-01 14:26     ` Guenter Roeck
2017-10-02  9:25     ` Sudeep Holla
2017-10-02  9:25       ` Sudeep Holla
2017-09-28 13:11 ` [PATCH v3 21/22] cpufreq: add support for CPU DVFS based on SCMI message protocol Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla
2017-10-04 11:30   ` Arnd Bergmann
2017-10-04 11:30     ` Arnd Bergmann
2017-10-04 11:30     ` Arnd Bergmann
2017-10-04 15:01     ` Sudeep Holla
2017-10-04 15:01       ` Sudeep Holla
2017-10-05 11:20       ` Arnd Bergmann
2017-10-05 11:20         ` Arnd Bergmann
2017-10-05 11:20         ` Arnd Bergmann
2017-10-05 11:26         ` Sudeep Holla
2017-10-05 11:26           ` Sudeep Holla
2017-10-05 11:26           ` Sudeep Holla
2017-09-28 13:11 ` [PATCH v3 22/22] cpufreq: scmi: add support for fast frequency switching Sudeep Holla
2017-09-28 13:11   ` Sudeep Holla

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.