Devicetree
 help / color / mirror / Atom feed
* Re: [PATCHv2] Documentation: dt-bindings: Add binding documentation for TI clkctrl clocks
From: Tony Lindgren @ 2017-01-23 18:38 UTC (permalink / raw)
  To: Tero Kristo
  Cc: Michael Turquette, Stephen Boyd,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-omap-u79uwXL29TY76Z2rM5mHXA, Paul Walmsley, Rob Herring
In-Reply-To: <f3c4154d-09d0-3930-4452-1f7d61622f3d-l0cyMroinI0@public.gmane.org>

* Tero Kristo <t-kristo-l0cyMroinI0@public.gmane.org> [170123 10:30]:
> On 23/01/17 18:28, Tony Lindgren wrote:
> > * Tero Kristo <t-kristo-l0cyMroinI0@public.gmane.org> [170123 06:45]:
> > > On 18/01/17 00:53, Tony Lindgren wrote:
> > > > Texas Instruments omap variant SoCs starting with omap4 have a clkctrl
> > > > clock controller instance for each interconnect target module. The clkctrl
> > > > controls functional and interface clocks for the module.
> > > > 
> > > > The clkctrl clocks are currently handled by arch/arm/mach-omap2 hwmod code.
> > > > With this binding and a related clock device driver we can start moving the
> > > > clkctrl clock handling to live in drivers/clk/ti.
> > > > 
> > > > Note that this binding allows keeping the clockdomain related parts out of
> > > > drivers/clock. The CLKCTCTRL and DYNAMICDEP registers can be handled by
> > > > a separate driver in drivers/soc/ti and genpd. If the clockdomain driver
> > > > needs to know it's clocks, we can just set the the clkctrl device
> > > > instances to be children of the related clockdomain device.
> > > > 
> > > > Each clkctrl clock can have multiple optional gate clocks, and multiple
> > > > optional mux clocks. To represent this in device tree, it seems that
> > > > it is best done using four clock cells #clock-cells = <4> property.
> > > > 
> > > > The reasons for using #clock-cells = <4> are:
> > > > 
> > > > 1. We need to specify the clkctrl offset from the instance base. Otherwise
> > > >    we end up with a large number of device tree nodes that need to be
> > > >    patched when new clocks are discovered in a clkctrl clock with minor
> > > >    hardware revision changes for example
> > > > 
> > > > 2. On omap5 CM_L3INIT_USB_HOST_HS_CLKCTRL has ten OPTFCLKEN bits. So we
> > > >    need to use a separate cell for optional gate clocks to avoid address
> > > >    space conflicts
> > > > 
> > > > 3. Some clkctrl instances can also also optional mux clocks. To address
> > > >    them properly we need also a separate cell for the optional mux
> > > >    clock index
> > > > 
> > > > 4. The modulemode clock needs a flag passed to it for hardware or
> > > >    software controlled mode
> > > 
> > > Hi Tony,
> > > 
> > > I think #clock-cells = <4> is too much. I believe we only need 2:
> > > 
> > > - one entry for clkctrl offset
> > > - one entry for clock offset within the clkctrl entry (0 = module clock, 8+
> > > = opt-clocks / mux clocks / dividers)
> > 
> > OK the less #clock-cells the better as long as it's enough :)
> > 
> > > Fields 2 / 3 in your proposal are mutually exclusive, if either field is
> > > non-zero, the other one must be zero. And, the opt clocks / mux / divs
> > > always have different values for these.
> > 
> > OK. Just to confirm the assumptions then:
> > 
> > 1. The optional mux clock the consumer needs to select the right
> >    source clock with with clk_set_parent()
> 
> Yes. And for this you need to fetch a clock handle via some mechanism
> (of_clk_get, clk_get...) Clock consumers can't directly use parent IDs.
> 
> > 
> > 2. The optional divider clock rate must be set by the consumer
> >    using clk_set_rate()
> 
> Yes again.
> 
> > 
> > And in that case we again don't need to define any artificial
> > clock indexes, which is good if new clocks are discovered between
> > various SoC revisions.
> > 
> > > Field 4 is kind of redundant also, as the module clock must be registered at
> > > the clkctrl probe time, it is too late for the clock consumer to provide the
> > > proper setting for the clock during its own probe. It seems I need to add
> > > static data to driver which basically has this information in place already.
> > 
> > OK yeah good point, the "clocks" is a consumer property.
> > 
> > So in that case we must also assume that if any clock consumer needs
> > to change between HWSUP or SWSUP, it needs to be done with some yet
> > to be determined API. We have not needed that so far AFAIK though.
> > 
> > If there are no issues with the above, I'm naturally fine using the
> > #clock-cells = <2> :)
> 
> Yeah, clock-cells = <2>; seems to work just fine in the WIP codebase I have.

OK thanks for confirming, will post v3 of the binding.

Regards,

Tony
--
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 00/18] ARM64: meson: DT cleanups
From: Kevin Hilman @ 2017-01-23 18:46 UTC (permalink / raw)
  To: Andreas Färber
  Cc: linux-amlogic, Carlo Caione, linux-arm-kernel, linux-kernel,
	devicetree
In-Reply-To: <20170120222118.21476-1-afaerber@suse.de>

Andreas Färber <afaerber@suse.de> writes:

> Hello,
>
> This series fixes several cosmetic issues, on top of v4.11/dt64 branch.
>
> Patches 3-5 rename a node, the rest should all be non-functional changes.

Can you respin patches 1-9 with minor comments addressed and
acks/reviews collected and I'll apply those.

> Patches 10-18 could be squashed if desired.

I'm less sure about these as I tend to agree with Rob that this is just
needless churn.  If you want to resend those separately, making your
arguments, I'll merge it if you convice the DT maintainers. :)

Kevin

^ permalink raw reply

* Re: [PATCH v4 0/9] meson-gx: reset RGMII PHYs and configure TX delay
From: Kevin Hilman @ 2017-01-23 18:55 UTC (permalink / raw)
  To: Martin Blumenstingl
  Cc: linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	carlo-KA+7E9HrN00dnm+yROfE0A,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, will.deacon-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, narmstrong-rdvid1DuHRBWk0Htik3J/w,
	jbrunet-rdvid1DuHRBWk0Htik3J/w, andrew-g2DYL2Zd6BY
In-Reply-To: <20170122181028.5014-1-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org> writes:

> This series adds the reset GPIOs for the (external) ethernet PHYs on all
> GXBB boards.
> Additionally it provides a ethernet PHY node which can be used to specify
> PHY-specific properties (this may be required if more boards require the
> "eee-broken-1000t" for the RTL8211F ethernet PHY). To make all board .dts
> consistent I chose to add the PHY node also for boards which don't have a
> RTL8211F PHY.
>
> Patch #7 from this series also removes ethernet support for the P200

I think you mean P201 here, right?

Kevin
--
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 v4 0/9] meson-gx: reset RGMII PHYs and configure TX delay
From: Martin Blumenstingl @ 2017-01-23 19:02 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	carlo-KA+7E9HrN00dnm+yROfE0A,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, will.deacon-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, narmstrong-rdvid1DuHRBWk0Htik3J/w,
	jbrunet-rdvid1DuHRBWk0Htik3J/w, andrew-g2DYL2Zd6BY
In-Reply-To: <m24m0p38sk.fsf-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>

On Mon, Jan 23, 2017 at 7:55 PM, Kevin Hilman <khilman-rdvid1DuHRBWk0Htik3J/w@public.gmane.org> wrote:
> Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org> writes:
>
>> This series adds the reset GPIOs for the (external) ethernet PHYs on all
>> GXBB boards.
>> Additionally it provides a ethernet PHY node which can be used to specify
>> PHY-specific properties (this may be required if more boards require the
>> "eee-broken-1000t" for the RTL8211F ethernet PHY). To make all board .dts
>> consistent I chose to add the PHY node also for boards which don't have a
>> RTL8211F PHY.
>>
>> Patch #7 from this series also removes ethernet support for the P200
>
> I think you mean P201 here, right?
indeed, that's a left-over of my P200 / P201 mixup in v2 - please ignore this :(
I should have dropped that sentence completely since it's a lie in v3
(v3 states in changes since v2: "instead of dropping ethernet support
for P201 we simply re-configure it to RMII mode")
--
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 2/3] pinctrl: meson: meson-gxl: add the pwm_ao_b pin
From: Kevin Hilman @ 2017-01-23 19:10 UTC (permalink / raw)
  To: Martin Blumenstingl
  Cc: linux-gpio-u79uwXL29TY76Z2rM5mHXA,
	linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
	carlo-KA+7E9HrN00dnm+yROfE0A,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, will.deacon-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <20170122210528.892-3-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org> writes:

> This adds support for the pwm_ao_b pin. Unfortunately the registers for
> the pwm_ao pins are not documented at all. The source for the pwm_ao_b
> pin from this patch is the Khadas VIM GPL kernel source, which sets bit
> 3 and unsets bits 4 and 31 to enable the PWM LEDs.
>
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
> ---
>  drivers/pinctrl/meson/pinctrl-meson-gxl.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
>
> diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxl.c b/drivers/pinctrl/meson/pinctrl-meson-gxl.c
> index 25694f7094c7..6ff321a7366d 100644
> --- a/drivers/pinctrl/meson/pinctrl-meson-gxl.c
> +++ b/drivers/pinctrl/meson/pinctrl-meson-gxl.c
> @@ -222,6 +222,8 @@ static const unsigned int uart_rts_ao_b_pins[]	= { PIN(GPIOAO_3, 0) };
>  
>  static const unsigned int remote_input_ao_pins[] = {PIN(GPIOAO_7, 0) };
>  
> +static const unsigned int pwm_ao_b_pins[]	= { PIN(GPIOAO_9, 0) };
> +

Hmm, the S905 public data sheet[1] shows this as GPIOAO_13.

>  static struct meson_pmx_group meson_gxl_periphs_groups[] = {
>  	GPIO_GROUP(GPIOZ_0, EE_OFF),
>  	GPIO_GROUP(GPIOZ_1, EE_OFF),
> @@ -418,6 +420,7 @@ static struct meson_pmx_group meson_gxl_aobus_groups[] = {
>  	GROUP(uart_cts_ao_b,	0,	8),
>  	GROUP(uart_rts_ao_b,	0,	7),
>  	GROUP(remote_input_ao,	0,	0),
> +	GROUP(pwm_ao_b,		0,	3),
>  };

but it does show as ao_reg[3].

Kevin

[1] http://dn.odroid.com/S905/DataSheet/S905_Public_Datasheet_V1.1.4.pdf
--
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 2/3] pinctrl: meson: meson-gxl: add the pwm_ao_b pin
From: Kevin Hilman @ 2017-01-23 19:12 UTC (permalink / raw)
  To: Martin Blumenstingl
  Cc: linux-gpio, linux-amlogic, Linus Walleij, Carlo Caione,
	linux-arm-kernel, devicetree, Will Deacon, Catalin Marinas,
	Mark Rutland, Rob Herring
In-Reply-To: <m2sho91tk5.fsf@baylibre.com>

On Mon, Jan 23, 2017 at 11:10 AM, Kevin Hilman <khilman@baylibre.com> wrote:
> Martin Blumenstingl <martin.blumenstingl@googlemail.com> writes:
>
>> This adds support for the pwm_ao_b pin. Unfortunately the registers for
>> the pwm_ao pins are not documented at all. The source for the pwm_ao_b
>> pin from this patch is the Khadas VIM GPL kernel source, which sets bit
>> 3 and unsets bits 4 and 31 to enable the PWM LEDs.
>>
>> Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
>> ---
>>  drivers/pinctrl/meson/pinctrl-meson-gxl.c | 8 ++++++++
>>  1 file changed, 8 insertions(+)
>>
>> diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxl.c b/drivers/pinctrl/meson/pinctrl-meson-gxl.c
>> index 25694f7094c7..6ff321a7366d 100644
>> --- a/drivers/pinctrl/meson/pinctrl-meson-gxl.c
>> +++ b/drivers/pinctrl/meson/pinctrl-meson-gxl.c
>> @@ -222,6 +222,8 @@ static const unsigned int uart_rts_ao_b_pins[]    = { PIN(GPIOAO_3, 0) };
>>
>>  static const unsigned int remote_input_ao_pins[] = {PIN(GPIOAO_7, 0) };
>>
>> +static const unsigned int pwm_ao_b_pins[]    = { PIN(GPIOAO_9, 0) };
>> +
>
> Hmm, the S905 public data sheet[1] shows this as GPIOAO_13.
>

gack, nevermind.  I see now this is for GXL, not GXBB.  Ignore my comments.

Linus, feel free to apply with:

Acked-by: Kevin Hilman <khilman@baylibre.com>

^ permalink raw reply

* Re: [PATCH linux v3 1/6] hwmon: Add core On-Chip Controller support for POWER CPUs
From: Edward James @ 2017-01-23 19:28 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: andrew, benh, corbet, devicetree, eajames.ibm, jdelvare, joel,
	linux-doc, linux-hwmon, linux-kernel, mark.rutland, robh+dt, wsa
In-Reply-To: <11e7a9a0-2735-79fc-226f-e725aefa4df7@roeck-us.net>

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

I still just can't get gmail to reply to this. Thanks for the review.

