On-Chip Controller (OCC) hwmon driver
Subsystems (4)
v5 cover On-Chip Controller (OCC) hwmon driver
From: "Edward A. James" <[email protected]>
This patchset provides a new OCC hwmon driver. There are a number of issues with the existing driver. Firstly, i2c access was embedded throughout the driver. Secondly, there is no way to easily differentiate versions of the OCC.
This patchset addresses the first issue by abstracting the bus transfer protocol into a modular structure. In this way, any low level transfer method may be easily implemented.
The second issue is addressed by separating the "version specific" code for the OCC and the common hwmon code. This task is not yet complete, but the general structure is in place. Ultimately, different OCC versions could be probed up using the device tree.
Edward A. James (5):
Revert "hwmon: Add Power8 OCC hwmon driver"
drivers: Add hwmon occ driver framework
drivers: hwmon OCC scom bus operations
drivers: Add hwmon OCC version specific functions
drivers: OCC hwmon driver and sysfs
.../devicetree/bindings/i2c/i2c-ibm-occ.txt | 2 +- drivers/hwmon/Kconfig | 13 +- drivers/hwmon/Makefile | 2 +- drivers/hwmon/occ/Kconfig | 15 + drivers/hwmon/occ/Makefile | 1 + drivers/hwmon/occ/occ.c | 892 ++++++++++++++ drivers/hwmon/occ/occ.h | 58 + drivers/hwmon/occ/occ_i2c.c | 147 +++ drivers/hwmon/occ/p8.c | 222 ++++ drivers/hwmon/occ/p8.h | 29 + drivers/hwmon/occ/p9.c | 253 ++++ drivers/hwmon/occ/p9.h | 29 + drivers/hwmon/occ/scom.h | 31 + drivers/hwmon/power8_occ_i2c.c | 1254 -------------------- 14 files changed, 1680 insertions(+), 1268 deletions(-) create mode 100644 drivers/hwmon/occ/Kconfig create mode 100644 drivers/hwmon/occ/Makefile create mode 100644 drivers/hwmon/occ/occ.c create mode 100644 drivers/hwmon/occ/occ.h create mode 100644 drivers/hwmon/occ/occ_i2c.c create mode 100644 drivers/hwmon/occ/p8.c create mode 100644 drivers/hwmon/occ/p8.h create mode 100644 drivers/hwmon/occ/p9.c create mode 100644 drivers/hwmon/occ/p9.h create mode 100644 drivers/hwmon/occ/scom.h delete mode 100644 drivers/hwmon/power8_occ_i2c.c
Signature · 1 line
1.9.1
cover On-Chip Controller (OCC) hwmon driver
Hi Eddie,
Quoted 5 lines
This patchset provides a new OCC hwmon driver. There are a number of issues with the existing driver. Firstly, i2c access was embedded throughout the driver. Secondly, there is no way to easily differentiate versions of the OCC.
Quoted 8 lines
This patchset addresses the first issue by abstracting the bus transfer protocol into a modular structure. In this way, any low level transfer method may be easily implemented.
The second issue is addressed by separating the "version specific" code for the OCC and the common hwmon code. This task is not yet complete, but the general structure is in place. Ultimately, different OCC versions could be probed up using the device tree.
I agree with all of this. However, I thought some of the layering could still be improved, so rather than provide a review through prose I figured it might be better for both of us if I mangled the patches directly.
I've attacked two things. The first is I found the series hard to review due to the way the patches were split, as the patches went from trivial to huge (and complex) in a fairly short step:
Quoted 7 lines
Edward A. James (5):
Revert "hwmon: Add Power8 OCC hwmon driver"
drivers: Add hwmon occ driver framework
drivers: hwmon OCC scom bus operations
drivers: Add hwmon OCC version specific functions
drivers: OCC hwmon driver and sysfs
So I have reworked them into what is now 8 patches (see below) and tried to tell a bit more of a story with them (hopefully I succeeded!) Second, I tried my hand at reworking the layering as mentioned above, such that hardware interaction is split from sysfs, and that the SCOM transport and sensor configuration is decoupled from the data parsing. You largely had all of these in-place already, I just cut and pasted code around a bit.
Please review the patches and provide feedback! I'd like to hear arguments for or against both of our approaches. Note though that I've only tested that these patches compile, I absolutely have not done any further testing.
Joel: Any chance you could chime in with an architectural review?
When the dust has settled on the bigger issues we can start to look at the finer details of the APIs (there are some bugs, oddities and complexities that I would like to address before they are applied to openbmc/linux).
Cheers,
Andrew
Andrew Jeffery (8):
hwmon: Add core On-Chip Controller support for POWER CPUs
hwmon: occ: Add sysfs interface
hwmon: occ: Add I2C SCOM transport implementation
hwmon: occ: Add callbacks for parsing P8 OCC datastructures
hwmon: occ: Add hwmon implementation for the P8 OCC
arm: aspeed: dt: Fix OCC compatible strings
hwmon: occ: Add callbacks for parsing P9 OCC datastructures
wip: hwmon: occ: Add sketch of the hwmon implementation for the P9 OCC
Edward A. James (1):
Revert "hwmon: Add Power8 OCC hwmon driver"
.../devicetree/bindings/i2c/i2c-ibm-occ.txt | 13 - arch/arm/boot/dts/aspeed-bmc-opp-barreleye.dts | 4 +- arch/arm/boot/dts/aspeed-bmc-opp-firestone.dts | 4 +- arch/arm/boot/dts/aspeed-bmc-opp-garrison.dts | 4 +- arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts | 2 +- drivers/hwmon/Kconfig | 13 +- drivers/hwmon/Makefile | 2 +- drivers/hwmon/occ/Kconfig | 38 + drivers/hwmon/occ/Makefile | 3 + drivers/hwmon/occ/occ.c | 494 ++++++++ drivers/hwmon/occ/occ.h | 79 ++ drivers/hwmon/occ/occ_p8.c | 219 ++++ drivers/hwmon/occ/occ_p8.h | 30 + drivers/hwmon/occ/occ_p8_i2c.c | 133 +++ drivers/hwmon/occ/occ_p9.c | 261 ++++ drivers/hwmon/occ/occ_p9.h | 30 + drivers/hwmon/occ/occ_p9_fsi.c | 93 ++ drivers/hwmon/occ/occ_scom_i2c.c | 68 ++ drivers/hwmon/occ/occ_scom_i2c.h | 20 + drivers/hwmon/occ/occ_sysfs.c | 498 ++++++++ drivers/hwmon/occ/occ_sysfs.h | 51 + drivers/hwmon/occ/scom.h | 50 + drivers/hwmon/power8_occ_i2c.c | 1254 -------------------- 23 files changed, 2076 insertions(+), 1287 deletions(-) delete mode 100644 Documentation/devicetree/bindings/i2c/i2c-ibm-occ.txt create mode 100644 drivers/hwmon/occ/Kconfig create mode 100644 drivers/hwmon/occ/Makefile create mode 100644 drivers/hwmon/occ/occ.c create mode 100644 drivers/hwmon/occ/occ.h create mode 100644 drivers/hwmon/occ/occ_p8.c create mode 100644 drivers/hwmon/occ/occ_p8.h create mode 100644 drivers/hwmon/occ/occ_p8_i2c.c create mode 100644 drivers/hwmon/occ/occ_p9.c create mode 100644 drivers/hwmon/occ/occ_p9.h create mode 100644 drivers/hwmon/occ/occ_p9_fsi.c create mode 100644 drivers/hwmon/occ/occ_scom_i2c.c create mode 100644 drivers/hwmon/occ/occ_scom_i2c.h create mode 100644 drivers/hwmon/occ/occ_sysfs.c create mode 100644 drivers/hwmon/occ/occ_sysfs.h create mode 100644 drivers/hwmon/occ/scom.h delete mode 100644 drivers/hwmon/power8_occ_i2c.c
Signature · 1 line
2.9.3
RFC PATCH 1/9 Revert "hwmon: Add Power8 OCC hwmon driver"
From: "Edward A. James" <[email protected]>
Remove old P8 OCC driver.
--- .../devicetree/bindings/i2c/i2c-ibm-occ.txt | 13 - drivers/hwmon/Kconfig | 13 - drivers/hwmon/Makefile | 1 - drivers/hwmon/power8_occ_i2c.c | 1254 -------------------- 4 files changed, 1281 deletions(-) delete mode 100644 Documentation/devicetree/bindings/i2c/i2c-ibm-occ.txt delete mode 100644 drivers/hwmon/power8_occ_i2c.c
Documentation/devicetree/bindings/i2c/i2c-ibm-occ.txt deleted +0 -13
@@ -1,13 +0,0 @@ -HWMON i2c driver for IBM POWER CPU OCC (On Chip Controller) - -Required properties: - - compatible: must be "ibm,power8-occ-i2c" - - reg: physical address - -Example: -i2c3: i2c-bus@100 { - occ@50 { - compatible = "ibm,occ-i2c"; - reg = <0x50>; - }; -};
drivers/hwmon/Kconfig +0 -13
@@ -1226,19 +1226,6 @@ config SENSORS_NSA320 This driver can also be built as a module. If so, the module will be called nsa320-hwmon. -config SENSORS_POWER8_OCC_I2C - tristate "Power8 On Chip Controller i2c driver" - depends on I2C - help - If you say yes here you get support to monitor Power8 CPU - sensors via the On Chip Controller (OCC) over the i2c bus. - - Generally this is used by management controllers such as a BMC - on an OpenPower system. - - This driver can also be built as a module. If so, the module - will be called power8_occ_i2c. - config SENSORS_PCF8591 tristate "Philips PCF8591 ADC/DAC" depends on I2C
drivers/hwmon/Makefile +0 -1
@@ -128,7 +128,6 @@ obj-$(CONFIG_SENSORS_NCT7802) += nct7802.o obj-$(CONFIG_SENSORS_NCT7904) += nct7904.o obj-$(CONFIG_SENSORS_NSA320) += nsa320-hwmon.o obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o -obj-$(CONFIG_SENSORS_POWER8_OCC_I2C) += power8_occ_i2c.o obj-$(CONFIG_SENSORS_PC87360) += pc87360.o obj-$(CONFIG_SENSORS_PC87427) += pc87427.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
drivers/hwmon/power8_occ_i2c.c deleted +0 -1254
1,254 lines not on this page · raw message
Signature · 1 line
2.9.3
RFC PATCH 2/9 hwmon: Add core On-Chip Controller support for POWER CPUs
In reply to Andrew JefferyThe On-Chip Controller (OCC) exposes frequency and temperature sensor information along with power draw measurement and capping for POWER chips. The information is gathered by SCOM reads and writes over a transport of choice, and structured in a flexible fashion to accomodate differences in sensors across designs.
Add core support for querying and parsing the data structures provided by the OCC via SCOMs.
--- drivers/hwmon/Kconfig | 2 + drivers/hwmon/Makefile | 1 + drivers/hwmon/occ/Kconfig | 15 ++ drivers/hwmon/occ/Makefile | 1 + drivers/hwmon/occ/occ.c | 494 +++++++++++++++++++++++++++++++++++++++++++++ drivers/hwmon/occ/occ.h | 79 ++++++++ drivers/hwmon/occ/scom.h | 50 +++++ 7 files changed, 642 insertions(+) create mode 100644 drivers/hwmon/occ/Kconfig create mode 100644 drivers/hwmon/occ/Makefile create mode 100644 drivers/hwmon/occ/occ.c create mode 100644 drivers/hwmon/occ/occ.h create mode 100644 drivers/hwmon/occ/scom.h
drivers/hwmon/Kconfig +2 -0
@@ -1226,6 +1226,8 @@ config SENSORS_NSA320 This driver can also be built as a module. If so, the module will be called nsa320-hwmon. +source drivers/hwmon/occ/Kconfig + config SENSORS_PCF8591 tristate "Philips PCF8591 ADC/DAC" depends on I2C
drivers/hwmon/Makefile +1 -0
@@ -165,6 +165,7 @@ obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o obj-$(CONFIG_PMBUS) += pmbus/ +obj-$(CONFIG_SENSORS_PPC_OCC) += occ/ ccflags-$(CONFIG_HWMON_DEBUG_CHIP) := -DDEBUG
drivers/hwmon/occ/Kconfig new file +15 -0
@@ -0,0 +1,15 @@ +# +# On Chip Controller configuration +# + +menuconfig SENSORS_PPC_OCC + bool "PPC On-Chip Controller" + help + If you say yes here you get support to monitor Power CPU + sensors via the On-Chip Controller (OCC). + + Generally this is used by management controllers such as a BMC + on an OpenPower system. + + This driver can also be built as a module. If so, the module + will be called occ.
drivers/hwmon/occ/Makefile new file +1 -0
@@ -0,0 +1 @@ +obj-$(CONFIG_SENSORS_PPC_OCC) += occ.o
drivers/hwmon/occ/occ.c new file +494 -0
494 lines not on this page · raw message
drivers/hwmon/occ/occ.h new file +79 -0
79 lines not on this page · raw message
drivers/hwmon/occ/scom.h new file +50 -0
50 lines not on this page · raw message
Signature · 1 line
2.9.3
RFC PATCH 3/9 hwmon: occ: Add sysfs interface
In reply to Andrew JefferyAdd a generic mechanism to expose the sensors provided by the OCC in sysfs.
--- drivers/hwmon/occ/Makefile | 2 +- drivers/hwmon/occ/occ_sysfs.c | 498 ++++++++++++++++++++++++++++++++++++++++++ drivers/hwmon/occ/occ_sysfs.h | 51 +++++ 3 files changed, 550 insertions(+), 1 deletion(-) create mode 100644 drivers/hwmon/occ/occ_sysfs.c create mode 100644 drivers/hwmon/occ/occ_sysfs.h
drivers/hwmon/occ/Makefile +1 -1
@@ -1 +1 @@ -obj-$(CONFIG_SENSORS_PPC_OCC) += occ.o +obj-$(CONFIG_SENSORS_PPC_OCC) += occ.o occ_sysfs.o
drivers/hwmon/occ/occ_sysfs.c new file +498 -0
498 lines not on this page · raw message
drivers/hwmon/occ/occ_sysfs.h new file +51 -0
51 lines not on this page · raw message
Signature · 1 line
2.9.3
RFC PATCH 4/9 hwmon: occ: Add I2C SCOM transport implementation
In reply to Andrew JefferyThe BMC queries the OCC on POWER8 chips with SCOMs over I2C.
--- drivers/hwmon/occ/occ_scom_i2c.c | 68 ++++++++++++++++++++++++++++++++++++++++ drivers/hwmon/occ/occ_scom_i2c.h | 20 ++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 drivers/hwmon/occ/occ_scom_i2c.c create mode 100644 drivers/hwmon/occ/occ_scom_i2c.h
drivers/hwmon/occ/occ_scom_i2c.c new file +68 -0
@@ -0,0 +1,68 @@ +/* +* occ_i2c.c - hwmon OCC driver +* +* This file contains the i2c layer for accessing the OCC over i2c bus. +* +* Copyright 2016 IBM Corp. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/i2c.h> +#include <linux/kernel.h> +#include <linux/module.h> + +#include "scom.h" +#include "occ_scom_i2c.h" + +#define OCC_I2C_NAME "occ-p8-i2c" + +int occ_i2c_getscom (void *bus,u32 address,u8 *data,size_t offset) +{ +ssize_t rc; +u64 buf; +struct i2c_client *client = bus; + + rc =i2c_master_send (client, (const char *)&address,sizeof (u32)); +if (rc !=sizeof (u32)) +return -SCOM_WRITE_ERROR ; + + rc =i2c_master_recv (client, (char *)&buf,sizeof (u64)); +if (rc !=sizeof (u64)) +return -SCOM_READ_ERROR ; + + *((u64 *)&data[offset]) =be64_to_cpu (buf); + +return 0 ; +} +EXPORT_SYMBOL (occ_i2c_getscom); + +int occ_i2c_putscom (void *bus,u32 address,u32 data0,u32 data1) +{ +u32 buf[3 ]; +ssize_t rc; +struct i2c_client *client = bus; + + buf[0 ] = address; + buf[1 ] = data1; + buf[2 ] = data0; + + rc =i2c_master_send (client, (const char *)buf,sizeof (u32) *3 ); +if (rc !=sizeof (u32) *3 ) +return -SCOM_WRITE_ERROR ; + +return 0 ; +} +EXPORT_SYMBOL (occ_i2c_putscom); + +MODULE_AUTHOR ("Eddie James <[email protected]>" ); +MODULE_DESCRIPTION ("I2C OCC SCOM transport" ); +MODULE_LICENSE ("GPL" );
drivers/hwmon/occ/occ_scom_i2c.h new file +20 -0
@@ -0,0 +1,20 @@ +/* +* occ_i2c.c - hwmon OCC driver +* +* This file contains the i2c layer for accessing the OCC over i2c bus. +* +* Copyright 2016 IBM Corp. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +int occ_i2c_getscom (void *bus,u32 address,u8 *data,size_t offset); +int occ_i2c_putscom (void *bus,u32 address,u32 data0,u32 data1);
Signature · 1 line
2.9.3
Re: [RFC PATCH linux 4/9] hwmon: occ: Add I2C SCOM transport implementation
Hi Andrew,
Just a general comment on this one. I'm not sure it's worth having an extra layer just to isolate these functions from the p8_i2c_getscom/putscom. Those just do the address shift for P8. But there's no situation where i2c is used that's not on the P8. So this seems like unnecessary complexity to me. I'm not sure, just a thought.
Thanks,
Eddie
Quoted 113 lines · Andrew Jeffery
The BMC queries the OCC on POWER8 chips with SCOMs over I2C.
Signed-off-by Andrew Jeffery <[email protected]>--- drivers/hwmon/occ/occ_scom_i2c.c | 68 ++++++++++++++++++++++++++++++++++++++++ drivers/hwmon/occ/occ_scom_i2c.h | 20 ++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 drivers/hwmon/occ/occ_scom_i2c.c create mode 100644 drivers/hwmon/occ/occ_scom_i2c.hdrivers/hwmon/occ/occ_scom_i2c.c new file +68
-0@@ -0,0 +1,68 @@ +/* +* occ_i2c.c - hwmon OCC driver +* +* This file contains the i2c layer for accessing the OCC over i2c bus. +* +* Copyright 2016 IBM Corp. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/i2c.h> +#include <linux/kernel.h> +#include <linux/module.h> + +#include "scom.h" +#include "occ_scom_i2c.h" + +#define OCC_I2C_NAME "occ-p8-i2c" + +int occ_i2c_getscom (void *bus,u32 address,u8 *data,size_t offset) +{ +ssize_t rc; +u64 buf; +struct i2c_client *client = bus; + + rc =i2c_master_send (client, (const char *)&address,sizeof (u32)); +if (rc !=sizeof (u32)) +return -SCOM_WRITE_ERROR ; + + rc =i2c_master_recv (client, (char *)&buf,sizeof (u64)); +if (rc !=sizeof (u64)) +return -SCOM_READ_ERROR ; + + *((u64 *)&data[offset]) =be64_to_cpu (buf); + +return 0 ; +} +EXPORT_SYMBOL (occ_i2c_getscom); + +int occ_i2c_putscom (void *bus,u32 address,u32 data0,u32 data1) +{ +u32 buf[3 ]; +ssize_t rc; +struct i2c_client *client = bus; + + buf[0 ] = address; + buf[1 ] = data1; + buf[2 ] = data0; + + rc =i2c_master_send (client, (const char *)buf,sizeof (u32) *3 ); +if (rc !=sizeof (u32) *3 ) +return -SCOM_WRITE_ERROR ; + +return 0 ; +} +EXPORT_SYMBOL (occ_i2c_putscom); + +MODULE_AUTHOR ("Eddie James <[email protected]>" ); +MODULE_DESCRIPTION ("I2C OCC SCOM transport" ); +MODULE_LICENSE ("GPL" );drivers/hwmon/occ/occ_scom_i2c.h new file +20
-1@@ -0,0 +1,20 @@ +/* +* occ_i2c.c - hwmon OCC driver +* +* This file contains the i2c layer for accessing the OCC over i2c bus. +* +* Copyright 2016 IBM Corp. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +int occ_i2c_getscom (void *bus,u32 address,u8 *data,size_t offset); +int occ_i2c_putscom (void *bus,u32 address,u32 data0,u32 data1); --2.9.3
Re: [RFC PATCH linux 4/9] hwmon: occ: Add I2C SCOM transport implementation
Quoted 7 lines · Eddie James
Hi Andrew,
Just a general comment on this one. I'm not sure it's worth having an extra layer just to isolate these functions from the p8_i2c_getscom/putscom. Those just do the address shift for P8. But there's no situation where i2c is used that's not on the P8. So this seems like unnecessary complexity to me. I'm not sure, just a thought.
My perspective is that baking P8 knowledge into the I2C SCOM operations
makes the code surprising. Maybe renaming the functions is enough,
something like p8_occ_getscom(). To me it doesn't seem like much cost in complexity to separate the transport from implementation-specific quirks with the addressing, and gaining a general approach in the process.
Maybe Joel can weigh in here?
Andrew
Quoted 118 lines
Thanks,
EddieQuoted 114 lines · Andrew Jeffery
The BMC queries the OCC on POWER8 chips with SCOMs over I2C.
Quoted 1 line
Quoted 1 line
Signed-off-by Andrew Jeffery <[email protected]>---
drivers/hwmon/occ/occ_scom_i2c.c | 68 ++++++++++++++++++++++++++++++++++++++++drivers/hwmon/occ/occ_scom_i2c.h| 20 ++++++++++++2 files changed, 88 insertions(+)create mode 100644
drivers/hwmon/occ/occ_scom_i2c.ccreate mode 100644drivers/hwmon/occ/occ_scom_i2c.hdrivers/hwmon/occ/occ_scom_i2c.c new file +65
-0@@ -0,0 +1,68 @@ +/* +* occ_i2c.c - hwmon OCC driver +* +* This file contains the i2c layer for accessing the OCC over i2c bus. +* +* Copyright 2016 IBM Corp. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/i2c.h> +#include <linux/kernel.h> +#include <linux/module.h> + +#include "scom.h" +#include "occ_scom_i2c.h" + +#define OCC_I2C_NAME "occ-p8-i2c" + +int occ_i2c_getscom (void *bus,u32 address,u8 *data,size_t offset) +{ + ssize_t rc; + u64 buf; + struct i2c_client *client = bus; + + rc = i2c_master_send(client, (const char *)&address, sizeof(u32)); + if (rc != sizeof(u32)) + return -SCOM_WRITE_ERROR; + + rc = i2c_master_recv(client, (char *)&buf, sizeof(u64)); + if (rc != sizeof(u64)) + return -SCOM_READ_ERROR; + + *((u64 *)&data[offset]) = be64_to_cpu(buf); + + return 0; +} +EXPORT_SYMBOL (occ_i2c_getscom); + +int occ_i2c_putscom (void *bus,u32 address,u32 data0,u32 data1) +{ + u32 buf[3]; + ssize_t rc; + struct i2c_client *client = bus; + + buf[0] = address; + buf[1] = data1; + buf[2] = data0; + + rc = i2c_master_send(client, (const char *)buf, sizeof(u32) * 3); + if (rc != sizeof(u32) * 3) + return -SCOM_WRITE_ERROR; + + return 0; +} +EXPORT_SYMBOL (occ_i2c_putscom); +Quoted 1 line
Quoted 1 line
+MODULE_AUTHOR("Eddie James <[email protected]>");
drivers/hwmon/occ/occ_scom_i2c.c new file +2
-0+MODULE_DESCRIPTION ("I2C OCC SCOM transport" ); +MODULE_LICENSE ("GPL" );drivers/hwmon/occ/occ_scom_i2c.h new file +20
-1@@ -0,0 +1,20 @@ +/* +* occ_i2c.c - hwmon OCC driver +* +* This file contains the i2c layer for accessing the OCC over i2c bus. +* +* Copyright 2016 IBM Corp. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +int occ_i2c_getscom (void *bus,u32 address,u8 *data,size_t offset); +int occ_i2c_putscom (void *bus,u32 address,u32 data0,u32 data1); --2.9.3
RFC PATCH 5/9 hwmon: occ: Add callbacks for parsing P8 OCC datastructures
In reply to Andrew Jeffery--- drivers/hwmon/occ/occ_p8.c | 219 +++++++++++++++++++++++++++++++++++++++++++++ drivers/hwmon/occ/occ_p8.h | 30 +++++++ 2 files changed, 249 insertions(+) create mode 100644 drivers/hwmon/occ/occ_p8.c create mode 100644 drivers/hwmon/occ/occ_p8.h
drivers/hwmon/occ/occ_p8.c new file +219 -0
@@ -0,0 +1,219 @@ +/* +* p8.c - OCC hwmon driver +* +* This file contains the Power8-specific methods and data structures for +* the OCC hwmon driver. +* +* Copyright 2016 IBM Corp. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/err.h> +#include <linux/of.h> +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/platform_device.h> + +#include "occ.h" +#include "occ_p8.h" + +/* P8 OCC sensor data format */ +struct occ_sensor_p8 { +u16 sensor_id; +u16 value; +}; + +struct power_sensor_p8 { +u16 sensor_id; +u32 update_tag; +u32 accumulator; +u16 value; +}; + +struct caps_sensor_p8 { +u16 curr_powercap; +u16 curr_powerreading; +u16 norm_powercap; +u16 max_powercap; +u16 min_powercap; +u16 user_powerlimit; +}; + +void p8_parse_sensor (u8 *data,void *sensor,int sensor_type,int off, +int snum) +{ +switch (sensor_type) { +case FREQ : +case TEMP : + { +struct occ_sensor_p8 *os = + &(((struct occ_sensor_p8 *)sensor)[snum]); + os->sensor_id = +be16_to_cpup ((const __be16 *)&data[off]); + os->value = +be16_to_cpup ((const __be16 *)&data[off +2 ]); + } +break ; +case POWER : + { +struct power_sensor_p8 *ps = + &(((struct power_sensor_p8 *)sensor)[snum]); + ps->sensor_id = +be16_to_cpup ((const __be16 *)&data[off]); + ps->update_tag = +be32_to_cpup ((const __be32 *)&data[off +2 ]); + ps->accumulator = +be32_to_cpup ((const __be32 *)&data[off +6 ]); + ps->value = +be16_to_cpup ((const __be16 *)&data[off +10 ]); + } +break ; +case CAPS : + { +struct caps_sensor_p8 *cs = + &(((struct caps_sensor_p8 *)sensor)[snum]); + cs->curr_powercap = +be16_to_cpup ((const __be16 *)&data[off]); + cs->curr_powerreading = +be16_to_cpup ((const __be16 *)&data[off +2 ]); + cs->norm_powercap = +be16_to_cpup ((const __be16 *)&data[off +4 ]); + cs->max_powercap = +be16_to_cpup ((const __be16 *)&data[off +6 ]); + cs->min_powercap = +be16_to_cpup ((const __be16 *)&data[off +8 ]); + cs->user_powerlimit = +be16_to_cpup ((const __be16 *)&data[off +10 ]); + } +break ; + }; +} + +void *p8_alloc_sensor (int sensor_type,int num_sensors) +{ +switch (sensor_type) { +case FREQ : +case TEMP : +return kcalloc (num_sensors, +sizeof (struct occ_sensor_p8 ), +GFP_KERNEL ); +case POWER : +return kcalloc (num_sensors, +sizeof (struct power_sensor_p8 ), +GFP_KERNEL ); +case CAPS : +return kcalloc (num_sensors, +sizeof (struct caps_sensor_p8 ), +GFP_KERNEL ); +default : +return NULL ; + } +} + +int p8_get_sensor_value (struct occ *driver,int sensor_type,int snum) +{ +void *sensor; + +if (sensor_type ==CAPS ) +return -1 ; + + sensor =occ_get_sensor (driver, sensor_type); +if (!sensor) +return -1 ; + +switch (sensor_type) { +case FREQ : +case TEMP : +return ((struct occ_sensor_p8 *)sensor)[snum].value; +case POWER : +return ((struct power_sensor_p8 *)sensor)[snum].value; +default : +return -1 ; + } +} + +int p8_get_sensor_id (struct occ *driver,int sensor_type,int snum) +{ +void *sensor; +int i = snum; + +if (sensor_type ==CAPS ) +return -1 ; + + sensor =occ_get_sensor (driver, sensor_type); +if (!sensor) +return -1 ; + +switch (sensor_type) { +case FREQ : +case TEMP : +return ((struct occ_sensor_p8 *)sensor)[i].sensor_id; +case POWER : +return ((struct power_sensor_p8 *)sensor)[i].sensor_id; +default : +return -1 ; + } +} + +int p8_get_caps_value (void *sensor,int snum,int caps_field) +{ +struct caps_sensor_p8 *caps_sensor = sensor; + +switch (caps_field) { +case 0 : +return caps_sensor[snum].curr_powercap; +case 1 : +return caps_sensor[snum].curr_powerreading; +case 2 : +return caps_sensor[snum].norm_powercap; +case 3 : +return caps_sensor[snum].max_powercap; +case 4 : +return caps_sensor[snum].min_powercap; +case 5 : +return caps_sensor[snum].user_powerlimit; +default : +return -1 ; + } +} + +static const struct occ_ops p8_ops = { + .parse_sensor = p8_parse_sensor, + .alloc_sensor = p8_alloc_sensor, + .get_sensor_value = p8_get_sensor_value, + .get_sensor_id = p8_get_sensor_id, + .get_caps_value = p8_get_caps_value, +}; + +static const struct occ_config p8_config = { + .command_addr =0xFFFF6000 , + .response_addr =0xFFFF7000 , +}; + +struct occ *occ_p8_start (struct device *dev,void *bus,struct occ_bus_ops bus_ops) +{ +return occ_start (dev, bus, bus_ops, p8_ops, p8_config); +} +EXPORT_SYMBOL (occ_p8_start); + +int occ_p8_stop (struct occ *occ) +{ +return occ_stop (occ); +} +EXPORT_SYMBOL (occ_p8_stop); + +MODULE_AUTHOR ("Eddie James <[email protected]>" ); +MODULE_DESCRIPTION ("P8 OCC sensors" ); +MODULE_LICENSE ("GPL" );
drivers/hwmon/occ/occ_p8.h new file +30 -0
@@ -0,0 +1,30 @@ +/* +* p8.h - OCC hwmon driver +* +* This file contains Power8-specific function prototypes +* +* Copyright 2016 IBM Corp. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#ifndef __P8_H__ +#define __P8_H__ + +#include "scom.h" + +struct device ; + +struct occ *occ_p8_start (struct device *dev,void *bus, +struct occ_bus_ops bus_ops); +int occ_p8_stop (struct occ *occ); + +#endif /* __P8_H__ */
Signature · 1 line
2.9.3
RFC PATCH 6/9 hwmon: occ: Add hwmon implementation for the P8 OCC
In reply to Andrew Jeffery--- drivers/hwmon/occ/Kconfig | 14 +++++ drivers/hwmon/occ/Makefile | 1 + drivers/hwmon/occ/occ_p8_i2c.c | 133 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 drivers/hwmon/occ/occ_p8_i2c.c
drivers/hwmon/occ/Kconfig +14 -0
@@ -13,3 +13,17 @@ menuconfig SENSORS_PPC_OCC This driver can also be built as a module. If so, the module will be called occ. + +if SENSORS_PPC_OCC + +config SENSORS_PPC_OCC_P8_I2C + tristate "POWER8 OCC hwmon support" + depends on I2C + help + Provide a hwmon sysfs interface for the POWER8 On-Chip Controller, + exposing temperature, frequency and power measurements. + + This driver can also be built as a module. If so, the module will be + called occ-p8-i2c. + +endif
drivers/hwmon/occ/Makefile +1 -0
@@ -1 +1,2 @@ obj-$(CONFIG_SENSORS_PPC_OCC) += occ.o occ_sysfs.o +obj-$(CONFIG_SENSORS_PPC_OCC_P8_I2C) += occ_scom_i2c.o occ_p8.o occ_p8_i2c.o
drivers/hwmon/occ/occ_p8_i2c.c new file +133 -0
133 lines not on this page · raw message
Signature · 1 line
2.9.3
Re: [RFC PATCH linux 6/9] hwmon: occ: Add hwmon implementation for the P8 OCC
Hi Andrew,
One comment on this one.
Thanks,
Eddie
Quoted 76 lines · Andrew Jeffery
Signed-off-by Andrew Jeffery <[email protected]>--- drivers/hwmon/occ/Kconfig | 14 +++++ drivers/hwmon/occ/Makefile | 1 + drivers/hwmon/occ/occ_p8_i2c.c | 133 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 drivers/hwmon/occ/occ_p8_i2c.cdrivers/hwmon/occ/Kconfig +14
-0@@ -13,3 +13,17 @@ menuconfig SENSORS_PPC_OCC This driver can also be built as a module. If so, the module will be called occ. + +if SENSORS_PPC_OCC + +config SENSORS_PPC_OCC_P8_I2C + tristate "POWER8 OCC hwmon support" + depends on I2C + help + Provide a hwmon sysfs interface for the POWER8 On-Chip Controller, + exposing temperature, frequency and power measurements. + + This driver can also be built as a module. If so, the module will be + called occ-p8-i2c. + +endifdrivers/hwmon/occ/Makefile +1
-0@@ -1 +1,2 @@ obj-$(CONFIG_SENSORS_PPC_OCC) += occ.o occ_sysfs.o +obj-$(CONFIG_SENSORS_PPC_OCC_P8_I2C) += occ_scom_i2c.o occ_p8.o occ_p8_i2c.odrivers/hwmon/occ/occ_p8_i2c.c new file +33
-0@@ -0,0 +1,133 @@ +/* +* occ_p8_i2c.c - hwmon OCC driver +* +* This file contains the i2c layer for accessing the OCC over i2c bus. +* +* Copyright 2016 IBM Corp. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/err.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/err.h> +#include <linux/of.h> +#include <linux/kernel.h> +#include <linux/device.h> + +#include "scom.h" +#include "occ_scom_i2c.h" +#include "occ_p8.h" +#include "occ_sysfs.h" +
drivers/hwmon/occ/occ_p8_i2c.c line 43
Quoted 10 lines
drivers/hwmon/occ/occ_p8_i2c.c new file +10
-0+#define OCC_I2C_NAME "occ-p8-i2c" + +static char *caps_sensor_names[] = { +"curr_powercap" , +"curr_powerreading" , +"norm_powercap" , +"max_powercap" , +"min_powercap" , +"user_powerlimit" +};
Does it make more sense to define this in the P8 callbacks code?
Quoted 16 lines
drivers/hwmon/occ/occ_p8_i2c.c new file +16
-0+ +int p8_i2c_getscom (void *bus,u32 address,u8 *data,size_t offset) +{ +/* P8 i2c slave requires address to be shifted by 1 */ + address = address <<1 ; + +return occ_i2c_getscom (bus, address, data, offset); +} + +int p8_i2c_putscom (void *bus,u32 address,u32 data0,u32 data1) +{ +/* P8 i2c slave requires address to be shifted by 1 */ + address = address <<1 ; + +return occ_i2c_putscom (bus, address, data0, data1); +}
drivers/hwmon/occ/occ_p8_i2c.c line 69
Quoted 10 lines
drivers/hwmon/occ/occ_p8_i2c.c new file +10
-0+ +static struct occ_bus_ops p8_bus_ops = { + .getscom = p8_i2c_getscom, + .putscom = p8_i2c_putscom, +}; + +static struct occ_sysfs_config p8_sysfs_config = { + .num_caps_fields =ARRAY_SIZE (caps_sensor_names), + .caps_names = caps_sensor_names, +};
Same as above for this structure.
drivers/hwmon/occ/occ_p8_i2c.c line 81
Quoted 12 lines
drivers/hwmon/occ/occ_p8_i2c.c new file +12
-0+ +static int occ_p8_probe (struct i2c_client *client, +const struct i2c_device_id *id) +{ +struct occ *occ; +struct occ_sysfs *hwmon; + + occ =occ_p8_start (&client->dev, client, p8_bus_ops); +if (IS_ERR (occ)) +return PTR_ERR (occ); + + hwmon =occ_sysfs_start (&client->dev, occ, &p8_sysfs_config);
I see why you defined those here. But I guess I don't see why occ_sysfs_config has to be separate from occ_config structure. It could be populated in occ_p8_start and then passed to occ_sysfs_start here.
Quoted 55 lines
drivers/hwmon/occ/occ_p8_i2c.c new file +52
-1+if (IS_ERR (hwmon)) +return PTR_ERR (hwmon); + +i2c_set_clientdata (client, hwmon); + +return 0 ; +} + +static int occ_p8_remove (struct i2c_client *client) +{ +return occ_p8_stop (i2c_get_clientdata (client)); +} + +/* used by old-style board info. */ +static const struct i2c_device_id occ_ids[] = { + {OCC_I2C_NAME ,0 }, + {} +}; +MODULE_DEVICE_TABLE (i2c, occ_ids); + +/* used by device table */ +static const struct of_device_id occ_of_match[] = { + { .compatible ="ibm,occ-p8-i2c" }, + {} +}; +MODULE_DEVICE_TABLE (of, occ_of_match); + +/* +* i2c-core uses i2c-detect() to detect device in below address list. +* If exists, address will be assigned to client. +* It is also possible to read address from device table. +*/ +static const unsigned short normal_i2c[] = {0x50 ,0x51 ,I2C_CLIENT_END }; + +static struct i2c_driver occ_p8_driver = { + .class =I2C_CLASS_HWMON , + .driver = { + .name =OCC_I2C_NAME , + .pm =NULL , + .of_match_table = occ_of_match, + }, + .probe = occ_p8_probe, + .remove = occ_p8_remove, + .id_table = occ_ids, + .address_list = normal_i2c, +}; + +module_i2c_driver (occ_p8_driver); + +MODULE_AUTHOR ("Eddie James <[email protected]>" ); +MODULE_DESCRIPTION ("BMC P8 OCC hwmon driver" ); +MODULE_LICENSE ("GPL" ); --2.9.3
Re: [RFC PATCH linux 6/9] hwmon: occ: Add hwmon implementation for the P8 OCC
Quoted 14 lines · Eddie James
drivers/hwmon/occ/occ_p8_i2c.c
Quoted 12 lines
drivers/hwmon/occ/occ_p8_i2c.c new file +12
-0+ +static int occ_p8_probe (struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct occ *occ; + struct occ_sysfs *hwmon; + + occ = occ_p8_start(&client->dev, client, p8_bus_ops); + if (IS_ERR(occ)) + return PTR_ERR(occ); + + hwmon = occ_sysfs_start(&client->dev, occ,
&p8_sysfs_config);
Quoted 4 lines
I see why you defined those here. But I guess I don't see why
occ_sysfs_confighas to be separate fromocc_configstructure. It could be populated inocc_p8_startand then passed toocc_sysfs_starthere.
I admit getting to this point was a little tricky, and I'm not completely satisfied by what I've come up with. Here's my reasoning:
I felt that only half of your struct occ_protocol dealt with SCOM protocol problems, specifically the command_addr and response_addr members. num_caps_fields and caps_names were only used in the sysfs code where they are relevant for interpretation of the payload, but are not in transacting SCOMs. Therefore I removed them from struct occ_protocol.
I also renamed struct occ_protocol to occ_config. I could live with either name but my feeling is it's more obvious that the consumer of the API needs to populate a struct with 'config' in its name.
Given I'd removed num_caps_fields and caps_names I had to put the information somewhere. One place might be in struct occ as I've interpreted your suggestion above. However, I was trying to keep struct occ opaque so in occ.c could fully encapsulate its behaviour. As struct occ is opaque, occ_sysfs.c has no visibility into its members and thus can't access anything we stash in it, e.g. num_caps_fields and caps_names.
That leaves us with needing some other solution, one of which I've implemented above. It achieves the goals I was outlining above and keeps the sysfs code free of any implementation specifics, at the cost of describing the information in a slightly weird spot.
An alternative might be to define struct occ_sysfs_config in occ_p8.c and add an extern to occ_p8.h. That bakes sysfs knowledge into the p8 header which to me feels more unfortunate than my current approach. Or, define say p8_caps_names and p8_num_caps in occ_p8.c and extern those in occ_p8.h and use them to define a struct occ_sysfs_config here. What do you think?
Andrew
Re: [RFC PATCH linux 6/9] hwmon: occ: Add hwmon implementation for the P8 OCC
Quoted 23 lines · Andrew Jeffery
Quoted 14 lines · Eddie James
drivers/hwmon/occ/occ_p8_i2c.c
Quoted 12 lines
drivers/hwmon/occ/occ_p8_i2c.c new file +12
-0+ +static int occ_p8_probe (struct i2c_client *client, +const struct i2c_device_id *id) +{ +struct occ *occ; +struct occ_sysfs *hwmon; + + occ =occ_p8_start (&client->dev, client, p8_bus_ops); +if (IS_ERR (occ)) +return PTR_ERR (occ); + + hwmon = occ_sysfs_start(&client->dev, occ,
&p8_sysfs_config);Quoted 4 lines
I see why you defined those here. But I guess I don't see why
occ_sysfs_confighas to be separate fromocc_configstructure. It could be populated inocc_p8_startand then passed toocc_sysfs_starthere.I admit getting to this point was a little tricky, and I'm not completely satisfied by what I've come up with. Here's my reasoning:
Quoted 6 lines
I felt that only half of your struct
occ_protocoldealt with SCOM protocol problems, specifically thecommand_addrandresponse_addrmembers.num_caps_fieldsandcaps_nameswere only used in the sysfs code where they are relevant for interpretation of the payload, but are not in transacting SCOMs. Therefore I removed them from structocc_protocol.
Makes sense.
Quoted 18 lines
I also renamed struct
occ_protocoltoocc_config. I could live with either name but my feeling is it's more obvious that the consumer of the API needs to populate a struct with 'config' in its name.Given I'd removed
num_caps_fieldsandcaps_namesI had to put the information somewhere. One place might be in struct occ as I've interpreted your suggestion above. However, I was trying to keep struct occ opaque so inocc.ccould fully encapsulate its behaviour. As struct occ is opaque,occ_sysfs.chas no visibility into its members and thus can't access anything we stash in it, e.g.num_caps_fieldsandcaps_names.That leaves us with needing some other solution, one of which I've implemented above. It achieves the goals I was outlining above and keeps the sysfs code free of any implementation specifics, at the cost of describing the information in a slightly weird spot.
Quoted 6 lines
An alternative might be to define struct
occ_sysfs_configinocc_p8.cand add an extern toocc_p8.h. That bakes sysfs knowledge into the p8 header which to me feels more unfortunate than my current approach. Or, define sayp8_caps_namesandp8_num_capsinocc_p8.cand extern those inocc_p8.hand use them to define a structocc_sysfs_confighere. What do you think?
I think your solution is fine, I was just a bit confused as to why you decided to do that. Let's stick with your solution, it's better than putting it in the headers.
Thanks,
Eddie
RFC PATCH 7/9 arm: aspeed: dt: Fix OCC compatible strings
In reply to Andrew Jeffery--- arch/arm/boot/dts/aspeed-bmc-opp-barreleye.dts | 4 ++-- arch/arm/boot/dts/aspeed-bmc-opp-firestone.dts | 4 ++-- arch/arm/boot/dts/aspeed-bmc-opp-garrison.dts | 4 ++-- arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-)
arch/arm/boot/dts/aspeed-bmc-opp-barreleye.dts +2 -2
@@ -110,12 +110,12 @@ status = "okay"; occ@50 { - compatible = "ibm,occ-i2c"; + compatible = "ibm,occ-p8-i2c"; reg = <0x50>; }; occ@51 { - compatible = "ibm,occ-i2c"; + compatible = "ibm,occ-p8-i2c"; reg = <0x51>; }; };
arch/arm/boot/dts/aspeed-bmc-opp-firestone.dts +2 -2
@@ -122,7 +122,7 @@ // turismo occ@50 { - compatible = "ibm,occ-i2c"; + compatible = "ibm,occ-p8-i2c"; reg = <0x50>; };
@@ -137,7 +137,7 @@ // turismo occ@50 { - compatible = "ibm,occ-i2c"; + compatible = "ibm,occ-p8-i2c"; reg = <0x50>; };
arch/arm/boot/dts/aspeed-bmc-opp-garrison.dts +2 -2
@@ -63,7 +63,7 @@ status = "okay"; occ@50 { - compatible = "ibm,occ-i2c"; + compatible = "ibm,occ-p8-i2c"; reg = <0x50>; }; };
@@ -72,7 +72,7 @@ status = "okay"; occ@50 { - compatible = "ibm,occ-i2c"; + compatible = "ibm,occ-p8-i2c"; reg = <0x50>; }; };
arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts +1 -1
@@ -127,7 +127,7 @@ status = "okay"; occ@50 { - compatible = "ibm,occ-i2c"; + compatible = "ibm,occ-p8-i2c"; reg = <0x50>; }; };
Signature · 1 line
2.9.3
RFC PATCH 8/9 hwmon: occ: Add callbacks for parsing P9 OCC datastructures
In reply to Andrew Jeffery--- drivers/hwmon/occ/occ_p9.c | 261 +++++++++++++++++++++++++++++++++++++++++++++ drivers/hwmon/occ/occ_p9.h | 30 ++++++ 2 files changed, 291 insertions(+) create mode 100644 drivers/hwmon/occ/occ_p9.c create mode 100644 drivers/hwmon/occ/occ_p9.h
drivers/hwmon/occ/occ_p9.c new file +261 -0
@@ -0,0 +1,261 @@ +/* +* p9.c - OCC hwmon driver +* +* This file contains the Power9-specific methods and data structures for +* the OCC hwmon driver. +* +* Copyright 2016 IBM Corp. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/err.h> +#include <linux/of.h> +#include <linux/kernel.h> +#include <linux/device.h> + +#include "occ.h" +#include "occ_p9.h" + +/* P9 OCC sensor data format */ +struct temp_sensor_p9 { +u32 sensor_id; +u8 fru_type; +u8 value; +}; + +struct freq_sensor_p9 { +u32 sensor_id; +u16 value; +}; + +struct power_sensor_p9 { +u32 sensor_id; +u8 function_id; +u8 apss_channel; +u16 reserved; +u32 update_tag; +u64 accumulator; +u16 value; +}; + +struct caps_sensor_p9 { +u16 curr_powercap; +u16 curr_powerreading; +u16 norm_powercap; +u16 max_powercap; +u16 min_powercap; +u16 user_powerlimit; +u8 user_powerlimit_source; +}; + +/* +static char *caps_sensor_names[] = { +"curr_powercap", +"curr_powerreading", +"norm_powercap", +"max_powercap", +"min_powercap", +"user_powerlimit", +"user_powerlimit_source" +}; +*/ + +void p9_parse_sensor (u8 *data,void *sensor,int sensor_type,int off, +int snum) +{ +switch (sensor_type) { +case FREQ : + { +struct freq_sensor_p9 *fs = + &(((struct freq_sensor_p9 *)sensor)[snum]); + fs->sensor_id = +be32_to_cpup ((const __be32 *)&data[off]); + fs->value = +be16_to_cpup ((const __be16 *)&data[off +4 ]); + } +break ; +case TEMP : + { +struct temp_sensor_p9 *ts = + &(((struct temp_sensor_p9 *)sensor)[snum]); + ts->sensor_id = +be32_to_cpup ((const __be32 *)&data[off]); + ts->fru_type = data[off +4 ]; + ts->value = data[off +5 ]; + } +break ; +case POWER : + { +struct power_sensor_p9 *ps = + &(((struct power_sensor_p9 *)sensor)[snum]); + ps->sensor_id = +be32_to_cpup ((const __be32 *)&data[off]); + ps->function_id = data[off +4 ]; + ps->apss_channel = data[off +5 ]; +/* two bytes reserved */ + ps->update_tag = +be32_to_cpup ((const __be32 *)&data[off +8 ]); + ps->accumulator = +be64_to_cpup ((const __be64 *)&data[off +12 ]); + ps->value = +be16_to_cpup ((const __be16 *)&data[off +20 ]); + } +break ; +case CAPS : + { +struct caps_sensor_p9 *cs = + &(((struct caps_sensor_p9 *)sensor)[snum]); + cs->curr_powercap = +be16_to_cpup ((const __be16 *)&data[off]); + cs->curr_powerreading = +be16_to_cpup ((const __be16 *)&data[off +2 ]); + cs->norm_powercap = +be16_to_cpup ((const __be16 *)&data[off +4 ]); + cs->max_powercap = +be16_to_cpup ((const __be16 *)&data[off +6 ]); + cs->min_powercap = +be16_to_cpup ((const __be16 *)&data[off +8 ]); + cs->user_powerlimit = +be16_to_cpup ((const __be16 *)&data[off +10 ]); + cs->user_powerlimit_source = data[off +12 ]; + } +break ; + }; +} + +void *p9_alloc_sensor (int sensor_type,int num_sensors) +{ +switch (sensor_type) { +case FREQ : +return kcalloc (num_sensors, +sizeof (struct freq_sensor_p9 ), +GFP_KERNEL ); +case TEMP : +return kcalloc (num_sensors, +sizeof (struct temp_sensor_p9 ), +GFP_KERNEL ); +case POWER : +return kcalloc (num_sensors, +sizeof (struct power_sensor_p9 ), +GFP_KERNEL ); +case CAPS : +return kcalloc (num_sensors, +sizeof (struct caps_sensor_p9 ), +GFP_KERNEL ); +default : +return NULL ; + } +} + +int p9_get_sensor_value (struct occ *driver,int sensor_type,int snum) +{ +void *sensor; + +if (sensor_type ==CAPS ) +return -1 ; + + sensor =occ_get_sensor (driver, sensor_type); +if (!sensor) +return -1 ; + +switch (sensor_type) { +case FREQ : +return ((struct freq_sensor_p9 *)sensor)[snum].value; +case TEMP : +return ((struct temp_sensor_p9 *)sensor)[snum].value; +case POWER : +return ((struct power_sensor_p9 *)sensor)[snum].value; +default : +return -1 ; + } +} + +int p9_get_sensor_id (struct occ *driver,int sensor_type,int snum) +{ +void *sensor; +int i = snum; + +if (sensor_type ==CAPS ) +return -1 ; + + sensor =occ_get_sensor (driver, sensor_type); +if (!sensor) +return -1 ; + +switch (sensor_type) { +case FREQ : +return ((struct freq_sensor_p9 *)sensor)[i].sensor_id; +case TEMP : +return ((struct temp_sensor_p9 *)sensor)[i].sensor_id; +case POWER : +return ((struct power_sensor_p9 *)sensor)[i].sensor_id; +default : +return -1 ; + } +} + +int p9_get_caps_value (void *sensor,int snum,int caps_field) +{ +struct caps_sensor_p9 *caps_sensor = sensor; + +switch (caps_field) { +case 0 : +return caps_sensor[snum].curr_powercap; +case 1 : +return caps_sensor[snum].curr_powerreading; +case 2 : +return caps_sensor[snum].norm_powercap; +case 3 : +return caps_sensor[snum].max_powercap; +case 4 : +return caps_sensor[snum].min_powercap; +case 5 : +return caps_sensor[snum].user_powerlimit; +case 6 : +return caps_sensor[snum].user_powerlimit_source; +default : +return -1 ; + } +} +static const struct occ_ops p9_ops = { + .parse_sensor = p9_parse_sensor, + .alloc_sensor = p9_alloc_sensor, + .get_sensor_value = p9_get_sensor_value, + .get_sensor_id = p9_get_sensor_id, + .get_caps_value = p9_get_caps_value, +}; + +static const struct occ_config p9_config = { + .command_addr =0xFFFBE000 , + .response_addr =0xFFFBF000 , +}; + +struct occ *occ_p9_start (struct device *dev,void *bus, +struct occ_bus_ops bus_ops) +{ +return occ_start (dev, bus, bus_ops, p9_ops, p9_config); +} +EXPORT_SYMBOL (occ_p9_start); + +int occ_p9_stop (struct occ *occ) +{ +return occ_stop (occ); +} +EXPORT_SYMBOL (occ_p9_stop); + +MODULE_AUTHOR ("Eddie James <[email protected]>" ); +MODULE_DESCRIPTION ("P9 OCC sensors" ); +MODULE_LICENSE ("GPL" );
drivers/hwmon/occ/occ_p9.h new file +30 -0
@@ -0,0 +1,30 @@ +/* +* p9.h - OCC hwmon driver +* +* This file contains Power9-specific function prototypes +* +* Copyright 2016 IBM Corp. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#ifndef __P9_H__ +#define __P9_H__ + +#include "scom.h" +#include "occ.h" + +struct device ; + +struct occ *occ_p9_start (struct device *dev,void *bus,struct occ_bus_ops bus_ops); +int occ_p9_stop (struct occ *occ); + +#endif /* __P9_H__ */
Signature · 1 line
2.9.3
RFC PATCH 9/9 wip: hwmon: occ: Add sketch of the hwmon implementation for the P9 OCC
In reply to Andrew Jeffery--- drivers/hwmon/occ/Kconfig | 9 ++++ drivers/hwmon/occ/Makefile | 1 + drivers/hwmon/occ/occ_p9_fsi.c | 93 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 drivers/hwmon/occ/occ_p9_fsi.c
drivers/hwmon/occ/Kconfig +9 -0
@@ -26,4 +26,13 @@ config SENSORS_PPC_OCC_P8_I2C This driver can also be built as a module. If so, the module will be called occ-p8-i2c. +config SENSORS_PPC_OCC_P9_FSI + tristate "POWER9 OCC hwmon support" + help + Provide a hwmon sysfs interface for the POWER9 On-Chip Controller, + exposing temperature, frequency and power measurements. + + This driver can also be built as a module. If so, the module will be + called occ-p9-fsi. + endif
drivers/hwmon/occ/Makefile +1 -0
@@ -1,2 +1,3 @@ obj-$(CONFIG_SENSORS_PPC_OCC) += occ.o occ_sysfs.o obj-$(CONFIG_SENSORS_PPC_OCC_P8_I2C) += occ_scom_i2c.o occ_p8.o occ_p8_i2c.o +obj-$(CONFIG_SENSORS_PPC_OCC_P9_FSI) += occ_p9.o occ_p9_fsi.o
drivers/hwmon/occ/occ_p9_fsi.c new file +93 -0
93 lines not on this page · raw message
Signature · 1 line
2.9.3
Re: [RFC PATCH linux 9/9] wip: hwmon: occ: Add sketch of the hwmon implementation for the P9 OCC
Hi Andrew,
Looks pretty good. Do we need to get this finalized before getting into our kernel or submitting it upstream? I don't think the SBE or FSI interfaces are nailed down, are they?
Eddie
Quoted 136 lines · Andrew Jeffery
Signed-off-by Andrew Jeffery <[email protected]>--- drivers/hwmon/occ/Kconfig | 9 ++++ drivers/hwmon/occ/Makefile | 1 + drivers/hwmon/occ/occ_p9_fsi.c | 93 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 drivers/hwmon/occ/occ_p9_fsi.cdrivers/hwmon/occ/Kconfig +9
-0@@ -26,4 +26,13 @@ config SENSORS_PPC_OCC_P8_I2C This driver can also be built as a module. If so, the module will be called occ-p8-i2c. +config SENSORS_PPC_OCC_P9_FSI + tristate "POWER9 OCC hwmon support" + help + Provide a hwmon sysfs interface for the POWER9 On-Chip Controller, + exposing temperature, frequency and power measurements. + + This driver can also be built as a module. If so, the module will be + called occ-p9-fsi. + endifdrivers/hwmon/occ/Makefile +1
-0@@ -1,2 +1,3 @@ obj-$(CONFIG_SENSORS_PPC_OCC) += occ.o occ_sysfs.o obj-$(CONFIG_SENSORS_PPC_OCC_P8_I2C) += occ_scom_i2c.o occ_p8.o occ_p8_i2c.o +obj-$(CONFIG_SENSORS_PPC_OCC_P9_FSI) += occ_p9.o occ_p9_fsi.odrivers/hwmon/occ/occ_p9_fsi.c new file +93
-1@@ -0,0 +1,93 @@ +/* +* occ_p9_fsi.c - hwmon OCC driver +* +* Copyright 2016 IBM Corp. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/err.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/err.h> +#include <linux/of.h> +#include <linux/kernel.h> +#include <linux/device.h> + +#include "scom.h" +#include "occ_p9.h" +#include "occ_sysfs.h" + +#define OCC_I2C_NAME "occ-p9-fsi" + +static char *caps_sensor_names[] = { +"curr_powercap" , +"curr_powerreading" , +"norm_powercap" , +"max_powercap" , +"min_powercap" , +"user_powerlimit" +}; + +int p9_fsi_getscom (void *bus,u32 address,u8 *data,size_t offset) +{ +return -SCOM_READ_ERROR ; +} + +int p9_fsi_putscom (void *bus,u32 address,u32 data0,u32 data1) +{ +return -SCOM_WRITE_ERROR ; +} + +static struct occ_bus_ops p9_bus_ops = { + .getscom = p9_fsi_getscom, + .putscom = p9_fsi_putscom, +}; + +static struct occ_sysfs_config p9_sysfs_config = { + .num_caps_fields =ARRAY_SIZE (caps_sensor_names), + .caps_names = caps_sensor_names, +}; + +int occ_p9_probe (struct device *dev,void *client) +{ +struct occ *occ; +struct occ_sysfs *hwmon; + + occ =occ_p9_start (dev, client, p9_bus_ops); +if (IS_ERR (occ)) +return PTR_ERR (occ); + + hwmon =occ_sysfs_start (dev, occ, &p9_sysfs_config); +if (IS_ERR (hwmon)) +return PTR_ERR (hwmon); + +return 0 ; +} + +int occ_p9_remove (void ) +{ +struct occ *occ =NULL ; + +return occ_p9_stop (occ); +} + +/* used by device table */ +static const struct of_device_id occ_of_match[] = { + { .compatible ="ibm,occ-p9-fsi" }, + {} +}; +MODULE_DEVICE_TABLE (of, occ_of_match); + +MODULE_AUTHOR ("Eddie James <[email protected]>" ); +MODULE_DESCRIPTION ("BMC P9 OCC hwmon driver" ); +MODULE_LICENSE ("GPL" ); --2.9.3
Re: [RFC PATCH linux 9/9] wip: hwmon: occ: Add sketch of the hwmon implementation for the P9 OCC
Quoted 5 lines · Eddie James
Hi Andrew,
Looks pretty good. Do we need to get this finalized before getting into our kernel or submitting it upstream? I don't think the SBE or FSI interfaces are nailed down, are they?
This patch is a complete hack only to illustrate how the abstractions would work for P9. It doesn't actually work in any way. So yes, we definitely need to finalise it before it goes anywhere.
FSI is coming together but we don't yet have it in the tree.
Andrew
Quoted 152 lines
Eddie
Quoted 147 lines · Andrew Jeffery
Signed-off-by Andrew Jeffery <[email protected]>---
drivers/hwmon/occ/Kconfig | 9 ++++
drivers/hwmon/occ/Makefile | 1 +
drivers/hwmon/occ/occ_p9_fsi.c | 93
++++++++++++++++++++++++++++++++++++++++++3 files changed, 103 insertions(+)create mode 100644
drivers/hwmon/occ/occ_p9_fsi.cdrivers/hwmon/occ/Kconfig +0
-0@@ -26,4 +26,13 @@ config SENSORS_PPC_OCC_P8_I2CThis driver can also be built as a module. If so, the module will be
called occ-p8-i2c.+config
SENSORS_PPC_OCC_P9_FSI
+ tristate "POWER9 OCC hwmon support"
+ help
+ Provide a hwmon sysfs interface for the POWER9 On-Chip Controller,
+ exposing temperature, frequency and power measurements. +
+ This driver can also be built as a module. If so, the module will be
+ called occ-p9-fsi.
+
endifdrivers/hwmon/occ/Makefile +0
-0@@ -1,2 +1,3 @@obj-$(CONFIG_SENSORS_PPC_OCC) += occ.o occ_sysfs.o obj-$(CONFIG_SENSORS_PPC_OCC_P8_I2C) += occ_scom_i2c.o occ_p8.o occ_p8_i2c.o
drivers/hwmon/occ/Makefile +1
-0+obj-$(CONFIG_SENSORS_PPC_OCC_P9_FSI) += occ_p9.o occ_p9_fsi.odrivers/hwmon/occ/occ_p9_fsi.c new file +6
-0@@ -0,0 +1,93 @@ +/* +* occ_p9_fsi.c - hwmon OCC driver +* +* Copyright 2016 IBM Corp. +* +* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */drivers/hwmon/occ/occ_p9_fsi.c new file +26
-0+ +#include <linux/err.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/err.h> +#include <linux/of.h> +#include <linux/kernel.h> +#include <linux/device.h> + +#include "scom.h" +#include "occ_p9.h" +#include "occ_sysfs.h" + +#define OCC_I2C_NAME "occ-p9-fsi" + +static char *caps_sensor_names[] = { + "curr_powercap", + "curr_powerreading", + "norm_powercap", + "max_powercap", + "min_powercap", + "user_powerlimit" +}; + +int p9_fsi_getscom(void *bus, u32 address, u8 *data, size_toffset)
drivers/hwmon/occ/occ_p9_fsi.c new file +52
-1+{ + return -SCOM_READ_ERROR; +} + +int p9_fsi_putscom (void *bus,u32 address,u32 data0,u32 data1) +{ + return -SCOM_WRITE_ERROR; +} + +static struct occ_bus_ops p9_bus_ops = { + .getscom = p9_fsi_getscom, + .putscom = p9_fsi_putscom, +}; + +static struct occ_sysfs_config p9_sysfs_config = { + .num_caps_fields = ARRAY_SIZE(caps_sensor_names), + .caps_names = caps_sensor_names, +}; + +int occ_p9_probe (struct device *dev,void *client) +{ + struct occ *occ; + struct occ_sysfs *hwmon; + + occ = occ_p9_start(dev, client, p9_bus_ops); + if (IS_ERR(occ)) + return PTR_ERR(occ); + + hwmon = occ_sysfs_start(dev, occ, &p9_sysfs_config); + if (IS_ERR(hwmon)) + return PTR_ERR(hwmon); + + return 0; +} + +int occ_p9_remove (void ) +{ + struct occ *occ = NULL; + + return occ_p9_stop(occ); +} + +/* used by device table */ +static const struct of_device_id occ_of_match[] = { + { .compatible = "ibm,occ-p9-fsi" }, + {} +}; +MODULE_DEVICE_TABLE (of, occ_of_match); + +MODULE_AUTHOR ("Eddie James <[email protected]>" ); +MODULE_DESCRIPTION ("BMC P9 OCC hwmon driver" ); +MODULE_LICENSE ("GPL" ); --2.9.3
Joel Stanley
maintainerQuoted 1 line · Andrew Jeffery
So I have reworked them into what is now 8 patches (see below) and tried
to
Quoted 1 line
tell a bit more of a story with them (hopefully I succeeded!) Second, I
tried
Quoted 3 lines
my hand at reworking the layering as mentioned above, such that hardware interaction is split from sysfs, and that the SCOM transport and sensor configuration is decoupled from the data parsing. You largely had all of
these
Quoted 1 line
in-place already, I just cut and pasted code around a bit.
Did you look at Jeremy and Chris B's FSI patches? I think you would be the first client of their new interfaces.
Quoted 1 line
Please review the patches and provide feedback! I'd like to hear
arguments for
Quoted 1 line
or against both of our approaches. Note though that I've only tested that
these
Quoted 3 lines
patches compile, I absolutely have not done any further testing.
Joel: Any chance you could chime in with an architectural review?
No worries.
Quoted 2 lines
When the dust has settled on the bigger issues we can start to look at the finer details of the APIs (there are some bugs, oddities and complexities
that
Quoted 1 line
I would like to address before they are applied to openbmc/linux).
I suggest the next step is upstream review. We can put them in the tree if it's urgent, but I trust that you and Eddie will beat them into shape in no time. If you succeed we can then apply the upstream versions directly.
Cheers,
Joel
Hi Andrew,
Thanks a lot for putting together this new patchset! On the whole, it looks very good! The split between sysfs, occ, and hardware transport layers is solid. I'm pretty satisfied with your modified structuring, although I had a couple of comments and questions. I'll send those out in the applicable patches.
I also tested this on palmetto and barreleye systems and fixed a couple of bugs. I went ahead and put them in a new patchset, which I'm about to send out. For reference, here's my only diffs though:
--- drivers/hwmon/occ/occ.c | 2 ++ drivers/hwmon/occ/occ_sysfs.c | 15 +++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-)
drivers/hwmon/occ/occ.c +0 -0
@@ -469,6 +470,7 @@ struct occ *occ_start(struct device *dev, void
*bus, struct occ_bus_ops bus_ops,
if (!driver)
return ERR_PTR(-ENOMEM);
+ driver->dev = dev;
driver->bus = bus;
driver->bus_ops = bus_ops;
driver->ops = ops;
drivers/hwmon/occ/occ_sysfs.c +2 -2
@@ -63,9 +63,9 @@ static ssize_t show_input(struct device *dev,struct sensor_attr_data *sdata =container_of (attr, struct sensor_attr_data, dev_attr); -struct occ *driver =dev_get_drvdata (dev); +struct occ_sysfs *driver =dev_get_drvdata (dev); - val =occ_get_sensor_value (driver, sdata->type, sdata->hwmon_index -1 ); + val = occ_get_sensor_value(driver->occ, sdata->type,
sdata->hwmon_index - 1);
if (sdata->type == TEMP)
val *= 1000; /* in millidegree Celsius */
@@ -79,9 +79,9 @@ static ssize_t show_label(struct device *dev,
struct sensor_attr_data *sdata = container_of(attr,
struct sensor_attr_data, dev_attr);
- struct occ *driver = dev_get_drvdata(dev);
+ struct occ_sysfs *driver = dev_get_drvdata(dev);
- val = occ_get_sensor_id(driver, sdata->type,
+ val = occ_get_sensor_id(driver->occ, sdata->type,
sdata->hwmon_index - 1);
return snprintf(buf, PAGE_SIZE - 1, "%d\n", val);@@ -95,15 +95,15 @@ static ssize_t show_caps(struct device *dev,
struct sensor_attr_data *sdata = container_of(attr,
struct sensor_attr_data, dev_attr);
- struct occ *driver = dev_get_drvdata(dev);
+ struct occ_sysfs *driver = dev_get_drvdata(dev);
- sensor = occ_get_sensor(driver, CAPS);
+ sensor = occ_get_sensor(driver->occ, CAPS);
if (!sensor) {
val = -1;
return snprintf(buf, PAGE_SIZE - 1, "%d\n", val);
}- val = occ_get_caps_value(driver, sensor, sdata->hwmon_index - 1,
+ val = occ_get_caps_value(driver->occ, sensor, sdata->hwmon_index - 1,
sdata->attr_id);
return snprintf(buf, PAGE_SIZE - 1, "%d\n", val);
@@ -467,7 +467,6 @@ struct occ_sysfs *occ_sysfs_start(struct device
*dev, struct occ *occ,
if (!hwmon)
return ERR_PTR(-ENOMEM);- hwmon->dev = dev;
hwmon->occ = occ;
hwmon->num_caps_fields = config->num_caps_fields;
hwmon->caps_names = config->caps_names;Signature · 1 line
1.9.1
Quoted 111 lines · Andrew Jeffery
Hi Eddie,
Quoted 5 lines
This patchset provides a new OCC hwmon driver. There are a number of issues with the existing driver. Firstly, i2c access was embedded throughout the driver. Secondly, there is no way to easily differentiate versions of the OCC.
Quoted 8 lines
This patchset addresses the first issue by abstracting the bus transfer protocol into a modular structure. In this way, any low level transfer method may be easily implemented.
The second issue is addressed by separating the "version specific" code for the OCC and the common hwmon code. This task is not yet complete, but the general structure is in place. Ultimately, different OCC versions could be probed up using the device tree.
I agree with all of this. However, I thought some of the layering could still be improved, so rather than provide a review through prose I figured it might be better for both of us if I mangled the patches directly.
I've attacked two things. The first is I found the series hard to review due to the way the patches were split, as the patches went from trivial to huge (and complex) in a fairly short step:
Quoted 7 lines
Edward A. James (5):
Revert "hwmon: Add Power8 OCC hwmon driver"
drivers: Add hwmon occ driver framework
drivers: hwmon OCC scom bus operations
drivers: Add hwmon OCC version specific functions
drivers: OCC hwmon driver and sysfsSo I have reworked them into what is now 8 patches (see below) and tried to tell a bit more of a story with them (hopefully I succeeded!) Second, I tried my hand at reworking the layering as mentioned above, such that hardware interaction is split from sysfs, and that the SCOM transport and sensor configuration is decoupled from the data parsing. You largely had all of these in-place already, I just cut and pasted code around a bit.
Please review the patches and provide feedback! I'd like to hear arguments for or against both of our approaches. Note though that I've only tested that these patches compile, I absolutely have not done any further testing.
Joel: Any chance you could chime in with an architectural review?
When the dust has settled on the bigger issues we can start to look at the finer details of the APIs (there are some bugs, oddities and complexities that I would like to address before they are applied to openbmc/linux).
Cheers,
Andrew
Andrew Jeffery (8):
hwmon: Add core On-Chip Controller support for POWER CPUs
hwmon: occ: Add sysfs interface
hwmon: occ: Add I2C SCOM transport implementation
hwmon: occ: Add callbacks for parsing P8 OCC datastructures
hwmon: occ: Add hwmon implementation for the P8 OCC
arm: aspeed: dt: Fix OCC compatible strings
hwmon: occ: Add callbacks for parsing P9 OCC datastructures
wip: hwmon: occ: Add sketch of the hwmon implementation for the P9 OCCEdward A. James (1):
Revert "hwmon: Add Power8 OCC hwmon driver".../devicetree/bindings/i2c/i2c-ibm-occ.txt | 13 - arch/arm/boot/dts/aspeed-bmc-opp-barreleye.dts | 4 +- arch/arm/boot/dts/aspeed-bmc-opp-firestone.dts | 4 +- arch/arm/boot/dts/aspeed-bmc-opp-garrison.dts | 4 +- arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts | 2 +- drivers/hwmon/Kconfig | 13 +- drivers/hwmon/Makefile | 2 +- drivers/hwmon/occ/Kconfig | 38 + drivers/hwmon/occ/Makefile | 3 + drivers/hwmon/occ/occ.c | 494 ++++++++ drivers/hwmon/occ/occ.h | 79 ++ drivers/hwmon/occ/occ_p8.c | 219 ++++ drivers/hwmon/occ/occ_p8.h | 30 + drivers/hwmon/occ/occ_p8_i2c.c | 133 +++ drivers/hwmon/occ/occ_p9.c | 261 ++++ drivers/hwmon/occ/occ_p9.h | 30 + drivers/hwmon/occ/occ_p9_fsi.c | 93 ++ drivers/hwmon/occ/occ_scom_i2c.c | 68 ++ drivers/hwmon/occ/occ_scom_i2c.h | 20 + drivers/hwmon/occ/occ_sysfs.c | 498 ++++++++ drivers/hwmon/occ/occ_sysfs.h | 51 + drivers/hwmon/occ/scom.h | 50 + drivers/hwmon/power8_occ_i2c.c | 1254 -------------------- 23 files changed, 2076 insertions(+), 1287 deletions(-) delete mode 100644 Documentation/devicetree/bindings/i2c/i2c-ibm-occ.txt create mode 100644 drivers/hwmon/occ/Kconfig create mode 100644 drivers/hwmon/occ/Makefile create mode 100644 drivers/hwmon/occ/occ.c create mode 100644 drivers/hwmon/occ/occ.h create mode 100644 drivers/hwmon/occ/occ_p8.c create mode 100644 drivers/hwmon/occ/occ_p8.h create mode 100644 drivers/hwmon/occ/occ_p8_i2c.c create mode 100644 drivers/hwmon/occ/occ_p9.c create mode 100644 drivers/hwmon/occ/occ_p9.h create mode 100644 drivers/hwmon/occ/occ_p9_fsi.c create mode 100644 drivers/hwmon/occ/occ_scom_i2c.c create mode 100644 drivers/hwmon/occ/occ_scom_i2c.h create mode 100644 drivers/hwmon/occ/occ_sysfs.c create mode 100644 drivers/hwmon/occ/occ_sysfs.h create mode 100644 drivers/hwmon/occ/scom.h delete mode 100644 drivers/hwmon/power8_occ_i2c.c--
2.9.3
Quoted 7 lines · Eddie James
Hi Andrew,
Thanks a lot for putting together this new patchset! On the whole, it looks very good! The split between sysfs, occ, and hardware transport layers is solid. I'm pretty satisfied with your modified structuring, although I had a couple of comments and questions. I'll send those out in the applicable patches.
I've just finished replying to your comments. The most controversial one was the cap_names/num_cap_names problem, but we have some alternatives there.
Quoted 3 lines
I also tested this on palmetto and barreleye systems and fixed a couple of bugs.
Great!
Quoted 2 lines
I went ahead and put them in a new patchset, which I'm
about to send out. For reference, here's my only diffs though:
Good ol' void conversions eh.
Thanks for testing!
Andrew
Hi Andrew,
What's the status on this? I last sent out a tested patch set that I'm pretty happy with. I'm not sure what the next step for me is, any ideas?
Thanks,
Eddie
Quoted 27 lines · Andrew Jeffery
Quoted 7 lines · Eddie James
Hi Andrew,
Thanks a lot for putting together this new patchset! On the whole, it looks very good! The split between sysfs, occ, and hardware transport layers is solid. I'm pretty satisfied with your modified structuring, although I had a couple of comments and questions. I'll send those out in the applicable patches.
I've just finished replying to your comments. The most controversial one was the cap_names/num_cap_names problem, but we have some alternatives there.
Quoted 3 lines
I also tested this on palmetto and barreleye systems and fixed a couple of bugs.
Great!
Quoted 2 lines
I went ahead and put them in a new patchset, which I'm
about to send out. For reference, here's my only diffs though:Good ol' void conversions eh.
Thanks for testing!
Andrew
Quoted 6 lines · Eddie James
Hi Andrew,
What's the status on this? I last sent out a tested patch set that I'm pretty happy with. I'm not sure what the next step for me is, any ideas?
Sorry, I've been busy on other things but will now have some time to look at the series. I'll take a look in the morning.
Andrew