All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5 V4] IIO in kernel interfaces (pull)
@ 2011-11-07 15:44 ` Jonathan Cameron
  0 siblings, 0 replies; 32+ messages in thread
From: Jonathan Cameron @ 2011-11-07 15:44 UTC (permalink / raw)
  To: linux-iio, linux-kernel
  Cc: guenter.roeck, khali, dmitry.torokhov, broonie, gregkh, alan,
	arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

Dear All,

Changes since V3 are all in processing of raw values to give sensible
hwmon outputs in response to Guenter's comments.

Also rebased on the new version of the IIO core.

Note this is just the association infrastructure and the pull interfaces.
Thus we can handle drivers polling for values.  Doing push interfaces
(interrupt triggered more or less) requires a lot more of the IIO
intrastructure to be in place and so will have to wait a little while.
This is available for the staging tree but will will require the second
large part of IIO to move out of staging (triggered and buffered capture)
plus needs a little more work and a lot more testing.  As the cover letter
for the push interface epxlains there are some complexities of the
interaction of push and pull interfaces on the same physical device.  These
are independent of the external interfaces so shouldn't block this support
merging.

The final patch is not intended for merging, but rather acts as an
example of the board configuration needed.


Since V2:

Fixes as per Guenter's comments on the iio_hwmon driver.
Only one that differred slightly from Guenters suggestion
is the value calculation where I reordered things to reduce
the chance of overflow as well as casting to longs.
Thanks Guenter!

Since V1:
Uses the bus's list of devices instead of having a local one.
     (thanks to Lars-Peter).

Added are interfaces for getting all channels mapped to a particular
device.

Hwmon driver is now vaguely complete - hence cc'd hwmon. If people
are happy I'd expect this to ultimately end up in drivers/hmwon.
Right now it is acting as a test driver for these interfaces.

Thanks and all comments welcome. I've added hwmon to the cc list 
this time round.

V1 message:

There are obviously some rough corners in here that will need cleaning up.
For now I've just put this out there to see if anyone radically disagrees
on the direction.  It sits on top the recent rfc to move first bit of IIO
out of staging with a few buglets fixed.  Best bet if anyone wants to
test is to pull from:

https://github.com/jic23/linux-iio/tree/outofstaging

which now also includes these patches.

Intereresting patches are 3 and 4.  5 gives a trivial example of
a driver using this (hwmon driver that only takes first matching channel
and sticks it out as in1_input - breaks all sorts elements of the hwmon
interface spec.)

For now I've gone with Mark Brown's suggestion of a datasheet_name for
finding the channels on the device.  Patch 2 hacks this name into the
max1363 driver.  I'll probably put a version matching on channel number and
type in at a later date.

Here we just have a pull interface.  Push is considerably harder to do
and needs quite a lot more of the IIO infrastructure to be in place
(triggers / buffers etc). Events obviously require IIO event handling
to be there. Hence all of that will have to wait until those elements
have in of themselves been posted for review.

It is pretty clear to me that hwmon interface for starters needs the
ability to say - 'give me all mappings that correspond to me'.

This is what I intend to add next followed by some utility functions
to make it easy to match the hwmon interface.

At that point I'll propose the hwmon driver goes into drivers/hwmon
(subject to the underlying iio stuff merging).

Fun fun fun.  Thanks to Linus an Mark for their input on this.
Hope this is roughly what you guys were looking for.

Also on my list to do is to check this very thoroughly for any
possible race conditions around the removal of the underlying
device.

Jonathan

Jonathan Cameron (5):
  IIO: core: add datasheet_name to chan_spec
  IIO:ADC:max1363 add datasheet_name entries.
  IIO:CORE add in kernel interface mapping and getting IIO channels.
  IIO:hwmon interface client driver.
  stargate2: example of map configuration for iio to hwmon example.

 arch/arm/mach-pxa/stargate2.c  |   23 ++++
 drivers/Makefile               |    2 +-
 drivers/iio/Kconfig            |    8 ++
 drivers/iio/Makefile           |    2 +
 drivers/iio/adc/max1363_core.c |    2 +
 drivers/iio/iio.c              |  264 +++++++++++++++++++++++++++++++++++++++-
 drivers/iio/iio_hwmon.c        |  227 ++++++++++++++++++++++++++++++++++
 drivers/iio/inkern.c           |   20 +++
 include/linux/iio/iio.h        |    7 +-
 include/linux/iio/inkern.h     |   95 ++++++++++++++
 10 files changed, 643 insertions(+), 7 deletions(-)
 create mode 100644 drivers/iio/iio_hwmon.c
 create mode 100644 drivers/iio/inkern.c
 create mode 100644 include/linux/iio/inkern.h

-- 
1.7.7.2


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

* [lm-sensors] [PATCH 0/5 V4] IIO in kernel interfaces (pull)
@ 2011-11-07 15:44 ` Jonathan Cameron
  0 siblings, 0 replies; 32+ messages in thread
From: Jonathan Cameron @ 2011-11-07 15:44 UTC (permalink / raw)
  To: linux-iio, linux-kernel
  Cc: guenter.roeck, khali, dmitry.torokhov, broonie, gregkh, alan,
	arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

Dear All,

Changes since V3 are all in processing of raw values to give sensible
hwmon outputs in response to Guenter's comments.

Also rebased on the new version of the IIO core.

Note this is just the association infrastructure and the pull interfaces.
Thus we can handle drivers polling for values.  Doing push interfaces
(interrupt triggered more or less) requires a lot more of the IIO
intrastructure to be in place and so will have to wait a little while.
This is available for the staging tree but will will require the second
large part of IIO to move out of staging (triggered and buffered capture)
plus needs a little more work and a lot more testing.  As the cover letter
for the push interface epxlains there are some complexities of the
interaction of push and pull interfaces on the same physical device.  These
are independent of the external interfaces so shouldn't block this support
merging.

The final patch is not intended for merging, but rather acts as an
example of the board configuration needed.


Since V2:

Fixes as per Guenter's comments on the iio_hwmon driver.
Only one that differred slightly from Guenters suggestion
is the value calculation where I reordered things to reduce
the chance of overflow as well as casting to longs.
Thanks Guenter!

Since V1:
Uses the bus's list of devices instead of having a local one.
     (thanks to Lars-Peter).

Added are interfaces for getting all channels mapped to a particular
device.

Hwmon driver is now vaguely complete - hence cc'd hwmon. If people
are happy I'd expect this to ultimately end up in drivers/hmwon.
Right now it is acting as a test driver for these interfaces.

Thanks and all comments welcome. I've added hwmon to the cc list 
this time round.

V1 message:

There are obviously some rough corners in here that will need cleaning up.
For now I've just put this out there to see if anyone radically disagrees
on the direction.  It sits on top the recent rfc to move first bit of IIO
out of staging with a few buglets fixed.  Best bet if anyone wants to
test is to pull from:

https://github.com/jic23/linux-iio/tree/outofstaging

which now also includes these patches.

Intereresting patches are 3 and 4.  5 gives a trivial example of
a driver using this (hwmon driver that only takes first matching channel
and sticks it out as in1_input - breaks all sorts elements of the hwmon
interface spec.)

For now I've gone with Mark Brown's suggestion of a datasheet_name for
finding the channels on the device.  Patch 2 hacks this name into the
max1363 driver.  I'll probably put a version matching on channel number and
type in at a later date.

Here we just have a pull interface.  Push is considerably harder to do
and needs quite a lot more of the IIO infrastructure to be in place
(triggers / buffers etc). Events obviously require IIO event handling
to be there. Hence all of that will have to wait until those elements
have in of themselves been posted for review.

It is pretty clear to me that hwmon interface for starters needs the
ability to say - 'give me all mappings that correspond to me'.

This is what I intend to add next followed by some utility functions
to make it easy to match the hwmon interface.

At that point I'll propose the hwmon driver goes into drivers/hwmon
(subject to the underlying iio stuff merging).

Fun fun fun.  Thanks to Linus an Mark for their input on this.
Hope this is roughly what you guys were looking for.

Also on my list to do is to check this very thoroughly for any
possible race conditions around the removal of the underlying
device.

Jonathan

Jonathan Cameron (5):
  IIO: core: add datasheet_name to chan_spec
  IIO:ADC:max1363 add datasheet_name entries.
  IIO:CORE add in kernel interface mapping and getting IIO channels.
  IIO:hwmon interface client driver.
  stargate2: example of map configuration for iio to hwmon example.

 arch/arm/mach-pxa/stargate2.c  |   23 ++++
 drivers/Makefile               |    2 +-
 drivers/iio/Kconfig            |    8 ++
 drivers/iio/Makefile           |    2 +
 drivers/iio/adc/max1363_core.c |    2 +
 drivers/iio/iio.c              |  264 +++++++++++++++++++++++++++++++++++++++-
 drivers/iio/iio_hwmon.c        |  227 ++++++++++++++++++++++++++++++++++
 drivers/iio/inkern.c           |   20 +++
 include/linux/iio/iio.h        |    7 +-
 include/linux/iio/inkern.h     |   95 ++++++++++++++
 10 files changed, 643 insertions(+), 7 deletions(-)
 create mode 100644 drivers/iio/iio_hwmon.c
 create mode 100644 drivers/iio/inkern.c
 create mode 100644 include/linux/iio/inkern.h

-- 
1.7.7.2


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* [PATCH 1/5] IIO: core: add datasheet_name to chan_spec
  2011-11-07 15:44 ` [lm-sensors] " Jonathan Cameron
@ 2011-11-07 15:44   ` Jonathan Cameron
  -1 siblings, 0 replies; 32+ messages in thread
From: Jonathan Cameron @ 2011-11-07 15:44 UTC (permalink / raw)
  To: linux-iio, linux-kernel
  Cc: guenter.roeck, khali, dmitry.torokhov, broonie, gregkh, alan,
	arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

From: Jonathan Cameron <jic23@cam.ac.uk>

This allows for matching against the name given
on a datasheet, however silly/inconsistent it might
be.

Useful for in kernel interfaces.

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 include/linux/iio/iio.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index 4367d82..36a50b2 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -122,6 +122,7 @@ struct iio_chan_spec {
 	} scan_type;
 	long                    info_mask;
 	char			*extend_name;
+	const char		*datasheet_name;
 	unsigned		processed_val:1;
 	unsigned		modified:1;
 	unsigned		indexed:1;
-- 
1.7.7.2


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

* [lm-sensors] [PATCH 1/5] IIO: core: add datasheet_name to chan_spec
@ 2011-11-07 15:44   ` Jonathan Cameron
  0 siblings, 0 replies; 32+ messages in thread
From: Jonathan Cameron @ 2011-11-07 15:44 UTC (permalink / raw)
  To: linux-iio, linux-kernel
  Cc: guenter.roeck, khali, dmitry.torokhov, broonie, gregkh, alan,
	arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

From: Jonathan Cameron <jic23@cam.ac.uk>

This allows for matching against the name given
on a datasheet, however silly/inconsistent it might
be.

Useful for in kernel interfaces.

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 include/linux/iio/iio.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index 4367d82..36a50b2 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -122,6 +122,7 @@ struct iio_chan_spec {
 	} scan_type;
 	long                    info_mask;
 	char			*extend_name;
+	const char		*datasheet_name;
 	unsigned		processed_val:1;
 	unsigned		modified:1;
 	unsigned		indexed:1;
-- 
1.7.7.2


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* [PATCH 2/5] IIO:ADC:max1363 add datasheet_name entries.
  2011-11-07 15:44 ` [lm-sensors] " Jonathan Cameron
@ 2011-11-07 15:44   ` Jonathan Cameron
  -1 siblings, 0 replies; 32+ messages in thread
From: Jonathan Cameron @ 2011-11-07 15:44 UTC (permalink / raw)
  To: linux-iio, linux-kernel
  Cc: guenter.roeck, khali, dmitry.torokhov, broonie, gregkh, alan,
	arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

From: Jonathan Cameron <jic23@cam.ac.uk>

Kind of obvious for this device but useful
for testing purposes.

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/iio/adc/max1363_core.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/iio/adc/max1363_core.c b/drivers/iio/adc/max1363_core.c
index f21ec63..603969b 100644
--- a/drivers/iio/adc/max1363_core.c
+++ b/drivers/iio/adc/max1363_core.c
@@ -252,6 +252,7 @@ static const enum max1363_modes max1363_mode_list[] = {
 		.channel = num,						\
 		.address = addr,					\
 		.info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,		\
+		.datasheet_name = "AIN"#num				\
 	}								\
 
 /* bipolar channel */
@@ -264,6 +265,7 @@ static const enum max1363_modes max1363_mode_list[] = {
 		.channel2 = num2,					\
 		.address = addr,					\
 		.info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,		\
+		.datasheet_name = "AIN"#num"-AIN"#num2			\
 	}
 
 
-- 
1.7.7.2


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

* [lm-sensors] [PATCH 2/5] IIO:ADC:max1363 add datasheet_name entries.
@ 2011-11-07 15:44   ` Jonathan Cameron
  0 siblings, 0 replies; 32+ messages in thread
From: Jonathan Cameron @ 2011-11-07 15:44 UTC (permalink / raw)
  To: linux-iio, linux-kernel
  Cc: guenter.roeck, khali, dmitry.torokhov, broonie, gregkh, alan,
	arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

From: Jonathan Cameron <jic23@cam.ac.uk>

Kind of obvious for this device but useful
for testing purposes.

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/iio/adc/max1363_core.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/iio/adc/max1363_core.c b/drivers/iio/adc/max1363_core.c
index f21ec63..603969b 100644
--- a/drivers/iio/adc/max1363_core.c
+++ b/drivers/iio/adc/max1363_core.c
@@ -252,6 +252,7 @@ static const enum max1363_modes max1363_mode_list[] = {
 		.channel = num,						\
 		.address = addr,					\
 		.info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,		\
+		.datasheet_name = "AIN"#num				\
 	}								\
 
 /* bipolar channel */
@@ -264,6 +265,7 @@ static const enum max1363_modes max1363_mode_list[] = {
 		.channel2 = num2,					\
 		.address = addr,					\
 		.info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT,		\
+		.datasheet_name = "AIN"#num"-AIN"#num2			\
 	}
 
 
-- 
1.7.7.2


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* [PATCH 3/5] IIO:CORE add in kernel interface mapping and getting IIO channels.
  2011-11-07 15:44 ` [lm-sensors] " Jonathan Cameron
@ 2011-11-07 15:44   ` Jonathan Cameron
  -1 siblings, 0 replies; 32+ messages in thread
From: Jonathan Cameron @ 2011-11-07 15:44 UTC (permalink / raw)
  To: linux-iio, linux-kernel
  Cc: guenter.roeck, khali, dmitry.torokhov, broonie, gregkh, alan,
	arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

From: Jonathan Cameron <jic23@cam.ac.uk>

Two elements here:
* Map as defined in include/linux/iio/inkern.h
* Matching code to actually get the iio_dev and channel
that we want from the global list of IIO devices.

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/Makefile           |    2 +-
 drivers/iio/Makefile       |    1 +
 drivers/iio/iio.c          |  264 +++++++++++++++++++++++++++++++++++++++++++-
 drivers/iio/inkern.c       |   20 ++++
 include/linux/iio/iio.h    |    6 +-
 include/linux/iio/inkern.h |   95 ++++++++++++++++
 6 files changed, 381 insertions(+), 7 deletions(-)

diff --git a/drivers/Makefile b/drivers/Makefile
index 216bba4..cf3d1f7 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -134,4 +134,4 @@ obj-$(CONFIG_HYPERV)		+= hv/
 
 obj-$(CONFIG_PM_DEVFREQ)	+= devfreq/
 
-obj-$(CONFIG_IIO)		+= iio/
+obj-y				+= iio/
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index db3c426..cfb588a 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -1,6 +1,7 @@
 #
 # Makefile for the Industrial I/O subsystem
 #
+obj-y = inkern.o
 
 obj-$(CONFIG_IIO) += iio.o
 industrialio-y := core.o
diff --git a/drivers/iio/iio.c b/drivers/iio/iio.c
index 9a98f5f..683a3db 100644
--- a/drivers/iio/iio.c
+++ b/drivers/iio/iio.c
@@ -12,8 +12,10 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/idr.h>
+#include <linux/err.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
+#include <linux/iio/inkern.h>
 
 static DEFINE_IDA(iio_ida);
 
@@ -66,6 +68,263 @@ static const char * const iio_chan_info_postfix[] = {
 	[IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW] = "quadrature_correction_raw",
 };
 