On Sat, Jan 21, 2017 at 11:49 AM, Guenter Roeck <linux@roeck-us.net> wrote:
> On 01/16/2017 01:13 PM, eajames.ibm@gmail.com wrote:
>>
>> From: "Edward A. James" <eajames@us.ibm.com>
>>
>> Add core support for polling the OCC for it's sensor data and parsing
that
>> data into sensor-specific information.
>>
>> Signed-off-by: Edward A. James <eajames@us.ibm.com>
>> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
>> ---
>>  Documentation/hwmon/occ    |  40 ++++
>>  MAINTAINERS                |   7 +
>>  drivers/hwmon/Kconfig      |   2 +
>>  drivers/hwmon/Makefile     |   1 +
>>  drivers/hwmon/occ/Kconfig  |  15 ++
>>  drivers/hwmon/occ/Makefile |   1 +
>>  drivers/hwmon/occ/occ.c    | 522
>> +++++++++++++++++++++++++++++++++++++++++++++
>>  drivers/hwmon/occ/occ.h    |  81 +++++++
>>  drivers/hwmon/occ/scom.h   |  47 ++++
>>  9 files changed, 716 insertions(+)
>>  create mode 100644 Documentation/hwmon/occ
>>  create mode 100644 drivers/hwmon/occ/Kconfig
>>  create mode 100644 drivers/hwmon/occ/Makefile
>>  create mode 100644 drivers/hwmon/occ/occ.c
>>  create mode 100644 drivers/hwmon/occ/occ.h
>>  create mode 100644 drivers/hwmon/occ/scom.h
>>
>> diff --git a/Documentation/hwmon/occ b/Documentation/hwmon/occ
>> new file mode 100644
>> index 0000000..79d1642
>> --- /dev/null
>> +++ b/Documentation/hwmon/occ
>> @@ -0,0 +1,40 @@
>> +Kernel driver occ
>> +=================
>> +
>> +Supported chips:
>> + * ASPEED AST2400
>> + * ASPEED AST2500
>> +
>> +Please note that the chip must be connected to a POWER8 or POWER9
>> processor
>> +(see the BMC - Host Communications section).
>> +
>> +Author: Eddie James <eajames@us.ibm.com>
>> +
>> +Description
>> +-----------
>> +
>> +This driver implements support for the OCC (On-Chip Controller) on the
>> IBM
>> +POWER8 and POWER9 processors, from a BMC (Baseboard Management
>> Controller). The
>> +OCC is an embedded processor that provides real time power and thermal
>> +monitoring.
>> +
>> +This driver provides an interface on a BMC to poll OCC sensor data, set
>> user
>> +power caps, and perform some basic OCC error handling.
>> +
>> +Currently, all versions of the OCC support four types of sensor data:
>> power,
>> +temperature, frequency, and "caps," which indicate limits and
thresholds
>> used
>> +internally on the OCC.
>> +
>> +BMC - Host Communications
>> +-------------------------
>> +
>> +For the POWER8 application, the BMC can communicate with the P8 over
I2C
>> bus.
>> +However, to access the OCC register space, any data transfer must use a
>> SCOM
>> +operation. SCOM is a procedure to initiate a data transfer, typically
of
>> 8
>> +bytes. SCOMs consist of writing a 32-bit command register and then
>> +reading/writing two 32-bit data registers. This driver implements these
>> +SCOM operations over I2C bus in order to communicate with the OCC.
>> +
>> +For the POWER9 application, the BMC can communicate with the P9 over
FSI
>> bus
>> +and SBE engine. Once again, SCOM operations are required. This driver
>> will
>> +implement SCOM ops over FSI/SBE. This will require the FSI driver.
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 5f0420a..f5d4195 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -9112,6 +9112,13 @@ T:       git git://linuxtv.org/media_tree.git
>>  S:     Maintained
>>  F:     drivers/media/i2c/ov7670.c
>>
>> +ON-CHIP CONTROLLER HWMON DRIVER
>> +M:     Eddie James <eajames@us.ibm.com>
>> +L:     linux-hwmon@vger.kernel.org
>> +S:     Maintained
>> +F:     Documentation/hwmon/occ
>> +F:     drivers/hwmon/occ/
>> +
>>  ONENAND FLASH DRIVER
>>  M:     Kyungmin Park <kyungmin.park@samsung.com>
>>  L:     linux-mtd@lists.infradead.org
>> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
>> index 190d270..e80ca81 100644
>> --- a/drivers/hwmon/Kconfig
>> +++ b/drivers/hwmon/Kconfig
>> @@ -1240,6 +1240,8 @@ config SENSORS_NSA320
>>           This driver can also be built as a module. If so, the module
>>           will be called nsa320-hwmon.
>>
>> +source drivers/hwmon/occ/Kconfig
>> +
>>  config SENSORS_PCF8591
>>         tristate "Philips PCF8591 ADC/DAC"
>>         depends on I2C
>> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
>> index d2cb7e8..c7ec5d4 100644
>> --- a/drivers/hwmon/Makefile
>> +++ b/drivers/hwmon/Makefile
>> @@ -169,6 +169,7 @@ obj-$(CONFIG_SENSORS_WM831X)        +=
wm831x-hwmon.o
>>  obj-$(CONFIG_SENSORS_WM8350)   += wm8350-hwmon.o
>>  obj-$(CONFIG_SENSORS_XGENE)    += xgene-hwmon.o
>>
>> +obj-$(CONFIG_SENSORS_PPC_OCC)  += occ/
>>  obj-$(CONFIG_PMBUS)            += pmbus/
>>
>>  ccflags-$(CONFIG_HWMON_DEBUG_CHIP) := -DDEBUG
>> diff --git a/drivers/hwmon/occ/Kconfig b/drivers/hwmon/occ/Kconfig
>> new file mode 100644
>> index 0000000..cdb64a7
>> --- /dev/null
>> +++ b/drivers/hwmon/occ/Kconfig
>> @@ -0,0 +1,15 @@
>> +#
>> +# On Chip Controller configuration
>> +#
>> +
>> +menuconfig SENSORS_PPC_OCC
>> +       bool "PPC On-Chip Controller"
>> +       help
>> +         If you say yes here you get support to monitor Power CPU
>> +         sensors via the On-Chip Controller (OCC).
>> +
>> +         Generally this is used by management controllers such as a BMC
>> +         on an OpenPower system.
>> +
>> +         This driver can also be built as a module. If so, the module
>> +         will be called occ.
>> diff --git a/drivers/hwmon/occ/Makefile b/drivers/hwmon/occ/Makefile
>> new file mode 100644
>> index 0000000..93cb52f
>> --- /dev/null
>> +++ b/drivers/hwmon/occ/Makefile
>> @@ -0,0 +1 @@
>> +obj-$(CONFIG_SENSORS_PPC_OCC) += occ.o
>> diff --git a/drivers/hwmon/occ/occ.c b/drivers/hwmon/occ/occ.c
>> new file mode 100644
>> index 0000000..3089762
>> --- /dev/null
>> +++ b/drivers/hwmon/occ/occ.c
>> @@ -0,0 +1,522 @@
>> +/*
>> + * occ.c - OCC hwmon driver
>> + *
>> + * This file contains the methods and data structures for the OCC hwmon
>> driver.
>> + *
>> + * Copyright 2016 IBM Corp.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + */
>> +
>> +#include <asm/unaligned.h>
>> +#include <linux/delay.h>
>> +#include <linux/device.h>
>> +#include <linux/err.h>
>> +#include <linux/init.h>
>> +#include <linux/jiffies.h>
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/mutex.h>
>> +#include <linux/slab.h>
>> +#include "occ.h"
>> +
>> +#define OCC_DATA_MAX           4096
>> +#define OCC_BMC_TIMEOUT_MS     20000
>> +
>> +/* To generate attn to OCC */
>> +#define ATTN_DATA              0x0006B035
>> +
>> +/* For BMC to read/write SRAM */
>> +#define OCB_ADDRESS            0x0006B070
>> +#define OCB_DATA               0x0006B075
>> +#define OCB_STATUS_CONTROL_AND 0x0006B072
>> +#define OCB_STATUS_CONTROL_OR  0x0006B073
>> +
>> +/* To init OCB */
>> +#define OCB_AND_INIT0          0xFBFFFFFF
>> +#define OCB_AND_INIT1          0xFFFFFFFF
>> +#define OCB_OR_INIT0           0x08000000
>> +#define OCB_OR_INIT1           0x00000000
>> +
>> +/* To generate attention on OCC */
>> +#define ATTN0                  0x01010000
>> +#define ATTN1                  0x00000000
>> +
>> +/* OCC return status */
>> +#define RESP_RETURN_CMD_IN_PRG 0xFF
>> +#define RESP_RETURN_SUCCESS    0
>> +#define RESP_RETURN_CMD_INVAL  0x11
>> +#define RESP_RETURN_CMD_LEN    0x12
>> +#define RESP_RETURN_DATA_INVAL 0x13
>> +#define RESP_RETURN_CHKSUM     0x14
>> +#define RESP_RETURN_OCC_ERR    0x15
>> +#define RESP_RETURN_STATE      0x16
>> +
>> +/* time interval to retry on "command in progress" return status */
>> +#define CMD_IN_PRG_INT_MS      100
>> +#define CMD_IN_PRG_RETRIES     (OCC_BMC_TIMEOUT_MS / CMD_IN_PRG_INT_MS)
>> +
>> +/* OCC command definitions */
>> +#define OCC_POLL               0
>> +#define OCC_SET_USER_POWR_CAP  0x22
>> +
>> +/* OCC poll command data */
>> +#define OCC_POLL_STAT_SENSOR   0x10
>> +
>> +/* OCC response data offsets */
>> +#define RESP_RETURN_STATUS     2
>> +#define RESP_DATA_LENGTH       3
>> +#define RESP_HEADER_OFFSET     5
>> +#define SENSOR_STR_OFFSET      37
>> +#define SENSOR_BLOCK_NUM_OFFSET        43
>> +#define SENSOR_BLOCK_OFFSET    45
>> +
>> +/* occ_poll_header
>> + * structure to match the raw occ poll response data
>> + */
>> +struct occ_poll_header {
>> +       u8 status;
>> +       u8 ext_status;
>> +       u8 occs_present;
>> +       u8 config;
>> +       u8 occ_state;
>> +       u8 mode;
>> +       u8 ips_status;
>> +       u8 error_log_id;
>> +       u32 error_log_addr_start;
>> +       u16 error_log_length;
>> +       u8 reserved2;
>> +       u8 reserved3;
>> +       u8 occ_code_level[16];
>> +       u8 sensor_eye_catcher[6];
>> +       u8 sensor_block_num;
>> +       u8 sensor_data_version;
>> +} __attribute__((packed, aligned(4)));
>> +
>> +struct occ_response {
>> +       struct occ_poll_header header;
>> +       struct occ_blocks data;
>> +};
>> +
>> +struct occ {
>> +       struct device *dev;
>> +       void *bus;
>> +       struct occ_bus_ops bus_ops;
>> +       struct occ_ops ops;
>> +       struct occ_config config;
>> +       unsigned long update_interval;
>> +       unsigned long last_updated;
>> +       struct mutex update_lock;
>> +       struct occ_response response;
>> +       bool valid;
>> +};
>> +
>> +static void deinit_occ_resp_buf(struct occ_response *resp)
>> +{
>> +       int i;
>> +
>> +       if (!resp)
>> +               return;
>> +
>
>
> This creates the impression that resp can ever be NULL, which is not the
> case.

Agreed. This might go away anyway if I follow your suggestions below
about memory management.

>
>> +       if (!resp->data.blocks)
>> +               return;
>> +
>> +       for (i = 0; i < resp->header.sensor_block_num; ++i)
>> +               kfree(resp->data.blocks[i].sensors);
>> +
>> +       kfree(resp->data.blocks);
>> +/sensor_type_s
>>
>> +       memset(resp, 0, sizeof(struct occ_response));
>> +
>> +       for (i = 0; i < MAX_OCC_SENSOR_TYPE; ++i)
>> +               resp->data.sensor_block_id[i] = -1;
>> +}
>> +
>> +static void *occ_get_sensor_by_type(struct occ_response *resp,
>> +                                   enum sensor_type t)
>> +{
>> +       if (!resp->data.blocks)
>> +               return NULL;
>> +
>> +       if (resp->data.sensor_block_id[t] == -1)
>> +               return NULL;
>> +
>> +       return resp->data.blocks[resp->data.sensor_block_id[t]].sensors;
>> +}
>> +
>> +static int occ_check_sensor(struct occ *driver, u8 sensor_length,
>> +                           u8 sensor_num, enum sensor_type t, int
block)
>> +{
>> +       void *sensor;
>> +       int type_block_id;
>> +       struct occ_response *resp = &driver->response;
>> +
>> +       sensor = occ_get_sensor_by_type(resp, t);
>> +
>> +       /* empty sensor block, release older sensor data */
>> +       if (sensor_num == 0 || sensor_length == 0) {
>> +               kfree(sensor);
>> +               dev_err(driver->dev, "no sensor blocks available\n");
>> +               return -ENODATA;
>> +       }
>> +
>> +       type_block_id = resp->data.sensor_block_id[t];
>> +       if (!sensor || sensor_num !=
>> +           resp->data.blocks[type_block_id].header.sensor_num) {
>> +               kfree(sensor);
>> +               resp->data.blocks[block].sensors =
>> +                       driver->ops.alloc_sensor(t, sensor_num);
>> +               if (!resp->data.blocks[block].sensors)
>> +                       return -ENOMEM;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int parse_occ_response(struct occ *driver, u8 *data,
>> +                             struct occ_response *resp)
>> +{
>> +       int b;
>> +       int s;
>> +       int rc;
>> +       int offset = SENSOR_BLOCK_OFFSET;
>> +       int sensor_type;
>> +       u8 sensor_block_num;
>> +       char sensor_type_string[5] = { 0 };
>
>
> The only purpose of this variable seems to be to zero-terminate it to be
> able
> to print it. Why not use length-limited print functions instead ?

Is there such a function to length limit to dev_err or dev_dbg?
Otherwise I have to snprintf or strncpy into a string to pass anyway.
I can drop the dev_dbg but I would like to print out the sensor string
if it doesn't match any of the expected ones.

>
>> +       struct sensor_data_block_header *block;
>> +       struct device *dev = driver->dev;
>> +
>> +       /* check if the data is valid */
>> +       if (strncmp(&data[SENSOR_STR_OFFSET], "SENSOR", 6) != 0) {
>> +               dev_err(dev, "no SENSOR string in response\n");
>
>
> Are those messages really necessary ? That can create a lot of logging
noise
> if the occ responds with bad data.

I will audit these, but I think it's limited to one error message
logged in any one function in case of error. Is that acceptable?
Otherwise it may be hard to tell where the error occurred.

>
>> +               rc = -ENODATA;
>> +               goto err;
>> +       }
>> +
>> +       sensor_block_num = data[SENSOR_BLOCK_NUM_OFFSET];
>
>
> There is a lot of trust in assuming that this data was actually received.
> At the same time, there is a lot of error checking. Why check if the
> information in this field is valid if you don't check if it was
> received in the first place ?

If we get to parse_occ_response, we know we got some data back from
the OCC (see occ_get_all). Here we are really checking the response is
a valid one, which I think makes sense in the parsing function.

>
>> +       if (sensor_block_num == 0) {
>> +               dev_err(dev, "no sensor blocks available\n");
>> +               rc = -ENODATA;
>> +               goto err;
>> +       }
>> +
>> +       /* if number of sensor block has changed, re-malloc */
>> +       if (sensor_block_num != resp->header.sensor_block_num) {
>> +               deinit_occ_resp_buf(resp);
>> +               resp->data.blocks = kcalloc(sensor_block_num,
>> +                                           sizeof(struct
>> sensor_data_block),
>> +                                           GFP_KERNEL);
>> +               if (!resp->data.blocks)
>> +                       return -ENOMEM;
>
>
> Why not just allocate the maximum number of sensors once ? That might
waste
> a bit of memory, but it would make the code much less error prone. We
know
> that
> there will never be more sensors than the number fitting into 4k of
memory,
> so the "waste" would not really be that much.

Fair point. I'll do that.

>
>
>> +       }
>> +
>> +       memcpy(&resp->header, &data[RESP_HEADER_OFFSET],
>> +              sizeof(struct occ_poll_header));
>> +       resp->header.error_log_addr_start =
>> +               be32_to_cpu(resp->header.error_log_addr_start);
>> +       resp->header.error_log_length =
>> +               be16_to_cpu(resp->header.error_log_length);
>> +
>> +       dev_dbg(dev, "Reading %d sensor blocks\n",
>> +               resp->header.sensor_block_num);
>> +       for (b = 0; b < sensor_block_num; b++) {
>> +               block = (struct sensor_data_block_header *)&data
[offset];
>> +               /* copy to a null terminated string */
>> +               strncpy(sensor_type_string, block->sensor_type, 4);
>> +               offset += 8;
>> +
>> +               dev_dbg(dev, "sensor block[%d]: type: %s, sensor_num:
>> %d\n", b,
>> +                       sensor_type_string, block->sensor_num);
>> +
>> +               if (strncmp(block->sensor_type, "FREQ", 4) == 0)
>> +                       sensor_type = FREQ;
>> +               else if (strncmp(block->sensor_type, "TEMP", 4) == 0)
>> +                       sensor_type = TEMP;
>> +               else if (strncmp(block->sensor_type, "POWR", 4) == 0)
>> +                       sensor_type = POWER;
>> +               else if (strncmp(block->sensor_type, "CAPS", 4) == 0)
>> +                       sensor_type = CAPS;
>> +               else {
>> +                       dev_err(dev, "sensor type not supported %s\n",
>> +                               sensor_type_string);
>> +                       continue;
>> +               }
>> +
>> +               rc = occ_check_sensor(driver, block->sensor_length,
>> +                                     block->sensor_num, sensor_type,
b);
>> +               if (rc == -ENOMEM)
>> +                       goto err;
>> +               else if (rc)
>> +                       continue;
>> +
>> +               resp->data.sensor_block_id[sensor_type] = b;
>> +               for (s = 0; s < block->sensor_num; s++) {
>> +                       driver->ops.parse_sensor(data,
>> +
>> resp->data.blocks[b].sensors,
>> +                                                sensor_type, offset,
s);
>> +                       offset += block->sensor_length;
>> +               }
>> +
>> +               /* copy block data over to response pointer */
>> +               resp->data.blocks[b].header = *block;
>> +       }
>> +
>> +       return 0;
>> +err:
>> +       deinit_occ_resp_buf(resp);
>> +       return rc;
>> +}
>> +
>> +static u8 occ_send_cmd(struct occ *driver, u8 seq, u8 type, u16 length,
>> +                      const u8 *data, u8 *resp)
>> +{
>> +       u32 cmd1, cmd2;
>> +       u16 checksum = 0;
>> +       u16 length_le = cpu_to_le16(length);
>> +       bool retry = 0;
>> +       int i, rc, tries = 0;
>> +
>> +       cmd1 = (seq << 24) | (type << 16) | length_le;
>> +       memcpy(&cmd2, data, length);
>> +       cmd2 <<= ((4 - length) * 8);
>> +
>> +       /* checksum: sum of every bytes of cmd1, cmd2 */
>> +       for (i = 0; i < 4; i++) {
>> +               checksum += (cmd1 >> (i * 8)) & 0xFF;
>> +               checksum += (cmd2 >> (i * 8)) & 0xFF;
>> +       }
>> +
>> +       cmd2 |= checksum << ((2 - length) * 8);
>> +
>> +       /* Init OCB */
>> +       rc = driver->bus_ops.putscom(driver->bus, OCB_STATUS_CONTROL_OR,
>> +                                    OCB_OR_INIT0, OCB_OR_INIT1);
>> +       if (rc)
>> +               goto err;
>> +
>> +       rc = driver->bus_ops.putscom(driver->bus,
OCB_STATUS_CONTROL_AND,
>> +                                    OCB_AND_INIT0, OCB_AND_INIT1);
>> +       if (rc)
>> +               goto err;
>> +
>> +       /* Send command, 2nd half of the 64-bit addr is unused (write 0)
>> */
>> +       rc = driver->bus_ops.putscom(driver->bus, OCB_ADDRESS,
>> +                                    driver->config.command_addr, 0);
>> +       if (rc)
>> +               goto err;
>> +
>> +       rc = driver->bus_ops.putscom(driver->bus, OCB_DATA, cmd1, cmd2);
>> +       if (rc)
>> +               goto err;
>> +
>> +       /* Trigger attention */
>> +       rc = driver->bus_ops.putscom(driver->bus, ATTN_DATA, ATTN0,
>> ATTN1);
>> +       if (rc)
>> +               goto err;
>> +
>> +       /* Get response data */
>> +       rc = driver->bus_ops.putscom(driver->bus, OCB_ADDRESS,
>> +                                    driver->config.response_addr, 0);
>> +       if (rc)
>> +               goto err;
>> +
>> +       do {
>> +               if (retry) {
>> +                       set_current_state(TASK_INTERRUPTIBLE);
>> +
>> schedule_timeout(msecs_to_jiffies(CMD_IN_PRG_INT_MS));
>> +               }
>> +
>
> Isn't there a better way to do this ? What exactly is interrupted ? The
> getscom function ? If so, shouldn't the timeout be handled there ?

There shouldn't be any interrupt. I set TASK_INTERRUPTIBLE because it
doesn't really matter if it's interrupted or not. The purpose of this
loop is to retry if we get the "command in progress" status from the
OCC. It's higher level than the getscom function, so I think the loop
is appropriate here.

>
>> +               rc = driver->bus_ops.getscom(driver->bus, OCB_DATA,
>> +                                            (u64 *)resp);
>> +               if (rc)
>> +                       goto err;
>> +
>> +               /* retry if we get "command in progress" return status
*/
>> +               retry = (resp[RESP_RETURN_STATUS] ==
>> RESP_RETURN_CMD_IN_PRG) &&
>> +                       (tries++ < CMD_IN_PRG_RETRIES);
>
>
> There are some unnecessary () in this expression.
>
>
>> +       } while (retry);
>> +
>> +       switch (resp[RESP_RETURN_STATUS]) {
>> +       case RESP_RETURN_CMD_IN_PRG:
>> +               rc = -EALREADY;
>> +               break;
>> +       case RESP_RETURN_SUCCESS:
>> +               rc = 0;
>> +               break;
>> +       case RESP_RETURN_CMD_INVAL:
>> +       case RESP_RETURN_CMD_LEN:
>> +       case RESP_RETURN_DATA_INVAL:
>> +       case RESP_RETURN_CHKSUM:
>> +               rc = -EINVAL;
>> +               break;
>> +       case RESP_RETURN_OCC_ERR:
>> +               rc = -EREMOTE;
>> +               break;
>> +       default:
>> +               rc = -EFAULT;
>> +       }
>> +
>> +       return rc;
>> +
>> +err:
>> +       dev_err(driver->dev, "scom op failed rc:%d\n", rc);
>
>
> Some of the errors result in an error message, some don't. What is
> the guiding principle ? Even if there is an error message, it doesn't
report
> what function caused it, which makes it as good as no error message.
> Can this be dropped ?

resp[RESP_RETURN_STATUS] is the status reported on the OCC, these
aren't necessarily errors, though most are. This is translating an OCC
status code to an error for occ_get_all to pick up. It cannot be
dropped, we need to know if the occ poll was successful. I'm not sure
what you mean by reporting the function? occ_get_all will fail out if
we report the error here. If it's the scom op that failed we will have
the dev_err message.

>
>> +       return rc;
>> +}
>> +
>> +static int occ_get_all(struct occ *driver)
>> +{
>> +       int i = 0, rc;
>> +       u8 *occ_data;
>> +       u16 num_bytes;
>> +       const u8 poll_cmd_data = OCC_POLL_STAT_SENSOR;
>> +       struct device *dev = driver->dev;
>> +       struct occ_response *resp = &driver->response;
>> +
>> +       occ_data = devm_kzalloc(dev, OCC_DATA_MAX, GFP_KERNEL);
>
>
> I am a bot lost here. What is the purpose of using a devm function ?
>
> Either case, you might want to allocate the memory once and just keep it
> allocated.
> Allocating a 4k buffer and freeing it each time data is read from the occ
> seems
> to be wasteful and not really worth it.

Agreed.

>
>> +       if (!occ_data)
>> +               return -ENOMEM;
>> +
>> +       rc = occ_send_cmd(driver, 0, OCC_POLL, 1, &poll_cmd_data,
>> occ_data);
>> +       if (rc) {
>> +               dev_err(dev, "OCC poll failed: %d\n", rc);
>> +               goto out;
>> +       }
>> +
>> +       num_bytes = get_unaligned((u16 *)&occ_data[RESP_DATA_LENGTH]);
>> +       num_bytes = be16_to_cpu(num_bytes);
>
>
> What data is in big endian, and what data is in little endian ?
>
> Looks like everything is big endian except for the length in the send
> command.
> Is that correct ? If so, an explanation would be useful, because the
logic
> isn't entirely clear.

I'll add some comments.

>
>> +       dev_dbg(dev, "OCC data length: %d\n", num_bytes);
>> +
>> +       if (num_bytes > OCC_DATA_MAX) {
>> +               dev_err(dev, "OCC data length must be < 4KB\n");
>> +               rc = -EINVAL;
>> +               goto out;
>> +       }
>> +
>> +       if (num_bytes <= 0) {
>
>
> This can never be < 0.

Good point.

>
>> +               dev_err(dev, "OCC data length is zero\n");
>> +               rc = -EINVAL;
>> +               goto out;
>> +       }
>> +
>> +       /* read remaining data */
>> +       for (i = 8; i < num_bytes + 8; i += 8) {
>> +               rc = driver->bus_ops.getscom(driver->bus, OCB_DATA,
>> +                                            (u64 *)&occ_data[i]);
>> +               if (rc) {
>> +                       dev_err(dev, "scom op failed rc:%d\n", rc);
>> +                       goto out;
>> +               }
>> +       }
>> +
>> +       /* don't need more sanity checks; buffer is alloc'd for max
>> response
>> +        * size so we just check for valid data in parse_occ_response
>> +        */
>
> Yes, but as mentioned above you don't check in that function if the data
> was actually received.

If we don't receive data, the data length will be 0 or the low level
getscom will fail. So we know we have data here.

>
>> +       rc = parse_occ_response(driver, occ_data, resp);
>> +
>> +out:
>> +       devm_kfree(dev, occ_data);
>> +       return rc;
>> +}
>> +
>> +int occ_update_device(struct occ *driver)
>> +{
>> +       int rc = 0;
>> +
>> +       mutex_lock(&driver->update_lock);
>> +
>> +       if (time_after(jiffies, driver->last_updated +
>> driver->update_interval)
>> +           || !driver->valid) {
>> +               driver->valid = 1;
>
>
> valid is bool.
>
>> +
>> +               rc = occ_get_all(driver);
>> +               if (rc)
>> +                       driver->valid = 0;
>
>
> valid is bool.

Good point.

>
>> +
>> +               driver->last_updated = jiffies;
>> +       }
>> +
>> +       mutex_unlock(&driver->update_lock);
>> +
>> +       return rc;
>> +}
>> +EXPORT_SYMBOL(occ_update_device);
>> +
>> +void *occ_get_sensor(struct occ *driver, int sensor_type)
>> +{
>> +       int rc;
>> +
>> +       /* occ_update_device locks the update lock */
>> +       rc = occ_update_device(driver);
>> +       if (rc) {
>> +               dev_err(driver->dev, "cannot get occ sensor data: %d\n",
>> +                       rc);
>
>
> Have you counted the number of error messages reported if anything goes
> wrong.
> This driver is quite noisy. I won't force you to drop the messages, but
it
> seems
> to me that if anything goes wrong, the kernel log will be clogged with
> messages
> just from this driver.

I'll audit these.

>
>
>> +               return NULL;
>> +       }
>> +
>> +       return occ_get_sensor_by_type(&driver->response, sensor_type);
>> +}
>> +EXPORT_SYMBOL(occ_get_sensor);
>> +
>> +int occ_get_sensor_value(struct occ *occ, int sensor_type, int
>> sensor_num,
>> +                        u32 hwmon, long *val)
>> +{
>> +       return occ->ops.get_sensor(occ, sensor_type, sensor_num, hwmon,
>> val);
>> +}
>> +EXPORT_SYMBOL(occ_get_sensor_value);
>> +
>> +void occ_get_response_blocks(struct occ *occ, struct occ_blocks
**blocks)
>> +{
>> +       *blocks = &occ->response.data;
>> +}
>> +EXPORT_SYMBOL(occ_get_response_blocks);
>> +
>> +void occ_set_update_interval(struct occ *occ, unsigned long interval)
>> +{
>> +       occ->update_interval = msecs_to_jiffies(interval);
>> +}
>> +EXPORT_SYMBOL(occ_set_update_interval);
>> +
>> +int occ_set_user_powercap(struct occ *occ, u16 cap)
>> +{
>> +       u8 resp[8];
>> +
>> +       cap = cpu_to_be16(cap);
>> +
>> +       return occ_send_cmd(occ, 0, OCC_SET_USER_POWR_CAP, 2, (const u8
>> *)&cap,
>> +                           resp);
>> +}
>> +EXPORT_SYMBOL(occ_set_user_powercap);
>> +
>> +struct occ *occ_start(struct device *dev, void *bus,
>> +                     struct occ_bus_ops *bus_ops, const struct occ_ops
>> *ops,
>> +                     const struct occ_config *config)
>> +{
>> +       struct occ *driver = devm_kzalloc(dev, sizeof(struct occ),
>> GFP_KERNEL);
>> +
>> +       if (!driver)
>> +               return ERR_PTR(-ENOMEM);
>> +
>> +       driver->dev = dev;
>> +       driver->bus = bus;
>> +       driver->bus_ops = *bus_ops;
>> +       driver->ops = *ops;
>> +       driver->config = *config;
>> +
>> +       driver->update_interval = HZ;
>
>
> The update interval is only supposed to be configurable if it can be
written
> into the hardware. Otherwise it is really up to user space to decide how
> often
> it wants to poll the data, not up to the kernel.
>
> I don't see a function to send the update interval to the occ. As such,
it
> should
> not be configurable but a constant.

I don't quite follow. Right now, the driver maximum polling rate is
configurable by userspace (via hwmon sysfs attribute). If you mean
that user space should control that rate just by how often users read
the attributes, I'm not sure that will work as there are a large
number of attributes that will all try and trigger an occ poll when
read. Besides, different users don't want to communicate about when
they last polled. If the rate is constant, if may be too slow or too
fast depending on the system and needs of the users. Why can't the
polling rate be configurable? To user space, the update interval works
the same if it's driver or hardware.

>
>
>> +       mutex_init(&driver->update_lock);
>> +
>> +       return driver;
>> +}
>> +EXPORT_SYMBOL(occ_start);
>> +
>> +MODULE_AUTHOR("Eddie James <eajames@us.ibm.com>");
>> +MODULE_DESCRIPTION("OCC hwmon core driver");
>> +MODULE_LICENSE("GPL");
>> diff --git a/drivers/hwmon/occ/occ.h b/drivers/hwmon/occ/occ.h
>> new file mode 100644
>> index 0000000..c86b06a
>> --- /dev/null
>> +++ b/drivers/hwmon/occ/occ.h
>> @@ -0,0 +1,81 @@
>> +/*
>> + * occ.h - hwmon OCC driver
>> + *
>> + * This file contains data structures and function prototypes for
common
>> access
>> + * between different bus protocols and host systems.
>> + *
>> + * Copyright 2016 IBM Corp.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + */
>> +
>> +#ifndef __OCC_H__
>> +#define __OCC_H__
>> +
>> +#include "scom.h"
>> +
>> +struct device;
>> +struct occ;
>> +
>> +/* sensor_data_block_header
>> + * structure to match the raw occ sensor block header
>> + */
>> +struct sensor_data_block_header {
>> +       u8 sensor_type[4];
>> +       u8 reserved0;
>> +       u8 sensor_format;
>> +       u8 sensor_length;
>> +       u8 sensor_num;
>> +} __attribute__((packed, aligned(4)));
>> +
>> +struct sensor_data_block {
>> +       struct sensor_data_block_header header;
>> +       void *sensors;
>> +};
>> +
>> +enum sensor_type {
>> +       FREQ = 0,
>> +       TEMP,
>> +       POWER,
>> +       CAPS,
>> +       MAX_OCC_SENSOR_TYPE
>> +};
>> +
>> +struct occ_ops {
>> +       void (*parse_sensor)(u8 *data, void *sensor, int sensor_type,
int
>> off,
>> +                            int snum);
>> +       void *(*alloc_sensor)(int sensor_type, int num_sensors);
>> +       int (*get_sensor)(struct occ *driver, int sensor_type, int
>> sensor_num,
>> +                         u32 hwmon, long *val);
>> +};
>> +
>> +struct occ_config {
>> +       u32 command_addr;
>> +       u32 response_addr;
>> +};
>> +
>> +struct occ_blocks {
>> +       int sensor_block_id[MAX_OCC_SENSOR_TYPE];
>> +       struct sensor_data_block *blocks;
>> +};
>> +
>> +struct occ *occ_start(struct device *dev, void *bus,
>> +                     struct occ_bus_ops *bus_ops, const struct occ_ops
>> *ops,
>> +                     const struct occ_config *config);
>> +void *occ_get_sensor(struct occ *occ, int sensor_type);
>> +int occ_get_sensor_value(struct occ *occ, int sensor_type, int
>> sensor_num,
>> +                        u32 hwmon, long *val);
>> +void occ_get_response_blocks(struct occ *occ, struct occ_blocks
>> **blocks);
>> +int occ_update_device(struct occ *driver);
>> +void occ_set_update_interval(struct occ *occ, unsigned long interval);
>> +int occ_set_user_powercap(struct occ *occ, u16 cap);
>> +
>> +#endif /* __OCC_H__ */
>> diff --git a/drivers/hwmon/occ/scom.h b/drivers/hwmon/occ/scom.h
>> new file mode 100644
>> index 0000000..c1da645
>> --- /dev/null
>> +++ b/drivers/hwmon/occ/scom.h
>> @@ -0,0 +1,47 @@
>> +/*
>> + * scom.h - hwmon OCC driver
>> + *
>> + * This file contains data structures for scom operations to the OCC
>> + *
>> + * Copyright 2016 IBM Corp.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + */
>> +
>> +#ifndef __SCOM_H__
>> +#define __SCOM_H__
>> +
>> +/*
>> + * occ_bus_ops - represent the low-level transfer methods to
communicate
>> with
>> + * the OCC.
>> + *
>> + * getscom - OCC scom read
>> + * @bus: handle to slave device
>> + * @address: address
>> + * @data: where to store data read from slave; buffer size must be at
>> least
>> + * eight bytes.
>> + *
>> + * Returns 0 on success or a negative errno on error
>> + *
>> + * putscom - OCC scom write
>> + * @bus: handle to slave device
>> + * @address: address
>> + * @data0: first data byte to write
>> + * @data1: second data byte to write
>
>
> 32 bit bytes ? It might also be worthwhile to mention the expected byte
> order.

Good point.


>
>
>> + *
>> + * Returns 0 on success or a negative errno on error
>> + */
>> +struct occ_bus_ops {
>> +       int (*getscom)(void *bus, u32 address, u64 *data);
>> +       int (*putscom)(void *bus, u32 address, u32 data0, u32 data1);
>> +};
>> +
>> +#endif /* __SCOM_H__ */
>>
>

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

^ permalink raw reply

* Re: [PATCH v4 1/3] dt: bindings: add documentation for zx2967 family watchdog controller
From: Rob Herring @ 2017-01-23 19:55 UTC (permalink / raw)
  To: Baoyou Xie
  Cc: jun.nie, wim, linux, mark.rutland, linux-arm-kernel,
	linux-watchdog, devicetree, linux-kernel, shawnguo, xie.baoyou,
	chen.chaokai, wang.qiang01
In-Reply-To: <1485073008-26699-1-git-send-email-baoyou.xie@linaro.org>

On Sun, Jan 22, 2017 at 04:16:46PM +0800, Baoyou Xie wrote:
> This patch adds dt-binding documentation for zx2967 family
> watchdog controller.
> 
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
> ---
>  .../bindings/watchdog/zte,zx2967-wdt.txt           | 31 ++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/watchdog/zte,zx2967-wdt.txt

Acked-by: Rob Herring <robh@kernel.org>

^ permalink raw reply

* Re: [PATCH 1/2] iio: adc: Add Renesas GyroADC bindings
From: Marek Vasut @ 2017-01-23 19:56 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA, Geert Uytterhoeven,
	Simon Horman, Jonathan Cameron,
	linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA, Wolfram Sang,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170123170827.tkatb2aizjhbfifo@rob-hp-laptop>

On 01/23/2017 06:08 PM, Rob Herring wrote:
> On Sat, Jan 21, 2017 at 03:42:11PM +0100, Marek Vasut wrote:
>> Add DT bindings for the Renesas RCar GyroADC block. This block is
>> a simple 4/8-channel ADC which samples 12/15/24 bits of data every
>> cycle from all channels.
> 
> Isn't this v7?

Technically yes, it was part of the 2/2 until now.

>> Signed-off-by: Marek Vasut <marek.vasut-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> Cc: Geert Uytterhoeven <geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
>> Cc: Simon Horman <horms+renesas-/R6kz+dDXgpPR4JQBCEnsQ@public.gmane.org>
>> Cc: Jonathan Cameron <jic23-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
>> Cc: linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>> Cc: Wolfram Sang <wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org>
>> Cc: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
>> Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>> ---
>>  .../bindings/iio/adc/renesas,gyroadc.txt           | 93 ++++++++++++++++++++++
>>  1 file changed, 93 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/iio/adc/renesas,gyroadc.txt
>>
>> diff --git a/Documentation/devicetree/bindings/iio/adc/renesas,gyroadc.txt b/Documentation/devicetree/bindings/iio/adc/renesas,gyroadc.txt
>> new file mode 100644
>> index 000000000000..081947367135
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/iio/adc/renesas,gyroadc.txt
>> @@ -0,0 +1,93 @@
>> +* Renesas RCar GyroADC device driver
> 
> What's a GyroADC?

The GyroADC block is a reduced SPI block with up to 8 chipselect lines,
which supports the SPI protocol of a selected few SPI ADCs. The SPI ADCs
are sampled by the GyroADC block in a round-robin fashion and the result
presented in the GyroADC registers.

Good ?

>> +
>> +Required properties:
>> +- compatible:	Should be "renesas,<chip>-gyroadc", "renesas,rcar-gyroadc".
> 
> Need to enumerate <chip>.

It's enumerated below , the only special-case we handle at this point is
the r8a7792 , which has extra interrupt block which we don't use anyway,
but the driver disables those interrupts.

>> +		Use "renesas,r8a7792-gyroadc" for a GyroADC with interrupt
>> +		block found in R8A7792.

I can add .... otherwise use the matching SoC model in <chip> field.

>> +- reg:		Address and length of the register set for the device
>> +- clocks:	References to all the clocks specified in the clock-names
>> +		property as specified in
>> +		Documentation/devicetree/bindings/clock/clock-bindings.txt.
>> +- clock-names:	Shall contain "fck" and "if". The "fck" is the GyroADC block
>> +		clock, the "if" is the interface clock.
>> +- power-domains: Must contain a reference to the PM domain, if available.
>> +- #address-cells: Should be <1> (setting for the subnodes) for all ADCs
>> +		except for "fujitsu,mb88101a". Should be <0> (setting for
>> +		only subnode) for "fujitsu,mb88101a".
>> +- #size-cells:	Should be <0> (setting for the subnodes)
>> +
>> +Sub-nodes:
>> +Optionally you can define subnodes which select the connected ADC type and
>> +reference voltage for the GyroADC channels.
> 
> Seems strange to be optional. How many nodes are possible?

1, up-to 4 or up-to 8, depending on the ADC you connect.

I guess it can be made mandatory as not having any ADC attached would
make it pretty pointless to enable this block in the first place ...

>> +
>> +Required properties for subnodes:
>> +- compatible:	Should be either of:
>> +		"fujitsu,mb88101a"
>> +			- Fujitsu MB88101A compatible mode,
>> +			  12bit sampling, up to 4 channels can be sampled in
>> +			  round-robin fashion. One Fujitsu chip supplies four
>> +			  GyroADC channels with data as it contains four ADCs
>> +			  on the chip and thus for 4-channel operation, single
>> +			  MB88101A is required. The Cx chipselect lines of the
>> +			  MB88101A connect directly to two CHS lines of the
>> +			  GyroADC, no demuxer is required. The data out line
>> +			  of each MB88101A connects to a shared input pin of
>> +			  the GyroADC.
>> +		"ti,adcs7476" or "ti,adc121" or "adi,ad7476"
>> +			- TI ADCS7476 / TI ADC121 / ADI AD7476 compatible mode,
>> +			  15bit sampling, up to 8 channels can be sampled in
>> +			  round-robin fashion. One TI/ADI chip supplies single
>> +			  ADC channel with data, thus for 8-channel operation,
>> +			  8 chips are required. A 3:8 chipselect demuxer is
>> +			  required to connect the nCS line of the TI/ADI chips
>> +			  to the GyroADC, while MISO line of each TI/ADI ADC
>> +			  connects to a shared input pin of the GyroADC.
>> +		"maxim,max1162" or "maxim,max11100"
>> +			- Maxim MAX1162 / Maxim MAX11100 compatible mode,
>> +			  16bit sampling, up to 8 channels can be sampled in
>> +			  round-robin fashion. One Maxim chip supplies single
>> +			  ADC channel with data, thus for 8-channel operation,
>> +			  8 chips are required. A 3:8 chipselect demuxer is
>> +			  required to connect the nCS line of the MAX chips
>> +			  to the GyroADC, while MISO line of each Maxim ADC
>> +			  connects to a shared input pin of the GyroADC.
>> +- reg:		Should be the number of the analog input. Should be present
>> +		for all ADCs except "fujitsu,mb88101a".
>> +- vref-supply:	Reference to the channel reference voltage regulator.
>> +
>> +Example:
>> +	vref_max1162: regulator-vref-max1162 {
>> +		compatible = "regulator-fixed";
>> +
>> +		regulator-name = "MAX1162 Vref";
>> +		regulator-min-microvolt = <4096000>;
>> +		regulator-max-microvolt = <4096000>;
>> +	};
>> +
>> +	&adc {
>> +		compatible = "renesas,r8a7791-gyroadc", "renesas,rcar-gyroadc";
>> +		reg = <0 0xe6e54000 0 64>;
>> +		clocks = <&mstp9_clks R8A7791_CLK_GYROADC>, <&clk_65m>;
>> +		clock-names = "fck", "if";
>> +		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
>> +
>> +		pinctrl-0 = <&adc_pins>;
>> +		pinctrl-names = "default";
>> +
>> +		status = "okay";
> 
> Drop status from examples.

Dropped.

>> +
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +
>> +		adc@0 {
>> +			reg = <0>;
>> +			compatible = "maxim,max1162";
>> +			vref-supply = <&vref_max1162>;
>> +		};
>> +
>> +		adc@1 {
>> +			reg = <1>;
>> +			compatible = "maxim,max1162";
>> +			vref-supply = <&vref_max1162>;
>> +		};
>> +	};
>> -- 
>> 2.11.0
>>


-- 
Best regards,
Marek Vasut
--
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 02/22] irqchip: DT bindings for Cortina Gemini irqchip
From: Rob Herring @ 2017-01-23 20:01 UTC (permalink / raw)
  To: Linus Walleij
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Hans Ulli Kroll, Florian Fainelli, Thomas Gleixner, Marc Zyngier,
	Janos Laube, Paulius Zaleckas,
	openwrt-devel-p3rKhJxN3npAfugRpC6u6w, Arnd Bergmann,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170122121609.10098-1-linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

On Sun, Jan 22, 2017 at 01:16:09PM +0100, Linus Walleij wrote:
> This adds device tree bindings for the Cortina Gemini interrupt
> controller. They are pretty standard.
> 
> Cc: Janos Laube <janos.dev-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Cc: Paulius Zaleckas <paulius.zaleckas-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Cc: Hans Ulli Kroll <ulli.kroll-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
> Cc: Florian Fainelli <f.fainelli-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Signed-off-by: Linus Walleij <linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
> irqchip maintainers: please just apply this when you feel pleased
> with it. These portions are functionally orthogonal to the series,
> it is just in a series for context.
> ---
>  .../cortina,gemini-interrupt-controller.txt        | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/cortina,gemini-interrupt-controller.txt

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
--
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 04/22] clocksource: add DT bindings for Cortina Gemini
From: Rob Herring @ 2017-01-23 20:02 UTC (permalink / raw)
  To: Linus Walleij
  Cc: linux-arm-kernel, Hans Ulli Kroll, Florian Fainelli,
	Daniel Lezcano, Thomas Gleixner, Janos Laube, Paulius Zaleckas,
	openwrt-devel, Arnd Bergmann, linux-kernel, devicetree
