All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH linux 5/7] hwmon: occ: Add hwmon implementation for the P8 OCC
@ 2016-12-16 20:35 eajames.ibm
  2016-12-20  0:53 ` Andrew Jeffery
  0 siblings, 1 reply; 2+ messages in thread
From: eajames.ibm @ 2016-12-16 20:35 UTC (permalink / raw)
  To: openbmc; +Cc: andrew, joel, Edward A. James

From: "Edward A. James" <eajames@us.ibm.com>

Add code to tie the hwmon sysfs code and the POWER8 OCC code together, as
well as probe the entire driver from the I2C bus. I2C is the communication
method between the BMC and the P8 OCC.

Signed-off-by: Edward A. James <eajames@us.ibm.com>
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
---
 .../devicetree/bindings/i2c/i2c-ibm-occ.txt        |  13 ++
 drivers/hwmon/occ/Kconfig                          |  14 ++
 drivers/hwmon/occ/Makefile                         |   1 +
 drivers/hwmon/occ/occ_p8_i2c.c                     | 141 +++++++++++++++++++++
 4 files changed, 169 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-ibm-occ.txt
 create mode 100644 drivers/hwmon/occ/occ_p8_i2c.c

diff --git a/Documentation/devicetree/bindings/i2c/i2c-ibm-occ.txt b/Documentation/devicetree/bindings/i2c/i2c-ibm-occ.txt
new file mode 100644
index 0000000..b0d2b36
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-ibm-occ.txt
@@ -0,0 +1,13 @@
+HWMON I2C driver for IBM POWER CPU OCC (On Chip Controller)
+
+Required properties:
+ - compatible: must be "ibm,p8-occ-i2c"
+ - reg: physical address
+
+Example:
+i2c3: i2c-bus@100 {
+	occ@50 {
+		compatible = "ibm,p8-occ-i2c";
+		reg = <0x50>;
+	};
+};
diff --git a/drivers/hwmon/occ/Kconfig b/drivers/hwmon/occ/Kconfig
index cdb64a7..e690001 100644
--- a/drivers/hwmon/occ/Kconfig
+++ b/drivers/hwmon/occ/Kconfig
@@ -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
diff --git a/drivers/hwmon/occ/Makefile b/drivers/hwmon/occ/Makefile
index a6881f9..05a84e9 100644
--- a/drivers/hwmon/occ/Makefile
+++ b/drivers/hwmon/occ/Makefile
@@ -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
diff --git a/drivers/hwmon/occ/occ_p8_i2c.c b/drivers/hwmon/occ/occ_p8_i2c.c
new file mode 100644
index 0000000..a151b3a
--- /dev/null
+++ b/drivers/hwmon/occ/occ_p8_i2c.c
@@ -0,0 +1,141 @@
+/*
+ * occ_p8_i2c.c - hwmon OCC driver
+ *
+ * This file contains the i2c layer for accessing the P8 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"
+
+#define P8_OCC_I2C_NAME	"p8-occ-i2c"
+
+static char *caps_sensor_names[] = {
+	"curr_powercap",
+	"curr_powerreading",
+	"norm_powercap",
+	"max_powercap",
+	"min_powercap",
+	"user_powerlimit"
+};
+
+int p8_i2c_getscom(void *bus, u32 address, u8 *data)
+{
+	/* P8 i2c slave requires address to be shifted by 1 */
+	address = address << 1;
+
+	return occ_i2c_getscom(bus, address, data);
+}
+
+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);
+}
+
+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,
+};
+
+static int p8_occ_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct occ *occ;
+	struct occ_sysfs *hwmon;
+
+	occ = p8_occ_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);
+	if (IS_ERR(hwmon))
+		return PTR_ERR(hwmon);
+
+	i2c_set_clientdata(client, hwmon);
+
+	return 0;
+}
+
+static int p8_occ_remove(struct i2c_client *client)
+{
+	int rc;
+	struct occ_sysfs *hwmon = i2c_get_clientdata(client);
+	struct occ *occ = hwmon->occ;
+
+	rc = occ_sysfs_stop(&client->dev, hwmon);
+
+	rc = rc || p8_occ_stop(occ);
+
+	return rc;
+}
+
+/* used by old-style board info. */
+static const struct i2c_device_id occ_ids[] = {
+	{ P8_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,p8-occ-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 p8_occ_driver = {
+	.class = I2C_CLASS_HWMON,
+	.driver = {
+		.name = P8_OCC_I2C_NAME,
+		.pm = NULL,
+		.of_match_table = occ_of_match,
+	},
+	.probe = p8_occ_probe,
+	.remove = p8_occ_remove,
+	.id_table = occ_ids,
+	.address_list = normal_i2c,
+};
+
+module_i2c_driver(p8_occ_driver);
+
+MODULE_AUTHOR("Eddie James <eajames@us.ibm.com>");
+MODULE_DESCRIPTION("BMC P8 OCC hwmon driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1

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

* Re: [PATCH linux 5/7] hwmon: occ: Add hwmon implementation for the P8 OCC
  2016-12-16 20:35 [PATCH linux 5/7] hwmon: occ: Add hwmon implementation for the P8 OCC eajames.ibm
@ 2016-12-20  0:53 ` Andrew Jeffery
  0 siblings, 0 replies; 2+ messages in thread
From: Andrew Jeffery @ 2016-12-20  0:53 UTC (permalink / raw)
  To: eajames.ibm, openbmc; +Cc: joel, Edward A. James

