Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH v7 00/12] mux controller abstraction and iio/i2c muxes
From: Peter Rosin @ 2017-01-08 21:56 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: linux-kernel, Rob Herring, Mark Rutland, Jonathan Cameron,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Jonathan Corbet, Arnd Bergmann, Greg Kroah-Hartman, linux-i2c,
	devicetree, linux-iio, linux-doc
In-Reply-To: <20170108105129.GB1983@katana>

On 2017-01-08 11:51, Wolfram Sang wrote:
> Hi peda,
> 
>> One thing that I would like to do, but don't see a solution
>> for, is to move the mux control code that is present in
>> various drivers in drivers/i2c/muxes to this new minimalistic
>> muxing subsystem, thus converting all present i2c muxes (but
>> perhaps not gates and arbitrators) to be i2c-mux-simple muxes.
> 
> In a few lines, what is preventing that?

i2c-mux-gpio has the auto-detect for mux-/parent-locked and (old
style?) support for specifying what gpios to use with platform data
from code (i.e. not from dt/acpi). All of that gets messier if
someone else (the mux) owns the gpios.

i2c-mux-pinctrl has similar issues.

i2c-mux-reg has the platform data from code issue, plus a read-write
mode (mux is write only, at least as-is).

i2c-mux-pca954x has things going on like irqs (not applied yet) and
a reset gpio that makes it a poor candidate for something generic.

i2c-mux-mlxcplc could probably be converted (I don't think it existed
when I wrote the quoted paragraph).

So, since there are issues with just about all of the i2c muxes, the
only way forward that I see would be to instantiate the mux locally
and feed it to the generic i2c-mux-simple, but what would be the point
of that? There would still be a handful of i2c-mux drivers under
drivers/i2c/muxes.

Maybe some of the above are non-issues and maybe I have failed to see
some issue? I didn't think too hard about it...

>> I'm using an rwsem to lock a mux, but that isn't really a
>> perfect fit. Is there a better locking primitive that I don't
>> know about that fits better? I had a mutex at one point, but
>> that didn't allow any concurrent accesses at all. At least
>> the rwsem allows concurrent access as long as all users
>> agree on the mux state, but I suspect that the rwsem will
>> degrade to the mutex situation pretty quickly if there is
>> any contention.
> 
> Maybe ask this question in a seperate email thread on lkml cc-ing the
> locking gurus (with a pointer to this thread)?

I don't think there is a suitable primitive. In order to get
something that really matches, I think the users need to hint
how long they (think they) are going to lock the mux. And
then it no longer a primitive, methinks. It something that is
much heavier...

>> Also, the "mux" name feels a bit ambitious, there are many muxes
>> in the world, and this tiny bit of code is probably not good
>> enough to be a nice fit for all...
> 
> "... and it probably never will support anything other than
> AT-harddisks, as that's all I have..." ;))

:-)

> Thanks for this work!

And thanks for looking!

Cheers,
peda

^ permalink raw reply

* Re: [PATCH v7 05/12] mux: support simplified bindings for single-user gpio mux
From: Peter Rosin @ 2017-01-08 21:56 UTC (permalink / raw)
  To: Jonathan Cameron, linux-kernel
  Cc: Wolfram Sang, Rob Herring, Mark Rutland, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Jonathan Corbet,
	Arnd Bergmann, Greg Kroah-Hartman, linux-i2c, devicetree,
	linux-iio, linux-doc
In-Reply-To: <9652928a-5d54-5fa4-48ad-6df57bc8513c@kernel.org>