In-Reply-To: <20170122121707.10200-1-linus.walleij@linaro.org>

On Sun, Jan 22, 2017 at 01:17:07PM +0100, Linus Walleij wrote:
> This adds device tree bindings for the Cortina Systems Gemini
> timer block used in these SoCs.
> 
> Cc: Janos Laube <janos.dev@gmail.com>
> Cc: Paulius Zaleckas <paulius.zaleckas@gmail.com>
> Cc: Hans Ulli Kroll <ulli.kroll@googlemail.com>
> Cc: Florian Fainelli <f.fainelli@gmail.com>
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> clocksource maintainers: please just apply this when you feel
> pleased with it. These portions are functionally orthogonal to
> the series, it is just in a series for context.
> ---
>  .../bindings/timer/cortina,gemini-timer.txt        | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/timer/cortina,gemini-timer.txt

Acked-by: Rob Herring <robh@kernel.org>

^ permalink raw reply

* Re: [PATCH 06/22] gpio: add DT bindings for Cortina Gemini GPIO
From: Rob Herring @ 2017-01-23 20:04 UTC (permalink / raw)
  To: Linus Walleij
  Cc: linux-arm-kernel, Hans Ulli Kroll, Florian Fainelli,
	Alexandre Courbot, Janos Laube, Paulius Zaleckas, openwrt-devel,
	Arnd Bergmann, linux-kernel, linux-gpio, devicetree
