Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH RFC V2 2/6] hwmon: Add support for RPi voltage sensor
From: Stefan Wahren @ 2018-05-22 19:31 UTC (permalink / raw)
  To: Rob Herring, Guenter Roeck, Eric Anholt, Mark Rutland,
	Jonathan Corbet, Jean Delvare
  Cc: linux-hwmon, devicetree, Florian Fainelli, Scott Branden,
	linux-doc, Ray Jui, Phil Elwell, Noralf Trønnes,
	bcm-kernel-feedback-list, linux-rpi-kernel, linux-arm-kernel
In-Reply-To: <bea3d6c7-a713-c4aa-8ae8-7fec80c5da5d@roeck-us.net>


> Guenter Roeck <linux@roeck-us.net> hat am 22. Mai 2018 um 16:10 geschrieben:
> 
> 
> On 05/22/2018 06:51 AM, Stefan Wahren wrote:
> > Hi Guenter,
> > 
> >> Guenter Roeck <linux@roeck-us.net> hat am 22. Mai 2018 um 15:41 geschrieben:
> >>
> >>
> >> On 05/22/2018 04:21 AM, Stefan Wahren wrote:
> >>> Currently there is no easy way to detect undervoltage conditions on a
> >>> remote Raspberry Pi. This hwmon driver retrieves the state of the
> >>> undervoltage sensor via mailbox interface. The handling based on
> >>> Noralf's modifications to the downstream firmware driver. In case of
> >>> an undervoltage condition only an entry is written to the kernel log.
> >>>
> >>> CC: "Noralf Trønnes" <noralf@tronnes.org>
> >>> Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
> >>> ---
> >>>    Documentation/hwmon/raspberrypi-hwmon |  22 +++++
> >>>    drivers/hwmon/Kconfig                 |  10 ++
> >>>    drivers/hwmon/Makefile                |   1 +
> >>>    drivers/hwmon/raspberrypi-hwmon.c     | 168 ++++++++++++++++++++++++++++++++++
> >>>    4 files changed, 201 insertions(+)
> >>>    create mode 100644 Documentation/hwmon/raspberrypi-hwmon
> >>>    create mode 100644 drivers/hwmon/raspberrypi-hwmon.c
> >>>
> >>> diff --git a/Documentation/hwmon/raspberrypi-hwmon b/Documentation/hwmon/raspberrypi-hwmon
> >>> new file mode 100644
> >>> index 0000000..3c92e2c
> >>> --- /dev/null
> >>> +++ b/Documentation/hwmon/raspberrypi-hwmon
> >>> @@ -0,0 +1,22 @@
> >>> +Kernel driver raspberrypi-hwmon
> >>> +===============================
> >>> +
> >>> +Supported boards:
> >>> +  * Raspberry Pi A+ (via GPIO on SoC)
> >>> +  * Raspberry Pi B+ (via GPIO on SoC)
> >>> +  * Raspberry Pi 2 B (via GPIO on SoC)
> >>> +  * Raspberry Pi 3 B (via GPIO on port expander)
> >>> +  * Raspberry Pi 3 B+ (via PMIC)
> >>> +
> >>> +Author: Stefan Wahren <stefan.wahren@i2se.com>
> >>> +
> >>> +Description
> >>> +-----------
> >>> +
> >>> +This driver periodically polls a mailbox property of the VC4 firmware to detect
> >>> +undervoltage conditions.
> >>> +
> >>> +Sysfs entries
> >>> +-------------
> >>> +
> >>> +in0_lcrit_alarm		Undervoltage alarm
> >>> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> >>> index 768aed5..9a5bdb0 100644
> >>> --- a/drivers/hwmon/Kconfig
> >>> +++ b/drivers/hwmon/Kconfig
> >>> @@ -1298,6 +1298,16 @@ config SENSORS_PWM_FAN
> >>>    	  This driver can also be built as a module.  If so, the module
> >>>    	  will be called pwm-fan.
> >>>    
> >>> +config SENSORS_RASPBERRYPI_HWMON
> >>> +	tristate "Raspberry Pi voltage monitor"
> >>> +	depends on RASPBERRYPI_FIRMWARE || COMPILE_TEST
> >>> +	help
> >>> +	  If you say yes here you get support for voltage sensor on the
> >>> +	  Raspberry Pi.
> >>> +
> >>> +	  This driver can also be built as a module. If so, the module
> >>> +	  will be called raspberrypi-hwmon.
> >>> +
> >>>    config SENSORS_SHT15
> >>>    	tristate "Sensiron humidity and temperature sensors. SHT15 and compat."
> >>>    	depends on GPIOLIB || COMPILE_TEST
> >>> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> >>> index e7d52a3..a929770 100644
> >>> --- a/drivers/hwmon/Makefile
> >>> +++ b/drivers/hwmon/Makefile
> >>> @@ -141,6 +141,7 @@ obj-$(CONFIG_SENSORS_PC87427)	+= pc87427.o
> >>>    obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
> >>>    obj-$(CONFIG_SENSORS_POWR1220)  += powr1220.o
> >>>    obj-$(CONFIG_SENSORS_PWM_FAN)	+= pwm-fan.o
> >>> +obj-$(CONFIG_SENSORS_RASPBERRYPI_HWMON)	+= raspberrypi-hwmon.o
> >>>    obj-$(CONFIG_SENSORS_S3C)	+= s3c-hwmon.o
> >>>    obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o
> >>>    obj-$(CONFIG_SENSORS_SCH5627)	+= sch5627.o
> >>> diff --git a/drivers/hwmon/raspberrypi-hwmon.c b/drivers/hwmon/raspberrypi-hwmon.c
> >>> new file mode 100644
> >>> index 0000000..6233e84
> >>> --- /dev/null
> >>> +++ b/drivers/hwmon/raspberrypi-hwmon.c
> >>> @@ -0,0 +1,168 @@
> >>> +// SPDX-License-Identifier: GPL-2.0+
> >>> +/*
> >>> + * Raspberry Pi voltage sensor driver
> >>> + *
> >>> + * Based on firmware/raspberrypi.c by Noralf Trønnes
> >>> + *
> >>> + * Copyright (C) 2018 Stefan Wahren <stefan.wahren@i2se.com>
> >>> + */
> >>> +#include <linux/device.h>
> >>> +#include <linux/err.h>
> >>> +#include <linux/hwmon.h>
> >>> +#include <linux/module.h>
> >>> +#include <linux/platform_device.h>
> >>> +#include <linux/slab.h>
> >>> +#include <linux/workqueue.h>
> >>> +#include <soc/bcm2835/raspberrypi-firmware.h>
> >>> +
> >>> +#define UNDERVOLTAGE_STICKY_BIT	BIT(16)
> >>> +
> >>> +struct rpi_hwmon_data {
> >>> +	struct device *hwmon_dev;
> >>> +	struct rpi_firmware *fw;
> >>> +	u32 last_throttled;
> >>> +	struct delayed_work get_values_poll_work;
> >>> +};
> >>> +
> >>> +static void rpi_firmware_get_throttled(struct rpi_hwmon_data *data)
> >>> +{
> >>> +	u32 new_uv, old_uv, value;
> >>> +	int ret;
> >>> +
> >>> +	/* Request firmware to clear sticky bits */
> >>> +	value = 0xffff;
> >>> +
> >>> +	ret = rpi_firmware_property(data->fw, RPI_FIRMWARE_GET_THROTTLED,
> >>> +				    &value, sizeof(value));
> >>> +	if (ret) {
> >>> +		dev_err_once(data->hwmon_dev, "Failed to get throttled (%d)\n",
> >>> +			     ret);
> >>> +		return;
> >>> +	}
> >>> +
> >>> +	new_uv = value & UNDERVOLTAGE_STICKY_BIT;
> >>> +	old_uv = data->last_throttled & UNDERVOLTAGE_STICKY_BIT;
> >>> +	data->last_throttled = value;
> >>> +
> >>> +	if (new_uv == old_uv)
> >>> +		return;
> >>> +
> >>> +	if (new_uv)
> >>> +		dev_crit(data->hwmon_dev, "Undervoltage detected!\n");
> >>> +	else
> >>> +		dev_info(data->hwmon_dev, "Voltage normalised\n");
> >>> +
> >>> +	sysfs_notify(&data->hwmon_dev->kobj, NULL, "in0_lcrit_alarm");
> >>> +}
> >>> +
> >>> +static void get_values_poll(struct work_struct *work)
> >>> +{
> >>> +	struct rpi_hwmon_data *data;
> >>> +
> >>> +	data = container_of(work, struct rpi_hwmon_data,
> >>> +			    get_values_poll_work.work);
> >>> +
> >>> +	rpi_firmware_get_throttled(data);
> >>> +
> >>> +	/*
> >>> +	 * We can't run faster than the sticky shift (100ms) since we get
> >>> +	 * flipping in the sticky bits that are cleared.
> >>> +	 */
> >>> +	schedule_delayed_work(&data->get_values_poll_work, 2 * HZ);
> >>> +}
> >>> +
> >>> +static int rpi_read(struct device *dev, enum hwmon_sensor_types type,
> >>> +		    u32 attr, int channel, long *val)
> >>> +{
> >>> +	struct rpi_hwmon_data *data = dev_get_drvdata(dev);
> >>> +
> >>> +	*val = !!(data->last_throttled & UNDERVOLTAGE_STICKY_BIT);
> >>> +	return 0;
> >>> +}
> >>> +
> >>> +static umode_t rpi_is_visible(const void *_data, enum hwmon_sensor_types type,
> >>> +			      u32 attr, int channel)
> >>> +{
> >>> +	return 0444;
> >>> +}
> >>> +
> >>> +static const u32 rpi_in_config[] = {
> >>> +	HWMON_I_LCRIT_ALARM,
> >>> +	0
> >>> +};
> >>> +
> >>> +static const struct hwmon_channel_info rpi_in = {
> >>> +	.type = hwmon_in,
> >>> +	.config = rpi_in_config,
> >>> +};
> >>> +
> >>> +static const struct hwmon_channel_info *rpi_info[] = {
> >>> +	&rpi_in,
> >>> +	NULL
> >>> +};
> >>> +
> >>> +static const struct hwmon_ops rpi_hwmon_ops = {
> >>> +	.is_visible = rpi_is_visible,
> >>> +	.read = rpi_read,
> >>> +};
> >>> +
> >>> +static const struct hwmon_chip_info rpi_chip_info = {
> >>> +	.ops = &rpi_hwmon_ops,
> >>> +	.info = rpi_info,
> >>> +};
> >>> +
> >>> +static int rpi_hwmon_probe(struct platform_device *pdev)
> >>> +{
> >>> +	struct device *dev = &pdev->dev;
> >>> +	struct rpi_hwmon_data *data;
> >>> +	int ret;
> >>> +
> >>> +	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> >>> +	if (!data)
> >>> +		return -ENOMEM;
> >>> +
> >>> +	data->fw = platform_get_drvdata(to_platform_device(dev->parent));
> >>> +	if (!data->fw)
> >>> +		return -EPROBE_DEFER;
> >>> +
> >>
> >> I am a bit at loss here (and sorry I didn't bring this up before).
> >> How would this ever be possible, given that the driver is registered
> >> from the firmware driver ?
> > 
> > Do you refer to the (wrong) return code, the assumption that the parent must be a platform driver or a possible race?
> > 
> 
> The return code is one thing. My question was how the driver would ever be instantiated
> with platform_get_drvdata(to_platform_device(dev->parent)) == NULL (but dev->parent != NULL),
> so I referred to the race. But, sure, a second question would be how that would indicate
> that the parent is not instantiated yet (which by itself seems like an odd question).

This shouldn't happen and worth a log error. In patch #3 the registration is called after the complete private data of the firmware driver is initialized. Did i missed something?

But i must confess that i didn't test all builtin/module combinations.

> 
> Yet another question, as you point out, is why to use platform_get_drvdata(to_platform_device(dev->parent))
> instead of dev_get_drvdata(dev->parent).

Sure this is much simpler

Thanks
Stefan

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

^ permalink raw reply

* Re: [PATCH v2 1/2] dt-bindings: cpufreq: Introduce QCOM CPUFREQ FW bindings
From: Rob Herring @ 2018-05-22 19:31 UTC (permalink / raw)
  To: Taniya Das
  Cc: Rafael J. Wysocki, Viresh Kumar, linux-kernel, linux-pm,
	Stephen Boyd, Rajendra Nayak, Amit Nischal, devicetree, skannan,
	amit.kucheria
In-Reply-To: <1526751291-17873-2-git-send-email-tdas@codeaurora.org>

On Sat, May 19, 2018 at 11:04:50PM +0530, Taniya Das wrote:
> Add QCOM cpufreq firmware device bindings for Qualcomm Technology Inc's
> SoCs. This is required for managing the cpu frequency transitions which are
> controlled by firmware.
> 
> Signed-off-by: Taniya Das <tdas@codeaurora.org>
> ---
>  .../bindings/cpufreq/cpufreq-qcom-fw.txt           | 68 ++++++++++++++++++++++
>  1 file changed, 68 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-fw.txt
> 
> diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-fw.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-fw.txt
> new file mode 100644
> index 0000000..bc912f4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-fw.txt
> @@ -0,0 +1,68 @@
> +Qualcomm Technologies, Inc. CPUFREQ Bindings
> +
> +CPUFREQ FW is a hardware engine used by some Qualcomm Technologies, Inc. (QTI)
> +SoCs to manage frequency in hardware. It is capable of controlling frequency
> +for multiple clusters.
> +
> +Properties:
> +- compatible
> +	Usage:		required
> +	Value type:	<string>
> +	Definition:	must be "qcom,cpufreq-fw".

Only 1 version ever?

> +
> +Note that #address-cells, #size-cells, and ranges shall be present to ensure
> +the cpufreq can address a freq-domain registers.
> +
> +A freq-domain sub-node would be defined for the cpus with the following
> +properties:
> +
> +- compatible:
> +	Usage:		required
> +	Value type:	<string>
> +	Definition:	must be "cpufreq".

Too generic. This is very much a QCom specific binding. Perhaps just 
drop the compatible.

> +
> +- reg
> +	Usage:		required
> +	Value type:	<prop-encoded-array>
> +	Definition:	Addresses and sizes for the memory of the perf_base
> +			, lut_base and en_base.
> +- reg-names
> +	Usage:		required
> +	Value type:	<stringlist>
> +	Definition:	Address names. Must be "perf_base", "lut_base",
> +			"en_base".

_base is redundant.

> +			Must be specified in the same order as the
> +			corresponding addresses are specified in the reg
> +			property.

Actually, must be specified in the order you specify here.

> +
> +- qcom,cpulist
> +	Usage:		required
> +	Value type:	<phandles of CPU>
> +	Definition:	List of related cpu handles which are under a cluster.
> +
> +Example:
> +	qcom,cpufreq-fw {
> +		compatible = "qcom,cpufreq-fw";
> +
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +		ranges;

There's not a smaller address range you can restrict children to?

> +
> +		freq-domain-0 {
> +			compatible = "cpufreq";
> +			reg = <0x17d43920 0x4>,
> +			     <0x17d43110 0x500>,
> +			     <0x17d41000 0x4>;
> +			reg-names = "perf_base", "lut_base", "en_base";
> +			qcom,cpulist = <&CPU0 &CPU1 &CPU2 &CPU3>;
> +		};
> +
> +		freq-domain-1 {
> +			compatible = "cpufreq";
> +			reg = <0x17d46120 0x4>,
> +			    <0x17d45910 0x500>,
> +			    <0x17d45800 0x4>;
> +			reg-names = "perf_base", "lut_base", "en_base";
> +			qcom,cpulist = <&CPU4 &CPU5 &CPU6 &CPU7>;
> +		};
> +	};
> --
> Qualcomm INDIA, on behalf of Qualcomm Innovation Center, Inc.is a member
> of the Code Aurora Forum, hosted by the  Linux Foundation.
> 

^ permalink raw reply

* Re: Revisiting Devicetree Overlay Manager
From: Alan Tull @ 2018-05-22 19:32 UTC (permalink / raw)
  To: Frank Rowand
  Cc: Manivannan Sadhasivam, Rob Herring, Grant Likely,
	Pantelis Antoniou, dimitrysh, john.stultz, nicolas.dechesne,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	daniel.thompson, loic.poulain
In-Reply-To: <5fb20388-5a0c-bb8b-4c6f-62d1ee42ec23@gmail.com>

On Thu, May 17, 2018 at 10:53 PM, Frank Rowand <frowand.list@gmail.com> wrote:
> Hi Manivannan,
>
> On 04/25/18 10:26, Frank Rowand wrote:
>> Hi Manivannan,
>>
>> Sorry for the delay.  I'll try to get to this today or tommorrow.
>>
>> -Frank
>
> Sorry for the even longer than expected delay.  As I mentioned to you
> off-list (bad Frank!), I wanted to pull together a lot of my disparate
> thoughts on overlays before responding to your specific proposal and
> questions.  The first (of probably many versions) of that write up
> is at:
>
>   https://elinux.org/Frank%27s_Evolving_Overlay_Thoughts

Slightly off topic (sorry), but you could move "FPGAs programmed after
kernel begins execution" to what has been completed since it's
implemented in drivers/fpga/of-fpga-region.c.  The remaining issue for
that use is adding some kind of acceptable userspace interface, that
seems to be captured in "overlay manager" in the "issues and what
needs to be completed" section.

>
> My thoughts on some of your questions are addressed on that page.
> I still need to read through your questions because there are
> probably several that I did not address on that page.
>
> -Frank
>
>>
>>
>> On 04/25/18 00:34, Manivannan Sadhasivam wrote:
>>> Hi Frank,
>>>
>>> Did you had time to look into this? Especially I'd like to hear your
>>> opinion on the first pain point I have mentioned. I can understand
>>> that the whole point on introducing the of_overlay_fdt_apply() API
>>> is to remove the duplication of overlay FDT unflattening, but do you have
>>> any idea of how we can make this API work with overlay nodes appended
>>> to the base DTB?
>>>
>>> Thanks,
>>> Mani
>>>
>>> On Thu, Apr 19, 2018 at 08:08:04PM +0530, Manivannan Sadhasivam wrote:
>>>> Hello Everyone,
>>>>
>>>> I have just started working on the Devicetree Overlay Manager support in
>>>> kernel. The idea is to merge overlays at boot time specified via some
>>>> interface like kernel command line. The motivation for this work comes from
>>>> Overlay Manager [1] submitted by John last year. The mechanism which I have
>>>> been working on is an extension to John's work. It focusses on addressing
>>>> Rob's comments on the Overlay Manager which involves having multiple ways
>>>> to load overlays.
>>>>
>>>> Proposal:
>>>> =========
>>>>
>>>> 1. Pass all devicetree overlays via following methods:
>>>>    - Overlays appended to base DTB
>>>>    - Individual overlays built into kernel as firmware blobs
>>>>    - Any other ways?

Would an interface that allows applying/removing overlays after boot
time work for you?  I'm referring to something like Pantelis' ConfigFS
interface which  has been proposed (and currently rejected). I
understand your proposal is on the kernel command line, but I am
wondering whether something like that could work for both our uses.
My use is applying overlays after the kernel has booted to reprogram a
FPGA and add nodes for the devices that show up in the FPGA (and
removing the overlays to prepare for reprogramming).

Alan

>>>>
>>>> 2. Specify overlays to load via kernel command line as below:
>>>>    - overlay_mgr.overlays=<overlay1,overlay2,...>
>>>>
>>>> 3. Merge only the specified overlays during boot time. First look for the
>>>> overlay in the base DTB. If it is found, just apply it, else defer to firmware
>>>> load approach.
>>>>
>>>> The Overlay Manager code is expected to be very simple and will just do the
>>>> above mentioned work. Later on, it will be extended to support dynamic
>>>> modification of overlays from userspace with some additional security
>>>> features like having a property listed in the base devicetree for only
>>>> allowing changes to the current node and its child nodes, etc...
>>>>
>>>> Pain Points:
>>>> ============
>>>>
>>>> 1. Starting from 4.17 we don't have any API exposed from DT core to merge
>>>> individual devicetree nodes. We only have of_overlay_fdt_apply() function
>>>> which takes the whole FDT. This will work very well for the firmware approach
>>>> since we will pass the overlays blobs but not for overlays appended to base DTB,
>>>> where we will pass individual overlay nodes.
>>>>
>>>> 2. Using firmware load method will force us to have this Overlay Manager code
>>>> at late_initcall level since firmware class exists only in fs_inticall level,
>>>> which might be too late for some devices.
>>>>
>>>> 3. This whole approach is not expected to work very well (still not yet tested)
>>>> on DSI based devices since it needs to be present at very early during boot
>>>> process.
>>>>
>>>> The Overlay Manager propsed here will be board agnostic and it should work on
>>>> all platforms supporting DT. This will be a _very_ useful feature for the
>>>> development boards such as 96Boards, Raspberry Pi, BBB etc... and also for
>>>> production ready devices.
>>>>
>>>> So, I'd like to hear suggestions/feedbacks for the above mentioned proposal &
>>>> pain points and hope to land the most awaited feature in kernel.
>>>>
>>>> Regards,
>>>> Mani
>>>>
>>>> [1] https://lkml.org/lkml/2017/10/10/20
>>>
>>
>> .
>>
>
> --
> 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 v2 1/5] dt-bindings: pinctrl: Add gpio bindings for Actions S900 SoC
From: Rob Herring @ 2018-05-22 19:33 UTC (permalink / raw)
  To: Manivannan Sadhasivam
  Cc: linus.walleij, afaerber, liuwei, mp-cs, 96boards, devicetree,
	andy.shevchenko, daniel.thompson, amit.kucheria, linux-arm-kernel,
	linux-gpio, linux-kernel, hzhang, bdong, manivannanece23
In-Reply-To: <20180520051736.4842-2-manivannan.sadhasivam@linaro.org>

On Sun, May 20, 2018 at 10:47:32AM +0530, Manivannan Sadhasivam wrote:
> Add gpio bindings for Actions Semi S900 SoC.
> 
> Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
> ---
>  .../devicetree/bindings/pinctrl/actions,s900-pinctrl.txt | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)

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