+static void iio_dev_release(struct device *device);
+static struct device_type iio_dev_type = {
+	.name = "iio_device",
+	.release = iio_dev_release,
+};
+
+static int iio_match_dev(struct device *dev, void *data)
+{
+	struct iio_dev *indio_dev;
+	struct device *dev2 = data;
+
+	if (dev->type != &iio_dev_type)
+		return 0;
+
+	indio_dev = container_of(dev, struct iio_dev, dev);
+	if (indio_dev->info->get_hardware_id)
+		return indio_dev->info->get_hardware_id(indio_dev) == dev2;
+	else
+		return indio_dev->dev.parent == dev2;
+}
+
+static int iio_match_dev_name(struct device *dev, void *data)
+{
+	struct iio_dev *indio_dev;
+	const char *name = data;
+
+	if (dev->type != &iio_dev_type)
+		return 0;
+
+	indio_dev = container_of(dev, struct iio_dev, dev);
+	if (indio_dev->info->get_hardware_id)
+		return !strcmp(dev_name(indio_dev->info
+					->get_hardware_id(indio_dev)),
+			       name);
+	else if (indio_dev->dev.parent)
+		return !strcmp(dev_name(indio_dev->dev.parent), name);
+	return 0;
+}
+
+static const struct iio_chan_spec
+*iio_chan_spec_from_name(const struct iio_dev *indio_dev,
+			 const char *name)
+{
+	int i;
+	const struct iio_chan_spec *chan = NULL;
+	for (i = 0; i < indio_dev->num_channels; i++)
+		if (indio_dev->channels[i].datasheet_name &&
+		    strcmp(name, indio_dev->channels[i].datasheet_name) == 0) {
+			chan = &indio_dev->channels[i];
+			break;
+		}
+	return chan;
+}
+
+struct iio_channel *iio_channel_get(const struct device *dev,
+				    const char *name,
+				    const char *channel_name)
+{
+	struct iio_map *c_i = NULL, *c = NULL;
+	struct device *dev_i;
+	struct iio_channel *channel;
+
+	if (dev == NULL && name == NULL && channel_name == NULL)
+		return ERR_PTR(-ENODEV);
+	/* first find matching entry the channel map */
+	list_for_each_entry(c_i, &iio_map_list, l) {
+		if ((dev && dev != c_i->consumer_dev) ||
+		    (name && strcmp(name, c_i->consumer_dev_name) != 0) ||
+		    (channel_name &&
+		     strcmp(channel_name, c_i->consumer_channel) != 0))
+			continue;
+		c = c_i;
+		break;
+	}
+	if (c == NULL)
+		return ERR_PTR(-ENODEV);
+
+	/* now find the iio device if it has been registered */
+	if (c->adc_dev)
+		dev_i = bus_find_device(&iio_bus_type, NULL, c->adc_dev,
+					&iio_match_dev);
+	else if (c->adc_dev_name)
+		dev_i = bus_find_device(&iio_bus_type, NULL,
+					(void *)c->adc_dev_name,
+					&iio_match_dev_name);
+	else
+		return ERR_PTR(-EINVAL);
+	if (IS_ERR(dev_i))
+		return (void *)dev_i;
+	if (dev_i == NULL)
+		return ERR_PTR(-ENODEV);
+
+	channel = kmalloc(sizeof(*channel), GFP_KERNEL);
+	if (channel == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	channel->indio_dev = container_of(dev_i, struct iio_dev, dev);
+
+	if (c->adc_channel_label)
+		channel->channel =
+			iio_chan_spec_from_name(channel->indio_dev,
+						c->adc_channel_label);
+	if (channel->channel == NULL)
+		channel->channel =
+			&channel->indio_dev->channels[c->channel_number];
+
+	return channel;
+}
+EXPORT_SYMBOL_GPL(iio_channel_get);
+
+void iio_channel_release(struct iio_channel *channel)
+{
+	put_device(&channel->indio_dev->dev);
+	kfree(channel);
+}
+EXPORT_SYMBOL_GPL(iio_channel_release);
+
+struct iio_channel **iio_channel_get_all(const struct device *dev,
+					const char *name)
+{
+	struct iio_channel **chans;
+	struct iio_map *c = NULL;
+	int nummaps = 0;
+	int mapind = 0;
+	int i, ret;
+	struct device *dev_i;
+
+	if (dev == NULL && name == NULL) {
+		ret = -EINVAL;
+		goto error_ret;
+	}
+
+	/* first count the matching maps */
+	list_for_each_entry(c, &iio_map_list, l)
+		if ((dev && dev != c->consumer_dev) ||
+		    (name && strcmp(name, c->consumer_dev_name) != 0))
+			continue;
+		else
+			nummaps++;
+
+	if (nummaps == 0) {
+		ret = -ENODEV;
+		goto error_ret;
+	}
+
+	/* for each map fill in the chans element */
+	chans = kzalloc(sizeof(*chans)*(nummaps + 1), GFP_KERNEL);
+	if (chans == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	for (i = 0; i < nummaps; i++) {
+		chans[i] = kzalloc(sizeof(*chans[0]), GFP_KERNEL);
+		if (chans[i] == NULL) {
+			ret = -ENOMEM;
+			goto error_free_chans;
+		}
+	}
+
+	/* for each map fill in the chans element */
+	list_for_each_entry(c, &iio_map_list, l) {
+		dev_i = NULL;
+		if (dev && dev != c->consumer_dev)
+			continue;
+		if (name && strcmp(name, c->consumer_dev_name) != 0)
+			continue;
+		while (1) {
+			if (c->adc_dev) {
+				dev_i = bus_find_device(&iio_bus_type,
+							dev_i,
+							c->adc_dev,
+							&iio_match_dev);
+			} else if (c->adc_dev_name) {
+				dev_i = bus_find_device(&iio_bus_type,
+							dev_i,
+							(void *)c->adc_dev_name,
+							&iio_match_dev_name);
+			} else {
+				ret = -EINVAL;
+				goto error_free_chans;
+			}
+			if (IS_ERR(dev_i)) {
+				ret = PTR_ERR(dev_i);
+				goto error_free_chans;
+			}
+			if (dev_i == NULL)
+				break;
+
+			chans[mapind]->indio_dev =
+				container_of(dev_i, struct iio_dev, dev);
+			chans[mapind]->channel =
+				iio_chan_spec_from_name(chans[mapind]->
+							indio_dev,
+							c->adc_channel_label);
+			if (chans[mapind]->channel == NULL) {
+				ret = -EINVAL;
+				put_device(&chans[mapind]->indio_dev->dev);
+				goto error_free_chans;
+			}
+			mapind++;
+		}
+	}
+	return chans;
+
+error_free_chans:
+	for (i = 0; i < nummaps; i++)
+		if (chans[i]) {
+			put_device(&chans[i]->indio_dev->dev);
+			kfree(chans[i]);
+		}
+	kfree(chans);
+error_ret:
+
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(iio_channel_get_all);
+
+void iio_channel_release_all(struct iio_channel **channels)
+{
+	int i = 0;
+	struct iio_channel *chan = channels[i];
+
+	while (chan) {
+		put_device(&chan->indio_dev->dev);
+		kfree(chan);
+		i++;
+		chan = channels[i];
+	}
+	kfree(channels);
+}
+EXPORT_SYMBOL_GPL(iio_channel_release_all);
+
+int iio_read_channel_raw(struct iio_channel *chan, int *val)
+{
+	int val2;
+	return chan->indio_dev->info->read_raw(chan->indio_dev, chan->channel,
+					       val, &val2, 0);
+}
+EXPORT_SYMBOL_GPL(iio_read_channel_raw);
+
+int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2)
+{
+	/* Does this channel have shared scale? */
+	return chan->indio_dev
+		->info->read_raw(chan->indio_dev,
+				 chan->channel,
+				 val, val2,
+				 (1 << IIO_CHAN_INFO_SCALE));
+}
+EXPORT_SYMBOL_GPL(iio_read_channel_scale);
+
+enum iio_chan_type iio_get_channel_type(struct iio_channel *channel)
+{
+	return channel->channel->type;
+}
+EXPORT_SYMBOL_GPL(iio_get_channel_type);
+
 static void iio_device_free_read_attr(struct iio_dev *indio_dev,
 						 struct iio_dev_attr *p)
 {
@@ -91,11 +350,6 @@ static void iio_dev_release(struct device *device)
 	iio_device_unregister_sysfs(indio_dev);
 }
 
-static struct device_type iio_dev_type = {
-	.name = "iio_device",
-	.release = iio_dev_release,
-};
-
 struct iio_dev *iio_device_allocate(int sizeof_priv)
 {
 	struct iio_dev *dev;
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
new file mode 100644
index 0000000..b7c2788
--- /dev/null
+++ b/drivers/iio/inkern.c
@@ -0,0 +1,20 @@
+/* The industrial I/O core in kernel channel mapping
+ *
+ * Copyright (c) 2011 Jonathan Cameron
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/iio/inkern.h>
+#include <linux/err.h>
+
+LIST_HEAD(iio_map_list);
+EXPORT_SYMBOL_GPL(iio_map_list);
+void iio_map_array_register(struct iio_map *map, int nummaps)
+{
+	int i;
+	for (i = 0; i < nummaps; i++)
+		list_add(&map[i].l, &iio_map_list);
+}
+EXPORT_SYMBOL(iio_map_array_register);
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index 36a50b2..875704d 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -147,7 +147,10 @@ struct iio_dev;
  * @write_raw_get_fmt:	callback function to query the expected
  *			format/precision. If not set by the driver, write_raw
  *			returns IIO_VAL_INT_PLUS_MICRO.
- **/
+ * @get_hardware_id:	obtain device relating to hardware. Typically based on
+ *			the parent device (actual hardware).  Note that if
+ *			not specified then iio_dev.dev->parent is used.
+ */
 struct iio_info {
 	struct module			*driver_module;
 	const struct attribute_group	*attrs;
@@ -167,6 +170,7 @@ struct iio_info {
 	int (*write_raw_get_fmt)(struct iio_dev *indio_dev,
 			 struct iio_chan_spec const *chan,
 			 long mask);
+	struct device *(*get_hardware_id)(struct iio_dev *indio_dev);
 };
 
 /**
diff --git a/include/linux/iio/inkern.h b/include/linux/iio/inkern.h
new file mode 100644
index 0000000..de15c00
--- /dev/null
+++ b/include/linux/iio/inkern.h
@@ -0,0 +1,95 @@
+/*
+ * The industrial I/O core - in kernel channel mapping infrastructure
+ *
+ * Copyright (c) 2011 Jonathan Cameron
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#ifndef _IIO_INKERN_H_
+#define _IIO_INKERN_H_
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/iio/types.h>
+
+struct iio_dev;
+struct iio_chan_spec;
+
+struct iio_channel {
+	struct iio_dev *indio_dev;
+	const struct iio_chan_spec *channel;
+};
+
+extern struct list_head iio_map_list;
+
+struct iio_map {
+	/* iio device side */
+	struct device *adc_dev;
+	const char *adc_dev_name;
+	const char *adc_channel_label;
+	int channel_number; /*naughty starting point */
+
+	/* consumer side */
+	struct device *consumer_dev;
+	const char *consumer_dev_name;
+	const char *consumer_channel;
+	/* management - probably neater ways of doing this */
+	struct list_head l;
+};
+
+void iio_map_array_register(struct iio_map *map, int nummaps);
+/**
+ * iio_channel_get() - get an opaque reference to a specified device.
+ */
+struct iio_channel *iio_channel_get(const struct device *dev,
+				    const char *name,
+				    const char *consumer_channel);
+void iio_channel_release(struct iio_channel *chan);
+
+/**
+ * iio_channel_get_all() - get all channels associated with a client
+ *
+ * returns a null terminated array of pointers to iio_channel structures.
+ */
+struct iio_channel **iio_channel_get_all(const struct device *dev,
+					const char *name);
+
+void iio_channel_release_all(struct iio_channel **chan);
+
+/**
+ * iio_st_read_channel_raw() - read from a given channel
+ * @channel:	the channel being queried.
+ * @val:	value read back.
+ *
+ * Note raw reads from iio channels are in adc counts and hence
+ * scale will need to be applied if standard units required.
+ *
+ * Maybe want to pass the type as a sanity check.
+ */
+int iio_read_channel_raw(struct iio_channel *chan,
+			    int *val);
+
+/**
+ * iio_get_channel_type() - get the type of a channel
+ * @channel:	the channel being queried.
+ *
+ * returns the enum iio_chan_type of the channel
+ */
+enum iio_chan_type iio_get_channel_type(struct iio_channel *channel);
+
+/**
+ * iio_read_channel_scale() - read the scale value for a channel
+ * @channel:	the channel being queried.
+ * @val:	first part of value read back.
+ * @val2:	second part of value read back.
+ *
+ * Note returns a description of what is in val and val2, such
+ * as IIO_VAL_INT_PLUS_MICRO telling us we have a value of val
+ * + val2/1e6
+ */
+int iio_read_channel_scale(struct iio_channel *chan, int *val,
+			      int *val2);
+
+#endif
-- 
1.7.7.2


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

* [lm-sensors] [PATCH 3/5] IIO:CORE add in kernel interface mapping
@ 2011-11-07 15:44   ` Jonathan Cameron
  0 siblings, 0 replies; 32+ messages in thread
From: Jonathan Cameron @ 2011-11-07 15:44 UTC (permalink / raw)
  To: linux-iio, linux-kernel
  Cc: guenter.roeck, khali, dmitry.torokhov, broonie, gregkh, alan,
	arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

From: Jonathan Cameron <jic23@cam.ac.uk>

Two elements here:
* Map as defined in include/linux/iio/inkern.h
* Matching code to actually get the iio_dev and channel
that we want from the global list of IIO devices.

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/Makefile           |    2 +-
 drivers/iio/Makefile       |    1 +
 drivers/iio/iio.c          |  264 +++++++++++++++++++++++++++++++++++++++++++-
 drivers/iio/inkern.c       |   20 ++++
 include/linux/iio/iio.h    |    6 +-
 include/linux/iio/inkern.h |   95 ++++++++++++++++
 6 files changed, 381 insertions(+), 7 deletions(-)

diff --git a/drivers/Makefile b/drivers/Makefile
index 216bba4..cf3d1f7 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -134,4 +134,4 @@ obj-$(CONFIG_HYPERV)		+= hv/
 
 obj-$(CONFIG_PM_DEVFREQ)	+= devfreq/
 
-obj-$(CONFIG_IIO)		+= iio/
+obj-y				+= iio/
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index db3c426..cfb588a 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -1,6 +1,7 @@
 #
 # Makefile for the Industrial I/O subsystem
 #
+obj-y = inkern.o
 
 obj-$(CONFIG_IIO) += iio.o
 industrialio-y := core.o
diff --git a/drivers/iio/iio.c b/drivers/iio/iio.c
index 9a98f5f..683a3db 100644
--- a/drivers/iio/iio.c
+++ b/drivers/iio/iio.c
@@ -12,8 +12,10 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/idr.h>
+#include <linux/err.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
+#include <linux/iio/inkern.h>
 
 static DEFINE_IDA(iio_ida);
 
@@ -66,6 +68,263 @@ static const char * const iio_chan_info_postfix[] = {
 	[IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW] = "quadrature_correction_raw",
 };
 
+static void iio_dev_release(struct device *device);
+static struct device_type iio_dev_type = {
+	.name = "iio_device",
+	.release = iio_dev_release,
+};
+
+static int iio_match_dev(struct device *dev, void *data)
+{
+	struct iio_dev *indio_dev;
+	struct device *dev2 = data;
+
+	if (dev->type != &iio_dev_type)
+		return 0;
+
+	indio_dev = container_of(dev, struct iio_dev, dev);
+	if (indio_dev->info->get_hardware_id)
+		return indio_dev->info->get_hardware_id(indio_dev) = dev2;
+	else
+		return indio_dev->dev.parent = dev2;
+}
+
+static int iio_match_dev_name(struct device *dev, void *data)
+{
+	struct iio_dev *indio_dev;
+	const char *name = data;
+
+	if (dev->type != &iio_dev_type)
+		return 0;
+
+	indio_dev = container_of(dev, struct iio_dev, dev);
+	if (indio_dev->info->get_hardware_id)
+		return !strcmp(dev_name(indio_dev->info
+					->get_hardware_id(indio_dev)),
+			       name);
+	else if (indio_dev->dev.parent)
+		return !strcmp(dev_name(indio_dev->dev.parent), name);
+	return 0;
+}
+
+static const struct iio_chan_spec
+*iio_chan_spec_from_name(const struct iio_dev *indio_dev,
+			 const char *name)
+{
+	int i;
+	const struct iio_chan_spec *chan = NULL;
+	for (i = 0; i < indio_dev->num_channels; i++)
+		if (indio_dev->channels[i].datasheet_name &&
+		    strcmp(name, indio_dev->channels[i].datasheet_name) = 0) {
+			chan = &indio_dev->channels[i];
+			break;
+		}
+	return chan;
+}
+
+struct iio_channel *iio_channel_get(const struct device *dev,
+				    const char *name,
+				    const char *channel_name)
+{
+	struct iio_map *c_i = NULL, *c = NULL;
+	struct device *dev_i;
+	struct iio_channel *channel;
+
+	if (dev = NULL && name = NULL && channel_name = NULL)
+		return ERR_PTR(-ENODEV);
+	/* first find matching entry the channel map */
+	list_for_each_entry(c_i, &iio_map_list, l) {
+		if ((dev && dev != c_i->consumer_dev) ||
+		    (name && strcmp(name, c_i->consumer_dev_name) != 0) ||
+		    (channel_name &&
+		     strcmp(channel_name, c_i->consumer_channel) != 0))
+			continue;
+		c = c_i;
+		break;
+	}
+	if (c = NULL)
+		return ERR_PTR(-ENODEV);
+
+	/* now find the iio device if it has been registered */
+	if (c->adc_dev)
+		dev_i = bus_find_device(&iio_bus_type, NULL, c->adc_dev,
+					&iio_match_dev);
+	else if (c->adc_dev_name)
+		dev_i = bus_find_device(&iio_bus_type, NULL,
+					(void *)c->adc_dev_name,
+					&iio_match_dev_name);
+	else
+		return ERR_PTR(-EINVAL);
+	if (IS_ERR(dev_i))
+		return (void *)dev_i;
+	if (dev_i = NULL)
+		return ERR_PTR(-ENODEV);
+
+	channel = kmalloc(sizeof(*channel), GFP_KERNEL);
+	if (channel = NULL)
+		return ERR_PTR(-ENOMEM);
+
+	channel->indio_dev = container_of(dev_i, struct iio_dev, dev);
+
+	if (c->adc_channel_label)
+		channel->channel +			iio_chan_spec_from_name(channel->indio_dev,
+						c->adc_channel_label);
+	if (channel->channel = NULL)
+		channel->channel +			&channel->indio_dev->channels[c->channel_number];
+
+	return channel;
+}
+EXPORT_SYMBOL_GPL(iio_channel_get);
+
+void iio_channel_release(struct iio_channel *channel)
+{
+	put_device(&channel->indio_dev->dev);
+	kfree(channel);
+}
+EXPORT_SYMBOL_GPL(iio_channel_release);
+
+struct iio_channel **iio_channel_get_all(const struct device *dev,
+					const char *name)
+{
+	struct iio_channel **chans;
+	struct iio_map *c = NULL;
+	int nummaps = 0;
+	int mapind = 0;
+	int i, ret;
+	struct device *dev_i;
+
+	if (dev = NULL && name = NULL) {
+		ret = -EINVAL;
+		goto error_ret;
+	}
+
+	/* first count the matching maps */
+	list_for_each_entry(c, &iio_map_list, l)
+		if ((dev && dev != c->consumer_dev) ||
+		    (name && strcmp(name, c->consumer_dev_name) != 0))
+			continue;
+		else
+			nummaps++;
+
+	if (nummaps = 0) {
+		ret = -ENODEV;
+		goto error_ret;
+	}
+
+	/* for each map fill in the chans element */
+	chans = kzalloc(sizeof(*chans)*(nummaps + 1), GFP_KERNEL);
+	if (chans = NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	for (i = 0; i < nummaps; i++) {
+		chans[i] = kzalloc(sizeof(*chans[0]), GFP_KERNEL);
+		if (chans[i] = NULL) {
+			ret = -ENOMEM;
+			goto error_free_chans;
+		}
+	}
+
+	/* for each map fill in the chans element */
+	list_for_each_entry(c, &iio_map_list, l) {
+		dev_i = NULL;
+		if (dev && dev != c->consumer_dev)
+			continue;
+		if (name && strcmp(name, c->consumer_dev_name) != 0)
+			continue;
+		while (1) {
+			if (c->adc_dev) {
+				dev_i = bus_find_device(&iio_bus_type,
+							dev_i,
+							c->adc_dev,
+							&iio_match_dev);
+			} else if (c->adc_dev_name) {
+				dev_i = bus_find_device(&iio_bus_type,
+							dev_i,
+							(void *)c->adc_dev_name,
+							&iio_match_dev_name);
+			} else {
+				ret = -EINVAL;
+				goto error_free_chans;
+			}
+			if (IS_ERR(dev_i)) {
+				ret = PTR_ERR(dev_i);
+				goto error_free_chans;
+			}
+			if (dev_i = NULL)
+				break;
+
+			chans[mapind]->indio_dev +				container_of(dev_i, struct iio_dev, dev);
+			chans[mapind]->channel +				iio_chan_spec_from_name(chans[mapind]->
+							indio_dev,
+							c->adc_channel_label);
+			if (chans[mapind]->channel = NULL) {
+				ret = -EINVAL;
+				put_device(&chans[mapind]->indio_dev->dev);
+				goto error_free_chans;
+			}
+			mapind++;
+		}
+	}
+	return chans;
+
+error_free_chans:
+	for (i = 0; i < nummaps; i++)
+		if (chans[i]) {
+			put_device(&chans[i]->indio_dev->dev);
+			kfree(chans[i]);
+		}
+	kfree(chans);
+error_ret:
+
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(iio_channel_get_all);
+
+void iio_channel_release_all(struct iio_channel **channels)
+{
+	int i = 0;
+	struct iio_channel *chan = channels[i];
+
+	while (chan) {
+		put_device(&chan->indio_dev->dev);
+		kfree(chan);
+		i++;
+		chan = channels[i];
+	}
+	kfree(channels);
+}
+EXPORT_SYMBOL_GPL(iio_channel_release_all);
+
+int iio_read_channel_raw(struct iio_channel *chan, int *val)
+{
+	int val2;
+	return chan->indio_dev->info->read_raw(chan->indio_dev, chan->channel,
+					       val, &val2, 0);
+}
+EXPORT_SYMBOL_GPL(iio_read_channel_raw);
+
+int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2)
+{
+	/* Does this channel have shared scale? */
+	return chan->indio_dev
+		->info->read_raw(chan->indio_dev,
+				 chan->channel,
+				 val, val2,
+				 (1 << IIO_CHAN_INFO_SCALE));
+}
+EXPORT_SYMBOL_GPL(iio_read_channel_scale);
+
+enum iio_chan_type iio_get_channel_type(struct iio_channel *channel)
+{
+	return channel->channel->type;
+}
+EXPORT_SYMBOL_GPL(iio_get_channel_type);
+
 static void iio_device_free_read_attr(struct iio_dev *indio_dev,
 						 struct iio_dev_attr *p)
 {
@@ -91,11 +350,6 @@ static void iio_dev_release(struct device *device)
 	iio_device_unregister_sysfs(indio_dev);
 }
 
-static struct device_type iio_dev_type = {
-	.name = "iio_device",
-	.release = iio_dev_release,
-};
-
 struct iio_dev *iio_device_allocate(int sizeof_priv)
 {
 	struct iio_dev *dev;
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
new file mode 100644
index 0000000..b7c2788
--- /dev/null
+++ b/drivers/iio/inkern.c
@@ -0,0 +1,20 @@
+/* The industrial I/O core in kernel channel mapping
+ *
+ * Copyright (c) 2011 Jonathan Cameron
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/iio/inkern.h>
+#include <linux/err.h>
+
+LIST_HEAD(iio_map_list);
+EXPORT_SYMBOL_GPL(iio_map_list);
+void iio_map_array_register(struct iio_map *map, int nummaps)
+{
+	int i;
+	for (i = 0; i < nummaps; i++)
+		list_add(&map[i].l, &iio_map_list);
+}
+EXPORT_SYMBOL(iio_map_array_register);
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index 36a50b2..875704d 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -147,7 +147,10 @@ struct iio_dev;
  * @write_raw_get_fmt:	callback function to query the expected
  *			format/precision. If not set by the driver, write_raw
  *			returns IIO_VAL_INT_PLUS_MICRO.
- **/
+ * @get_hardware_id:	obtain device relating to hardware. Typically based on
+ *			the parent device (actual hardware).  Note that if
+ *			not specified then iio_dev.dev->parent is used.
+ */
 struct iio_info {
 	struct module			*driver_module;
 	const struct attribute_group	*attrs;
@@ -167,6 +170,7 @@ struct iio_info {
 	int (*write_raw_get_fmt)(struct iio_dev *indio_dev,
 			 struct iio_chan_spec const *chan,
 			 long mask);
+	struct device *(*get_hardware_id)(struct iio_dev *indio_dev);
 };
 
 /**
diff --git a/include/linux/iio/inkern.h b/include/linux/iio/inkern.h
new file mode 100644
index 0000000..de15c00
--- /dev/null
+++ b/include/linux/iio/inkern.h
@@ -0,0 +1,95 @@
+/*
+ * The industrial I/O core - in kernel channel mapping infrastructure
+ *
+ * Copyright (c) 2011 Jonathan Cameron
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#ifndef _IIO_INKERN_H_
+#define _IIO_INKERN_H_
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/iio/types.h>
+
+struct iio_dev;
+struct iio_chan_spec;
+
+struct iio_channel {
+	struct iio_dev *indio_dev;
+	const struct iio_chan_spec *channel;
+};
+
+extern struct list_head iio_map_list;
+
+struct iio_map {
+	/* iio device side */
+	struct device *adc_dev;
+	const char *adc_dev_name;
+	const char *adc_channel_label;
+	int channel_number; /*naughty starting point */
+
+	/* consumer side */
+	struct device *consumer_dev;
+	const char *consumer_dev_name;
+	const char *consumer_channel;
+	/* management - probably neater ways of doing this */
+	struct list_head l;
+};
+
+void iio_map_array_register(struct iio_map *map, int nummaps);
+/**
+ * iio_channel_get() - get an opaque reference to a specified device.
+ */
+struct iio_channel *iio_channel_get(const struct device *dev,
+				    const char *name,
+				    const char *consumer_channel);
+void iio_channel_release(struct iio_channel *chan);
+
+/**
+ * iio_channel_get_all() - get all channels associated with a client
+ *
+ * returns a null terminated array of pointers to iio_channel structures.
+ */
+struct iio_channel **iio_channel_get_all(const struct device *dev,
+					const char *name);
+
+void iio_channel_release_all(struct iio_channel **chan);
+
+/**
+ * iio_st_read_channel_raw() - read from a given channel
+ * @channel:	the channel being queried.
+ * @val:	value read back.
+ *
+ * Note raw reads from iio channels are in adc counts and hence
+ * scale will need to be applied if standard units required.
+ *
+ * Maybe want to pass the type as a sanity check.
+ */
+int iio_read_channel_raw(struct iio_channel *chan,
+			    int *val);
+
+/**
+ * iio_get_channel_type() - get the type of a channel
+ * @channel:	the channel being queried.
+ *
+ * returns the enum iio_chan_type of the channel
+ */
+enum iio_chan_type iio_get_channel_type(struct iio_channel *channel);
+
+/**
+ * iio_read_channel_scale() - read the scale value for a channel
+ * @channel:	the channel being queried.
+ * @val:	first part of value read back.
+ * @val2:	second part of value read back.
+ *
+ * Note returns a description of what is in val and val2, such
+ * as IIO_VAL_INT_PLUS_MICRO telling us we have a value of val
+ * + val2/1e6
+ */
+int iio_read_channel_scale(struct iio_channel *chan, int *val,
+			      int *val2);
+
+#endif
-- 
1.7.7.2


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* [PATCH 4/5] IIO:hwmon interface client driver.
  2011-11-07 15:44 ` [lm-sensors] " Jonathan Cameron
@ 2011-11-07 15:44   ` Jonathan Cameron
  -1 siblings, 0 replies; 32+ messages in thread
From: Jonathan Cameron @ 2011-11-07 15:44 UTC (permalink / raw)
  To: linux-iio, linux-kernel
  Cc: guenter.roeck, khali, dmitry.torokhov, broonie, gregkh, alan,
	arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

From: Jonathan Cameron <jic23@cam.ac.uk>

Should move to drivers/hwmon once people are happy with it.

Minimal support of simple in, curr and temp attributes
so far.

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/iio/Kconfig     |    8 ++
 drivers/iio/Makefile    |    1 +
 drivers/iio/iio_hwmon.c |  227 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 236 insertions(+), 0 deletions(-)

diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index 308bc97..c2f0970 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -11,6 +11,14 @@ menuconfig IIO
 
 if IIO
 
+config IIO_HWMON
+       tristate "Hwmon driver that uses channels specified via iio maps"
+       depends on HWMON
+       help
+	  This is a platform driver that in combination with a suitable
+	  map allows IIO devices to provide  basic hwmon functionality
+	  for those channels specified in the map.
+
 source "drivers/iio/adc/Kconfig"
 source "drivers/iio/imu/Kconfig"
 source "drivers/iio/light/Kconfig"
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index cfb588a..5f9c01a 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -6,6 +6,7 @@ obj-y = inkern.o
 obj-$(CONFIG_IIO) += iio.o
 industrialio-y := core.o
 
+obj-$(CONFIG_IIO_HWMON) += iio_hwmon.o
 obj-y += adc/
 obj-y += imu/
 obj-y += light/
diff --git a/drivers/iio/iio_hwmon.c b/drivers/iio/iio_hwmon.c
new file mode 100644
index 0000000..4bd7651
--- /dev/null
+++ b/drivers/iio/iio_hwmon.c
@@ -0,0 +1,227 @@
+/* Hwmon client for industrial I/O devices
+ *
+ * Copyright (c) 2011 Jonathan Cameron
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * Limited functionality currently supported.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/iio/inkern.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+/**
+ * struct iio_hwmon_state - device instance state
+ * @channels:		filled with null terminated array of channels from iio
+ * @num_channels:	number of channels in channels (saves counting twice)
+ * @hwmon_dev:		associated hwmon device
+ * @attr_group:	the group of attributes
+ * @attrs:		null terminated array of attribute pointers.
+ */
+struct iio_hwmon_state {
+	struct iio_channel **channels;
+	int num_channels;
+	struct device *hwmon_dev;
+	struct attribute_group attr_group;
+	struct attribute **attrs;
+};
+
+/*
+ * Assumes that IIO and hwmon operate in the same base units.
+ * This is supposed to be true, but needs verification for
+ * new channel types.
+ */
+static ssize_t iio_hwmon_read_val(struct device *dev,
+				  struct device_attribute *attr,
+				  char *buf)
+{
+	long result;
+	int val, ret, scaleint, scalepart;
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	struct iio_hwmon_state *state = dev_get_drvdata(dev);
+
+	/*
+	 * No locking between this pair, so theoretically possible
+	 * the scale has changed.
+	 */
+	ret = iio_read_channel_raw(state->channels[sattr->index],
+				   &val);
+	if (ret < 0)
+		return ret;
+
+	ret = iio_read_channel_scale(state->channels[sattr->index],
+				     &scaleint, &scalepart);
+	if (ret < 0)
+		return ret;
+	switch (ret) {
+	case IIO_VAL_INT:
+		result = val * scaleint;
+		break;
+	case IIO_VAL_INT_PLUS_MICRO:
+		result = (long)val * (long)scaleint +
+			div_s64((s64)val * (s64)scalepart, 1000000LL);
+		break;
+	case IIO_VAL_INT_PLUS_NANO:
+		result = (long)val * (long)scaleint +
+			div_s64((s64)val * (s64)scalepart, 1000000000LL);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return sprintf(buf, "%ld\n", result);
+}
+
+static void iio_hwmon_free_attrs(struct iio_hwmon_state *st)
+{
+	int i;
+	struct sensor_device_attribute *a;
+	for (i = 0; i < st->num_channels; i++)
+		if (st->attrs[i]) {
+			a = to_sensor_dev_attr(
+				container_of(st->attrs[i],
+					     struct device_attribute,
+					     attr));
+			kfree(a);
+		}
+}
+
+static int __devinit iio_hwmon_probe(struct platform_device *pdev)
+{
+	struct iio_hwmon_state *st;
+	struct sensor_device_attribute *a;
+	int ret, i;
+	int in_i = 1, temp_i = 1, curr_i = 1;
+
+	st = kzalloc(sizeof(*st), GFP_KERNEL);
+	if (st == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+
+	st->channels = iio_channel_get_all(&pdev->dev, NULL);
+	if (IS_ERR(st->channels)) {
+		ret = PTR_ERR(st->channels);
+		goto error_free_state;
+	}
+
+	/* count how many attributes we have */
+	while (st->channels[st->num_channels])
+		st->num_channels++;
+
+	st->attrs = kzalloc(sizeof(st->attrs) * (st->num_channels + 1),
+			    GFP_KERNEL);
+	if (st->attrs == NULL) {
+		ret = -ENOMEM;
+		goto error_release_channels;
+	}
+	for (i = 0; i < st->num_channels; i++) {
+		a = kzalloc(sizeof(*a), GFP_KERNEL);
+		if (a == NULL) {
+			ret = -ENOMEM;
+			goto error_free_attrs;
+		}
+
+		sysfs_attr_init(&a->dev_attr.attr);
+		switch (iio_get_channel_type(st->channels[i])) {
+		case IIO_VOLTAGE:
+			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
+							  "in%d_input",
+							  in_i++);
+			break;
+		case IIO_TEMP:
+			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
+							  "temp%d_input",
+							  temp_i++);
+			break;
+		case IIO_CURRENT:
+			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
+							  "curr%d_input",
+							  curr_i++);
+			break;
+		default:
+			ret = -EINVAL;
+			kfree(a);
+			goto error_free_attrs;
+		}
+		if (a->dev_attr.attr.name == NULL) {
+			kfree(a);
+			ret = -ENOMEM;
+			goto error_free_attrs;
+		}
+		a->dev_attr.show = iio_hwmon_read_val;
+		a->dev_attr.attr.mode = S_IRUGO;
+		a->index = i;
+		st->attrs[i] = &a->dev_attr.attr;
+	}
+
+	st->attr_group.attrs = st->attrs;
+	platform_set_drvdata(pdev, st);
+	ret = sysfs_create_group(&pdev->dev.kobj, &st->attr_group);
+	if (ret < 0)
+		goto error_free_attrs;
+
+	st->hwmon_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(st->hwmon_dev)) {
+		ret = PTR_ERR(st->hwmon_dev);
+		goto error_remove_group;
+	}
+	return 0;
+
+error_remove_group:
+	sysfs_remove_group(&pdev->dev.kobj, &st->attr_group);
+error_free_attrs:
+	iio_hwmon_free_attrs(st);
+	kfree(st->attrs);
+error_release_channels:
+	iio_channel_release_all(st->channels);
+error_free_state:
+	kfree(st);
+error_ret:
+	return ret;
+}
+
+static int __devexit iio_hwmon_remove(struct platform_device *pdev)
+{
+	struct iio_hwmon_state *st = platform_get_drvdata(pdev);
+
+	hwmon_device_unregister(st->hwmon_dev);
+	sysfs_remove_group(&pdev->dev.kobj, &st->attr_group);
+	iio_hwmon_free_attrs(st);
+	kfree(st->attrs);
+	iio_channel_release_all(st->channels);
+
+	return 0;
+}
+
+static struct platform_driver __refdata iio_hwmon_driver = {
+	.driver = {
+		.name = "iio_hwmon",
+		.owner = THIS_MODULE,
+	},
+	.probe = iio_hwmon_probe,
+	.remove = __devexit_p(iio_hwmon_remove),
+};
+
+static int iio_inkern_init(void)
+{
+	return platform_driver_register(&iio_hwmon_driver);
+}
+module_init(iio_inkern_init);
+
+static void iio_inkern_exit(void)
+{
+	platform_driver_unregister(&iio_hwmon_driver);
+}
+module_exit(iio_inkern_exit);
+
+MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
+MODULE_DESCRIPTION("IIO to hwmon driver");
+MODULE_LICENSE("GPL v2");
-- 
1.7.7.2


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

* [lm-sensors] [PATCH 4/5] IIO:hwmon interface client driver.
@ 2011-11-07 15:44   ` Jonathan Cameron
  0 siblings, 0 replies; 32+ messages in thread
From: Jonathan Cameron @ 2011-11-07 15:44 UTC (permalink / raw)
  To: linux-iio, linux-kernel
  Cc: guenter.roeck, khali, dmitry.torokhov, broonie, gregkh, alan,
	arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

From: Jonathan Cameron <jic23@cam.ac.uk>

Should move to drivers/hwmon once people are happy with it.

Minimal support of simple in, curr and temp attributes
so far.

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/iio/Kconfig     |    8 ++
 drivers/iio/Makefile    |    1 +
 drivers/iio/iio_hwmon.c |  227 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 236 insertions(+), 0 deletions(-)

diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index 308bc97..c2f0970 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -11,6 +11,14 @@ menuconfig IIO
 
 if IIO
 
+config IIO_HWMON
+       tristate "Hwmon driver that uses channels specified via iio maps"
+       depends on HWMON
+       help
+	  This is a platform driver that in combination with a suitable
+	  map allows IIO devices to provide  basic hwmon functionality
+	  for those channels specified in the map.
+
 source "drivers/iio/adc/Kconfig"
 source "drivers/iio/imu/Kconfig"
 source "drivers/iio/light/Kconfig"
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index cfb588a..5f9c01a 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -6,6 +6,7 @@ obj-y = inkern.o
 obj-$(CONFIG_IIO) += iio.o
 industrialio-y := core.o
 
+obj-$(CONFIG_IIO_HWMON) += iio_hwmon.o
 obj-y += adc/
 obj-y += imu/
 obj-y += light/
diff --git a/drivers/iio/iio_hwmon.c b/drivers/iio/iio_hwmon.c
new file mode 100644
index 0000000..4bd7651
--- /dev/null
+++ b/drivers/iio/iio_hwmon.c
@@ -0,0 +1,227 @@
+/* Hwmon client for industrial I/O devices
+ *
+ * Copyright (c) 2011 Jonathan Cameron
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * Limited functionality currently supported.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/iio/inkern.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+/**
+ * struct iio_hwmon_state - device instance state
+ * @channels:		filled with null terminated array of channels from iio
+ * @num_channels:	number of channels in channels (saves counting twice)
+ * @hwmon_dev:		associated hwmon device
+ * @attr_group:	the group of attributes
+ * @attrs:		null terminated array of attribute pointers.
+ */
+struct iio_hwmon_state {
+	struct iio_channel **channels;
+	int num_channels;
+	struct device *hwmon_dev;
+	struct attribute_group attr_group;
+	struct attribute **attrs;
+};
+
+/*
+ * Assumes that IIO and hwmon operate in the same base units.
+ * This is supposed to be true, but needs verification for
+ * new channel types.
+ */
+static ssize_t iio_hwmon_read_val(struct device *dev,
+				  struct device_attribute *attr,
+				  char *buf)
+{
+	long result;
+	int val, ret, scaleint, scalepart;
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	struct iio_hwmon_state *state = dev_get_drvdata(dev);
+
+	/*
+	 * No locking between this pair, so theoretically possible
+	 * the scale has changed.
+	 */
+	ret = iio_read_channel_raw(state->channels[sattr->index],
+				   &val);
+	if (ret < 0)
+		return ret;
+
+	ret = iio_read_channel_scale(state->channels[sattr->index],
+				     &scaleint, &scalepart);
+	if (ret < 0)
+		return ret;
+	switch (ret) {
+	case IIO_VAL_INT:
+		result = val * scaleint;
+		break;
+	case IIO_VAL_INT_PLUS_MICRO:
+		result = (long)val * (long)scaleint +
+			div_s64((s64)val * (s64)scalepart, 1000000LL);
+		break;
+	case IIO_VAL_INT_PLUS_NANO:
+		result = (long)val * (long)scaleint +
+			div_s64((s64)val * (s64)scalepart, 1000000000LL);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return sprintf(buf, "%ld\n", result);
+}
+
+static void iio_hwmon_free_attrs(struct iio_hwmon_state *st)
+{
+	int i;
+	struct sensor_device_attribute *a;
+	for (i = 0; i < st->num_channels; i++)
+		if (st->attrs[i]) {
+			a = to_sensor_dev_attr(
+				container_of(st->attrs[i],
+					     struct device_attribute,
+					     attr));
+			kfree(a);
+		}
+}
+
+static int __devinit iio_hwmon_probe(struct platform_device *pdev)
+{
+	struct iio_hwmon_state *st;
+	struct sensor_device_attribute *a;
+	int ret, i;
+	int in_i = 1, temp_i = 1, curr_i = 1;
+
+	st = kzalloc(sizeof(*st), GFP_KERNEL);
+	if (st = NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+
+	st->channels = iio_channel_get_all(&pdev->dev, NULL);
+	if (IS_ERR(st->channels)) {
+		ret = PTR_ERR(st->channels);
+		goto error_free_state;
+	}
+
+	/* count how many attributes we have */
+	while (st->channels[st->num_channels])
+		st->num_channels++;
+
+	st->attrs = kzalloc(sizeof(st->attrs) * (st->num_channels + 1),
+			    GFP_KERNEL);
+	if (st->attrs = NULL) {
+		ret = -ENOMEM;
+		goto error_release_channels;
+	}
+	for (i = 0; i < st->num_channels; i++) {
+		a = kzalloc(sizeof(*a), GFP_KERNEL);
+		if (a = NULL) {
+			ret = -ENOMEM;
+			goto error_free_attrs;
+		}
+
+		sysfs_attr_init(&a->dev_attr.attr);
+		switch (iio_get_channel_type(st->channels[i])) {
+		case IIO_VOLTAGE:
+			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
+							  "in%d_input",
+							  in_i++);
+			break;
+		case IIO_TEMP:
+			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
+							  "temp%d_input",
+							  temp_i++);
+			break;
+		case IIO_CURRENT:
+			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
+							  "curr%d_input",
+							  curr_i++);
+			break;
+		default:
+			ret = -EINVAL;
+			kfree(a);
+			goto error_free_attrs;
+		}
+		if (a->dev_attr.attr.name = NULL) {
+			kfree(a);
+			ret = -ENOMEM;
+			goto error_free_attrs;
+		}
+		a->dev_attr.show = iio_hwmon_read_val;
+		a->dev_attr.attr.mode = S_IRUGO;
+		a->index = i;
+		st->attrs[i] = &a->dev_attr.attr;
+	}
+
+	st->attr_group.attrs = st->attrs;
+	platform_set_drvdata(pdev, st);
+	ret = sysfs_create_group(&pdev->dev.kobj, &st->attr_group);
+	if (ret < 0)
+		goto error_free_attrs;
+
+	st->hwmon_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(st->hwmon_dev)) {
+		ret = PTR_ERR(st->hwmon_dev);
+		goto error_remove_group;
+	}
+	return 0;
+
+error_remove_group:
+	sysfs_remove_group(&pdev->dev.kobj, &st->attr_group);
+error_free_attrs:
+	iio_hwmon_free_attrs(st);
+	kfree(st->attrs);
+error_release_channels:
+	iio_channel_release_all(st->channels);
+error_free_state:
+	kfree(st);
+error_ret:
+	return ret;
+}
+
+static int __devexit iio_hwmon_remove(struct platform_device *pdev)
+{
+	struct iio_hwmon_state *st = platform_get_drvdata(pdev);
+
+	hwmon_device_unregister(st->hwmon_dev);
+	sysfs_remove_group(&pdev->dev.kobj, &st->attr_group);
+	iio_hwmon_free_attrs(st);
+	kfree(st->attrs);
+	iio_channel_release_all(st->channels);
+
+	return 0;
+}
+
+static struct platform_driver __refdata iio_hwmon_driver = {
+	.driver = {
+		.name = "iio_hwmon",
+		.owner = THIS_MODULE,
+	},
+	.probe = iio_hwmon_probe,
+	.remove = __devexit_p(iio_hwmon_remove),
+};
+
+static int iio_inkern_init(void)
+{
+	return platform_driver_register(&iio_hwmon_driver);
+}
+module_init(iio_inkern_init);
+
+static void iio_inkern_exit(void)
+{
+	platform_driver_unregister(&iio_hwmon_driver);
+}
+module_exit(iio_inkern_exit);
+
+MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
+MODULE_DESCRIPTION("IIO to hwmon driver");
+MODULE_LICENSE("GPL v2");
-- 
1.7.7.2


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* [PATCH 5/5] stargate2: example of map configuration for iio to hwmon example.
  2011-11-07 15:44 ` [lm-sensors] " Jonathan Cameron
@ 2011-11-07 15:44   ` Jonathan Cameron
  -1 siblings, 0 replies; 32+ messages in thread
From: Jonathan Cameron @ 2011-11-07 15:44 UTC (permalink / raw)
  To: linux-iio, linux-kernel
  Cc: guenter.roeck, khali, dmitry.torokhov, broonie, gregkh, alan,
	arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

From: Jonathan Cameron <jic23@cam.ac.uk>

Do not commit.
---
 arch/arm/mach-pxa/stargate2.c |   23 +++++++++++++++++++++++
 1 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c
index 4c9a48b..25a69c7 100644
--- a/arch/arm/mach-pxa/stargate2.c
+++ b/arch/arm/mach-pxa/stargate2.c
@@ -54,6 +54,8 @@
 #include <linux/mfd/da903x.h>
 #include <linux/sht15.h>
 
+#include <linux/iio/inkern.h>
+
 #include "devices.h"
 #include "generic.h"
 
@@ -406,6 +408,24 @@ static struct i2c_pxa_platform_data i2c_pdata = {
 	.fast_mode = 1,
 };
 
+static struct platform_device iio_hwmon_test = {
+	.name = "iio_hwmon",
+};
+
+static struct iio_map adc_map[] = {
+	{
+		.adc_dev_name = "0-0035",
+		.adc_channel_label = "AIN1",
+		.consumer_dev = &iio_hwmon_test.dev,
+		.consumer_channel = "testchan1",
+	}, {
+		.adc_dev_name = "0-0035",
+		.adc_channel_label = "AIN2",
+		.consumer_dev = &iio_hwmon_test.dev,
+		.consumer_channel = "testchan2",
+	},
+};
+
 static void __init imote2_stargate2_init(void)
 {
 
@@ -423,6 +443,8 @@ static void __init imote2_stargate2_init(void)
 
 	pxa27x_set_i2c_power_info(&i2c_pwr_pdata);
 	pxa_set_i2c_info(&i2c_pdata);
+
+	iio_map_array_register(adc_map, ARRAY_SIZE(adc_map));
 }
 
 #ifdef CONFIG_MACH_INTELMOTE2
@@ -971,6 +993,7 @@ static struct platform_device *stargate2_devices[] = {
 	&stargate2_sram,
 	&smc91x_device,
 	&sht15,
+	&iio_hwmon_test,
 };
 
 static void __init stargate2_init(void)
-- 
1.7.7.2


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

* [lm-sensors] [PATCH 5/5] stargate2: example of map configuration
@ 2011-11-07 15:44   ` Jonathan Cameron
  0 siblings, 0 replies; 32+ messages in thread
From: Jonathan Cameron @ 2011-11-07 15:44 UTC (permalink / raw)
  To: linux-iio, linux-kernel
  Cc: guenter.roeck, khali, dmitry.torokhov, broonie, gregkh, alan,
	arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

From: Jonathan Cameron <jic23@cam.ac.uk>

Do not commit.
---
 arch/arm/mach-pxa/stargate2.c |   23 +++++++++++++++++++++++
 1 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c
index 4c9a48b..25a69c7 100644
--- a/arch/arm/mach-pxa/stargate2.c
+++ b/arch/arm/mach-pxa/stargate2.c
@@ -54,6 +54,8 @@
 #include <linux/mfd/da903x.h>
 #include <linux/sht15.h>
 
+#include <linux/iio/inkern.h>
+
 #include "devices.h"
 #include "generic.h"
 
@@ -406,6 +408,24 @@ static struct i2c_pxa_platform_data i2c_pdata = {
 	.fast_mode = 1,
 };
 
+static struct platform_device iio_hwmon_test = {
+	.name = "iio_hwmon",
+};
+
+static struct iio_map adc_map[] = {
+	{
+		.adc_dev_name = "0-0035",
+		.adc_channel_label = "AIN1",
+		.consumer_dev = &iio_hwmon_test.dev,
+		.consumer_channel = "testchan1",
+	}, {
+		.adc_dev_name = "0-0035",
+		.adc_channel_label = "AIN2",
+		.consumer_dev = &iio_hwmon_test.dev,
+		.consumer_channel = "testchan2",
+	},
+};
+
 static void __init imote2_stargate2_init(void)
 {
 
@@ -423,6 +443,8 @@ static void __init imote2_stargate2_init(void)
 
 	pxa27x_set_i2c_power_info(&i2c_pwr_pdata);
 	pxa_set_i2c_info(&i2c_pdata);
+
+	iio_map_array_register(adc_map, ARRAY_SIZE(adc_map));
 }
 
 #ifdef CONFIG_MACH_INTELMOTE2
@@ -971,6 +993,7 @@ static struct platform_device *stargate2_devices[] = {
 	&stargate2_sram,
 	&smc91x_device,
 	&sht15,
+	&iio_hwmon_test,
 };
 
 static void __init stargate2_init(void)
-- 
1.7.7.2


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [PATCH 4/5] IIO:hwmon interface client driver.
  2011-11-07 15:44   ` [lm-sensors] " Jonathan Cameron
  (?)
@ 2011-11-07 16:29     ` Guenter Roeck
  -1 siblings, 0 replies; 32+ messages in thread
From: Guenter Roeck @ 2011-11-07 16:29 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio, linux-kernel, khali, dmitry.torokhov, broonie, gregkh,
	alan, arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

Hi Jonathan,

On Mon, 2011-11-07 at 10:44 -0500, Jonathan Cameron wrote:
> From: Jonathan Cameron <jic23@cam.ac.uk>
> 
> Should move to drivers/hwmon once people are happy with it.
> 
> Minimal support of simple in, curr and temp attributes
> so far.
> 
> Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
> ---
>  drivers/iio/Kconfig     |    8 ++
>  drivers/iio/Makefile    |    1 +
>  drivers/iio/iio_hwmon.c |  227 +++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 236 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
> index 308bc97..c2f0970 100644
> --- a/drivers/iio/Kconfig
> +++ b/drivers/iio/Kconfig
> @@ -11,6 +11,14 @@ menuconfig IIO
>  
>  if IIO
>  
> +config IIO_HWMON
> +       tristate "Hwmon driver that uses channels specified via iio maps"
> +       depends on HWMON
> +       help
> +	  This is a platform driver that in combination with a suitable
> +	  map allows IIO devices to provide  basic hwmon functionality
> +	  for those channels specified in the map.
> +
>  source "drivers/iio/adc/Kconfig"
>  source "drivers/iio/imu/Kconfig"
>  source "drivers/iio/light/Kconfig"
> diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
> index cfb588a..5f9c01a 100644
> --- a/drivers/iio/Makefile
> +++ b/drivers/iio/Makefile
> @@ -6,6 +6,7 @@ obj-y = inkern.o
>  obj-$(CONFIG_IIO) += iio.o
>  industrialio-y := core.o
>  
> +obj-$(CONFIG_IIO_HWMON) += iio_hwmon.o
>  obj-y += adc/
>  obj-y += imu/
>  obj-y += light/
> diff --git a/drivers/iio/iio_hwmon.c b/drivers/iio/iio_hwmon.c
> new file mode 100644
> index 0000000..4bd7651
> --- /dev/null
> +++ b/drivers/iio/iio_hwmon.c
> @@ -0,0 +1,227 @@
> +/* Hwmon client for industrial I/O devices
> + *
> + * Copyright (c) 2011 Jonathan Cameron
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published by
> + * the Free Software Foundation.
> + *
> + * Limited functionality currently supported.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/module.h>
> +#include <linux/err.h>
> +#include <linux/platform_device.h>
> +#include <linux/iio/inkern.h>
> +#include <linux/hwmon.h>
> +#include <linux/hwmon-sysfs.h>
> +
> +/**
> + * struct iio_hwmon_state - device instance state
> + * @channels:		filled with null terminated array of channels from iio
> + * @num_channels:	number of channels in channels (saves counting twice)
> + * @hwmon_dev:		associated hwmon device
> + * @attr_group:	the group of attributes
> + * @attrs:		null terminated array of attribute pointers.
> + */
> +struct iio_hwmon_state {
> +	struct iio_channel **channels;
> +	int num_channels;
> +	struct device *hwmon_dev;
> +	struct attribute_group attr_group;
> +	struct attribute **attrs;
> +};
> +
> +/*
> + * Assumes that IIO and hwmon operate in the same base units.
> + * This is supposed to be true, but needs verification for
> + * new channel types.
> + */
> +static ssize_t iio_hwmon_read_val(struct device *dev,
> +				  struct device_attribute *attr,
> +				  char *buf)
> +{
> +	long result;
> +	int val, ret, scaleint, scalepart;
> +	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
> +	struct iio_hwmon_state *state = dev_get_drvdata(dev);
> +
> +	/*
> +	 * No locking between this pair, so theoretically possible
> +	 * the scale has changed.
> +	 */
> +	ret = iio_read_channel_raw(state->channels[sattr->index],
> +				   &val);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = iio_read_channel_scale(state->channels[sattr->index],
> +				     &scaleint, &scalepart);
> +	if (ret < 0)
> +		return ret;
> +	switch (ret) {
> +	case IIO_VAL_INT:
> +		result = val * scaleint;
> +		break;
> +	case IIO_VAL_INT_PLUS_MICRO:
> +		result = (long)val * (long)scaleint +
> +			div_s64((s64)val * (s64)scalepart, 1000000LL);
> +		break;
> +	case IIO_VAL_INT_PLUS_NANO:
> +		result = (long)val * (long)scaleint +
> +			div_s64((s64)val * (s64)scalepart, 1000000000LL);
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +	return sprintf(buf, "%ld\n", result);
> +}
> +
> +static void iio_hwmon_free_attrs(struct iio_hwmon_state *st)
> +{
> +	int i;
> +	struct sensor_device_attribute *a;
> +	for (i = 0; i < st->num_channels; i++)
> +		if (st->attrs[i]) {
> +			a = to_sensor_dev_attr(
> +				container_of(st->attrs[i],
> +					     struct device_attribute,
> +					     attr));
> +			kfree(a);
> +		}
> +}
> +
> +static int __devinit iio_hwmon_probe(struct platform_device *pdev)
> +{
> +	struct iio_hwmon_state *st;
> +	struct sensor_device_attribute *a;
> +	int ret, i;
> +	int in_i = 1, temp_i = 1, curr_i = 1;
> +
> +	st = kzalloc(sizeof(*st), GFP_KERNEL);
> +	if (st == NULL) {
> +		ret = -ENOMEM;
> +		goto error_ret;
> +	}
> +
> +	st->channels = iio_channel_get_all(&pdev->dev, NULL);
> +	if (IS_ERR(st->channels)) {
> +		ret = PTR_ERR(st->channels);
> +		goto error_free_state;
> +	}
> +
> +	/* count how many attributes we have */
> +	while (st->channels[st->num_channels])
> +		st->num_channels++;
> +
> +	st->attrs = kzalloc(sizeof(st->attrs) * (st->num_channels + 1),
> +			    GFP_KERNEL);
> +	if (st->attrs == NULL) {
> +		ret = -ENOMEM;
> +		goto error_release_channels;
> +	}
> +	for (i = 0; i < st->num_channels; i++) {
> +		a = kzalloc(sizeof(*a), GFP_KERNEL);
> +		if (a == NULL) {
> +			ret = -ENOMEM;
> +			goto error_free_attrs;
> +		}
> +
> +		sysfs_attr_init(&a->dev_attr.attr);
> +		switch (iio_get_channel_type(st->channels[i])) {
> +		case IIO_VOLTAGE:
> +			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
> +							  "in%d_input",
> +							  in_i++);
> +			break;
> +		case IIO_TEMP:
> +			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
> +							  "temp%d_input",
> +							  temp_i++);
> +			break;
> +		case IIO_CURRENT:
> +			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
> +							  "curr%d_input",
> +							  curr_i++);
> +			break;
> +		default:
> +			ret = -EINVAL;
> +			kfree(a);
> +			goto error_free_attrs;
> +		}
> +		if (a->dev_attr.attr.name == NULL) {
> +			kfree(a);
> +			ret = -ENOMEM;
> +			goto error_free_attrs;
> +		}
> +		a->dev_attr.show = iio_hwmon_read_val;
> +		a->dev_attr.attr.mode = S_IRUGO;
> +		a->index = i;
> +		st->attrs[i] = &a->dev_attr.attr;
> +	}
> +
> +	st->attr_group.attrs = st->attrs;
> +	platform_set_drvdata(pdev, st);
> +	ret = sysfs_create_group(&pdev->dev.kobj, &st->attr_group);
> +	if (ret < 0)
> +		goto error_free_attrs;
> +
> +	st->hwmon_dev = hwmon_device_register(&pdev->dev);
> +	if (IS_ERR(st->hwmon_dev)) {
> +		ret = PTR_ERR(st->hwmon_dev);
> +		goto error_remove_group;
> +	}
> +	return 0;
> +
> +error_remove_group:
> +	sysfs_remove_group(&pdev->dev.kobj, &st->attr_group);
> +error_free_attrs:
> +	iio_hwmon_free_attrs(st);
> +	kfree(st->attrs);
> +error_release_channels:
> +	iio_channel_release_all(st->channels);
> +error_free_state:
> +	kfree(st);
> +error_ret:
> +	return ret;
> +}
> +
> +static int __devexit iio_hwmon_remove(struct platform_device *pdev)
> +{
> +	struct iio_hwmon_state *st = platform_get_drvdata(pdev);
> +
> +	hwmon_device_unregister(st->hwmon_dev);
> +	sysfs_remove_group(&pdev->dev.kobj, &st->attr_group);
> +	iio_hwmon_free_attrs(st);
> +	kfree(st->attrs);
> +	iio_channel_release_all(st->channels);
> +

Either I missed it before, or I am missing something now ... should
there be kfree(st) here ?

Thanks,
Guenter

> +	return 0;
> +}
> +
> +static struct platform_driver __refdata iio_hwmon_driver = {
> +	.driver = {
> +		.name = "iio_hwmon",
> +		.owner = THIS_MODULE,
> +	},
> +	.probe = iio_hwmon_probe,
> +	.remove = __devexit_p(iio_hwmon_remove),
> +};
> +
> +static int iio_inkern_init(void)
> +{
> +	return platform_driver_register(&iio_hwmon_driver);
> +}
> +module_init(iio_inkern_init);
> +
> +static void iio_inkern_exit(void)
> +{
> +	platform_driver_unregister(&iio_hwmon_driver);
> +}
> +module_exit(iio_inkern_exit);
> +
> +MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
> +MODULE_DESCRIPTION("IIO to hwmon driver");
> +MODULE_LICENSE("GPL v2");



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

* Re: [PATCH 4/5] IIO:hwmon interface client driver.
@ 2011-11-07 16:29     ` Guenter Roeck
  0 siblings, 0 replies; 32+ messages in thread
From: Guenter Roeck @ 2011-11-07 16:29 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio, linux-kernel, khali, dmitry.torokhov, broonie, gregkh,
	alan, arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

Hi Jonathan,

On Mon, 2011-11-07 at 10:44 -0500, Jonathan Cameron wrote:
> From: Jonathan Cameron <jic23@cam.ac.uk>
> 
> Should move to drivers/hwmon once people are happy with it.
> 
> Minimal support of simple in, curr and temp attributes
> so far.
> 
> Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
> ---
>  drivers/iio/Kconfig     |    8 ++
>  drivers/iio/Makefile    |    1 +
>  drivers/iio/iio_hwmon.c |  227 +++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 236 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
> index 308bc97..c2f0970 100644
> --- a/drivers/iio/Kconfig
> +++ b/drivers/iio/Kconfig
> @@ -11,6 +11,14 @@ menuconfig IIO
>  
>  if IIO
>  
> +config IIO_HWMON
> +       tristate "Hwmon driver that uses channels specified via iio maps"
> +       depends on HWMON
> +       help
> +	  This is a platform driver that in combination with a suitable
> +	  map allows IIO devices to provide  basic hwmon functionality
> +	  for those channels specified in the map.
> +
>  source "drivers/iio/adc/Kconfig"
>  source "drivers/iio/imu/Kconfig"
>  source "drivers/iio/light/Kconfig"
> diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
> index cfb588a..5f9c01a 100644
> --- a/drivers/iio/Makefile
> +++ b/drivers/iio/Makefile
> @@ -6,6 +6,7 @@ obj-y = inkern.o
>  obj-$(CONFIG_IIO) += iio.o
>  industrialio-y := core.o
>  
> +obj-$(CONFIG_IIO_HWMON) += iio_hwmon.o
>  obj-y += adc/
>  obj-y += imu/
>  obj-y += light/
> diff --git a/drivers/iio/iio_hwmon.c b/drivers/iio/iio_hwmon.c
> new file mode 100644
> index 0000000..4bd7651
> --- /dev/null
> +++ b/drivers/iio/iio_hwmon.c
> @@ -0,0 +1,227 @@
> +/* Hwmon client for industrial I/O devices
> + *
> + * Copyright (c) 2011 Jonathan Cameron
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published by
> + * the Free Software Foundation.
> + *
> + * Limited functionality currently supported.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/module.h>
> +#include <linux/err.h>
> +#include <linux/platform_device.h>
> +#include <linux/iio/inkern.h>
> +#include <linux/hwmon.h>
> +#include <linux/hwmon-sysfs.h>
> +
> +/**
> + * struct iio_hwmon_state - device instance state
> + * @channels:		filled with null terminated array of channels from iio
> + * @num_channels:	number of channels in channels (saves counting twice)
> + * @hwmon_dev:		associated hwmon device
> + * @attr_group:	the group of attributes
> + * @attrs:		null terminated array of attribute pointers.
> + */
> +struct iio_hwmon_state {
> +	struct iio_channel **channels;
> +	int num_channels;
> +	struct device *hwmon_dev;
> +	struct attribute_group attr_group;
> +	struct attribute **attrs;
> +};
> +
> +/*
> + * Assumes that IIO and hwmon operate in the same base units.
> + * This is supposed to be true, but needs verification for
> + * new channel types.
> + */
> +static ssize_t iio_hwmon_read_val(struct device *dev,
> +				  struct device_attribute *attr,
> +				  char *buf)
> +{
> +	long result;
> +	int val, ret, scaleint, scalepart;
> +	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
> +	struct iio_hwmon_state *state = dev_get_drvdata(dev);
> +
> +	/*
> +	 * No locking between this pair, so theoretically possible
> +	 * the scale has changed.
> +	 */
> +	ret = iio_read_channel_raw(state->channels[sattr->index],
> +				   &val);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = iio_read_channel_scale(state->channels[sattr->index],
> +				     &scaleint, &scalepart);
> +	if (ret < 0)
> +		return ret;
> +	switch (ret) {
> +	case IIO_VAL_INT:
> +		result = val * scaleint;
> +		break;
> +	case IIO_VAL_INT_PLUS_MICRO:
> +		result = (long)val * (long)scaleint +
> +			div_s64((s64)val * (s64)scalepart, 1000000LL);
> +		break;
> +	case IIO_VAL_INT_PLUS_NANO:
> +		result = (long)val * (long)scaleint +
> +			div_s64((s64)val * (s64)scalepart, 1000000000LL);
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +	return sprintf(buf, "%ld\n", result);
> +}
> +
> +static void iio_hwmon_free_attrs(struct iio_hwmon_state *st)
> +{
> +	int i;
> +	struct sensor_device_attribute *a;
> +	for (i = 0; i < st->num_channels; i++)
> +		if (st->attrs[i]) {
> +			a = to_sensor_dev_attr(
> +				container_of(st->attrs[i],
> +					     struct device_attribute,
> +					     attr));
> +			kfree(a);
> +		}
> +}
> +
> +static int __devinit iio_hwmon_probe(struct platform_device *pdev)
> +{
> +	struct iio_hwmon_state *st;
> +	struct sensor_device_attribute *a;
> +	int ret, i;
> +	int in_i = 1, temp_i = 1, curr_i = 1;
> +
> +	st = kzalloc(sizeof(*st), GFP_KERNEL);
> +	if (st == NULL) {
> +		ret = -ENOMEM;
> +		goto error_ret;
> +	}
> +
> +	st->channels = iio_channel_get_all(&pdev->dev, NULL);
> +	if (IS_ERR(st->channels)) {
> +		ret = PTR_ERR(st->channels);
> +		goto error_free_state;
> +	}
> +
> +	/* count how many attributes we have */
> +	while (st->channels[st->num_channels])
> +		st->num_channels++;
> +
> +	st->attrs = kzalloc(sizeof(st->attrs) * (st->num_channels + 1),
> +			    GFP_KERNEL);
> +	if (st->attrs == NULL) {
> +		ret = -ENOMEM;
> +		goto error_release_channels;
> +	}
> +	for (i = 0; i < st->num_channels; i++) {
> +		a = kzalloc(sizeof(*a), GFP_KERNEL);
> +		if (a == NULL) {
> +			ret = -ENOMEM;
> +			goto error_free_attrs;
> +		}
> +
> +		sysfs_attr_init(&a->dev_attr.attr);
> +		switch (iio_get_channel_type(st->channels[i])) {
> +		case IIO_VOLTAGE:
> +			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
> +							  "in%d_input",
> +							  in_i++);
> +			break;
> +		case IIO_TEMP:
> +			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
> +							  "temp%d_input",
> +							  temp_i++);
> +			break;
> +		case IIO_CURRENT:
> +			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
> +							  "curr%d_input",
> +							  curr_i++);
> +			break;
> +		default:
> +			ret = -EINVAL;
> +			kfree(a);
> +			goto error_free_attrs;
> +		}
> +		if (a->dev_attr.attr.name == NULL) {
> +			kfree(a);
> +			ret = -ENOMEM;
> +			goto error_free_attrs;
> +		}
> +		a->dev_attr.show = iio_hwmon_read_val;
> +		a->dev_attr.attr.mode = S_IRUGO;
> +		a->index = i;
> +		st->attrs[i] = &a->dev_attr.attr;
> +	}
> +
> +	st->attr_group.attrs = st->attrs;
> +	platform_set_drvdata(pdev, st);
> +	ret = sysfs_create_group(&pdev->dev.kobj, &st->attr_group);
> +	if (ret < 0)
> +		goto error_free_attrs;
> +
> +	st->hwmon_dev = hwmon_device_register(&pdev->dev);
> +	if (IS_ERR(st->hwmon_dev)) {
> +		ret = PTR_ERR(st->hwmon_dev);
> +		goto error_remove_group;
> +	}
> +	return 0;
> +
> +error_remove_group:
> +	sysfs_remove_group(&pdev->dev.kobj, &st->attr_group);
> +error_free_attrs:
> +	iio_hwmon_free_attrs(st);
> +	kfree(st->attrs);
> +error_release_channels:
> +	iio_channel_release_all(st->channels);
> +error_free_state:
> +	kfree(st);
> +error_ret:
> +	return ret;
> +}
> +
> +static int __devexit iio_hwmon_remove(struct platform_device *pdev)
> +{
> +	struct iio_hwmon_state *st = platform_get_drvdata(pdev);
> +
> +	hwmon_device_unregister(st->hwmon_dev);
> +	sysfs_remove_group(&pdev->dev.kobj, &st->attr_group);
> +	iio_hwmon_free_attrs(st);
> +	kfree(st->attrs);
> +	iio_channel_release_all(st->channels);
> +

Either I missed it before, or I am missing something now ... should
there be kfree(st) here ?

Thanks,
Guenter

> +	return 0;
> +}
> +
> +static struct platform_driver __refdata iio_hwmon_driver = {
> +	.driver = {
> +		.name = "iio_hwmon",
> +		.owner = THIS_MODULE,
> +	},
> +	.probe = iio_hwmon_probe,
> +	.remove = __devexit_p(iio_hwmon_remove),
> +};
> +
> +static int iio_inkern_init(void)
> +{
> +	return platform_driver_register(&iio_hwmon_driver);
> +}
> +module_init(iio_inkern_init);
> +
> +static void iio_inkern_exit(void)
> +{
> +	platform_driver_unregister(&iio_hwmon_driver);
> +}
> +module_exit(iio_inkern_exit);
> +
> +MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
> +MODULE_DESCRIPTION("IIO to hwmon driver");
> +MODULE_LICENSE("GPL v2");

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