In-Reply-To: <20170122121830.10336-1-linus.walleij@linaro.org>

On Sun, Jan 22, 2017 at 01:18:30PM +0100, Linus Walleij wrote:
> This adds fairly standard DT bindings for the Cortina Systems
> Gemini GPIO controller.
> 
> Cc: Janos Laube <janos.dev@gmail.com>
> Cc: Paulius Zaleckas <paulius.zaleckas@gmail.com>
> Cc: Hans Ulli Kroll <ulli.kroll@googlemail.com>
> Cc: Florian Fainelli <f.fainelli@gmail.com>
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> Note to self: just apply this to the GPIO tree when discussion is over.
> ---
>  .../bindings/gpio/cortina,gemini-gpio.txt          | 24 ++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/gpio/cortina,gemini-gpio.txt

Acked-by: Rob Herring <robh@kernel.org>

^ permalink raw reply

* Re: [PATCH 08/22] rtc: Add device tree probing to the Gemini driver
From: Rob Herring @ 2017-01-23 20:06 UTC (permalink / raw)
  To: Linus Walleij
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Hans Ulli Kroll, Florian Fainelli, Alessandro Zummo,
	Alexandre Belloni, Janos Laube, Paulius Zaleckas,
	openwrt-devel-p3rKhJxN3npAfugRpC6u6w, Arnd Bergmann,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	rtc-linux-/JYPxA39Uh5TLH3MbocFFw,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170122121950.10449-1-linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