^ permalink raw reply

* Re: [PATCH 2/2] ARM: pxa: dts: add pin definitions for extended GPIOs
From: Robert Jarzmik @ 2018-05-22 19:34 UTC (permalink / raw)
  To: Daniel Mack; +Cc: devicetree, robh+dt, linux-arm-kernel, haojian.zhuang
In-Reply-To: <20180521220044.821-2-daniel@zonque.org>

Daniel Mack <daniel@zonque.org> writes:

> The PXA3xx series features some extended GPIO banks which are named GPIO0_2,
> GPIO1_2 etc. The PXA300, PXA310 and PXA320 have different numbers of such
> pins, and they also have variant-specific register offsets.
>
> Signed-off-by: Daniel Mack <daniel@zonque.org>
> ---
>  arch/arm/boot/dts/pxa3xx.dtsi | 24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
>
> diff --git a/arch/arm/boot/dts/pxa3xx.dtsi b/arch/arm/boot/dts/pxa3xx.dtsi
> index a13ac52e4fd2..446e612688c0 100644
> --- a/arch/arm/boot/dts/pxa3xx.dtsi
> +++ b/arch/arm/boot/dts/pxa3xx.dtsi
> @@ -8,6 +8,13 @@
>  	 (gpio <= 98) ? (0x0400 + 4 * (gpio - 27)) :	\
>  	 (gpio <= 127) ? (0x0600 + 4 * (gpio - 99)) :	\
>  	 0)
> +#define MFP_PIN_PXA300_0_2	0x674
> +#define MFP_PIN_PXA300_1_2	0x678
> +#define MFP_PIN_PXA300_2_2	0x2dc
> +#define MFP_PIN_PXA300_3_2	0x2e0
> +#define MFP_PIN_PXA300_4_2	0x2e4
> +#define MFP_PIN_PXA300_5_2	0x2e8
> +#define MFP_PIN_PXA300_6_2	0x2ec

To be consistent with the previous items, could it be something like :
#define MFP_PIN_PXA300_2(gpio) \
  ... etc ...

And so on for the others.

Cheers.

-- 
Robert

^ permalink raw reply

* Re: [RESEND PATCH v2 1/2] dt-bindings: Add vendor prefix for DLC Display Co., Ltd.
From: Rob Herring @ 2018-05-22 19:35 UTC (permalink / raw)
  To: Marco Felsch; +Cc: mark.rutland, devicetree, thierry.reding, kernel, dri-devel
In-Reply-To: <20180522094812.31608-2-m.felsch@pengutronix.de>

On Tue, May 22, 2018 at 11:48:11AM +0200, Marco Felsch wrote:
> From: Philipp Zabel <p.zabel@pengutronix.de>
> 
> DLC provides a wide range of display solutions.
> Website: http://www.dlcdisplay.com/
> 
> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
>  1 file changed, 1 insertion(+)

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

> 
> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
> index b5f978a4cac6..52de5eed11bf 100644
> --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
> +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
> @@ -89,6 +89,7 @@ dh	DH electronics GmbH
>  digi	Digi International Inc.
>  digilent	Diglent, Inc.
>  dioo	Dioo Microcircuit Co., Ltd
> +dlc	DLC Display Co., Ltd.
>  dlg	Dialog Semiconductor
>  dlink	D-Link Corporation
>  dmo	Data Modul AG
> -- 
> 2.17.0
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply

* Re: [RESEND PATCH v2 2/2] gpu: drm/panel: Add DLC DLC0700YZG-1 panel
From: Rob Herring @ 2018-05-22 19:37 UTC (permalink / raw)
  To: Marco Felsch; +Cc: mark.rutland, devicetree, thierry.reding, kernel, dri-devel
In-Reply-To: <20180522094812.31608-3-m.felsch@pengutronix.de>

On Tue, May 22, 2018 at 11:48:12AM +0200, Marco Felsch wrote:
> From: Philipp Zabel <p.zabel@pengutronix.de>
> 
> This patch adds support for DLC DLC0700YZG-1 1024x600 LVDS panels
> to the simple-panel driver.
> 
> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> [m.felsch@pengutronix.de: fix typo in compatible dt-binding]
> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> ---
>  .../display/panel/dlc,dlc0700yzg-1.txt        |  7 ++++
>  drivers/gpu/drm/panel/panel-simple.c          | 32 +++++++++++++++++++
>  2 files changed, 39 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/panel/dlc,dlc0700yzg-1.txt
> 
> diff --git a/Documentation/devicetree/bindings/display/panel/dlc,dlc0700yzg-1.txt b/Documentation/devicetree/bindings/display/panel/dlc,dlc0700yzg-1.txt
> new file mode 100644
> index 000000000000..3cfafe26eb35
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/panel/dlc,dlc0700yzg-1.txt
> @@ -0,0 +1,7 @@
> +DLC Display Co. DLC0700YZG-1 7.0" WSVGA TFT LCD panel
> +
> +Required properties:
> +- compatible: should be "dlc,dlc0700yzg-1"
> +
> +This binding is compatible with the simple-panel binding, which is specified
> +in simple-panel.txt in this directory.

You need to list exactly which properties this panel uses.

Rob
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply

* Re: [PATCH v7 2/2] drivers: soc: Add LLCC driver
From: Andy Shevchenko @ 2018-05-22 19:38 UTC (permalink / raw)
  To: Rishabh Bhatnagar
  Cc: linux-arm Mailing List, linux-arm-msm, devicetree,
	Linux Kernel Mailing List, linux-arm, tsoni, ckadabi, Evan Green,
	Rob Herring
In-Reply-To: <f1970a64be17267e0f044242dc0764d6@codeaurora.org>

On Tue, May 22, 2018 at 9:33 PM,  <rishabhb@codeaurora.org> wrote:
> On 2018-05-18 14:01, Andy Shevchenko wrote:
>> On Wed, May 16, 2018 at 8:43 PM, Rishabh Bhatnagar
>> <rishabhb@codeaurora.org> wrote:

>>> +#define ACTIVATE                      0x1
>>> +#define DEACTIVATE                    0x2
>>> +#define ACT_CTRL_OPCODE_ACTIVATE      0x1
>>> +#define ACT_CTRL_OPCODE_DEACTIVATE    0x2
>>> +#define ACT_CTRL_ACT_TRIG             0x1
>>
>>
>> Are these bits? Perhaps BIT() ?
>>
> isn't it just better to use fixed size as u suggest in the next comment?

If the are bits, use BIT() macro.

>>> +struct llcc_slice_desc *llcc_slice_getd(u32 uid)
>>> +{
>>> +       const struct llcc_slice_config *cfg;
>>> +       struct llcc_slice_desc *desc;
>>> +       u32 sz, count = 0;
>>> +
>>> +       cfg = drv_data->cfg;
>>> +       sz = drv_data->cfg_size;
>>> +
>>
>>
>>> +       while (cfg && count < sz) {
>>> +               if (cfg->usecase_id == uid)
>>> +                       break;
>>> +               cfg++;
>>> +               count++;
>>> +       }
>>> +       if (cfg == NULL || count == sz)
>>> +               return ERR_PTR(-ENODEV);
>>
>>
>> if (!cfg)
>>           return ERR_PTR(-ENODEV);
>>
>> while (cfg->... != uid) {
>>   cfg++;
>>   count++;
>> }
>>
>> if (count == sz)
>>  return ...
>>
>> Though I would rather put it to for () loop.
>>
> In each while loop iteration the cfg pointer needs to be checked for
> NULL. What if the usecase id never matches the uid passed by client
> and we keep iterating. At some point it will crash.

do {
  if (!cfg || count == sz)
   return ...(-ENODEV);
 ...
} while (...);

Though, as I said for-loop will look slightly better I think.

>>> +       ret = llcc_update_act_ctrl(desc->slice_id, act_ctrl_val,
>>> +                                 DEACTIVATE);
>>
>>
>> Perhaps one line (~83 characters here is OK) ?
>
> The checkpatch script complains about such lines.

So what if it just 3 characters out?

>>> +       ret = llcc_update_act_ctrl(desc->slice_id, act_ctrl_val,
>>> +                                 ACTIVATE);

>> Ditto.

>>> +               attr1_cfg = bcast_off +
>>> +
>>> LLCC_TRP_ATTR1_CFGn(llcc_table[i].slice_id);
>>> +               attr0_cfg = bcast_off +
>>> +
>>> LLCC_TRP_ATTR0_CFGn(llcc_table[i].slice_id);

>> Ditto.

>>> +               attr1_val |= llcc_table[i].probe_target_ways <<
>>> +                               ATTR1_PROBE_TARGET_WAYS_SHIFT;
>>> +               attr1_val |= llcc_table[i].fixed_size <<
>>> +                               ATTR1_FIXED_SIZE_SHIFT;
>>> +               attr1_val |= llcc_table[i].priority <<
>>> ATTR1_PRIORITY_SHIFT;

>> foo |=
>>   bar << SHIFT;
>>
>> would look slightly better.

Did you consider this option ?

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply

* Re: [PATCH net-next v2 1/7] net: dsa: qca8k: Add QCA8334 binding documentation
From: Rob Herring @ 2018-05-22 19:40 UTC (permalink / raw)
  To: Michal Vokáč
  Cc: netdev, linux-kernel, devicetree, f.fainelli, vivien.didelot,
	andrew, mark.rutland, davem, michal.vokac
In-Reply-To: <1526987792-56861-2-git-send-email-michal.vokac@ysoft.com>

On Tue, May 22, 2018 at 01:16:26PM +0200, Michal Vokáč wrote:
> Add support for the four-port variant of the Qualcomm QCA833x switch.
> 
> The CPU port default link settings can be reconfigured using
> a fixed-link sub-node.
> 
> Signed-off-by: Michal Vokáč <michal.vokac@ysoft.com>
> ---
> Changes in v2:
>  - Add commit message and document fixed-link binding.
> 
>  .../devicetree/bindings/net/dsa/qca8k.txt          | 23 +++++++++++++++++++++-
>  1 file changed, 22 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/net/dsa/qca8k.txt b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
> index 9c67ee4..15b9057 100644
> --- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt
> +++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
> @@ -2,7 +2,10 @@
>  
>  Required properties:
>  
> -- compatible: should be "qca,qca8337"
> +- compatible: should be one of:
> +    "qca,qca8334"
> +    "qca,qca8337"
> +
>  - #size-cells: must be 0
>  - #address-cells: must be 1
>  
> @@ -14,6 +17,20 @@ port and PHY id, each subnode describing a port needs to have a valid phandle
>  referencing the internal PHY connected to it. The CPU port of this switch is
>  always port 0.
>  
> +A CPU port node has the following optional property:

s/property/node/

Otherwise,

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

^ permalink raw reply

* Re: [PATCH V1 3/3] mmc: host: Register changes for sdcc V5
From: Rob Herring @ 2018-05-22 19:45 UTC (permalink / raw)
  To: Vijay Viswanath
  Cc: adrian.hunter, ulf.hansson, mark.rutland, linux-mmc, linux-kernel,
	shawn.lin, linux-arm-msm, georgi.djakov, devicetree, asutoshd,
	stummala, venkatg, jeremymc, bjorn.andersson, riteshh, vbadigan,
	dianders, sayalil
In-Reply-To: <1526552938-21292-4-git-send-email-vviswana@codeaurora.org>

On Thu, May 17, 2018 at 03:58:58PM +0530, Vijay Viswanath wrote:
> From: Sayali Lokhande <sayalil@codeaurora.org>
> 
> For SDCC version 5.0.0 and higher, new compatible string
> "qcom,sdhci-msm-v5" is added.
> 
> Based on the msm variant, pick the relevant variant data and
> use it for register read/write to msm specific registers.
> 
> Signed-off-by: Sayali Lokhande <sayalil@codeaurora.org>
> Signed-off-by: Vijay Viswanath <vviswana@codeaurora.org>
> ---
>  .../devicetree/bindings/mmc/sdhci-msm.txt          |   5 +-

Please split binding patches.

>  drivers/mmc/host/sdhci-msm.c                       | 344 +++++++++++++--------
>  2 files changed, 222 insertions(+), 127 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
> index bfdcdc4..c2b7b2b 100644
> --- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
> +++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
> @@ -4,7 +4,10 @@ This file documents differences between the core properties in mmc.txt
>  and the properties used by the sdhci-msm driver.
>  
>  Required properties:
> -- compatible: Should contain "qcom,sdhci-msm-v4".
> +- compatible: Should contain "qcom,sdhci-msm-v4" or "qcom,sdhci-msm-v5".

Format with 1 per line.

> +		 For SDCC version 5.0.0, MCI registers are removed from SDCC
> +		 interface and some registers are moved to HC. New compatible
> +		 string is added to support this change - "qcom,sdhci-msm-v5".
>  - reg: Base address and length of the register in the following order:
>  	- Host controller register map (required)
>  	- SD Core register map (required)

^ permalink raw reply

* Re: [PATCH 2/2] ARM: pxa: dts: add pin definitions for extended GPIOs
From: Daniel Mack @ 2018-05-22 19:46 UTC (permalink / raw)
  To: Robert Jarzmik; +Cc: devicetree, robh+dt, linux-arm-kernel, haojian.zhuang
In-Reply-To: <87tvqzxz5z.fsf@belgarion.home>

On Tuesday, May 22, 2018 09:34 PM, Robert Jarzmik wrote:
> Daniel Mack <daniel@zonque.org> writes:
> 
>> The PXA3xx series features some extended GPIO banks which are named GPIO0_2,
>> GPIO1_2 etc. The PXA300, PXA310 and PXA320 have different numbers of such
>> pins, and they also have variant-specific register offsets.
>>
>> Signed-off-by: Daniel Mack <daniel@zonque.org>
>> ---
>>   arch/arm/boot/dts/pxa3xx.dtsi | 24 ++++++++++++++++++++++++
>>   1 file changed, 24 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/pxa3xx.dtsi b/arch/arm/boot/dts/pxa3xx.dtsi
>> index a13ac52e4fd2..446e612688c0 100644
>> --- a/arch/arm/boot/dts/pxa3xx.dtsi
>> +++ b/arch/arm/boot/dts/pxa3xx.dtsi
>> @@ -8,6 +8,13 @@
>>   	 (gpio <= 98) ? (0x0400 + 4 * (gpio - 27)) :	\
>>   	 (gpio <= 127) ? (0x0600 + 4 * (gpio - 99)) :	\
>>   	 0)
>> +#define MFP_PIN_PXA300_0_2	0x674
>> +#define MFP_PIN_PXA300_1_2	0x678
>> +#define MFP_PIN_PXA300_2_2	0x2dc
>> +#define MFP_PIN_PXA300_3_2	0x2e0
>> +#define MFP_PIN_PXA300_4_2	0x2e4
>> +#define MFP_PIN_PXA300_5_2	0x2e8
>> +#define MFP_PIN_PXA300_6_2	0x2ec
> 
> To be consistent with the previous items, could it be something like :
> #define MFP_PIN_PXA300_2(gpio) \
>    ... etc ...
> 

Ah, yes. Much nicer. Will resend!


Thanks,
Daniel

^ permalink raw reply

* [PATCH] arm64: dts: fix regulator property name for wlan pcie endpoint
From: Niklas Cassel @ 2018-05-22 19:57 UTC (permalink / raw)
  To: Andy Gross, David Brown, Rob Herring, Mark Rutland,
	Catalin Marinas, Will Deacon
  Cc: Niklas Cassel, linux-arm-msm, linux-soc, devicetree,
	linux-arm-kernel, linux-kernel

The property name vddpe-supply is not included in
Documentation/devicetree/bindings/pci/qcom,pcie.txt
nor in the pcie-qcom PCIe Root Complex driver.

This property name was used in an initial patchset for pcie-qcom,
but was renamed in a later revision.

Therefore, the regulator is currently never enabled, leaving us with
unoperational wlan.

Fix this by using the correct regulator property name, so that wlan
comes up correctly.

Fixes: 1c8ca74a2ea1 ("arm64: dts: apq8096-db820c: Enable wlan and bt en pins")
Signed-off-by: Niklas Cassel <niklas.cassel@linaro.org>
---
Bluetooth needs a similar patch, but since bluetooth needs some more
work, submit this right now, so we at least have working wlan.

 arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
index 818bf0efd501..804268f54f37 100644
--- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
@@ -203,7 +203,7 @@
 			pcie@600000 {
 				status = "okay";
 				perst-gpio = <&msmgpio 35 GPIO_ACTIVE_LOW>;
-				vddpe-supply = <&wlan_en>;
+				vddpe-3v3-supply = <&wlan_en>;
 				vddpe1-supply = <&bt_en>;
 			};
 
-- 
2.17.0

^ permalink raw reply related

* Re: [RFC 12/13] ARM: dts: ti: add dra71-evm FIT description file
From: Rob Herring @ 2018-05-22 20:01 UTC (permalink / raw)
  To: Tero Kristo
  Cc: mark.rutland, devicetree, trini, Tony Lindgren,
	Russell King - ARM Linux, frowand.list, wmills,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <43ff3894-a287-1558-687c-40f50712735c@ti.com>

On Mon, May 21, 2018 at 09:57:54AM +0300, Tero Kristo wrote:
> On 17/04/18 17:49, Tony Lindgren wrote:
> > * Tero Kristo <t-kristo@ti.com> [180417 09:36]:
> > > In typical setup, you can boot a large number of different configs via:
> > > 
> > > bootm 0x82000000#dra71-evm#nand#lcd-auo-g101evn01.0
> > > 
> > > ... assuming the configs were named like that, and assuming they would be
> > > compatible with each other. The am57xx-evm example provided is better, as
> > > you can chain the different cameras to the available evm configs.
> > 
> > Why not just do it in the bootloader to put together the dtb?
> > 
> > Then for external devices, you could just pass info on the
> > kernel cmdline with lcd=foo camera=bar if they cannot be
> > detected over I2C.
> 
> (Added Linux ARM list to CC, this was not part of the original delivery.)
> 
> Ok trying to resurrect this thread a bit. Is there any kind of consensus how
> things like this should be handled? Should we add the DT overlay files to
> kernel tree or not?

IMO, yes.

> Should we add any kind of build infra to kernel tree, and at what level
> would this be? Just DT overlay file building support, and drop the FIT build
> support as was proposed in this RFC series or...?

I think I mentioned this already, but I expect that this is going to 
cause a number of conversions of dtsi + dtsi -> dtb into base dts and 
overlay(s) dts files. In doing so, we still need to be able to build the 
original, full dtb.

> U-boot can obviously parse the base DTB + overlay DTB:s into a single DTB,
> but this is somewhat clumsy approach and is relatively error prone to get it
> right.

Why? How is the kernel better?