[-- Attachment #1: Type: text/plain, Size: 7164 bytes --]

On Fri, 2016-12-16 at 14:35 -0600, eajames.ibm@gmail.com wrote:
> > From: "Edward A. James" <eajames@us.ibm.com>
> 
> Add code to tie the hwmon sysfs code and the POWER8 OCC code together, as
> well as probe the entire driver from the I2C bus. I2C is the communication
> method between the BMC and the P8 OCC.
> 
> > Signed-off-by: Edward A. James <eajames@us.ibm.com>
> > Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
> ---
>  .../devicetree/bindings/i2c/i2c-ibm-occ.txt        |  13 ++
>  drivers/hwmon/occ/Kconfig                          |  14 ++
>  drivers/hwmon/occ/Makefile                         |   1 +
>  drivers/hwmon/occ/occ_p8_i2c.c                     | 141 +++++++++++++++++++++
>  4 files changed, 169 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/i2c/i2c-ibm-occ.txt
>  create mode 100644 drivers/hwmon/occ/occ_p8_i2c.c
> 
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-ibm-occ.txt b/Documentation/devicetree/bindings/i2c/i2c-ibm-occ.txt
> new file mode 100644
> index 0000000..b0d2b36
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/i2c/i2c-ibm-occ.txt
> @@ -0,0 +1,13 @@
> +HWMON I2C driver for IBM POWER CPU OCC (On Chip Controller)
> +
> +Required properties:
> + - compatible: must be "ibm,p8-occ-i2c"
> + - reg: physical address
> +
> +Example:
> > +i2c3: i2c-bus@100 {
> > +	occ@50 {
> > +		compatible = "ibm,p8-occ-i2c";
> > +		reg = <0x50>;
> > +	};
> +};
> diff --git a/drivers/hwmon/occ/Kconfig b/drivers/hwmon/occ/Kconfig
> index cdb64a7..e690001 100644
> --- a/drivers/hwmon/occ/Kconfig
> +++ b/drivers/hwmon/occ/Kconfig
> @@ -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.

I think this should be p8-occ-i2c by the #define below and your
compatible string. Though the C file is called 'occ_p8_i2c.c' as well;
maybe it should be renamed? Other than that, consider it tagged with
reviewed-by, these are minor issues.

> +
> +endif
> diff --git a/drivers/hwmon/occ/Makefile b/drivers/hwmon/occ/Makefile
> index a6881f9..05a84e9 100644
> --- a/drivers/hwmon/occ/Makefile
> +++ b/drivers/hwmon/occ/Makefile
> @@ -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
> diff --git a/drivers/hwmon/occ/occ_p8_i2c.c b/drivers/hwmon/occ/occ_p8_i2c.c
> new file mode 100644
> index 0000000..a151b3a
> --- /dev/null
> +++ b/drivers/hwmon/occ/occ_p8_i2c.c
> @@ -0,0 +1,141 @@
> +/*
> + * occ_p8_i2c.c - hwmon OCC driver
> + *
> + * This file contains the i2c layer for accessing the P8 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"
> +
> > +#define P8_OCC_I2C_NAME	"p8-occ-i2c"
> +
> +static char *caps_sensor_names[] = {
> > +	"curr_powercap",
> > +	"curr_powerreading",
> > +	"norm_powercap",
> > +	"max_powercap",
> > +	"min_powercap",
> > +	"user_powerlimit"
> +};
> +
> +int p8_i2c_getscom(void *bus, u32 address, u8 *data)
> +{
> > +	/* P8 i2c slave requires address to be shifted by 1 */
> > +	address = address << 1;
> +
> > +	return occ_i2c_getscom(bus, address, data);
> +}
> +
> +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);
> +}
> +
> +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,
> +};
> +
> +static int p8_occ_probe(struct i2c_client *client,
> > +			const struct i2c_device_id *id)
> +{
> > +	struct occ *occ;
> > +	struct occ_sysfs *hwmon;
> +
> > +	occ = p8_occ_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);
> > +	if (IS_ERR(hwmon))
> > +		return PTR_ERR(hwmon);
> +
> > +	i2c_set_clientdata(client, hwmon);
> +
> > +	return 0;
> +}
> +
> +static int p8_occ_remove(struct i2c_client *client)
> +{
> > +	int rc;
> > +	struct occ_sysfs *hwmon = i2c_get_clientdata(client);
> > +	struct occ *occ = hwmon->occ;
> +
> > +	rc = occ_sysfs_stop(&client->dev, hwmon);
> +
> > +	rc = rc || p8_occ_stop(occ);
> +
> > +	return rc;
> +}
> +
> +/* used by old-style board info. */
> +static const struct i2c_device_id occ_ids[] = {
> > +	{ P8_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,p8-occ-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 p8_occ_driver = {
> > +	.class = I2C_CLASS_HWMON,
> > +	.driver = {
> > +		.name = P8_OCC_I2C_NAME,
> > +		.pm = NULL,
> > +		.of_match_table = occ_of_match,
> > +	},
> > +	.probe = p8_occ_probe,
> > +	.remove = p8_occ_remove,
> > +	.id_table = occ_ids,
> > +	.address_list = normal_i2c,
> +};
> +
> +module_i2c_driver(p8_occ_driver);
> +
> > +MODULE_AUTHOR("Eddie James <eajames@us.ibm.com>");
> +MODULE_DESCRIPTION("BMC P8 OCC hwmon driver");
> +MODULE_LICENSE("GPL");

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

end of thread, other threads:[~2016-12-20  0:53 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-16 20:35 [PATCH linux 5/7] hwmon: occ: Add hwmon implementation for the P8 OCC eajames.ibm
2016-12-20  0:53 ` Andrew Jeffery

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