On Sun, Jan 22, 2017 at 01:19:50PM +0100, Linus Walleij wrote:
> This adds bindings and simple probing for the Cortina Systems Gemini
> SoC RTC.
> 
> Cc: Janos Laube <janos.dev-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Cc: Paulius Zaleckas <paulius.zaleckas-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Cc: Hans Ulli Kroll <ulli.kroll-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
> Cc: Florian Fainelli <f.fainelli-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Signed-off-by: Linus Walleij <linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
> RTC maintainers: please just apply this to the RTC tree when you
> are pleased with it. It is functionally orthogonal to the rest of
> the series and just in a series for context.
> ---
>  Documentation/devicetree/bindings/rtc/cortina,gemini.txt | 14 ++++++++++++++
>  drivers/rtc/rtc-gemini.c                                 |  7 +++++++
>  2 files changed, 21 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/rtc/cortina,gemini.txt

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

-- 
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
--- 
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.

^ permalink raw reply

* Re: [PATCH v3 2/4] dt-bindings: Add TI SCI PM Domains
From: Dave Gerlach @ 2017-01-23 20:11 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Rob Herring, Kevin Hilman, Tero Kristo, Rafael J . Wysocki,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-pm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Nishanth Menon, Keerthy, Russell King, Sudeep Holla,
	Santosh Shilimkar, Lokesh Vutla
In-Reply-To: <CAPDyKFpTyn2isNahywmOOSWiZKov9xsudyWi_i-FejXjC+1AZw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On 01/20/2017 10:52 AM, Ulf Hansson wrote:
> [...]
>
>>>> Another option is create something new either common or TI SCI
>>>> specific. It could be just a table of ids and phandles in the SCI
>>>> node. I'm much more comfortable with an isolated property in one node
>>>> than something scattered throughout the DT.
>>>
>>> To me, this seems like the best possible solution.
>>>
>>> However, perhaps we should also consider the SCPI Generic power domain
>>> (drivers/firmware/scpi_pm_domain.c), because I believe it's closely
>>> related.
>>> To change the power state of a device, this PM domain calls
>>> scpi_device_set|get_power_state() (drivers/firmware/arm_scpi.c), which
>>> also needs a device id as a parameter. Very similar to our case with
>>> the TI SCI domain.
>>>
>>> Currently these SCPI device ids lacks corresponding DT bindings, so
>>> the scpi_pm_domain tries to work around it by assigning ids
>>> dynamically at genpd creation time.
>>>
>>> That makes me wonder, whether we should think of something common/generic?
>>
>> When you say something common/generic, do you mean a better binding for genpd,
>> or something bigger than that like a new driver? Because I do think a phandle
>> cell left open for the genpd provider to interpret solves both the scpi and
>> ti-sci problem we are facing here in the best way. Using generic PM domains lets
>> us do exactly what we want apart from interpreting the phandle cell with our
>> driver, and I feel like anything else we try at this point is just going to be
>> to work around that. Is bringing back genpd xlate something we can discuss?
>
> Bringing back xlate, how would that help? Wouldn't that just mean that
> you will get one genpd per device? That's not an option, I think we
> are all in agreement to that.

Sure, perhaps the custom xlate wouldn't be the right way to do it, as we 
wouldn't be able to associate a device directly to a phandle, at least 
with how it was implemented before, but I think we can skip that 
entirely. Does opening up the interpretation of the cells of the 
'power-domains' phandle not solve all of these issues? Is that out of 
the question?

genpd_xlate_simple currently just makes sure the args_count of the 
'power-domains' phandle was zero and bails if it was not. Why couldn't 
we remove this check and let the driver interpret it while still using 
of_genpd_add_provider_simple to register the provider? It's still a 
'simple' provider from the perspective of the genpd framework and the 
actual pm domain mapping will not change, but now the driver can parse 
the cells and do whatever it needs to, such as reading a device id.

I think that's a bit more flexible and will avoid breaking anything that 
is there today.

Regards,
Dave

>
> Or am I missing something here?
>
> Regarding something "common/generic", I was merely thinking of some
> common bindings describing the list of phandle to device ids mapping.
> However, let's not make this more complicated than it is already. So
> please just ignore my suggestion so we can make this work for your
> case first.
>
> However, maybe I didn't fully understood Rob's suggestion. Perhaps Rob
> can clarify once more.
>
> Anyway, this is how interpreted Rob's suggestion:
>
> TISCI_PM_DOMAIN_DEVLIST: tisci-pm-domain-devlist {
>      devs = <&serial0>, <&mmc0>;
>      devids = <5 10>;
> }
>
> With this, you should be to extract the devid which corresponds to the
> device that has been attached to the TI SCI PM domain. Don't you
> think?
>
> Kind regards
> Uffe
>

--
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 09/22] mtd: add DT bindings for the Cortina Systems Gemini Flash
From: Rob Herring @ 2017-01-23 20:13 UTC (permalink / raw)
  To: Linus Walleij
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Hans Ulli Kroll, Florian Fainelli, David Woodhouse, Brian Norris,
	Boris Brezillon, Marek Vasut, Richard Weinberger, Cyrille Pitchen,
	Janos Laube, Paulius Zaleckas,
	openwrt-devel-p3rKhJxN3npAfugRpC6u6w, Arnd Bergmann,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170122122119.10510-1-linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

On Sun, Jan 22, 2017 at 01:21:19PM +0100, Linus Walleij wrote:
> This adds device tree bindings for the Cortina systems Gemini
> flash controller, a simple physmap which however need a few
> syscon bits to be poked to operate properly.
> 
> Cc: Janos Laube <janos.dev-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Cc: Paulius Zaleckas <paulius.zaleckas-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Cc: Hans Ulli Kroll <ulli.kroll-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
> Cc: Florian Fainelli <f.fainelli-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Signed-off-by: Linus Walleij <linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
> MTD maintainers: please just apply this to the MTD tree when
> you are happy with it. It is functionally orthogonal to the rest
> of the series and is just in the series for context.
> ---
>  .../bindings/mtd/cortina,gemini-flash.txt          | 24 ++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mtd/cortina,gemini-flash.txt

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
--
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 linux v3 1/6] hwmon: Add core On-Chip Controller support for POWER CPUs
From: Guenter Roeck @ 2017-01-23 20:21 UTC (permalink / raw)
  To: Edward James
  Cc: andrew, benh, corbet, devicetree, eajames.ibm, jdelvare, joel,
	linux-doc, linux-hwmon, linux-kernel, mark.rutland, robh+dt, wsa
In-Reply-To: <OFFB249CF0.36530F73-ON002580B1.006A773E-862580B1.006B038A@notes.na.collabserv.com>