> Building the FIT image post kernel build would also be possible, but who
> would be doing this, is there any need to get this done in generic manner or
> shall we just add SoC vendor specific tools for this?

I'll tell you up front, I'm not a fan of FIT image (nor uImage, 
Android boot image, $bootloader image). If you want a collection of 
files and some configuration data, use a filesystem and a text file.

Rob

^ permalink raw reply

* Re: [PATCH v1 1/7] dt-bindings: pinctrl: add external interrupt support to MT7622 pinctrl
From: Rob Herring @ 2018-05-22 20:02 UTC (permalink / raw)
  To: sean.wang
  Cc: mark.rutland, linus.walleij, matthias.bgg, devicetree,
	linux-mediatek, linux-arm-kernel, linux-gpio, linux-kernel
In-Reply-To: <3898620ef606004aaddc332591ca467f56773029.1526835466.git.sean.wang@mediatek.com>

On Mon, May 21, 2018 at 01:01:47AM +0800, sean.wang@mediatek.com wrote:
> From: Sean Wang <sean.wang@mediatek.com>
> 
> Extend the capability of MT7622 pinctrl with adding EINT so that each
> GPIO can be used to notify CPU when a signal state is changing on the
> line as an external interrupt.
> 
> Signed-off-by: Sean Wang <sean.wang@mediatek.com>
> ---
>  Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt | 10 ++++++++++
>  1 file changed, 10 insertions(+)

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

^ permalink raw reply

* Re: [PATCH 4/5] arm64: allwinner: h6: add USB3 device nodes
From: Rob Herring @ 2018-05-22 20:09 UTC (permalink / raw)
  To: Sergei Shtylyov
  Cc: Icenowy Zheng, Mark Rutland, Maxime Ripard, Chen-Yu Tsai,
	Greg Kroah-Hartman, Kishon Vijay Abraham I, Felipe Balbi,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <9a25a561-b643-a77b-3287-8082780fce60-M4DtvfQ/ZS1MRgGoP+s0PdBPR1lH4CV8@public.gmane.org>

On Tue, May 08, 2018 at 11:31:27AM +0300, Sergei Shtylyov wrote:
> Hello!
> 
> On 5/7/2018 6:18 PM, Icenowy Zheng wrote:
> 
> > Allwinner H6 SoC features USB3 functionality, with a DWC3 controller and
> > a custom PHY.
> > 
> > Add device tree nodes for them.
> > 
> > Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
> > ---
> >   arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 38 ++++++++++++++++++++
> >   1 file changed, 38 insertions(+)
> > 
> > diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
> > index c72da8cd9ef5..9564c938717c 100644
> > --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
> > +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
> > @@ -174,6 +174,44 @@
> >   			status = "disabled";
> >   		};
> > +		usb3: usb@5200000 {
> 
>    I don't think <unit-address> is allowed for a node having no "reg" prop...

Right. One way to fix is fill out ranges property because the unit 
address can come from either.

However, there's work to deprecate doing DWC3 binding with a child node 
like this. See the series "usb: dwc3: support clocks and resets for DWC3 
core". Please follow that.

Rob

^ permalink raw reply

* Re: [PATCH 1/5] phy: allwinner: add phy driver for USB3 PHY on Allwinner H6 SoC
From: Rob Herring @ 2018-05-22 20:12 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Mark Rutland, Maxime Ripard, Chen-Yu Tsai, Greg Kroah-Hartman,
	Kishon Vijay Abraham I, Felipe Balbi,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20180507151817.55663-2-icenowy-h8G6r0blFSE@public.gmane.org>

On Mon, May 07, 2018 at 11:18:13PM +0800, Icenowy Zheng wrote:
> Allwinner H6 SoC contains a USB3 PHY (with USB2 DP/DM lines also
> controlled).
> 
> Add a driver for it.
> 
> The register operations in this driver is mainly extracted from the BSP
> USB3 driver.
> 
> Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
> ---
>  .../bindings/phy/sun50i-usb3-phy.txt          |  24 +++

Please split bindings to separate patch.

>  drivers/phy/allwinner/Kconfig                 |  13 ++
>  drivers/phy/allwinner/Makefile                |   1 +
>  drivers/phy/allwinner/phy-sun50i-usb3.c       | 195 ++++++++++++++++++
>  4 files changed, 233 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/phy/sun50i-usb3-phy.txt
>  create mode 100644 drivers/phy/allwinner/phy-sun50i-usb3.c
> 
> diff --git a/Documentation/devicetree/bindings/phy/sun50i-usb3-phy.txt b/Documentation/devicetree/bindings/phy/sun50i-usb3-phy.txt
> new file mode 100644
> index 000000000000..912d55f9f69d
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/sun50i-usb3-phy.txt
> @@ -0,0 +1,24 @@
> +Allwinner sun50i USB3 PHY
> +-----------------------
> +
> +Required properties:
> +- compatible : should be one of
> +  * allwinner,sun60i-h6-usb3-phy
> +- reg : a list of offset + length pairs
> +- #phy-cells : from the generic phy bindings, must be 0
> +- clocks : phandle + clock specifier for the phy clock
> +- resets : phandle + reset specifier for the phy reset
> +
> +Optional Properties:
> +- phy-supply : from the generic phy bindings, a phandle to a regulator that
> +	       provides power to VBUS.
> +
> +Example:
> +	usb3phy: phy@5210000 {

usb-phy@...

> +		compatible = "allwinner,sun50i-h6-usb3-phy";
> +		reg = <0x5210000 0x10000>;
> +		clocks = <&ccu CLK_USB_PHY1>;
> +		resets = <&ccu RST_USB_PHY1>;
> +		#phy-cells = <0>;
> +		status = "disabled";

Don't show status in examples.

> +	};

^ permalink raw reply

* Re: [PATCH v8 2/2] leds: lm3601x: Introduce the lm3601x LED driver
From: Andy Shevchenko @ 2018-05-22 20:12 UTC (permalink / raw)
  To: Dan Murphy
  Cc: Rob Herring, Mark Rutland, Jacek Anaszewski, devicetree,
	Linux Kernel Mailing List, Linux LED Subsystem
In-Reply-To: <20180522142417.19639-2-dmurphy@ti.com>

On Tue, May 22, 2018 at 5:24 PM, Dan Murphy <dmurphy@ti.com> wrote:
> Introduce the family of LED devices that can
> drive a torch, strobe or IR LED.
>
> The LED driver can be configured with a strobe
> timer to execute a strobe flash.  The IR LED
> brightness is controlled via the torch brightness
> register.
>
> The data sheet for each the LM36010 and LM36011
> LED drivers can be found here:
> http://www.ti.com/product/LM36010
> http://www.ti.com/product/LM36011
>
> Signed-off-by: Dan Murphy <dmurphy@ti.com>
> ---
>
> v8 - Removed OF Kconfig dependency, change strobe to flash, updated label generation,
> fixed brightness calculation, added mutex_destroy and flash_unregister - https://patchwork.kernel.org/patch/10416163/
>
> v7 - Numerous fixes to many to list.  Highlights are moved from OF APIs to device_property
> APIs, updated LED registration, timeout to reg algorithim, and fixed label generation -
> https://patchwork.kernel.org/patch/10401437/
> v6 - This driver has been heavily modified from v5.  There is no longer reading
> of individual child nodes.  There are too many changes to list here see -
> https://patchwork.kernel.org/patch/10392123/
> v5 - Fixed magic numbers, change reg cache type, added of_put_node to release
> the dt node ref, and I did not change the remove function to leave the LED in its
> state on driver removal - https://patchwork.kernel.org/patch/10391741/
> v4 - Fixed Cocci issue using ARRAY_SIZE - https://patchwork.kernel.org/patch/10389259/
> v3 - removed wildcard dt compatible, fixed copyright, fixed struct doc, removed
> RO registers from default, added regmap volatile for FLAGS_REG, updated regmap cache type,
> fixed unlock and extra semi colon in strobe_set, removed unnecessary out label
> in led register and fixed checking of the ret in brightness_set - https://patchwork.kernel.org/patch/10386243/
> v2 - Fixed kbuild issue and removed unused cdev_strobe - https://patchwork.kernel.org/patch/10384585/
>
>
>  drivers/leds/Kconfig        |   9 +
>  drivers/leds/Makefile       |   1 +
>  drivers/leds/leds-lm3601x.c | 492 ++++++++++++++++++++++++++++++++++++
>  3 files changed, 502 insertions(+)
>  create mode 100644 drivers/leds/leds-lm3601x.c
>
> diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
> index 2c896c0e69e1..d95d436e6089 100644
> --- a/drivers/leds/Kconfig
> +++ b/drivers/leds/Kconfig
> @@ -145,6 +145,15 @@ config LEDS_LM3692X
>           This option enables support for the TI LM3692x family
>           of white LED string drivers used for backlighting.
>
> +config LEDS_LM3601X
> +       tristate "LED support for LM3601x Chips"
> +       depends on LEDS_CLASS && I2C
> +       depends on LEDS_CLASS_FLASH
> +       select REGMAP_I2C
> +       help
> +         This option enables support for the TI LM3601x family
> +         of flash, torch and indicator classes.
> +
>  config LEDS_LOCOMO
>         tristate "LED Support for Locomo device"
>         depends on LEDS_CLASS
> diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
> index 91eca81cae82..b79807fe1b67 100644
> --- a/drivers/leds/Makefile
> +++ b/drivers/leds/Makefile
> @@ -76,6 +76,7 @@ obj-$(CONFIG_LEDS_MLXREG)             += leds-mlxreg.o
>  obj-$(CONFIG_LEDS_NIC78BX)             += leds-nic78bx.o
>  obj-$(CONFIG_LEDS_MT6323)              += leds-mt6323.o
>  obj-$(CONFIG_LEDS_LM3692X)             += leds-lm3692x.o
> +obj-$(CONFIG_LEDS_LM3601X)             += leds-lm3601x.o
>
>  # LED SPI Drivers
>  obj-$(CONFIG_LEDS_DAC124S085)          += leds-dac124s085.o
> diff --git a/drivers/leds/leds-lm3601x.c b/drivers/leds/leds-lm3601x.c
> new file mode 100644
> index 000000000000..b1f0ede704c1
> --- /dev/null
> +++ b/drivers/leds/leds-lm3601x.c
> @@ -0,0 +1,492 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Flash and torch driver for Texas Instruments LM3601X LED
> +// Flash driver chip family
> +// Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
> +
> +#include <linux/delay.h>
> +#include <linux/i2c.h>
> +#include <linux/leds.h>
> +#include <linux/led-class-flash.h>
> +#include <linux/module.h>
> +#include <linux/regmap.h>
> +#include <linux/slab.h>
> +#include <uapi/linux/uleds.h>
> +
> +#define LM3601X_LED_IR         0x0
> +#define LM3601X_LED_TORCH      0x1
> +
> +/* Registers */
> +#define LM3601X_ENABLE_REG     0x01
> +#define LM3601X_CFG_REG                0x02
> +#define LM3601X_LED_FLASH_REG  0x03
> +#define LM3601X_LED_TORCH_REG  0x04
> +#define LM3601X_FLAGS_REG      0x05
> +#define LM3601X_DEV_ID_REG     0x06
> +
> +#define LM3601X_SW_RESET       BIT(7)
> +
> +/* Enable Mode bits */
> +#define LM3601X_MODE_STANDBY   0x00
> +#define LM3601X_MODE_IR_DRV    BIT(0)
> +#define LM3601X_MODE_TORCH     BIT(1)
> +#define LM3601X_MODE_STROBE    (BIT(0) | BIT(1))
> +#define LM3601X_STRB_EN                BIT(2)
> +#define LM3601X_STRB_EDGE_TRIG BIT(3)
> +#define LM3601X_IVFM_EN                BIT(4)
> +
> +#define LM36010_BOOST_LIMIT_28 BIT(5)
> +#define LM36010_BOOST_FREQ_4MHZ        BIT(6)
> +#define LM36010_BOOST_MODE_PASS        BIT(7)
> +
> +/* Flag Mask */
> +#define LM3601X_FLASH_TIME_OUT BIT(0)
> +#define LM3601X_UVLO_FAULT     BIT(1)
> +#define LM3601X_THERM_SHUTDOWN BIT(2)
> +#define LM3601X_THERM_CURR     BIT(3)
> +#define LM36010_CURR_LIMIT     BIT(4)
> +#define LM3601X_SHORT_FAULT    BIT(5)
> +#define LM3601X_IVFM_TRIP      BIT(6)
> +#define LM36010_OVP_FAULT      BIT(7)
> +
> +#define LM3601X_MAX_TORCH_I_UA 376000
> +#define LM3601X_MIN_TORCH_I_UA 2400
> +#define LM3601X_TORCH_REG_DIV  2965
> +
> +#define LM3601X_MAX_STROBE_I_UA        1500000
> +#define LM3601X_MIN_STROBE_I_UA        11000
> +#define LM3601X_STROBE_REG_DIV 11800
> +
> +#define LM3601X_TIMEOUT_MASK   0x1e
> +#define LM3601X_ENABLE_MASK    (LM3601X_MODE_IR_DRV | LM3601X_MODE_TORCH)
> +
> +#define LM3601X_LOWER_STEP_US  40000
> +#define LM3601X_UPPER_STEP_US  200000
> +#define LM3601X_MIN_TIMEOUT_US 40000
> +#define LM3601X_MAX_TIMEOUT_US 1600000
> +#define LM3601X_TIMEOUT_XOVER_US 400000
> +
> +enum lm3601x_type {
> +       CHIP_LM36010 = 0,
> +       CHIP_LM36011,
> +};
> +
> +/**
> + * struct lm3601x_led -
> + * @fled_cdev: flash LED class device pointer
> + * @client: Pointer to the I2C client
> + * @regmap: Devices register map
> + * @lock: Lock for reading/writing the device
> + * @led_name: LED label for the Torch or IR LED
> + * @flash_timeout: the timeout for the flash
> + * @last_flag: last known flags register value
> + * @torch_current_max: maximum current for the torch
> + * @flash_current_max: maximum current for the flash
> + * @max_flash_timeout: maximum timeout for the flash
> + * @led_mode: The mode to enable either IR or Torch
> + */
> +struct lm3601x_led {
> +       struct led_classdev_flash fled_cdev;
> +       struct i2c_client *client;
> +       struct regmap *regmap;
> +       struct mutex lock;
> +
> +       char led_name[LED_MAX_NAME_SIZE];
> +
> +       unsigned int flash_timeout;
> +       unsigned int last_flag;
> +
> +       u32 torch_current_max;
> +       u32 flash_current_max;
> +       u32 max_flash_timeout;
> +
> +       u32 led_mode;
> +};
> +
> +static const struct reg_default lm3601x_regmap_defs[] = {
> +       { LM3601X_ENABLE_REG, 0x20 },
> +       { LM3601X_CFG_REG, 0x15 },
> +       { LM3601X_LED_FLASH_REG, 0x00 },
> +       { LM3601X_LED_TORCH_REG, 0x00 },
> +};
> +
> +static bool lm3601x_volatile_reg(struct device *dev, unsigned int reg)
> +{
> +       switch (reg) {
> +       case LM3601X_FLAGS_REG:
> +               return true;
> +       default:
> +               return false;
> +       }
> +}
> +
> +static const struct regmap_config lm3601x_regmap = {
> +       .reg_bits = 8,
> +       .val_bits = 8,
> +
> +       .max_register = LM3601X_DEV_ID_REG,
> +       .reg_defaults = lm3601x_regmap_defs,
> +       .num_reg_defaults = ARRAY_SIZE(lm3601x_regmap_defs),
> +       .cache_type = REGCACHE_RBTREE,
> +       .volatile_reg = lm3601x_volatile_reg,
> +};
> +

> +static struct lm3601x_led *fled_cdev_to_led(
> +                               struct led_classdev_flash *fled_cdev)

Didn't notice before. This will look much better in one line.

> +{
> +       return container_of(fled_cdev, struct lm3601x_led, fled_cdev);
> +}
> +
> +static int lm3601x_read_faults(struct lm3601x_led *led)
> +{
> +       int flags_val;
> +       int ret;
> +
> +       ret = regmap_read(led->regmap, LM3601X_FLAGS_REG, &flags_val);
> +       if (ret < 0)
> +               return -EIO;
> +
> +       led->last_flag = 0;
> +
> +       if (flags_val & LM36010_OVP_FAULT)
> +               led->last_flag |= LED_FAULT_OVER_VOLTAGE;
> +
> +       if (flags_val & (LM3601X_THERM_SHUTDOWN | LM3601X_THERM_CURR))
> +               led->last_flag |= LED_FAULT_OVER_TEMPERATURE;
> +
> +       if (flags_val & LM3601X_SHORT_FAULT)
> +               led->last_flag |= LED_FAULT_SHORT_CIRCUIT;
> +
> +       if (flags_val & LM36010_CURR_LIMIT)
> +               led->last_flag |= LED_FAULT_OVER_CURRENT;
> +
> +       if (flags_val & LM3601X_UVLO_FAULT)
> +               led->last_flag |= LED_FAULT_UNDER_VOLTAGE;
> +
> +       if (flags_val & LM3601X_IVFM_TRIP)
> +               led->last_flag |= LED_FAULT_INPUT_VOLTAGE;
> +
> +       if (flags_val & LM3601X_THERM_SHUTDOWN)
> +               led->last_flag |= LED_FAULT_LED_OVER_TEMPERATURE;
> +
> +       return led->last_flag;
> +}
> +
> +static int lm3601x_brightness_set(struct led_classdev *cdev,
> +                                       enum led_brightness brightness)
> +{
> +       struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(cdev);
> +       struct lm3601x_led *led = fled_cdev_to_led(fled_cdev);
> +       int ret, led_mode_val;
> +
> +       mutex_lock(&led->lock);
> +
> +       ret = lm3601x_read_faults(led);
> +       if (ret < 0)
> +               goto out;
> +
> +       if (led->led_mode == LM3601X_LED_TORCH)
> +               led_mode_val = LM3601X_MODE_TORCH;
> +       else
> +               led_mode_val = LM3601X_MODE_IR_DRV;
> +
> +       if (brightness == LED_OFF) {
> +               ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
> +                                       led_mode_val, LED_OFF);
> +               goto out;
> +       }
> +
> +       ret = regmap_write(led->regmap, LM3601X_LED_TORCH_REG, brightness);
> +       if (ret < 0)
> +               goto out;
> +
> +       ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
> +                               LM3601X_MODE_TORCH | LM3601X_MODE_IR_DRV,
> +                               led_mode_val);
> +out:
> +       mutex_unlock(&led->lock);
> +       return ret;
> +}
> +
> +static int lm3601x_flash_set(struct led_classdev_flash *fled_cdev,
> +                               bool state)
> +{
> +       struct lm3601x_led *led = fled_cdev_to_led(fled_cdev);

> +       int timeout_reg_val = 0;

Redundant assignment.

> +       int current_timeout;
> +       int ret;
> +
> +       mutex_lock(&led->lock);
> +
> +       ret = regmap_read(led->regmap, LM3601X_CFG_REG, &current_timeout);
> +       if (ret < 0)
> +               goto out;
> +
> +       if (led->flash_timeout >= LM3601X_TIMEOUT_XOVER_US)
> +               timeout_reg_val = led->flash_timeout / LM3601X_UPPER_STEP_US + 0x07;
> +       else
> +               timeout_reg_val = led->flash_timeout / LM3601X_LOWER_STEP_US - 0x01;
> +
> +       if (led->flash_timeout != current_timeout)
> +               ret = regmap_update_bits(led->regmap, LM3601X_CFG_REG,
> +                                       LM3601X_TIMEOUT_MASK, timeout_reg_val);
> +
> +       if (state)
> +               ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
> +                                       LM3601X_MODE_TORCH | LM3601X_MODE_IR_DRV,
> +                                       LM3601X_MODE_STROBE);
> +       else
> +               ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
> +                                       LM3601X_MODE_STROBE, LED_OFF);
> +
> +       ret = lm3601x_read_faults(led);
> +out:
> +       mutex_unlock(&led->lock);
> +       return ret;
> +}
> +
> +static int lm3601x_flash_brightness_set(struct led_classdev_flash *fled_cdev,
> +                                       u32 brightness)
> +{
> +       struct lm3601x_led *led = fled_cdev_to_led(fled_cdev);

> +       int ret;
> +       u8 brightness_val;

Better to read reversed xmas tree order.

> +
> +       mutex_lock(&led->lock);
> +       ret = lm3601x_read_faults(led);
> +       if (ret < 0)
> +               goto out;
> +
> +       if (brightness == LED_OFF) {
> +               ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
> +                                       LM3601X_MODE_STROBE, LED_OFF);
> +               goto out;
> +       }
> +
> +       brightness_val = brightness / LM3601X_STROBE_REG_DIV;
> +
> +       ret = regmap_write(led->regmap, LM3601X_LED_FLASH_REG, brightness_val);
> +out:
> +       mutex_unlock(&led->lock);
> +       return ret;
> +}
> +
> +static int lm3601x_flash_timeout_set(struct led_classdev_flash *fled_cdev,
> +                               u32 timeout)
> +{
> +       struct lm3601x_led *led = fled_cdev_to_led(fled_cdev);

> +       int ret = 0;

Redundant variable.

> +
> +       mutex_lock(&led->lock);
> +
> +       led->flash_timeout = timeout;
> +
> +       mutex_unlock(&led->lock);
> +
> +       return ret;
> +}
> +
> +static int lm3601x_flash_get(struct led_classdev_flash *fled_cdev,
> +                               bool *state)
> +{
> +       struct lm3601x_led *led = fled_cdev_to_led(fled_cdev);
> +       int ret;
> +       int flash_state;
> +
> +       mutex_lock(&led->lock);
> +
> +       ret = regmap_read(led->regmap, LM3601X_ENABLE_REG, &flash_state);
> +       if (ret < 0)
> +               goto out;
> +
> +       *state = flash_state & LM3601X_MODE_STROBE;
> +
> +out:
> +       mutex_unlock(&led->lock);
> +       return ret;
> +}
> +
> +static int lm3601x_flash_fault_get(struct led_classdev_flash *fled_cdev,
> +                               u32 *fault)
> +{
> +       struct lm3601x_led *led = fled_cdev_to_led(fled_cdev);
> +
> +       lm3601x_read_faults(led);
> +
> +       *fault = led->last_flag;
> +
> +       return 0;
> +}
> +
> +static const struct led_flash_ops flash_ops = {
> +       .flash_brightness_set   = lm3601x_flash_brightness_set,
> +       .strobe_set             = lm3601x_flash_set,
> +       .strobe_get             = lm3601x_flash_get,
> +       .timeout_set            = lm3601x_flash_timeout_set,
> +       .fault_get              = lm3601x_flash_fault_get,
> +};
> +
> +static int lm3601x_register_leds(struct lm3601x_led *led)
> +{
> +       struct led_classdev *led_cdev;
> +       struct led_flash_setting *setting;
> +
> +       led->fled_cdev.ops = &flash_ops;
> +
> +       setting = &led->fled_cdev.timeout;
> +       setting->min = LM3601X_MIN_TIMEOUT_US;
> +       setting->max = led->max_flash_timeout;
> +       setting->step = LM3601X_LOWER_STEP_US;
> +       setting->val = led->max_flash_timeout;
> +
> +       setting = &led->fled_cdev.brightness;
> +       setting->min = LM3601X_MIN_STROBE_I_UA;
> +       setting->max = led->flash_current_max;
> +       setting->step = LM3601X_TORCH_REG_DIV;
> +       setting->val = led->flash_current_max;
> +
> +       led_cdev = &led->fled_cdev.led_cdev;
> +       led_cdev->name = led->led_name;
> +       led_cdev->brightness_set_blocking = lm3601x_brightness_set;
> +       led_cdev->max_brightness = DIV_ROUND_UP(led->torch_current_max,
> +                                               LM3601X_TORCH_REG_DIV);
> +       led_cdev->flags |= LED_DEV_CAP_FLASH;
> +
> +       return led_classdev_flash_register(&led->client->dev, &led->fled_cdev);
> +}
> +
> +static int lm3601x_parse_node(struct lm3601x_led *led,

> +                             struct device_node *node)