* Re: [lm-sensors] [PATCH 4/5] IIO:hwmon interface client driver.
@ 2011-11-07 16:29     ` Guenter Roeck
  0 siblings, 0 replies; 32+ messages in thread
From: Guenter Roeck @ 2011-11-07 16:29 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio, linux-kernel, khali, dmitry.torokhov, broonie, gregkh,
	alan, arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

Hi Jonathan,

On Mon, 2011-11-07 at 10:44 -0500, Jonathan Cameron wrote:
> From: Jonathan Cameron <jic23@cam.ac.uk>
> 
> Should move to drivers/hwmon once people are happy with it.
> 
> Minimal support of simple in, curr and temp attributes
> so far.
> 
> Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
> ---
>  drivers/iio/Kconfig     |    8 ++
>  drivers/iio/Makefile    |    1 +
>  drivers/iio/iio_hwmon.c |  227 +++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 236 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
> index 308bc97..c2f0970 100644
> --- a/drivers/iio/Kconfig
> +++ b/drivers/iio/Kconfig
> @@ -11,6 +11,14 @@ menuconfig IIO
>  
>  if IIO
>  
> +config IIO_HWMON
> +       tristate "Hwmon driver that uses channels specified via iio maps"
> +       depends on HWMON
> +       help
> +	  This is a platform driver that in combination with a suitable
> +	  map allows IIO devices to provide  basic hwmon functionality
> +	  for those channels specified in the map.
> +
>  source "drivers/iio/adc/Kconfig"
>  source "drivers/iio/imu/Kconfig"
>  source "drivers/iio/light/Kconfig"
> diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
> index cfb588a..5f9c01a 100644
> --- a/drivers/iio/Makefile
> +++ b/drivers/iio/Makefile
> @@ -6,6 +6,7 @@ obj-y = inkern.o
>  obj-$(CONFIG_IIO) += iio.o
>  industrialio-y := core.o
>  
> +obj-$(CONFIG_IIO_HWMON) += iio_hwmon.o
>  obj-y += adc/
>  obj-y += imu/
>  obj-y += light/
> diff --git a/drivers/iio/iio_hwmon.c b/drivers/iio/iio_hwmon.c
> new file mode 100644
> index 0000000..4bd7651
> --- /dev/null
> +++ b/drivers/iio/iio_hwmon.c
> @@ -0,0 +1,227 @@
> +/* Hwmon client for industrial I/O devices
> + *
> + * Copyright (c) 2011 Jonathan Cameron
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published by
> + * the Free Software Foundation.
> + *
> + * Limited functionality currently supported.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/module.h>
> +#include <linux/err.h>
> +#include <linux/platform_device.h>
> +#include <linux/iio/inkern.h>
> +#include <linux/hwmon.h>
> +#include <linux/hwmon-sysfs.h>
> +
> +/**
> + * struct iio_hwmon_state - device instance state
> + * @channels:		filled with null terminated array of channels from iio
> + * @num_channels:	number of channels in channels (saves counting twice)
> + * @hwmon_dev:		associated hwmon device
> + * @attr_group:	the group of attributes
> + * @attrs:		null terminated array of attribute pointers.
> + */
> +struct iio_hwmon_state {
> +	struct iio_channel **channels;
> +	int num_channels;
> +	struct device *hwmon_dev;
> +	struct attribute_group attr_group;
> +	struct attribute **attrs;
> +};
> +
> +/*
> + * Assumes that IIO and hwmon operate in the same base units.
> + * This is supposed to be true, but needs verification for
> + * new channel types.
> + */
> +static ssize_t iio_hwmon_read_val(struct device *dev,
> +				  struct device_attribute *attr,
> +				  char *buf)
> +{
> +	long result;
> +	int val, ret, scaleint, scalepart;
> +	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
> +	struct iio_hwmon_state *state = dev_get_drvdata(dev);
> +
> +	/*
> +	 * No locking between this pair, so theoretically possible
> +	 * the scale has changed.
> +	 */
> +	ret = iio_read_channel_raw(state->channels[sattr->index],
> +				   &val);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = iio_read_channel_scale(state->channels[sattr->index],
> +				     &scaleint, &scalepart);
> +	if (ret < 0)
> +		return ret;
> +	switch (ret) {
> +	case IIO_VAL_INT:
> +		result = val * scaleint;
> +		break;
> +	case IIO_VAL_INT_PLUS_MICRO:
> +		result = (long)val * (long)scaleint +
> +			div_s64((s64)val * (s64)scalepart, 1000000LL);
> +		break;
> +	case IIO_VAL_INT_PLUS_NANO:
> +		result = (long)val * (long)scaleint +
> +			div_s64((s64)val * (s64)scalepart, 1000000000LL);
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +	return sprintf(buf, "%ld\n", result);
> +}
> +
> +static void iio_hwmon_free_attrs(struct iio_hwmon_state *st)
> +{
> +	int i;
> +	struct sensor_device_attribute *a;
> +	for (i = 0; i < st->num_channels; i++)
> +		if (st->attrs[i]) {
> +			a = to_sensor_dev_attr(
> +				container_of(st->attrs[i],
> +					     struct device_attribute,
> +					     attr));
> +			kfree(a);
> +		}
> +}
> +
> +static int __devinit iio_hwmon_probe(struct platform_device *pdev)
> +{
> +	struct iio_hwmon_state *st;
> +	struct sensor_device_attribute *a;
> +	int ret, i;
> +	int in_i = 1, temp_i = 1, curr_i = 1;
> +
> +	st = kzalloc(sizeof(*st), GFP_KERNEL);
> +	if (st = NULL) {
> +		ret = -ENOMEM;
> +		goto error_ret;
> +	}
> +
> +	st->channels = iio_channel_get_all(&pdev->dev, NULL);
> +	if (IS_ERR(st->channels)) {
> +		ret = PTR_ERR(st->channels);
> +		goto error_free_state;
> +	}
> +
> +	/* count how many attributes we have */
> +	while (st->channels[st->num_channels])
> +		st->num_channels++;
> +
> +	st->attrs = kzalloc(sizeof(st->attrs) * (st->num_channels + 1),
> +			    GFP_KERNEL);
> +	if (st->attrs = NULL) {
> +		ret = -ENOMEM;
> +		goto error_release_channels;
> +	}
> +	for (i = 0; i < st->num_channels; i++) {
> +		a = kzalloc(sizeof(*a), GFP_KERNEL);
> +		if (a = NULL) {
> +			ret = -ENOMEM;
> +			goto error_free_attrs;
> +		}
> +
> +		sysfs_attr_init(&a->dev_attr.attr);
> +		switch (iio_get_channel_type(st->channels[i])) {
> +		case IIO_VOLTAGE:
> +			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
> +							  "in%d_input",
> +							  in_i++);
> +			break;
> +		case IIO_TEMP:
> +			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
> +							  "temp%d_input",
> +							  temp_i++);
> +			break;
> +		case IIO_CURRENT:
> +			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
> +							  "curr%d_input",
> +							  curr_i++);
> +			break;
> +		default:
> +			ret = -EINVAL;
> +			kfree(a);
> +			goto error_free_attrs;
> +		}
> +		if (a->dev_attr.attr.name = NULL) {
> +			kfree(a);
> +			ret = -ENOMEM;
> +			goto error_free_attrs;
> +		}
> +		a->dev_attr.show = iio_hwmon_read_val;
> +		a->dev_attr.attr.mode = S_IRUGO;
> +		a->index = i;
> +		st->attrs[i] = &a->dev_attr.attr;
> +	}
> +
> +	st->attr_group.attrs = st->attrs;
> +	platform_set_drvdata(pdev, st);
> +	ret = sysfs_create_group(&pdev->dev.kobj, &st->attr_group);
> +	if (ret < 0)
> +		goto error_free_attrs;
> +
> +	st->hwmon_dev = hwmon_device_register(&pdev->dev);
> +	if (IS_ERR(st->hwmon_dev)) {
> +		ret = PTR_ERR(st->hwmon_dev);
> +		goto error_remove_group;
> +	}
> +	return 0;
> +
> +error_remove_group:
> +	sysfs_remove_group(&pdev->dev.kobj, &st->attr_group);
> +error_free_attrs:
> +	iio_hwmon_free_attrs(st);
> +	kfree(st->attrs);
> +error_release_channels:
> +	iio_channel_release_all(st->channels);
> +error_free_state:
> +	kfree(st);
> +error_ret:
> +	return ret;
> +}
> +
> +static int __devexit iio_hwmon_remove(struct platform_device *pdev)
> +{
> +	struct iio_hwmon_state *st = platform_get_drvdata(pdev);
> +
> +	hwmon_device_unregister(st->hwmon_dev);
> +	sysfs_remove_group(&pdev->dev.kobj, &st->attr_group);
> +	iio_hwmon_free_attrs(st);
> +	kfree(st->attrs);
> +	iio_channel_release_all(st->channels);
> +

Either I missed it before, or I am missing something now ... should
there be kfree(st) here ?

Thanks,
Guenter

> +	return 0;
> +}
> +
> +static struct platform_driver __refdata iio_hwmon_driver = {
> +	.driver = {
> +		.name = "iio_hwmon",
> +		.owner = THIS_MODULE,
> +	},
> +	.probe = iio_hwmon_probe,
> +	.remove = __devexit_p(iio_hwmon_remove),
> +};
> +
> +static int iio_inkern_init(void)
> +{
> +	return platform_driver_register(&iio_hwmon_driver);
> +}
> +module_init(iio_inkern_init);
> +
> +static void iio_inkern_exit(void)
> +{
> +	platform_driver_unregister(&iio_hwmon_driver);
> +}
> +module_exit(iio_inkern_exit);
> +
> +MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
> +MODULE_DESCRIPTION("IIO to hwmon driver");
> +MODULE_LICENSE("GPL v2");



_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [PATCH 4/5] IIO:hwmon interface client driver.
  2011-11-07 16:29     ` Guenter Roeck
  (?)