On Mon, Jan 23, 2017 at 01:28:52PM -0600, Edward James wrote:
> I still just can't get gmail to reply to this. Thanks for the review.
> 
> On Sat, Jan 21, 2017 at 11:49 AM, Guenter Roeck <linux@roeck-us.net> wrote:
> > On 01/16/2017 01:13 PM, eajames.ibm@gmail.com wrote:
> >>
> >> From: "Edward A. James" <eajames@us.ibm.com>
> >>
> >> Add core support for polling the OCC for it's sensor data and parsing
> that
> >> data into sensor-specific information.
> >>
> >> Signed-off-by: Edward A. James <eajames@us.ibm.com>
> >> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
> >> ---
> >>  Documentation/hwmon/occ    |  40 ++++
> >>  MAINTAINERS                |   7 +
> >>  drivers/hwmon/Kconfig      |   2 +
> >>  drivers/hwmon/Makefile     |   1 +
> >>  drivers/hwmon/occ/Kconfig  |  15 ++
> >>  drivers/hwmon/occ/Makefile |   1 +
> >>  drivers/hwmon/occ/occ.c    | 522
> >> +++++++++++++++++++++++++++++++++++++++++++++
> >>  drivers/hwmon/occ/occ.h    |  81 +++++++
> >>  drivers/hwmon/occ/scom.h   |  47 ++++
> >>  9 files changed, 716 insertions(+)
> >>  create mode 100644 Documentation/hwmon/occ
> >>  create mode 100644 drivers/hwmon/occ/Kconfig
> >>  create mode 100644 drivers/hwmon/occ/Makefile
> >>  create mode 100644 drivers/hwmon/occ/occ.c
> >>  create mode 100644 drivers/hwmon/occ/occ.h
> >>  create mode 100644 drivers/hwmon/occ/scom.h
> >>
> >> diff --git a/Documentation/hwmon/occ b/Documentation/hwmon/occ
> >> new file mode 100644
> >> index 0000000..79d1642
> >> --- /dev/null
> >> +++ b/Documentation/hwmon/occ
> >> @@ -0,0 +1,40 @@
> >> +Kernel driver occ
> >> +=================
> >> +
> >> +Supported chips:
> >> + * ASPEED AST2400
> >> + * ASPEED AST2500
> >> +
> >> +Please note that the chip must be connected to a POWER8 or POWER9
> >> processor
> >> +(see the BMC - Host Communications section).
> >> +
> >> +Author: Eddie James <eajames@us.ibm.com>
> >> +
> >> +Description
> >> +-----------
> >> +
> >> +This driver implements support for the OCC (On-Chip Controller) on the
> >> IBM
> >> +POWER8 and POWER9 processors, from a BMC (Baseboard Management
> >> Controller). The
> >> +OCC is an embedded processor that provides real time power and thermal
> >> +monitoring.
> >> +
> >> +This driver provides an interface on a BMC to poll OCC sensor data, set
> >> user
> >> +power caps, and perform some basic OCC error handling.
> >> +
> >> +Currently, all versions of the OCC support four types of sensor data:
> >> power,
> >> +temperature, frequency, and "caps," which indicate limits and
> thresholds
> >> used
> >> +internally on the OCC.
> >> +
> >> +BMC - Host Communications
> >> +-------------------------
> >> +
> >> +For the POWER8 application, the BMC can communicate with the P8 over
> I2C
> >> bus.
> >> +However, to access the OCC register space, any data transfer must use a
> >> SCOM
> >> +operation. SCOM is a procedure to initiate a data transfer, typically
> of
> >> 8
> >> +bytes. SCOMs consist of writing a 32-bit command register and then
> >> +reading/writing two 32-bit data registers. This driver implements these
> >> +SCOM operations over I2C bus in order to communicate with the OCC.
> >> +
> >> +For the POWER9 application, the BMC can communicate with the P9 over
> FSI
> >> bus
> >> +and SBE engine. Once again, SCOM operations are required. This driver
> >> will
> >> +implement SCOM ops over FSI/SBE. This will require the FSI driver.
> >> diff --git a/MAINTAINERS b/MAINTAINERS
> >> index 5f0420a..f5d4195 100644
> >> --- a/MAINTAINERS
> >> +++ b/MAINTAINERS
> >> @@ -9112,6 +9112,13 @@ T:       git git://linuxtv.org/media_tree.git
> >>  S:     Maintained
> >>  F:     drivers/media/i2c/ov7670.c
> >>
> >> +ON-CHIP CONTROLLER HWMON DRIVER
> >> +M:     Eddie James <eajames@us.ibm.com>
> >> +L:     linux-hwmon@vger.kernel.org
> >> +S:     Maintained
> >> +F:     Documentation/hwmon/occ
> >> +F:     drivers/hwmon/occ/
> >> +
> >>  ONENAND FLASH DRIVER
> >>  M:     Kyungmin Park <kyungmin.park@samsung.com>
> >>  L:     linux-mtd@lists.infradead.org
> >> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> >> index 190d270..e80ca81 100644
> >> --- a/drivers/hwmon/Kconfig
> >> +++ b/drivers/hwmon/Kconfig
> >> @@ -1240,6 +1240,8 @@ config SENSORS_NSA320
> >>           This driver can also be built as a module. If so, the module
> >>           will be called nsa320-hwmon.
> >>
> >> +source drivers/hwmon/occ/Kconfig
> >> +
> >>  config SENSORS_PCF8591
> >>         tristate "Philips PCF8591 ADC/DAC"
> >>         depends on I2C
> >> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> >> index d2cb7e8..c7ec5d4 100644
> >> --- a/drivers/hwmon/Makefile
> >> +++ b/drivers/hwmon/Makefile
> >> @@ -169,6 +169,7 @@ obj-$(CONFIG_SENSORS_WM831X)        +=
> wm831x-hwmon.o
> >>  obj-$(CONFIG_SENSORS_WM8350)   += wm8350-hwmon.o
> >>  obj-$(CONFIG_SENSORS_XGENE)    += xgene-hwmon.o
> >>
> >> +obj-$(CONFIG_SENSORS_PPC_OCC)  += occ/
> >>  obj-$(CONFIG_PMBUS)            += pmbus/
> >>
> >>  ccflags-$(CONFIG_HWMON_DEBUG_CHIP) := -DDEBUG
> >> diff --git a/drivers/hwmon/occ/Kconfig b/drivers/hwmon/occ/Kconfig
> >> new file mode 100644
> >> index 0000000..cdb64a7
> >> --- /dev/null
> >> +++ b/drivers/hwmon/occ/Kconfig
> >> @@ -0,0 +1,15 @@
> >> +#
> >> +# On Chip Controller configuration
> >> +#
> >> +
> >> +menuconfig SENSORS_PPC_OCC
> >> +       bool "PPC On-Chip Controller"
> >> +       help
> >> +         If you say yes here you get support to monitor Power CPU
> >> +         sensors via the On-Chip Controller (OCC).
> >> +
> >> +         Generally this is used by management controllers such as a BMC
> >> +         on an OpenPower system.
> >> +
> >> +         This driver can also be built as a module. If so, the module
> >> +         will be called occ.
> >> diff --git a/drivers/hwmon/occ/Makefile b/drivers/hwmon/occ/Makefile
> >> new file mode 100644
> >> index 0000000..93cb52f
> >> --- /dev/null
> >> +++ b/drivers/hwmon/occ/Makefile
> >> @@ -0,0 +1 @@
> >> +obj-$(CONFIG_SENSORS_PPC_OCC) += occ.o
> >> diff --git a/drivers/hwmon/occ/occ.c b/drivers/hwmon/occ/occ.c
> >> new file mode 100644
> >> index 0000000..3089762
> >> --- /dev/null
> >> +++ b/drivers/hwmon/occ/occ.c
> >> @@ -0,0 +1,522 @@
> >> +/*
> >> + * occ.c - OCC hwmon driver
> >> + *
> >> + * This file contains the methods and data structures for the OCC hwmon
> >> driver.
> >> + *
> >> + * Copyright 2016 IBM Corp.
> >> + *
> >> + * This program is free software; you can redistribute it and/or modify
> >> + * it under the terms of the GNU General Public License as published by
> >> + * the Free Software Foundation; either version 2 of the License, or
> >> + * (at your option) any later version.
> >> + *
> >> + * This program is distributed in the hope that it will be useful,
> >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> >> + * GNU General Public License for more details.
> >> + */
> >> +
> >> +#include <asm/unaligned.h>
> >> +#include <linux/delay.h>
> >> +#include <linux/device.h>
> >> +#include <linux/err.h>
> >> +#include <linux/init.h>
> >> +#include <linux/jiffies.h>
> >> +#include <linux/kernel.h>
> >> +#include <linux/module.h>
> >> +#include <linux/mutex.h>
> >> +#include <linux/slab.h>
> >> +#include "occ.h"
> >> +
> >> +#define OCC_DATA_MAX           4096
> >> +#define OCC_BMC_TIMEOUT_MS     20000
> >> +
> >> +/* To generate attn to OCC */
> >> +#define ATTN_DATA              0x0006B035
> >> +
> >> +/* For BMC to read/write SRAM */
> >> +#define OCB_ADDRESS            0x0006B070
> >> +#define OCB_DATA               0x0006B075
> >> +#define OCB_STATUS_CONTROL_AND 0x0006B072
> >> +#define OCB_STATUS_CONTROL_OR  0x0006B073
> >> +
> >> +/* To init OCB */
> >> +#define OCB_AND_INIT0          0xFBFFFFFF
> >> +#define OCB_AND_INIT1          0xFFFFFFFF
> >> +#define OCB_OR_INIT0           0x08000000
> >> +#define OCB_OR_INIT1           0x00000000
> >> +
> >> +/* To generate attention on OCC */
> >> +#define ATTN0                  0x01010000
> >> +#define ATTN1                  0x00000000
> >> +
> >> +/* OCC return status */
> >> +#define RESP_RETURN_CMD_IN_PRG 0xFF
> >> +#define RESP_RETURN_SUCCESS    0
> >> +#define RESP_RETURN_CMD_INVAL  0x11
> >> +#define RESP_RETURN_CMD_LEN    0x12
> >> +#define RESP_RETURN_DATA_INVAL 0x13
> >> +#define RESP_RETURN_CHKSUM     0x14
> >> +#define RESP_RETURN_OCC_ERR    0x15
> >> +#define RESP_RETURN_STATE      0x16
> >> +
> >> +/* time interval to retry on "command in progress" return status */
> >> +#define CMD_IN_PRG_INT_MS      100
> >> +#define CMD_IN_PRG_RETRIES     (OCC_BMC_TIMEOUT_MS / CMD_IN_PRG_INT_MS)
> >> +
> >> +/* OCC command definitions */
> >> +#define OCC_POLL               0
> >> +#define OCC_SET_USER_POWR_CAP  0x22
> >> +
> >> +/* OCC poll command data */
> >> +#define OCC_POLL_STAT_SENSOR   0x10
> >> +
> >> +/* OCC response data offsets */
> >> +#define RESP_RETURN_STATUS     2
> >> +#define RESP_DATA_LENGTH       3
> >> +#define RESP_HEADER_OFFSET     5
> >> +#define SENSOR_STR_OFFSET      37
> >> +#define SENSOR_BLOCK_NUM_OFFSET        43
> >> +#define SENSOR_BLOCK_OFFSET    45
> >> +
> >> +/* occ_poll_header
> >> + * structure to match the raw occ poll response data
> >> + */
> >> +struct occ_poll_header {
> >> +       u8 status;
> >> +       u8 ext_status;
> >> +       u8 occs_present;
> >> +       u8 config;
> >> +       u8 occ_state;
> >> +       u8 mode;
> >> +       u8 ips_status;
> >> +       u8 error_log_id;
> >> +       u32 error_log_addr_start;
> >> +       u16 error_log_length;
> >> +       u8 reserved2;
> >> +       u8 reserved3;
> >> +       u8 occ_code_level[16];
> >> +       u8 sensor_eye_catcher[6];
> >> +       u8 sensor_block_num;
> >> +       u8 sensor_data_version;
> >> +} __attribute__((packed, aligned(4)));
> >> +
> >> +struct occ_response {
> >> +       struct occ_poll_header header;
> >> +       struct occ_blocks data;
> >> +};
> >> +
> >> +struct occ {
> >> +       struct device *dev;
> >> +       void *bus;
> >> +       struct occ_bus_ops bus_ops;
> >> +       struct occ_ops ops;
> >> +       struct occ_config config;
> >> +       unsigned long update_interval;
> >> +       unsigned long last_updated;
> >> +       struct mutex update_lock;
> >> +       struct occ_response response;
> >> +       bool valid;
> >> +};
> >> +
> >> +static void deinit_occ_resp_buf(struct occ_response *resp)
> >> +{
> >> +       int i;
> >> +
> >> +       if (!resp)
> >> +               return;
> >> +
> >
> >
> > This creates the impression that resp can ever be NULL, which is not the
> > case.
> 
> Agreed. This might go away anyway if I follow your suggestions below
> about memory management.
> 
> >
> >> +       if (!resp->data.blocks)
> >> +               return;
> >> +
> >> +       for (i = 0; i < resp->header.sensor_block_num; ++i)
> >> +               kfree(resp->data.blocks[i].sensors);
> >> +
> >> +       kfree(resp->data.blocks);
> >> +/sensor_type_s
> >>
> >> +       memset(resp, 0, sizeof(struct occ_response));
> >> +
> >> +       for (i = 0; i < MAX_OCC_SENSOR_TYPE; ++i)
> >> +               resp->data.sensor_block_id[i] = -1;
> >> +}
> >> +
> >> +static void *occ_get_sensor_by_type(struct occ_response *resp,
> >> +                                   enum sensor_type t)
> >> +{
> >> +       if (!resp->data.blocks)
> >> +               return NULL;
> >> +
> >> +       if (resp->data.sensor_block_id[t] == -1)
> >> +               return NULL;
> >> +
> >> +       return resp->data.blocks[resp->data.sensor_block_id[t]].sensors;
> >> +}
> >> +
> >> +static int occ_check_sensor(struct occ *driver, u8 sensor_length,
> >> +                           u8 sensor_num, enum sensor_type t, int
> block)
> >> +{
> >> +       void *sensor;
> >> +       int type_block_id;
> >> +       struct occ_response *resp = &driver->response;
> >> +
> >> +       sensor = occ_get_sensor_by_type(resp, t);
> >> +
> >> +       /* empty sensor block, release older sensor data */
> >> +       if (sensor_num == 0 || sensor_length == 0) {
> >> +               kfree(sensor);
> >> +               dev_err(driver->dev, "no sensor blocks available\n");
> >> +               return -ENODATA;
> >> +       }
> >> +
> >> +       type_block_id = resp->data.sensor_block_id[t];
> >> +       if (!sensor || sensor_num !=
> >> +           resp->data.blocks[type_block_id].header.sensor_num) {
> >> +               kfree(sensor);
> >> +               resp->data.blocks[block].sensors =
> >> +                       driver->ops.alloc_sensor(t, sensor_num);
> >> +               if (!resp->data.blocks[block].sensors)
> >> +                       return -ENOMEM;
> >> +       }
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static int parse_occ_response(struct occ *driver, u8 *data,
> >> +                             struct occ_response *resp)
> >> +{
> >> +       int b;
> >> +       int s;
> >> +       int rc;
> >> +       int offset = SENSOR_BLOCK_OFFSET;
> >> +       int sensor_type;
> >> +       u8 sensor_block_num;
> >> +       char sensor_type_string[5] = { 0 };
> >
> >
> > The only purpose of this variable seems to be to zero-terminate it to be
> > able
> > to print it. Why not use length-limited print functions instead ?
> 
> Is there such a function to length limit to dev_err or dev_dbg?
> Otherwise I have to snprintf or strncpy into a string to pass anyway.
> I can drop the dev_dbg but I would like to print out the sensor string
> if it doesn't match any of the expected ones.
> 
%*s or %-*s ?

> >
> >> +       struct sensor_data_block_header *block;
> >> +       struct device *dev = driver->dev;
> >> +
> >> +       /* check if the data is valid */
> >> +       if (strncmp(&data[SENSOR_STR_OFFSET], "SENSOR", 6) != 0) {
> >> +               dev_err(dev, "no SENSOR string in response\n");
> >
> >
> > Are those messages really necessary ? That can create a lot of logging
> noise
> > if the occ responds with bad data.
> 
> I will audit these, but I think it's limited to one error message
> logged in any one function in case of error. Is that acceptable?
> Otherwise it may be hard to tell where the error occurred.
> 
> >
> >> +               rc = -ENODATA;
> >> +               goto err;
> >> +       }
> >> +
> >> +       sensor_block_num = data[SENSOR_BLOCK_NUM_OFFSET];
> >
> >
> > There is a lot of trust in assuming that this data was actually received.
> > At the same time, there is a lot of error checking. Why check if the
> > information in this field is valid if you don't check if it was
> > received in the first place ?
> 
> If we get to parse_occ_response, we know we got some data back from
> the OCC (see occ_get_all). Here we are really checking the response is
> a valid one, which I think makes sense in the parsing function.
> 
Yes, but you don't check the length of the data vs. the length indicated
in the header.

> >
> >> +       if (sensor_block_num == 0) {
> >> +               dev_err(dev, "no sensor blocks available\n");
> >> +               rc = -ENODATA;
> >> +               goto err;
> >> +       }
> >> +
> >> +       /* if number of sensor block has changed, re-malloc */
> >> +       if (sensor_block_num != resp->header.sensor_block_num) {
> >> +               deinit_occ_resp_buf(resp);
> >> +               resp->data.blocks = kcalloc(sensor_block_num,
> >> +                                           sizeof(struct
> >> sensor_data_block),
> >> +                                           GFP_KERNEL);
> >> +               if (!resp->data.blocks)
> >> +                       return -ENOMEM;
> >
> >
> > Why not just allocate the maximum number of sensors once ? That might
> waste
> > a bit of memory, but it would make the code much less error prone. We
> know
> > that
> > there will never be more sensors than the number fitting into 4k of
> memory,
> > so the "waste" would not really be that much.
> 
> Fair point. I'll do that.
> 
> >
> >
> >> +       }
> >> +
> >> +       memcpy(&resp->header, &data[RESP_HEADER_OFFSET],
> >> +              sizeof(struct occ_poll_header));
> >> +       resp->header.error_log_addr_start =
> >> +               be32_to_cpu(resp->header.error_log_addr_start);
> >> +       resp->header.error_log_length =
> >> +               be16_to_cpu(resp->header.error_log_length);
> >> +
> >> +       dev_dbg(dev, "Reading %d sensor blocks\n",
> >> +               resp->header.sensor_block_num);
> >> +       for (b = 0; b < sensor_block_num; b++) {
> >> +               block = (struct sensor_data_block_header *)&data
> [offset];
> >> +               /* copy to a null terminated string */
> >> +               strncpy(sensor_type_string, block->sensor_type, 4);
> >> +               offset += 8;
> >> +
> >> +               dev_dbg(dev, "sensor block[%d]: type: %s, sensor_num:
> >> %d\n", b,
> >> +                       sensor_type_string, block->sensor_num);
> >> +
> >> +               if (strncmp(block->sensor_type, "FREQ", 4) == 0)
> >> +                       sensor_type = FREQ;
> >> +               else if (strncmp(block->sensor_type, "TEMP", 4) == 0)
> >> +                       sensor_type = TEMP;
> >> +               else if (strncmp(block->sensor_type, "POWR", 4) == 0)
> >> +                       sensor_type = POWER;
> >> +               else if (strncmp(block->sensor_type, "CAPS", 4) == 0)
> >> +                       sensor_type = CAPS;
> >> +               else {
> >> +                       dev_err(dev, "sensor type not supported %s\n",
> >> +                               sensor_type_string);
> >> +                       continue;
> >> +               }
> >> +
> >> +               rc = occ_check_sensor(driver, block->sensor_length,
> >> +                                     block->sensor_num, sensor_type,
> b);
> >> +               if (rc == -ENOMEM)
> >> +                       goto err;
> >> +               else if (rc)
> >> +                       continue;
> >> +
> >> +               resp->data.sensor_block_id[sensor_type] = b;
> >> +               for (s = 0; s < block->sensor_num; s++) {
> >> +                       driver->ops.parse_sensor(data,
> >> +
> >> resp->data.blocks[b].sensors,
> >> +                                                sensor_type, offset,
> s);
> >> +                       offset += block->sensor_length;
> >> +               }
> >> +
> >> +               /* copy block data over to response pointer */
> >> +               resp->data.blocks[b].header = *block;
> >> +       }
> >> +
> >> +       return 0;
> >> +err:
> >> +       deinit_occ_resp_buf(resp);
> >> +       return rc;
> >> +}
> >> +
> >> +static u8 occ_send_cmd(struct occ *driver, u8 seq, u8 type, u16 length,
> >> +                      const u8 *data, u8 *resp)
> >> +{
> >> +       u32 cmd1, cmd2;
> >> +       u16 checksum = 0;
> >> +       u16 length_le = cpu_to_le16(length);
> >> +       bool retry = 0;
> >> +       int i, rc, tries = 0;
> >> +
> >> +       cmd1 = (seq << 24) | (type << 16) | length_le;
> >> +       memcpy(&cmd2, data, length);
> >> +       cmd2 <<= ((4 - length) * 8);
> >> +
> >> +       /* checksum: sum of every bytes of cmd1, cmd2 */
> >> +       for (i = 0; i < 4; i++) {
> >> +               checksum += (cmd1 >> (i * 8)) & 0xFF;
> >> +               checksum += (cmd2 >> (i * 8)) & 0xFF;
> >> +       }
> >> +
> >> +       cmd2 |= checksum << ((2 - length) * 8);
> >> +
> >> +       /* Init OCB */
> >> +       rc = driver->bus_ops.putscom(driver->bus, OCB_STATUS_CONTROL_OR,
> >> +                                    OCB_OR_INIT0, OCB_OR_INIT1);
> >> +       if (rc)
> >> +               goto err;
> >> +
> >> +       rc = driver->bus_ops.putscom(driver->bus,
> OCB_STATUS_CONTROL_AND,
> >> +                                    OCB_AND_INIT0, OCB_AND_INIT1);
> >> +       if (rc)
> >> +               goto err;
> >> +
> >> +       /* Send command, 2nd half of the 64-bit addr is unused (write 0)
> >> */
> >> +       rc = driver->bus_ops.putscom(driver->bus, OCB_ADDRESS,
> >> +                                    driver->config.command_addr, 0);
> >> +       if (rc)
> >> +               goto err;
> >> +
> >> +       rc = driver->bus_ops.putscom(driver->bus, OCB_DATA, cmd1, cmd2);
> >> +       if (rc)
> >> +               goto err;
> >> +
> >> +       /* Trigger attention */
> >> +       rc = driver->bus_ops.putscom(driver->bus, ATTN_DATA, ATTN0,
> >> ATTN1);
> >> +       if (rc)
> >> +               goto err;
> >> +
> >> +       /* Get response data */
> >> +       rc = driver->bus_ops.putscom(driver->bus, OCB_ADDRESS,
> >> +                                    driver->config.response_addr, 0);
> >> +       if (rc)
> >> +               goto err;
> >> +
> >> +       do {
> >> +               if (retry) {
> >> +                       set_current_state(TASK_INTERRUPTIBLE);
> >> +
> >> schedule_timeout(msecs_to_jiffies(CMD_IN_PRG_INT_MS));
> >> +               }
> >> +
> >
> > Isn't there a better way to do this ? What exactly is interrupted ? The
> > getscom function ? If so, shouldn't the timeout be handled there ?
> 
> There shouldn't be any interrupt. I set TASK_INTERRUPTIBLE because it
> doesn't really matter if it's interrupted or not. The purpose of this
> loop is to retry if we get the "command in progress" status from the
> OCC. It's higher level than the getscom function, so I think the loop
> is appropriate here.
> 
This is quite unusual. Why is this needed here but not elsewhere
in the kernel ? Normally the called function would time out and return
an appropriate error.

> >
> >> +               rc = driver->bus_ops.getscom(driver->bus, OCB_DATA,
> >> +                                            (u64 *)resp);
> >> +               if (rc)
> >> +                       goto err;
> >> +
> >> +               /* retry if we get "command in progress" return status
> */
> >> +               retry = (resp[RESP_RETURN_STATUS] ==
> >> RESP_RETURN_CMD_IN_PRG) &&
> >> +                       (tries++ < CMD_IN_PRG_RETRIES);
> >
> >
> > There are some unnecessary () in this expression.
> >
> >
> >> +       } while (retry);
> >> +
> >> +       switch (resp[RESP_RETURN_STATUS]) {
> >> +       case RESP_RETURN_CMD_IN_PRG:
> >> +               rc = -EALREADY;
> >> +               break;
> >> +       case RESP_RETURN_SUCCESS:
> >> +               rc = 0;
> >> +               break;
> >> +       case RESP_RETURN_CMD_INVAL:
> >> +       case RESP_RETURN_CMD_LEN:
> >> +       case RESP_RETURN_DATA_INVAL:
> >> +       case RESP_RETURN_CHKSUM:
> >> +               rc = -EINVAL;
> >> +               break;
> >> +       case RESP_RETURN_OCC_ERR:
> >> +               rc = -EREMOTE;
> >> +               break;
> >> +       default:
> >> +               rc = -EFAULT;
> >> +       }
> >> +
> >> +       return rc;
> >> +
> >> +err:
> >> +       dev_err(driver->dev, "scom op failed rc:%d\n", rc);
> >
> >
> > Some of the errors result in an error message, some don't. What is
> > the guiding principle ? Even if there is an error message, it doesn't
> report
> > what function caused it, which makes it as good as no error message.
> > Can this be dropped ?
> 
> resp[RESP_RETURN_STATUS] is the status reported on the OCC, these
> aren't necessarily errors, though most are. This is translating an OCC
> status code to an error for occ_get_all to pick up. It cannot be
> dropped, we need to know if the occ poll was successful. I'm not sure
> what you mean by reporting the function? occ_get_all will fail out if

There are several function returns which all end up here. You don't know
which one actually failed.

> we report the error here. If it's the scom op that failed we will have
> the dev_err message.
> 
But which scom operation ? You mean it is important to report that some
operation failed, but not which one ? Ok, I'll accept that, it just seems
odd.

> >
> >> +       return rc;
> >> +}
> >> +
> >> +static int occ_get_all(struct occ *driver)
> >> +{
> >> +       int i = 0, rc;
> >> +       u8 *occ_data;
> >> +       u16 num_bytes;
> >> +       const u8 poll_cmd_data = OCC_POLL_STAT_SENSOR;
> >> +       struct device *dev = driver->dev;
> >> +       struct occ_response *resp = &driver->response;
> >> +
> >> +       occ_data = devm_kzalloc(dev, OCC_DATA_MAX, GFP_KERNEL);
> >
> >
> > I am a bot lost here. What is the purpose of using a devm function ?
> >
> > Either case, you might want to allocate the memory once and just keep it
> > allocated.
> > Allocating a 4k buffer and freeing it each time data is read from the occ
> > seems
> > to be wasteful and not really worth it.
> 
> Agreed.
> 
> >
> >> +       if (!occ_data)
> >> +               return -ENOMEM;
> >> +
> >> +       rc = occ_send_cmd(driver, 0, OCC_POLL, 1, &poll_cmd_data,
> >> occ_data);
> >> +       if (rc) {
> >> +               dev_err(dev, "OCC poll failed: %d\n", rc);
> >> +               goto out;
> >> +       }
> >> +
> >> +       num_bytes = get_unaligned((u16 *)&occ_data[RESP_DATA_LENGTH]);
> >> +       num_bytes = be16_to_cpu(num_bytes);
> >
> >
> > What data is in big endian, and what data is in little endian ?
> >
> > Looks like everything is big endian except for the length in the send
> > command.
> > Is that correct ? If so, an explanation would be useful, because the
> logic
> > isn't entirely clear.
> 
> I'll add some comments.
> 
> >
> >> +       dev_dbg(dev, "OCC data length: %d\n", num_bytes);
> >> +
> >> +       if (num_bytes > OCC_DATA_MAX) {
> >> +               dev_err(dev, "OCC data length must be < 4KB\n");
> >> +               rc = -EINVAL;
> >> +               goto out;
> >> +       }
> >> +
> >> +       if (num_bytes <= 0) {
> >
> >
> > This can never be < 0.
> 
> Good point.
> 
> >
> >> +               dev_err(dev, "OCC data length is zero\n");
> >> +               rc = -EINVAL;
> >> +               goto out;
> >> +       }
> >> +
> >> +       /* read remaining data */
> >> +       for (i = 8; i < num_bytes + 8; i += 8) {
> >> +               rc = driver->bus_ops.getscom(driver->bus, OCB_DATA,
> >> +                                            (u64 *)&occ_data[i]);
> >> +               if (rc) {
> >> +                       dev_err(dev, "scom op failed rc:%d\n", rc);
> >> +                       goto out;
> >> +               }
> >> +       }
> >> +
> >> +       /* don't need more sanity checks; buffer is alloc'd for max
> >> response
> >> +        * size so we just check for valid data in parse_occ_response
> >> +        */
> >
> > Yes, but as mentioned above you don't check in that function if the data
> > was actually received.
> 
> If we don't receive data, the data length will be 0 or the low level
> getscom will fail. So we know we have data here.
> 
Ok. However, since you don't pass num_bytes to the parse function,
there is no verification that num_bytes actually matches what is in the packet.
The rest of the header could indicate that there is 4k of data, but num_bytes
reports, say, the minimum size. In that case, parse_occ_response() would end
up parsing a stale buffer.

> >
> >> +       rc = parse_occ_response(driver, occ_data, resp);
> >> +
> >> +out:
> >> +       devm_kfree(dev, occ_data);
> >> +       return rc;
> >> +}
> >> +
> >> +int occ_update_device(struct occ *driver)
> >> +{
> >> +       int rc = 0;
> >> +
> >> +       mutex_lock(&driver->update_lock);
> >> +
> >> +       if (time_after(jiffies, driver->last_updated +
> >> driver->update_interval)
> >> +           || !driver->valid) {
> >> +               driver->valid = 1;
> >
> >
> > valid is bool.
> >
> >> +
> >> +               rc = occ_get_all(driver);
> >> +               if (rc)
> >> +                       driver->valid = 0;
> >
> >
> > valid is bool.
> 
> Good point.
> 
> >
> >> +
> >> +               driver->last_updated = jiffies;
> >> +       }
> >> +
> >> +       mutex_unlock(&driver->update_lock);
> >> +
> >> +       return rc;
> >> +}
> >> +EXPORT_SYMBOL(occ_update_device);
> >> +
> >> +void *occ_get_sensor(struct occ *driver, int sensor_type)
> >> +{
> >> +       int rc;
> >> +
> >> +       /* occ_update_device locks the update lock */
> >> +       rc = occ_update_device(driver);
> >> +       if (rc) {
> >> +               dev_err(driver->dev, "cannot get occ sensor data: %d\n",
> >> +                       rc);
> >
> >
> > Have you counted the number of error messages reported if anything goes
> > wrong.
> > This driver is quite noisy. I won't force you to drop the messages, but
> it
> > seems
> > to me that if anything goes wrong, the kernel log will be clogged with
> > messages
> > just from this driver.
> 
> I'll audit these.
> 
> >
> >
> >> +               return NULL;
> >> +       }
> >> +
> >> +       return occ_get_sensor_by_type(&driver->response, sensor_type);
> >> +}
> >> +EXPORT_SYMBOL(occ_get_sensor);
> >> +
> >> +int occ_get_sensor_value(struct occ *occ, int sensor_type, int
> >> sensor_num,
> >> +                        u32 hwmon, long *val)
> >> +{
> >> +       return occ->ops.get_sensor(occ, sensor_type, sensor_num, hwmon,
> >> val);
> >> +}
> >> +EXPORT_SYMBOL(occ_get_sensor_value);
> >> +
> >> +void occ_get_response_blocks(struct occ *occ, struct occ_blocks
> **blocks)
> >> +{
> >> +       *blocks = &occ->response.data;
> >> +}
> >> +EXPORT_SYMBOL(occ_get_response_blocks);
> >> +
> >> +void occ_set_update_interval(struct occ *occ, unsigned long interval)
> >> +{
> >> +       occ->update_interval = msecs_to_jiffies(interval);
> >> +}
> >> +EXPORT_SYMBOL(occ_set_update_interval);
> >> +
> >> +int occ_set_user_powercap(struct occ *occ, u16 cap)
> >> +{
> >> +       u8 resp[8];
> >> +
> >> +       cap = cpu_to_be16(cap);
> >> +
> >> +       return occ_send_cmd(occ, 0, OCC_SET_USER_POWR_CAP, 2, (const u8
> >> *)&cap,
> >> +                           resp);
> >> +}
> >> +EXPORT_SYMBOL(occ_set_user_powercap);
> >> +
> >> +struct occ *occ_start(struct device *dev, void *bus,
> >> +                     struct occ_bus_ops *bus_ops, const struct occ_ops
> >> *ops,
> >> +                     const struct occ_config *config)
> >> +{
> >> +       struct occ *driver = devm_kzalloc(dev, sizeof(struct occ),
> >> GFP_KERNEL);
> >> +
> >> +       if (!driver)
> >> +               return ERR_PTR(-ENOMEM);
> >> +
> >> +       driver->dev = dev;
> >> +       driver->bus = bus;
> >> +       driver->bus_ops = *bus_ops;
> >> +       driver->ops = *ops;
> >> +       driver->config = *config;
> >> +
> >> +       driver->update_interval = HZ;
> >
> >
> > The update interval is only supposed to be configurable if it can be
> written
> > into the hardware. Otherwise it is really up to user space to decide how
> > often
> > it wants to poll the data, not up to the kernel.
> >
> > I don't see a function to send the update interval to the occ. As such,
> it
> > should
> > not be configurable but a constant.
> 
> I don't quite follow. Right now, the driver maximum polling rate is
> configurable by userspace (via hwmon sysfs attribute). If you mean
> that user space should control that rate just by how often users read
> the attributes, I'm not sure that will work as there are a large
> number of attributes that will all try and trigger an occ poll when
> read. Besides, different users don't want to communicate about when
> they last polled. If the rate is constant, if may be too slow or too
> fast depending on the system and needs of the users. Why can't the
> polling rate be configurable? To user space, the update interval works
> the same if it's driver or hardware.
> 

The update_interval attribute is only supposed to exist if writing it
results in writing a value into a chip register. It is supposed to set
the _chip_ update interval, not the kernel update interval. If you want
to limit the rate of chip accesses, you can do it by using a constant
in the driver, just like other drivers do it.

This is similar to limit registers. If the chip does not support limit
registers, we don't make up "soft" limits either, but don't support
the respective attributes.

Thanks,
Guenter

^ permalink raw reply

* Re: [PATCH 11/22] ARM: dts: add top-level DT bindings for Cortina Gemini
From: Rob Herring @ 2017-01-23 20:21 UTC (permalink / raw)
  To: Linus Walleij
  Cc: linux-arm-kernel, Hans Ulli Kroll, Florian Fainelli, Janos Laube,
	Paulius Zaleckas, openwrt-devel, Arnd Bergmann, linux-kernel,
	devicetree
In-Reply-To: <20170122122219.10611-1-linus.walleij@linaro.org>

On Sun, Jan 22, 2017 at 01:22:19PM +0100, Linus Walleij wrote:
> This adds the top level SoC bindings for Cortina systems Gemini
> platforms.
> 
> Cc: Janos Laube <janos.dev@gmail.com>
> Cc: Paulius Zaleckas <paulius.zaleckas@gmail.com>
> Cc: Hans Ulli Kroll <ulli.kroll@googlemail.com>
> Cc: Florian Fainelli <f.fainelli@gmail.com>
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
>  Documentation/devicetree/bindings/arm/gemini.txt | 58 ++++++++++++++++++++++++
>  1 file changed, 58 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/gemini.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/gemini.txt b/Documentation/devicetree/bindings/arm/gemini.txt
> new file mode 100644
> index 000000000000..28ce7db0cfd3
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/gemini.txt
> @@ -0,0 +1,58 @@
> +Cortina systems Gemini platforms
> +
> +The gemini SoC is an ARMv4 SoC from Cortina systems used for NAS
> +and similar usecases.
> +
> +Required properties (in root node):
> +	compatible = "cortina,gemini";
> +
> +Required nodes:
> +
> +- syscon: the root node must have a system controller node pointing to the
> +  global control registers, with the compatible string
> +  "cortina,gemini-syscon", "syscon";
> +
> +- timer: the root node must have a timer node pointing to the SoC timer
> +  block, with the compatible string "cortina,gemini-timer"
> +  See: clocksource/cortina,gemini-timer.txt
> +
> +- intcon: the root node must have an interrupt controller node pointing to

intcon is just a source label and not meaningful for the binding.

> +  the SoC interrupt controller block, with the compatible string
> +  "cortina,gemini-interrupt-controller"
> +  See interrupt-controller/cortina,gemini-interrupt-controller.txt
> +
> +Example:
> +
> +/ {
> +	interrupt-parent = <&intcon>;
> +
> +	syscon: syscon@40000000 {

This chip has no internal bus? Put all these nodes under a bus.

> +		compatible = "cortina,gemini-syscon", "syscon";
> +		reg = <0x40000000 0x1000>;
> +	};
> +
> +	timer@43000000 {
> +		compatible = "cortina,gemini-timer";
> +		reg = <0x43000000 0x1000>;
> +		interrupt-parent = <&intcon>;
> +		interrupts = <14 IRQ_TYPE_EDGE_RISING>, /* Timer 1 */
> +			   <15 IRQ_TYPE_EDGE_RISING>, /* Timer 2 */
> +			   <16 IRQ_TYPE_EDGE_RISING>; /* Timer 3 */
> +		syscon = <&syscon>;
> +	};
> +
> +	uart0: serial@42000000 {
> +		compatible = "ns16550a";
> +		reg = <0x42000000 0x100>;
> +		clock-frequency = <48000000>;
> +		interrupts = <18 IRQ_TYPE_LEVEL_HIGH>;
> +		reg-shift = <2>;
> +	};
> +
> +	intcon: interrupt-controller@48000000 {
> +		compatible = "cortina,gemini-interrupt-controller";
> +		reg = <0x48000000 0x1000>;
> +		interrupt-controller;
> +		#interrupt-cells = <2>;
> +	};
> +};
> -- 
> 2.9.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH] Documentation: net: phy: improve explanation when to specify the PHY ID
From: Rob Herring @ 2017-01-23 20:32 UTC (permalink / raw)
  To: Martin Blumenstingl
  Cc: andrew-g2DYL2Zd6BY, devicetree-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	f.fainelli-Re5JQEeQqe8AvxtiuMwx3w, mark.rutland-5wv7dgnIgG8
In-Reply-To: <20170122164132.13967-1-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

On Sun, Jan 22, 2017 at 05:41:32PM +0100, Martin Blumenstingl wrote:
> The old description basically read like "ethernet-phy-idAAAA.BBBB" can
> be specified when you know the actual PHY ID. However, specifying this
> has a side-effect: it forces Linux to bind to a certain PHY driver (the
> one that matches the ID given in the compatible string), ignoring the ID
> which is reported by the actual PHY.
> Whenever a device is shipped with (multiple) different PHYs during it's
> production lifetime then explicitly specifying
> "ethernet-phy-idAAAA.BBBB" could break certain revisions of that device.
> 
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
> ---
> Thanks to Andrew Lunn for pointing the documentation issue out to me in:
> http://lists.infradead.org/pipermail/linux-amlogic/2017-January/002141.html
> 
> 
>  Documentation/devicetree/bindings/net/phy.txt | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
--
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 7/9] of: Add vendor prefix for Multi-Inno
From: Rob Herring @ 2017-01-23 20:33 UTC (permalink / raw)
  To: Noralf Trønnes
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170122181117.8210-8-noralf-L59+Z2yzLopAfugRpC6u6w@public.gmane.org>