I don't see how it's used.

> +{
> +       struct fwnode_handle *child = NULL;
> +       int ret = -ENODEV;
> +       const char *name;
> +
> +       child = device_get_next_child_node(&led->client->dev, child);
> +       if (!child) {
> +               dev_err(&led->client->dev, "No LED Child node\n");
> +               return ret;
> +       }
> +
> +       ret = fwnode_property_read_u32(child, "reg", &led->led_mode);
> +       if (ret) {
> +               dev_err(&led->client->dev, "reg DT property missing\n");
> +               goto out_err;
> +       }
> +
> +       if (led->led_mode > LM3601X_LED_TORCH ||
> +           led->led_mode < LM3601X_LED_IR) {
> +               dev_warn(&led->client->dev, "Invalid led mode requested\n");
> +               ret = -EINVAL;
> +               goto out_err;
> +       }
> +
> +       ret = fwnode_property_read_string(child, "label", &name);
> +       if (ret) {
> +               if (led->led_mode == LM3601X_LED_TORCH)
> +                       name = "torch";
> +               else
> +                       name = "infrared";
> +       }
> +
> +       snprintf(led->led_name, sizeof(led->led_name),
> +               "%s:%s", led->client->name, name);
> +
> +       ret = fwnode_property_read_u32(child, "led-max-microamp",
> +                                       &led->torch_current_max);

> +       if (ret < 0) {

Be consistent with above or other way around.

> +               dev_warn(&led->client->dev,
> +                       "led-max-microamp DT property missing\n");
> +               goto out_err;
> +       }
> +
> +       ret = fwnode_property_read_u32(child, "flash-max-microamp",
> +                               &led->flash_current_max);
> +       if (ret < 0) {
> +               dev_warn(&led->client->dev,
> +                        "flash-max-microamp DT property missing\n");
> +               goto out_err;
> +       }
> +
> +       ret = fwnode_property_read_u32(child, "flash-max-timeout-us",
> +                               &led->max_flash_timeout);
> +       if (ret < 0) {
> +               dev_warn(&led->client->dev,
> +                        "flash-max-timeout-us DT property missing\n");
> +               goto out_err;
> +       }
> +
> +out_err:
> +       fwnode_handle_put(child);
> +       return ret;
> +}
> +
> +static int lm3601x_probe(struct i2c_client *client,
> +                       const struct i2c_device_id *id)
> +{
> +       struct lm3601x_led *led;

> +       int err;

Be consistent, either err everywhere, or ret.

> +
> +       led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL);
> +       if (!led)
> +               return -ENOMEM;
> +
> +       led->client = client;
> +       i2c_set_clientdata(client, led);
> +

> +       err = lm3601x_parse_node(led, client->dev.of_node);

Can't you use dev_fwnode() helper?
It seems it's even not used inside the function.