@ 2011-11-07 17:39       ` Jonathan Cameron
  -1 siblings, 0 replies; 32+ messages in thread
From: Jonathan Cameron @ 2011-11-07 17:39 UTC (permalink / raw)
  To: guenter.roeck
  Cc: linux-iio, linux-kernel, khali, dmitry.torokhov, broonie, gregkh,
	alan, arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

>> +static int __devexit iio_hwmon_remove(struct platform_device *pdev)
>> +{
>> +	struct iio_hwmon_state *st = platform_get_drvdata(pdev);
>> +
>> +	hwmon_device_unregister(st->hwmon_dev);
>> +	sysfs_remove_group(&pdev->dev.kobj, &st->attr_group);
>> +	iio_hwmon_free_attrs(st);
>> +	kfree(st->attrs);
>> +	iio_channel_release_all(st->channels);
>> +
> 
> Either I missed it before, or I am missing something now ... should
> there be kfree(st) here ?
> 
> Thanks,
> Guenter

Gah! you are quite right.  Good spot.  I'll fix that one up and repost
this individual patch.


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

* Re: [PATCH 4/5] IIO:hwmon interface client driver.
@ 2011-11-07 17:39       ` Jonathan Cameron
  0 siblings, 0 replies; 32+ messages in thread
From: Jonathan Cameron @ 2011-11-07 17:39 UTC (permalink / raw)
  To: guenter.roeck
  Cc: linux-iio, linux-kernel, khali, dmitry.torokhov, broonie, gregkh,
	alan, arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