On Sun, Jan 22, 2017 at 07:11:15PM +0100, Noralf Trønnes wrote:
> Multi-Inno Technology Co.,Ltd is a Hong Kong based company offering
> LCD, LCD module products and complete panel solutions.
> 
> Signed-off-by: Noralf Trønnes <noralf-L59+Z2yzLopAfugRpC6u6w@public.gmane.org>
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
>  1 file changed, 1 insertion(+)

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
--
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] Documentation: net: phy: improve explanation when to specify the PHY ID
From: Florian Fainelli @ 2017-01-23 20:33 UTC (permalink / raw)
  To: Martin Blumenstingl, andrew-g2DYL2Zd6BY,
	devicetree-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
	davem-fT/PcQaiUtIeIZ0/mPfg9Q
  Cc: mark.rutland-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <20170122164132.13967-1-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

On 01/22/2017 08:41 AM, Martin Blumenstingl wrote:
> The old description basically read like "ethernet-phy-idAAAA.BBBB" can
> be specified when you know the actual PHY ID. However, specifying this
> has a side-effect: it forces Linux to bind to a certain PHY driver (the
> one that matches the ID given in the compatible string), ignoring the ID
> which is reported by the actual PHY.
> Whenever a device is shipped with (multiple) different PHYs during it's
> production lifetime then explicitly specifying
> "ethernet-phy-idAAAA.BBBB" could break certain revisions of that device.
> 
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