> +       if (err < 0)
> +               return -ENODEV;
> +
> +       led->regmap = devm_regmap_init_i2c(client, &lm3601x_regmap);
> +       if (IS_ERR(led->regmap)) {
> +               err = PTR_ERR(led->regmap);
> +               dev_err(&client->dev,
> +                       "Failed to allocate register map: %d\n", err);
> +               return err;
> +       }
> +
> +       mutex_init(&led->lock);
> +
> +       return lm3601x_register_leds(led);
> +}
> +
> +static int lm3601x_remove(struct i2c_client *client)
> +{
> +       struct lm3601x_led *led = i2c_get_clientdata(client);
> +
> +       led_classdev_flash_unregister(&led->fled_cdev);
> +       mutex_destroy(&led->lock);
> +
> +       return regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
> +                          LM3601X_ENABLE_MASK,
> +                          LM3601X_MODE_STANDBY);
> +}
> +

> +static const struct i2c_device_id lm3601x_id[] = {
> +       { "LM36010", CHIP_LM36010 },
> +       { "LM36011", CHIP_LM36011 },
> +       { }
> +};
> +MODULE_DEVICE_TABLE(i2c, lm3601x_id);

Are you going to use it as a pure i2c driver? If yes, I would like to hear why.
Otherwise just switch to ->probe_new().

> +
> +static const struct of_device_id of_lm3601x_leds_match[] = {
> +       { .compatible = "ti,lm36010", },
> +       { .compatible = "ti,lm36011", },
> +       { }
> +};
> +MODULE_DEVICE_TABLE(of, of_lm3601x_leds_match);
> +
> +static struct i2c_driver lm3601x_i2c_driver = {
> +       .driver = {
> +               .name = "lm3601x",
> +               .of_match_table = of_lm3601x_leds_match,
> +       },
> +       .probe = lm3601x_probe,
> +       .remove = lm3601x_remove,
> +       .id_table = lm3601x_id,
> +};
> +module_i2c_driver(lm3601x_i2c_driver);
> +
> +MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3601X");
> +MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
> +MODULE_LICENSE("GPL v2");
> --
> 2.17.0.582.gccdcbd54c
>



-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply

* Re: [PATCH] thermal: qcom: tsens: Allow number of sensors to come from DT
From: Rob Herring @ 2018-05-22 20:14 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Zhang Rui, Eduardo Valentin, Mark Rutland, Rajendra Nayak,
	linux-pm, devicetree, linux-kernel, linux-arm-msm
In-Reply-To: <20180507235339.8836-1-bjorn.andersson@linaro.org>

On Mon, May 07, 2018 at 04:53:39PM -0700, Bjorn Andersson wrote:
> For platforms that has multiple copies of the TSENS hardware block it's
> necessary to be able to specify the number of sensors per block in DeviceTree.
> 
> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> ---
>  .../devicetree/bindings/thermal/qcom-tsens.txt       |  1 +

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

>  drivers/thermal/qcom/tsens.c                         | 12 +++++++++---
>  2 files changed, 10 insertions(+), 3 deletions(-)

^ permalink raw reply

* Re: [PATCH 2/2] dt-bindings: Add compatible string for FRWY-LS1012A
From: Rob Herring @ 2018-05-22 20:15 UTC (permalink / raw)
  To: Bhaskar Upadhaya
  Cc: oss, devicetree, shawnguo, stuart.yoder, linux-arm-kernel
In-Reply-To: <1525760999-6187-2-git-send-email-Bhaskar.Upadhaya@nxp.com>

On Tue, May 08, 2018 at 11:59:59AM +0530, Bhaskar Upadhaya wrote:
> Signed-off-by: Bhaskar Upadhaya <Bhaskar.Upadhaya@nxp.com>
> ---
>  Documentation/devicetree/bindings/arm/fsl.txt | 4 ++++
>  1 file changed, 4 insertions(+)

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

^ permalink raw reply

* Re: [PATCH 2/8] dt-bindings: serial: Add bindings for nvidia,tegra194-tcu
From: Rob Herring @ 2018-05-22 20:18 UTC (permalink / raw)
  To: Jon Hunter
  Cc: Mikko Perttunen, mark.rutland, jassisinghbrar, gregkh,
	thierry.reding, araza, devicetree, linux-serial, linux-tegra,
	linux-arm-kernel, linux-kernel
In-Reply-To: <3ddaafbd-d8cb-3cca-be4e-8c5c53fd9734@nvidia.com>

On Tue, May 22, 2018 at 04:15:09PM +0100, Jon Hunter wrote:
> 
> On 08/05/18 12:43, Mikko Perttunen wrote:
> > Add bindings for the Tegra Combined UART device used to talk to the
> > UART console on Tegra194 systems.
> > 
> > Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
> > ---
> >   .../bindings/serial/nvidia,tegra194-tcu.txt        | 35 ++++++++++++++++++++++
> >   1 file changed, 35 insertions(+)
> >   create mode 100644 Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt
> > 
> > diff --git a/Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt b/Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt
> > new file mode 100644
> > index 000000000000..86763bc5d74f
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt
> > @@ -0,0 +1,35 @@
> > +NVIDIA Tegra Combined UART (TCU)
> > +
> > +The TCU is a system for sharing a hardware UART instance among multiple
> > +systems withing the Tegra SoC. It is implemented through a mailbox-
> > +based protocol where each "virtual UART" has a pair of mailboxes, one
> > +for transmitting and one for receiving, that is used to communicate
> > +with the hardware implementing the TCU.
> > +
> > +Required properties:
> > +- name : Should be tcu
> > +- compatible
> > +    Array of strings
> > +    One of:
> > +    - "nvidia,tegra194-tcu"
> 
> Nit. We should say what device the above compatibility is applicable for ...
> 
>     - "nvidia,tegra194-tcu": for Tegra194

Yeah, everyone seems to do that, but I find it to be redundant.

Rob

^ permalink raw reply

* Re: [PATCH 2/8] dt-bindings: serial: Add bindings for nvidia,tegra194-tcu
From: Rob Herring @ 2018-05-22 20:20 UTC (permalink / raw)
  To: Mikko Perttunen
  Cc: mark.rutland, jassisinghbrar, gregkh, thierry.reding, jonathanh,
	araza, devicetree, linux-serial, linux-tegra, linux-arm-kernel,
	linux-kernel
In-Reply-To: <20180508114403.14499-3-mperttunen@nvidia.com>

On Tue, May 08, 2018 at 02:43:57PM +0300, Mikko Perttunen wrote:
> Add bindings for the Tegra Combined UART device used to talk to the
> UART console on Tegra194 systems.
> 
> Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
> ---
>  .../bindings/serial/nvidia,tegra194-tcu.txt        | 35 ++++++++++++++++++++++
>  1 file changed, 35 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt
> 
> diff --git a/Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt b/Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt
> new file mode 100644
> index 000000000000..86763bc5d74f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt
> @@ -0,0 +1,35 @@
> +NVIDIA Tegra Combined UART (TCU)
> +
> +The TCU is a system for sharing a hardware UART instance among multiple
> +systems withing the Tegra SoC. It is implemented through a mailbox-

s/withing/within/

Otherwise,

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

> +based protocol where each "virtual UART" has a pair of mailboxes, one
> +for transmitting and one for receiving, that is used to communicate
> +with the hardware implementing the TCU.
> +
> +Required properties:
> +- name : Should be tcu
> +- compatible
> +    Array of strings
> +    One of:
> +    - "nvidia,tegra194-tcu"
> +- mbox-names:
> +    "rx" - Mailbox for receiving data from hardware UART
> +    "tx" - Mailbox for transmitting data to hardware UART
> +- mboxes: Mailboxes corresponding to the mbox-names. 
> +
> +This node is a mailbox consumer. See the following files for details of
> +the mailbox subsystem, and the specifiers implemented by the relevant
> +provider(s):
> +
> +- .../mailbox/mailbox.txt
> +- .../mailbox/nvidia,tegra186-hsp.txt
> +
> +Example bindings:
> +-----------------
> +
> +tcu: tcu {
> +	compatible = "nvidia,tegra194-tcu";
> +	mboxes = <&hsp_top0 TEGRA_HSP_MBOX_TYPE_SM 0>,
> +	         <&hsp_aon TEGRA_HSP_MBOX_TYPE_SM 1>;
> +	mbox-names = "rx", "tx";
> +};
> -- 
> 2.16.1
> 

^ permalink raw reply

* Re: [patch v21 2/4] drivers: jtag: Add Aspeed SoC 24xx and 25xx families JTAG master driver
From: Andy Shevchenko @ 2018-05-22 20:21 UTC (permalink / raw)
  To: Oleksandr Shamray
  Cc: Greg Kroah-Hartman, Arnd Bergmann, Linux Kernel Mailing List,
	linux-arm Mailing List, devicetree, openbmc@lists.ozlabs.org,
	Joel Stanley, Jiří Pírko, Tobias Klauser,
	open list:SERIAL DRIVERS, Vadim Pasternak, system-sw-low-level,
	Rob Herring, openocd-devel-owner@lists.sourceforge.net,
	linux-api@vger.kernel.org
In-Reply-To: <AM5PR0501MB244981D83DD33BD29FD64924B1940@AM5PR0501MB2449.eurprd05.prod.outlook.com>

On Tue, May 22, 2018 at 6:00 PM, Oleksandr Shamray
<oleksandrs@mellanox.com> wrote:


> Ok. Changed to:
> #define ASPEED_JTAG_IOUT_LEN(len) \
>                                (ASPEED_JTAG_CTL_ENG_EN | \
>                                ASPEED_JTAG_CTL_ENG_OUT_EN | \
>                                ASPEED_JTAG_CTL_INST_LEN(len))
>
> #define ASPEED_JTAG_DOUT_LEN(len) \
>                                (ASPEED_JTAG_CTL_ENG_EN | \
>                                ASPEED_JTAG_CTL_ENG_OUT_EN | \
>                                ASPEED_JTAG_CTL_DATA_LEN(len))

What about

#define _JTAG_OUT_ENABLE \
( _ENG_EN | _ENG_OUT_EN)

#define _IOUT_LEN(len) \
 (_ENABLE | _INST_LEN(len))

#define _DOUT_LEN(len) \
...

?

>> > +       apb_frq = clk_get_rate(aspeed_jtag->pclk);
>>
>> > +       div = (apb_frq % freq == 0) ? (apb_frq / freq) - 1 :
>> > + (apb_frq / freq);
>>
>> Isn't it the same as
>>
>> div = (apb_frq - 1) / freq;
>>
>> ?

> Seems it is same. Thanks.

Though be careful if apb_frq == 0.
In either case the hw will be screwed, but differently.

>> > +       if (xfer->direction == JTAG_READ_XFER)
>> > +               tdi = UINT_MAX;
>> > +       else
>> > +               tdi = data[index];
>>
>> > +                       if (xfer->direction == JTAG_READ_XFER)
>> > +                               tdi = UINT_MAX;
>> > +                       else
>> > +                               tdi = data[index];
>>
>> Take your time to think how the above duplication can be avoided.
>>
>
> In both cases data[] is different, so I should check it twice, but I will
> change it to, macro like:
>
> #define ASPEED_JTAG_GET_TDI(direction, data) \
>                               (direction == JTAG_READ_XFER) ? UNIT_MAX : data

Perhaps choose better name for data, b/c in the above you are using data[index].

>> > +               dev_err(aspeed_jtag->dev, "irq status:%x\n",
>> > +                       status);

>> Huh, really?! SPAM.

> I will review and delete redundant debug messages.

Just to be sure you got a point. This is interrupt context. Imagine
what might go wrong.


>> > +       err = jtag_register(jtag);
>>
>> Perhaps we might have devm_ variant of this. Check how SPI framework
>> deal with a such.
>>
>
> Jtag driver uses miscdevice and related  misc_register and misc_deregister
> calls for creation and destruction. There is no device object prior
> to call to misc_register, which could be used in devm_jtag_register.

Same question as per previous patch.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply

* [PATCH v2] ARM: pxa: dts: add pin definitions for extended GPIOs
From: Daniel Mack @ 2018-05-22 20:22 UTC (permalink / raw)
  To: robert.jarzmik, haojian.zhuang
  Cc: devicetree, robh+dt, Daniel Mack, linux-arm-kernel

The PXA3xx series features some extended GPIO banks which are named GPIO0_2,
GPIO1_2 etc. The PXA300, PXA310 and PXA320 have different numbers of such
pins, and they also have variant-specific register offsets.

Signed-off-by: Daniel Mack <daniel@zonque.org>
---
 arch/arm/boot/dts/pxa3xx.dtsi | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/arm/boot/dts/pxa3xx.dtsi b/arch/arm/boot/dts/pxa3xx.dtsi
index a13ac52e4fd2..99c3687e89d3 100644
--- a/arch/arm/boot/dts/pxa3xx.dtsi
+++ b/arch/arm/boot/dts/pxa3xx.dtsi
@@ -8,6 +8,10 @@
 	 (gpio <= 98) ? (0x0400 + 4 * (gpio - 27)) :	\
 	 (gpio <= 127) ? (0x0600 + 4 * (gpio - 99)) :	\
 	 0)
+#define MFP_PIN_PXA300_2(gpio)				\
+	((gpio <= 1) ? (0x674 + 4 * gpio) :		\
+	 (gpio <= 6) ? (0x2dc + 4 * gpio) :		\
+	 0)
 
 #define MFP_PIN_PXA310(gpio)				\
 	((gpio <= 2) ? (0x00b4 + 4 * gpio) :		\
@@ -18,6 +22,11 @@
 	 (gpio <= 262) ? 0 :				\
 	 (gpio <= 268) ? (0x052c + 4 * (gpio - 263)) :	\
 	 0)
+#define MFP_PIN_PXA310_2(gpio)				\
+	((gpio <= 1) ? (0x674 + 4 * gpio) :		\
+	 (gpio <= 6) ? (0x2dc + 4 * gpio) :		\
+	 (gpio <= 10) ? (0x52c + 4 * gpio) :		\
+	 0)
 
 #define MFP_PIN_PXA320(gpio)				\
 	((gpio <= 4) ? (0x0124 + 4 * gpio) :		\
@@ -30,6 +39,10 @@
 	 (gpio <= 98) ? (0x04f0 + 4 * (gpio - 74)) :	\
 	 (gpio <= 127) ? (0x0600 + 4 * (gpio - 99)) :	\
 	 0)