On 2017-01-08 11:28, Jonathan Cameron wrote:
> On 05/01/17 16:21, Peter Rosin wrote:
>> On 2017-01-04 13:16, Peter Rosin wrote:
>>> Signed-off-by: Peter Rosin <peda@axentia.se>
>>> ---
>>>  drivers/mux/mux-core.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++--
>>>  drivers/mux/mux-gpio.c | 56 ++--------------------------------
>>>  include/linux/mux.h    |  7 +++++
>>>  3 files changed, 89 insertions(+), 55 deletions(-)
>>>
>>> diff --git a/drivers/mux/mux-core.c b/drivers/mux/mux-core.c
>>> index 21da15a264ad..d887ae1c0e55 100644
>>> --- a/drivers/mux/mux-core.c
>>> +++ b/drivers/mux/mux-core.c
>>> @@ -15,6 +15,7 @@
>>>  #include <linux/device.h>
>>>  #include <linux/err.h>
>>>  #include <linux/idr.h>
>>> +#include <linux/gpio/consumer.h>
>>>  #include <linux/module.h>
>>>  #include <linux/mux.h>
>>>  #include <linux/of.h>
>>> @@ -288,6 +289,63 @@ static struct mux_chip *of_find_mux_chip_by_node(struct device_node *np)
>>>  	return dev ? to_mux_chip(dev) : NULL;
>>>  }
>>>  
>>> +#ifdef CONFIG_MUX_GPIO
>>> +
>>> +static int mux_gpio_set(struct mux_control *mux, int state)
>>> +{
>>> +	struct mux_gpio *mux_gpio = mux_chip_priv(mux->chip);
>>> +	int i;
>>> +
>>> +	for (i = 0; i < mux_gpio->gpios->ndescs; i++)
>>> +		mux_gpio->val[i] = (state >> i) & 1;
>>> +
>>> +	gpiod_set_array_value_cansleep(mux_gpio->gpios->ndescs,
>>> +				       mux_gpio->gpios->desc,
>>> +				       mux_gpio->val);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static const struct mux_control_ops mux_gpio_ops = {
>>> +	.set = mux_gpio_set,
>>> +};
>>> +
>>> +struct mux_chip *mux_gpio_alloc(struct device *dev)
>>> +{
>>> +	struct mux_chip *mux_chip;
>>> +	struct mux_gpio *mux_gpio;
>>> +	int pins;
>>> +	int ret;
>>> +
>>> +	pins = gpiod_count(dev, "mux");
>>> +	if (pins < 0)
>>> +		return ERR_PTR(pins);
>>> +
>>> +	mux_chip = devm_mux_chip_alloc(dev, 1, sizeof(*mux_gpio) +
>>> +				       pins * sizeof(*mux_gpio->val));
>>> +	if (!mux_chip)
>>> +		return ERR_PTR(-ENOMEM);
>>> +
>>> +	mux_gpio = mux_chip_priv(mux_chip);
>>> +	mux_gpio->val = (int *)(mux_gpio + 1);
>>> +	mux_chip->ops = &mux_gpio_ops;
>>> +
>>> +	mux_gpio->gpios = devm_gpiod_get_array(dev, "mux", GPIOD_OUT_LOW);
>>> +	if (IS_ERR(mux_gpio->gpios)) {
>>> +		ret = PTR_ERR(mux_gpio->gpios);
>>> +		if (ret != -EPROBE_DEFER)
>>> +			dev_err(dev, "failed to get gpios\n");
>>> +		return ERR_PTR(ret);
>>> +	}
>>> +	WARN_ON(pins != mux_gpio->gpios->ndescs);
>>> +	mux_chip->mux->states = 1 << pins;
>>> +
>>> +	return mux_chip;
>>> +}
>>> +EXPORT_SYMBOL_GPL(mux_gpio_alloc);
>>> +
>>> +#endif /* CONFIG_MUX_GPIO */
>>> +
>>>  struct mux_control *mux_control_get(struct device *dev, const char *mux_name)
>>>  {
>>>  	struct device_node *np = dev->of_node;
>>> @@ -307,9 +365,28 @@ struct mux_control *mux_control_get(struct device *dev, const char *mux_name)
>>>  	ret = of_parse_phandle_with_args(np,
>>>  					 "mux-controls", "#mux-control-cells",
>>>  					 index, &args);
>>> +
>>> +#ifdef CONFIG_MUX_GPIO
>>> +	if (ret == -ENOENT && !mux_name && gpiod_count(dev, "mux") > 0) {
>>> +		mux_chip = mux_gpio_alloc(dev);
>>> +		if (!IS_ERR(mux_chip)) {
>>> +			ret = devm_mux_chip_register(dev, mux_chip);
>>> +			if (ret < 0) {
>>> +				dev_err(dev, "failed to register mux-chip\n");
>>> +				return ERR_PTR(ret);
>>> +			}
>>> +			get_device(&mux_chip->dev);
>>> +			return mux_chip->mux;
>>> +		}
>>> +
>>> +		ret = PTR_ERR(mux_chip);
>>> +	}
>>> +#endif
>>> +
>>>  	if (ret) {
>>> -		dev_err(dev, "%s: failed to get mux-control %s(%i)\n",
>>> -			np->full_name, mux_name ?: "", index);
>>> +		if (ret != -EPROBE_DEFER)
>>> +			dev_err(dev, "%s: failed to get mux-control %s(%i)\n",
>>> +				np->full_name, mux_name ?: "", index);
>>>  		return ERR_PTR(ret);
>>>  	}
>>>  
>>> diff --git a/drivers/mux/mux-gpio.c b/drivers/mux/mux-gpio.c
>>> index 76b52bc63470..8a7bfbc0c4bb 100644
>>> --- a/drivers/mux/mux-gpio.c
>>> +++ b/drivers/mux/mux-gpio.c
>>> @@ -11,37 +11,12 @@
>>>   */
>>>  
>>>  #include <linux/err.h>
>>> -#include <linux/gpio/consumer.h>
>>>  #include <linux/module.h>
>>>  #include <linux/mux.h>
>>>  #include <linux/of_platform.h>
>>>  #include <linux/platform_device.h>
>>>  #include <linux/property.h>
>>
>> Instead of moving the mux-gpio guts from mux-gpio.c to mux-core.c, I
>> will instead make CONFIG_MUX_GPIO a bool option (no module possible)
>> and call it from the mux-core. That will be cleaner and less of a
>> break of abstractions in my opinion.
> Hmm. I wonder if the balance is right here or whether we should just not have the
> simplified binding at all as it breaks the assumption that all muxes are of the
> same level...
> 
> I like the binding, but it is causing significant complexity in here.

Yes, in this patch it looks pretty bad. But with the suggested
changes it at least looks fine (apart from the remaining ifdef
in mux_control_get). But then there's of course the conceptual
badness of the core depending on a specific driver that you
mention...

But. I expect that gpio based muxes will be in vast majority, and
giving them some extra freedoms is probably not wrong considering
the upside of the simpler binding.

>>
>> Cheers,
>> Peter
>>
>>> -struct mux_gpio {
>>> -	struct gpio_descs *gpios;
>>> -	int *val;
>>> -};
>>> -
>>> -static int mux_gpio_set(struct mux_control *mux, int state)
>>> -{
>>> -	struct mux_gpio *mux_gpio = mux_chip_priv(mux->chip);
>>> -	int i;
>>> -
>>> -	for (i = 0; i < mux_gpio->gpios->ndescs; i++)
>>> -		mux_gpio->val[i] = (state >> i) & 1;
>>> -
>>> -	gpiod_set_array_value_cansleep(mux_gpio->gpios->ndescs,
>>> -				       mux_gpio->gpios->desc,
>>> -				       mux_gpio->val);
>>> -
>>> -	return 0;
>>> -}
>>> -
>>> -static const struct mux_control_ops mux_gpio_ops = {
>>> -	.set = mux_gpio_set,
>>> -};
>>> -
>>>  static const struct of_device_id mux_gpio_dt_ids[] = {
>>>  	{ .compatible = "mux-gpio", },
>>>  	{ /* sentinel */ }
>>> @@ -51,38 +26,13 @@ MODULE_DEVICE_TABLE(of, mux_gpio_dt_ids);
>>>  static int mux_gpio_probe(struct platform_device *pdev)
>>>  {
>>>  	struct device *dev = &pdev->dev;
>>> -	struct device_node *np = dev->of_node;
>>>  	struct mux_chip *mux_chip;
>>> -	struct mux_gpio *mux_gpio;
>>> -	int pins;
>>>  	u32 idle_state;
>>>  	int ret;
>>>  
>>> -	if (!np)
>>> -		return -ENODEV;
>>> -
>>> -	pins = gpiod_count(dev, "mux");
>>> -	if (pins < 0)
>>> -		return pins;
>>> -
>>> -	mux_chip = devm_mux_chip_alloc(dev, 1, sizeof(*mux_gpio) +
>>> -				       pins * sizeof(*mux_gpio->val));
>>> -	if (!mux_chip)
>>> -		return -ENOMEM;
>>> -
>>> -	mux_gpio = mux_chip_priv(mux_chip);
>>> -	mux_gpio->val = (int *)(mux_gpio + 1);
>>> -	mux_chip->ops = &mux_gpio_ops;
>>> -
>>> -	mux_gpio->gpios = devm_gpiod_get_array(dev, "mux", GPIOD_OUT_LOW);
>>> -	if (IS_ERR(mux_gpio->gpios)) {
>>> -		ret = PTR_ERR(mux_gpio->gpios);
>>> -		if (ret != -EPROBE_DEFER)
>>> -			dev_err(dev, "failed to get gpios\n");
>>> -		return ret;
>>> -	}
>>> -	WARN_ON(pins != mux_gpio->gpios->ndescs);
>>> -	mux_chip->mux->states = 1 << pins;
>>> +	mux_chip = mux_gpio_alloc(dev);
>>> +	if (IS_ERR(mux_chip))
>>> +		return PTR_ERR(mux_chip);
>>>  
>>>  	ret = device_property_read_u32(dev, "idle-state", &idle_state);
>>>  	if (ret >= 0) {
>>> diff --git a/include/linux/mux.h b/include/linux/mux.h
>>> index 3b9439927f11..3bfee23cfb8c 100644
>>> --- a/include/linux/mux.h
>>> +++ b/include/linux/mux.h
>>> @@ -241,4 +241,11 @@ struct mux_control *devm_mux_control_get(struct device *dev,
>>>   */
>>>  void devm_mux_control_put(struct device *dev, struct mux_control *mux);
>>>  
>>> +struct mux_gpio {
>>> +	struct gpio_descs *gpios;
>>> +	int *val;
>>> +};
>>> +
>>> +struct mux_chip *mux_gpio_alloc(struct device *dev);
>>> +
>>>  #endif /* _LINUX_MUX_H */
>>>
>>
> 

^ permalink raw reply

* Re: [PATCH v7 03/12] mux: minimal mux subsystem and gpio-based mux controller
From: Peter Rosin @ 2017-01-08 21:55 UTC (permalink / raw)
  To: Jonathan Cameron, linux-kernel
  Cc: Wolfram Sang, Rob Herring, Mark Rutland, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Jonathan Corbet,
	Arnd Bergmann, Greg Kroah-Hartman, linux-i2c, devicetree,
	linux-iio, linux-doc
In-Reply-To: <9e4ee54f-f781-8d3b-1c46-1549392a9f2f@kernel.org>

On 2017-01-08 11:23, Jonathan Cameron wrote:
> On 04/01/17 12:16, Peter Rosin wrote:
>> Add a new minimalistic subsystem that handles multiplexer controllers.
>> When multiplexers are used in various places in the kernel, and the
>> same multiplexer controller can be used for several independent things,
>> there should be one place to implement support for said multiplexer
>> controller.
>>
>> A single multiplexer controller can also be used to control several
>> parallel multiplexers, that are in turn used by different subsystems
>> in the kernel, leading to a need to coordinate multiplexer accesses.
>> The multiplexer subsystem handles this coordination.
>>
>> This new mux controller subsystem initially comes with a single backend
>> driver that controls gpio based multiplexers. Even though not needed by
>> this initial driver, the mux controller subsystem is prepared to handle
>> chips with multiple (independent) mux controllers.
>>
>> Signed-off-by: Peter Rosin <peda@axentia.se>
> Reviewed-by: Jonathan Cameron <jic23@kernel.org>
>> ---
>>  Documentation/driver-model/devres.txt |   8 +
>>  MAINTAINERS                           |   2 +
>>  drivers/Kconfig                       |   2 +
>>  drivers/Makefile                      |   1 +
>>  drivers/mux/Kconfig                   |  33 +++
>>  drivers/mux/Makefile                  |   6 +
>>  drivers/mux/mux-core.c                | 398 ++++++++++++++++++++++++++++++++++
>>  drivers/mux/mux-gpio.c                | 120 ++++++++++
>>  include/linux/mux.h                   | 244 +++++++++++++++++++++
>>  9 files changed, 814 insertions(+)
>>  create mode 100644 drivers/mux/Kconfig
>>  create mode 100644 drivers/mux/Makefile
>>  create mode 100644 drivers/mux/mux-core.c
>>  create mode 100644 drivers/mux/mux-gpio.c
>>  create mode 100644 include/linux/mux.h
>>
>> diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
>> index dc51fb024190..1e9ae701a587 100644
>> --- a/Documentation/driver-model/devres.txt
>> +++ b/Documentation/driver-model/devres.txt
>> @@ -332,6 +332,14 @@ MEM
>>  MFD
>>    devm_mfd_add_devices()
>>  
>> +MUX
>> +  devm_mux_chip_alloc()
>> +  devm_mux_chip_free()
>> +  devm_mux_chip_register()
>> +  devm_mux_chip_unregister()
>> +  devm_mux_control_get()
>> +  devm_mux_control_put()
>> +
>>  PER-CPU MEM
>>    devm_alloc_percpu()
>>    devm_free_percpu()
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 32abef2b6d05..ebe96f3e25a0 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -8442,6 +8442,8 @@ MULTIPLEXER SUBSYSTEM
>>  M:	Peter Rosin <peda@axentia.se>
>>  S:	Maintained
>>  F:	Documentation/devicetree/bindings/mux/
>> +F:	include/linux/mux.h
>> +F:	drivers/mux/
>>  
>>  MULTISOUND SOUND DRIVER
>>  M:	Andrew Veliath <andrewtv@usa.net>
>> diff --git a/drivers/Kconfig b/drivers/Kconfig
>> index e1e2066cecdb..993aeb65affa 100644
>> --- a/drivers/Kconfig
>> +++ b/drivers/Kconfig
>> @@ -76,6 +76,8 @@ source "drivers/hwmon/Kconfig"
>>  
>>  source "drivers/thermal/Kconfig"
>>  
>> +source "drivers/mux/Kconfig"
>> +
> 
> Why this location in the list?  I think the convention for new subystems is
> to just go last in the list.

Oh. I'll move it to the end...

Thanks for all your acks/reviews!

Cheers,
peda

^ permalink raw reply

* Re: [PATCH 2/2] media: rc: add driver for IR remote receiver on MT7623 SoC
From: Sean Young @ 2017-01-08 21:16 UTC (permalink / raw)
  To: Sean Wang
  Cc: mchehab, hdegoede, hkallweit1, robh+dt, mark.rutland,
	matthias.bgg, andi.shyti, hverkuil, ivo.g.dimitrov.75,
	linux-media, devicetree, linux-mediatek, linux-arm-kernel,
	linux-kernel, keyhaede
In-Reply-To: <1483687885.16976.19.camel@mtkswgap22>

Hi Sean,

On Fri, Jan 06, 2017 at 03:31:25PM +0800, Sean Wang wrote:
> On Thu, 2017-01-05 at 17:12 +0000, Sean Young wrote:
> > On Fri, Jan 06, 2017 at 12:06:24AM +0800, sean.wang@mediatek.com wrote:
> > > +	/* Handle pulse and space until end of message */
> > > +	for (i = 0 ; i < MTK_CHKDATA_SZ ; i++) {
> > > +		val = mtk_r32(ir, MTK_CHKDATA_REG(i));
> > > +		dev_dbg(ir->dev, "@reg%d=0x%08x\n", i, val);
> > > +
> > > +		for (j = 0 ; j < 4 ; j++) {
> > > +			wid = (val & (0xff << j * 8)) >> j * 8;
> > > +			rawir.pulse = !rawir.pulse;
> > > +			rawir.duration = wid * (MTK_IR_SAMPLE + 1);
> > > +			ir_raw_event_store_with_filter(ir->rc, &rawir);
> > > +
> > > +			if (MTK_IR_END(wid))
> > > +				goto end_msg;
> > > +		}
> > > +	}
> > 
> > If I read this correctly, there is a maximum of 17 * 4 = 68 edges per
> > IR message. The rc6 mce key 0 (scancode 0x800f0400) is 69 edges, so that
> > won't work.
> > 
> Uh, this is related to hardware limitation. Maximum number hardware
> holds indeed is only 68 edges as you said :( 
> 
> For the case, I will try change the logic into that the whole message 
> is dropped if no end of message is seen within 68 counts to avoid
> wasting CPU for decoding. 

I'm not sure it is worthwhile dropping the IR in that case. The processing
is minimal and it might be possible that we have just enough IR to decode
a scancode even if the trailing end of message is missing. Note that
the call to ir_raw_event_set_idle() will generate an timeout IR event, so
there will always be an end of message marker.

All I wanted to do was point out a limitation in case there is a
workaround; if there is not then we might as well make do with the IR
we do have.

Thanks
Sean

^ permalink raw reply

* Re: [PATCH v4 1/2] power: reset: add linkstation-reset driver
From: Ryan Tandy @ 2017-01-08 17:02 UTC (permalink / raw)
  To: Roger Shimizu
  Cc: Andrew Lunn, Martin Michlmayr, Sylver Bruneau,
	Herbert Valerio Riedel, Florian Fainelli, linux-pm, devicetree,
	linux-arm-kernel
In-Reply-To: <20170107150451.17912-2-rogershimizu@gmail.com>

Hi Roger,

On Sun, Jan 08, 2017 at 12:04:50AM +0900, Roger Shimizu wrote:
>+config POWER_RESET_LINKSTATION
>+	bool "Buffalo Linkstation and its variants reset driver"
>+	depends on OF_GPIO && PLAT_ORION
>+	help
>+	  This driver supports power off Buffalo Linkstation / KuroBox Pro
>+	  NAS and their variants by sending commands to the micro-controller
>+	  which controls the main power.
>+
>+	  Say Y if you have a Buffalo Linkstation / KuroBox Pro NAS.
>+

Would it make sense to mention something about these being the 
ARM9/orion5x Linkstations? If I understand correctly, the older PPC 
Linkstations have a single-byte poweroff command. (Maybe they could even 
be supported by qnap-poweroff.)

See arch/powerpc/platforms/embedded6xx/linkstation.c around line 123, 
and arch/powerpc/platforms/embedded6xx/ls_uart.c.

^ permalink raw reply

* Re: [PATCH v5 2/2] iio: adc: hx711: Add IIO driver for AVIA HX711
From: Jonathan Cameron @ 2017-01-08 16:43 UTC (permalink / raw)
  To: Andreas Klinger, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-iio-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, pawel.moll-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ, knaack.h-Mmb7MZpHnFY,
	lars-Qo5EllUWu/uELgA04lAiVw, pmeerw-jW+XmwGofnusTnJN9+BGXg
In-Reply-To: <ca8b33a0-92b1-cf4e-d129-fc6876330a7f-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

On 08/01/17 11:12, Jonathan Cameron wrote:
> On 05/01/17 17:51, Andreas Klinger wrote:
>> This is the IIO driver for AVIA HX711 ADC which is mostly used in weighting
>> cells.
>>
>> The protocol is quite simple and using GPIOs:
>> One GPIO is used as clock (SCK) while another GPIO is read (DOUT)
>>
>> The raw value read from the chip is delivered. 
>> To get a weight one needs to subtract the zero offset and scale it.
>>
>> Signed-off-by: Andreas Klinger <ak-n176/SwNRljddJNmlsFzeA@public.gmane.org>
> I think your locking is a little heavy handed, perhaps a follow up patch to
> relax it a little.
> 
> I fixed a trivial typo when applying.
> 
> Applied to the togreg branch of iio.git and pushed out as testing for the
> autobuilders to play with it.
And I forgot to fix the missing mutex_unlock.  Good thing zeroday caught that.

Updated and pushed out again for another round of build tests.

Jonathan
> 
> Thanks,
> 
> Jonathan
>> ---
>>  drivers/iio/adc/Kconfig  |  19 ++
>>  drivers/iio/adc/Makefile |   1 +
>>  drivers/iio/adc/hx711.c  | 531 +++++++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 551 insertions(+)
>>  create mode 100644 drivers/iio/adc/hx711.c
>>
>> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
>> index 932de1f9d1e7..1dcf2ace1697 100644
>> --- a/drivers/iio/adc/Kconfig
>> +++ b/drivers/iio/adc/Kconfig
>> @@ -205,6 +205,25 @@ config HI8435
>>  	  This driver can also be built as a module. If so, the module will be
>>  	  called hi8435.
>>  
>> +config HX711
>> +	tristate "AVIA HX711 ADC for weight cells"
>> +	depends on GPIOLIB
>> +	help
>> +	  If you say yes here you get support for AVIA HX711 ADC which is used
>> +	  for weigh cells
>> +
>> +	  This driver uses two GPIOs, one acts as the clock and controls the
>> +	  channel selection and gain, the other one is used for the measurement
>> +          data
>> +
>> +	  Currently the raw value is read from the chip and delivered.
>> +	  To get an actual weight one needs to subtract the
>> +	  zero offset and multiply by a scale factor.
>> +	  This should be done in userspace.
>> +
>> +	  This driver can also be built as a module. If so, the module will be
>> +	  called hx711.
>> +
>>  config INA2XX_ADC
>>  	tristate "Texas Instruments INA2xx Power Monitors IIO driver"
>>  	depends on I2C && !SENSORS_INA2XX
>> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
>> index b1aa456e6af3..d46e289900ef 100644
>> --- a/drivers/iio/adc/Makefile
>> +++ b/drivers/iio/adc/Makefile
>> @@ -21,6 +21,7 @@ obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o
>>  obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o
>>  obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
>>  obj-$(CONFIG_HI8435) += hi8435.o
>> +obj-$(CONFIG_HX711) += hx711.o
>>  obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o
>>  obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o
>>  obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
>> diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
>> new file mode 100644
>> index 000000000000..e41414556158
>> --- /dev/null
>> +++ b/drivers/iio/adc/hx711.c
>> @@ -0,0 +1,531 @@
>> +/*
>> + * HX711: analog to digital converter for weight sensor module
>> + *
>> + * Copyright (c) 2016 Andreas Klinger <ak-n176/SwNRljddJNmlsFzeA@public.gmane.org>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + */
>> +#include <linux/err.h>
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/property.h>
>> +#include <linux/slab.h>
>> +#include <linux/sched.h>
>> +#include <linux/delay.h>
>> +#include <linux/iio/iio.h>
>> +#include <linux/iio/sysfs.h>
>> +#include <linux/gpio/consumer.h>
>> +#include <linux/regulator/consumer.h>
>> +
>> +/* gain to pulse and scale conversion */
>> +#define HX711_GAIN_MAX		3
>> +
>> +struct hx711_gain_to_scale {
>> +	int			gain;
>> +	int			gain_pulse;
>> +	int			scale;
>> +	int			channel;
>> +};
>> +
>> +/*
>> + * .scale depends on AVDD which in turn is known as soon as the regulator
>> + * is available
>> + * therefore we set .scale in hx711_probe()
>> + *
>> + * channel A in documentation is channel 0 in source code
>> + * channel B in documentation is channel 1 in source code
>> + */
>> +static struct hx711_gain_to_scale hx711_gain_to_scale[HX711_GAIN_MAX] = {
>> +	{ 128, 1, 0, 0 },
>> +	{  32, 2, 0, 1 },
>> +	{  64, 3, 0, 0 }
>> +};
>> +
>> +static int hx711_get_gain_to_pulse(int gain)
>> +{
>> +	int i;
>> +
>> +	for (i = 0; i < HX711_GAIN_MAX; i++)
>> +		if (hx711_gain_to_scale[i].gain == gain)
>> +			return hx711_gain_to_scale[i].gain_pulse;
>> +	return 1;
>> +}
>> +
>> +static int hx711_get_gain_to_scale(int gain)
>> +{
>> +	int i;
>> +
>> +	for (i = 0; i < HX711_GAIN_MAX; i++)
>> +		if (hx711_gain_to_scale[i].gain == gain)
>> +			return hx711_gain_to_scale[i].scale;
>> +	return 0;
>> +}
>> +
>> +static int hx711_get_scale_to_gain(int scale)
>> +{
>> +	int i;
>> +
>> +	for (i = 0; i < HX711_GAIN_MAX; i++)
>> +		if (hx711_gain_to_scale[i].scale == scale)
>> +			return hx711_gain_to_scale[i].gain;
>> +	return -EINVAL;
>> +}
>> +
>> +struct hx711_data {
>> +	struct device		*dev;
>> +	struct gpio_desc	*gpiod_pd_sck;
>> +	struct gpio_desc	*gpiod_dout;
>> +	struct regulator	*reg_avdd;
>> +	int			gain_set;	/* gain set on device */
>> +	int			gain_chan_a;	/* gain for channel A */
>> +	struct mutex		lock;
>> +};
>> +
>> +static int hx711_cycle(struct hx711_data *hx711_data)
>> +{
>> +	int val;
>> +
>> +	/*
>> +	 * if preempted for more then 60us while PD_SCK is high:
>> +	 * hx711 is going in reset
>> +	 * ==> measuring is false
>> +	 */
>> +	preempt_disable();
>> +	gpiod_set_value(hx711_data->gpiod_pd_sck, 1);
>> +	val = gpiod_get_value(hx711_data->gpiod_dout);
>> +	/*
>> +	 * here we are not waiting for 0.2 us as suggested by the datasheet,
>> +	 * because the oszilloscope showed in a test scenario
>> +	 * at least 1.15 us for PD_SCK high (T3 in datasheet)
>> +	 * and 0.56 us for PD_SCK low on TI Sitara with 800 MHz
>> +	 */
>> +	gpiod_set_value(hx711_data->gpiod_pd_sck, 0);
>> +	preempt_enable();
>> +
>> +	return val;
>> +}
>> +
>> +static int hx711_read(struct hx711_data *hx711_data)
>> +{
>> +	int i, ret;
>> +	int value = 0;
>> +	int val = gpiod_get_value(hx711_data->gpiod_dout);
>> +
>> +	/* we double check if it's really down */
>> +	if (val)
>> +		return -EIO;
>> +
>> +	for (i = 0; i < 24; i++) {
>> +		value <<= 1;
>> +		ret = hx711_cycle(hx711_data);
>> +		if (ret)
>> +			value++;
>> +	}
>> +
>> +	value ^= 0x800000;
>> +
>> +	for (i = 0; i < hx711_get_gain_to_pulse(hx711_data->gain_set); i++)
>> +		hx711_cycle(hx711_data);
>> +
>> +	return value;
>> +}
>> +
>> +static int hx711_wait_for_ready(struct hx711_data *hx711_data)
>> +{
>> +	int i, val;
>> +
>> +	/*
>> +	 * a maximum reset cycle time of 56 ms was measured.
>> +	 * we round it up to 100 ms
>> +	 */
>> +	for (i = 0; i < 100; i++) {
>> +		val = gpiod_get_value(hx711_data->gpiod_dout);
>> +		if (!val)
>> +			break;
>> +		/* sleep at least 1 ms */
>> +		msleep(1);
>> +	}
>> +	if (val)
>> +		return -EIO;
>> +
>> +	return 0;
>> +}
>> +
>> +static int hx711_reset(struct hx711_data *hx711_data)
>> +{
>> +	int ret;
>> +	int val = gpiod_get_value(hx711_data->gpiod_dout);
>> +
>> +	if (val) {
>> +		/*
>> +		 * an examination with the oszilloscope indicated
> oscilloscope
>> +		 * that the first value read after the reset is not stable
>> +		 * if we reset too short;
>> +		 * the shorter the reset cycle
>> +		 * the less reliable the first value after reset is;
>> +		 * there were no problems encountered with a value
>> +		 * of 10 ms or higher
>> +		 */
>> +		gpiod_set_value(hx711_data->gpiod_pd_sck, 1);
>> +		msleep(10);
>> +		gpiod_set_value(hx711_data->gpiod_pd_sck, 0);
>> +
>> +		ret = hx711_wait_for_ready(hx711_data);
>> +		if (ret)
>> +			return ret;
>> +		/*
>> +		 * after a reset the gain is 128 so we do a dummy read
>> +		 * to set the gain for the next read
>> +		 */
>> +		ret = hx711_read(hx711_data);
>> +		if (ret < 0)
>> +			return ret;
>> +
>> +		/*
>> +		 * after a dummy read we need to wait vor readiness
>> +		 * for not mixing gain pulses with the clock
>> +		 */
>> +		ret = hx711_wait_for_ready(hx711_data);
>> +		if (ret)
>> +			return ret;
>> +	}
>> +
>> +	return val;
>> +}
>> +
>> +static int hx711_set_gain_for_channel(struct hx711_data *hx711_data, int chan)
>> +{
>> +	int ret;
>> +
>> +	if (chan == 0) {
>> +		if (hx711_data->gain_set == 32) {
>> +			hx711_data->gain_set = hx711_data->gain_chan_a;
>> +
>> +			ret = hx711_read(hx711_data);
>> +			if (ret < 0)
>> +				return ret;
>> +
>> +			ret = hx711_wait_for_ready(hx711_data);
>> +			if (ret)
>> +				return ret;
>> +		}
>> +	} else {
>> +		if (hx711_data->gain_set != 32) {
>> +			hx711_data->gain_set = 32;
>> +
>> +			ret = hx711_read(hx711_data);
>> +			if (ret < 0)
>> +				return ret;
>> +
>> +			ret = hx711_wait_for_ready(hx711_data);
>> +			if (ret)
>> +				return ret;
>> +		}
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int hx711_read_raw(struct iio_dev *indio_dev,
>> +				const struct iio_chan_spec *chan,
>> +				int *val, int *val2, long mask)
>> +{
>> +	struct hx711_data *hx711_data = iio_priv(indio_dev);
>> +	int ret;
>> +
>> +	switch (mask) {
>> +	case IIO_CHAN_INFO_RAW:
>> +		mutex_lock(&hx711_data->lock);
>> +
>> +		/*
>> +		 * hx711_reset() must be called from here
>> +		 * because it could be calling hx711_read() by itself
>> +		 */
>> +		if (hx711_reset(hx711_data)) {
> No unlock in this error path.
>> +			dev_err(hx711_data->dev, "reset failed!");
>> +			return -EIO;
>> +		}
>> +
>> +		ret = hx711_set_gain_for_channel(hx711_data, chan->channel);
>> +		if (ret < 0) {
>> +			mutex_unlock(&hx711_data->lock);
>> +			return ret;
>> +		}
>> +
>> +		*val = hx711_read(hx711_data);
>> +
>> +		mutex_unlock(&hx711_data->lock);
>> +
>> +		if (*val < 0)
>> +			return *val;
>> +		return IIO_VAL_INT;
>> +	case IIO_CHAN_INFO_SCALE:
>> +		*val = 0;
>> +		mutex_lock(&hx711_data->lock);
>> +
> Looking feels overly paranoid here as we are only accessing locally stored
> data.  Still it's not actively doing any harm...
>> +		*val2 = hx711_get_gain_to_scale(hx711_data->gain_set);
>> +
>> +		mutex_unlock(&hx711_data->lock);
>> +
>> +		return IIO_VAL_INT_PLUS_NANO;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +}
>> +
>> +static int hx711_write_raw(struct iio_dev *indio_dev,
>> +				struct iio_chan_spec const *chan,
>> +				int val,
>> +				int val2,
>> +				long mask)
>> +{
>> +	struct hx711_data *hx711_data = iio_priv(indio_dev);
>> +	int ret;
>> +	int gain;
>> +
>> +	switch (mask) {
>> +	case IIO_CHAN_INFO_SCALE:
>> +		/*
>> +		 * a scale greater than 1 mV per LSB is not possible
>> +		 * with the HX711, therefore val must be 0
>> +		 */
>> +		if (val != 0)
>> +			return -EINVAL;
>> +
>> +		mutex_lock(&hx711_data->lock);
>> +
>> +		gain = hx711_get_scale_to_gain(val2);
>> +		if (gain < 0) {
>> +			mutex_unlock(&hx711_data->lock);
>> +			return gain;
>> +		}
>> +
>> +		if (gain != hx711_data->gain_set) {
>> +			hx711_data->gain_set = gain;
>> +			if (gain != 32)
>> +				hx711_data->gain_chan_a = gain;
>> +
>> +			ret = hx711_read(hx711_data);
>> +			if (ret < 0) {
>> +				mutex_unlock(&hx711_data->lock);
>> +				return ret;
>> +			}
>> +		}
>> +
>> +		mutex_unlock(&hx711_data->lock);
>> +		return 0;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int hx711_write_raw_get_fmt(struct iio_dev *indio_dev,
>> +		struct iio_chan_spec const *chan,
>> +		long mask)
>> +{
>> +	return IIO_VAL_INT_PLUS_NANO;
>> +}
>> +
>> +static ssize_t hx711_scale_available_show(struct device *dev,
>> +				struct device_attribute *attr,
>> +				char *buf)
>> +{
>> +	struct iio_dev_attr *iio_attr = to_iio_dev_attr(attr);
>> +	int channel = iio_attr->address;
>> +	int i, len = 0;
>> +
>> +	for (i = 0; i < HX711_GAIN_MAX; i++)
>> +		if (hx711_gain_to_scale[i].channel == channel)
>> +			len += sprintf(buf + len, "0.%09d ",
>> +					hx711_gain_to_scale[i].scale);
>> +
>> +	len += sprintf(buf + len, "\n");
>> +
>> +	return len;
>> +}
>> +
>> +static IIO_DEVICE_ATTR(in_voltage0_scale_available, S_IRUGO,
>> +	hx711_scale_available_show, NULL, 0);
>> +
>> +static IIO_DEVICE_ATTR(in_voltage1_scale_available, S_IRUGO,
>> +	hx711_scale_available_show, NULL, 1);
>> +
>> +static struct attribute *hx711_attributes[] = {
>> +	&iio_dev_attr_in_voltage0_scale_available.dev_attr.attr,
>> +	&iio_dev_attr_in_voltage1_scale_available.dev_attr.attr,
>> +	NULL,
>> +};
>> +
>> +static struct attribute_group hx711_attribute_group = {
>> +	.attrs = hx711_attributes,
>> +};
>> +
>> +static const struct iio_info hx711_iio_info = {
>> +	.driver_module		= THIS_MODULE,
>> +	.read_raw		= hx711_read_raw,
>> +	.write_raw		= hx711_write_raw,
>> +	.write_raw_get_fmt	= hx711_write_raw_get_fmt,
>> +	.attrs			= &hx711_attribute_group,
>> +};
>> +
>> +static const struct iio_chan_spec hx711_chan_spec[] = {
>> +	{
>> +		.type = IIO_VOLTAGE,
>> +		.channel = 0,
>> +		.indexed = 1,
>> +		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
>> +		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
>> +	},
>> +	{
>> +		.type = IIO_VOLTAGE,
>> +		.channel = 1,
>> +		.indexed = 1,
>> +		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
>> +		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
>> +	},
>> +};
>> +
>> +static int hx711_probe(struct platform_device *pdev)
>> +{
>> +	struct device *dev = &pdev->dev;
>> +	struct hx711_data *hx711_data;
>> +	struct iio_dev *indio_dev;
>> +	int ret;
>> +	int i;
>> +
>> +	indio_dev = devm_iio_device_alloc(dev, sizeof(struct hx711_data));
>> +	if (!indio_dev) {
>> +		dev_err(dev, "failed to allocate IIO device\n");
>> +		return -ENOMEM;
>> +	}
>> +
>> +	hx711_data = iio_priv(indio_dev);
>> +	hx711_data->dev = dev;
>> +
>> +	mutex_init(&hx711_data->lock);
>> +
>> +	/*
>> +	 * PD_SCK stands for power down and serial clock input of HX711
>> +	 * in the driver it is an output
>> +	 */
>> +	hx711_data->gpiod_pd_sck = devm_gpiod_get(dev, "sck", GPIOD_OUT_LOW);
>> +	if (IS_ERR(hx711_data->gpiod_pd_sck)) {
>> +		dev_err(dev, "failed to get sck-gpiod: err=%ld\n",
>> +					PTR_ERR(hx711_data->gpiod_pd_sck));
>> +		return PTR_ERR(hx711_data->gpiod_pd_sck);
>> +	}
>> +
>> +	/*
>> +	 * DOUT stands for serial data output of HX711
>> +	 * for the driver it is an input
>> +	 */
>> +	hx711_data->gpiod_dout = devm_gpiod_get(dev, "dout", GPIOD_IN);
>> +	if (IS_ERR(hx711_data->gpiod_dout)) {
>> +		dev_err(dev, "failed to get dout-gpiod: err=%ld\n",
>> +					PTR_ERR(hx711_data->gpiod_dout));
>> +		return PTR_ERR(hx711_data->gpiod_dout);
>> +	}
>> +
>> +	hx711_data->reg_avdd = devm_regulator_get(dev, "avdd");
>> +	if (IS_ERR(hx711_data->reg_avdd))
>> +		return PTR_ERR(hx711_data->reg_avdd);
>> +
>> +	ret = regulator_enable(hx711_data->reg_avdd);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	/*
>> +	 * with
>> +	 * full scale differential input range: AVDD / GAIN
>> +	 * full scale output data: 2^24
>> +	 * we can say:
>> +	 *     AVDD / GAIN = 2^24
>> +	 * therefore:
>> +	 *     1 LSB = AVDD / GAIN / 2^24
>> +	 * AVDD is in uV, but we need 10^-9 mV
>> +	 * approximately to fit into a 32 bit number:
>> +	 * 1 LSB = (AVDD * 100) / GAIN / 1678 [10^-9 mV]
>> +	 */
>> +	ret = regulator_get_voltage(hx711_data->reg_avdd);
>> +	if (ret < 0) {
>> +		regulator_disable(hx711_data->reg_avdd);
>> +		return ret;
>> +	}
>> +	/* we need 10^-9 mV */
>> +	ret *= 100;
>> +
>> +	for (i = 0; i < HX711_GAIN_MAX; i++)
>> +		hx711_gain_to_scale[i].scale =
>> +			ret / hx711_gain_to_scale[i].gain / 1678;
>> +
>> +	hx711_data->gain_set = 128;
>> +	hx711_data->gain_chan_a = 128;
>> +
>> +	platform_set_drvdata(pdev, indio_dev);
>> +
>> +	indio_dev->name = "hx711";
>> +	indio_dev->dev.parent = &pdev->dev;
>> +	indio_dev->info = &hx711_iio_info;
>> +	indio_dev->modes = INDIO_DIRECT_MODE;
>> +	indio_dev->channels = hx711_chan_spec;
>> +	indio_dev->num_channels = ARRAY_SIZE(hx711_chan_spec);
>> +
>> +	ret = iio_device_register(indio_dev);
>> +	if (ret < 0) {
>> +		dev_err(dev, "Couldn't register the device\n");
>> +		regulator_disable(hx711_data->reg_avdd);
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>> +static int hx711_remove(struct platform_device *pdev)
>> +{
>> +	struct hx711_data *hx711_data;
>> +	struct iio_dev *indio_dev;
>> +
>> +	indio_dev = platform_get_drvdata(pdev);
>> +	hx711_data = iio_priv(indio_dev);
>> +
>> +	iio_device_unregister(indio_dev);
>> +
>> +	regulator_disable(hx711_data->reg_avdd);
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct of_device_id of_hx711_match[] = {
>> +	{ .compatible = "avia,hx711", },
>> +	{},
>> +};
>> +
>> +MODULE_DEVICE_TABLE(of, of_hx711_match);
>> +
>> +static struct platform_driver hx711_driver = {
>> +	.probe		= hx711_probe,
>> +	.remove		= hx711_remove,
>> +	.driver		= {
>> +		.name		= "hx711-gpio",
>> +		.of_match_table	= of_hx711_match,
>> +	},
>> +};
>> +
>> +module_platform_driver(hx711_driver);
>> +
>> +MODULE_AUTHOR("Andreas Klinger <ak-n176/SwNRljddJNmlsFzeA@public.gmane.org>");
>> +MODULE_DESCRIPTION("HX711 bitbanging driver - ADC for weight cells");
>> +MODULE_LICENSE("GPL");
>> +MODULE_ALIAS("platform:hx711-gpio");
>> +
>>
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply

* Re: [PATCH 1/4] ARM: dts: imx6qdl: add HummingBoard2 boards
From: Jon Nettleton @ 2017-01-08 15:49 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Fabio Estevam, Mark Rutland, devicetree@vger.kernel.org,
	Rob Herring, Sascha Hauer, Fabio Estevam, Shawn Guo,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <20170108152050.GU14217@n2100.armlinux.org.uk>

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

On Sun, Jan 8, 2017 at 4:20 PM, Russell King - ARM Linux <
linux@armlinux.org.uk> wrote:

> On Sun, Jan 08, 2017 at 01:07:42PM -0200, Fabio Estevam wrote:
> > On Sun, Jan 8, 2017 at 1:03 PM, Russell King <rmk+kernel@armlinux.org.uk>
> wrote:
> > > From: Jon Nettleton <jon.nettleton@gmail.com>
> > >
> > > This adds support for the Hummingboard Gate and Edge devices from
> > > SolidRun.
> > >
> > > Signed-off-by: Rabeeh Khoury <rabeeh@solid-run.com>
> > > Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> >
> > This one misses a Signed-off-by tag from Jon.
>
> That depends whether Jon is the author or not... Jon needs to comment
> on that.
>
> As I said in the cover, this is rather "not ready" but is being posted
> because Lucas is forcing our hands.
>
> --
> RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
> FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
> according to speedtest.net.
>

Sorry that was my fault.  We can add

Signed-off-by: Jon Nettleton <jon@solid-run.com>

or I will resubmit it it via rmk.

[-- Attachment #2: Type: text/html, Size: 2109 bytes --]

^ permalink raw reply

* Re: [PATCH 1/4] ARM: dts: imx6qdl: add HummingBoard2 boards
From: Russell King - ARM Linux @ 2017-01-08 15:20 UTC (permalink / raw)
  To: Fabio Estevam
  Cc: Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Jon Nettleton, Rob Herring, Sascha Hauer, Fabio Estevam,
	Shawn Guo,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
In-Reply-To: <CAOMZO5AcyweJ8xgGyGKD4CVPiuxaEE+JKs=ASNUU5BcL+3fASQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On Sun, Jan 08, 2017 at 01:07:42PM -0200, Fabio Estevam wrote:
> On Sun, Jan 8, 2017 at 1:03 PM, Russell King <rmk+kernel-I+IVW8TIWO2tmTQ+vhA3Yw@public.gmane.org> wrote:
> > From: Jon Nettleton <jon.nettleton-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> >
> > This adds support for the Hummingboard Gate and Edge devices from
> > SolidRun.
> >
> > Signed-off-by: Rabeeh Khoury <rabeeh-UBr1pzP51AyaMJb+Lgu22Q@public.gmane.org>
> > Signed-off-by: Russell King <rmk+kernel-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org>
> 
> This one misses a Signed-off-by tag from Jon.

That depends whether Jon is the author or not... Jon needs to comment
on that.

As I said in the cover, this is rather "not ready" but is being posted
because Lucas is forcing our hands.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 1/4] ARM: dts: imx6qdl: add HummingBoard2 boards
From: Fabio Estevam @ 2017-01-08 15:07 UTC (permalink / raw)
  To: Russell King
  Cc: Fabio Estevam, Sascha Hauer, Shawn Guo, Jon Nettleton,
	Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Rob Herring,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
In-Reply-To: <E1cQF03-0003N1-HY-eh5Bv4kxaXIk46pC+1QYvQNdhmdF6hFW@public.gmane.org>

On Sun, Jan 8, 2017 at 1:03 PM, Russell King <rmk+kernel-I+IVW8TIWO2tmTQ+vhA3Yw@public.gmane.org> wrote:
> From: Jon Nettleton <jon.nettleton-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>
> This adds support for the Hummingboard Gate and Edge devices from
> SolidRun.
>
> Signed-off-by: Rabeeh Khoury <rabeeh-UBr1pzP51AyaMJb+Lgu22Q@public.gmane.org>
> Signed-off-by: Russell King <rmk+kernel-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org>

This one misses a Signed-off-by tag from Jon.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 4/4] ARM: dts: imx6*-hummingboard2: convert to more conventional vmmc-supply
From: Russell King - ARM Linux @ 2017-01-08 15:06 UTC (permalink / raw)
  To: Fabio Estevam, Sascha Hauer, Shawn Guo, Jon Nettleton
  Cc: Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <E1cQF0I-0003NN-S7-eh5Bv4kxaXIk46pC+1QYvQNdhmdF6hFW@public.gmane.org>

Damn it, missed the RFC annotation on these patches (very easy to do)
and this one doesn't have a description yet because it needs discussion
with Jon and testing.

On Sun, Jan 08, 2017 at 03:03:26PM +0000, Russell King wrote:
> Signed-off-by: Russell King <rmk+kernel-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org>
> ---
>  arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi | 26 +++++++++++++++++++-------
>  1 file changed, 19 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi b/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi
> index 88833d757f7b..66098a5fdd8d 100644
> --- a/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi
> +++ b/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi
> @@ -75,6 +75,18 @@
>  			regulator-always-on;
>  		};
>  
> +		reg_usdhc2_vmmc: reg-usdhc2-vmmc {
> +			compatible = "regulator-fixed";
> +			gpio = <&gpio4 30 GPIO_ACTIVE_HIGH>;
> +			pinctrl-names = "default";
> +			pinctrl-0 = <&pinctrl_hummingboard2_vmmc>;
> +			regulator-boot-on;
> +			regulator-max-microvolt = <3300000>;
> +			regulator-min-microvolt = <3300000>;
> +			regulator-name = "usdhc2_vmmc";
> +			startup-delay-us = <1000>;
> +		};
> +
>  		reg_usbh1_vbus: usb-h1-vbus {
>  			compatible = "regulator-fixed";
>  			enable-active-high;
> @@ -122,11 +134,6 @@
>  		};
>  	};
>  
> -	usdhc2_pwrseq: usdhc2_pwrseq {
> -		compatible = "mmc-pwrseq-simple";
> -		reset-gpios = <&gpio4 30 GPIO_ACTIVE_HIGH>;
> -	};
> -
>  	sound-sgtl5000 {
>  		audio-codec = <&sgtl5000>;
>  		audio-routing =
> @@ -388,7 +395,6 @@
>  
>  		pinctrl_hummingboard2_usdhc2_aux: hummingboard2-usdhc2-aux {
>  			fsl,pins = <
> -				MX6QDL_PAD_GPIO_4__GPIO1_IO04    0x1f071
>  				MX6QDL_PAD_KEY_ROW1__SD2_VSELECT 0x1b071
>  				MX6QDL_PAD_DISP0_DAT9__GPIO4_IO30 0x1b0b0
>  			>;
> @@ -427,6 +433,12 @@
>  			>;
>  		};
>  
> +		pinctrl_hummingboard2_vmmc: hummingboard2-vmmc {
> +			fsl,pins = <
> +				MX6QDL_PAD_GPIO_4__GPIO1_IO04    0x1f071
> +			>;
> +		};
> +
>  		pinctrl_hummingboard2_usdhc3: hummingboard2-usdhc3 {
>  			fsl,pins = <
>  				MX6QDL_PAD_SD3_CMD__SD3_CMD    0x17059
> @@ -526,7 +538,7 @@
>  		&pinctrl_hummingboard2_usdhc2_aux
>  		&pinctrl_hummingboard2_usdhc2_200mhz
>  	>;
> -	mmc-pwrseq = <&usdhc2_pwrseq>;
> +	vmmc-supply = <&reg_usdhc2_vmmc>;
>  	cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
>  	status = "okay";
>  };
> -- 
> 2.7.4
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH 4/4] ARM: dts: imx6*-hummingboard2: convert to more conventional vmmc-supply
From: Russell King @ 2017-01-08 15:03 UTC (permalink / raw)
  To: Fabio Estevam, Sascha Hauer, Shawn Guo, Jon Nettleton
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Rob Herring,
	Mark Rutland
In-Reply-To: <20170108150201.GS14217-l+eeeJia6m9URfEZ8mYm6t73F7V6hmMc@public.gmane.org>

Signed-off-by: Russell King <rmk+kernel-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org>
---
 arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi b/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi
index 88833d757f7b..66098a5fdd8d 100644
--- a/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi
@@ -75,6 +75,18 @@
 			regulator-always-on;
 		};
 
+		reg_usdhc2_vmmc: reg-usdhc2-vmmc {
+			compatible = "regulator-fixed";
+			gpio = <&gpio4 30 GPIO_ACTIVE_HIGH>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_hummingboard2_vmmc>;
+			regulator-boot-on;
+			regulator-max-microvolt = <3300000>;
+			regulator-min-microvolt = <3300000>;
+			regulator-name = "usdhc2_vmmc";
+			startup-delay-us = <1000>;
+		};
+
 		reg_usbh1_vbus: usb-h1-vbus {
 			compatible = "regulator-fixed";
 			enable-active-high;
@@ -122,11 +134,6 @@
 		};
 	};
 
-	usdhc2_pwrseq: usdhc2_pwrseq {
-		compatible = "mmc-pwrseq-simple";
-		reset-gpios = <&gpio4 30 GPIO_ACTIVE_HIGH>;
-	};
-
 	sound-sgtl5000 {
 		audio-codec = <&sgtl5000>;
 		audio-routing =
@@ -388,7 +395,6 @@
 
 		pinctrl_hummingboard2_usdhc2_aux: hummingboard2-usdhc2-aux {
 			fsl,pins = <
-				MX6QDL_PAD_GPIO_4__GPIO1_IO04    0x1f071
 				MX6QDL_PAD_KEY_ROW1__SD2_VSELECT 0x1b071
 				MX6QDL_PAD_DISP0_DAT9__GPIO4_IO30 0x1b0b0
 			>;
@@ -427,6 +433,12 @@
 			>;
 		};
 
+		pinctrl_hummingboard2_vmmc: hummingboard2-vmmc {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_4__GPIO1_IO04    0x1f071
+			>;
+		};
+
 		pinctrl_hummingboard2_usdhc3: hummingboard2-usdhc3 {
 			fsl,pins = <
 				MX6QDL_PAD_SD3_CMD__SD3_CMD    0x17059
@@ -526,7 +538,7 @@
 		&pinctrl_hummingboard2_usdhc2_aux
 		&pinctrl_hummingboard2_usdhc2_200mhz
 	>;
-	mmc-pwrseq = <&usdhc2_pwrseq>;
+	vmmc-supply = <&reg_usdhc2_vmmc>;
 	cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
 	status = "okay";
 };
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH 3/4] ARM: dts: imx6*-hummingboard2: use proper gpio flags definitions
From: Russell King @ 2017-01-08 15:03 UTC (permalink / raw)
  To: Fabio Estevam, Sascha Hauer, Shawn Guo, Jon Nettleton
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Rob Herring,
	Mark Rutland
In-Reply-To: <20170108150201.GS14217-l+eeeJia6m9URfEZ8mYm6t73F7V6hmMc@public.gmane.org>

Use proper gpio flag definitions for GPIOs rather than using opaque
uninformative numbers.

Signed-off-by: Russell King <rmk+kernel-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org>
---
 arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi b/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi
index a98ddcad175f..88833d757f7b 100644
--- a/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi
@@ -50,7 +50,7 @@
 
 	ir_recv: ir-receiver {
 		compatible = "gpio-ir-receiver";
-		gpios = <&gpio7 9 1>;
+		gpios = <&gpio7 9 GPIO_ACTIVE_LOW>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinctrl_hummingboard2_gpio7_9>;
 		linux,rc-map-name = "rc-rc6-mce";
@@ -78,7 +78,7 @@
 		reg_usbh1_vbus: usb-h1-vbus {
 			compatible = "regulator-fixed";
 			enable-active-high;
-			gpio = <&gpio1 0 0>;
+			gpio = <&gpio1 0 GPIO_ACTIVE_HIGH>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_hummingboard2_usbh1_vbus>;
 			regulator-name = "usb_h1_vbus";
@@ -89,7 +89,7 @@
 		reg_usbotg_vbus: usb-otg-vbus {
 			compatible = "regulator-fixed";
 			enable-active-high;
-			gpio = <&gpio3 22 0>;
+			gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_hummingboard2_usbotg_vbus>;
 			regulator-name = "usb_otg_vbus";
@@ -100,7 +100,7 @@
 		reg_usbh2_vbus: usb-h2-vbus {
 			compatible = "regulator-gpio";
 			enable-active-high;
-			enable-gpio = <&gpio2 13 0>;
+			enable-gpio = <&gpio2 13 GPIO_ACTIVE_HIGH>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_hummingboard2_usbh2_vbus>;
 			regulator-name = "usb_h2_vbus";
@@ -112,7 +112,7 @@
 		reg_usbh3_vbus: usb-h3-vbus {
 			compatible = "regulator-gpio";
 			enable-active-high;
-			enable-gpio = <&gpio7 10 0>;
+			enable-gpio = <&gpio7 10 GPIO_ACTIVE_HIGH>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_hummingboard2_usbh3_vbus>;
 			regulator-name = "usb_h3_vbus";
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH 2/4] ARM: dts: imx6*-hummingboard2: fix SD card detect
From: Russell King @ 2017-01-08 15:03 UTC (permalink / raw)
  To: Fabio Estevam, Sascha Hauer, Shawn Guo, Jon Nettleton
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Rob Herring,
	Mark Rutland
In-Reply-To: <20170108150201.GS14217-l+eeeJia6m9URfEZ8mYm6t73F7V6hmMc@public.gmane.org>

Fix the SD card detect signal, which was missing the polarity
specification, and the pull-up necessary for proper signalling.

Signed-off-by: Russell King <rmk+kernel-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org>
---
 arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi b/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi
index 4512ed4fe011..a98ddcad175f 100644
--- a/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi
@@ -388,7 +388,7 @@
 
 		pinctrl_hummingboard2_usdhc2_aux: hummingboard2-usdhc2-aux {
 			fsl,pins = <
-				MX6QDL_PAD_GPIO_4__GPIO1_IO04    0x13071
+				MX6QDL_PAD_GPIO_4__GPIO1_IO04    0x1f071
 				MX6QDL_PAD_KEY_ROW1__SD2_VSELECT 0x1b071
 				MX6QDL_PAD_DISP0_DAT9__GPIO4_IO30 0x1b0b0
 			>;
@@ -527,7 +527,7 @@
 		&pinctrl_hummingboard2_usdhc2_200mhz
 	>;
 	mmc-pwrseq = <&usdhc2_pwrseq>;
-	cd-gpios = <&gpio1 4 0>;
+	cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
 	status = "okay";
 };
 
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH 1/4] ARM: dts: imx6qdl: add HummingBoard2 boards
From: Russell King @ 2017-01-08 15:03 UTC (permalink / raw)
  To: Fabio Estevam, Sascha Hauer, Shawn Guo, Jon Nettleton
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Rob Herring,
	Mark Rutland
In-Reply-To: <20170108150201.GS14217-l+eeeJia6m9URfEZ8mYm6t73F7V6hmMc@public.gmane.org>

From: Jon Nettleton <jon.nettleton-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

This adds support for the Hummingboard Gate and Edge devices from
SolidRun.

Signed-off-by: Rabeeh Khoury <rabeeh-UBr1pzP51AyaMJb+Lgu22Q@public.gmane.org>
Signed-off-by: Russell King <rmk+kernel-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org>
---
 arch/arm/boot/dts/Makefile                   |   2 +
 arch/arm/boot/dts/imx6dl-hummingboard2.dts   |  52 +++
 arch/arm/boot/dts/imx6q-hummingboard2.dts    |  60 +++
 arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi | 550 +++++++++++++++++++++++++++
 4 files changed, 664 insertions(+)
 create mode 100644 arch/arm/boot/dts/imx6dl-hummingboard2.dts
 create mode 100644 arch/arm/boot/dts/imx6q-hummingboard2.dts
 create mode 100644 arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index c558ba75cbcc..ea53640652f9 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -340,6 +340,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
 	imx6dl-gw552x.dtb \
 	imx6dl-gw553x.dtb \
 	imx6dl-hummingboard.dtb \
+	imx6dl-hummingboard2.dtb \
 	imx6dl-nit6xlite.dtb \
 	imx6dl-nitrogen6x.dtb \
 	imx6dl-phytec-pbab01.dtb \
@@ -381,6 +382,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
 	imx6q-gw553x.dtb \
 	imx6q-h100.dtb \
 	imx6q-hummingboard.dtb \
+	imx6q-hummingboard2.dtb \
 	imx6q-icore-rqs.dtb \
 	imx6q-marsboard.dtb \
 	imx6q-nitrogen6x.dtb \
diff --git a/arch/arm/boot/dts/imx6dl-hummingboard2.dts b/arch/arm/boot/dts/imx6dl-hummingboard2.dts
new file mode 100644
index 000000000000..990b5050de5b
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-hummingboard2.dts
@@ -0,0 +1,52 @@
+/*
+ * Device Tree file for SolidRun HummingBoard2
+ * Copyright (C) 2015 Rabeeh Khoury <rabeeh-UBr1pzP51AyaMJb+Lgu22Q@public.gmane.org>
+ * Based on work by Russell King
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+/dts-v1/;
+
+#include "imx6dl.dtsi"
+#include "imx6qdl-hummingboard2.dtsi"
+
+/ {
+	model = "SolidRun HummingBoard2 Solo/DualLite";
+	compatible = "solidrun,hummingboard2/dl", "fsl,imx6dl";
+};
diff --git a/arch/arm/boot/dts/imx6q-hummingboard2.dts b/arch/arm/boot/dts/imx6q-hummingboard2.dts
new file mode 100644
index 000000000000..f5eec9163bb8
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-hummingboard2.dts
@@ -0,0 +1,60 @@
+/*
+ * Device Tree file for SolidRun HummingBoard2
+ * Copyright (C) 2015 Rabeeh Khoury <rabeeh-UBr1pzP51AyaMJb+Lgu22Q@public.gmane.org>
+ * Based on work by Russell King
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+/dts-v1/;
+
+#include "imx6q.dtsi"
+#include "imx6qdl-hummingboard2.dtsi"
+
+/ {
+	model = "SolidRun HummingBoard2 Dual/Quad";
+	compatible = "solidrun,hummingboard2/q", "fsl,imx6q";
+};
+
+&sata {
+	status = "okay";
+	fsl,transmit-level-mV = <1104>;
+	fsl,transmit-boost-mdB = <0>;
+	fsl,transmit-atten-16ths = <9>;
+	fsl,no-spread-spectrum;
+};
diff --git a/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi b/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi
new file mode 100644
index 000000000000..4512ed4fe011
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi
@@ -0,0 +1,550 @@
+/*
+ * Device Tree file for SolidRun HummingBoard2
+ * Copyright (C) 2015 Rabeeh Khoury <rabeeh-UBr1pzP51AyaMJb+Lgu22Q@public.gmane.org>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "imx6qdl-microsom.dtsi"
+#include "imx6qdl-microsom-ar8035.dtsi"
+
+/ {
+	chosen {
+		stdout-path = &uart1;
+	};
+
+	ir_recv: ir-receiver {
+		compatible = "gpio-ir-receiver";
+		gpios = <&gpio7 9 1>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_hummingboard2_gpio7_9>;
+		linux,rc-map-name = "rc-rc6-mce";
+	};
+
+	regulators {
+		compatible = "simple-bus";
+
+		reg_3p3v: 3p3v {
+			compatible = "regulator-fixed";
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		reg_1p8v: 1p8v {
+			compatible = "regulator-fixed";
+			regulator-name = "1P8V";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			regulator-always-on;
+		};
+
+		reg_usbh1_vbus: usb-h1-vbus {
+			compatible = "regulator-fixed";
+			enable-active-high;
+			gpio = <&gpio1 0 0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_hummingboard2_usbh1_vbus>;
+			regulator-name = "usb_h1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+		};
+
+		reg_usbotg_vbus: usb-otg-vbus {
+			compatible = "regulator-fixed";
+			enable-active-high;
+			gpio = <&gpio3 22 0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_hummingboard2_usbotg_vbus>;
+			regulator-name = "usb_otg_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+		};
+
+		reg_usbh2_vbus: usb-h2-vbus {
+			compatible = "regulator-gpio";
+			enable-active-high;
+			enable-gpio = <&gpio2 13 0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_hummingboard2_usbh2_vbus>;
+			regulator-name = "usb_h2_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-boot-on;
+		};
+
+		reg_usbh3_vbus: usb-h3-vbus {
+			compatible = "regulator-gpio";
+			enable-active-high;
+			enable-gpio = <&gpio7 10 0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_hummingboard2_usbh3_vbus>;
+			regulator-name = "usb_h3_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-boot-on;
+		};
+	};
+
+	usdhc2_pwrseq: usdhc2_pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&gpio4 30 GPIO_ACTIVE_HIGH>;
+	};
+
+	sound-sgtl5000 {
+		audio-codec = <&sgtl5000>;
+		audio-routing =
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"Headphone Jack", "HP_OUT";
+		compatible = "fsl,imx-audio-sgtl5000";
+		model = "On-board Codec";
+		mux-ext-port = <5>;
+		mux-int-port = <1>;
+		ssi-controller = <&ssi1>;
+	};
+};
+
+&audmux {
+	status = "okay";
+};
+
+&ecspi2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hummingboard2_ecspi2>;
+	fsl,spi-num-chipselects = <1>;
+	cs-gpios = <&gpio2 26 0>;
+	status = "okay";
+};
+
+&hdmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hummingboard2_hdmi>;
+	ddc-i2c-bus = <&i2c2>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hummingboard2_i2c1>;
+	status = "okay";
+
+	rtc: pcf8523@68 {
+		compatible = "nxp,pcf8523";
+		reg = <0x68>;
+		nxp,12p5_pf;
+	};
+
+	sgtl5000: sgtl5000@0a {
+		clocks = <&clks IMX6QDL_CLK_CKO>;
+		compatible = "fsl,sgtl5000";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_hummingboard2_sgtl5000>;
+		reg = <0x0a>;
+		VDDA-supply = <&reg_3p3v>;
+		VDDIO-supply = <&reg_3p3v>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hummingboard2_i2c2>;
+	status = "okay";
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hummingboard2_i2c3>;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+	hummingboard2 {
+		pinctrl_hog: hoggrp {
+		fsl,pins = <
+				/*
+				 * 36 pin headers GPIO description. The pins
+				 * numbering as following -
+				 *
+				 * 	3.2v	5v	74	75
+				 *	73	72	71	70
+				 *	69	68	67	66
+				 *
+				 *	77	78	79	76
+				 *	65	64	61	60
+				 *	53	52	51	50
+				 *	49	48	166	132
+				 *	95	94	90	91
+				 *	GND	54	24	204
+				 *
+				 * The GPIO numbers can be extracted using
+				 * signal name from below.
+				 * Example -
+				 * MX6QDL_PAD_EIM_DA10__GPIO3_IO10 is
+				 * GPIO(3,10) which is (3-1)*32+10 = gpio 74
+				 *
+				 * i.e. The mapping of GPIO(X,Y) to Linux gpio
+				 * number is : gpio number = (X-1) * 32 + Y
+				 */
+				/* DI1_PIN15 */
+				MX6QDL_PAD_EIM_DA10__GPIO3_IO10 0x400130b1
+				/* DI1_PIN02 */
+				MX6QDL_PAD_EIM_DA11__GPIO3_IO11 0x400130b1
+				/* DISP1_DATA00 */
+				MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x400130b1
+				/* DISP1_DATA01 */
+				MX6QDL_PAD_EIM_DA8__GPIO3_IO08 0x400130b1
+				/* DISP1_DATA02 */
+				MX6QDL_PAD_EIM_DA7__GPIO3_IO07 0x400130b1
+				/* DISP1_DATA03 */
+				MX6QDL_PAD_EIM_DA6__GPIO3_IO06 0x400130b1
+				/* DISP1_DATA04 */
+				MX6QDL_PAD_EIM_DA5__GPIO3_IO05 0x400130b1
+				/* DISP1_DATA05 */
+				MX6QDL_PAD_EIM_DA4__GPIO3_IO04 0x400130b1
+				/* DISP1_DATA06 */
+				MX6QDL_PAD_EIM_DA3__GPIO3_IO03 0x400130b1
+				/* DISP1_DATA07 */
+				MX6QDL_PAD_EIM_DA2__GPIO3_IO02 0x400130b1
+				/* DI1_D0_CS */
+				MX6QDL_PAD_EIM_DA13__GPIO3_IO13 0x400130b1
+				/* DI1_D1_CS */
+				MX6QDL_PAD_EIM_DA14__GPIO3_IO14 0x400130b1
+				/* DI1_PIN01 */
+				MX6QDL_PAD_EIM_DA15__GPIO3_IO15 0x400130b1
+				/* DI1_PIN03 */
+				MX6QDL_PAD_EIM_DA12__GPIO3_IO12 0x400130b1
+				/* DISP1_DATA08 */
+				MX6QDL_PAD_EIM_DA1__GPIO3_IO01 0x400130b1
+				/* DISP1_DATA09 */
+				MX6QDL_PAD_EIM_DA0__GPIO3_IO00 0x400130b1
+				/* DISP1_DATA10 */
+				MX6QDL_PAD_EIM_EB1__GPIO2_IO29 0x400130b1
+				/* DISP1_DATA11 */
+				MX6QDL_PAD_EIM_EB0__GPIO2_IO28 0x400130b1
+				/* DISP1_DATA12 */
+				MX6QDL_PAD_EIM_A17__GPIO2_IO21 0x400130b1
+				/* DISP1_DATA13 */
+				MX6QDL_PAD_EIM_A18__GPIO2_IO20 0x400130b1
+				/* DISP1_DATA14 */
+				MX6QDL_PAD_EIM_A19__GPIO2_IO19 0x400130b1
+				/* DISP1_DATA15 */
+				MX6QDL_PAD_EIM_A20__GPIO2_IO18 0x400130b1
+				/* DISP1_DATA16 */
+				MX6QDL_PAD_EIM_A21__GPIO2_IO17 0x400130b1
+				/* DISP1_DATA17 */
+				MX6QDL_PAD_EIM_A22__GPIO2_IO16 0x400130b1
+				/* DISP1_DATA18 */
+				MX6QDL_PAD_EIM_A23__GPIO6_IO06 0x400130b1
+				/* DISP1_DATA19 */
+				MX6QDL_PAD_EIM_A24__GPIO5_IO04 0x400130b1
+				/* DISP1_DATA20 */
+				MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x400130b1
+				/* DISP1_DATA21 */
+				MX6QDL_PAD_EIM_D30__GPIO3_IO30 0x400130b1
+				/* DISP1_DATA22 */
+				MX6QDL_PAD_EIM_D26__GPIO3_IO26 0x400130b1
+				/* DISP1_DATA23 */
+				MX6QDL_PAD_EIM_D27__GPIO3_IO27 0x400130b1
+				/* DI1_DISP_CLK */
+				MX6QDL_PAD_EIM_A16__GPIO2_IO22 0x400130b1
+				/* SPDIF_IN */
+				MX6QDL_PAD_ENET_RX_ER__GPIO1_IO24 0x400130b1
+				/* SPDIF_OUT */
+				MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x400130b1
+
+				/* MikroBUS GPIO pin number 10 */
+				MX6QDL_PAD_EIM_LBA__GPIO2_IO27 0x400130b1
+			>;
+		};
+
+		pinctrl_hummingboard2_gpio7_9: hummingboard2-gpio7_9 {
+			fsl,pins = <
+				MX6QDL_PAD_SD4_CMD__GPIO7_IO09 0x80000000
+			>;
+		};
+
+		pinctrl_hummingboard2_hdmi: hummingboard2-hdmi {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
+			>;
+		};
+
+		pinctrl_hummingboard2_i2c1: hummingboard2-i2c1 {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
+				MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
+			>;
+		};
+
+		pinctrl_hummingboard2_i2c2: hummingboard2-i2c2 {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+				MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+			>;
+		};
+
+		pinctrl_hummingboard2_i2c3: hummingboard2-i2c3 {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
+				MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
+			>;
+		};
+
+                pinctrl_hummingboard2_mipi: hummingboard2_mipi {
+                        fsl,pins = <
+                                MX6QDL_PAD_SD4_DAT2__GPIO2_IO10 0x4001b8b1
+                                MX6QDL_PAD_KEY_COL4__GPIO4_IO14 0x4001b8b1
+                                MX6QDL_PAD_NANDF_CS2__CCM_CLKO2 0x130b0
+                        >;
+                };
+
+		pinctrl_hummingboard2_pcie_reset: hummingboard2-pcie-reset {
+			fsl,pins = <
+				MX6QDL_PAD_SD4_DAT3__GPIO2_IO11 0x1b0b1
+			>;
+		};
+
+		pinctrl_hummingboard2_pwm1: pwm1grp {
+			fsl,pins = <
+				MX6QDL_PAD_DISP0_DAT8__PWM1_OUT 0x1b0b1
+			>;
+		};
+
+		pinctrl_hummingboard2_sgtl5000: hummingboard2-sgtl5000 {
+			fsl,pins = <
+				MX6QDL_PAD_DISP0_DAT19__AUD5_RXD 0x130b0
+				MX6QDL_PAD_KEY_COL0__AUD5_TXC 0x130b0
+				MX6QDL_PAD_KEY_ROW0__AUD5_TXD 0x110b0
+				MX6QDL_PAD_KEY_COL1__AUD5_TXFS 0x130b0
+				MX6QDL_PAD_GPIO_5__CCM_CLKO1 0x130b0
+			>;
+		};
+
+		pinctrl_hummingboard2_usbh1_vbus: hummingboard2-usbh1-vbus {
+			fsl,pins = <MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x1b0b0>;
+		};
+
+		pinctrl_hummingboard2_usbh2_vbus: hummingboard2-usbh2-vbus {
+			fsl,pins = <MX6QDL_PAD_SD4_DAT5__GPIO2_IO13 0x1b0b0>;
+		};
+
+		pinctrl_hummingboard2_usbh3_vbus: hummingboard2-usbh3-vbus {
+			fsl,pins = <MX6QDL_PAD_SD4_CLK__GPIO7_IO10 0x1b0b0>;
+		};
+
+		pinctrl_hummingboard2_usbotg_id: hummingboard2-usbotg-id {
+			/*
+			 * Similar to pinctrl_usbotg_2, but we want it
+			 * pulled down for a fixed host connection.
+			 */
+			fsl,pins = <MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059>;
+		};
+
+		pinctrl_hummingboard2_usbotg_vbus: hummingboard2-usbotg-vbus {
+			fsl,pins = <MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b0>;
+		};
+
+		pinctrl_hummingboard2_usdhc2_aux: hummingboard2-usdhc2-aux {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_4__GPIO1_IO04    0x13071
+				MX6QDL_PAD_KEY_ROW1__SD2_VSELECT 0x1b071
+				MX6QDL_PAD_DISP0_DAT9__GPIO4_IO30 0x1b0b0
+			>;
+		};
+
+		pinctrl_hummingboard2_usdhc2: hummingboard2-usdhc2 {
+			fsl,pins = <
+				MX6QDL_PAD_SD2_CMD__SD2_CMD    0x17059
+				MX6QDL_PAD_SD2_CLK__SD2_CLK    0x10059
+				MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+				MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+				MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+				MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x13059
+			>;
+		};
+
+		pinctrl_hummingboard2_usdhc2_100mhz: hummingboard2-usdhc2-100mhz {
+			fsl,pins = <
+				MX6QDL_PAD_SD2_CMD__SD2_CMD    0x170b9
+				MX6QDL_PAD_SD2_CLK__SD2_CLK    0x100b9
+				MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170b9
+				MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170b9
+				MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170b9
+				MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x130b9
+			>;
+		};
+
+		pinctrl_hummingboard2_usdhc2_200mhz: hummingboard2-usdhc2-200mhz {
+			fsl,pins = <
+				MX6QDL_PAD_SD2_CMD__SD2_CMD    0x170f9
+				MX6QDL_PAD_SD2_CLK__SD2_CLK    0x100f9
+				MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170f9
+				MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170f9
+				MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170f9
+				MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x130f9
+			>;
+		};
+
+		pinctrl_hummingboard2_usdhc3: hummingboard2-usdhc3 {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_CMD__SD3_CMD    0x17059
+				MX6QDL_PAD_SD3_CLK__SD3_CLK    0x10059
+				MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+				MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+				MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+				MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+				MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059
+				MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059
+				MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059
+				MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059
+				MX6QDL_PAD_SD3_RST__SD3_RESET  0x17059
+			>;
+		};
+
+		pinctrl_hummingboard2_uart3: hummingboard2-uart3 {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D25__UART3_TX_DATA	0x1b0b1
+				MX6QDL_PAD_EIM_D24__UART3_RX_DATA	0x40013000
+			>;
+		};
+
+		pinctrl_hummingboard2_ecspi2: hummingboard2-ecspi2grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_OE__ECSPI2_MISO	0x100b1
+				MX6QDL_PAD_EIM_CS1__ECSPI2_MOSI	0x100b1
+				MX6QDL_PAD_EIM_CS0__ECSPI2_SCLK	0x100b1
+				MX6QDL_PAD_EIM_RW__GPIO2_IO26	0x000b1 /* CS */
+			>;
+		};
+	};
+};
+
+&ldb {
+	status = "disabled";
+
+	lvds-channel@0 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+	};
+};
+
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <
+		&pinctrl_hummingboard2_pcie_reset
+	>;
+	reset-gpio = <&gpio2 11 0>;
+	status = "okay";
+};
+
+&pwm1 {
+        pinctrl-names = "default";
+        pinctrl-0 = <&pinctrl_hummingboard2_pwm1>;
+        status = "okay";
+};
+
+&pwm3 {
+	status = "disabled";
+};
+
+&pwm4 {
+	status = "disabled";
+};
+
+&ssi1 {
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
+
+&usbh1 {
+	disable-over-current;
+	vbus-supply = <&reg_usbh1_vbus>;
+	status = "okay";
+};
+
+&usbotg {
+	disable-over-current;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hummingboard2_usbotg_id>;
+	vbus-supply = <&reg_usbotg_vbus>;
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <
+		&pinctrl_hummingboard2_usdhc2_aux
+		&pinctrl_hummingboard2_usdhc2
+	>;
+	pinctrl-1 = <
+		&pinctrl_hummingboard2_usdhc2_aux
+		&pinctrl_hummingboard2_usdhc2_100mhz
+	>;
+	pinctrl-2 = <
+		&pinctrl_hummingboard2_usdhc2_aux
+		&pinctrl_hummingboard2_usdhc2_200mhz
+	>;
+	mmc-pwrseq = <&usdhc2_pwrseq>;
+	cd-gpios = <&gpio1 4 0>;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <
+		&pinctrl_hummingboard2_usdhc3
+	>;
+	vmmc-supply = <&reg_3p3v>;
+	vqmmc-supply = <&reg_3p3v>;
+	bus-width = <8>;
+	non-removable;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hummingboard2_uart3>;
+	status = "okay";
+};
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH RFC 0/4] SolidRun Hummingboard 2 support
From: Russell King - ARM Linux @ 2017-01-08 15:02 UTC (permalink / raw)
  To: Fabio Estevam, Sascha Hauer, Shawn Guo, Jon Nettleton
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Mark Rutland,
	Rob Herring

These patches add support for SolidRun's Hummingboard 2 to mainline.
The first is the official SolidRun DTS file supplied by Jon, the
remainder are cleanups to it for mainline.

These can be found in my HB2 branch.

 arch/arm/boot/dts/Makefile                   |   2 +
 arch/arm/boot/dts/imx6dl-hummingboard2.dts   |  52 +++
 arch/arm/boot/dts/imx6q-hummingboard2.dts    |  60 +++
 arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi | 562 +++++++++++++++++++++++++++
 4 files changed, 676 insertions(+)
 create mode 100644 arch/arm/boot/dts/imx6dl-hummingboard2.dts
 create mode 100644 arch/arm/boot/dts/imx6q-hummingboard2.dts
 create mode 100644 arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH 4/4] MAINTAINERS: Extend ARM/Mediatek SoC support section
From: Andreas Färber @ 2017-01-08 13:31 UTC (permalink / raw)
  To: linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Matthias Brugger, Paul Lai,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Andreas Färber
In-Reply-To: <20170108133100.10428-1-afaerber-l3A5Bk7waGM@public.gmane.org>

Catch mt7623 and arm64 dts subdirectory.

Cc: Matthias Brugger <matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Andreas Färber <afaerber-l3A5Bk7waGM@public.gmane.org>
---
 MAINTAINERS | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 93a983a..7f5a629 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1522,8 +1522,10 @@ L:	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org (moderated for non-subscribers)
 L:	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org (moderated for non-subscribers)
 S:	Maintained
 F:	arch/arm/boot/dts/mt6*
+F:	arch/arm/boot/dts/mt7*
 F:	arch/arm/boot/dts/mt8*
 F:	arch/arm/mach-mediatek/
+F:	arch/arm64/boot/dts/mediatek/
 N:	mtk
 K:	mediatek
 
-- 
2.10.2

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH 3/4] ARM: dts: mt7623: Add Geek Force config
From: Andreas Färber @ 2017-01-08 13:30 UTC (permalink / raw)
  To: linux-mediatek
  Cc: Mark Rutland, devicetree, Paul Lai, linux-kernel, Russell King,
	Rob Herring, Matthias Brugger, Andreas Färber,
	linux-arm-kernel
In-Reply-To: <20170108133100.10428-1-afaerber@suse.de>

Signed-off-by: Andreas Färber <afaerber@suse.de>
---
 arch/arm/boot/dts/Makefile             |  1 +
 arch/arm/boot/dts/mt7623-geekforce.dts | 77 ++++++++++++++++++++++++++++++++++
 2 files changed, 78 insertions(+)
 create mode 100644 arch/arm/boot/dts/mt7623-geekforce.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index fa68843..fc1d4be 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -987,6 +987,7 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \
 	mt6589-aquaris5.dtb \
 	mt6592-evb.dtb \
 	mt7623-evb.dtb \
+	mt7623-geekforce.dtb \
 	mt8127-moose.dtb \
 	mt8135-evbp1.dtb
 dtb-$(CONFIG_ARCH_ZX) += zx296702-ad1.dtb
diff --git a/arch/arm/boot/dts/mt7623-geekforce.dts b/arch/arm/boot/dts/mt7623-geekforce.dts
new file mode 100644
index 0000000..ab4cecd
--- /dev/null
+++ b/arch/arm/boot/dts/mt7623-geekforce.dts
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016-2017 Andreas Färber
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "mt7623.dtsi"
+
+/ {
+	model = "AsiaRF Geek Force";
+	compatible = "asiarf,geekforce", "mediatek,mt7623";
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+	};
+
+	chosen {
+		stdout-path = "serial2:115200n8";
+	};
+
+	memory {
+		reg = <0 0x80000000 0 0x40000000>;
+	};
+};
+
+/* on Raspberry Pi connector */
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
-- 
2.10.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH 2/4] Documentation: devicetree: arm: mediatek: Add Geek Force board
From: Andreas Färber @ 2017-01-08 13:30 UTC (permalink / raw)
  To: linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Matthias Brugger, Paul Lai,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Andreas Färber,
	Rob Herring, Mark Rutland
In-Reply-To: <20170108133100.10428-1-afaerber-l3A5Bk7waGM@public.gmane.org>

Signed-off-by: Andreas Färber <afaerber-l3A5Bk7waGM@public.gmane.org>
---
 Documentation/devicetree/bindings/arm/mediatek.txt | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/mediatek.txt b/Documentation/devicetree/bindings/arm/mediatek.txt
index c860b24..f533758 100644
--- a/Documentation/devicetree/bindings/arm/mediatek.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek.txt
@@ -41,6 +41,9 @@ Supported boards:
 - Evaluation board for MT7623:
     Required root node properties:
       - compatible = "mediatek,mt7623-evb", "mediatek,mt7623";
+- AsiaRF Geek Force board:
+    Required root node properties:
+      - compatible = "asiarf,geekforce", "mediatek,mt7623";
 - MTK mt8127 tablet moose EVB:
     Required root node properties:
       - compatible = "mediatek,mt8127-moose", "mediatek,mt8127";
-- 
2.10.2

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH 1/4] Documentation: devicetree: Add vendor prefix for AsiaRF
From: Andreas Färber @ 2017-01-08 13:30 UTC (permalink / raw)
  To: linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Matthias Brugger, Paul Lai,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Andreas Färber,
	Rob Herring, Mark Rutland
In-Reply-To: <20170108133100.10428-1-afaerber-l3A5Bk7waGM@public.gmane.org>

Signed-off-by: Andreas Färber <afaerber-l3A5Bk7waGM@public.gmane.org>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 4ec84b7..01d222b 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -34,6 +34,7 @@ armadeus	ARMadeus Systems SARL
 arrow	Arrow Electronics
 artesyn	Artesyn Embedded Technologies Inc.
 asahi-kasei	Asahi Kasei Corp.
+asiarf	AsiaRF Co., Ltd.
 aspeed	ASPEED Technology Inc.
 atlas	Atlas Scientific LLC
 atmel	Atmel Corporation
-- 
2.10.2

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH 0/4] ARM: dts: mt7623: Add initial Geek Force support
From: Andreas Färber @ 2017-01-08 13:30 UTC (permalink / raw)
  To: linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Matthias Brugger, Paul Lai,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Andreas Färber


Andreas Färber (4):
  Documentation: devicetree: Add vendor prefix for AsiaRF
  Documentation: devicetree: arm: mediatek: Add Geek Force board
  ARM: dts: mt7623: Add Geek Force config
  MAINTAINERS: Extend ARM/Mediatek SoC support section

 Documentation/devicetree/bindings/arm/mediatek.txt |  3 +
 .../devicetree/bindings/vendor-prefixes.txt        |  1 +
 MAINTAINERS                                        |  2 +
 arch/arm/boot/dts/Makefile                         |  1 +
 arch/arm/boot/dts/mt7623-geekforce.dts             | 77 ++++++++++++++++++++++
 5 files changed, 84 insertions(+)
 create mode 100644 arch/arm/boot/dts/mt7623-geekforce.dts

-- 
2.10.2

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v7 6/8] IIO: add STM32 timer trigger driver
From: Jonathan Cameron @ 2017-01-08 11:30 UTC (permalink / raw)
  To: Benjamin Gaignard, lee.jones, robh+dt, mark.rutland,
	alexandre.torgue, devicetree, linux-kernel, thierry.reding,
	linux-pwm, knaack.h, lars, pmeerw, linux-iio, linux-arm-kernel
  Cc: fabrice.gasnier, gerald.baeza, arnaud.pouliquen, linus.walleij,
	linaro-kernel, Benjamin Gaignard