Reviewed-by: Florian Fainelli <f.fainelli-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
-- 
Florian
--
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/2] iio: adc: Add Renesas GyroADC bindings
From: Geert Uytterhoeven @ 2017-01-23 20:41 UTC (permalink / raw)
  To: Marek Vasut
  Cc: Rob Herring, linux-iio-u79uwXL29TY76Z2rM5mHXA, Geert Uytterhoeven,
	Simon Horman, Jonathan Cameron, Linux-Renesas, Wolfram Sang,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <63b3660b-6ce0-134c-ef79-c06430c735c5-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Hi Marek,

On Mon, Jan 23, 2017 at 8:56 PM, Marek Vasut <marek.vasut-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> On 01/23/2017 06:08 PM, Rob Herring wrote:
>> On Sat, Jan 21, 2017 at 03:42:11PM +0100, Marek Vasut wrote:
>>> new file mode 100644
>>> index 000000000000..081947367135
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/iio/adc/renesas,gyroadc.txt

>>> +Required properties:
>>> +- compatible:       Should be "renesas,<chip>-gyroadc", "renesas,rcar-gyroadc".
>>
>> Need to enumerate <chip>.
>
> It's enumerated below , the only special-case we handle at this point is
> the r8a7792 , which has extra interrupt block which we don't use anyway,
> but the driver disables those interrupts.

It is not enumerated below. You just give an example for r8a7791.

Please list all supported/tested compatible values, so checkpatch
can validate compatible values in DTS patches adding GyroADC device
nodes.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
--
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 8/9] dt-bindings: Add Multi-Inno MI0283QT binding
From: Rob Herring @ 2017-01-23 20:43 UTC (permalink / raw)
  To: Noralf Trønnes; +Cc: thomas.petazzoni, devicetree, linux-kernel, dri-devel
In-Reply-To: <20170122181117.8210-9-noralf@tronnes.org>

On Sun, Jan 22, 2017 at 07:11:16PM +0100, Noralf Trønnes wrote:
> Add device-tree binding documentation for the MI0283QT display panel.
> 
> Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
> ---
> 
> Datasheet: https://cdn-shop.adafruit.com/datasheets/MI0283QT-11+V1.1.PDF
> 
> 
>  .../bindings/display/multi-inno,mi0283qt.txt       | 27 ++++++++++++++++++++++
>  1 file changed, 27 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/multi-inno,mi0283qt.txt
> 
> diff --git a/Documentation/devicetree/bindings/display/multi-inno,mi0283qt.txt b/Documentation/devicetree/bindings/display/multi-inno,mi0283qt.txt
> new file mode 100644
> index 0000000..eed48c3
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/multi-inno,mi0283qt.txt
> @@ -0,0 +1,27 @@
> +Multi-Inno MI0283QT display panel
> +
> +Required properties:
> +- compatible:	"multi-inno,mi0283qt".
> +
> +The node for this driver must be a child node of a SPI controller, hence
> +all mandatory properties described in ../spi/spi-bus.txt must be specified.
> +
> +Optional properties:
> +- dc-gpios:	D/C pin. The presence/absence of this GPIO determines
> +		the panel interface mode (IM[3:0] pins):
> +		- present: IM=x110 4-wire 8-bit data serial interface
> +		- absent:  IM=x101 3-wire 9-bit data serial interface
> +- reset-gpios:	Reset pin
> +- power-supply:	A regulator node for the supply voltage.
> +- backlight:	phandle of the backlight device attached to the panel
> +- rotation:	panel rotation in degrees counter clockwise (0,90,180,270)

This isn't a standard property, but probably should be. Please document 
in a common spot.

> +
> +Example:
> +	mi0283qt@0{
> +		compatible = "multi-inno,mi0283qt";
> +		reg = <0>;
> +		spi-max-frequency = <32000000>;
> +		rotation = <90>;
> +		dc-gpios = <&gpio 25 0>;
> +		backlight = <&backlight>;
> +	};
> --
> 2.10.2
> 
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply

* Re: [PATCH v4 1/3] Documentation: dt-bindings: add the Amlogic Meson SAR ADC documentation
From: Rob Herring @ 2017-01-23 20:44 UTC (permalink / raw)
  To: Martin Blumenstingl
  Cc: jic23-DgEjT+Ai2ygdnm+yROfE0A, knaack.h-Mmb7MZpHnFY,
	lars-Qo5EllUWu/uELgA04lAiVw, pmeerw-jW+XmwGofnusTnJN9+BGXg,
	mark.rutland-5wv7dgnIgG8, khilman-rdvid1DuHRBWk0Htik3J/w,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	carlo-KA+7E9HrN00dnm+yROfE0A, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, narmstrong-rdvid1DuHRBWk0Htik3J/w,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20170122181714.6259-2-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

On Sun, Jan 22, 2017 at 07:17:12PM +0100, Martin Blumenstingl wrote:
> This adds the devicetree binding documentation for the SAR ADC found in
> Amlogic Meson SoCs.
> Currently only the GXBB, GXL and GXM SoCs are supported.
> 
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
> Tested-by: Neil Armstrong <narmstrong-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
> Reviewed-by: Andreas Färber <afaerber-l3A5Bk7waGM@public.gmane.org>
> ---
>  .../bindings/iio/adc/amlogic,meson-saradc.txt      | 32 ++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
--
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 v2 2/2] Documentation: dt: iio: imu: st_lsm6dsx: add st,drdy-int-pin property
From: Rob Herring @ 2017-01-23 20:45 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: jic23-DgEjT+Ai2ygdnm+yROfE0A, linux-iio-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, lorenzo.bianconi-qxv4g6HH51o
In-Reply-To: <20170122183225.2539-3-lorenzo.bianconi-qxv4g6HH51o@public.gmane.org>

On Sun, Jan 22, 2017 at 07:32:25PM +0100, Lorenzo Bianconi wrote:
> Add st,drdy-int-pin property to select interrupt pin of the package
> 
> Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi-qxv4g6HH51o@public.gmane.org>
> ---
>  Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt | 2 ++
>  1 file changed, 2 insertions(+)

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

^ permalink raw reply

* [PATCH v3 0/3] OF phandle nexus support + GPIO nexus
From: Stephen Boyd @ 2017-01-23 20:48 UTC (permalink / raw)
  To: Rob Herring, Frank Rowand
  Cc: linux-arm-kernel, linux-kernel, devicetree, linux-gpio,
	Linus Walleij, Pantelis Antoniou, Mark Brown

This is one small chunk of work related to DT overlays for expansion
boards. It would be good to have a way to expose #<list>-cells types of
providers through a connector in a standard way. So we introduce a way
to make "nexus" nodes for these types of properties to remap the consumer
number space to the other side of the connector's number space. It's
basically a copy of the interrupt nexus implementation, but without
the address space matching design and interrupt-parent walking.

The first patch implements a generic method to do this, and the second patch
adds a unit test for it. The third patch is more of an example than anything
else. It shows how we would modify frameworks to use the new API.

Changes since v2:
 * Picked up Linus' ack on the gpio core patch
 * Made const stack arrays static (Rob Herring)
 * Used of_property_read_u32() instead of open coding (Rob Herring)

Changes since v1:
 * Addition of optional pass-thru parameter
 * Reduction of strings passed to 1 instead of 3 (or 4 now)
 * Updated gpio patch for the new function signature
 * Updated test-case for new funciton signature and pass-thru parameter
 * Updated kernel-doc to be correct and highlighted difference between
   this API and of_parse_phandle_with_args()

Stephen Boyd (3):
  of: Support parsing phandle argument lists through a nexus node
  of: unittest: Add phandle remapping test
  gpio: Support gpio nexus dt bindings

 drivers/gpio/gpiolib-of.c                   |   4 +-
 drivers/of/base.c                           | 184 ++++++++++++++++++++++++++++
 drivers/of/unittest-data/testcases.dts      |  11 ++
 drivers/of/unittest-data/tests-phandle.dtsi |  25 ++++
 drivers/of/unittest.c                       | 120 ++++++++++++++++++
 include/linux/of.h                          |  12 ++
 6 files changed, 354 insertions(+), 2 deletions(-)

-- 
2.10.0.297.gf6727b0

^ 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