+#define MFP_PIN_PXA320_2(gpio)				\
+	((gpio <= 3) ? (0x674 + 4 * gpio) :		\
+	 (gpio <= 5) ? (0x284 + 4 * gpio) :		\
+	 0)
 
 /*
  * MFP Alternate functions for pins having a gpio.
-- 
2.14.3

^ permalink raw reply related

* Re: [PATCH v8 2/2] leds: lm3601x: Introduce the lm3601x LED driver
From: Dan Murphy @ 2018-05-22 20:26 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Rob Herring, Mark Rutland, Jacek Anaszewski, devicetree,
	Linux Kernel Mailing List, Linux LED Subsystem
In-Reply-To: <CAHp75VfTtD3Mnyqb63R_BP8BoAGNZProLCgWoDMo-aTk5C-iVA@mail.gmail.com>

On 05/22/2018 03:12 PM, Andy Shevchenko wrote:
> On Tue, May 22, 2018 at 5:24 PM, Dan Murphy <dmurphy@ti.com> wrote:
>> Introduce the family of LED devices that can
>> drive a torch, strobe or IR LED.
>>
>> The LED driver can be configured with a strobe
>> timer to execute a strobe flash.  The IR LED
>> brightness is controlled via the torch brightness
>> register.
>>
>> The data sheet for each the LM36010 and LM36011
>> LED drivers can be found here:
>> http://www.ti.com/product/LM36010
>> http://www.ti.com/product/LM36011
>>
>> Signed-off-by: Dan Murphy <dmurphy@ti.com>
>> ---
>>
>> v8 - Removed OF Kconfig dependency, change strobe to flash, updated label generation,
>> fixed brightness calculation, added mutex_destroy and flash_unregister - https://patchwork.kernel.org/patch/10416163/
>>
>> v7 - Numerous fixes to many to list.  Highlights are moved from OF APIs to device_property
>> APIs, updated LED registration, timeout to reg algorithim, and fixed label generation -
>> https://patchwork.kernel.org/patch/10401437/
>> v6 - This driver has been heavily modified from v5.  There is no longer reading
>> of individual child nodes.  There are too many changes to list here see -
>> https://patchwork.kernel.org/patch/10392123/
>> v5 - Fixed magic numbers, change reg cache type, added of_put_node to release
>> the dt node ref, and I did not change the remove function to leave the LED in its
>> state on driver removal - https://patchwork.kernel.org/patch/10391741/
>> v4 - Fixed Cocci issue using ARRAY_SIZE - https://patchwork.kernel.org/patch/10389259/
>> v3 - removed wildcard dt compatible, fixed copyright, fixed struct doc, removed
>> RO registers from default, added regmap volatile for FLAGS_REG, updated regmap cache type,
>> fixed unlock and extra semi colon in strobe_set, removed unnecessary out label
>> in led register and fixed checking of the ret in brightness_set - https://patchwork.kernel.org/patch/10386243/
>> v2 - Fixed kbuild issue and removed unused cdev_strobe - https://patchwork.kernel.org/patch/10384585/
>>
>>
>>  drivers/leds/Kconfig        |   9 +
>>  drivers/leds/Makefile       |   1 +
>>  drivers/leds/leds-lm3601x.c | 492 ++++++++++++++++++++++++++++++++++++
>>  3 files changed, 502 insertions(+)
>>  create mode 100644 drivers/leds/leds-lm3601x.c
>>
>> diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
>> index 2c896c0e69e1..d95d436e6089 100644
>> --- a/drivers/leds/Kconfig
>> +++ b/drivers/leds/Kconfig
>> @@ -145,6 +145,15 @@ config LEDS_LM3692X
>>           This option enables support for the TI LM3692x family
>>           of white LED string drivers used for backlighting.
>>
>> +config LEDS_LM3601X
>> +       tristate "LED support for LM3601x Chips"
>> +       depends on LEDS_CLASS && I2C
>> +       depends on LEDS_CLASS_FLASH
>> +       select REGMAP_I2C
>> +       help
>> +         This option enables support for the TI LM3601x family
>> +         of flash, torch and indicator classes.
>> +
>>  config LEDS_LOCOMO
>>         tristate "LED Support for Locomo device"
>>         depends on LEDS_CLASS
>> diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
>> index 91eca81cae82..b79807fe1b67 100644
>> --- a/drivers/leds/Makefile
>> +++ b/drivers/leds/Makefile
>> @@ -76,6 +76,7 @@ obj-$(CONFIG_LEDS_MLXREG)             += leds-mlxreg.o
>>  obj-$(CONFIG_LEDS_NIC78BX)             += leds-nic78bx.o
>>  obj-$(CONFIG_LEDS_MT6323)              += leds-mt6323.o
>>  obj-$(CONFIG_LEDS_LM3692X)             += leds-lm3692x.o
>> +obj-$(CONFIG_LEDS_LM3601X)             += leds-lm3601x.o
>>
>>  # LED SPI Drivers
>>  obj-$(CONFIG_LEDS_DAC124S085)          += leds-dac124s085.o
>> diff --git a/drivers/leds/leds-lm3601x.c b/drivers/leds/leds-lm3601x.c
>> new file mode 100644
>> index 000000000000..b1f0ede704c1
>> --- /dev/null
>> +++ b/drivers/leds/leds-lm3601x.c
>> @@ -0,0 +1,492 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +// Flash and torch driver for Texas Instruments LM3601X LED
>> +// Flash driver chip family
>> +// Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
>> +
>> +#include <linux/delay.h>
>> +#include <linux/i2c.h>
>> +#include <linux/leds.h>
>> +#include <linux/led-class-flash.h>
>> +#include <linux/module.h>
>> +#include <linux/regmap.h>
>> +#include <linux/slab.h>
>> +#include <uapi/linux/uleds.h>
>> +
>> +#define LM3601X_LED_IR         0x0
>> +#define LM3601X_LED_TORCH      0x1
>> +
>> +/* Registers */
>> +#define LM3601X_ENABLE_REG     0x01
>> +#define LM3601X_CFG_REG                0x02
>> +#define LM3601X_LED_FLASH_REG  0x03
>> +#define LM3601X_LED_TORCH_REG  0x04
>> +#define LM3601X_FLAGS_REG      0x05
>> +#define LM3601X_DEV_ID_REG     0x06
>> +
>> +#define LM3601X_SW_RESET       BIT(7)
>> +
>> +/* Enable Mode bits */
>> +#define LM3601X_MODE_STANDBY   0x00
>> +#define LM3601X_MODE_IR_DRV    BIT(0)
>> +#define LM3601X_MODE_TORCH     BIT(1)
>> +#define LM3601X_MODE_STROBE    (BIT(0) | BIT(1))
>> +#define LM3601X_STRB_EN                BIT(2)
>> +#define LM3601X_STRB_EDGE_TRIG BIT(3)
>> +#define LM3601X_IVFM_EN                BIT(4)
>> +
>> +#define LM36010_BOOST_LIMIT_28 BIT(5)
>> +#define LM36010_BOOST_FREQ_4MHZ        BIT(6)
>> +#define LM36010_BOOST_MODE_PASS        BIT(7)
>> +
>> +/* Flag Mask */
>> +#define LM3601X_FLASH_TIME_OUT BIT(0)
>> +#define LM3601X_UVLO_FAULT     BIT(1)
>> +#define LM3601X_THERM_SHUTDOWN BIT(2)
>> +#define LM3601X_THERM_CURR     BIT(3)
>> +#define LM36010_CURR_LIMIT     BIT(4)
>> +#define LM3601X_SHORT_FAULT    BIT(5)
>> +#define LM3601X_IVFM_TRIP      BIT(6)
>> +#define LM36010_OVP_FAULT      BIT(7)
>> +
>> +#define LM3601X_MAX_TORCH_I_UA 376000
>> +#define LM3601X_MIN_TORCH_I_UA 2400
>> +#define LM3601X_TORCH_REG_DIV  2965
>> +
>> +#define LM3601X_MAX_STROBE_I_UA        1500000
>> +#define LM3601X_MIN_STROBE_I_UA        11000
>> +#define LM3601X_STROBE_REG_DIV 11800
>> +
>> +#define LM3601X_TIMEOUT_MASK   0x1e
>> +#define LM3601X_ENABLE_MASK    (LM3601X_MODE_IR_DRV | LM3601X_MODE_TORCH)
>> +
>> +#define LM3601X_LOWER_STEP_US  40000
>> +#define LM3601X_UPPER_STEP_US  200000
>> +#define LM3601X_MIN_TIMEOUT_US 40000
>> +#define LM3601X_MAX_TIMEOUT_US 1600000
>> +#define LM3601X_TIMEOUT_XOVER_US 400000
>> +
>> +enum lm3601x_type {
>> +       CHIP_LM36010 = 0,
>> +       CHIP_LM36011,
>> +};
>> +
>> +/**
>> + * struct lm3601x_led -
>> + * @fled_cdev: flash LED class device pointer
>> + * @client: Pointer to the I2C client
>> + * @regmap: Devices register map
>> + * @lock: Lock for reading/writing the device
>> + * @led_name: LED label for the Torch or IR LED
>> + * @flash_timeout: the timeout for the flash
>> + * @last_flag: last known flags register value
>> + * @torch_current_max: maximum current for the torch
>> + * @flash_current_max: maximum current for the flash
>> + * @max_flash_timeout: maximum timeout for the flash
>> + * @led_mode: The mode to enable either IR or Torch
>> + */
>> +struct lm3601x_led {
>> +       struct led_classdev_flash fled_cdev;
>> +       struct i2c_client *client;
>> +       struct regmap *regmap;
>> +       struct mutex lock;
>> +
>> +       char led_name[LED_MAX_NAME_SIZE];
>> +
>> +       unsigned int flash_timeout;
>> +       unsigned int last_flag;
>> +
>> +       u32 torch_current_max;
>> +       u32 flash_current_max;
>> +       u32 max_flash_timeout;
>> +
>> +       u32 led_mode;
>> +};
>> +
>> +static const struct reg_default lm3601x_regmap_defs[] = {
>> +       { LM3601X_ENABLE_REG, 0x20 },
>> +       { LM3601X_CFG_REG, 0x15 },
>> +       { LM3601X_LED_FLASH_REG, 0x00 },
>> +       { LM3601X_LED_TORCH_REG, 0x00 },
>> +};
>> +
>> +static bool lm3601x_volatile_reg(struct device *dev, unsigned int reg)
>> +{
>> +       switch (reg) {
>> +       case LM3601X_FLAGS_REG:
>> +               return true;
>> +       default:
>> +               return false;
>> +       }
>> +}
>> +
>> +static const struct regmap_config lm3601x_regmap = {
>> +       .reg_bits = 8,
>> +       .val_bits = 8,
>> +
>> +       .max_register = LM3601X_DEV_ID_REG,
>> +       .reg_defaults = lm3601x_regmap_defs,
>> +       .num_reg_defaults = ARRAY_SIZE(lm3601x_regmap_defs),
>> +       .cache_type = REGCACHE_RBTREE,
>> +       .volatile_reg = lm3601x_volatile_reg,
>> +};
>> +
> 
>> +static struct lm3601x_led *fled_cdev_to_led(
>> +                               struct led_classdev_flash *fled_cdev)
> 
> Didn't notice before. This will look much better in one line.

Gives LTL warning.