In-Reply-To: <1483608344-9012-7-git-send-email-benjamin.gaignard@st.com>

On 05/01/17 09:25, Benjamin Gaignard wrote:
> Timers IPs can be used to generate triggers for other IPs like
> DAC or ADC.
> Each trigger may result of timer internals signals like counter enable,
> reset or edge, this configuration could be done through "master_mode"
> device attribute.
> 
> Since triggers could be used by DAC or ADC their names are defined
> in include/ nux/iio/timer/stm32-timer-trigger.h and is_stm32_iio_timer_trigger
> function could be used to check if the trigger is valid or not.
> 
> "trgo" trigger have a "sampling_frequency" attribute which allow to configure
> timer sampling frequency.
> 
> version 7:
> - remove all iio_device related code
> - move driver into trigger directory
> 
> version 5:
> - simplify tables of triggers
> - only create an IIO device when needed
> 
> version 4:
> - get triggers configuration from "reg" in DT
> - add tables of triggers
> - sampling frequency is enable/disable when writing in trigger
>   sampling_frequency attribute
> - no more use of interruptions
> 
> version 3:
> - change compatible to "st,stm32-timer-trigger"
> - fix attributes access right
> - use string instead of int for master_mode and slave_mode
> - document device attributes in sysfs-bus-iio-timer-stm32
> 
> version 2:
> - keep only one compatible
> - use st,input-triggers-names and st,output-triggers-names
>   to know which triggers are accepted and/or create by the device
> 
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
One line snuck in that shouldn't be there (the one in iio/Kconfig).
Other than that