>> +static int __devexit iio_hwmon_remove(struct platform_device *pdev)
>> +{
>> +	struct iio_hwmon_state *st = platform_get_drvdata(pdev);
>> +
>> +	hwmon_device_unregister(st->hwmon_dev);
>> +	sysfs_remove_group(&pdev->dev.kobj, &st->attr_group);
>> +	iio_hwmon_free_attrs(st);
>> +	kfree(st->attrs);
>> +	iio_channel_release_all(st->channels);
>> +
> 
> Either I missed it before, or I am missing something now ... should
> there be kfree(st) here ?
> 
> Thanks,
> Guenter

Gah! you are quite right.  Good spot.  I'll fix that one up and repost
this individual patch.

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

* Re: [lm-sensors] [PATCH 4/5] IIO:hwmon interface client driver.
@ 2011-11-07 17:39       ` Jonathan Cameron
  0 siblings, 0 replies; 32+ messages in thread
From: Jonathan Cameron @ 2011-11-07 17:39 UTC (permalink / raw)
  To: guenter.roeck
  Cc: linux-iio, linux-kernel, khali, dmitry.torokhov, broonie, gregkh,
	alan, arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

>> +static int __devexit iio_hwmon_remove(struct platform_device *pdev)
>> +{
>> +	struct iio_hwmon_state *st = platform_get_drvdata(pdev);
>> +
>> +	hwmon_device_unregister(st->hwmon_dev);
>> +	sysfs_remove_group(&pdev->dev.kobj, &st->attr_group);
>> +	iio_hwmon_free_attrs(st);
>> +	kfree(st->attrs);
>> +	iio_channel_release_all(st->channels);
>> +
> 
> Either I missed it before, or I am missing something now ... should
> there be kfree(st) here ?
> 
> Thanks,
> Guenter

Gah! you are quite right.  Good spot.  I'll fix that one up and repost
this individual patch.


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* [PATCH] IIO:hwmon interface client driver.
  2011-11-07 17:39       ` Jonathan Cameron
@ 2011-11-07 17:43         ` Jonathan Cameron
  -1 siblings, 0 replies; 32+ messages in thread
From: Jonathan Cameron @ 2011-11-07 17:43 UTC (permalink / raw)
  To: linux-iio, linux-kernel
  Cc: guenter.roeck, khali, dmitry.torokhov, broonie, gregkh, alan,
	arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

From: Jonathan Cameron <jic23@cam.ac.uk>

Should move to drivers/hwmon once people are happy with it.

Minimal support of simple in, curr and temp attributes
so far.

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
Fixed up the missing free Guenter spotted.
Thanks!
 drivers/iio/Kconfig     |    8 ++
 drivers/iio/Makefile    |    1 +
 drivers/iio/iio_hwmon.c |  228 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 237 insertions(+), 0 deletions(-)
 create mode 100644 drivers/iio/iio_hwmon.c

diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index 308bc97..c2f0970 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -11,6 +11,14 @@ menuconfig IIO
 
 if IIO
 
+config IIO_HWMON
+       tristate "Hwmon driver that uses channels specified via iio maps"
+       depends on HWMON
+       help
+	  This is a platform driver that in combination with a suitable
+	  map allows IIO devices to provide  basic hwmon functionality
+	  for those channels specified in the map.
+
 source "drivers/iio/adc/Kconfig"
 source "drivers/iio/imu/Kconfig"
 source "drivers/iio/light/Kconfig"
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index cfb588a..5f9c01a 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -6,6 +6,7 @@ obj-y = inkern.o
 obj-$(CONFIG_IIO) += iio.o
 industrialio-y := core.o
 
+obj-$(CONFIG_IIO_HWMON) += iio_hwmon.o
 obj-y += adc/
 obj-y += imu/
 obj-y += light/
diff --git a/drivers/iio/iio_hwmon.c b/drivers/iio/iio_hwmon.c
new file mode 100644
index 0000000..880ce6d
--- /dev/null
+++ b/drivers/iio/iio_hwmon.c
@@ -0,0 +1,228 @@
+/* Hwmon client for industrial I/O devices
+ *
+ * Copyright (c) 2011 Jonathan Cameron
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * Limited functionality currently supported.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/iio/inkern.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+/**
+ * struct iio_hwmon_state - device instance state
+ * @channels:		filled with null terminated array of channels from iio
+ * @num_channels:	number of channels in channels (saves counting twice)
+ * @hwmon_dev:		associated hwmon device
+ * @attr_group:	the group of attributes
+ * @attrs:		null terminated array of attribute pointers.
+ */
+struct iio_hwmon_state {
+	struct iio_channel **channels;
+	int num_channels;
+	struct device *hwmon_dev;
+	struct attribute_group attr_group;
+	struct attribute **attrs;
+};
+
+/*
+ * Assumes that IIO and hwmon operate in the same base units.
+ * This is supposed to be true, but needs verification for
+ * new channel types.
+ */
+static ssize_t iio_hwmon_read_val(struct device *dev,
+				  struct device_attribute *attr,
+				  char *buf)
+{
+	long result;
+	int val, ret, scaleint, scalepart;
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	struct iio_hwmon_state *state = dev_get_drvdata(dev);
+
+	/*
+	 * No locking between this pair, so theoretically possible
+	 * the scale has changed.
+	 */
+	ret = iio_read_channel_raw(state->channels[sattr->index],
+				   &val);
+	if (ret < 0)
+		return ret;
+
+	ret = iio_read_channel_scale(state->channels[sattr->index],
+				     &scaleint, &scalepart);
+	if (ret < 0)
+		return ret;
+	switch (ret) {
+	case IIO_VAL_INT:
+		result = val * scaleint;
+		break;
+	case IIO_VAL_INT_PLUS_MICRO:
+		result = (long)val * (long)scaleint +
+			div_s64((s64)val * (s64)scalepart, 1000000LL);
+		break;
+	case IIO_VAL_INT_PLUS_NANO:
+		result = (long)val * (long)scaleint +
+			div_s64((s64)val * (s64)scalepart, 1000000000LL);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return sprintf(buf, "%ld\n", result);
+}
+
+static void iio_hwmon_free_attrs(struct iio_hwmon_state *st)
+{
+	int i;
+	struct sensor_device_attribute *a;
+	for (i = 0; i < st->num_channels; i++)
+		if (st->attrs[i]) {
+			a = to_sensor_dev_attr(
+				container_of(st->attrs[i],
+					     struct device_attribute,
+					     attr));
+			kfree(a);
+		}
+}
+
+static int __devinit iio_hwmon_probe(struct platform_device *pdev)
+{
+	struct iio_hwmon_state *st;
+	struct sensor_device_attribute *a;
+	int ret, i;
+	int in_i = 1, temp_i = 1, curr_i = 1;
+
+	st = kzalloc(sizeof(*st), GFP_KERNEL);
+	if (st == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+
+	st->channels = iio_channel_get_all(&pdev->dev, NULL);
+	if (IS_ERR(st->channels)) {
+		ret = PTR_ERR(st->channels);
+		goto error_free_state;
+	}
+
+	/* count how many attributes we have */
+	while (st->channels[st->num_channels])
+		st->num_channels++;
+
+	st->attrs = kzalloc(sizeof(st->attrs) * (st->num_channels + 1),
+			    GFP_KERNEL);
+	if (st->attrs == NULL) {
+		ret = -ENOMEM;
+		goto error_release_channels;
+	}
+	for (i = 0; i < st->num_channels; i++) {
+		a = kzalloc(sizeof(*a), GFP_KERNEL);
+		if (a == NULL) {
+			ret = -ENOMEM;
+			goto error_free_attrs;
+		}
+
+		sysfs_attr_init(&a->dev_attr.attr);
+		switch (iio_get_channel_type(st->channels[i])) {
+		case IIO_VOLTAGE:
+			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
+							  "in%d_input",
+							  in_i++);
+			break;
+		case IIO_TEMP:
+			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
+							  "temp%d_input",
+							  temp_i++);
+			break;
+		case IIO_CURRENT:
+			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
+							  "curr%d_input",
+							  curr_i++);
+			break;
+		default:
+			ret = -EINVAL;
+			kfree(a);
+			goto error_free_attrs;
+		}
+		if (a->dev_attr.attr.name == NULL) {
+			kfree(a);
+			ret = -ENOMEM;
+			goto error_free_attrs;
+		}
+		a->dev_attr.show = iio_hwmon_read_val;
+		a->dev_attr.attr.mode = S_IRUGO;
+		a->index = i;
+		st->attrs[i] = &a->dev_attr.attr;
+	}
+
+	st->attr_group.attrs = st->attrs;
+	platform_set_drvdata(pdev, st);
+	ret = sysfs_create_group(&pdev->dev.kobj, &st->attr_group);
+	if (ret < 0)
+		goto error_free_attrs;
+
+	st->hwmon_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(st->hwmon_dev)) {
+		ret = PTR_ERR(st->hwmon_dev);
+		goto error_remove_group;
+	}
+	return 0;
+
+error_remove_group:
+	sysfs_remove_group(&pdev->dev.kobj, &st->attr_group);
+error_free_attrs:
+	iio_hwmon_free_attrs(st);
+	kfree(st->attrs);
+error_release_channels:
+	iio_channel_release_all(st->channels);
+error_free_state:
+	kfree(st);
+error_ret:
+	return ret;
+}
+
+static int __devexit iio_hwmon_remove(struct platform_device *pdev)
+{
+	struct iio_hwmon_state *st = platform_get_drvdata(pdev);
+
+	hwmon_device_unregister(st->hwmon_dev);
+	sysfs_remove_group(&pdev->dev.kobj, &st->attr_group);
+	iio_hwmon_free_attrs(st);
+	kfree(st->attrs);
+	iio_channel_release_all(st->channels);
+	kfree(st);
+
+	return 0;
+}
+
+static struct platform_driver __refdata iio_hwmon_driver = {
+	.driver = {
+		.name = "iio_hwmon",
+		.owner = THIS_MODULE,
+	},
+	.probe = iio_hwmon_probe,
+	.remove = __devexit_p(iio_hwmon_remove),
+};
+
+static int iio_inkern_init(void)
+{
+	return platform_driver_register(&iio_hwmon_driver);
+}
+module_init(iio_inkern_init);
+
+static void iio_inkern_exit(void)
+{
+	platform_driver_unregister(&iio_hwmon_driver);
+}
+module_exit(iio_inkern_exit);
+
+MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
+MODULE_DESCRIPTION("IIO to hwmon driver");
+MODULE_LICENSE("GPL v2");
-- 
1.7.7.2


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

* [lm-sensors] [PATCH] IIO:hwmon interface client driver.
@ 2011-11-07 17:43         ` Jonathan Cameron
  0 siblings, 0 replies; 32+ messages in thread
From: Jonathan Cameron @ 2011-11-07 17:43 UTC (permalink / raw)
  To: linux-iio, linux-kernel
  Cc: guenter.roeck, khali, dmitry.torokhov, broonie, gregkh, alan,
	arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

From: Jonathan Cameron <jic23@cam.ac.uk>

Should move to drivers/hwmon once people are happy with it.

Minimal support of simple in, curr and temp attributes
so far.

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
Fixed up the missing free Guenter spotted.
Thanks!
 drivers/iio/Kconfig     |    8 ++
 drivers/iio/Makefile    |    1 +
 drivers/iio/iio_hwmon.c |  228 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 237 insertions(+), 0 deletions(-)
 create mode 100644 drivers/iio/iio_hwmon.c

diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index 308bc97..c2f0970 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -11,6 +11,14 @@ menuconfig IIO
 
 if IIO
 
+config IIO_HWMON
+       tristate "Hwmon driver that uses channels specified via iio maps"
+       depends on HWMON
+       help
+	  This is a platform driver that in combination with a suitable
+	  map allows IIO devices to provide  basic hwmon functionality
+	  for those channels specified in the map.
+
 source "drivers/iio/adc/Kconfig"
 source "drivers/iio/imu/Kconfig"
 source "drivers/iio/light/Kconfig"
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index cfb588a..5f9c01a 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -6,6 +6,7 @@ obj-y = inkern.o
 obj-$(CONFIG_IIO) += iio.o
 industrialio-y := core.o
 
+obj-$(CONFIG_IIO_HWMON) += iio_hwmon.o
 obj-y += adc/
 obj-y += imu/
 obj-y += light/
diff --git a/drivers/iio/iio_hwmon.c b/drivers/iio/iio_hwmon.c
new file mode 100644
index 0000000..880ce6d
--- /dev/null
+++ b/drivers/iio/iio_hwmon.c
@@ -0,0 +1,228 @@
+/* Hwmon client for industrial I/O devices
+ *
+ * Copyright (c) 2011 Jonathan Cameron
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * Limited functionality currently supported.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/iio/inkern.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+/**
+ * struct iio_hwmon_state - device instance state
+ * @channels:		filled with null terminated array of channels from iio
+ * @num_channels:	number of channels in channels (saves counting twice)
+ * @hwmon_dev:		associated hwmon device
+ * @attr_group:	the group of attributes
+ * @attrs:		null terminated array of attribute pointers.
+ */
+struct iio_hwmon_state {
+	struct iio_channel **channels;
+	int num_channels;
+	struct device *hwmon_dev;
+	struct attribute_group attr_group;
+	struct attribute **attrs;
+};
+
+/*
+ * Assumes that IIO and hwmon operate in the same base units.
+ * This is supposed to be true, but needs verification for
+ * new channel types.
+ */
+static ssize_t iio_hwmon_read_val(struct device *dev,
+				  struct device_attribute *attr,
+				  char *buf)
+{
+	long result;
+	int val, ret, scaleint, scalepart;
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	struct iio_hwmon_state *state = dev_get_drvdata(dev);
+
+	/*
+	 * No locking between this pair, so theoretically possible
+	 * the scale has changed.
+	 */
+	ret = iio_read_channel_raw(state->channels[sattr->index],
+				   &val);
+	if (ret < 0)
+		return ret;
+
+	ret = iio_read_channel_scale(state->channels[sattr->index],
+				     &scaleint, &scalepart);
+	if (ret < 0)
+		return ret;
+	switch (ret) {
+	case IIO_VAL_INT:
+		result = val * scaleint;
+		break;
+	case IIO_VAL_INT_PLUS_MICRO:
+		result = (long)val * (long)scaleint +
+			div_s64((s64)val * (s64)scalepart, 1000000LL);
+		break;
+	case IIO_VAL_INT_PLUS_NANO:
+		result = (long)val * (long)scaleint +
+			div_s64((s64)val * (s64)scalepart, 1000000000LL);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return sprintf(buf, "%ld\n", result);
+}
+
+static void iio_hwmon_free_attrs(struct iio_hwmon_state *st)
+{
+	int i;
+	struct sensor_device_attribute *a;
+	for (i = 0; i < st->num_channels; i++)
+		if (st->attrs[i]) {
+			a = to_sensor_dev_attr(
+				container_of(st->attrs[i],
+					     struct device_attribute,
+					     attr));
+			kfree(a);
+		}
+}
+
+static int __devinit iio_hwmon_probe(struct platform_device *pdev)
+{
+	struct iio_hwmon_state *st;
+	struct sensor_device_attribute *a;
+	int ret, i;
+	int in_i = 1, temp_i = 1, curr_i = 1;
+
+	st = kzalloc(sizeof(*st), GFP_KERNEL);
+	if (st = NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+
+	st->channels = iio_channel_get_all(&pdev->dev, NULL);
+	if (IS_ERR(st->channels)) {
+		ret = PTR_ERR(st->channels);
+		goto error_free_state;
+	}
+
+	/* count how many attributes we have */
+	while (st->channels[st->num_channels])
+		st->num_channels++;
+
+	st->attrs = kzalloc(sizeof(st->attrs) * (st->num_channels + 1),
+			    GFP_KERNEL);
+	if (st->attrs = NULL) {
+		ret = -ENOMEM;
+		goto error_release_channels;
+	}
+	for (i = 0; i < st->num_channels; i++) {
+		a = kzalloc(sizeof(*a), GFP_KERNEL);
+		if (a = NULL) {
+			ret = -ENOMEM;
+			goto error_free_attrs;
+		}
+
+		sysfs_attr_init(&a->dev_attr.attr);
+		switch (iio_get_channel_type(st->channels[i])) {
+		case IIO_VOLTAGE:
+			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
+							  "in%d_input",
+							  in_i++);
+			break;
+		case IIO_TEMP:
+			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
+							  "temp%d_input",
+							  temp_i++);
+			break;
+		case IIO_CURRENT:
+			a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
+							  "curr%d_input",
+							  curr_i++);
+			break;
+		default:
+			ret = -EINVAL;
+			kfree(a);
+			goto error_free_attrs;
+		}
+		if (a->dev_attr.attr.name = NULL) {
+			kfree(a);
+			ret = -ENOMEM;
+			goto error_free_attrs;
+		}
+		a->dev_attr.show = iio_hwmon_read_val;
+		a->dev_attr.attr.mode = S_IRUGO;
+		a->index = i;
+		st->attrs[i] = &a->dev_attr.attr;
+	}
+
+	st->attr_group.attrs = st->attrs;
+	platform_set_drvdata(pdev, st);
+	ret = sysfs_create_group(&pdev->dev.kobj, &st->attr_group);
+	if (ret < 0)
+		goto error_free_attrs;
+
+	st->hwmon_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(st->hwmon_dev)) {
+		ret = PTR_ERR(st->hwmon_dev);
+		goto error_remove_group;
+	}
+	return 0;
+
+error_remove_group:
+	sysfs_remove_group(&pdev->dev.kobj, &st->attr_group);
+error_free_attrs:
+	iio_hwmon_free_attrs(st);
+	kfree(st->attrs);
+error_release_channels:
+	iio_channel_release_all(st->channels);
+error_free_state:
+	kfree(st);
+error_ret:
+	return ret;
+}
+
+static int __devexit iio_hwmon_remove(struct platform_device *pdev)
+{
+	struct iio_hwmon_state *st = platform_get_drvdata(pdev);
+
+	hwmon_device_unregister(st->hwmon_dev);
+	sysfs_remove_group(&pdev->dev.kobj, &st->attr_group);
+	iio_hwmon_free_attrs(st);
+	kfree(st->attrs);
+	iio_channel_release_all(st->channels);
+	kfree(st);
+
+	return 0;
+}
+
+static struct platform_driver __refdata iio_hwmon_driver = {
+	.driver = {
+		.name = "iio_hwmon",
+		.owner = THIS_MODULE,
+	},
+	.probe = iio_hwmon_probe,
+	.remove = __devexit_p(iio_hwmon_remove),
+};
+
+static int iio_inkern_init(void)
+{
+	return platform_driver_register(&iio_hwmon_driver);
+}
+module_init(iio_inkern_init);
+
+static void iio_inkern_exit(void)
+{
+	platform_driver_unregister(&iio_hwmon_driver);
+}
+module_exit(iio_inkern_exit);
+
+MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
+MODULE_DESCRIPTION("IIO to hwmon driver");
+MODULE_LICENSE("GPL v2");
-- 
1.7.7.2


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [PATCH] IIO:hwmon interface client driver.
  2011-11-07 17:43         ` [lm-sensors] " Jonathan Cameron
  (?)
@ 2011-11-07 17:52           ` Guenter Roeck
  -1 siblings, 0 replies; 32+ messages in thread