> 
>> +{
>> +       return container_of(fled_cdev, struct lm3601x_led, fled_cdev);
>> +}
>> +
>> +static int lm3601x_read_faults(struct lm3601x_led *led)
>> +{
>> +       int flags_val;
>> +       int ret;
>> +
>> +       ret = regmap_read(led->regmap, LM3601X_FLAGS_REG, &flags_val);
>> +       if (ret < 0)
>> +               return -EIO;
>> +
>> +       led->last_flag = 0;
>> +
>> +       if (flags_val & LM36010_OVP_FAULT)
>> +               led->last_flag |= LED_FAULT_OVER_VOLTAGE;
>> +
>> +       if (flags_val & (LM3601X_THERM_SHUTDOWN | LM3601X_THERM_CURR))
>> +               led->last_flag |= LED_FAULT_OVER_TEMPERATURE;
>> +
>> +       if (flags_val & LM3601X_SHORT_FAULT)
>> +               led->last_flag |= LED_FAULT_SHORT_CIRCUIT;
>> +
>> +       if (flags_val & LM36010_CURR_LIMIT)
>> +               led->last_flag |= LED_FAULT_OVER_CURRENT;
>> +
>> +       if (flags_val & LM3601X_UVLO_FAULT)
>> +               led->last_flag |= LED_FAULT_UNDER_VOLTAGE;
>> +
>> +       if (flags_val & LM3601X_IVFM_TRIP)
>> +               led->last_flag |= LED_FAULT_INPUT_VOLTAGE;
>> +
>> +       if (flags_val & LM3601X_THERM_SHUTDOWN)
>> +               led->last_flag |= LED_FAULT_LED_OVER_TEMPERATURE;
>> +
>> +       return led->last_flag;
>> +}
>> +
>> +static int lm3601x_brightness_set(struct led_classdev *cdev,
>> +                                       enum led_brightness brightness)
>> +{
>> +       struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(cdev);
>> +       struct lm3601x_led *led = fled_cdev_to_led(fled_cdev);
>> +       int ret, led_mode_val;
>> +
>> +       mutex_lock(&led->lock);
>> +
>> +       ret = lm3601x_read_faults(led);
>> +       if (ret < 0)
>> +               goto out;
>> +
>> +       if (led->led_mode == LM3601X_LED_TORCH)
>> +               led_mode_val = LM3601X_MODE_TORCH;
>> +       else
>> +               led_mode_val = LM3601X_MODE_IR_DRV;
>> +
>> +       if (brightness == LED_OFF) {
>> +               ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
>> +                                       led_mode_val, LED_OFF);
>> +               goto out;
>> +       }
>> +
>> +       ret = regmap_write(led->regmap, LM3601X_LED_TORCH_REG, brightness);
>> +       if (ret < 0)
>> +               goto out;
>> +
>> +       ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
>> +                               LM3601X_MODE_TORCH | LM3601X_MODE_IR_DRV,
>> +                               led_mode_val);
>> +out:
>> +       mutex_unlock(&led->lock);
>> +       return ret;
>> +}
>> +
>> +static int lm3601x_flash_set(struct led_classdev_flash *fled_cdev,
>> +                               bool state)
>> +{
>> +       struct lm3601x_led *led = fled_cdev_to_led(fled_cdev);
> 
>> +       int timeout_reg_val = 0;
> 
> Redundant assignment.

OK

> 
>> +       int current_timeout;
>> +       int ret;
>> +
>> +       mutex_lock(&led->lock);
>> +
>> +       ret = regmap_read(led->regmap, LM3601X_CFG_REG, &current_timeout);
>> +       if (ret < 0)
>> +               goto out;
>> +
>> +       if (led->flash_timeout >= LM3601X_TIMEOUT_XOVER_US)
>> +               timeout_reg_val = led->flash_timeout / LM3601X_UPPER_STEP_US + 0x07;
>> +       else
>> +               timeout_reg_val = led->flash_timeout / LM3601X_LOWER_STEP_US - 0x01;
>> +
>> +       if (led->flash_timeout != current_timeout)
>> +               ret = regmap_update_bits(led->regmap, LM3601X_CFG_REG,
>> +                                       LM3601X_TIMEOUT_MASK, timeout_reg_val);
>> +
>> +       if (state)
>> +               ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
>> +                                       LM3601X_MODE_TORCH | LM3601X_MODE_IR_DRV,
>> +                                       LM3601X_MODE_STROBE);
>> +       else
>> +               ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
>> +                                       LM3601X_MODE_STROBE, LED_OFF);
>> +
>> +       ret = lm3601x_read_faults(led);
>> +out:
>> +       mutex_unlock(&led->lock);
>> +       return ret;
>> +}
>> +
>> +static int lm3601x_flash_brightness_set(struct led_classdev_flash *fled_cdev,
>> +                                       u32 brightness)
>> +{
>> +       struct lm3601x_led *led = fled_cdev_to_led(fled_cdev);
> 
>> +       int ret;
>> +       u8 brightness_val;
> 
> Better to read reversed xmas tree order.

ok

> 
>> +
>> +       mutex_lock(&led->lock);
>> +       ret = lm3601x_read_faults(led);
>> +       if (ret < 0)
>> +               goto out;
>> +
>> +       if (brightness == LED_OFF) {
>> +               ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
>> +                                       LM3601X_MODE_STROBE, LED_OFF);
>> +               goto out;
>> +       }
>> +
>> +       brightness_val = brightness / LM3601X_STROBE_REG_DIV;
>> +
>> +       ret = regmap_write(led->regmap, LM3601X_LED_FLASH_REG, brightness_val);
>> +out:
>> +       mutex_unlock(&led->lock);
>> +       return ret;
>> +}
>> +
>> +static int lm3601x_flash_timeout_set(struct led_classdev_flash *fled_cdev,
>> +                               u32 timeout)
>> +{
>> +       struct lm3601x_led *led = fled_cdev_to_led(fled_cdev);
> 
>> +       int ret = 0;
> 
> Redundant variable.

Removed

> 
>> +
>> +       mutex_lock(&led->lock);
>> +
>> +       led->flash_timeout = timeout;
>> +
>> +       mutex_unlock(&led->lock);
>> +
>> +       return ret;
>> +}
>> +
>> +static int lm3601x_flash_get(struct led_classdev_flash *fled_cdev,
>> +                               bool *state)
>> +{
>> +       struct lm3601x_led *led = fled_cdev_to_led(fled_cdev);
>> +       int ret;
>> +       int flash_state;
>> +
>> +       mutex_lock(&led->lock);
>> +
>> +       ret = regmap_read(led->regmap, LM3601X_ENABLE_REG, &flash_state);
>> +       if (ret < 0)
>> +               goto out;
>> +
>> +       *state = flash_state & LM3601X_MODE_STROBE;
>> +
>> +out:
>> +       mutex_unlock(&led->lock);
>> +       return ret;
>> +}
>> +
>> +static int lm3601x_flash_fault_get(struct led_classdev_flash *fled_cdev,
>> +                               u32 *fault)
>> +{
>> +       struct lm3601x_led *led = fled_cdev_to_led(fled_cdev);
>> +
>> +       lm3601x_read_faults(led);
>> +
>> +       *fault = led->last_flag;
>> +
>> +       return 0;
>> +}
>> +
>> +static const struct led_flash_ops flash_ops = {
>> +       .flash_brightness_set   = lm3601x_flash_brightness_set,
>> +       .strobe_set             = lm3601x_flash_set,
>> +       .strobe_get             = lm3601x_flash_get,
>> +       .timeout_set            = lm3601x_flash_timeout_set,
>> +       .fault_get              = lm3601x_flash_fault_get,
>> +};
>> +
>> +static int lm3601x_register_leds(struct lm3601x_led *led)
>> +{
>> +       struct led_classdev *led_cdev;
>> +       struct led_flash_setting *setting;
>> +
>> +       led->fled_cdev.ops = &flash_ops;
>> +
>> +       setting = &led->fled_cdev.timeout;
>> +       setting->min = LM3601X_MIN_TIMEOUT_US;
>> +       setting->max = led->max_flash_timeout;
>> +       setting->step = LM3601X_LOWER_STEP_US;
>> +       setting->val = led->max_flash_timeout;
>> +
>> +       setting = &led->fled_cdev.brightness;
>> +       setting->min = LM3601X_MIN_STROBE_I_UA;
>> +       setting->max = led->flash_current_max;
>> +       setting->step = LM3601X_TORCH_REG_DIV;
>> +       setting->val = led->flash_current_max;
>> +
>> +       led_cdev = &led->fled_cdev.led_cdev;
>> +       led_cdev->name = led->led_name;
>> +       led_cdev->brightness_set_blocking = lm3601x_brightness_set;
>> +       led_cdev->max_brightness = DIV_ROUND_UP(led->torch_current_max,
>> +                                               LM3601X_TORCH_REG_DIV);
>> +       led_cdev->flags |= LED_DEV_CAP_FLASH;
>> +
>> +       return led_classdev_flash_register(&led->client->dev, &led->fled_cdev);
>> +}
>> +
>> +static int lm3601x_parse_node(struct lm3601x_led *led,
> 
>> +                             struct device_node *node)
> 
> I don't see how it's used.

Removed

> 
>> +{
>> +       struct fwnode_handle *child = NULL;
>> +       int ret = -ENODEV;
>> +       const char *name;
>> +
>> +       child = device_get_next_child_node(&led->client->dev, child);
>> +       if (!child) {
>> +               dev_err(&led->client->dev, "No LED Child node\n");
>> +               return ret;
>> +       }
>> +
>> +       ret = fwnode_property_read_u32(child, "reg", &led->led_mode);
>> +       if (ret) {
>> +               dev_err(&led->client->dev, "reg DT property missing\n");
>> +               goto out_err;
>> +       }
>> +
>> +       if (led->led_mode > LM3601X_LED_TORCH ||
>> +           led->led_mode < LM3601X_LED_IR) {
>> +               dev_warn(&led->client->dev, "Invalid led mode requested\n");
>> +               ret = -EINVAL;
>> +               goto out_err;
>> +       }
>> +
>> +       ret = fwnode_property_read_string(child, "label", &name);
>> +       if (ret) {
>> +               if (led->led_mode == LM3601X_LED_TORCH)
>> +                       name = "torch";
>> +               else
>> +                       name = "infrared";
>> +       }
>> +
>> +       snprintf(led->led_name, sizeof(led->led_name),
>> +               "%s:%s", led->client->name, name);
>> +
>> +       ret = fwnode_property_read_u32(child, "led-max-microamp",
>> +                                       &led->torch_current_max);
> 
>> +       if (ret < 0) {
> 
> Be consistent with above or other way around.

Fixed

> 
>> +               dev_warn(&led->client->dev,
>> +                       "led-max-microamp DT property missing\n");
>> +               goto out_err;
>> +       }
>> +
>> +       ret = fwnode_property_read_u32(child, "flash-max-microamp",
>> +                               &led->flash_current_max);
>> +       if (ret < 0) {
>> +               dev_warn(&led->client->dev,
>> +                        "flash-max-microamp DT property missing\n");
>> +               goto out_err;
>> +       }
>> +
>> +       ret = fwnode_property_read_u32(child, "flash-max-timeout-us",
>> +                               &led->max_flash_timeout);
>> +       if (ret < 0) {
>> +               dev_warn(&led->client->dev,
>> +                        "flash-max-timeout-us DT property missing\n");
>> +               goto out_err;
>> +       }
>> +
>> +out_err:
>> +       fwnode_handle_put(child);
>> +       return ret;
>> +}
>> +
>> +static int lm3601x_probe(struct i2c_client *client,
>> +                       const struct i2c_device_id *id)
>> +{
>> +       struct lm3601x_led *led;
> 
>> +       int err;
> 
> Be consistent, either err everywhere, or ret.

Seems pedantic but I will change it

> 
>> +
>> +       led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL);
>> +       if (!led)
>> +               return -ENOMEM;
>> +
>> +       led->client = client;
>> +       i2c_set_clientdata(client, led);
>> +
> 
>> +       err = lm3601x_parse_node(led, client->dev.of_node);
> 
> Can't you use dev_fwnode() helper?
> It seems it's even not used inside the function.

Dropping of_node anyway it is unused

> 
>> +       if (err < 0)
>> +               return -ENODEV;
>> +
>> +       led->regmap = devm_regmap_init_i2c(client, &lm3601x_regmap);
>> +       if (IS_ERR(led->regmap)) {
>> +               err = PTR_ERR(led->regmap);
>> +               dev_err(&client->dev,
>> +                       "Failed to allocate register map: %d\n", err);
>> +               return err;
>> +       }
>> +
>> +       mutex_init(&led->lock);
>> +
>> +       return lm3601x_register_leds(led);
>> +}
>> +
>> +static int lm3601x_remove(struct i2c_client *client)
>> +{
>> +       struct lm3601x_led *led = i2c_get_clientdata(client);
>> +
>> +       led_classdev_flash_unregister(&led->fled_cdev);
>> +       mutex_destroy(&led->lock);
>> +
>> +       return regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
>> +                          LM3601X_ENABLE_MASK,
>> +                          LM3601X_MODE_STANDBY);
>> +}
>> +
> 
>> +static const struct i2c_device_id lm3601x_id[] = {
>> +       { "LM36010", CHIP_LM36010 },
>> +       { "LM36011", CHIP_LM36011 },
>> +       { }
>> +};
>> +MODULE_DEVICE_TABLE(i2c, lm3601x_id);
> 
> Are you going to use it as a pure i2c driver? If yes, I would like to hear why.
> Otherwise just switch to ->probe_new().

I was going to use the id variable but with code changes I don't use it anymore so
I can convert the driver.

Dan

> 
>> +
>> +static const struct of_device_id of_lm3601x_leds_match[] = {
>> +       { .compatible = "ti,lm36010", },
>> +       { .compatible = "ti,lm36011", },
>> +       { }
>> +};
>> +MODULE_DEVICE_TABLE(of, of_lm3601x_leds_match);
>> +
>> +static struct i2c_driver lm3601x_i2c_driver = {
>> +       .driver = {
>> +               .name = "lm3601x",
>> +               .of_match_table = of_lm3601x_leds_match,
>> +       },
>> +       .probe = lm3601x_probe,
>> +       .remove = lm3601x_remove,
>> +       .id_table = lm3601x_id,
>> +};
>> +module_i2c_driver(lm3601x_i2c_driver);
>> +
>> +MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3601X");
>> +MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
>> +MODULE_LICENSE("GPL v2");
>> --
>> 2.17.0.582.gccdcbd54c
>>
> 
> 
> 


-- 
------------------
Dan Murphy

^ permalink raw reply

* Re: [PATCH v8 2/2] leds: lm3601x: Introduce the lm3601x LED driver
From: Andy Shevchenko @ 2018-05-22 20:34 UTC (permalink / raw)
  To: Dan Murphy
  Cc: Rob Herring, Mark Rutland, Jacek Anaszewski, devicetree,
	Linux Kernel Mailing List, Linux LED Subsystem
In-Reply-To: <dca52e6e-451c-2ca4-a001-867708622d7b@ti.com>

On Tue, May 22, 2018 at 11:26 PM, Dan Murphy <dmurphy@ti.com> wrote:
> On 05/22/2018 03:12 PM, Andy Shevchenko wrote:
>> On Tue, May 22, 2018 at 5:24 PM, Dan Murphy <dmurphy@ti.com> wrote:


>>> +static struct lm3601x_led *fled_cdev_to_led(
>>> +                               struct led_classdev_flash *fled_cdev)
>>
>> Didn't notice before. This will look much better in one line.
>
> Gives LTL warning.

I wouldn't really care about it.
But I leave to Jacek to decide.

After addressing the rest, FWIW,

Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>

-- 
With Best Regards,
Andy Shevchenko

^ 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