Acked-by: Jonathan Cameron <jic23@kernel.org>

I didn't get a chance to look at doing trigger trees unfortunately.
Not sure when I'll next get a window to work on new stuff.

Thanks,

Jonathan

> ---
>  .../ABI/testing/sysfs-bus-iio-timer-stm32          |  29 ++
>  drivers/iio/Kconfig                                |   1 -
>  drivers/iio/trigger/Kconfig                        |  10 +
>  drivers/iio/trigger/Makefile                       |   1 +
>  drivers/iio/trigger/stm32-timer-trigger.c          | 340 +++++++++++++++++++++
>  include/linux/iio/timer/stm32-timer-trigger.h      |  62 ++++
>  6 files changed, 442 insertions(+), 1 deletion(-)
>  create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-timer-stm32
>  create mode 100644 drivers/iio/trigger/stm32-timer-trigger.c
>  create mode 100644 include/linux/iio/timer/stm32-timer-trigger.h
> 
> diff --git a/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 b/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32
> new file mode 100644
> index 0000000..a7f5177
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32
> @@ -0,0 +1,29 @@
> +What:		/sys/bus/iio/devices/triggerX/master_mode_available
> +KernelVersion:	4.10
> +Contact:	benjamin.gaignard@st.com
> +Description:
> +		Reading returns the list possible master modes which are:
> +		- "reset"     :	The UG bit from the TIMx_EGR register is used as trigger output (TRGO).
> +		- "enable"    : The Counter Enable signal CNT_EN is used as trigger output.
> +		- "update"    : The update event is selected as trigger output.
> +				For instance a master timer can then be used as a prescaler for a slave timer.
> +		- "compare_pulse" : The trigger output send a positive pulse when the CC1IF flag is to be set.
> +		- "OC1REF"    : OC1REF signal is used as trigger output.
> +		- "OC2REF"    : OC2REF signal is used as trigger output.
> +		- "OC3REF"    : OC3REF signal is used as trigger output.
> +		- "OC4REF"    : OC4REF signal is used as trigger output.
> +
> +What:		/sys/bus/iio/devices/triggerX/master_mode
> +KernelVersion:	4.10
> +Contact:	benjamin.gaignard@st.com
> +Description:
> +		Reading returns the current master modes.
> +		Writing set the master mode
> +
> +What:		/sys/bus/iio/devices/triggerX/sampling_frequency
> +KernelVersion:	4.10
> +Contact:	benjamin.gaignard@st.com
> +Description:
> +		Reading returns the current sampling frequency.
> +		Writing an value different of 0 set and start sampling.
> +		Writing 0 stop sampling.
> diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
> index a918270..6b0c427 100644
> --- a/drivers/iio/Kconfig
> +++ b/drivers/iio/Kconfig
> @@ -92,5 +92,4 @@ source "drivers/iio/potentiostat/Kconfig"
>  source "drivers/iio/pressure/Kconfig"
>  source "drivers/iio/proximity/Kconfig"
>  source "drivers/iio/temperature/Kconfig"
> -
Please fix this!!
>  endif # IIO
> diff --git a/drivers/iio/trigger/Kconfig b/drivers/iio/trigger/Kconfig
> index 809b2e7..72d3a32 100644
> --- a/drivers/iio/trigger/Kconfig
> +++ b/drivers/iio/trigger/Kconfig
> @@ -24,6 +24,16 @@ config IIO_INTERRUPT_TRIGGER
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called iio-trig-interrupt.
>  
> +config IIO_STM32_TIMER_TRIGGER
> +	tristate "STM32 Timer Trigger"
> +	depends on (ARCH_STM32 && OF && MFD_STM32_TIMERS) || COMPILE_TEST
> +	help
> +	  Select this option to enable STM32 Timer Trigger
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called stm32-timer-trigger.
> +
> +
>  config IIO_TIGHTLOOP_TRIGGER
>  	tristate "A kthread based hammering loop trigger"
>  	depends on IIO_SW_TRIGGER
> diff --git a/drivers/iio/trigger/Makefile b/drivers/iio/trigger/Makefile
> index aab4dc2..5c4ecd3 100644
> --- a/drivers/iio/trigger/Makefile
> +++ b/drivers/iio/trigger/Makefile
> @@ -6,5 +6,6 @@
>  
>  obj-$(CONFIG_IIO_HRTIMER_TRIGGER) += iio-trig-hrtimer.o
>  obj-$(CONFIG_IIO_INTERRUPT_TRIGGER) += iio-trig-interrupt.o
> +obj-$(CONFIG_IIO_STM32_TIMER_TRIGGER) += stm32-timer-trigger.o
>  obj-$(CONFIG_IIO_SYSFS_TRIGGER) += iio-trig-sysfs.o
>  obj-$(CONFIG_IIO_TIGHTLOOP_TRIGGER) += iio-trig-loop.o
> diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c
> new file mode 100644
> index 0000000..409fb0c
> --- /dev/null
> +++ b/drivers/iio/trigger/stm32-timer-trigger.c
> @@ -0,0 +1,340 @@
> +/*
> + * Copyright (C) STMicroelectronics 2016
> + *
> + * Author: Benjamin Gaignard <benjamin.gaignard@st.com>
> + *
> + * License terms:  GNU General Public License (GPL), version 2
> + */
> +
> +#include <linux/iio/iio.h>
> +#include <linux/iio/sysfs.h>
> +#include <linux/iio/timer/stm32-timer-trigger.h>
> +#include <linux/iio/trigger.h>
> +#include <linux/mfd/stm32-timers.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +
> +#define MAX_TRIGGERS 6
> +
> +/* List the triggers created by each timer */
> +static const void *triggers_table[][MAX_TRIGGERS] = {
> +	{ TIM1_TRGO, TIM1_CH1, TIM1_CH2, TIM1_CH3, TIM1_CH4,},
> +	{ TIM2_TRGO, TIM2_CH1, TIM2_CH2, TIM2_CH3, TIM2_CH4,},
> +	{ TIM3_TRGO, TIM3_CH1, TIM3_CH2, TIM3_CH3, TIM3_CH4,},
> +	{ TIM4_TRGO, TIM4_CH1, TIM4_CH2, TIM4_CH3, TIM4_CH4,},
> +	{ TIM5_TRGO, TIM5_CH1, TIM5_CH2, TIM5_CH3, TIM5_CH4,},
> +	{ TIM6_TRGO,},
> +	{ TIM7_TRGO,},
> +	{ TIM8_TRGO, TIM8_CH1, TIM8_CH2, TIM8_CH3, TIM8_CH4,},
> +	{ TIM9_TRGO, TIM9_CH1, TIM9_CH2,},
> +	{ TIM12_TRGO, TIM12_CH1, TIM12_CH2,},
> +};
> +
> +struct stm32_timer_trigger {
> +	struct device *dev;
> +	struct regmap *regmap;
> +	struct clk *clk;
> +	u32 max_arr;
> +	const void *triggers;
> +};
> +
> +static int stm32_timer_start(struct stm32_timer_trigger *priv,
> +			     unsigned int frequency)
> +{
> +	unsigned long long prd, div;
> +	int prescaler = 0;
> +	u32 ccer, cr1;
> +
> +	/* Period and prescaler values depends of clock rate */
> +	div = (unsigned long long)clk_get_rate(priv->clk);
> +
> +	do_div(div, frequency);
> +
> +	prd = div;
> +
> +	/*
> +	 * Increase prescaler value until we get a result that fit
> +	 * with auto reload register maximum value.
> +	 */
> +	while (div > priv->max_arr) {
> +		prescaler++;
> +		div = prd;
> +		do_div(div, (prescaler + 1));
> +	}
> +	prd = div;
> +
> +	if (prescaler > MAX_TIM_PSC) {
> +		dev_err(priv->dev, "prescaler exceeds the maximum value\n");
> +		return -EINVAL;
> +	}
> +
> +	/* Check if nobody else use the timer */
> +	regmap_read(priv->regmap, TIM_CCER, &ccer);
> +	if (ccer & TIM_CCER_CCXE)
> +		return -EBUSY;
> +
> +	regmap_read(priv->regmap, TIM_CR1, &cr1);
> +	if (!(cr1 & TIM_CR1_CEN))
> +		clk_enable(priv->clk);
> +
> +	regmap_write(priv->regmap, TIM_PSC, prescaler);
> +	regmap_write(priv->regmap, TIM_ARR, prd - 1);
> +	regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, TIM_CR1_ARPE);
> +
> +	/* Force master mode to update mode */
> +	regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS, 0x20);
> +
> +	/* Make sure that registers are updated */
> +	regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG);
> +
> +	/* Enable controller */
> +	regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, TIM_CR1_CEN);
> +
> +	return 0;
> +}
> +
> +static void stm32_timer_stop(struct stm32_timer_trigger *priv)
> +{
> +	u32 ccer, cr1;
> +
> +	regmap_read(priv->regmap, TIM_CCER, &ccer);
> +	if (ccer & TIM_CCER_CCXE)
> +		return;
> +
> +	regmap_read(priv->regmap, TIM_CR1, &cr1);
> +	if (cr1 & TIM_CR1_CEN)
> +		clk_disable(priv->clk);
> +
> +	/* Stop timer */
> +	regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0);
> +	regmap_write(priv->regmap, TIM_PSC, 0);
> +	regmap_write(priv->regmap, TIM_ARR, 0);
> +
> +	/* Make sure that registers are updated */
> +	regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG);
> +}
> +
> +static ssize_t stm32_tt_store_frequency(struct device *dev,
> +					struct device_attribute *attr,
> +					const char *buf, size_t len)
> +{
> +	struct iio_trigger *trig = to_iio_trigger(dev);
> +	struct stm32_timer_trigger *priv = iio_trigger_get_drvdata(trig);
> +	unsigned int freq;
> +	int ret;
> +
> +	ret = kstrtouint(buf, 10, &freq);
> +	if (ret)
> +		return ret;
> +
> +	if (freq == 0) {
> +		stm32_timer_stop(priv);
> +	} else {
> +		ret = stm32_timer_start(priv, freq);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return len;
> +}
> +
> +static ssize_t stm32_tt_read_frequency(struct device *dev,
> +				       struct device_attribute *attr, char *buf)
> +{
> +	struct iio_trigger *trig = to_iio_trigger(dev);
> +	struct stm32_timer_trigger *priv = iio_trigger_get_drvdata(trig);
> +	u32 psc, arr, cr1;
> +	unsigned long long freq = 0;
> +
> +	regmap_read(priv->regmap, TIM_CR1, &cr1);
> +	regmap_read(priv->regmap, TIM_PSC, &psc);
> +	regmap_read(priv->regmap, TIM_ARR, &arr);
> +
> +	if (psc && arr && (cr1 & TIM_CR1_CEN)) {
> +		freq = (unsigned long long)clk_get_rate(priv->clk);
> +		do_div(freq, psc);
> +		do_div(freq, arr);
> +	}
> +
> +	return sprintf(buf, "%d\n", (unsigned int)freq);
> +}
> +
> +static IIO_DEV_ATTR_SAMP_FREQ(0660,
> +			      stm32_tt_read_frequency,
> +			      stm32_tt_store_frequency);
> +
> +static char *master_mode_table[] = {
> +	"reset",
> +	"enable",
> +	"update",
> +	"compare_pulse",
> +	"OC1REF",
> +	"OC2REF",
> +	"OC3REF",
> +	"OC4REF"
> +};
> +
> +static ssize_t stm32_tt_show_master_mode(struct device *dev,
> +					 struct device_attribute *attr,
> +					 char *buf)
> +{
> +	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> +	struct stm32_timer_trigger *priv = iio_priv(indio_dev);
> +	u32 cr2;
> +
> +	regmap_read(priv->regmap, TIM_CR2, &cr2);
> +	cr2 = (cr2 & TIM_CR2_MMS) >> TIM_CR2_MMS_SHIFT;
> +
> +	return snprintf(buf, PAGE_SIZE, "%s\n", master_mode_table[cr2]);
> +}
> +
> +static ssize_t stm32_tt_store_master_mode(struct device *dev,
> +					  struct device_attribute *attr,
> +					  const char *buf, size_t len)
> +{
> +	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> +	struct stm32_timer_trigger *priv = iio_priv(indio_dev);
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(master_mode_table); i++) {
> +		if (!strncmp(master_mode_table[i], buf,
> +			     strlen(master_mode_table[i]))) {
> +			regmap_update_bits(priv->regmap, TIM_CR2,
> +					   TIM_CR2_MMS, i << TIM_CR2_MMS_SHIFT);
> +			/* Make sure that registers are updated */
> +			regmap_update_bits(priv->regmap, TIM_EGR,
> +					   TIM_EGR_UG, TIM_EGR_UG);
> +			return len;
> +		}
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static IIO_CONST_ATTR(master_mode_available,
> +	"reset enable update compare_pulse OC1REF OC2REF OC3REF OC4REF");
> +
> +static IIO_DEVICE_ATTR(master_mode, 0660,
> +		       stm32_tt_show_master_mode,
> +		       stm32_tt_store_master_mode,
> +		       0);
> +
> +static struct attribute *stm32_trigger_attrs[] = {
> +	&iio_dev_attr_sampling_frequency.dev_attr.attr,
> +	&iio_dev_attr_master_mode.dev_attr.attr,
> +	&iio_const_attr_master_mode_available.dev_attr.attr,
> +	NULL,
> +};
> +
> +static const struct attribute_group stm32_trigger_attr_group = {
> +	.attrs = stm32_trigger_attrs,
> +};
> +
> +static const struct attribute_group *stm32_trigger_attr_groups[] = {
> +	&stm32_trigger_attr_group,
> +	NULL,
> +};
> +
> +static const struct iio_trigger_ops timer_trigger_ops = {
> +	.owner = THIS_MODULE,
> +};
> +
> +static int stm32_setup_iio_triggers(struct stm32_timer_trigger *priv)
> +{
> +	int ret;
> +	const char * const *cur = priv->triggers;
> +
> +	while (cur && *cur) {
> +		struct iio_trigger *trig;
> +
> +		trig = devm_iio_trigger_alloc(priv->dev, "%s", *cur);
> +		if  (!trig)
> +			return -ENOMEM;
> +
> +		trig->dev.parent = priv->dev->parent;
> +		trig->ops = &timer_trigger_ops;
> +
> +		/*
> +		 * sampling frequency and master mode attributes
> +		 * should only be available on trgo trigger which
> +		 * is always the first in the list.
> +		 */
> +		if (cur == priv->triggers)
> +			trig->dev.groups = stm32_trigger_attr_groups;
> +
> +		iio_trigger_set_drvdata(trig, priv);
> +
> +		ret = devm_iio_trigger_register(priv->dev, trig);
> +		if (ret)
> +			return ret;
> +		cur++;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * is_stm32_timer_trigger
> + * @trig: trigger to be checked
> + *
> + * return true if the trigger is a valid stm32 iio timer trigger
> + * either return false
> + */
> +bool is_stm32_timer_trigger(struct iio_trigger *trig)
> +{
> +	return (trig->ops == &timer_trigger_ops);
> +}
> +EXPORT_SYMBOL(is_stm32_timer_trigger);
> +
> +static int stm32_timer_trigger_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct stm32_timer_trigger *priv;
> +	struct stm32_timers *ddata = dev_get_drvdata(pdev->dev.parent);
> +	unsigned int index;
> +	int ret;
> +
> +	if (of_property_read_u32(dev->of_node, "reg", &index))
> +		return -EINVAL;
> +
> +	if (index >= ARRAY_SIZE(triggers_table))
> +		return -EINVAL;
> +
> +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	priv->dev = dev;
> +	priv->regmap = ddata->regmap;
> +	priv->clk = ddata->clk;
> +	priv->max_arr = ddata->max_arr;
> +	priv->triggers = triggers_table[index];
> +
> +	ret = stm32_setup_iio_triggers(priv);
> +	if (ret)
> +		return ret;
> +
> +	platform_set_drvdata(pdev, priv);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id stm32_trig_of_match[] = {
> +	{ .compatible = "st,stm32-timer-trigger", },
> +	{ /* end node */ },
> +};
> +MODULE_DEVICE_TABLE(of, stm32_trig_of_match);
> +
> +static struct platform_driver stm32_timer_trigger_driver = {
> +	.probe = stm32_timer_trigger_probe,
> +	.driver = {
> +		.name = "stm32-timer-trigger",
> +		.of_match_table = stm32_trig_of_match,
> +	},
> +};
> +module_platform_driver(stm32_timer_trigger_driver);
> +
> +MODULE_ALIAS("platform: stm32-timer-trigger");
> +MODULE_DESCRIPTION("STMicroelectronics STM32 Timer Trigger driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/iio/timer/stm32-timer-trigger.h b/include/linux/iio/timer/stm32-timer-trigger.h
> new file mode 100644
> index 0000000..55535ae
> --- /dev/null
> +++ b/include/linux/iio/timer/stm32-timer-trigger.h
> @@ -0,0 +1,62 @@
> +/*
> + * Copyright (C) STMicroelectronics 2016
> + *
> + * Author: Benjamin Gaignard <benjamin.gaignard@st.com>
> + *
> + * License terms:  GNU General Public License (GPL), version 2
> + */
> +
> +#ifndef _STM32_TIMER_TRIGGER_H_
> +#define _STM32_TIMER_TRIGGER_H_
> +
> +#define TIM1_TRGO	"tim1_trgo"
> +#define TIM1_CH1	"tim1_ch1"
> +#define TIM1_CH2	"tim1_ch2"
> +#define TIM1_CH3	"tim1_ch3"
> +#define TIM1_CH4	"tim1_ch4"
> +
> +#define TIM2_TRGO	"tim2_trgo"
> +#define TIM2_CH1	"tim2_ch1"
> +#define TIM2_CH2	"tim2_ch2"
> +#define TIM2_CH3	"tim2_ch3"
> +#define TIM2_CH4	"tim2_ch4"
> +
> +#define TIM3_TRGO	"tim3_trgo"
> +#define TIM3_CH1	"tim3_ch1"
> +#define TIM3_CH2	"tim3_ch2"
> +#define TIM3_CH3	"tim3_ch3"
> +#define TIM3_CH4	"tim3_ch4"
> +
> +#define TIM4_TRGO	"tim4_trgo"
> +#define TIM4_CH1	"tim4_ch1"
> +#define TIM4_CH2	"tim4_ch2"
> +#define TIM4_CH3	"tim4_ch3"
> +#define TIM4_CH4	"tim4_ch4"
> +
> +#define TIM5_TRGO	"tim5_trgo"
> +#define TIM5_CH1	"tim5_ch1"
> +#define TIM5_CH2	"tim5_ch2"
> +#define TIM5_CH3	"tim5_ch3"
> +#define TIM5_CH4	"tim5_ch4"
> +
> +#define TIM6_TRGO	"tim6_trgo"
> +
> +#define TIM7_TRGO	"tim7_trgo"
> +
> +#define TIM8_TRGO	"tim8_trgo"
> +#define TIM8_CH1	"tim8_ch1"
> +#define TIM8_CH2	"tim8_ch2"
> +#define TIM8_CH3	"tim8_ch3"
> +#define TIM8_CH4	"tim8_ch4"
> +
> +#define TIM9_TRGO	"tim9_trgo"
> +#define TIM9_CH1	"tim9_ch1"
> +#define TIM9_CH2	"tim9_ch2"
> +
> +#define TIM12_TRGO	"tim12_trgo"
> +#define TIM12_CH1	"tim12_ch1"
> +#define TIM12_CH2	"tim12_ch2"
> +
> +bool is_stm32_timer_trigger(struct iio_trigger *trig);
> +
> +#endif
> 

^ permalink raw reply

* Re: [PATCH v7 5/8] IIO: add bindings for STM32 timer trigger driver
From: Jonathan Cameron @ 2017-01-08 11:23 UTC (permalink / raw)
  To: Benjamin Gaignard, lee.jones, robh+dt, mark.rutland,
	alexandre.torgue, devicetree, linux-kernel, thierry.reding,
	linux-pwm, knaack.h, lars, pmeerw, linux-iio, linux-arm-kernel
  Cc: fabrice.gasnier, gerald.baeza, arnaud.pouliquen, linus.walleij,
	linaro-kernel, Benjamin Gaignard
In-Reply-To: <1483608344-9012-6-git-send-email-benjamin.gaignard@st.com>

On 05/01/17 09:25, Benjamin Gaignard wrote:
> Define bindings for STM32 timer trigger
> 
> version 4:
> - remove triggers enumeration from DT
> - add reg parameter
> 
> version 3:
> - change file name
> - add cross reference with mfd bindings
> 
> version 2:
> - only keep one compatible
> - add DT parameters to set lists of the triggers:
>   one list describe the triggers created by the device
>   another one give the triggers accepted by the device
> 
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Acked-by: Jonathan Cameron <jic23@kernel.org>
> ---
>  .../bindings/iio/timer/stm32-timer-trigger.txt     | 23 ++++++++++++++++++++++
>  1 file changed, 23 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/iio/timer/stm32-timer-trigger.txt
> 
> diff --git a/Documentation/devicetree/bindings/iio/timer/stm32-timer-trigger.txt b/Documentation/devicetree/bindings/iio/timer/stm32-timer-trigger.txt
> new file mode 100644
> index 0000000..36a6c4a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/timer/stm32-timer-trigger.txt
> @@ -0,0 +1,23 @@
> +STMicroelectronics STM32 Timers IIO timer bindings
> +
> +Must be a sub-node of an STM32 Timers device tree node.
> +See ../mfd/stm32-timers.txt for details about the parent node.
> +
> +Required parameters:
> +- compatible:	Must be "st,stm32-timer-trigger".
> +- reg:		Define triggers configuration of the hardware IP.
> +
> +Example:
> +	timers@40010000 {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		compatible = "st,stm32-timers";
> +		reg = <0x40010000 0x400>;
> +		clocks = <&rcc 0 160>;
> +		clock-names = "clk_int";
> +
> +		timer {
> +			compatible = "st,stm32-timer-trigger";
> +			reg = <0>;
> +		};
> +	};
> 

^ permalink raw reply

* Re: [PATCH v5 2/2] iio: adc: hx711: Add IIO driver for AVIA HX711
From: Jonathan Cameron @ 2017-01-08 11:12 UTC (permalink / raw)
  To: Andreas Klinger, devicetree, linux-iio
  Cc: linux-kernel, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, knaack.h, lars, pmeerw
In-Reply-To: <20170105175156.GA12221@andreas>

On 05/01/17 17:51, Andreas Klinger wrote:
> This is the IIO driver for AVIA HX711 ADC which is mostly used in weighting
> cells.
> 
> The protocol is quite simple and using GPIOs:
> One GPIO is used as clock (SCK) while another GPIO is read (DOUT)
> 
> The raw value read from the chip is delivered. 
> To get a weight one needs to subtract the zero offset and scale it.
> 
> Signed-off-by: Andreas Klinger <ak@it-klinger.de>
I think your locking is a little heavy handed, perhaps a follow up patch to
relax it a little.

I fixed a trivial typo when applying.

Applied to the togreg branch of iio.git and pushed out as testing for the
autobuilders to play with it.

Thanks,

Jonathan
> ---
>  drivers/iio/adc/Kconfig  |  19 ++
>  drivers/iio/adc/Makefile |   1 +
>  drivers/iio/adc/hx711.c  | 531 +++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 551 insertions(+)
>  create mode 100644 drivers/iio/adc/hx711.c
> 
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 932de1f9d1e7..1dcf2ace1697 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -205,6 +205,25 @@ config HI8435
>  	  This driver can also be built as a module. If so, the module will be
>  	  called hi8435.
>  
> +config HX711
> +	tristate "AVIA HX711 ADC for weight cells"
> +	depends on GPIOLIB
> +	help
> +	  If you say yes here you get support for AVIA HX711 ADC which is used
> +	  for weigh cells
> +
> +	  This driver uses two GPIOs, one acts as the clock and controls the
> +	  channel selection and gain, the other one is used for the measurement
> +          data
> +
> +	  Currently the raw value is read from the chip and delivered.
> +	  To get an actual weight one needs to subtract the
> +	  zero offset and multiply by a scale factor.
> +	  This should be done in userspace.
> +
> +	  This driver can also be built as a module. If so, the module will be
> +	  called hx711.
> +
>  config INA2XX_ADC
>  	tristate "Texas Instruments INA2xx Power Monitors IIO driver"
>  	depends on I2C && !SENSORS_INA2XX
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index b1aa456e6af3..d46e289900ef 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -21,6 +21,7 @@ obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o
>  obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o
>  obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
>  obj-$(CONFIG_HI8435) += hi8435.o
> +obj-$(CONFIG_HX711) += hx711.o
>  obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o
>  obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o
>  obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
> diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
> new file mode 100644
> index 000000000000..e41414556158
> --- /dev/null
> +++ b/drivers/iio/adc/hx711.c
> @@ -0,0 +1,531 @@
> +/*
> + * HX711: analog to digital converter for weight sensor module
> + *
> + * Copyright (c) 2016 Andreas Klinger <ak@it-klinger.de>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +#include <linux/err.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/property.h>
> +#include <linux/slab.h>
> +#include <linux/sched.h>
> +#include <linux/delay.h>
> +#include <linux/iio/iio.h>
> +#include <linux/iio/sysfs.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/regulator/consumer.h>
> +
> +/* gain to pulse and scale conversion */
> +#define HX711_GAIN_MAX		3
> +
> +struct hx711_gain_to_scale {
> +	int			gain;
> +	int			gain_pulse;
> +	int			scale;
> +	int			channel;
> +};
> +
> +/*
> + * .scale depends on AVDD which in turn is known as soon as the regulator
> + * is available
> + * therefore we set .scale in hx711_probe()
> + *
> + * channel A in documentation is channel 0 in source code
> + * channel B in documentation is channel 1 in source code
> + */
> +static struct hx711_gain_to_scale hx711_gain_to_scale[HX711_GAIN_MAX] = {
> +	{ 128, 1, 0, 0 },
> +	{  32, 2, 0, 1 },
> +	{  64, 3, 0, 0 }
> +};
> +
> +static int hx711_get_gain_to_pulse(int gain)
> +{
> +	int i;
> +
> +	for (i = 0; i < HX711_GAIN_MAX; i++)
> +		if (hx711_gain_to_scale[i].gain == gain)
> +			return hx711_gain_to_scale[i].gain_pulse;
> +	return 1;
> +}
> +
> +static int hx711_get_gain_to_scale(int gain)
> +{
> +	int i;
> +
> +	for (i = 0; i < HX711_GAIN_MAX; i++)
> +		if (hx711_gain_to_scale[i].gain == gain)
> +			return hx711_gain_to_scale[i].scale;
> +	return 0;
> +}
> +
> +static int hx711_get_scale_to_gain(int scale)
> +{
> +	int i;
> +
> +	for (i = 0; i < HX711_GAIN_MAX; i++)
> +		if (hx711_gain_to_scale[i].scale == scale)
> +			return hx711_gain_to_scale[i].gain;
> +	return -EINVAL;
> +}
> +
> +struct hx711_data {
> +	struct device		*dev;
> +	struct gpio_desc	*gpiod_pd_sck;
> +	struct gpio_desc	*gpiod_dout;
> +	struct regulator	*reg_avdd;
> +	int			gain_set;	/* gain set on device */
> +	int			gain_chan_a;	/* gain for channel A */
> +	struct mutex		lock;
> +};
> +
> +static int hx711_cycle(struct hx711_data *hx711_data)
> +{
> +	int val;
> +
> +	/*
> +	 * if preempted for more then 60us while PD_SCK is high:
> +	 * hx711 is going in reset
> +	 * ==> measuring is false
> +	 */
> +	preempt_disable();
> +	gpiod_set_value(hx711_data->gpiod_pd_sck, 1);
> +	val = gpiod_get_value(hx711_data->gpiod_dout);
> +	/*
> +	 * here we are not waiting for 0.2 us as suggested by the datasheet,
> +	 * because the oszilloscope showed in a test scenario
> +	 * at least 1.15 us for PD_SCK high (T3 in datasheet)
> +	 * and 0.56 us for PD_SCK low on TI Sitara with 800 MHz
> +	 */
> +	gpiod_set_value(hx711_data->gpiod_pd_sck, 0);
> +	preempt_enable();
> +
> +	return val;
> +}
> +
> +static int hx711_read(struct hx711_data *hx711_data)
> +{
> +	int i, ret;
> +	int value = 0;
> +	int val = gpiod_get_value(hx711_data->gpiod_dout);
> +
> +	/* we double check if it's really down */
> +	if (val)
> +		return -EIO;
> +
> +	for (i = 0; i < 24; i++) {
> +		value <<= 1;
> +		ret = hx711_cycle(hx711_data);
> +		if (ret)
> +			value++;
> +	}
> +
> +	value ^= 0x800000;
> +
> +	for (i = 0; i < hx711_get_gain_to_pulse(hx711_data->gain_set); i++)
> +		hx711_cycle(hx711_data);
> +
> +	return value;
> +}
> +
> +static int hx711_wait_for_ready(struct hx711_data *hx711_data)
> +{
> +	int i, val;
> +
> +	/*
> +	 * a maximum reset cycle time of 56 ms was measured.
> +	 * we round it up to 100 ms
> +	 */
> +	for (i = 0; i < 100; i++) {
> +		val = gpiod_get_value(hx711_data->gpiod_dout);
> +		if (!val)
> +			break;
> +		/* sleep at least 1 ms */
> +		msleep(1);
> +	}
> +	if (val)
> +		return -EIO;
> +
> +	return 0;
> +}
> +
> +static int hx711_reset(struct hx711_data *hx711_data)
> +{
> +	int ret;
> +	int val = gpiod_get_value(hx711_data->gpiod_dout);
> +
> +	if (val) {
> +		/*
> +		 * an examination with the oszilloscope indicated
oscilloscope
> +		 * that the first value read after the reset is not stable
> +		 * if we reset too short;
> +		 * the shorter the reset cycle
> +		 * the less reliable the first value after reset is;
> +		 * there were no problems encountered with a value
> +		 * of 10 ms or higher
> +		 */
> +		gpiod_set_value(hx711_data->gpiod_pd_sck, 1);
> +		msleep(10);
> +		gpiod_set_value(hx711_data->gpiod_pd_sck, 0);
> +
> +		ret = hx711_wait_for_ready(hx711_data);
> +		if (ret)
> +			return ret;
> +		/*
> +		 * after a reset the gain is 128 so we do a dummy read
> +		 * to set the gain for the next read
> +		 */
> +		ret = hx711_read(hx711_data);
> +		if (ret < 0)
> +			return ret;
> +
> +		/*
> +		 * after a dummy read we need to wait vor readiness
> +		 * for not mixing gain pulses with the clock
> +		 */
> +		ret = hx711_wait_for_ready(hx711_data);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return val;
> +}
> +
> +static int hx711_set_gain_for_channel(struct hx711_data *hx711_data, int chan)
> +{
> +	int ret;
> +
> +	if (chan == 0) {
> +		if (hx711_data->gain_set == 32) {
> +			hx711_data->gain_set = hx711_data->gain_chan_a;
> +
> +			ret = hx711_read(hx711_data);
> +			if (ret < 0)
> +				return ret;
> +
> +			ret = hx711_wait_for_ready(hx711_data);
> +			if (ret)
> +				return ret;
> +		}
> +	} else {
> +		if (hx711_data->gain_set != 32) {
> +			hx711_data->gain_set = 32;
> +
> +			ret = hx711_read(hx711_data);
> +			if (ret < 0)
> +				return ret;
> +
> +			ret = hx711_wait_for_ready(hx711_data);
> +			if (ret)
> +				return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int hx711_read_raw(struct iio_dev *indio_dev,
> +				const struct iio_chan_spec *chan,
> +				int *val, int *val2, long mask)
> +{
> +	struct hx711_data *hx711_data = iio_priv(indio_dev);
> +	int ret;
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +		mutex_lock(&hx711_data->lock);
> +
> +		/*
> +		 * hx711_reset() must be called from here
> +		 * because it could be calling hx711_read() by itself
> +		 */
> +		if (hx711_reset(hx711_data)) {
No unlock in this error path.
> +			dev_err(hx711_data->dev, "reset failed!");
> +			return -EIO;
> +		}
> +
> +		ret = hx711_set_gain_for_channel(hx711_data, chan->channel);
> +		if (ret < 0) {
> +			mutex_unlock(&hx711_data->lock);
> +			return ret;
> +		}
> +
> +		*val = hx711_read(hx711_data);
> +
> +		mutex_unlock(&hx711_data->lock);
> +
> +		if (*val < 0)
> +			return *val;
> +		return IIO_VAL_INT;
> +	case IIO_CHAN_INFO_SCALE:
> +		*val = 0;
> +		mutex_lock(&hx711_data->lock);
> +
Looking feels overly paranoid here as we are only accessing locally stored
data.  Still it's not actively doing any harm...
> +		*val2 = hx711_get_gain_to_scale(hx711_data->gain_set);
> +
> +		mutex_unlock(&hx711_data->lock);
> +
> +		return IIO_VAL_INT_PLUS_NANO;
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +
> +static int hx711_write_raw(struct iio_dev *indio_dev,
> +				struct iio_chan_spec const *chan,
> +				int val,
> +				int val2,
> +				long mask)
> +{
> +	struct hx711_data *hx711_data = iio_priv(indio_dev);
> +	int ret;
> +	int gain;
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_SCALE:
> +		/*
> +		 * a scale greater than 1 mV per LSB is not possible
> +		 * with the HX711, therefore val must be 0
> +		 */
> +		if (val != 0)
> +			return -EINVAL;
> +
> +		mutex_lock(&hx711_data->lock);
> +
> +		gain = hx711_get_scale_to_gain(val2);
> +		if (gain < 0) {
> +			mutex_unlock(&hx711_data->lock);
> +			return gain;
> +		}
> +
> +		if (gain != hx711_data->gain_set) {
> +			hx711_data->gain_set = gain;
> +			if (gain != 32)
> +				hx711_data->gain_chan_a = gain;
> +
> +			ret = hx711_read(hx711_data);
> +			if (ret < 0) {
> +				mutex_unlock(&hx711_data->lock);
> +				return ret;
> +			}
> +		}
> +
> +		mutex_unlock(&hx711_data->lock);
> +		return 0;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int hx711_write_raw_get_fmt(struct iio_dev *indio_dev,
> +		struct iio_chan_spec const *chan,
> +		long mask)
> +{
> +	return IIO_VAL_INT_PLUS_NANO;
> +}
> +
> +static ssize_t hx711_scale_available_show(struct device *dev,
> +				struct device_attribute *attr,
> +				char *buf)
> +{
> +	struct iio_dev_attr *iio_attr = to_iio_dev_attr(attr);
> +	int channel = iio_attr->address;
> +	int i, len = 0;
> +
> +	for (i = 0; i < HX711_GAIN_MAX; i++)
> +		if (hx711_gain_to_scale[i].channel == channel)
> +			len += sprintf(buf + len, "0.%09d ",
> +					hx711_gain_to_scale[i].scale);
> +
> +	len += sprintf(buf + len, "\n");
> +
> +	return len;
> +}
> +
> +static IIO_DEVICE_ATTR(in_voltage0_scale_available, S_IRUGO,
> +	hx711_scale_available_show, NULL, 0);
> +
> +static IIO_DEVICE_ATTR(in_voltage1_scale_available, S_IRUGO,
> +	hx711_scale_available_show, NULL, 1);
> +
> +static struct attribute *hx711_attributes[] = {
> +	&iio_dev_attr_in_voltage0_scale_available.dev_attr.attr,
> +	&iio_dev_attr_in_voltage1_scale_available.dev_attr.attr,
> +	NULL,
> +};
> +
> +static struct attribute_group hx711_attribute_group = {
> +	.attrs = hx711_attributes,
> +};
> +
> +static const struct iio_info hx711_iio_info = {
> +	.driver_module		= THIS_MODULE,
> +	.read_raw		= hx711_read_raw,
> +	.write_raw		= hx711_write_raw,
> +	.write_raw_get_fmt	= hx711_write_raw_get_fmt,
> +	.attrs			= &hx711_attribute_group,
> +};
> +
> +static const struct iio_chan_spec hx711_chan_spec[] = {
> +	{
> +		.type = IIO_VOLTAGE,
> +		.channel = 0,
> +		.indexed = 1,
> +		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> +		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
> +	},
> +	{
> +		.type = IIO_VOLTAGE,
> +		.channel = 1,
> +		.indexed = 1,
> +		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> +		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
> +	},
> +};
> +
> +static int hx711_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct hx711_data *hx711_data;
> +	struct iio_dev *indio_dev;
> +	int ret;
> +	int i;
> +
> +	indio_dev = devm_iio_device_alloc(dev, sizeof(struct hx711_data));
> +	if (!indio_dev) {
> +		dev_err(dev, "failed to allocate IIO device\n");
> +		return -ENOMEM;
> +	}
> +
> +	hx711_data = iio_priv(indio_dev);
> +	hx711_data->dev = dev;
> +
> +	mutex_init(&hx711_data->lock);
> +
> +	/*
> +	 * PD_SCK stands for power down and serial clock input of HX711
> +	 * in the driver it is an output
> +	 */
> +	hx711_data->gpiod_pd_sck = devm_gpiod_get(dev, "sck", GPIOD_OUT_LOW);
> +	if (IS_ERR(hx711_data->gpiod_pd_sck)) {
> +		dev_err(dev, "failed to get sck-gpiod: err=%ld\n",
> +					PTR_ERR(hx711_data->gpiod_pd_sck));
> +		return PTR_ERR(hx711_data->gpiod_pd_sck);
> +	}
> +
> +	/*
> +	 * DOUT stands for serial data output of HX711
> +	 * for the driver it is an input
> +	 */
> +	hx711_data->gpiod_dout = devm_gpiod_get(dev, "dout", GPIOD_IN);
> +	if (IS_ERR(hx711_data->gpiod_dout)) {
> +		dev_err(dev, "failed to get dout-gpiod: err=%ld\n",
> +					PTR_ERR(hx711_data->gpiod_dout));
> +		return PTR_ERR(hx711_data->gpiod_dout);
> +	}
> +
> +	hx711_data->reg_avdd = devm_regulator_get(dev, "avdd");
> +	if (IS_ERR(hx711_data->reg_avdd))
> +		return PTR_ERR(hx711_data->reg_avdd);
> +
> +	ret = regulator_enable(hx711_data->reg_avdd);
> +	if (ret < 0)
> +		return ret;
> +
> +	/*
> +	 * with
> +	 * full scale differential input range: AVDD / GAIN
> +	 * full scale output data: 2^24
> +	 * we can say:
> +	 *     AVDD / GAIN = 2^24
> +	 * therefore:
> +	 *     1 LSB = AVDD / GAIN / 2^24
> +	 * AVDD is in uV, but we need 10^-9 mV
> +	 * approximately to fit into a 32 bit number:
> +	 * 1 LSB = (AVDD * 100) / GAIN / 1678 [10^-9 mV]
> +	 */
> +	ret = regulator_get_voltage(hx711_data->reg_avdd);
> +	if (ret < 0) {
> +		regulator_disable(hx711_data->reg_avdd);
> +		return ret;
> +	}
> +	/* we need 10^-9 mV */
> +	ret *= 100;
> +
> +	for (i = 0; i < HX711_GAIN_MAX; i++)
> +		hx711_gain_to_scale[i].scale =
> +			ret / hx711_gain_to_scale[i].gain / 1678;
> +
> +	hx711_data->gain_set = 128;
> +	hx711_data->gain_chan_a = 128;
> +
> +	platform_set_drvdata(pdev, indio_dev);
> +
> +	indio_dev->name = "hx711";
> +	indio_dev->dev.parent = &pdev->dev;
> +	indio_dev->info = &hx711_iio_info;
> +	indio_dev->modes = INDIO_DIRECT_MODE;
> +	indio_dev->channels = hx711_chan_spec;
> +	indio_dev->num_channels = ARRAY_SIZE(hx711_chan_spec);
> +
> +	ret = iio_device_register(indio_dev);
> +	if (ret < 0) {
> +		dev_err(dev, "Couldn't register the device\n");
> +		regulator_disable(hx711_data->reg_avdd);
> +	}
> +
> +	return ret;
> +}
> +
> +static int hx711_remove(struct platform_device *pdev)
> +{
> +	struct hx711_data *hx711_data;
> +	struct iio_dev *indio_dev;
> +
> +	indio_dev = platform_get_drvdata(pdev);
> +	hx711_data = iio_priv(indio_dev);
> +
> +	iio_device_unregister(indio_dev);
> +
> +	regulator_disable(hx711_data->reg_avdd);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id of_hx711_match[] = {
> +	{ .compatible = "avia,hx711", },
> +	{},
> +};
> +
> +MODULE_DEVICE_TABLE(of, of_hx711_match);
> +
> +static struct platform_driver hx711_driver = {
> +	.probe		= hx711_probe,
> +	.remove		= hx711_remove,
> +	.driver		= {
> +		.name		= "hx711-gpio",
> +		.of_match_table	= of_hx711_match,
> +	},
> +};
> +
> +module_platform_driver(hx711_driver);
> +
> +MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>");
> +MODULE_DESCRIPTION("HX711 bitbanging driver - ADC for weight cells");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:hx711-gpio");
> +
> 

^ permalink raw reply

* Re: [PATCH v5 1/2] iio: adc: hx711: Add DT binding for avia,hx711
From: Jonathan Cameron @ 2017-01-08 11:10 UTC (permalink / raw)
  To: Andreas Klinger, devicetree, linux-iio
  Cc: linux-kernel, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, knaack.h, lars, pmeerw
In-Reply-To: <20170105175136.GA12210@andreas>

On 05/01/17 17:51, Andreas Klinger wrote:
> Add DT bindings for avia,hx711
> Add vendor avia to vendor list
> 
> Signed-off-by: Andreas Klinger <ak@it-klinger.de>
> Acked-by: Rob Herring <robh@kernel.org>
Applied to the togreg branch of iio.git - initially pushed out as testing.

Thanks,

Jonathan
> ---
> [PATCH v3 1/2] of this patch was Acked-by: Rob Herring <robh@kernel.org>
> In v4 the regulator (avdd-supply) was added
> 
>  .../devicetree/bindings/iio/adc/avia-hx711.txt         | 18 ++++++++++++++++++
>  Documentation/devicetree/bindings/vendor-prefixes.txt  |  1 +
>  2 files changed, 19 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/iio/adc/avia-hx711.txt
> 
> diff --git a/Documentation/devicetree/bindings/iio/adc/avia-hx711.txt b/Documentation/devicetree/bindings/iio/adc/avia-hx711.txt
> new file mode 100644
> index 000000000000..b3629405f568
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/adc/avia-hx711.txt
> @@ -0,0 +1,18 @@
> +* AVIA HX711 ADC chip for weight cells
> +  Bit-banging driver
> +
> +Required properties:
> + - compatible:	Should be "avia,hx711"
> + - sck-gpios:	Definition of the GPIO for the clock
> + - dout-gpios:	Definition of the GPIO for data-out
> +		See Documentation/devicetree/bindings/gpio/gpio.txt
> + - avdd-supply:	Definition of the regulator used as analog supply
> +
> +Example:
> +weight@0 {
> +	compatible = "avia,hx711";
> +	sck-gpios = <&gpio3 10 GPIO_ACTIVE_HIGH>;
> +	dout-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
> +	avdd-suppy = <&avdd>;
> +};
> +
> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
> index 44ddc980b085..4696bb5c2198 100644
> --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
> +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
> @@ -32,6 +32,7 @@ atlas	Atlas Scientific LLC
>  atmel	Atmel Corporation
>  auo	AU Optronics Corporation
>  avago	Avago Technologies
> +avia	avia semiconductor
>  avic	Shanghai AVIC Optoelectronics Co., Ltd.
>  axis	Axis Communications AB
>  boe	BOE Technology Group Co., Ltd.
> 

^ permalink raw reply

* Re: [PATCH 14/22] dt-bindings: power: supply: add AXP20X/AXP22X battery DT binding
From: Jonathan Cameron @ 2017-01-08 10:59 UTC (permalink / raw)
  To: Quentin Schulz, Rob Herring
  Cc: mark.rutland, devicetree, lars, linux-pm, linux-iio, linux-kernel,
	sre, linux, wens, icenowy, pmeerw, knaack.h, maxime.ripard,
	bonbons, lee.jones, thomas.petazzoni, linux-arm-kernel
In-Reply-To: <4a8456e6-c6e9-73ac-0f5c-29e9faceb13c@free-electrons.com>

On 08/01/17 10:48, Quentin Schulz wrote:
> Hi Jonathan,
> 
> On 07/01/2017 20:33, Jonathan Cameron wrote:
>> On 04/01/17 08:21, Rob Herring wrote:
>>> On Mon, Jan 02, 2017 at 05:37:14PM +0100, Quentin Schulz wrote:
>>>> The X-Powers AXP20X and AXP22X PMICs can have a battery as power supply.
>>>>
>>>> This patch adds the DT binding documentation for the battery power
>>>> supply which gets various data from the PMIC, such as the battery status
>>>> (charging, discharging, full, dead), current max limit, current current,
>>>> battery capacity (in percentage), voltage max and min limits, current
>>>> voltage and battery capacity (in Ah).
>>>>
>>>> Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
>>>> ---
>>>>  .../bindings/power/supply/axp20x_battery.txt       | 27 ++++++++++++++++++++++
>>>>  1 file changed, 27 insertions(+)
>>>>  create mode 100644 Documentation/devicetree/bindings/power/supply/axp20x_battery.txt
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/power/supply/axp20x_battery.txt b/Documentation/devicetree/bindings/power/supply/axp20x_battery.txt
>>>> new file mode 100644
>>>> index 0000000..5489d0d
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/power/supply/axp20x_battery.txt
>>>> @@ -0,0 +1,27 @@
>>>> +AXP20x and AXP22x battery power supply
>>>> +
>>>> +Required Properties:
>>>> + - compatible, one of:
>>>> +			"x-powers,axp209-battery-power-supply"
>>>> +			"x-powers,axp221-battery-power-supply"
>>>> + - io-channels: phandles to battery voltage, charge and discharge
>>>> + currents ADC channels
>>>> + - io-channel-names = "batt_v", "batt_chrg_i", "batt_dischrg_i";
>>>> +
>>>> +This node is a subnode of the axp20x/axp22x PMIC.
>>>> +
>>>> +The AXP20X and AXP22X can read the battery voltage, charge and discharge
>>>> +currents of the battery by reading ADC channels from the AXP20X/AXP22X
>>>> +ADC.
>>>> +
>>>> +Example:
>>>> +
>>>> +&axp209 {
>>>> +	battery_power_supply: battery_power_supply {
>>>
>>> Humm, I guess you power-supply is not sufficient, so 
>>> 'battery-power-supply' and similar for ac.
>>>
>>>> +		compatible = "x-powers,axp209-battery-power-supply";
>>>> +		io-channels = <&axp209_adc 7>, <&axp209_adc 8>,
>>>> +			<&axp209_adc 9>;
>>>> +		io-channel-names = "batt_v", "batt_chrg_i",
>>>> +			"batt_dischrg_i";
>> Is this stuff fixed for the device?
> 
> If we don't mix the IIO channels order, it is. This driver only requires
> batt_v, batt_chrg_i and batt_dischrg_i so we've to keep them at that
> place in the list of IIO channels. Or as suggested by Rob and Chen-Yu, I
> can move all this inside the driver with iio_map and don't care anymore
> about the order.
> 
I'd do that. Makes life easier to represented fixed things as fixed!
> Thanks,
> Quentin
> 

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox