From: Nick Hawkins <[email protected]>
The GXP SoC can support up to 16 fans through the interface provided by
the CPLD. The fans speeds are controlled via a pwm value 0-255. The fans
are also capable of reporting if they have failed to the CPLD which in
turn reports the status to the GXP SoC. Based on previous feedback the
registers required for fan control have been regmaped individualy to fan
driver. Specifically these registers are the function 2 registers and the
programmable logic registers from the CPLD. Additionally in this patchset
there is support for the SPI driver which already exists as spi-gxp.c in
the SPI driver.
---
Changes since v3:
*Removed patch for ABI documentation of sysfs-class-hwmon as it
was applied
*Removed unecessary HWMON_PWM_ENABLE usage
Changes since v2:
*Removed use of regmap in favor of __iomem
*Updated description on yaml documentation
*Simplified commit description on sysfs-class-hwmon
*Removed use of dev and hwmon_dev from drvdata structure
*Fixed missing breaks in switch statements
*Added check for pwm values less than 0
*Removed regmap and slab header file includes
Changes since v1:
*Renamed fn2reg to fn2 in dtsi file and documentation
*Renamed plreg to pl in dtsi file and documentation
*Renamed fanctrl to fan-controller in dtsi file and documentation
*Adjusted base register range for fan ctrl in dtsi
*Changed commit description on fan-ctrl device-tree binding
*Changed register description on fan-ctrl device-tree binding
*Changed number of supported fans from 16 to 8 in driver code and
documentation
*Modified commit description of fan code
*Removed support for fan[0-15]_input
*Removed PWM defines in driver code
*Added gxp-fan-ctrl to hwmon's index.rst
*Removed mutex in driver code
*Added fan_enable support in fan code and documentation
*Fixed comment in driver code presents -> present
*Removed unecessary include files in fan code
*Added comments to describe what power state is and
calculations for accessing plreg in fan code
*Removed use of variable offsets in fan code
*Fixed GPL header in fan code
*Changed module description for fan controller
*Added kfree in case of failure to initialize driver
*Added missing yaml file to MAINTAINERS*** SUBJECT HERE ***
Nick Hawkins (5):
hwmon: (gxp-fan-ctrl) Add GXP fan controller
dt-bindings: hwmon: Add hpe,gxp-fan-ctrl
ARM: dts: add GXP Support for fans and SPI
ARM: multi_v7_defconfig: Add GXP Fan and SPI support
MAINTAINERS: add gxp fan controller and documents
.../bindings/hwmon/hpe,gxp-fan-ctrl.yaml | 45 ++++
Documentation/hwmon/gxp-fan-ctrl.rst | 28 ++
Documentation/hwmon/index.rst | 1 +
MAINTAINERS | 3 +
arch/arm/boot/dts/hpe-bmc-dl360gen10.dts | 58 ++++
arch/arm/boot/dts/hpe-gxp.dtsi | 64 +++--
arch/arm/configs/multi_v7_defconfig | 2 +
drivers/hwmon/Kconfig | 9 +
drivers/hwmon/Makefile | 1 +
drivers/hwmon/gxp-fan-ctrl.c | 254 ++++++++++++++++++
10 files changed, 446 insertions(+), 19 deletions(-)
create mode 100644 Documentation/devicetree/bindings/hwmon/hpe,gxp-fan-ctrl.yaml
create mode 100644 Documentation/hwmon/gxp-fan-ctrl.rst
create mode 100644 drivers/hwmon/gxp-fan-ctrl.c
--
2.17.1
From: Nick Hawkins <[email protected]>
Create documentation for the binding to support control of the fans on
HPE platforms.
Signed-off-by: Nick Hawkins <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
Reviewed-by: Guenter Roeck <[email protected]>
---
v4:
*No change
v3:
*No change
v2:
*Changed plreg to pl
*Changed fn2reg to reg
*Edited descriptions for all registers
*Changed fanctrl to fan-controller
*Changed commit description
---
.../bindings/hwmon/hpe,gxp-fan-ctrl.yaml | 45 +++++++++++++++++++
1 file changed, 45 insertions(+)
create mode 100644 Documentation/devicetree/bindings/hwmon/hpe,gxp-fan-ctrl.yaml
diff --git a/Documentation/devicetree/bindings/hwmon/hpe,gxp-fan-ctrl.yaml b/Documentation/devicetree/bindings/hwmon/hpe,gxp-fan-ctrl.yaml
new file mode 100644
index 000000000000..4a52aac6be72
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/hpe,gxp-fan-ctrl.yaml
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/hwmon/hpe,gxp-fan-ctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: HPE GXP Fan Controller
+
+maintainers:
+ - Nick Hawkins <[email protected]>
+
+description: |
+ The HPE GXP fan controller controls the fans through an external CPLD
+ device that connects to the fans.
+
+properties:
+ compatible:
+ const: hpe,gxp-fan-ctrl
+
+ reg:
+ items:
+ - description: Fan controller PWM
+ - description: Programmable logic
+ - description: Function 2
+
+ reg-names:
+ items:
+ - const: base
+ - const: pl
+ - const: fn2
+
+required:
+ - compatible
+ - reg
+ - reg-names
+
+additionalProperties: false
+
+examples:
+ - |
+ fan-controller@1000c00 {
+ compatible = "hpe,gxp-fan-ctrl";
+ reg = <0x1000c00 0x200>, <0xd1000000 0xff>, <0x80200000 0x100000>;
+ reg-names = "base", "pl", "fn2";
+ };
--
2.17.1
From: Nick Hawkins <[email protected]>
Add the gxp-fan-ctrl.c and gxp-fan-ctrl.rst in hwmon
driver/documentation.
Signed-off-by: Nick Hawkins <[email protected]>
Reviewed-by: Guenter Roek <[email protected]>
---
v4:
*No change
v3:
*No change
v2:
*Added missing gxp-fan-ctrl.yaml
---
MAINTAINERS | 3 +++
1 file changed, 3 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 1daadaa4d48b..00b52be102d6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2216,13 +2216,16 @@ ARM/HPE GXP ARCHITECTURE
M: Jean-Marie Verdun <[email protected]>
M: Nick Hawkins <[email protected]>
S: Maintained
+F: Documentation/hwmon/gxp-fan-ctrl.rst
F: Documentation/devicetree/bindings/arm/hpe,gxp.yaml
+F: Documentation/devicetree/bindings/hwmon/hpe,gxp-fan-ctrl.yaml
F: Documentation/devicetree/bindings/spi/hpe,gxp-spifi.yaml
F: Documentation/devicetree/bindings/timer/hpe,gxp-timer.yaml
F: arch/arm/boot/dts/hpe-bmc*
F: arch/arm/boot/dts/hpe-gxp*
F: arch/arm/mach-hpe/
F: drivers/clocksource/timer-gxp.c
+F: drivers/hwmon/gxp-fan-ctrl.c
F: drivers/spi/spi-gxp.c
F: drivers/watchdog/gxp-wdt.c
--
2.17.1
From: Nick Hawkins <[email protected]>
The GXP SoC can support up to 16 fans through the interface provided by
the CPLD. The current support is limited to 8 fans. The fans speeds are
controlled via 8 different PWMs which can vary in value from 0-255. The
fans are also capable of reporting if they have failed to the CPLD which
in turn reports the status to the GXP SoC.
Signed-off-by: Nick Hawkins <[email protected]>
---
v4:
*Removed unecessary HWMON_PWM_ENABLE
v3:
*Removed use of regmap in favor of __iomem
*Removed use of dev and hwmon_dev from drvdata structure
*Fixed missing breaks in switch statements
*Added check for pwm values less than 0
*Removed regmap and slab header file includes
v2:
*Changed number of supported fans from 16 to 8 in code
*Remove last sentence of commit description
*Removed support for fan[0-15]_input in code and documentation
*Changed documentation to limit fan count to 7
*Changed documentation license
*Removed PWM defines
*Added gxp-fan-ctrl to hwmon's index.rst
*Removed mutex
*Added fan_enable support to report if the fan is enabled
*Changed presents to present
*Removed unnecessary ()
*Add comment for plreg reads and calculations
*Add comment for the use of platform power state in code
*Removed use of variable offsets and went with hardcoding instead
*Rewrote driver to use devm_hwmon_device_register_with_info()
*Remove unused header files
*Fix GPL header
*Changed module description
*Add kfree in case of failure to get regmaps or resource
---
Documentation/hwmon/gxp-fan-ctrl.rst | 28 +++
Documentation/hwmon/index.rst | 1 +
drivers/hwmon/Kconfig | 9 +
drivers/hwmon/Makefile | 1 +
drivers/hwmon/gxp-fan-ctrl.c | 254 +++++++++++++++++++++++++++
5 files changed, 293 insertions(+)
create mode 100644 Documentation/hwmon/gxp-fan-ctrl.rst
create mode 100644 drivers/hwmon/gxp-fan-ctrl.c
diff --git a/Documentation/hwmon/gxp-fan-ctrl.rst b/Documentation/hwmon/gxp-fan-ctrl.rst
new file mode 100644
index 000000000000..ae3397e81c04
--- /dev/null
+++ b/Documentation/hwmon/gxp-fan-ctrl.rst
@@ -0,0 +1,28 @@
+.. SPDX-License-Identifier: GPL-2.0-only
+
+Kernel driver gxp-fan-ctrl
+==========================
+
+Supported chips:
+
+ * HPE GXP SOC
+
+Author: Nick Hawkins <[email protected]>
+
+
+Description
+-----------
+
+gxp-fan-ctrl is a driver which provides fan control for the hpe gxp soc.
+The driver allows the gathering of fan status and the use of fan
+PWM control.
+
+
+Sysfs attributes
+----------------
+
+======================= ===========================================================
+pwm[0-7] Fan 0 to 7 respective PWM value (0-255)
+fan[0-7]_fault Fan 0 to 7 respective fault status: 1 fail, 0 ok
+fan[0-7]_enable Fan 0 to 7 respective enabled status: 1 enabled, 0 disabled
+======================= ===========================================================
diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
index c1d11cf13eef..97819cf5c97f 100644
--- a/Documentation/hwmon/index.rst
+++ b/Documentation/hwmon/index.rst
@@ -73,6 +73,7 @@ Hardware Monitoring Kernel Drivers
g762
gsc-hwmon
gl518sm
+ gxp-fan-ctrl
hih6130
ibmaem
ibm-cffps
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 7ac3daaf59ce..45febd5d5cf7 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -706,6 +706,15 @@ config SENSORS_GPIO_FAN
This driver can also be built as a module. If so, the module
will be called gpio-fan.
+config SENSORS_GXP_FAN_CTRL
+ tristate "HPE GXP fan controller"
+ depends on ARCH_HPE_GXP || COMPILE_TEST
+ help
+ If you say yes here you get support for GXP fan control functionality.
+
+ The GXP controls fan function via the CPLD through the use of PWM
+ registers. This driver reports status and pwm setting of the fans.
+
config SENSORS_HIH6130
tristate "Honeywell Humidicon HIH-6130 humidity/temperature sensor"
depends on I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 11d076cad8a2..b5782dc4dc6e 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -83,6 +83,7 @@ obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o
obj-$(CONFIG_SENSORS_GSC) += gsc-hwmon.o
obj-$(CONFIG_SENSORS_GPIO_FAN) += gpio-fan.o
+obj-$(CONFIG_SENSORS_GXP_FAN_CTRL) += gxp-fan-ctrl.o
obj-$(CONFIG_SENSORS_HIH6130) += hih6130.o
obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o
obj-$(CONFIG_SENSORS_I5500) += i5500_temp.o
diff --git a/drivers/hwmon/gxp-fan-ctrl.c b/drivers/hwmon/gxp-fan-ctrl.c
new file mode 100644
index 000000000000..c7ebd3bbf35b
--- /dev/null
+++ b/drivers/hwmon/gxp-fan-ctrl.c
@@ -0,0 +1,254 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (C) 2022 Hewlett-Packard Enterprise Development Company, L.P. */
+
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#define OFS_FAN_INST 0 /* Is 0 because plreg base will be set at INST */
+#define OFS_FAN_FAIL 2 /* Is 2 bytes after base */
+#define OFS_SEVSTAT 0 /* Is 0 because fn2 base will be set at SEVSTAT */
+#define POWER_BIT 24
+
+struct gxp_fan_ctrl_drvdata {
+ void __iomem *base;
+ void __iomem *plreg;
+ void __iomem *fn2;
+};
+
+static bool fan_installed(struct device *dev, int fan)
+{
+ struct gxp_fan_ctrl_drvdata *drvdata = dev_get_drvdata(dev);
+ u8 val;
+
+ val = readb(drvdata->plreg + OFS_FAN_INST);
+
+ return !!(val & BIT(fan));
+}
+
+static long fan_failed(struct device *dev, int fan)
+{
+ struct gxp_fan_ctrl_drvdata *drvdata = dev_get_drvdata(dev);
+ u8 val;
+
+ val = readb(drvdata->plreg + OFS_FAN_FAIL);
+
+ return !!(val & BIT(fan));
+}
+
+static long fan_enabled(struct device *dev, int fan)
+{
+ struct gxp_fan_ctrl_drvdata *drvdata = dev_get_drvdata(dev);
+ u32 val;
+
+ /*
+ * Check the power status as if the platform is off the value
+ * reported for the PWM will be incorrect. Report fan as
+ * disabled.
+ */
+ val = readl(drvdata->fn2 + OFS_SEVSTAT);
+
+ return !!((val & BIT(POWER_BIT)) && fan_installed(dev, fan));
+}
+
+static int gxp_pwm_write(struct device *dev, u32 attr, int channel, long val)
+{
+ struct gxp_fan_ctrl_drvdata *drvdata = dev_get_drvdata(dev);
+
+ switch (attr) {
+ case hwmon_pwm_input:
+ if (val > 255 || val < 0)
+ return -EINVAL;
+ writeb(val, drvdata->base + channel);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int gxp_fan_ctrl_write(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long val)
+{
+ switch (type) {
+ case hwmon_pwm:
+ return gxp_pwm_write(dev, attr, channel, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int gxp_fan_read(struct device *dev, u32 attr, int channel, long *val)
+{
+ switch (attr) {
+ case hwmon_fan_enable:
+ *val = fan_enabled(dev, channel);
+ return 0;
+ case hwmon_fan_fault:
+ *val = fan_failed(dev, channel);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int gxp_pwm_read(struct device *dev, u32 attr, int channel, long *val)
+{
+ struct gxp_fan_ctrl_drvdata *drvdata = dev_get_drvdata(dev);
+ u32 reg;
+
+ /*
+ * Check the power status of the platform. If the platform is off
+ * the value reported for the PWM will be incorrect. In this case
+ * report a PWM of zero.
+ */
+
+ reg = readl(drvdata->fn2 + OFS_SEVSTAT);
+
+ if (reg & BIT(POWER_BIT))
+ *val = fan_installed(dev, channel) ? readb(drvdata->base + channel) : 0;
+ else
+ *val = 0;
+
+ return 0;
+}
+
+static int gxp_fan_ctrl_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ switch (type) {
+ case hwmon_fan:
+ return gxp_fan_read(dev, attr, channel, val);
+ case hwmon_pwm:
+ return gxp_pwm_read(dev, attr, channel, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static umode_t gxp_fan_ctrl_is_visible(const void *_data,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ umode_t mode = 0;
+
+ switch (type) {
+ case hwmon_fan:
+ switch (attr) {
+ case hwmon_fan_enable:
+ case hwmon_fan_fault:
+ mode = 0444;
+ break;
+ default:
+ break;
+ }
+ break;
+ case hwmon_pwm:
+ switch (attr) {
+ case hwmon_pwm_input:
+ mode = 0644;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return mode;
+}
+
+static const struct hwmon_ops gxp_fan_ctrl_ops = {
+ .is_visible = gxp_fan_ctrl_is_visible,
+ .read = gxp_fan_ctrl_read,
+ .write = gxp_fan_ctrl_write,
+};
+
+static const struct hwmon_channel_info *gxp_fan_ctrl_info[] = {
+ HWMON_CHANNEL_INFO(fan,
+ HWMON_F_FAULT | HWMON_F_ENABLE,
+ HWMON_F_FAULT | HWMON_F_ENABLE,
+ HWMON_F_FAULT | HWMON_F_ENABLE,
+ HWMON_F_FAULT | HWMON_F_ENABLE,
+ HWMON_F_FAULT | HWMON_F_ENABLE,
+ HWMON_F_FAULT | HWMON_F_ENABLE,
+ HWMON_F_FAULT | HWMON_F_ENABLE,
+ HWMON_F_FAULT | HWMON_F_ENABLE),
+ HWMON_CHANNEL_INFO(pwm,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT),
+ NULL
+};
+
+static const struct hwmon_chip_info gxp_fan_ctrl_chip_info = {
+ .ops = &gxp_fan_ctrl_ops,
+ .info = gxp_fan_ctrl_info,
+
+};
+
+static int gxp_fan_ctrl_probe(struct platform_device *pdev)
+{
+ struct gxp_fan_ctrl_drvdata *drvdata;
+ struct resource *res;
+ struct device *dev = &pdev->dev;
+ struct device *hwmon_dev;
+
+ drvdata = devm_kzalloc(dev, sizeof(struct gxp_fan_ctrl_drvdata),
+ GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ drvdata->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(drvdata->base))
+ return dev_err_probe(dev, PTR_ERR(drvdata->base),
+ "failed to map base\n");
+
+ drvdata->plreg = devm_platform_ioremap_resource_byname(pdev,
+ "pl");
+ if (IS_ERR(drvdata->plreg))
+ return dev_err_probe(dev, PTR_ERR(drvdata->plreg),
+ "failed to map plreg\n");
+
+ drvdata->fn2 = devm_platform_ioremap_resource_byname(pdev,
+ "fn2");
+ if (IS_ERR(drvdata->fn2))
+ return dev_err_probe(dev, PTR_ERR(drvdata->fn2),
+ "failed to map fn2\n");
+
+ hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev,
+ "hpe_gxp_fan_ctrl",
+ drvdata,
+ &gxp_fan_ctrl_chip_info,
+ NULL);
+
+ return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static const struct of_device_id gxp_fan_ctrl_of_match[] = {
+ { .compatible = "hpe,gxp-fan-ctrl", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, gxp_fan_ctrl_of_match);
+
+static struct platform_driver gxp_fan_ctrl_driver = {
+ .probe = gxp_fan_ctrl_probe,
+ .driver = {
+ .name = "gxp-fan-ctrl",
+ .of_match_table = gxp_fan_ctrl_of_match,
+ },
+};
+module_platform_driver(gxp_fan_ctrl_driver);
+
+MODULE_AUTHOR("Nick Hawkins <[email protected]>");
+MODULE_DESCRIPTION("HPE GXP fan controller");
+MODULE_LICENSE("GPL");
--
2.17.1
From: Nick Hawkins <[email protected]>
In order for HPE platforms to be supported by linux on GXP it is
necessary for there to be fan and spi driver support. There fan driver
can support up to 16 fans that are driven by pwm through the CPLD. The
SPI driver supports access to the core flash and bios part. The SPI
driver spi-gxp was added previously to linux.
Signed-off-by: Nick Hawkins <[email protected]>
---
v4:
*No change
v3:
*No change
v2:
*No change
---
arch/arm/configs/multi_v7_defconfig | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index b61b2e3d116b..192c89bfd02a 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -441,6 +441,7 @@ CONFIG_SPI_CADENCE=y
CONFIG_SPI_DAVINCI=y
CONFIG_SPI_FSL_QUADSPI=m
CONFIG_SPI_GPIO=m
+CONFIG_SPI_GXP=m
CONFIG_SPI_FSL_DSPI=m
CONFIG_SPI_OMAP24XX=y
CONFIG_SPI_ORION=y
@@ -530,6 +531,7 @@ CONFIG_SENSORS_NTC_THERMISTOR=m
CONFIG_SENSORS_PWM_FAN=m
CONFIG_SENSORS_RASPBERRYPI_HWMON=m
CONFIG_SENSORS_INA2XX=m
+CONFIG_SENSORS_GXP_FAN_CTRL=m
CONFIG_CPU_THERMAL=y
CONFIG_DEVFREQ_THERMAL=y
CONFIG_IMX_THERMAL=y
--
2.17.1
From: Nick Hawkins <[email protected]>
Reorganize the base address of AHB to accommodate the SPI and fan driver
register requirements. Add the hpe,gxp-spifi and hpe,gxp-fan-ctrl
compatibles. Add comments to make the register range more clear.
Signed-off-by: Nick Hawkins <[email protected]>
---
v4:
*No change
v3:
*No change
v2:
*Changed fn2reg to fn2
*Changed plreg to pl
*Changed fanctrl to fan-controller
*Adjusted base register range to elminate need for defines in code
---
arch/arm/boot/dts/hpe-bmc-dl360gen10.dts | 58 +++++++++++++++++++++
arch/arm/boot/dts/hpe-gxp.dtsi | 64 +++++++++++++++++-------
2 files changed, 103 insertions(+), 19 deletions(-)
diff --git a/arch/arm/boot/dts/hpe-bmc-dl360gen10.dts b/arch/arm/boot/dts/hpe-bmc-dl360gen10.dts
index 3a7382ce40ef..d49dcef95c5c 100644
--- a/arch/arm/boot/dts/hpe-bmc-dl360gen10.dts
+++ b/arch/arm/boot/dts/hpe-bmc-dl360gen10.dts
@@ -24,3 +24,61 @@
reg = <0x40000000 0x20000000>;
};
};
+
+&spifi {
+ status = "okay";
+ flash@0 {
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ u-boot@0 {
+ label = "u-boot";
+ reg = <0x0 0x60000>;
+ };
+
+ u-boot-env@60000 {
+ label = "u-boot-env";
+ reg = <0x60000 0x20000>;
+ };
+
+ kernel@80000 {
+ label = "kernel";
+ reg = <0x80000 0x4c0000>;
+ };
+
+ rofs@540000 {
+ label = "rofs";
+ reg = <0x540000 0x1740000>;
+ };
+
+ rwfs@1c80000 {
+ label = "rwfs";
+ reg = <0x1c80000 0x250000>;
+ };
+
+ section@1ed0000{
+ label = "section";
+ reg = <0x1ed0000 0x130000>;
+ };
+ };
+ };
+ flash@1 {
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ host-prime@0 {
+ label = "host-prime";
+ reg = <0x0 0x02000000>;
+ };
+
+ host-second@2000000 {
+ label = "host-second";
+ reg = <0x02000000 0x02000000>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/hpe-gxp.dtsi b/arch/arm/boot/dts/hpe-gxp.dtsi
index cf735b3c4f35..b73b22a93716 100644
--- a/arch/arm/boot/dts/hpe-gxp.dtsi
+++ b/arch/arm/boot/dts/hpe-gxp.dtsi
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Device Tree file for HPE GXP
+ * Device Tree for HPE
*/
/dts-v1/;
@@ -52,76 +52,102 @@
cache-level = <2>;
};
- ahb@c0000000 {
+ ahb@80000000 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
- ranges = <0x0 0xc0000000 0x30000000>;
+ ranges = <0x0 0x80000000 0xf000000>, /* 0x80000000 - 0x8f000000 */
+ <0x40000000 0xc0000000 0x7fffffff>; /* 0xc0000000 - 0xffffffff */
dma-ranges;
- vic0: interrupt-controller@eff0000 {
+ spifi: spi@40000200 { /* 0xc0000200 */
+ compatible = "hpe,gxp-spifi";
+ reg = <0x40000200 0x80>, <0x4000c000 0x100>, <0x78000000 0x7ff0000>;
+ interrupts = <20>;
+ interrupt-parent = <&vic0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ flash@0 {
+ reg = <0>;
+ compatible = "jedec,spi-nor";
+ };
+
+ flash@1 {
+ reg = <1>;
+ compatible = "jedec,spi-nor";
+ };
+ };
+
+ vic0: interrupt-controller@4eff0000 { /* 0xceff0000 */
compatible = "arm,pl192-vic";
- reg = <0xeff0000 0x1000>;
+ reg = <0x4eff0000 0x1000>;
interrupt-controller;
#interrupt-cells = <1>;
};
- vic1: interrupt-controller@80f00000 {
+ vic1: interrupt-controller@f00000 { /* 0x80f00000 */
compatible = "arm,pl192-vic";
- reg = <0x80f00000 0x1000>;
+ reg = <0xf00000 0x1000>;
interrupt-controller;
#interrupt-cells = <1>;
};
- uarta: serial@e0 {
+ uarta: serial@400000e0 { /* 0xc00000e0 */
compatible = "ns16550a";
- reg = <0xe0 0x8>;
+ reg = <0x400000e0 0x8>;
interrupts = <17>;
interrupt-parent = <&vic0>;
clock-frequency = <1846153>;
reg-shift = <0>;
};
- uartb: serial@e8 {
+ uartb: serial@400000e8 { /* 0xc00000e8 */
compatible = "ns16550a";
- reg = <0xe8 0x8>;
+ reg = <0x400000e8 0x8>;
interrupts = <18>;
interrupt-parent = <&vic0>;
clock-frequency = <1846153>;
reg-shift = <0>;
};
- uartc: serial@f0 {
+ uartc: serial@400000f0 { /* 0xc00000f0 */
compatible = "ns16550a";
- reg = <0xf0 0x8>;
+ reg = <0x400000f0 0x8>;
interrupts = <19>;
interrupt-parent = <&vic0>;
clock-frequency = <1846153>;
reg-shift = <0>;
};
- usb0: usb@efe0000 {
+ usb0: usb@4efe0000 { /* 0xcefe0000 */
compatible = "hpe,gxp-ehci", "generic-ehci";
- reg = <0xefe0000 0x100>;
+ reg = <0x4efe0000 0x100>;
interrupts = <7>;
interrupt-parent = <&vic0>;
};
- st: timer@80 {
+ st: timer@40000080 { /* 0xc0000080 */
compatible = "hpe,gxp-timer";
- reg = <0x80 0x16>;
+ reg = <0x40000080 0x16>;
interrupts = <0>;
interrupt-parent = <&vic0>;
clocks = <&iopclk>;
clock-names = "iop";
};
- usb1: usb@efe0100 {
+ usb1: usb@4efe0100 { /* 0xcefe0100 */
compatible = "hpe,gxp-ohci", "generic-ohci";
- reg = <0xefe0100 0x110>;
+ reg = <0x4efe0100 0x110>;
interrupts = <6>;
interrupt-parent = <&vic0>;
};
+
+ fan-controller@40000c10 { /* 0xc0000c10 */
+ compatible = "hpe,gxp-fan-ctrl";
+ reg = <0x40000c10 0x8>, <0x51000027 0x06>, <0x200070 0x04>;
+ reg-names = "base", "pl", "fn2";
+ };
};
};
};
--
2.17.1
On Tue, Jan 03, 2023 at 02:36:54PM -0600, [email protected] wrote:
> From: Nick Hawkins <[email protected]>
>
> Add the gxp-fan-ctrl.c and gxp-fan-ctrl.rst in hwmon
> driver/documentation.
>
> Signed-off-by: Nick Hawkins <[email protected]>
> Reviewed-by: Guenter Roek <[email protected]>
Applied to hwmon-next.
Thanks,
Guenter
> ---
> v4:
> *No change
> v3:
> *No change
> v2:
> *Added missing gxp-fan-ctrl.yaml
> ---
> MAINTAINERS | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 1daadaa4d48b..00b52be102d6 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2216,13 +2216,16 @@ ARM/HPE GXP ARCHITECTURE
> M: Jean-Marie Verdun <[email protected]>
> M: Nick Hawkins <[email protected]>
> S: Maintained
> +F: Documentation/hwmon/gxp-fan-ctrl.rst
> F: Documentation/devicetree/bindings/arm/hpe,gxp.yaml
> +F: Documentation/devicetree/bindings/hwmon/hpe,gxp-fan-ctrl.yaml
> F: Documentation/devicetree/bindings/spi/hpe,gxp-spifi.yaml
> F: Documentation/devicetree/bindings/timer/hpe,gxp-timer.yaml
> F: arch/arm/boot/dts/hpe-bmc*
> F: arch/arm/boot/dts/hpe-gxp*
> F: arch/arm/mach-hpe/
> F: drivers/clocksource/timer-gxp.c
> +F: drivers/hwmon/gxp-fan-ctrl.c
> F: drivers/spi/spi-gxp.c
> F: drivers/watchdog/gxp-wdt.c
>
On Tue, Jan 03, 2023 at 02:36:50PM -0600, [email protected] wrote:
> From: Nick Hawkins <[email protected]>
>
> The GXP SoC can support up to 16 fans through the interface provided by
> the CPLD. The current support is limited to 8 fans. The fans speeds are
> controlled via 8 different PWMs which can vary in value from 0-255. The
> fans are also capable of reporting if they have failed to the CPLD which
> in turn reports the status to the GXP SoC.
>
> Signed-off-by: Nick Hawkins <[email protected]>
Applied, with two minor changes (see below)
> ---
> v4:
> *Removed unecessary HWMON_PWM_ENABLE
> v3:
> *Removed use of regmap in favor of __iomem
> *Removed use of dev and hwmon_dev from drvdata structure
> *Fixed missing breaks in switch statements
> *Added check for pwm values less than 0
> *Removed regmap and slab header file includes
> v2:
> *Changed number of supported fans from 16 to 8 in code
> *Remove last sentence of commit description
> *Removed support for fan[0-15]_input in code and documentation
> *Changed documentation to limit fan count to 7
> *Changed documentation license
> *Removed PWM defines
> *Added gxp-fan-ctrl to hwmon's index.rst
> *Removed mutex
> *Added fan_enable support to report if the fan is enabled
> *Changed presents to present
> *Removed unnecessary ()
> *Add comment for plreg reads and calculations
> *Add comment for the use of platform power state in code
> *Removed use of variable offsets and went with hardcoding instead
> *Rewrote driver to use devm_hwmon_device_register_with_info()
> *Remove unused header files
> *Fix GPL header
> *Changed module description
> *Add kfree in case of failure to get regmaps or resource
> ---
> Documentation/hwmon/gxp-fan-ctrl.rst | 28 +++
> Documentation/hwmon/index.rst | 1 +
> drivers/hwmon/Kconfig | 9 +
> drivers/hwmon/Makefile | 1 +
> drivers/hwmon/gxp-fan-ctrl.c | 254 +++++++++++++++++++++++++++
> 5 files changed, 293 insertions(+)
> create mode 100644 Documentation/hwmon/gxp-fan-ctrl.rst
> create mode 100644 drivers/hwmon/gxp-fan-ctrl.c
>
> diff --git a/Documentation/hwmon/gxp-fan-ctrl.rst b/Documentation/hwmon/gxp-fan-ctrl.rst
> new file mode 100644
> index 000000000000..ae3397e81c04
> --- /dev/null
> +++ b/Documentation/hwmon/gxp-fan-ctrl.rst
> @@ -0,0 +1,28 @@
> +.. SPDX-License-Identifier: GPL-2.0-only
> +
> +Kernel driver gxp-fan-ctrl
> +==========================
> +
> +Supported chips:
> +
> + * HPE GXP SOC
> +
> +Author: Nick Hawkins <[email protected]>
> +
> +
> +Description
> +-----------
> +
> +gxp-fan-ctrl is a driver which provides fan control for the hpe gxp soc.
> +The driver allows the gathering of fan status and the use of fan
> +PWM control.
> +
> +
> +Sysfs attributes
> +----------------
> +
> +======================= ===========================================================
> +pwm[0-7] Fan 0 to 7 respective PWM value (0-255)
> +fan[0-7]_fault Fan 0 to 7 respective fault status: 1 fail, 0 ok
> +fan[0-7]_enable Fan 0 to 7 respective enabled status: 1 enabled, 0 disabled
> +======================= ===========================================================
> diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
> index c1d11cf13eef..97819cf5c97f 100644
> --- a/Documentation/hwmon/index.rst
> +++ b/Documentation/hwmon/index.rst
> @@ -73,6 +73,7 @@ Hardware Monitoring Kernel Drivers
> g762
> gsc-hwmon
> gl518sm
> + gxp-fan-ctrl
> hih6130
> ibmaem
> ibm-cffps
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index 7ac3daaf59ce..45febd5d5cf7 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -706,6 +706,15 @@ config SENSORS_GPIO_FAN
> This driver can also be built as a module. If so, the module
> will be called gpio-fan.
>
> +config SENSORS_GXP_FAN_CTRL
> + tristate "HPE GXP fan controller"
> + depends on ARCH_HPE_GXP || COMPILE_TEST
> + help
> + If you say yes here you get support for GXP fan control functionality.
> +
> + The GXP controls fan function via the CPLD through the use of PWM
> + registers. This driver reports status and pwm setting of the fans.
> +
> config SENSORS_HIH6130
> tristate "Honeywell Humidicon HIH-6130 humidity/temperature sensor"
> depends on I2C
> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> index 11d076cad8a2..b5782dc4dc6e 100644
> --- a/drivers/hwmon/Makefile
> +++ b/drivers/hwmon/Makefile
> @@ -83,6 +83,7 @@ obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
> obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o
> obj-$(CONFIG_SENSORS_GSC) += gsc-hwmon.o
> obj-$(CONFIG_SENSORS_GPIO_FAN) += gpio-fan.o
> +obj-$(CONFIG_SENSORS_GXP_FAN_CTRL) += gxp-fan-ctrl.o
> obj-$(CONFIG_SENSORS_HIH6130) += hih6130.o
> obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o
> obj-$(CONFIG_SENSORS_I5500) += i5500_temp.o
> diff --git a/drivers/hwmon/gxp-fan-ctrl.c b/drivers/hwmon/gxp-fan-ctrl.c
> new file mode 100644
> index 000000000000..c7ebd3bbf35b
> --- /dev/null
> +++ b/drivers/hwmon/gxp-fan-ctrl.c
> @@ -0,0 +1,254 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/* Copyright (C) 2022 Hewlett-Packard Enterprise Development Company, L.P. */
> +
> +#include <linux/err.h>
> +#include <linux/hwmon.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
Use of BITS() asks for include of linux/bits.h
> +
> +#define OFS_FAN_INST 0 /* Is 0 because plreg base will be set at INST */
> +#define OFS_FAN_FAIL 2 /* Is 2 bytes after base */
> +#define OFS_SEVSTAT 0 /* Is 0 because fn2 base will be set at SEVSTAT */
> +#define POWER_BIT 24
Tab-aligned defines
> +
> +struct gxp_fan_ctrl_drvdata {
> + void __iomem *base;
> + void __iomem *plreg;
> + void __iomem *fn2;
> +};
> +
> +static bool fan_installed(struct device *dev, int fan)
> +{
> + struct gxp_fan_ctrl_drvdata *drvdata = dev_get_drvdata(dev);
> + u8 val;
> +
> + val = readb(drvdata->plreg + OFS_FAN_INST);
> +
> + return !!(val & BIT(fan));
> +}
> +
> +static long fan_failed(struct device *dev, int fan)
> +{
> + struct gxp_fan_ctrl_drvdata *drvdata = dev_get_drvdata(dev);
> + u8 val;
> +
> + val = readb(drvdata->plreg + OFS_FAN_FAIL);
> +
> + return !!(val & BIT(fan));
> +}
> +
> +static long fan_enabled(struct device *dev, int fan)
> +{
> + struct gxp_fan_ctrl_drvdata *drvdata = dev_get_drvdata(dev);
> + u32 val;
> +
> + /*
> + * Check the power status as if the platform is off the value
> + * reported for the PWM will be incorrect. Report fan as
> + * disabled.
> + */
> + val = readl(drvdata->fn2 + OFS_SEVSTAT);
> +
> + return !!((val & BIT(POWER_BIT)) && fan_installed(dev, fan));
> +}
> +
> +static int gxp_pwm_write(struct device *dev, u32 attr, int channel, long val)
> +{
> + struct gxp_fan_ctrl_drvdata *drvdata = dev_get_drvdata(dev);
> +
> + switch (attr) {
> + case hwmon_pwm_input:
> + if (val > 255 || val < 0)
> + return -EINVAL;
> + writeb(val, drvdata->base + channel);
> + return 0;
> + default:
> + return -EOPNOTSUPP;
> + }
> +}
> +
> +static int gxp_fan_ctrl_write(struct device *dev, enum hwmon_sensor_types type,
> + u32 attr, int channel, long val)
> +{
> + switch (type) {
> + case hwmon_pwm:
> + return gxp_pwm_write(dev, attr, channel, val);
> + default:
> + return -EOPNOTSUPP;
> + }
> +}
> +
> +static int gxp_fan_read(struct device *dev, u32 attr, int channel, long *val)
> +{
> + switch (attr) {
> + case hwmon_fan_enable:
> + *val = fan_enabled(dev, channel);
> + return 0;
> + case hwmon_fan_fault:
> + *val = fan_failed(dev, channel);
> + return 0;
> + default:
> + return -EOPNOTSUPP;
> + }
> +}
> +
> +static int gxp_pwm_read(struct device *dev, u32 attr, int channel, long *val)
> +{
> + struct gxp_fan_ctrl_drvdata *drvdata = dev_get_drvdata(dev);
> + u32 reg;
> +
> + /*
> + * Check the power status of the platform. If the platform is off
> + * the value reported for the PWM will be incorrect. In this case
> + * report a PWM of zero.
> + */
> +
> + reg = readl(drvdata->fn2 + OFS_SEVSTAT);
> +
> + if (reg & BIT(POWER_BIT))
> + *val = fan_installed(dev, channel) ? readb(drvdata->base + channel) : 0;
> + else
> + *val = 0;
> +
> + return 0;
> +}
> +
> +static int gxp_fan_ctrl_read(struct device *dev, enum hwmon_sensor_types type,
> + u32 attr, int channel, long *val)
> +{
> + switch (type) {
> + case hwmon_fan:
> + return gxp_fan_read(dev, attr, channel, val);
> + case hwmon_pwm:
> + return gxp_pwm_read(dev, attr, channel, val);
> + default:
> + return -EOPNOTSUPP;
> + }
> +}
> +
> +static umode_t gxp_fan_ctrl_is_visible(const void *_data,
> + enum hwmon_sensor_types type,
> + u32 attr, int channel)
> +{
> + umode_t mode = 0;
> +
> + switch (type) {
> + case hwmon_fan:
> + switch (attr) {
> + case hwmon_fan_enable:
> + case hwmon_fan_fault:
> + mode = 0444;
> + break;
> + default:
> + break;
> + }
> + break;
> + case hwmon_pwm:
> + switch (attr) {
> + case hwmon_pwm_input:
> + mode = 0644;
> + break;
> + default:
> + break;
> + }
> + break;
> + default:
> + break;
> + }
> +
> + return mode;
> +}
> +
> +static const struct hwmon_ops gxp_fan_ctrl_ops = {
> + .is_visible = gxp_fan_ctrl_is_visible,
> + .read = gxp_fan_ctrl_read,
> + .write = gxp_fan_ctrl_write,
> +};
> +
> +static const struct hwmon_channel_info *gxp_fan_ctrl_info[] = {
> + HWMON_CHANNEL_INFO(fan,
> + HWMON_F_FAULT | HWMON_F_ENABLE,
> + HWMON_F_FAULT | HWMON_F_ENABLE,
> + HWMON_F_FAULT | HWMON_F_ENABLE,
> + HWMON_F_FAULT | HWMON_F_ENABLE,
> + HWMON_F_FAULT | HWMON_F_ENABLE,
> + HWMON_F_FAULT | HWMON_F_ENABLE,
> + HWMON_F_FAULT | HWMON_F_ENABLE,
> + HWMON_F_FAULT | HWMON_F_ENABLE),
> + HWMON_CHANNEL_INFO(pwm,
> + HWMON_PWM_INPUT,
> + HWMON_PWM_INPUT,
> + HWMON_PWM_INPUT,
> + HWMON_PWM_INPUT,
> + HWMON_PWM_INPUT,
> + HWMON_PWM_INPUT,
> + HWMON_PWM_INPUT,
> + HWMON_PWM_INPUT),
> + NULL
> +};
> +
> +static const struct hwmon_chip_info gxp_fan_ctrl_chip_info = {
> + .ops = &gxp_fan_ctrl_ops,
> + .info = gxp_fan_ctrl_info,
> +
> +};
> +
> +static int gxp_fan_ctrl_probe(struct platform_device *pdev)
> +{
> + struct gxp_fan_ctrl_drvdata *drvdata;
> + struct resource *res;
> + struct device *dev = &pdev->dev;
> + struct device *hwmon_dev;
> +
> + drvdata = devm_kzalloc(dev, sizeof(struct gxp_fan_ctrl_drvdata),
> + GFP_KERNEL);
> + if (!drvdata)
> + return -ENOMEM;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + drvdata->base = devm_ioremap_resource(&pdev->dev, res);
> + if (IS_ERR(drvdata->base))
> + return dev_err_probe(dev, PTR_ERR(drvdata->base),
> + "failed to map base\n");
> +
> + drvdata->plreg = devm_platform_ioremap_resource_byname(pdev,
> + "pl");
> + if (IS_ERR(drvdata->plreg))
> + return dev_err_probe(dev, PTR_ERR(drvdata->plreg),
> + "failed to map plreg\n");
> +
> + drvdata->fn2 = devm_platform_ioremap_resource_byname(pdev,
> + "fn2");
> + if (IS_ERR(drvdata->fn2))
> + return dev_err_probe(dev, PTR_ERR(drvdata->fn2),
> + "failed to map fn2\n");
> +
> + hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev,
> + "hpe_gxp_fan_ctrl",
> + drvdata,
> + &gxp_fan_ctrl_chip_info,
> + NULL);
> +
> + return PTR_ERR_OR_ZERO(hwmon_dev);
> +}
> +
> +static const struct of_device_id gxp_fan_ctrl_of_match[] = {
> + { .compatible = "hpe,gxp-fan-ctrl", },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, gxp_fan_ctrl_of_match);
> +
> +static struct platform_driver gxp_fan_ctrl_driver = {
> + .probe = gxp_fan_ctrl_probe,
> + .driver = {
> + .name = "gxp-fan-ctrl",
> + .of_match_table = gxp_fan_ctrl_of_match,
> + },
> +};
> +module_platform_driver(gxp_fan_ctrl_driver);
> +
> +MODULE_AUTHOR("Nick Hawkins <[email protected]>");
> +MODULE_DESCRIPTION("HPE GXP fan controller");
> +MODULE_LICENSE("GPL");
On Tue, Jan 03, 2023 at 02:36:52PM -0600, [email protected] wrote:
> From: Nick Hawkins <[email protected]>
>
> Reorganize the base address of AHB to accommodate the SPI and fan driver
> register requirements. Add the hpe,gxp-spifi and hpe,gxp-fan-ctrl
> compatibles. Add comments to make the register range more clear.
>
> Signed-off-by: Nick Hawkins <[email protected]>
Acked-by: Guenter Roeck <[email protected]>
Note that I can not apply this patch; it will have to be applied through
the arm tree.
Guenter
> ---
> v4:
> *No change
> v3:
> *No change
> v2:
> *Changed fn2reg to fn2
> *Changed plreg to pl
> *Changed fanctrl to fan-controller
> *Adjusted base register range to elminate need for defines in code
> ---
> arch/arm/boot/dts/hpe-bmc-dl360gen10.dts | 58 +++++++++++++++++++++
> arch/arm/boot/dts/hpe-gxp.dtsi | 64 +++++++++++++++++-------
> 2 files changed, 103 insertions(+), 19 deletions(-)
>
> diff --git a/arch/arm/boot/dts/hpe-bmc-dl360gen10.dts b/arch/arm/boot/dts/hpe-bmc-dl360gen10.dts
> index 3a7382ce40ef..d49dcef95c5c 100644
> --- a/arch/arm/boot/dts/hpe-bmc-dl360gen10.dts
> +++ b/arch/arm/boot/dts/hpe-bmc-dl360gen10.dts
> @@ -24,3 +24,61 @@
> reg = <0x40000000 0x20000000>;
> };
> };
> +
> +&spifi {
> + status = "okay";
> + flash@0 {
> + partitions {
> + compatible = "fixed-partitions";
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + u-boot@0 {
> + label = "u-boot";
> + reg = <0x0 0x60000>;
> + };
> +
> + u-boot-env@60000 {
> + label = "u-boot-env";
> + reg = <0x60000 0x20000>;
> + };
> +
> + kernel@80000 {
> + label = "kernel";
> + reg = <0x80000 0x4c0000>;
> + };
> +
> + rofs@540000 {
> + label = "rofs";
> + reg = <0x540000 0x1740000>;
> + };
> +
> + rwfs@1c80000 {
> + label = "rwfs";
> + reg = <0x1c80000 0x250000>;
> + };
> +
> + section@1ed0000{
> + label = "section";
> + reg = <0x1ed0000 0x130000>;
> + };
> + };
> + };
> + flash@1 {
> + partitions {
> + compatible = "fixed-partitions";
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + host-prime@0 {
> + label = "host-prime";
> + reg = <0x0 0x02000000>;
> + };
> +
> + host-second@2000000 {
> + label = "host-second";
> + reg = <0x02000000 0x02000000>;
> + };
> + };
> + };
> +};
> diff --git a/arch/arm/boot/dts/hpe-gxp.dtsi b/arch/arm/boot/dts/hpe-gxp.dtsi
> index cf735b3c4f35..b73b22a93716 100644
> --- a/arch/arm/boot/dts/hpe-gxp.dtsi
> +++ b/arch/arm/boot/dts/hpe-gxp.dtsi
> @@ -1,6 +1,6 @@
> // SPDX-License-Identifier: GPL-2.0
> /*
> - * Device Tree file for HPE GXP
> + * Device Tree for HPE
> */
>
> /dts-v1/;
> @@ -52,76 +52,102 @@
> cache-level = <2>;
> };
>
> - ahb@c0000000 {
> + ahb@80000000 {
> compatible = "simple-bus";
> #address-cells = <1>;
> #size-cells = <1>;
> - ranges = <0x0 0xc0000000 0x30000000>;
> + ranges = <0x0 0x80000000 0xf000000>, /* 0x80000000 - 0x8f000000 */
> + <0x40000000 0xc0000000 0x7fffffff>; /* 0xc0000000 - 0xffffffff */
> dma-ranges;
>
> - vic0: interrupt-controller@eff0000 {
> + spifi: spi@40000200 { /* 0xc0000200 */
> + compatible = "hpe,gxp-spifi";
> + reg = <0x40000200 0x80>, <0x4000c000 0x100>, <0x78000000 0x7ff0000>;
> + interrupts = <20>;
> + interrupt-parent = <&vic0>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> + status = "disabled";
> + flash@0 {
> + reg = <0>;
> + compatible = "jedec,spi-nor";
> + };
> +
> + flash@1 {
> + reg = <1>;
> + compatible = "jedec,spi-nor";
> + };
> + };
> +
> + vic0: interrupt-controller@4eff0000 { /* 0xceff0000 */
> compatible = "arm,pl192-vic";
> - reg = <0xeff0000 0x1000>;
> + reg = <0x4eff0000 0x1000>;
> interrupt-controller;
> #interrupt-cells = <1>;
> };
>
> - vic1: interrupt-controller@80f00000 {
> + vic1: interrupt-controller@f00000 { /* 0x80f00000 */
> compatible = "arm,pl192-vic";
> - reg = <0x80f00000 0x1000>;
> + reg = <0xf00000 0x1000>;
> interrupt-controller;
> #interrupt-cells = <1>;
> };
>
> - uarta: serial@e0 {
> + uarta: serial@400000e0 { /* 0xc00000e0 */
> compatible = "ns16550a";
> - reg = <0xe0 0x8>;
> + reg = <0x400000e0 0x8>;
> interrupts = <17>;
> interrupt-parent = <&vic0>;
> clock-frequency = <1846153>;
> reg-shift = <0>;
> };
>
> - uartb: serial@e8 {
> + uartb: serial@400000e8 { /* 0xc00000e8 */
> compatible = "ns16550a";
> - reg = <0xe8 0x8>;
> + reg = <0x400000e8 0x8>;
> interrupts = <18>;
> interrupt-parent = <&vic0>;
> clock-frequency = <1846153>;
> reg-shift = <0>;
> };
>
> - uartc: serial@f0 {
> + uartc: serial@400000f0 { /* 0xc00000f0 */
> compatible = "ns16550a";
> - reg = <0xf0 0x8>;
> + reg = <0x400000f0 0x8>;
> interrupts = <19>;
> interrupt-parent = <&vic0>;
> clock-frequency = <1846153>;
> reg-shift = <0>;
> };
>
> - usb0: usb@efe0000 {
> + usb0: usb@4efe0000 { /* 0xcefe0000 */
> compatible = "hpe,gxp-ehci", "generic-ehci";
> - reg = <0xefe0000 0x100>;
> + reg = <0x4efe0000 0x100>;
> interrupts = <7>;
> interrupt-parent = <&vic0>;
> };
>
> - st: timer@80 {
> + st: timer@40000080 { /* 0xc0000080 */
> compatible = "hpe,gxp-timer";
> - reg = <0x80 0x16>;
> + reg = <0x40000080 0x16>;
> interrupts = <0>;
> interrupt-parent = <&vic0>;
> clocks = <&iopclk>;
> clock-names = "iop";
> };
>
> - usb1: usb@efe0100 {
> + usb1: usb@4efe0100 { /* 0xcefe0100 */
> compatible = "hpe,gxp-ohci", "generic-ohci";
> - reg = <0xefe0100 0x110>;
> + reg = <0x4efe0100 0x110>;
> interrupts = <6>;
> interrupt-parent = <&vic0>;
> };
> +
> + fan-controller@40000c10 { /* 0xc0000c10 */
> + compatible = "hpe,gxp-fan-ctrl";
> + reg = <0x40000c10 0x8>, <0x51000027 0x06>, <0x200070 0x04>;
> + reg-names = "base", "pl", "fn2";
> + };
> };
> };
> };
On Tue, Jan 03, 2023 at 02:36:51PM -0600, [email protected] wrote:
> From: Nick Hawkins <[email protected]>
>
> Create documentation for the binding to support control of the fans on
> HPE platforms.
>
> Signed-off-by: Nick Hawkins <[email protected]>
> Reviewed-by: Rob Herring <[email protected]>
> Reviewed-by: Guenter Roeck <[email protected]>
Applied to hwmon-next.
Thanks,
Guenter
> ---
> v4:
> *No change
> v3:
> *No change
> v2:
> *Changed plreg to pl
> *Changed fn2reg to reg
> *Edited descriptions for all registers
> *Changed fanctrl to fan-controller
> *Changed commit description
> ---
> .../bindings/hwmon/hpe,gxp-fan-ctrl.yaml | 45 +++++++++++++++++++
> 1 file changed, 45 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/hwmon/hpe,gxp-fan-ctrl.yaml
>
> diff --git a/Documentation/devicetree/bindings/hwmon/hpe,gxp-fan-ctrl.yaml b/Documentation/devicetree/bindings/hwmon/hpe,gxp-fan-ctrl.yaml
> new file mode 100644
> index 000000000000..4a52aac6be72
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/hwmon/hpe,gxp-fan-ctrl.yaml
> @@ -0,0 +1,45 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/hwmon/hpe,gxp-fan-ctrl.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: HPE GXP Fan Controller
> +
> +maintainers:
> + - Nick Hawkins <[email protected]>
> +
> +description: |
> + The HPE GXP fan controller controls the fans through an external CPLD
> + device that connects to the fans.
> +
> +properties:
> + compatible:
> + const: hpe,gxp-fan-ctrl
> +
> + reg:
> + items:
> + - description: Fan controller PWM
> + - description: Programmable logic
> + - description: Function 2
> +
> + reg-names:
> + items:
> + - const: base
> + - const: pl
> + - const: fn2
> +
> +required:
> + - compatible
> + - reg
> + - reg-names
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + fan-controller@1000c00 {
> + compatible = "hpe,gxp-fan-ctrl";
> + reg = <0x1000c00 0x200>, <0xd1000000 0xff>, <0x80200000 0x100000>;
> + reg-names = "base", "pl", "fn2";
> + };
On Tue, Jan 03, 2023 at 02:36:53PM -0600, [email protected] wrote:
> From: Nick Hawkins <[email protected]>
>
> In order for HPE platforms to be supported by linux on GXP it is
> necessary for there to be fan and spi driver support. There fan driver
> can support up to 16 fans that are driven by pwm through the CPLD. The
> SPI driver supports access to the core flash and bios part. The SPI
> driver spi-gxp was added previously to linux.
>
> Signed-off-by: Nick Hawkins <[email protected]>
Acked-by: Guenter Roeck <[email protected]>
This patch will have to be applied through the arm tree.
Thanks,
Guenter
> ---
> v4:
> *No change
> v3:
> *No change
> v2:
> *No change
> ---
> arch/arm/configs/multi_v7_defconfig | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
> index b61b2e3d116b..192c89bfd02a 100644
> --- a/arch/arm/configs/multi_v7_defconfig
> +++ b/arch/arm/configs/multi_v7_defconfig
> @@ -441,6 +441,7 @@ CONFIG_SPI_CADENCE=y
> CONFIG_SPI_DAVINCI=y
> CONFIG_SPI_FSL_QUADSPI=m
> CONFIG_SPI_GPIO=m
> +CONFIG_SPI_GXP=m
> CONFIG_SPI_FSL_DSPI=m
> CONFIG_SPI_OMAP24XX=y
> CONFIG_SPI_ORION=y
> @@ -530,6 +531,7 @@ CONFIG_SENSORS_NTC_THERMISTOR=m
> CONFIG_SENSORS_PWM_FAN=m
> CONFIG_SENSORS_RASPBERRYPI_HWMON=m
> CONFIG_SENSORS_INA2XX=m
> +CONFIG_SENSORS_GXP_FAN_CTRL=m
> CONFIG_CPU_THERMAL=y
> CONFIG_DEVFREQ_THERMAL=y
> CONFIG_IMX_THERMAL=y
On Tue, Jan 3, 2023, at 21:36, [email protected] wrote:
> From: Nick Hawkins <[email protected]>
>
> Reorganize the base address of AHB to accommodate the SPI and fan driver
> register requirements. Add the hpe,gxp-spifi and hpe,gxp-fan-ctrl
> compatibles. Add comments to make the register range more clear.
>
> Signed-off-by: Nick Hawkins <[email protected]>
>
> diff --git a/arch/arm/boot/dts/hpe-gxp.dtsi
> b/arch/arm/boot/dts/hpe-gxp.dtsi
> index cf735b3c4f35..b73b22a93716 100644
> --- a/arch/arm/boot/dts/hpe-gxp.dtsi
> +++ b/arch/arm/boot/dts/hpe-gxp.dtsi
> @@ -1,6 +1,6 @@
> // SPDX-License-Identifier: GPL-2.0
> /*
> - * Device Tree file for HPE GXP
> + * Device Tree for HPE
> */
>
> /dts-v1/;
> @@ -52,76 +52,102 @@
> cache-level = <2>;
> };
>
> - ahb@c0000000 {
> + ahb@80000000 {
> compatible = "simple-bus";
> #address-cells = <1>;
> #size-cells = <1>;
> - ranges = <0x0 0xc0000000 0x30000000>;
> + ranges = <0x0 0x80000000 0xf000000>, /* 0x80000000 - 0x8f000000 */
> + <0x40000000 0xc0000000 0x7fffffff>; /* 0xc0000000 - 0xffffffff */
I'm a bit confused by the change in the mappings: are you
sure this all the same ahb bus and not two separate buses?
The comment for the second range looks wrong to me, as
you define a 2GB (minus one byte) sized mapping but the
comment only lists a 1GB (including the last byte) mapping.
I would expect that the original 0x30000000 (including the
last byte) was correct here.
> - vic1: interrupt-controller@80f00000 {
> + vic1: interrupt-controller@f00000 { /* 0x80f00000 */
This is not the same address as before. I'm also not sure the
comment is helpful here.
Arnd
> > - ahb@c0000000 {
> > + ahb@80000000 {
> > compatible = "simple-bus";
> > #address-cells = <1>;
> > #size-cells = <1>;
> > - ranges = <0x0 0xc0000000 0x30000000>;
> > + ranges = <0x0 0x80000000 0xf000000>, /* 0x80000000 - 0x8f000000 */
> > + <0x40000000 0xc0000000 0x7fffffff>; /* 0xc0000000 - 0xffffffff */
> I'm a bit confused by the change in the mappings: are you
> sure this all the same ahb bus and not two separate buses?
Yes this is the same bus, however we are not including all of
it as it maps some host registers that we do not want to access
at this time.
> The comment for the second range looks wrong to me, as
> you define a 2GB (minus one byte) sized mapping but the
> comment only lists a 1GB (including the last byte) mapping.
> I would expect that the original 0x30000000 (including the
> last byte) was correct here.
Yes this was incorrect, I believe it should be:
ranges = <0x0 0x80000000 0xf000000>, /* 0x80000000 - 0x8f000000 */
<0x40000000 0xc0000000 0x3fffffff>; /* 0xc0000000 - 0xffffffff */
I will create a v5 version of this patchset with just this and the
defconfig for your review.
> > - vic1: interrupt-controller@80f00000 {
> > + vic1: interrupt-controller@f00000 { /* 0x80f00000 */
> This is not the same address as before. I'm also not sure the
> comment is helpful here.
My understanding was that the physical address would be the
0x80000000 from the first range plus the 0xf00000 to be
0x80f00000?
Thank you,
-Nick Hawkins
On Tue, Jan 3, 2023, at 22:38, Guenter Roeck wrote:
> On Tue, Jan 03, 2023 at 02:36:53PM -0600, [email protected] wrote:
>> From: Nick Hawkins <[email protected]>
>>
>> In order for HPE platforms to be supported by linux on GXP it is
>> necessary for there to be fan and spi driver support. There fan driver
>> can support up to 16 fans that are driven by pwm through the CPLD. The
>> SPI driver supports access to the core flash and bios part. The SPI
>> driver spi-gxp was added previously to linux.
>>
>> Signed-off-by: Nick Hawkins <[email protected]>
>
> Acked-by: Guenter Roeck <[email protected]>
>
> This patch will have to be applied through the arm tree.
>
The patch looks good to me, please send it to [email protected]
(Cc the interested parties and lists) for inclusion, I'll
pick it up from there.
Arnd
On Thu, Jan 12, 2023, at 16:40, Hawkins, Nick wrote:
>> > - ahb@c0000000 {
>> > + ahb@80000000 {
>> > compatible = "simple-bus";
>> > #address-cells = <1>;
>> > #size-cells = <1>;
>> > - ranges = <0x0 0xc0000000 0x30000000>;
>> > + ranges = <0x0 0x80000000 0xf000000>, /* 0x80000000 - 0x8f000000 */
>> > + <0x40000000 0xc0000000 0x7fffffff>; /* 0xc0000000 - 0xffffffff */
>
>
>> I'm a bit confused by the change in the mappings: are you
>> sure this all the same ahb bus and not two separate buses?
>
> Yes this is the same bus, however we are not including all of
> it as it maps some host registers that we do not want to access
> at this time.
If the two ranges are actually translated separately on the
bus, you could also decide to enumerate the translations with
a 64-bit local address and make the upper word an enumeration,
such as
ranges = <0x1 0x0 0x80000000 0xf000000>,
<0x2 0x0 0xc0000000 0x30000000>;
then you get small numbers again in the 'reg' properties
that are easier to read and ideally match the bus-local
numbers from the hardware manual.
>> The comment for the second range looks wrong to me, as
>> you define a 2GB (minus one byte) sized mapping but the
>> comment only lists a 1GB (including the last byte) mapping.
>
>
>> I would expect that the original 0x30000000 (including the
>> last byte) was correct here.
>
> Yes this was incorrect, I believe it should be:
>
> ranges = <0x0 0x80000000 0xf000000>, /* 0x80000000 - 0x8f000000 */
> <0x40000000 0xc0000000 0x3fffffff>; /* 0xc0000000 -
> 0xffffffff */
>
> I will create a v5 version of this patchset with just this and the
> defconfig for your review.
Now it almost matches, except for the final byte, as the
range actually ends at 0xfffffffe not 0xffffffff if you make
the size one byte less than 1GB.
Is there a special register in the last byte?
>> > - vic1: interrupt-controller@80f00000 {
>> > + vic1: interrupt-controller@f00000 { /* 0x80f00000 */
>
>
>> This is not the same address as before. I'm also not sure the
>> comment is helpful here.
>
> My understanding was that the physical address would be the
> 0x80000000 from the first range plus the 0xf00000 to be
> 0x80f00000?
I suppose the physical address in the old mapping was actually
outside of the 0xc0000000-0xefffffff range, so it wasn't
even accessible. If the addresses are interpreted to wrap around
at the end of the mapping, that would have made the CPU visible
address 0xe0f00000 (0xc0000000 + (0x80f00000 % 0x30000000)).
If it just wrapped around as a 32-bit number, it would be
0x40f00000 ((0xc0000000 + 0x80f00000)% 0x100000000), but I
don't see you you'd get to 80f00000.
Arnd
> If the two ranges are actually translated separately on the
> bus, you could also decide to enumerate the translations with
> a 64-bit local address and make the upper word an enumeration,
> such as
> ranges = <0x1 0x0 0x80000000 0xf000000>,
> <0x2 0x0 0xc0000000 0x30000000>;
I am not finding a good example on how this would affect the node
addresses and reg properties. I believe I will stick with the current
format if that is acceptable.
> Now it almost matches, except for the final byte, as the
> range actually ends at 0xfffffffe not 0xffffffff if you make
> the size one byte less than 1GB.
> Is there a special register in the last byte?
No there is not I will now have ranges as:
ranges = <0x0 0x80000000 0xf000000>, /* 0x80000000 - 0x8f000000 */
<0x40000000 0xc0000000 0x40000000>; /* 0xc0000000 - 0xffffffff */
> I suppose the physical address in the old mapping was actually
> outside of the 0xc0000000-0xefffffff range, so it wasn't
> even accessible. If the addresses are interpreted to wrap around
> at the end of the mapping, that would have made the CPU visible
> address 0xe0f00000 (0xc0000000 + (0x80f00000 % 0x30000000)).
> If it just wrapped around as a 32-bit number, it would be
> 0x40f00000 ((0xc0000000 + 0x80f00000)% 0x100000000), but I
> don't see you you'd get to 80f00000.
It was not intended to wrap around; it was an error before and was
not accessible.
The updated section of the device tree will be:
ahb@80000000 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x80000000 0xf000000>, /* 0x80000000 - 0x8f000000 */
<0x40000000 0xc0000000 0x40000000>; /* 0xc0000000 - 0xffffffff */
dma-ranges;
...
vic0: interrupt-controller@4eff0000 { /* 0xceff0000 */
compatible = "arm,pl192-vic";
reg = <0x4eff0000 0x1000>;
interrupt-controller;
#interrupt-cells = <1>;
};
vic1: interrupt-controller@f00000 { /* 0x80f00000 */
compatible = "arm,pl192-vic";
reg = <0xf00000 0x1000>;
interrupt-controller;
#interrupt-cells = <1>;
};
...
};
Thanks,
-Nick Hawkins
On Thu, Jan 12, 2023, at 20:58, Hawkins, Nick wrote:
> The updated section of the device tree will be:
>
> ahb@80000000 {
> compatible = "simple-bus";
> #address-cells = <1>;
> #size-cells = <1>;
> ranges = <0x0 0x80000000 0xf000000>, /*
> 0x80000000 - 0x8f000000 */
> <0x40000000 0xc0000000 0x40000000>; /*
> 0xc0000000 - 0xffffffff */
> dma-ranges;
Ok
>
> ...
>
> vic0: interrupt-controller@4eff0000 { /* 0xceff0000 */
> compatible = "arm,pl192-vic";
> reg = <0x4eff0000 0x1000>;
> interrupt-controller;
> #interrupt-cells = <1>;
> };
>
> vic1: interrupt-controller@f00000 { /* 0x80f00000 */
> compatible = "arm,pl192-vic";
> reg = <0xf00000 0x1000>;
> interrupt-controller;
> #interrupt-cells = <1>;
> };
I still don't see the value of the /* 0x80f00000 */ comments,
you should define the ranges to the most sensible mapping
based on the datasheet so you don't need the comments.
If the datasheet uses a bus-local address (0xf00000), then
just get rid of the comment, since that only adds confusion.
OTOH if the 0x80f00000 number is what is in the datasheet,
then adjust the ranges to do a 1:1 mapping of the registers
on the bus and use that address directly.
Arnd