From: Guenter Roeck @ 2011-11-07 17:52 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio, linux-kernel, khali, dmitry.torokhov, broonie, gregkh,
	alan, arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

Hi Jonathan,

I know I must be getting annoying, but somehow it seems I just keep
finding something whenever I look at the code again.

On Mon, 2011-11-07 at 12:43 -0500, Jonathan Cameron wrote:
> From: Jonathan Cameron <jic23@cam.ac.uk>
> 
> Should move to drivers/hwmon once people are happy with it.
> 
> Minimal support of simple in, curr and temp attributes
> so far.
> 
> Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
> ---
> Fixed up the missing free Guenter spotted.
> Thanks!
>  drivers/iio/Kconfig     |    8 ++
>  drivers/iio/Makefile    |    1 +
>  drivers/iio/iio_hwmon.c |  228 +++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 237 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/iio/iio_hwmon.c
> 
> diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
> index 308bc97..c2f0970 100644
> --- a/drivers/iio/Kconfig
> +++ b/drivers/iio/Kconfig
> @@ -11,6 +11,14 @@ menuconfig IIO
>  
>  if IIO
>  
> +config IIO_HWMON
> +       tristate "Hwmon driver that uses channels specified via iio maps"
> +       depends on HWMON
> +       help
> +	  This is a platform driver that in combination with a suitable
> +	  map allows IIO devices to provide  basic hwmon functionality
> +	  for those channels specified in the map.
> +
>  source "drivers/iio/adc/Kconfig"
>  source "drivers/iio/imu/Kconfig"
>  source "drivers/iio/light/Kconfig"
> diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
> index cfb588a..5f9c01a 100644
> --- a/drivers/iio/Makefile
> +++ b/drivers/iio/Makefile
> @@ -6,6 +6,7 @@ obj-y = inkern.o
>  obj-$(CONFIG_IIO) += iio.o
>  industrialio-y := core.o
>  
> +obj-$(CONFIG_IIO_HWMON) += iio_hwmon.o
>  obj-y += adc/
>  obj-y += imu/
>  obj-y += light/
> diff --git a/drivers/iio/iio_hwmon.c b/drivers/iio/iio_hwmon.c
> new file mode 100644
> index 0000000..880ce6d
> --- /dev/null
> +++ b/drivers/iio/iio_hwmon.c
> @@ -0,0 +1,228 @@
> +/* Hwmon client for industrial I/O devices
> + *
> + * Copyright (c) 2011 Jonathan Cameron
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published by
> + * the Free Software Foundation.
> + *
> + * Limited functionality currently supported.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/module.h>
> +#include <linux/err.h>
> +#include <linux/platform_device.h>
> +#include <linux/iio/inkern.h>
> +#include <linux/hwmon.h>
> +#include <linux/hwmon-sysfs.h>
> +
> +/**
> + * struct iio_hwmon_state - device instance state
> + * @channels:		filled with null terminated array of channels from iio
> + * @num_channels:	number of channels in channels (saves counting twice)
> + * @hwmon_dev:		associated hwmon device
> + * @attr_group:	the group of attributes
> + * @attrs:		null terminated array of attribute pointers.
> + */
> +struct iio_hwmon_state {
> +	struct iio_channel **channels;
> +	int num_channels;
> +	struct device *hwmon_dev;
> +	struct attribute_group attr_group;
> +	struct attribute **attrs;
> +};
> +
> +/*
> + * Assumes that IIO and hwmon operate in the same base units.
> + * This is supposed to be true, but needs verification for
> + * new channel types.
> + */
> +static ssize_t iio_hwmon_read_val(struct device *dev,
> +				  struct device_attribute *attr,
> +				  char *buf)
> +{
> +	long result;
> +	int val, ret, scaleint, scalepart;
> +	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
> +	struct iio_hwmon_state *state = dev_get_drvdata(dev);
> +
> +	/*
> +	 * No locking between this pair, so theoretically possible
> +	 * the scale has changed.
> +	 */
> +	ret = iio_read_channel_raw(state->channels[sattr->index],
> +				   &val);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = iio_read_channel_scale(state->channels[sattr->index],
> +				     &scaleint, &scalepart);
> +	if (ret < 0)
> +		return ret;
> +	switch (ret) {
> +	case IIO_VAL_INT:
> +		result = val * scaleint;
> +		break;
> +	case IIO_VAL_INT_PLUS_MICRO:
> +		result = (long)val * (long)scaleint +
> +			div_s64((s64)val * (s64)scalepart, 1000000LL);
> +		break;
> +	case IIO_VAL_INT_PLUS_NANO:
> +		result = (long)val * (long)scaleint +
> +			div_s64((s64)val * (s64)scalepart, 1000000000LL);
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +	return sprintf(buf, "%ld\n", result);
> +}
> +
> +static void iio_hwmon_free_attrs(struct iio_hwmon_state *st)
> +{
> +	int i;
> +	struct sensor_device_attribute *a;
> +	for (i = 0; i < st->num_channels; i++)
> +		if (st->attrs[i]) {
> +			a = to_sensor_dev_attr(
> +				container_of(st->attrs[i],
> +					     struct device_attribute,
> +					     attr));

I finally looked into kasprintf ... which as it turns out allocates
memory. Yet, there is no kfree(a->dev_attr.attr.name).

Thanks,
Guenter




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

* Re: [PATCH] IIO:hwmon interface client driver.
@ 2011-11-07 17:52           ` Guenter Roeck
  0 siblings, 0 replies; 32+ messages in thread
From: Guenter Roeck @ 2011-11-07 17:52 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio, linux-kernel, khali, dmitry.torokhov, broonie, gregkh,
	alan, arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

Hi Jonathan,

I know I must be getting annoying, but somehow it seems I just keep
finding something whenever I look at the code again.

On Mon, 2011-11-07 at 12:43 -0500, Jonathan Cameron wrote:
> From: Jonathan Cameron <jic23@cam.ac.uk>
> 
> Should move to drivers/hwmon once people are happy with it.
> 
> Minimal support of simple in, curr and temp attributes
> so far.
> 
> Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
> ---
> Fixed up the missing free Guenter spotted.
> Thanks!
>  drivers/iio/Kconfig     |    8 ++
>  drivers/iio/Makefile    |    1 +
>  drivers/iio/iio_hwmon.c |  228 +++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 237 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/iio/iio_hwmon.c
> 
> diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
> index 308bc97..c2f0970 100644
> --- a/drivers/iio/Kconfig
> +++ b/drivers/iio/Kconfig
> @@ -11,6 +11,14 @@ menuconfig IIO
>  
>  if IIO
>  
> +config IIO_HWMON
> +       tristate "Hwmon driver that uses channels specified via iio maps"
> +       depends on HWMON
> +       help
> +	  This is a platform driver that in combination with a suitable
> +	  map allows IIO devices to provide  basic hwmon functionality
> +	  for those channels specified in the map.
> +
>  source "drivers/iio/adc/Kconfig"
>  source "drivers/iio/imu/Kconfig"
>  source "drivers/iio/light/Kconfig"
> diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
> index cfb588a..5f9c01a 100644
> --- a/drivers/iio/Makefile
> +++ b/drivers/iio/Makefile
> @@ -6,6 +6,7 @@ obj-y = inkern.o
>  obj-$(CONFIG_IIO) += iio.o
>  industrialio-y := core.o
>  
> +obj-$(CONFIG_IIO_HWMON) += iio_hwmon.o
>  obj-y += adc/
>  obj-y += imu/
>  obj-y += light/
> diff --git a/drivers/iio/iio_hwmon.c b/drivers/iio/iio_hwmon.c
> new file mode 100644
> index 0000000..880ce6d
> --- /dev/null
> +++ b/drivers/iio/iio_hwmon.c
> @@ -0,0 +1,228 @@
> +/* Hwmon client for industrial I/O devices
> + *
> + * Copyright (c) 2011 Jonathan Cameron
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published by
> + * the Free Software Foundation.
> + *
> + * Limited functionality currently supported.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/module.h>
> +#include <linux/err.h>
> +#include <linux/platform_device.h>
> +#include <linux/iio/inkern.h>
> +#include <linux/hwmon.h>
> +#include <linux/hwmon-sysfs.h>
> +
> +/**
> + * struct iio_hwmon_state - device instance state
> + * @channels:		filled with null terminated array of channels from iio
> + * @num_channels:	number of channels in channels (saves counting twice)
> + * @hwmon_dev:		associated hwmon device
> + * @attr_group:	the group of attributes
> + * @attrs:		null terminated array of attribute pointers.
> + */
> +struct iio_hwmon_state {
> +	struct iio_channel **channels;
> +	int num_channels;
> +	struct device *hwmon_dev;
> +	struct attribute_group attr_group;
> +	struct attribute **attrs;
> +};
> +
> +/*
> + * Assumes that IIO and hwmon operate in the same base units.
> + * This is supposed to be true, but needs verification for
> + * new channel types.
> + */
> +static ssize_t iio_hwmon_read_val(struct device *dev,
> +				  struct device_attribute *attr,
> +				  char *buf)
> +{
> +	long result;
> +	int val, ret, scaleint, scalepart;
> +	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
> +	struct iio_hwmon_state *state = dev_get_drvdata(dev);
> +
> +	/*
> +	 * No locking between this pair, so theoretically possible
> +	 * the scale has changed.
> +	 */
> +	ret = iio_read_channel_raw(state->channels[sattr->index],
> +				   &val);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = iio_read_channel_scale(state->channels[sattr->index],
> +				     &scaleint, &scalepart);
> +	if (ret < 0)
> +		return ret;
> +	switch (ret) {
> +	case IIO_VAL_INT:
> +		result = val * scaleint;
> +		break;
> +	case IIO_VAL_INT_PLUS_MICRO:
> +		result = (long)val * (long)scaleint +
> +			div_s64((s64)val * (s64)scalepart, 1000000LL);
> +		break;
> +	case IIO_VAL_INT_PLUS_NANO:
> +		result = (long)val * (long)scaleint +
> +			div_s64((s64)val * (s64)scalepart, 1000000000LL);
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +	return sprintf(buf, "%ld\n", result);
> +}
> +
> +static void iio_hwmon_free_attrs(struct iio_hwmon_state *st)
> +{
> +	int i;
> +	struct sensor_device_attribute *a;
> +	for (i = 0; i < st->num_channels; i++)
> +		if (st->attrs[i]) {
> +			a = to_sensor_dev_attr(
> +				container_of(st->attrs[i],
> +					     struct device_attribute,
> +					     attr));

I finally looked into kasprintf ... which as it turns out allocates
memory. Yet, there is no kfree(a->dev_attr.attr.name).

Thanks,
Guenter

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

* Re: [lm-sensors] [PATCH] IIO:hwmon interface client driver.
@ 2011-11-07 17:52           ` Guenter Roeck
  0 siblings, 0 replies; 32+ messages in thread
From: Guenter Roeck @ 2011-11-07 17:52 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio, linux-kernel, khali, dmitry.torokhov, broonie, gregkh,
	alan, arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

Hi Jonathan,

I know I must be getting annoying, but somehow it seems I just keep
finding something whenever I look at the code again.

On Mon, 2011-11-07 at 12:43 -0500, Jonathan Cameron wrote:
> From: Jonathan Cameron <jic23@cam.ac.uk>
> 
> Should move to drivers/hwmon once people are happy with it.
> 
> Minimal support of simple in, curr and temp attributes
> so far.
> 
> Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
> ---
> Fixed up the missing free Guenter spotted.
> Thanks!
>  drivers/iio/Kconfig     |    8 ++
>  drivers/iio/Makefile    |    1 +
>  drivers/iio/iio_hwmon.c |  228 +++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 237 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/iio/iio_hwmon.c
> 
> diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
> index 308bc97..c2f0970 100644
> --- a/drivers/iio/Kconfig
> +++ b/drivers/iio/Kconfig
> @@ -11,6 +11,14 @@ menuconfig IIO
>  
>  if IIO
>  
> +config IIO_HWMON
> +       tristate "Hwmon driver that uses channels specified via iio maps"
> +       depends on HWMON
> +       help
> +	  This is a platform driver that in combination with a suitable
> +	  map allows IIO devices to provide  basic hwmon functionality
> +	  for those channels specified in the map.
> +
>  source "drivers/iio/adc/Kconfig"
>  source "drivers/iio/imu/Kconfig"
>  source "drivers/iio/light/Kconfig"
> diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
> index cfb588a..5f9c01a 100644
> --- a/drivers/iio/Makefile
> +++ b/drivers/iio/Makefile
> @@ -6,6 +6,7 @@ obj-y = inkern.o
>  obj-$(CONFIG_IIO) += iio.o
>  industrialio-y := core.o
>  
> +obj-$(CONFIG_IIO_HWMON) += iio_hwmon.o
>  obj-y += adc/
>  obj-y += imu/
>  obj-y += light/
> diff --git a/drivers/iio/iio_hwmon.c b/drivers/iio/iio_hwmon.c
> new file mode 100644
> index 0000000..880ce6d
> --- /dev/null
> +++ b/drivers/iio/iio_hwmon.c
> @@ -0,0 +1,228 @@
> +/* Hwmon client for industrial I/O devices
> + *
> + * Copyright (c) 2011 Jonathan Cameron
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published by
> + * the Free Software Foundation.
> + *
> + * Limited functionality currently supported.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/module.h>
> +#include <linux/err.h>
> +#include <linux/platform_device.h>
> +#include <linux/iio/inkern.h>
> +#include <linux/hwmon.h>
> +#include <linux/hwmon-sysfs.h>
> +
> +/**
> + * struct iio_hwmon_state - device instance state
> + * @channels:		filled with null terminated array of channels from iio
> + * @num_channels:	number of channels in channels (saves counting twice)
> + * @hwmon_dev:		associated hwmon device
> + * @attr_group:	the group of attributes
> + * @attrs:		null terminated array of attribute pointers.
> + */
> +struct iio_hwmon_state {
> +	struct iio_channel **channels;
> +	int num_channels;
> +	struct device *hwmon_dev;
> +	struct attribute_group attr_group;
> +	struct attribute **attrs;
> +};
> +
> +/*
> + * Assumes that IIO and hwmon operate in the same base units.
> + * This is supposed to be true, but needs verification for
> + * new channel types.
> + */
> +static ssize_t iio_hwmon_read_val(struct device *dev,
> +				  struct device_attribute *attr,
> +				  char *buf)
> +{
> +	long result;
> +	int val, ret, scaleint, scalepart;
> +	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
> +	struct iio_hwmon_state *state = dev_get_drvdata(dev);
> +
> +	/*
> +	 * No locking between this pair, so theoretically possible
> +	 * the scale has changed.
> +	 */
> +	ret = iio_read_channel_raw(state->channels[sattr->index],
> +				   &val);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = iio_read_channel_scale(state->channels[sattr->index],
> +				     &scaleint, &scalepart);
> +	if (ret < 0)
> +		return ret;
> +	switch (ret) {
> +	case IIO_VAL_INT:
> +		result = val * scaleint;
> +		break;
> +	case IIO_VAL_INT_PLUS_MICRO:
> +		result = (long)val * (long)scaleint +
> +			div_s64((s64)val * (s64)scalepart, 1000000LL);
> +		break;
> +	case IIO_VAL_INT_PLUS_NANO:
> +		result = (long)val * (long)scaleint +
> +			div_s64((s64)val * (s64)scalepart, 1000000000LL);
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +	return sprintf(buf, "%ld\n", result);
> +}
> +
> +static void iio_hwmon_free_attrs(struct iio_hwmon_state *st)
> +{
> +	int i;
> +	struct sensor_device_attribute *a;
> +	for (i = 0; i < st->num_channels; i++)
> +		if (st->attrs[i]) {
> +			a = to_sensor_dev_attr(
> +				container_of(st->attrs[i],
> +					     struct device_attribute,
> +					     attr));

I finally looked into kasprintf ... which as it turns out allocates
memory. Yet, there is no kfree(a->dev_attr.attr.name).

Thanks,
Guenter




_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [PATCH] IIO:hwmon interface client driver.
  2011-11-07 17:52           ` Guenter Roeck
  (?)
@ 2011-11-07 18:09             ` Jonathan Cameron
  -1 siblings, 0 replies; 32+ messages in thread
From: Jonathan Cameron @ 2011-11-07 18:09 UTC (permalink / raw)
  To: guenter.roeck
  Cc: linux-iio, linux-kernel, khali, dmitry.torokhov, broonie, gregkh,
	alan, arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

On 11/07/2011 05:52 PM, Guenter Roeck wrote:
> Hi Jonathan,
> 
> I know I must be getting annoying, but somehow it seems I just keep
> finding something whenever I look at the code again.
Not at all.  It's becoming clear I wrote some extremely slapdash code.
Sorry I have been wasting your time with this!
> 
> On Mon, 2011-11-07 at 12:43 -0500, Jonathan Cameron wrote:
>> From: Jonathan Cameron <jic23@cam.ac.uk>
>>
>> Should move to drivers/hwmon once people are happy with it.
>>
>> Minimal support of simple in, curr and temp attributes
>> so far.
>>
>> Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
>> ---
>> Fixed up the missing free Guenter spotted.
>> Thanks!
>>  drivers/iio/Kconfig     |    8 ++
>>  drivers/iio/Makefile    |    1 +
>>  drivers/iio/iio_hwmon.c |  228 +++++++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 237 insertions(+), 0 deletions(-)
>>  create mode 100644 drivers/iio/iio_hwmon.c
>>
>> diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
>> index 308bc97..c2f0970 100644
>> --- a/drivers/iio/Kconfig
>> +++ b/drivers/iio/Kconfig
>> @@ -11,6 +11,14 @@ menuconfig IIO
>>  
>>  if IIO
>>  
>> +config IIO_HWMON
>> +       tristate "Hwmon driver that uses channels specified via iio maps"
>> +       depends on HWMON
>> +       help
>> +	  This is a platform driver that in combination with a suitable
>> +	  map allows IIO devices to provide  basic hwmon functionality
>> +	  for those channels specified in the map.
>> +
>>  source "drivers/iio/adc/Kconfig"
>>  source "drivers/iio/imu/Kconfig"
>>  source "drivers/iio/light/Kconfig"
>> diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
>> index cfb588a..5f9c01a 100644
>> --- a/drivers/iio/Makefile
>> +++ b/drivers/iio/Makefile
>> @@ -6,6 +6,7 @@ obj-y = inkern.o
>>  obj-$(CONFIG_IIO) += iio.o
>>  industrialio-y := core.o
>>  
>> +obj-$(CONFIG_IIO_HWMON) += iio_hwmon.o
>>  obj-y += adc/
>>  obj-y += imu/
>>  obj-y += light/
>> diff --git a/drivers/iio/iio_hwmon.c b/drivers/iio/iio_hwmon.c
>> new file mode 100644
>> index 0000000..880ce6d
>> --- /dev/null
>> +++ b/drivers/iio/iio_hwmon.c
>> @@ -0,0 +1,228 @@
>> +/* Hwmon client for industrial I/O devices
>> + *
>> + * Copyright (c) 2011 Jonathan Cameron
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License version 2 as published by
>> + * the Free Software Foundation.
>> + *
>> + * Limited functionality currently supported.
>> + */
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/slab.h>
>> +#include <linux/module.h>
>> +#include <linux/err.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/iio/inkern.h>
>> +#include <linux/hwmon.h>
>> +#include <linux/hwmon-sysfs.h>
>> +
>> +/**
>> + * struct iio_hwmon_state - device instance state
>> + * @channels:		filled with null terminated array of channels from iio
>> + * @num_channels:	number of channels in channels (saves counting twice)
>> + * @hwmon_dev:		associated hwmon device
>> + * @attr_group:	the group of attributes
>> + * @attrs:		null terminated array of attribute pointers.
>> + */
>> +struct iio_hwmon_state {
>> +	struct iio_channel **channels;
>> +	int num_channels;
>> +	struct device *hwmon_dev;
>> +	struct attribute_group attr_group;
>> +	struct attribute **attrs;
>> +};
>> +
>> +/*
>> + * Assumes that IIO and hwmon operate in the same base units.
>> + * This is supposed to be true, but needs verification for
>> + * new channel types.
>> + */
>> +static ssize_t iio_hwmon_read_val(struct device *dev,
>> +				  struct device_attribute *attr,
>> +				  char *buf)
>> +{
>> +	long result;
>> +	int val, ret, scaleint, scalepart;
>> +	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
>> +	struct iio_hwmon_state *state = dev_get_drvdata(dev);
>> +
>> +	/*
>> +	 * No locking between this pair, so theoretically possible
>> +	 * the scale has changed.
>> +	 */
>> +	ret = iio_read_channel_raw(state->channels[sattr->index],
>> +				   &val);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	ret = iio_read_channel_scale(state->channels[sattr->index],
>> +				     &scaleint, &scalepart);
>> +	if (ret < 0)
>> +		return ret;
>> +	switch (ret) {
>> +	case IIO_VAL_INT:
>> +		result = val * scaleint;
>> +		break;
>> +	case IIO_VAL_INT_PLUS_MICRO:
>> +		result = (long)val * (long)scaleint +
>> +			div_s64((s64)val * (s64)scalepart, 1000000LL);
>> +		break;
>> +	case IIO_VAL_INT_PLUS_NANO:
>> +		result = (long)val * (long)scaleint +
>> +			div_s64((s64)val * (s64)scalepart, 1000000000LL);
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +	return sprintf(buf, "%ld\n", result);
>> +}
>> +
>> +static void iio_hwmon_free_attrs(struct iio_hwmon_state *st)
>> +{
>> +	int i;
>> +	struct sensor_device_attribute *a;
>> +	for (i = 0; i < st->num_channels; i++)
>> +		if (st->attrs[i]) {
>> +			a = to_sensor_dev_attr(
>> +				container_of(st->attrs[i],
>> +					     struct device_attribute,
>> +					     attr));
> 
> I finally looked into kasprintf ... which as it turns out allocates
> memory. Yet, there is no kfree(a->dev_attr.attr.name).
> 
> Thanks,
> Guenter
> 
> 
> 


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

* Re: [PATCH] IIO:hwmon interface client driver.
@ 2011-11-07 18:09             ` Jonathan Cameron
  0 siblings, 0 replies; 32+ messages in thread
From: Jonathan Cameron @ 2011-11-07 18:09 UTC (permalink / raw)
  To: guenter.roeck
  Cc: linux-iio, linux-kernel, khali, dmitry.torokhov, broonie, gregkh,
	alan, arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

On 11/07/2011 05:52 PM, Guenter Roeck wrote:
> Hi Jonathan,
> 
> I know I must be getting annoying, but somehow it seems I just keep
> finding something whenever I look at the code again.
Not at all.  It's becoming clear I wrote some extremely slapdash code.
Sorry I have been wasting your time with this!
> 
> On Mon, 2011-11-07 at 12:43 -0500, Jonathan Cameron wrote:
>> From: Jonathan Cameron <jic23@cam.ac.uk>
>>
>> Should move to drivers/hwmon once people are happy with it.
>>
>> Minimal support of simple in, curr and temp attributes
>> so far.
>>
>> Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
>> ---
>> Fixed up the missing free Guenter spotted.
>> Thanks!
>>  drivers/iio/Kconfig     |    8 ++
>>  drivers/iio/Makefile    |    1 +
>>  drivers/iio/iio_hwmon.c |  228 +++++++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 237 insertions(+), 0 deletions(-)
>>  create mode 100644 drivers/iio/iio_hwmon.c
>>
>> diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
>> index 308bc97..c2f0970 100644
>> --- a/drivers/iio/Kconfig
>> +++ b/drivers/iio/Kconfig
>> @@ -11,6 +11,14 @@ menuconfig IIO
>>  
>>  if IIO
>>  
>> +config IIO_HWMON
>> +       tristate "Hwmon driver that uses channels specified via iio maps"
>> +       depends on HWMON
>> +       help
>> +	  This is a platform driver that in combination with a suitable
>> +	  map allows IIO devices to provide  basic hwmon functionality
>> +	  for those channels specified in the map.
>> +
>>  source "drivers/iio/adc/Kconfig"
>>  source "drivers/iio/imu/Kconfig"
>>  source "drivers/iio/light/Kconfig"
>> diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
>> index cfb588a..5f9c01a 100644
>> --- a/drivers/iio/Makefile
>> +++ b/drivers/iio/Makefile
>> @@ -6,6 +6,7 @@ obj-y = inkern.o
>>  obj-$(CONFIG_IIO) += iio.o
>>  industrialio-y := core.o
>>  
>> +obj-$(CONFIG_IIO_HWMON) += iio_hwmon.o
>>  obj-y += adc/
>>  obj-y += imu/
>>  obj-y += light/
>> diff --git a/drivers/iio/iio_hwmon.c b/drivers/iio/iio_hwmon.c
>> new file mode 100644
>> index 0000000..880ce6d
>> --- /dev/null
>> +++ b/drivers/iio/iio_hwmon.c
>> @@ -0,0 +1,228 @@
>> +/* Hwmon client for industrial I/O devices
>> + *
>> + * Copyright (c) 2011 Jonathan Cameron
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License version 2 as published by
>> + * the Free Software Foundation.
>> + *
>> + * Limited functionality currently supported.
>> + */
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/slab.h>
>> +#include <linux/module.h>
>> +#include <linux/err.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/iio/inkern.h>
>> +#include <linux/hwmon.h>
>> +#include <linux/hwmon-sysfs.h>
>> +
>> +/**
>> + * struct iio_hwmon_state - device instance state
>> + * @channels:		filled with null terminated array of channels from iio
>> + * @num_channels:	number of channels in channels (saves counting twice)
>> + * @hwmon_dev:		associated hwmon device
>> + * @attr_group:	the group of attributes
>> + * @attrs:		null terminated array of attribute pointers.
>> + */
>> +struct iio_hwmon_state {
>> +	struct iio_channel **channels;
>> +	int num_channels;
>> +	struct device *hwmon_dev;
>> +	struct attribute_group attr_group;
>> +	struct attribute **attrs;
>> +};
>> +
>> +/*
>> + * Assumes that IIO and hwmon operate in the same base units.
>> + * This is supposed to be true, but needs verification for
>> + * new channel types.
>> + */
>> +static ssize_t iio_hwmon_read_val(struct device *dev,
>> +				  struct device_attribute *attr,
>> +				  char *buf)
>> +{
>> +	long result;
>> +	int val, ret, scaleint, scalepart;
>> +	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
>> +	struct iio_hwmon_state *state = dev_get_drvdata(dev);
>> +
>> +	/*
>> +	 * No locking between this pair, so theoretically possible
>> +	 * the scale has changed.
>> +	 */
>> +	ret = iio_read_channel_raw(state->channels[sattr->index],
>> +				   &val);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	ret = iio_read_channel_scale(state->channels[sattr->index],
>> +				     &scaleint, &scalepart);
>> +	if (ret < 0)
>> +		return ret;
>> +	switch (ret) {
>> +	case IIO_VAL_INT:
>> +		result = val * scaleint;
>> +		break;
>> +	case IIO_VAL_INT_PLUS_MICRO:
>> +		result = (long)val * (long)scaleint +
>> +			div_s64((s64)val * (s64)scalepart, 1000000LL);
>> +		break;
>> +	case IIO_VAL_INT_PLUS_NANO:
>> +		result = (long)val * (long)scaleint +
>> +			div_s64((s64)val * (s64)scalepart, 1000000000LL);
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +	return sprintf(buf, "%ld\n", result);
>> +}
>> +
>> +static void iio_hwmon_free_attrs(struct iio_hwmon_state *st)
>> +{
>> +	int i;
>> +	struct sensor_device_attribute *a;
>> +	for (i = 0; i < st->num_channels; i++)
>> +		if (st->attrs[i]) {
>> +			a = to_sensor_dev_attr(
>> +				container_of(st->attrs[i],
>> +					     struct device_attribute,
>> +					     attr));
> 
> I finally looked into kasprintf ... which as it turns out allocates
> memory. Yet, there is no kfree(a->dev_attr.attr.name).
> 
> Thanks,
> Guenter
> 
> 
> 

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

* Re: [lm-sensors] [PATCH] IIO:hwmon interface client driver.
@ 2011-11-07 18:09             ` Jonathan Cameron
  0 siblings, 0 replies; 32+ messages in thread
From: Jonathan Cameron @ 2011-11-07 18:09 UTC (permalink / raw)
  To: guenter.roeck
  Cc: linux-iio, linux-kernel, khali, dmitry.torokhov, broonie, gregkh,
	alan, arnd, linus.walleij, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

On 11/07/2011 05:52 PM, Guenter Roeck wrote:
> Hi Jonathan,
> 
> I know I must be getting annoying, but somehow it seems I just keep
> finding something whenever I look at the code again.
Not at all.  It's becoming clear I wrote some extremely slapdash code.
Sorry I have been wasting your time with this!
> 
> On Mon, 2011-11-07 at 12:43 -0500, Jonathan Cameron wrote:
>> From: Jonathan Cameron <jic23@cam.ac.uk>
>>
>> Should move to drivers/hwmon once people are happy with it.
>>
>> Minimal support of simple in, curr and temp attributes
>> so far.
>>
>> Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
>> ---
>> Fixed up the missing free Guenter spotted.
>> Thanks!
>>  drivers/iio/Kconfig     |    8 ++
>>  drivers/iio/Makefile    |    1 +
>>  drivers/iio/iio_hwmon.c |  228 +++++++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 237 insertions(+), 0 deletions(-)
>>  create mode 100644 drivers/iio/iio_hwmon.c
>>
>> diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
>> index 308bc97..c2f0970 100644
>> --- a/drivers/iio/Kconfig
>> +++ b/drivers/iio/Kconfig
>> @@ -11,6 +11,14 @@ menuconfig IIO
>>  
>>  if IIO
>>  
>> +config IIO_HWMON
>> +       tristate "Hwmon driver that uses channels specified via iio maps"
>> +       depends on HWMON
>> +       help
>> +	  This is a platform driver that in combination with a suitable
>> +	  map allows IIO devices to provide  basic hwmon functionality
>> +	  for those channels specified in the map.
>> +
>>  source "drivers/iio/adc/Kconfig"
>>  source "drivers/iio/imu/Kconfig"
>>  source "drivers/iio/light/Kconfig"
>> diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
>> index cfb588a..5f9c01a 100644
>> --- a/drivers/iio/Makefile
>> +++ b/drivers/iio/Makefile
>> @@ -6,6 +6,7 @@ obj-y = inkern.o
>>  obj-$(CONFIG_IIO) += iio.o
>>  industrialio-y := core.o
>>  
>> +obj-$(CONFIG_IIO_HWMON) += iio_hwmon.o
>>  obj-y += adc/
>>  obj-y += imu/
>>  obj-y += light/
>> diff --git a/drivers/iio/iio_hwmon.c b/drivers/iio/iio_hwmon.c
>> new file mode 100644
>> index 0000000..880ce6d
>> --- /dev/null
>> +++ b/drivers/iio/iio_hwmon.c
>> @@ -0,0 +1,228 @@
>> +/* Hwmon client for industrial I/O devices
>> + *
>> + * Copyright (c) 2011 Jonathan Cameron
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License version 2 as published by
>> + * the Free Software Foundation.
>> + *
>> + * Limited functionality currently supported.
>> + */
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/slab.h>
>> +#include <linux/module.h>
>> +#include <linux/err.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/iio/inkern.h>
>> +#include <linux/hwmon.h>
>> +#include <linux/hwmon-sysfs.h>
>> +
>> +/**
>> + * struct iio_hwmon_state - device instance state
>> + * @channels:		filled with null terminated array of channels from iio
>> + * @num_channels:	number of channels in channels (saves counting twice)
>> + * @hwmon_dev:		associated hwmon device
>> + * @attr_group:	the group of attributes
>> + * @attrs:		null terminated array of attribute pointers.
>> + */
>> +struct iio_hwmon_state {
>> +	struct iio_channel **channels;
>> +	int num_channels;
>> +	struct device *hwmon_dev;
>> +	struct attribute_group attr_group;
>> +	struct attribute **attrs;
>> +};
>> +
>> +/*
>> + * Assumes that IIO and hwmon operate in the same base units.
>> + * This is supposed to be true, but needs verification for
>> + * new channel types.
>> + */
>> +static ssize_t iio_hwmon_read_val(struct device *dev,
>> +				  struct device_attribute *attr,
>> +				  char *buf)
>> +{
>> +	long result;
>> +	int val, ret, scaleint, scalepart;
>> +	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
>> +	struct iio_hwmon_state *state = dev_get_drvdata(dev);
>> +
>> +	/*
>> +	 * No locking between this pair, so theoretically possible
>> +	 * the scale has changed.
>> +	 */
>> +	ret = iio_read_channel_raw(state->channels[sattr->index],
>> +				   &val);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	ret = iio_read_channel_scale(state->channels[sattr->index],
>> +				     &scaleint, &scalepart);
>> +	if (ret < 0)
>> +		return ret;
>> +	switch (ret) {
>> +	case IIO_VAL_INT:
>> +		result = val * scaleint;
>> +		break;
>> +	case IIO_VAL_INT_PLUS_MICRO:
>> +		result = (long)val * (long)scaleint +
>> +			div_s64((s64)val * (s64)scalepart, 1000000LL);
>> +		break;
>> +	case IIO_VAL_INT_PLUS_NANO:
>> +		result = (long)val * (long)scaleint +
>> +			div_s64((s64)val * (s64)scalepart, 1000000000LL);
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +	return sprintf(buf, "%ld\n", result);
>> +}
>> +
>> +static void iio_hwmon_free_attrs(struct iio_hwmon_state *st)
>> +{
>> +	int i;
>> +	struct sensor_device_attribute *a;
>> +	for (i = 0; i < st->num_channels; i++)
>> +		if (st->attrs[i]) {
>> +			a = to_sensor_dev_attr(
>> +				container_of(st->attrs[i],
>> +					     struct device_attribute,
>> +					     attr));
> 
> I finally looked into kasprintf ... which as it turns out allocates
> memory. Yet, there is no kfree(a->dev_attr.attr.name).
> 
> Thanks,
> Guenter
> 
> 
> 


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [PATCH 3/5] IIO:CORE add in kernel interface mapping and getting IIO channels.
  2011-11-07 15:44   ` [lm-sensors] [PATCH 3/5] IIO:CORE add in kernel interface mapping Jonathan Cameron
@ 2011-11-10 13:25     ` Mark Brown
  -1 siblings, 0 replies; 32+ messages in thread
From: Mark Brown @ 2011-11-10 13:25 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio, linux-kernel, guenter.roeck, khali, dmitry.torokhov,
	gregkh, alan, arnd, linus.walleij, lars, maxime.ripard,
	lm-sensors, thomas.petazzoni, zdevai, Jonathan Cameron

On Mon, Nov 07, 2011 at 03:44:39PM +0000, Jonathan Cameron wrote:
> From: Jonathan Cameron <jic23@cam.ac.uk>
> 
> Two elements here:
> * Map as defined in include/linux/iio/inkern.h
> * Matching code to actually get the iio_dev and channel
> that we want from the global list of IIO devices.

I've not read it thoroughly but this certainly this looks sensible from
an external interface point of view, I'd expect that issues can be
worked through incrementally.

Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

> +extern struct list_head iio_map_list;

It's surprising that this is part of the external interface of IIO
rather than something hidden within the implementation.

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

* Re: [lm-sensors] [PATCH 3/5] IIO:CORE add in kernel interface
@ 2011-11-10 13:25     ` Mark Brown
  0 siblings, 0 replies; 32+ messages in thread
From: Mark Brown @ 2011-11-10 13:25 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio, linux-kernel, guenter.roeck, khali, dmitry.torokhov,
	gregkh, alan, arnd, linus.walleij, lars, maxime.ripard,
	lm-sensors, thomas.petazzoni, zdevai, Jonathan Cameron

On Mon, Nov 07, 2011 at 03:44:39PM +0000, Jonathan Cameron wrote:
> From: Jonathan Cameron <jic23@cam.ac.uk>
> 
> Two elements here:
> * Map as defined in include/linux/iio/inkern.h
> * Matching code to actually get the iio_dev and channel
> that we want from the global list of IIO devices.

I've not read it thoroughly but this certainly this looks sensible from
an external interface point of view, I'd expect that issues can be
worked through incrementally.

Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

> +extern struct list_head iio_map_list;

It's surprising that this is part of the external interface of IIO
rather than something hidden within the implementation.

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [PATCH 3/5] IIO:CORE add in kernel interface mapping and getting IIO channels.
  2011-11-10 13:25     ` [lm-sensors] [PATCH 3/5] IIO:CORE add in kernel interface Mark Brown
@ 2011-11-10 17:04       ` Jonathan Cameron
  -1 siblings, 0 replies; 32+ messages in thread
From: Jonathan Cameron @ 2011-11-10 17:04 UTC (permalink / raw)
  To: Mark Brown
  Cc: Jonathan Cameron, linux-iio, linux-kernel, guenter.roeck, khali,
	dmitry.torokhov, gregkh, alan, arnd, linus.walleij, lars,
	maxime.ripard, lm-sensors, thomas.petazzoni, zdevai

On 11/10/2011 01:25 PM, Mark Brown wrote:
> On Mon, Nov 07, 2011 at 03:44:39PM +0000, Jonathan Cameron wrote:
>> From: Jonathan Cameron <jic23@cam.ac.uk>
>>
>> Two elements here:
>> * Map as defined in include/linux/iio/inkern.h
>> * Matching code to actually get the iio_dev and channel
>> that we want from the global list of IIO devices.
> 
> I've not read it thoroughly but this certainly this looks sensible from
> an external interface point of view, I'd expect that issues can be
> worked through incrementally.
> 
> Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Thanks.
> 
>> +extern struct list_head iio_map_list;
> 
> It's surprising that this is part of the external interface of IIO
> rather than something hidden within the implementation.
You are quite correct. I was being lazy and had that one element that
didn't fit in any headers.  I'lll add a trivial inkern-core.h to handle
that one bit.



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

* Re: [lm-sensors] [PATCH 3/5] IIO:CORE add in kernel interface
@ 2011-11-10 17:04       ` Jonathan Cameron
  0 siblings, 0 replies; 32+ messages in thread
From: Jonathan Cameron @ 2011-11-10 17:04 UTC (permalink / raw)
  To: Mark Brown
  Cc: Jonathan Cameron, linux-iio, linux-kernel, guenter.roeck, khali,
	dmitry.torokhov, gregkh, alan, arnd, linus.walleij, lars,
	maxime.ripard, lm-sensors, thomas.petazzoni, zdevai

On 11/10/2011 01:25 PM, Mark Brown wrote:
> On Mon, Nov 07, 2011 at 03:44:39PM +0000, Jonathan Cameron wrote:
>> From: Jonathan Cameron <jic23@cam.ac.uk>
>>
>> Two elements here:
>> * Map as defined in include/linux/iio/inkern.h
>> * Matching code to actually get the iio_dev and channel
>> that we want from the global list of IIO devices.
> 
> I've not read it thoroughly but this certainly this looks sensible from
> an external interface point of view, I'd expect that issues can be
> worked through incrementally.
> 
> Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Thanks.
> 
>> +extern struct list_head iio_map_list;
> 
> It's surprising that this is part of the external interface of IIO
> rather than something hidden within the implementation.
You are quite correct. I was being lazy and had that one element that
didn't fit in any headers.  I'lll add a trivial inkern-core.h to handle
that one bit.



_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [PATCH 3/5] IIO:CORE add in kernel interface mapping and getting IIO channels.
  2011-11-07 15:44   ` [lm-sensors] [PATCH 3/5] IIO:CORE add in kernel interface mapping Jonathan Cameron
@ 2011-11-11 15:42     ` Linus Walleij
  -1 siblings, 0 replies; 32+ messages in thread
From: Linus Walleij @ 2011-11-11 15:42 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio, linux-kernel, guenter.roeck, khali, dmitry.torokhov,
	broonie, gregkh, alan, arnd, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

On Mon, Nov 7, 2011 at 4:44 PM, Jonathan Cameron <jic23@kernel.org> wrote:

> From: Jonathan Cameron <jic23@cam.ac.uk>
>
> Two elements here:
> * Map as defined in include/linux/iio/inkern.h
> * Matching code to actually get the iio_dev and channel
> that we want from the global list of IIO devices.
>
> Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>

Overall this is what we want:
Acked-by: Linus Walleij <linus.walleij@linaro.org>

Thanks,
Linus Walleij

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

* Re: [lm-sensors] [PATCH 3/5] IIO:CORE add in kernel interface
@ 2011-11-11 15:42     ` Linus Walleij
  0 siblings, 0 replies; 32+ messages in thread
From: Linus Walleij @ 2011-11-11 15:42 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio, linux-kernel, guenter.roeck, khali, dmitry.torokhov,
	broonie, gregkh, alan, arnd, lars, maxime.ripard, lm-sensors,
	thomas.petazzoni, zdevai, Jonathan Cameron

On Mon, Nov 7, 2011 at 4:44 PM, Jonathan Cameron <jic23@kernel.org> wrote:

> From: Jonathan Cameron <jic23@cam.ac.uk>
>
> Two elements here:
> * Map as defined in include/linux/iio/inkern.h
> * Matching code to actually get the iio_dev and channel
> that we want from the global list of IIO devices.
>
> Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>

Overall this is what we want:
Acked-by: Linus Walleij <linus.walleij@linaro.org>

Thanks,
Linus Walleij

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

end of thread, other threads:[~2011-11-11 15:42 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-11-07 15:44 [PATCH 0/5 V4] IIO in kernel interfaces (pull) Jonathan Cameron
2011-11-07 15:44 ` [lm-sensors] " Jonathan Cameron
2011-11-07 15:44 ` [PATCH 1/5] IIO: core: add datasheet_name to chan_spec Jonathan Cameron
2011-11-07 15:44   ` [lm-sensors] " Jonathan Cameron
2011-11-07 15:44 ` [PATCH 2/5] IIO:ADC:max1363 add datasheet_name entries Jonathan Cameron
2011-11-07 15:44   ` [lm-sensors] " Jonathan Cameron
2011-11-07 15:44 ` [PATCH 3/5] IIO:CORE add in kernel interface mapping and getting IIO channels Jonathan Cameron
2011-11-07 15:44   ` [lm-sensors] [PATCH 3/5] IIO:CORE add in kernel interface mapping Jonathan Cameron
2011-11-10 13:25   ` [PATCH 3/5] IIO:CORE add in kernel interface mapping and getting IIO channels Mark Brown
2011-11-10 13:25     ` [lm-sensors] [PATCH 3/5] IIO:CORE add in kernel interface Mark Brown
2011-11-10 17:04     ` [PATCH 3/5] IIO:CORE add in kernel interface mapping and getting IIO channels Jonathan Cameron
2011-11-10 17:04       ` [lm-sensors] [PATCH 3/5] IIO:CORE add in kernel interface Jonathan Cameron
2011-11-11 15:42   ` [PATCH 3/5] IIO:CORE add in kernel interface mapping and getting IIO channels Linus Walleij
2011-11-11 15:42     ` [lm-sensors] [PATCH 3/5] IIO:CORE add in kernel interface Linus Walleij
2011-11-07 15:44 ` [PATCH 4/5] IIO:hwmon interface client driver Jonathan Cameron
2011-11-07 15:44   ` [lm-sensors] " Jonathan Cameron
2011-11-07 16:29   ` Guenter Roeck
2011-11-07 16:29     ` [lm-sensors] " Guenter Roeck
2011-11-07 16:29     ` Guenter Roeck
2011-11-07 17:39     ` Jonathan Cameron
2011-11-07 17:39       ` [lm-sensors] " Jonathan Cameron
2011-11-07 17:39       ` Jonathan Cameron
2011-11-07 17:43       ` [PATCH] " Jonathan Cameron
2011-11-07 17:43         ` [lm-sensors] " Jonathan Cameron
2011-11-07 17:52         ` Guenter Roeck
2011-11-07 17:52           ` [lm-sensors] " Guenter Roeck
2011-11-07 17:52           ` Guenter Roeck
2011-11-07 18:09           ` Jonathan Cameron
2011-11-07 18:09             ` [lm-sensors] " Jonathan Cameron
2011-11-07 18:09             ` Jonathan Cameron
2011-11-07 15:44 ` [PATCH 5/5] stargate2: example of map configuration for iio to hwmon example Jonathan Cameron
2011-11-07 15:44   ` [lm-sensors] [PATCH 5/5] stargate2: example of map configuration Jonathan Cameron

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.