Re: [PATCH 17/17] staging: nuc-led: update the TODOs

2021-05-17 Thread Mauro Carvalho Chehab
Em Mon, 17 May 2021 10:05:27 +0200
Pavel Machek  escreveu:

> No. Take a look at triggers; for example hdd monitor should look very
> much like existing disk trigger.

Hmm... after looking at triggers, I'm not sure if this is the right
interface, nor if we're talking about the same thing.

See, at least the way ledtrig-disk.c uses it, two drivers are triggering 
the LED based on software events:

drivers/ata/libata-core.c:  ledtrig_disk_activity(!!(qc->tf.flags & 
ATA_TFLAG_WRITE));
drivers/ide/ide-disk.c: ledtrig_disk_activity(rq_data_dir(rq) == WRITE);

This is not how the NUC LEDs are work. On NUC, the hardware itself 
triggers the event and/or blinks the LED(*).

(*) By default, blink is enabled only when the device is suspended
or it is hibernating.

There's no need to do any software emulation.

The API is meant to just program the hardware (and/or the firmware) 
for it to do the behavior expected by the user.

So, for instance, setting the indicator event that will trigger the
LED is done by sending a WMI message for this GUID object:
8C5DA44C-CDC3-46b3-8619-4E26D34390B7 (somewhat similar to using
the way ACPI works, but WMI is a different firmware interface).

The method at the WMI API which sets the LED indicator is this one:

0x05 message (Set an Indicator option for the LED type)

Such method receives two parameters. The first one is the LED 
number, which can be:

0 - Power button LED
1 - HDD LED
2 - Skull LED
3 - Eyes LED
4 - Front LED 1
5 - Front LED 1
6 - Front LED 1

The second one tells which hardware event will trigger the LED:

=   ==  ===
Value   Indicator type  Meaning
=   ==  ===
0   Power State Shows if the device is powered and what power level
it is (e. g. if the device is suspended or not, and
on which kind of suspended level).
1   HDD ActivityIndicates if the LED is measuring the hard disk (or
SDD) activity.
2   EthernetIndicates the activity Ethernet adapter(s)
3   WiFiIndicates if WiFi is enabled
4   SoftwareDoesn't indicate any hardware level. Instead, the LED
status is controlled via software.
5   Power Limit Changes the LED color when the computer is throttling
its power limits.
6   Disable The LED was disabled (either by BIOS or via WMI).
=   ==  ===

There is an example at page 7 of the datasheet:


https://raw.githubusercontent.com/nomego/intel_nuc_led/master/specs/INTEL_WMI_LED_0.64.pdf

Where it shows what happens if the WMI message is filled with:

<0x05>  <0x00>  <0x01>

On such example, it changes the behavior of the button named "Power button" 
to change it to monitor the disk activity, instead of monitoring if the
device is powered on or not.

Such setting is even persistent after rebooting, and the event is
hardware/firmware triggered.

So, IMO, it would only makes sense to use something else from the LED
class if are there a way for the sysfs nodes to dynamically be shown/hidden
when the indicator changes.

At least on my eyes, that doesn't seem to be what triggers do.

Thanks,
Mauro
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 17/17] staging: nuc-led: update the TODOs

2021-05-17 Thread Mauro Carvalho Chehab
Em Mon, 17 May 2021 10:57:49 +0200
Mauro Carvalho Chehab  escreveu:

> Em Mon, 17 May 2021 10:05:27 +0200
> Pavel Machek  escreveu:

> > No. Take a look at triggers; for example hdd monitor should look very
> > much like existing disk trigger.  

Btw, is there a way to trigger brightness?

When a LED is monitoring the power state, brightness should be
hidden, as, instead of a single brightness parameter, the device
will now have one brightness per different power state, e. g.:

When the LED indicator is measuring *Power State*, the following 
parameters may be available:

=   ===
Parameter   Meaning
=   ===
_brightnessBrightness in percent (from 0 to 100)
_blink_behaviortype of blink.
See :ref:`nuc_blink_behavior`.
_blink_frequency   Blink frequency.
See :ref:`nuc_blink_behavior`.
_color LED color
See :ref:`nuc_color`.
=   ===

Where  is different, depending on the WMI API version:

On version 0.64 (NUC8/9):

++
| s0 |
++
| s3 |
++
| s5 |
++
| ready_mode |
++

Btw, I've no idea what "ready mode" is, as the specs don't explain it.
This particular mode is disabled on my NUC8 device, so I can't test it.

On version 1.0 (NUC10+):

++
| s0 |
++
| s3 |
++
| standby|
++

Note: At the specs, "Standby" is actually "Modern Standby". I ended
simplifying it, as just "standby_brightness" sounds good enough.

Thanks,
Mauro
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 00/17] Add an experimental driver for Intel NUC leds

2021-05-17 Thread Mauro Carvalho Chehab
Em Mon, 17 May 2021 10:18:57 +0200
Greg KH  escreveu:

> On Sun, May 16, 2021 at 12:53:28PM +0200, Mauro Carvalho Chehab wrote:
> > Hi Greg,
> > 
> > This series add support for the LEDs found at Intel NUCs since
> > NUC version 6.
> > 
> > On several NUC models, the function of the LEDs are programmable,
> > which allow them to indicate several different hardware events.
> > 
> > They can even be programmed to represent an userspace-driven event.
> > 
> > Some models come with single colored or dual-colored LEDs, but
> > high end models have RGB LEDs.
> > 
> > Programming them can ether be done via BIOS or by the OS.
> > 
> > There are 3 different API types, and there is already some OOT
> > drivers that were written to support them, using procfs, each
> > one using a different (and IMO confusing) API.
> > 
> > After looking at the existing drivers and not liking the uAPI
> > interfaces there, I opted to write a new driver from scratch,
> > unifying support for all different versions and using sysfs
> > via the leds class.  
> 
> Just do this the "right way" and not add it to staging first.  Just use
> the existing LED class apis and all should be fine, no need for doing
> anything unusual here.

I'm using the standard LED class already (but not triggers), and the
standard WMI support.

Still, this API is complex, as it controls the LED behavior even when
the machine is suspended. I would feel more comfortable if the ABI
is not set into a stone at the beginning.

But it is your and Pavel's call.

Thanks,
Mauro
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 17/17] staging: nuc-led: update the TODOs

2021-05-17 Thread Mauro Carvalho Chehab
Em Mon, 17 May 2021 10:05:27 +0200
Pavel Machek  escreveu:

> Hi!
> 
> > > > -  Need to validate the uAPI and document it before moving
> > > >this driver out of staging.
> > >   
> > > >  - Stabilize and document its sysfs interface.
> > >
> > > Would you mind starting with this one?  
> > 
> > Do you mean writing the ABI document for it? Surely I can do that,
> > but I'm not sure where to put such document while it is on staging.  
> 
> No need for formal ABI just yet, but it needs to be clear what the interface
> is.
> 
> > > We should have existing APIs
> > > for most of functionality described...  
> > 
> > I tried to stay as close as possible to the existing API, but
> > there are some things that required a different one.  
> 
> I believe it should be possible to move _way_ closer to existing APIs.
> 
> > For instance, with WMI rev 0.64 and 1.0, any LED of the device
> > can be programmed to be a power indicator.
> > 
> > When a LED is programmed this way, there are up to 3 (on rev 1.0) or up
> > to 4 (on rev 0.64) different brightness level of the LED, and those
> > are associated with a power status (like S0, S3, S5, "ready mode").  
> 
> I'll need a description how this works.
> 
> > /sys/class/leds/nuc::front1/
> > ├── blink_behavior
> > ├── blink_frequency  
> 
> We have timer trigger for these.

Not really. The LED blink behavior is provided by the hardware itself.

The LEDs can blink *even* when the device is suspended or is
hibernating. That's something that a timer trigger can't do ;-)

See below for a draft of the ABI description.

> 
> > ├── ethernet_type
> > ├── hdd_default
> > ├── indicator
> > ├── ready_mode_blink_behavior
> > ├── ready_mode_blink_frequency
> > ├── ready_mode_brightness
> > ├── s0_blink_behavior
> > ├── s0_blink_frequency
> > ├── s0_brightness
> > ├── s3_blink_behavior
> > ├── s3_blink_frequency
> > ├── s3_brightness
> > ├── s5_blink_behavior
> > ├── s5_blink_frequency
> > ├── s5_brightness  
> 
> No. Take a look at triggers; for example hdd monitor should look very
> much like existing disk trigger.

Ok, I'll double-check how this works. Yeah, it would be a way better if
the sysfs nodes could be hidden when changing the indicator type.

For instance, when monitoring disk activity, only those parameters
may be available:

=   ===
Parameter   Meaning
=   ===
brightness  Brightness in percent (from 0 to 100)
color   LED color.
See :ref:`nuc_color`.
hdd_default Default is LED turned ON or OFF.
When set toOFF, the LED will turn on
at disk activity.
When set to ON, the LED will be turned
on by default, turning off at disk
activity.
=   ===

(color is only available for multi-colored or RGB leds).

> 
> > On other words, the "indicator" tells what type of hardware event
> > the LED is currently measuring:
> > 
> > $ cat /sys/class/leds/nuc\:\:front1/indicator 
> > Power State  [HDD Activity]  Ethernet  WiFi  Software  Power Limit  
> > Disable
> 
> So this will use existing "trigger" infrastructure.

Ok, I will take a look on that. Are there any driver that I could use
as an example, using it in a configurable way?

> > That should likely be easier to discuss if any changes at the
> > ABI would be needed. Before moving it out of staging, I would
> > add another one under Documentation/ABI describing the meaning
> > of each sysfs node.  
> 
> Lets get reasonable ABI before moving it _into_ tree, staging or
> otherwise.

I'm enclosing a document that I started to write today, describing the
way the current ABI was designed. The document doesn't describe in
full the NUC6 variant (which is really limited: just two LEDs
with fixed behavior).

Thanks,
Mauro


==
Intel NUC WMI LEDs
==

Some models of the Intel Next Unit of Computing (NUC) may have programmable
LEDs on its panel via its BIOS. A subset of those may also be programmed on
user space.

There are currently three different APIs on such devices, depending on the
NUC generation:

* NUC 6/7:
  
https://www.intel.com/content/www/us/en/support/articles/23426/intel-nuc/intel-nuc-kits.html
* NUC 8/9:
  
https://raw.githubusercontent.com/nomego/intel_nuc_led/master/specs/INTEL_WMI_LED_0.64.pdf
* NUC 10 and newer:
  
https://www.intel.com/content/dam/support/us/en/documents/intel-nuc/WMI-Spec-Intel-NUC-NUC10ixFNx.pdf

This document desc

Re: [PATCH 17/17] staging: nuc-led: update the TODOs

2021-05-16 Thread Mauro Carvalho Chehab
Hi Pavel,

Em Sun, 16 May 2021 20:21:50 +0200
Pavel Machek  escreveu:

> Hi!
> 
> > -  Need to validate the uAPI and document it before moving
> >this driver out of staging.  
> 
> >  - Stabilize and document its sysfs interface.  
>
> Would you mind starting with this one?

Do you mean writing the ABI document for it? Surely I can do that,
but I'm not sure where to put such document while it is on staging.

> We should have existing APIs
> for most of functionality described...

I tried to stay as close as possible to the existing API, but
there are some things that required a different one.

For instance, with WMI rev 0.64 and 1.0, any LED of the device
can be programmed to be a power indicator.

When a LED is programmed this way, there are up to 3 (on rev 1.0) or up
to 4 (on rev 0.64) different brightness level of the LED, and those
are associated with a power status (like S0, S3, S5, "ready mode").

So, the LED API standard "brightness" is meaningless. On the other
hand, when the same LED is programmed to monitor, let's say, the
WiFi or one of the two Ethernets (or both at the same time), the
standard "brightness" level makes sense.

> 
> We really don't want to merge code with bad API, not even to staging.

See, this is the API that it is exposed on with a NUC8:

$ tree /sys/class/leds/nuc\:\:front1/
/sys/class/leds/nuc::front1/
├── blink_behavior
├── blink_frequency
├── brightness
├── color
├── device -> ../../../8C5DA44C-CDC3-46B3-8619-4E26D34390B7
├── ethernet_type
├── hdd_default
├── indicator
├── max_brightness
├── power
│   ├── autosuspend_delay_ms
│   ├── control
│   ├── runtime_active_time
│   ├── runtime_status
│   └── runtime_suspended_time
├── power_limit_scheme
├── ready_mode_blink_behavior
├── ready_mode_blink_frequency
├── ready_mode_brightness
├── s0_blink_behavior
├── s0_blink_frequency
├── s0_brightness
├── s3_blink_behavior
├── s3_blink_frequency
├── s3_brightness
├── s5_blink_behavior
├── s5_blink_frequency
├── s5_brightness
├── subsystem -> ../../../../../../../../class/leds
├── trigger
└── uevent

As the behavior of the LEDs can be dynamically changed, each
LED expose parameters for all types of hardware event it can
deal, but only the ones that are applied to its current indicator
type can be seen/changed.

On other words, the "indicator" tells what type of hardware event
the LED is currently measuring:

$ cat /sys/class/leds/nuc\:\:front1/indicator 
Power State  [HDD Activity]  Ethernet  WiFi  Software  Power Limit  
Disable  

In this case, as it is measuring the HDD activity. If one tries to
read/write something to, let's say, the Ethernet type, a -EINVAL
is returned:

$ cat /sys/class/leds/nuc\:\:front1/ethernet_type 
cat: '/sys/class/leds/nuc::front1/ethernet_type': Invalid argument

So, before being able to use the ethernet_type, the indicator needs
to be changed:

$ echo Ethernet > /sys/class/leds/nuc\:\:front1/indicator 
$ cat /sys/class/leds/nuc\:\:front1/ethernet_type
LAN1  LAN2  [LAN1+LAN2]  

Anyway, I suspect that besides a document under ABI, it would
make sense to add a .rst file describing it under admin-guide,
explaining how to use the ABI.

That should likely be easier to discuss if any changes at the
ABI would be needed. Before moving it out of staging, I would
add another one under Documentation/ABI describing the meaning
of each sysfs node.

Would that work for you?

Thanks,
Mauro
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 17/17] staging: nuc-led: update the TODOs

2021-05-16 Thread Mauro Carvalho Chehab
Now that most functionality were merged at the driver,
update its TODO list, and add a "TODO" comment for the two
WMI API commands that are currently not implemented.

In summary:

-  on Rev 0.64, command 0x07 (LED_NOTIFICATION) is meant to store
   all config settings at EEPROM. That doesn't seem to be needed
   on Skull Canyon, but tests with different hardware would be
   nice in order to double-check it. Also, maybe Rev 1.00 would
   make it mandatory;
-  Rev 1.00 added command 0x08 to switch the LED type
   (LED_SWITCH_TYPE at the driver's nomenclature) between
   single color LED and multi color LED). Not sure how this
   should be properly implemented (if this is the case);
-  The tests for NUC6 version were using a Skull Canyon NUC.
   It allowed to check that the driver's logic runs, but
   it is not enough to see if everything is really working.
   Tests on NUC6 or NUC7 are required;
-  On a suspend test, I noticed that some controls were reset
   to the default at resume time. It is required to check
   what's happening there and address it properly.
-  Need to validate the uAPI and document it before moving
   this driver out of staging.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/nuc-led/TODO  | 12 +++-
 drivers/staging/nuc-led/nuc-wmi.c |  6 ++
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/nuc-led/TODO b/drivers/staging/nuc-led/TODO
index d5296d7186a7..df6f3f653eb0 100644
--- a/drivers/staging/nuc-led/TODO
+++ b/drivers/staging/nuc-led/TODO
@@ -1,6 +1,8 @@
-- Add support for 6th gen NUCs, like Skull Canyon
-- Improve LED core support to avoid it to try to manage the
-  LED brightness directly;
-- Test it with 8th gen NUCs;
-- Add more functionality to the driver;
+- Test it with 6th gen and 10th NUCs;
+- Add support for LED_NOTIFICATION;
+- Add support for LED_SWITCH_TYPE;
+- Some LED parameters are changing after returning
+  from suspend. Need to check what's happening there
+  (hardware bug?) and ensure that the parameters will
+  be properly restored after resume.
 - Stabilize and document its sysfs interface.
diff --git a/drivers/staging/nuc-led/nuc-wmi.c 
b/drivers/staging/nuc-led/nuc-wmi.c
index 2d9c49d72703..e87e97d56364 100644
--- a/drivers/staging/nuc-led/nuc-wmi.c
+++ b/drivers/staging/nuc-led/nuc-wmi.c
@@ -42,16 +42,14 @@ enum led_cmds {
LED_OLD_SET_LED = 0x02,
 
/* Rev 0.64 and 1.0 cmds */
-
LED_QUERY   = 0x03,
LED_NEW_GET_STATUS  = 0x04,
LED_SET_INDICATOR   = 0x05,
LED_SET_VALUE   = 0x06,
-   LED_NOTIFICATION= 0x07,
-   LED_SWITCH_TYPE = 0x08,
+   LED_NOTIFICATION= 0x07, // TODO: add support for it
 
/* Rev 1.0 cmds */
-
+   LED_SWITCH_TYPE = 0x08, // TODO: add support for it
LED_VERSION_CONTROL = 0x09,
 };
 
-- 
2.31.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 01/17] staging: add support for NUC WMI LEDs

2021-05-16 Thread Mauro Carvalho Chehab
Some Intel Next Unit of Computing (NUC) machines have
software-configured LEDs that can be used to display a
variety of events:

- Power State
- HDD Activity
- Ethernet
- WiFi
- Power Limit

They can even be controlled directly via software, without
any hardware-specific indicator connected into them.

Some devices have mono-colored LEDs, but the more advanced
ones have RGB leds that can show any color.

Different color and 4 blink states can be programmed for
thee system states:

- powered on (S0);
- S3;
- Standby.

The NUC BIOSes allow to partially set them for S0, but doesn't
provide any control for the other states, nor does allow
changing the blinking logic.

They all use a WMI interface using GUID:
8C5DA44C-CDC3-46b3-8619-4E26D34390B7

But there are 3 different revisions of the spec, all using
the same GUID, but two different APIs:

- the original one, for NUC6 and to NUCi7:
- 
https://www.intel.com/content/www/us/en/support/articles/23426/intel-nuc/intel-nuc-kits.html

- a new one, starting with NUCi8, with two revisions:
- 
https://raw.githubusercontent.com/nomego/intel_nuc_led/master/specs/INTEL_WMI_LED_0.64.pdf
- 
https://www.intel.com/content/dam/support/us/en/documents/intel-nuc/WMI-Spec-Intel-NUC-NUC10ixFNx.pdf

There are some OOT drivers for them, but they use procfs
and use a messy interface to setup it. Also, there are
different drivers with the same name, each with support
for each NUC family.

Let's start a new driver from scratch, using the x86 platform
WMI core and the LED class.

This initial version is compatible with NUCi8 and above, and it
was tested with a Hades Canyon NUC (NUC8i7HNK).

Signed-off-by: Mauro Carvalho Chehab 
---
 MAINTAINERS   |   6 +
 drivers/staging/Kconfig   |   2 +
 drivers/staging/Makefile  |   1 +
 drivers/staging/nuc-led/Kconfig   |  11 +
 drivers/staging/nuc-led/Makefile  |   3 +
 drivers/staging/nuc-led/TODO  |   6 +
 drivers/staging/nuc-led/nuc-wmi.c | 489 ++
 7 files changed, 518 insertions(+)
 create mode 100644 drivers/staging/nuc-led/Kconfig
 create mode 100644 drivers/staging/nuc-led/Makefile
 create mode 100644 drivers/staging/nuc-led/TODO
 create mode 100644 drivers/staging/nuc-led/nuc-wmi.c

diff --git a/MAINTAINERS b/MAINTAINERS
index bd7aff0c120f..50d181e1d745 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13063,6 +13063,12 @@ T: git 
git://git.kernel.org/pub/scm/linux/kernel/git/aia21/ntfs.git
 F: Documentation/filesystems/ntfs.rst
 F: fs/ntfs/
 
+NUC LED DRIVER
+M:  Mauro Carvalho Chehab 
+L:  de...@driverdev.osuosl.org
+S:  Maintained
+F:  drivers/staging/nuc-led
+
 NUBUS SUBSYSTEM
 M: Finn Thain 
 L: linux-m...@lists.linux-m68k.org
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index b7ae5bdc4eb5..d1a8e3e08d00 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -84,6 +84,8 @@ source "drivers/staging/greybus/Kconfig"
 
 source "drivers/staging/vc04_services/Kconfig"
 
+source "drivers/staging/nuc-led/Kconfig"
+
 source "drivers/staging/pi433/Kconfig"
 
 source "drivers/staging/mt7621-pci/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 075c979bfe7c..de937f947edb 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_UNISYSSPAR)  += unisys/
 obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD)  += clocking-wizard/
 obj-$(CONFIG_FB_TFT)   += fbtft/
 obj-$(CONFIG_MOST) += most/
+obj-$(CONFIG_LEDS_NUC_WMI) += nuc-led/
 obj-$(CONFIG_KS7010)   += ks7010/
 obj-$(CONFIG_GREYBUS)  += greybus/
 obj-$(CONFIG_BCM2835_VCHIQ)+= vc04_services/
diff --git a/drivers/staging/nuc-led/Kconfig b/drivers/staging/nuc-led/Kconfig
new file mode 100644
index ..0f870f45bf44
--- /dev/null
+++ b/drivers/staging/nuc-led/Kconfig
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config LEDS_NUC_WMI
+   tristate "Intel NUC WMI support for LEDs"
+   depends on LEDS_CLASS
+   depends on ACPI_WMI
+   help
+ Enable this to support the Intel NUC WMI support for
+ LEDs, starting from NUCi8 and upper devices.
+
+ To compile this driver as a module, choose M here.
diff --git a/drivers/staging/nuc-led/Makefile b/drivers/staging/nuc-led/Makefile
new file mode 100644
index ..abba9e305fa1
--- /dev/null
+++ b/drivers/staging/nuc-led/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_LEDS_NUC_WMI) += nuc-wmi.o
diff --git a/drivers/staging/nuc-led/TODO b/drivers/staging/nuc-led/TODO
new file mode 100644
index ..d5296d7186a7
--- /dev/null
+++ b/drivers/staging/nuc-led/TODO
@@ -0,0 +1,6 @@
+- Add support for 6th gen NUCs, like Skull Canyon
+- Improve LED co

[PATCH 07/17] staging: nuc-wmi: add basic support for NUC6 WMI

2021-05-16 Thread Mauro Carvalho Chehab
The NUC6 and NUCi7 supports an earlier version of the LEDs
WMI, as specified at:


https://www.intel.com/content/www/us/en/support/articles/23426/intel-nuc/intel-nuc-kits.html

Implement the query part of the LED detection for those devices.

Weird enough, at least with Skull Canyon (NUC6i7KYB) using
the latest firmware release (KYSKLi70 0071), the WMI call
return all zeros. It could well be due to a regression at
the Intel's firmware, although this model was not announced
as supporting this WMI. At the manufacturer's site, only
NUC Kits NUC7i[x]BN and NUC6CAY are mentioned.

Yet, it sounds to me that this is due to a firmware bug:

$ sudo fwts wmi -
...
Test 1 of 1: Windows Management Instrumentation test.
...

\_SB_.WMTF._WDG (1 of 1)
  GUID: 86CCFD48-205E-4A77-9C48-2021CBEDE341
  WMI Method:
Flags  : 0x02 (Method)
Object ID  : TF
Instance   : 0x01
Driver : intel-wmi-thunderbolt (Intel)
FAILED [LOW] WMIMultipleMethod: Test 1, GUID 
86CCFD48-205E-4A77-9C48-2021CBEDE341 has multiple associated methods WMTF 
defined, this is a firmware bug that leads to ambiguous behaviour.
...
\AMW0._WDG (1 of 2)
  GUID: 8C5DA44C-CDC3-46B3-8619-4E26D34390B7
  WMI Method:
Flags  : 0x02 (Method)
Object ID  : AA
Instance   : 0x01
PASSED: Test 1, 8C5DA44C-CDC3-46B3-8619-4E26D34390B7 has associated 
method \AMW0.WMAA
...
Low failures: 1
 wmi: GUID 86CCFD48-205E-4A77-9C48-2021CBEDE341 has multiple associated 
methods WMTF defined, this is a firmware bug that leads to ambiguous behaviour.

Anyway, this was good enough to test that this patch will be
producing exactly the WMI query as the NUC6 OOT driver at:

https://github.com/milesp20/intel_nuc_led/

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/nuc-led/nuc-wmi.c | 134 +++---
 1 file changed, 106 insertions(+), 28 deletions(-)

diff --git a/drivers/staging/nuc-led/nuc-wmi.c 
b/drivers/staging/nuc-led/nuc-wmi.c
index e9c59f656283..db38c40c223a 100644
--- a/drivers/staging/nuc-led/nuc-wmi.c
+++ b/drivers/staging/nuc-led/nuc-wmi.c
@@ -8,12 +8,15 @@
  *
  * Inspired on WMI from https://github.com/nomego/intel_nuc_led
  *
- * It follows this spec:
- * 
https://www.intel.com/content/dam/support/us/en/documents/intel-nuc/WMI-Spec-Intel-NUC-NUC10ixFNx.pdf
+ * It follows those specs:
+ *   
https://www.intel.com/content/www/us/en/support/articles/23426/intel-nuc/intel-nuc-kits.html
+ *   
https://raw.githubusercontent.com/nomego/intel_nuc_led/master/specs/INTEL_WMI_LED_0.64.pdf
+ *   
https://www.intel.com/content/dam/support/us/en/documents/intel-nuc/WMI-Spec-Intel-NUC-NUC10ixFNx.pdf
  */
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -34,12 +37,21 @@ enum led_api_rev {
 };
 
 enum led_cmds {
+   /* NUC6-specific cmds */
+   LED_OLD_GET_STATUS  = 0x01,
+   LED_OLD_SET_LED = 0x02,
+
+   /* Rev 0.64 and 1.0 cmds */
+
LED_QUERY   = 0x03,
LED_NEW_GET_STATUS  = 0x04,
LED_SET_INDICATOR   = 0x05,
LED_SET_VALUE   = 0x06,
LED_NOTIFICATION= 0x07,
LED_SWITCH_TYPE = 0x08,
+
+   /* Rev 1.0 cmds */
+
LED_VERSION_CONTROL = 0x09,
 };
 
@@ -55,6 +67,11 @@ enum led_new_get_subcmd {
LED_NEW_GET_CONTROL_ITEM= 0x01,
 };
 
+enum led_old_get_subcmd {
+   LED_OLD_GET_S0_POWER= 0x01,
+   LED_OLD_GET_S0_RING = 0x02,
+};
+
 enum led_function {
LED_FUNC_BRIGHTNESS,
LED_FUNC_COLOR1,
@@ -146,14 +163,19 @@ static const u8 
led_func_rev_1_0_singlecolor[MAX_IND][MAX_LED_FUNC] = {
 #define LED_RGBBIT(2)
 #defineLED_SINGLE_COLORBIT(3)
 
+#define POWER_LED  0
+#define RING_LED   (MAX_LEDS + 1)
+
 static const char * const led_names[] = {
-   "nuc::power",
+   [POWER_LED] = "nuc::power",
"nuc::hdd",
"nuc::skull",
"nuc::eyes",
"nuc::front1",
"nuc::front2",
"nuc::front3",
+
+   [RING_LED] = "nuc::ring",   // NUC6 models
 };
 
 struct nuc_nmi_led {
@@ -276,48 +298,98 @@ static int nuc_nmi_cmd(struct device *dev,
return ret;
 }
 
+static int nuc_wmi_query_leds_nuc6(struct device *dev)
+{
+   // FIXME: add a check for the specific models that are known to work
+   struct nuc_wmi *priv = dev_get_drvdata(dev);
+   u8 cmd, input[NUM_INPUT_ARGS] = { 0 };
+   u8 output[NUM_OUTPUT_ARGS];
+   struct nuc_nmi_led *led;
+   int ret;
+
+   cmd = LED_OLD_GET_STATUS;
+   input[0] = LED_OLD_GET_S0_PO

[PATCH 04/17] staging: nuc-wmi: add all types of brightness

2021-05-16 Thread Mauro Carvalho Chehab
Improve the logic in order to support not only S0 brightness,
but also the brightness for other indicators and for all
power states.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/nuc-led/nuc-wmi.c | 369 --
 1 file changed, 249 insertions(+), 120 deletions(-)

diff --git a/drivers/staging/nuc-led/nuc-wmi.c 
b/drivers/staging/nuc-led/nuc-wmi.c
index 62c2764814dd..711897ba4666 100644
--- a/drivers/staging/nuc-led/nuc-wmi.c
+++ b/drivers/staging/nuc-led/nuc-wmi.c
@@ -55,21 +55,89 @@ enum led_new_get_subcmd {
LED_NEW_GET_CONTROL_ITEM= 0x01,
 };
 
+enum led_function {
+   LED_FUNC_BRIGHTNESS,
+   LED_FUNC_COLOR1,
+   LED_FUNC_COLOR_GREEN,
+   LED_FUNC_COLOR_BLUE,
+
+   LED_FUNC_BLINK_BEHAVIOR,
+   LED_FUNC_BLINK_FREQ,
+
+   LED_FUNC_HDD_BEHAVIOR,
+   LED_FUNC_ETH_TYPE,
+   LED_FUNC_POWER_LIMIT_SCHEME,
+
+   MAX_LED_FUNC
+};
+
+enum led_indicators {
+   LED_IND_POWER_STATE,
+   LED_IND_HDD_ACTIVITY,
+   LED_IND_ETHERNET,
+   LED_IND_WIFI,
+   LED_IND_SOFTWARE,
+   LED_IND_POWER_LIMIT,
+   LED_IND_DISABLE,
+
+   MAX_IND = LED_IND_DISABLE
+};
+
+/*
+ * control items ID for each of the valid indicators on spec Rev 0.64.
+ */
+static const u8 led_func_rev_0_64[MAX_IND][MAX_LED_FUNC] = {
+   [LED_IND_POWER_STATE] = {   /* Offsets for each power state */
+   [LED_FUNC_BRIGHTNESS]   = 0x00,
+   [LED_FUNC_BLINK_BEHAVIOR]   = 0x01,
+   [LED_FUNC_BLINK_FREQ]   = 0x02,
+   [LED_FUNC_COLOR1]   = 0x03,
+   [LED_FUNC_COLOR_GREEN]  = 0x04,
+   [LED_FUNC_COLOR_BLUE]   = 0x05
+   },
+   [LED_IND_HDD_ACTIVITY] = {
+   [LED_FUNC_BRIGHTNESS]   = 0x00,
+   [LED_FUNC_COLOR1]   = 0x01,
+   [LED_FUNC_COLOR_GREEN]  = 0x02,
+   [LED_FUNC_COLOR_BLUE]   = 0x03,
+   [LED_FUNC_HDD_BEHAVIOR] = 0x04
+   },
+   [LED_IND_ETHERNET] = {
+   [LED_FUNC_ETH_TYPE] = 0x00,
+   [LED_FUNC_BRIGHTNESS]   = 0x01,
+   [LED_FUNC_COLOR1]   = 0x02,
+   [LED_FUNC_COLOR_GREEN]  = 0x03,
+   [LED_FUNC_COLOR_BLUE]   = 0x04
+   },
+   [LED_IND_WIFI] = {
+   [LED_FUNC_BRIGHTNESS]   = 0x00,
+   [LED_FUNC_COLOR1]   = 0x01,
+   [LED_FUNC_COLOR_GREEN]  = 0x02,
+   [LED_FUNC_COLOR_BLUE]   = 0x03
+   },
+   [LED_IND_SOFTWARE] = {
+   [LED_FUNC_BRIGHTNESS]   = 0x00,
+   [LED_FUNC_BLINK_BEHAVIOR]   = 0x01,
+   [LED_FUNC_BLINK_FREQ]   = 0x02,
+   [LED_FUNC_COLOR1]   = 0x03,
+   [LED_FUNC_COLOR_GREEN]  = 0x04,
+   [LED_FUNC_COLOR_BLUE]   = 0x05
+   },
+   [LED_IND_POWER_LIMIT] = {
+   [LED_FUNC_POWER_LIMIT_SCHEME]   = 0x00,
+   [LED_FUNC_BRIGHTNESS]   = 0x01,
+   [LED_FUNC_COLOR1]   = 0x02,
+   [LED_FUNC_COLOR_GREEN]  = 0x03,
+   [LED_FUNC_COLOR_BLUE]   = 0x04
+   },
+};
+
 /* LED color indicator */
 #define LED_BLUE_AMBER BIT(0)
 #define LED_BLUE_WHITE BIT(1)
 #define LED_RGBBIT(2)
 #defineLED_SINGLE_COLORBIT(3)
 
-/* LED indicator options */
-#define LED_IND_POWER_STATEBIT(0)
-#define LED_IND_HDD_ACTIVITY   BIT(1)
-#define LED_IND_ETHERNET   BIT(2)
-#define LED_IND_WIFI   BIT(3)
-#define LED_IND_SOFTWARE   BIT(4)
-#define LED_IND_POWER_LIMITBIT(5)
-#define LED_IND_DISABLEBIT(6)
-
 static const char * const led_names[] = {
"nuc::power",
"nuc::hdd",
@@ -87,7 +155,6 @@ struct nuc_nmi_led {
u8 indicator;
u32 color_type;
u32 avail_indicators;
-   u32 control_items;
 };
 
 struct nuc_wmi {
@@ -201,9 +268,9 @@ static int nuc_nmi_cmd(struct device *dev,
 static int nuc_wmi_query_leds(struct device *dev)
 {
struct nuc_wmi *priv = dev_get_drvdata(dev);
-   u8 cmd, input[NUM_INPUT_ARGS] = { 0 };
+   u8 input[NUM_INPUT_ARGS] = { 0 };
u8 output[NUM_OUTPUT_ARGS];
-   int i, id, ret, ver = LED_API_UNKNOWN;
+   int id, ret, ver = LED_API_UNKNOWN;
u8 leds;
 
/*
@@ -214,9 +281,8 @@ static int nuc_wmi_query_leds(struct device *dev)
 * FIXME: Should add a fallback code for it to work with older NUCs,
 * as LED_QUERY returns an error on older devices like Skull Canyon.
 */
-   cmd = LED_QUERY;
input[0] = LED_QUERY_LIST_ALL;
-   ret = nuc_nmi_cmd(dev, cmd, input, output);
+   ret = nuc_nmi_cmd(dev, LED_QUERY, input, output);
  

[PATCH 08/17] staging: muc-wmi: add brightness and color for NUC6 API

2021-05-16 Thread Mauro Carvalho Chehab
The NUC6 WMI API is really simple: it has just 2 messages,
that retrieves everything for a LED, and it has just 2 LEDs.

Add support for retrieving and set brightness and color.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/nuc-led/nuc-wmi.c | 198 --
 1 file changed, 191 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/nuc-led/nuc-wmi.c 
b/drivers/staging/nuc-led/nuc-wmi.c
index db38c40c223a..a365a8603182 100644
--- a/drivers/staging/nuc-led/nuc-wmi.c
+++ b/drivers/staging/nuc-led/nuc-wmi.c
@@ -302,14 +302,13 @@ static int nuc_wmi_query_leds_nuc6(struct device *dev)
 {
// FIXME: add a check for the specific models that are known to work
struct nuc_wmi *priv = dev_get_drvdata(dev);
-   u8 cmd, input[NUM_INPUT_ARGS] = { 0 };
+   u8 input[NUM_INPUT_ARGS] = { 0 };
u8 output[NUM_OUTPUT_ARGS];
struct nuc_nmi_led *led;
int ret;
 
-   cmd = LED_OLD_GET_STATUS;
input[0] = LED_OLD_GET_S0_POWER;
-   ret = nuc_nmi_cmd(dev, cmd, input, output);
+   ret = nuc_nmi_cmd(dev, LED_OLD_GET_STATUS, input, output);
if (ret) {
dev_warn(dev, "Get S0 Power: error %d\n", ret);
return ret;
@@ -322,9 +321,8 @@ static int nuc_wmi_query_leds_nuc6(struct device *dev)
led->indicator = fls(led->avail_indicators);
priv->num_leds++;
 
-   cmd = LED_OLD_GET_STATUS;
input[0] = LED_OLD_GET_S0_RING;
-   ret = nuc_nmi_cmd(dev, cmd, input, output);
+   ret = nuc_nmi_cmd(dev, LED_OLD_GET_STATUS, input, output);
if (ret) {
dev_warn(dev, "Get S0 Ring: error %d\n", ret);
return ret;
@@ -544,6 +542,167 @@ static ssize_t nuc_wmi_set_brightness_offset(struct 
device *dev,
}  \
static DEVICE_ATTR(_name, 0644, show_##_name, store_##_name)
 
+/*
+ * NUC6 specific logic
+ */
+
+static int nuc_wmi_nuc6_led_get_set(struct device *dev,
+   struct nuc_nmi_led *led, int *brightness,
+   int *blink_fade, int *color_state)
+{
+   u8 input[NUM_INPUT_ARGS] = { 0 };
+   u8 output[NUM_OUTPUT_ARGS];
+   int ret;
+
+   if (led->id == POWER_LED)
+   input[0] = LED_OLD_GET_S0_POWER;
+   else
+   input[0] = LED_OLD_GET_S0_RING;
+
+   ret = nuc_nmi_cmd(dev, LED_OLD_GET_STATUS, input, output);
+   if (ret) {
+   dev_warn(dev, "Get %s: error %d\n", led_names[led->id], ret);
+   return ret;
+   }
+
+   if (brightness && *brightness >= 0)
+   input[1] = *brightness;
+   else
+   input[1] = output[0];
+
+   if (blink_fade && *blink_fade >= 0)
+   input[2] = *blink_fade;
+   else
+   input[2] = output[1];
+
+   if (color_state && *color_state >= 0)
+   input[3] = *color_state;
+   else
+   input[3] = output[2];
+
+   ret = nuc_nmi_cmd(dev, LED_OLD_SET_LED, input, output);
+   if (ret) {
+   dev_warn(dev, "Get %s: error %d\n", led_names[led->id], ret);
+   return ret;
+   }
+
+   if (brightness)
+   *brightness = output[0];
+   if (blink_fade)
+   *blink_fade = output[1];
+   if (color_state)
+   *color_state = output[2];
+
+   return 0;
+}
+
+static enum led_brightness nuc_wmi_nuc6_get_brightness(struct led_classdev 
*cdev)
+{
+   struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev);
+   int ret, brightness = -1;
+
+   ret = nuc_wmi_nuc6_led_get_set(cdev->dev, led, &brightness, NULL, NULL);
+   if (ret)
+   return ret;
+
+   return brightness;
+}
+
+static int nuc_wmi_nuc6_set_brightness(struct led_classdev *cdev,
+  enum led_brightness bright)
+{
+   int brightness = bright;
+   struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev);
+
+   return nuc_wmi_nuc6_led_get_set(cdev->dev, led, &brightness,
+   NULL, NULL);
+}
+
+static const char * const nuc6_power_colors[] = {
+   "disable",
+   "blue",
+   "amber"
+};
+
+static const char * const nuc6_ring_colors[] = {
+   "disable",
+   "cyan",
+   "pink",
+   "yellow",
+   "blue",
+   "red",
+   "green",
+   "white"
+};
+
+static ssize_t nuc6_show_color(struct device *dev,
+  struct device_attribute *attr,
+  char *buf)
+{
+   struct led_classdev *cdev = dev_get_drvdata(dev);
+   struct nuc_nmi_led *led = container_of(cdev, struc

[PATCH 11/17] staging: nuc-wmi: implement blink control for NUC6

2021-05-16 Thread Mauro Carvalho Chehab
The blink control logic for NUC6 API is somewhat messy, as it
uses a single register for controlling both the blink type
and the frequency, using a random order.

Let's use the same API as defined for other versions,
splitting this setting on two different properties.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/nuc-led/nuc-wmi.c | 269 +-
 1 file changed, 267 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/nuc-led/nuc-wmi.c 
b/drivers/staging/nuc-led/nuc-wmi.c
index 78b0a3279f25..5bc4dcec3ea8 100644
--- a/drivers/staging/nuc-led/nuc-wmi.c
+++ b/drivers/staging/nuc-led/nuc-wmi.c
@@ -713,6 +713,247 @@ static ssize_t nuc6_store_color(struct device *dev,
return len;
 }
 
+enum nuc6_blink_mode_freq {
+   NUC6_BLINK_MODE_BLINK_1HZ   = 0x01,
+   NUC6_BLINK_MODE_BLINK_0_25HZ= 0x02,
+   NUC6_BLINK_MODE_FADE_1HZ= 0x03,
+   NUC6_BLINK_MODE_DONT_BLINK  = 0x04,
+
+   /* BIOS equal or upper AY0038 or BN0043 */
+   NUC6_BLINK_MODE_BLINK_0_5HZ = 0x05,
+   NUC6_BLINK_MODE_FADE_0_25HZ = 0x06,
+   NUC6_BLINK_MODE_FADE_0_5HZ  = 0x07
+};
+
+enum nuc6_blink_mode {
+   NUC6_BLINK_MODE_SOLID,
+   NUC6_BLINK_MODE_BLINK,
+   NUC6_BLINK_MODE_FADE
+};
+
+static const char * const nuc6_blink_behavior[] = {
+   "solid",
+   "blink",
+   "fade",
+};
+
+enum nuc6_blink_freq {
+   NUC6_BLINK_FREQ_1HZ,
+   NUC6_BLINK_FREQ_0_5HZ,
+   NUC6_BLINK_FREQ_0_25HZ,
+};
+
+static const char * const nuc6_blink_frequency[] = {
+   "1",
+   "0.5",
+   "0.25",
+};
+
+static int nuc_wmi_nuc6_set_blink(struct device *dev,
+ struct nuc_nmi_led *led,
+ int freq, enum nuc6_blink_mode mode)
+{
+   int val;
+
+   switch(mode) {
+   case NUC6_BLINK_MODE_SOLID:
+   val = NUC6_BLINK_MODE_DONT_BLINK;
+   break;
+   case NUC6_BLINK_MODE_BLINK:
+   if (freq == NUC6_BLINK_FREQ_0_25HZ)
+   val = NUC6_BLINK_MODE_BLINK_0_25HZ;
+   else if (freq == NUC6_BLINK_FREQ_0_5HZ)
+   val = NUC6_BLINK_MODE_BLINK_0_5HZ;
+   else
+   val = NUC6_BLINK_MODE_BLINK_1HZ;
+   break;
+   case NUC6_BLINK_MODE_FADE:
+   if (freq == NUC6_BLINK_FREQ_0_25HZ)
+   val = NUC6_BLINK_MODE_FADE_0_25HZ;
+   else if (freq == NUC6_BLINK_FREQ_0_5HZ)
+   val = NUC6_BLINK_MODE_FADE_0_5HZ;
+   else
+   val = NUC6_BLINK_MODE_FADE_1HZ;
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   return nuc_wmi_nuc6_led_get_set(dev, led, NULL, &val, NULL);
+}
+
+static ssize_t nuc6_show_blink_behavior(struct device *dev,
+  struct device_attribute *attr,
+  char *buf)
+{
+   struct led_classdev *cdev = dev_get_drvdata(dev);
+   struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev);
+   int val = -1, mode = -1, ret, i, n;
+   int size = PAGE_SIZE;
+   char *p = buf;
+
+   ret = nuc_wmi_nuc6_led_get_set(dev, led, NULL, &val, NULL);
+   if (ret)
+   return ret;
+
+   switch (val) {
+   case NUC6_BLINK_MODE_BLINK_1HZ:
+   case NUC6_BLINK_MODE_BLINK_0_25HZ:
+   case NUC6_BLINK_MODE_BLINK_0_5HZ:
+   mode = NUC6_BLINK_MODE_BLINK;
+   break;
+   case NUC6_BLINK_MODE_FADE_1HZ:
+   case NUC6_BLINK_MODE_FADE_0_25HZ:
+   case NUC6_BLINK_MODE_FADE_0_5HZ:
+   mode = NUC6_BLINK_MODE_FADE;
+   break;
+   case NUC6_BLINK_MODE_DONT_BLINK:
+   mode = NUC6_BLINK_MODE_SOLID;
+   break;
+   }
+
+   for (i = 0; i < ARRAY_SIZE(nuc6_blink_behavior); i++) {
+   if (i == mode)
+   n = scnprintf(p, size, "[%s]  ", 
nuc6_blink_behavior[i]);
+   else
+   n = scnprintf(p, size, "%s  ", nuc6_blink_behavior[i]);
+   p += n;
+   size -= n;
+   }
+   size -= scnprintf(p, size, "\n");
+
+   return PAGE_SIZE - size;
+
+}
+
+static ssize_t nuc6_store_blink_behavior(struct device *dev,
+   struct device_attribute *attr,
+   const char *buf, size_t len)
+{
+   struct led_classdev *cdev = dev_get_drvdata(dev);
+   struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev);
+   int ret, val = -1, freq;
+   const char *tmp;
+
+   tmp = strsep((char **)&buf, "\n");
+
+   ret = nuc_wmi_nuc6_led_get_set(dev, led, NULL, &val, NULL);
+   if (ret)
+   return ret;
+
+   /* Preserve

[PATCH 14/17] staging: nuc-wmi: fix software blink behavior logic

2021-05-16 Thread Mauro Carvalho Chehab
The is_visible logic for it is plain wrong:

1. it is used only during devnode creation;
2. it was using the wrong field (id, instead of indicator).

Fix it.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/nuc-led/nuc-wmi.c | 30 --
 1 file changed, 12 insertions(+), 18 deletions(-)

diff --git a/drivers/staging/nuc-led/nuc-wmi.c 
b/drivers/staging/nuc-led/nuc-wmi.c
index 68143d45c34c..fab0094a20e4 100644
--- a/drivers/staging/nuc-led/nuc-wmi.c
+++ b/drivers/staging/nuc-led/nuc-wmi.c
@@ -1476,6 +1476,9 @@ static ssize_t show_blink_behavior(struct device *dev,
if (led->api_rev == LED_API_NUC6)
return nuc6_show_blink_behavior(dev, attr, buf);
 
+   if (led->indicator != LED_IND_SOFTWARE)
+   return -EINVAL;
+
return offset_show_blink_behavior(dev, attr, 0, buf);
 }
 
@@ -1489,6 +1492,9 @@ static ssize_t store_blink_behavior(struct device *dev,
if (led->api_rev == LED_API_NUC6)
return nuc6_store_blink_behavior(dev, attr, buf, len);
 
+   if (led->indicator != LED_IND_SOFTWARE)
+   return -EINVAL;
+
return offset_store_blink_behavior(dev, attr, 0, buf, len);
 }
 
@@ -1593,6 +1599,9 @@ static ssize_t show_blink_frequency(struct device *dev,
if (led->api_rev == LED_API_NUC6)
return nuc6_show_blink_frequency(dev, attr, buf);
 
+   if (led->indicator != LED_IND_SOFTWARE)
+   return -EINVAL;
+
return offset_show_blink_frequency(dev, attr, 0, buf);
 }
 
@@ -1606,26 +1615,12 @@ static ssize_t store_blink_frequency(struct device *dev,
if (led->api_rev == LED_API_NUC6)
return nuc6_store_blink_frequency(dev, attr, buf, len);
 
+   if (led->indicator != LED_IND_SOFTWARE)
+   return -EINVAL;
+
return offset_store_blink_frequency(dev, attr, 0, buf, len);
 }
 
-static umode_t nuc_wmi_led_blink_is_visible(struct kobject *kobj,
-   struct attribute *attr, int idx)
-{
-   struct device *dev = kobj_to_dev(kobj);
-   struct led_classdev *cdev = dev_get_drvdata(dev);
-   struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev);
-   umode_t mode = attr->mode;
-
-   if (led->api_rev == LED_API_NUC6)
-   return mode;
-
-   if (led->id == LED_IND_SOFTWARE)
-   return mode;
-
-   return 0;
-}
-
 /* HDD activity behavior */
 static ssize_t show_hdd_default(struct device *dev,
   struct device_attribute *attr,
@@ -1785,7 +1780,6 @@ static struct attribute 
*nuc_wmi_led_blink_behavior_attr[] = {
 };
 
 static const struct attribute_group nuc_wmi_led_blink_attribute_group = {
-   .is_visible = nuc_wmi_led_blink_is_visible,
.attrs = nuc_wmi_led_blink_behavior_attr,
 };
 
-- 
2.31.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 06/17] staging: nuc-wmi: add support for WMI API version 1.0

2021-05-16 Thread Mauro Carvalho Chehab
The control indicators for WMI version 1.0 (used on NUCi10
and above) are on different locations.

The main difference is on single color LEDs.

Also, the Power State brightness names are defined on a
different way, and there are 3 groups instead of 4.

As the driver was written with some tables to map the
control option values, it is easy to extend it to support
the new definitions: all we need to do is to add the
V1.0 tables and ensure that the right table will be used.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/nuc-led/nuc-wmi.c | 119 +-
 1 file changed, 99 insertions(+), 20 deletions(-)

diff --git a/drivers/staging/nuc-led/nuc-wmi.c 
b/drivers/staging/nuc-led/nuc-wmi.c
index 07cf18e6f4c4..e9c59f656283 100644
--- a/drivers/staging/nuc-led/nuc-wmi.c
+++ b/drivers/staging/nuc-led/nuc-wmi.c
@@ -62,6 +62,7 @@ enum led_function {
LED_FUNC_BLINK_BEHAVIOR,
LED_FUNC_BLINK_FREQ,
 
+   LED_FUNC_POWER_STATE_NUM_CTRLS,
LED_FUNC_HDD_BEHAVIOR,
LED_FUNC_ETH_TYPE,
LED_FUNC_POWER_LIMIT_SCHEME,
@@ -84,8 +85,11 @@ enum led_indicators {
 /*
  * control items ID for each of the valid indicators on spec Rev 0.64.
  */
-static const u8 led_func_rev_0_64[MAX_IND][MAX_LED_FUNC] = {
-   [LED_IND_POWER_STATE] = {   /* Offsets for each power state */
+static const u8 led_func_multicolor[MAX_IND][MAX_LED_FUNC] = {
+   [LED_IND_POWER_STATE] = {
+   [LED_FUNC_POWER_STATE_NUM_CTRLS] = 0x06,
+
+   /* Offsets for each power state */
[LED_FUNC_BRIGHTNESS]   = 0x00,
[LED_FUNC_BLINK_BEHAVIOR]   = 0x01,
[LED_FUNC_BLINK_FREQ]   = 0x02,
@@ -118,6 +122,24 @@ static const u8 led_func_rev_0_64[MAX_IND][MAX_LED_FUNC] = 
{
},
 };
 
+static const u8 led_func_rev_1_0_singlecolor[MAX_IND][MAX_LED_FUNC] = {
+   [LED_IND_POWER_STATE] = {
+   [LED_FUNC_POWER_STATE_NUM_CTRLS] = 0x02,
+
+   /* Offsets for each power state */
+   [LED_FUNC_BRIGHTNESS]   = 0x00,
+   [LED_FUNC_BLINK_BEHAVIOR]   = 0x01,
+   },
+   [LED_IND_HDD_ACTIVITY] = {
+   [LED_FUNC_BRIGHTNESS]   = 0x00,
+   [LED_FUNC_HDD_BEHAVIOR] = 0x01
+   },
+   [LED_IND_SOFTWARE] = {
+   [LED_FUNC_BRIGHTNESS]   = 0x00,
+   [LED_FUNC_BLINK_BEHAVIOR]   = 0x01,
+   },
+};
+
 /* LED color indicator */
 #define LED_BLUE_AMBER BIT(0)
 #define LED_BLUE_WHITE BIT(1)
@@ -141,6 +163,9 @@ struct nuc_nmi_led {
u8 indicator;
u32 color_type;
u32 avail_indicators;
+   enum led_api_rev api_rev;
+
+   const u8 (*reg_table)[MAX_LED_FUNC];
 };
 
 struct nuc_wmi {
@@ -251,7 +276,7 @@ static int nuc_nmi_cmd(struct device *dev,
return ret;
 }
 
-static int nuc_wmi_query_leds(struct device *dev)
+static int nuc_wmi_query_leds(struct device *dev, enum led_api_rev *api_rev)
 {
struct nuc_wmi *priv = dev_get_drvdata(dev);
u8 input[NUM_INPUT_ARGS] = { 0 };
@@ -288,9 +313,11 @@ static int nuc_wmi_query_leds(struct device *dev)
}
 
/* Currently, only API Revision 0.64 is supported */
-   if (ver != LED_API_REV_0_64)
+   if (ver != LED_API_REV_0_64 && ver != LED_API_REV_1_0)
return -ENODEV;
 
+   *api_rev = ver;
+
if (!leds) {
dev_warn(dev, "No LEDs found\n");
return -ENODEV;
@@ -379,7 +406,7 @@ static int nuc_wmi_get_brightness_offset(struct device *dev,
if (led->indicator == LED_IND_DISABLE)
return -ENODEV;
 
-   ctrl = led_func_rev_0_64[led->indicator][LED_FUNC_BRIGHTNESS] + offset;
+   ctrl = led->reg_table[led->indicator][LED_FUNC_BRIGHTNESS] + offset;
 
if (!nuc_wmi_test_control(dev, led, ctrl))
return -ENODEV;
@@ -410,7 +437,7 @@ static ssize_t nuc_wmi_set_brightness_offset(struct device 
*dev,
if (led->indicator == LED_IND_DISABLE)
return -ENODEV;
 
-   ctrl = led_func_rev_0_64[led->indicator][LED_FUNC_BRIGHTNESS] + offset;
+   ctrl = led->reg_table[led->indicator][LED_FUNC_BRIGHTNESS] + offset;
 
if (!nuc_wmi_test_control(dev, led, ctrl))
return -ENODEV;
@@ -561,7 +588,7 @@ static ssize_t show_color(struct device *dev,
if (led->indicator == LED_IND_DISABLE)
return -ENODEV;
 
-   ctrl = led_func_rev_0_64[led->indicator][LED_FUNC_COLOR1];
+   ctrl = led->reg_table[led->indicator][LED_FUNC_COLOR1];
 
if (!nuc_wmi_test_control(dev, led, ctrl))
return -ENODEV;
@@ -658,7 +685,7 @@ static ssize_t store_color(struct device *dev,
}
}
 
-   ctrl = led_func_rev_0_64[led->indicator][LED_FUNC_COLOR1];
+   ctrl = led->reg_table[led->indicator][LED_FUNC_COLOR1]

[PATCH 05/17] staging: nuc-wmi: allow changing the LED colors

2021-05-16 Thread Mauro Carvalho Chehab
Add routines to allow seeing and changing the LED colors.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/nuc-led/nuc-wmi.c | 244 --
 1 file changed, 228 insertions(+), 16 deletions(-)

diff --git a/drivers/staging/nuc-led/nuc-wmi.c 
b/drivers/staging/nuc-led/nuc-wmi.c
index 711897ba4666..07cf18e6f4c4 100644
--- a/drivers/staging/nuc-led/nuc-wmi.c
+++ b/drivers/staging/nuc-led/nuc-wmi.c
@@ -58,8 +58,6 @@ enum led_new_get_subcmd {
 enum led_function {
LED_FUNC_BRIGHTNESS,
LED_FUNC_COLOR1,
-   LED_FUNC_COLOR_GREEN,
-   LED_FUNC_COLOR_BLUE,
 
LED_FUNC_BLINK_BEHAVIOR,
LED_FUNC_BLINK_FREQ,
@@ -92,43 +90,31 @@ static const u8 led_func_rev_0_64[MAX_IND][MAX_LED_FUNC] = {
[LED_FUNC_BLINK_BEHAVIOR]   = 0x01,
[LED_FUNC_BLINK_FREQ]   = 0x02,
[LED_FUNC_COLOR1]   = 0x03,
-   [LED_FUNC_COLOR_GREEN]  = 0x04,
-   [LED_FUNC_COLOR_BLUE]   = 0x05
},
[LED_IND_HDD_ACTIVITY] = {
[LED_FUNC_BRIGHTNESS]   = 0x00,
[LED_FUNC_COLOR1]   = 0x01,
-   [LED_FUNC_COLOR_GREEN]  = 0x02,
-   [LED_FUNC_COLOR_BLUE]   = 0x03,
[LED_FUNC_HDD_BEHAVIOR] = 0x04
},
[LED_IND_ETHERNET] = {
[LED_FUNC_ETH_TYPE] = 0x00,
[LED_FUNC_BRIGHTNESS]   = 0x01,
[LED_FUNC_COLOR1]   = 0x02,
-   [LED_FUNC_COLOR_GREEN]  = 0x03,
-   [LED_FUNC_COLOR_BLUE]   = 0x04
},
[LED_IND_WIFI] = {
[LED_FUNC_BRIGHTNESS]   = 0x00,
[LED_FUNC_COLOR1]   = 0x01,
-   [LED_FUNC_COLOR_GREEN]  = 0x02,
-   [LED_FUNC_COLOR_BLUE]   = 0x03
},
[LED_IND_SOFTWARE] = {
[LED_FUNC_BRIGHTNESS]   = 0x00,
[LED_FUNC_BLINK_BEHAVIOR]   = 0x01,
[LED_FUNC_BLINK_FREQ]   = 0x02,
[LED_FUNC_COLOR1]   = 0x03,
-   [LED_FUNC_COLOR_GREEN]  = 0x04,
-   [LED_FUNC_COLOR_BLUE]   = 0x05
},
[LED_IND_POWER_LIMIT] = {
[LED_FUNC_POWER_LIMIT_SCHEME]   = 0x00,
[LED_FUNC_BRIGHTNESS]   = 0x01,
[LED_FUNC_COLOR1]   = 0x02,
-   [LED_FUNC_COLOR_GREEN]  = 0x03,
-   [LED_FUNC_COLOR_BLUE]   = 0x04
},
 };
 
@@ -459,6 +445,8 @@ static ssize_t nuc_wmi_set_brightness_offset(struct device 
*dev,
}  \
static DEVICE_ATTR(_name, 0644, show_##_name, store_##_name)
 
+/* Show/change the LED indicator */
+
 static const char * const led_indicators[] = {
"Power State",
"HDD Activity",
@@ -531,7 +519,220 @@ static ssize_t store_indicator(struct device *dev,
return -EINVAL;
 }
 
-/* Get brightness */
+/* Show/change the LED color */
+
+enum led_colors {
+   LED_COLOR_BLUE,
+   LED_COLOR_AMBER,
+   LED_COLOR_WHITE
+};
+
+struct led_color_name {
+   const char *name;
+   u8 r, g, b;
+};
+
+static const struct led_color_name led_colors[] = {
+   /* The first colors should match the dual-LED colorset */
+   [LED_COLOR_BLUE]  = { "blue",  0,   0, 0xff },
+   [LED_COLOR_AMBER] = { "amber", 0xff, 0xbf,0 },
+   [LED_COLOR_WHITE] = { "white", 0xff, 0xff, 0xff },
+
+   /* Let's add a couple of common color names as well */
+   { "red", 0xff,0,0 },
+   { "green",  0, 0xff,0 },
+   { "yellow",  0xff, 0xff,0 },
+   { "cyan",   0, 0xff, 0xff },
+   { "magenta", 0xff,0, 0xff },
+};
+
+static ssize_t show_color(struct device *dev,
+ struct device_attribute *attr,
 char *buf)
+{
+   struct led_classdev *cdev = dev_get_drvdata(dev);
+   struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev);
+   u8 input[NUM_INPUT_ARGS];
+   u8 output[NUM_OUTPUT_ARGS];
+   int ret, ctrl;
+   int size = PAGE_SIZE;
+   char *p = buf;
+   int color, r, g, b;
+
+   if (led->indicator == LED_IND_DISABLE)
+   return -ENODEV;
+
+   ctrl = led_func_rev_0_64[led->indicator][LED_FUNC_COLOR1];
+
+   if (!nuc_wmi_test_control(dev, led, ctrl))
+   return -ENODEV;
+
+   input[0] = LED_NEW_GET_CONTROL_ITEM;
+   input[1] = led->id;
+   input[2] = led->indicator;
+   input[3] = ctrl;
+
+   ret = nuc_nmi_cmd(dev, LED_NEW_GET_STATUS, input, output);
+   if (ret)
+ 

[PATCH 09/17] staging: nuc-wmi: Add support to blink behavior for NUC8/10

2021-05-16 Thread Mauro Carvalho Chehab
The hardware blink logic works for both Power State and Software
controlled LEDs.

Just like brightness, there is one different blink behavior
per different power state. Due to that, the logic is somewhat
more complex than what it would be expected otherwise.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/nuc-led/nuc-wmi.c | 347 +++---
 1 file changed, 322 insertions(+), 25 deletions(-)

diff --git a/drivers/staging/nuc-led/nuc-wmi.c 
b/drivers/staging/nuc-led/nuc-wmi.c
index a365a8603182..8967c8d54dac 100644
--- a/drivers/staging/nuc-led/nuc-wmi.c
+++ b/drivers/staging/nuc-led/nuc-wmi.c
@@ -527,18 +527,30 @@ static ssize_t nuc_wmi_set_brightness_offset(struct 
device *dev,
 #define LED_ATTR_RW(_name) \
DEVICE_ATTR(_name, 0644, show_##_name, store_##_name)
 
-#define LED_ATTR_POWER_STATE_RW(_name, offset)\
+#define LED_ATTR_POWER_STATE_RW(_name, _offname, _offset) \
static ssize_t show_##_name(struct device *dev,\
struct device_attribute *attr, \
char *buf) \
{  \
-   return show_brightness_offset(dev, attr, offset, buf); \
+   struct led_classdev *cdev = dev_get_drvdata(dev);  \
+   struct nuc_nmi_led *led;   \
+  \
+   led = container_of(cdev, struct nuc_nmi_led, cdev);\
+   if (led->indicator != LED_IND_POWER_STATE) \
+   return -ENODEV;\
+   return offset_show_##_offname(dev, attr, _offset, buf);\
}  \
static ssize_t store_##_name(struct device *dev,   \
-   struct device_attribute *attr, \
-   const char *buf, size_t len)   \
+struct device_attribute *attr,\
+const char *buf, size_t len)  \
{  \
-   return store_brightness_offset(dev, attr, offset, buf, len);   \
+   struct led_classdev *cdev = dev_get_drvdata(dev);  \
+   struct nuc_nmi_led *led;   \
+  \
+   led = container_of(cdev, struct nuc_nmi_led, cdev);\
+   if (led->indicator != LED_IND_POWER_STATE) \
+   return -ENODEV;\
+   return offset_store_##_offname(dev, attr, _offset, buf, len);  \
}  \
static DEVICE_ATTR(_name, 0644, show_##_name, store_##_name)
 
@@ -681,7 +693,7 @@ static ssize_t nuc6_store_color(struct device *dev,
const char *tmp;
int ret, color;
 
-   tmp = strsep((char **)&buf, ",\n");
+   tmp = strsep((char **)&buf, "\n");
 
if (led->id == POWER_LED) {
for (color = ARRAY_SIZE(nuc6_power_colors)+1; color >= 0; 
color--)
@@ -1000,7 +1012,7 @@ static umode_t nuc_wmi_led_color_is_visible(struct 
kobject *kobj,
 }
 
 /* Show/store brightness */
-static ssize_t show_brightness_offset(struct device *dev,
+static ssize_t offset_show_brightness(struct device *dev,
  struct device_attribute *attr,
  u8 offset,
  char *buf)
@@ -1009,9 +1021,6 @@ static ssize_t show_brightness_offset(struct device *dev,
struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev);
int ret;
 
-   if (led->indicator != LED_IND_POWER_STATE)
-   return -ENODEV;
-
offset *= 
led->reg_table[led->indicator][LED_FUNC_POWER_STATE_NUM_CTRLS];
 
ret = nuc_wmi_get_brightness_offset(dev, led, offset);
@@ -1021,7 +1030,7 @@ static ssize_t show_brightness_offset(struct device *dev,
return scnprintf(buf, PAGE_SIZE, "%d\n", ret);
 }
 
-static ssize_t store_brightness_offset(struct device *dev,
+static ssize_t offset_store_brightness(struct device *dev,
   struct device_attribute *attr,
   u8 offset,
   const char *buf, size_t len)
@@ -1031,9 +1040,6 @

[PATCH 13/17] staging: nuc-led: add support for HDD activity default

2021-05-16 Thread Mauro Carvalho Chehab
There are two possible values for HDD activity behavior:

- 0 Normally off, ON when active
- 1 Normally on, OFF when active

Implement a logic to set it.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/nuc-led/nuc-wmi.c | 77 +++
 1 file changed, 77 insertions(+)

diff --git a/drivers/staging/nuc-led/nuc-wmi.c 
b/drivers/staging/nuc-led/nuc-wmi.c
index 1a6e2b17c888..68143d45c34c 100644
--- a/drivers/staging/nuc-led/nuc-wmi.c
+++ b/drivers/staging/nuc-led/nuc-wmi.c
@@ -1626,10 +1626,86 @@ static umode_t nuc_wmi_led_blink_is_visible(struct 
kobject *kobj,
return 0;
 }
 
+/* HDD activity behavior */
+static ssize_t show_hdd_default(struct device *dev,
+  struct device_attribute *attr,
+  char *buf)
+{
+   struct led_classdev *cdev = dev_get_drvdata(dev);
+   struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev);
+   u8 input[NUM_INPUT_ARGS] = { 0 };
+   u8 output[NUM_OUTPUT_ARGS];
+   int ctrl, ret, val;
+
+   if (led->indicator != LED_IND_HDD_ACTIVITY)
+   return -EINVAL;
+
+   ctrl = led->reg_table[led->indicator][LED_FUNC_HDD_BEHAVIOR];
+
+   if (!nuc_wmi_test_control(dev, led, ctrl))
+   return -ENODEV;
+
+   input[0] = LED_NEW_GET_CONTROL_ITEM;
+   input[1] = led->id;
+   input[2] = led->indicator;
+   input[3] = ctrl;
+
+   ret = nuc_nmi_cmd(dev, LED_NEW_GET_STATUS, input, output);
+   if (ret)
+   return ret;
+
+   val = output[0];
+
+   if (val == 0)
+   return scnprintf(buf, PAGE_SIZE, "off\n");
+
+   return scnprintf(buf, PAGE_SIZE, "on\n");
+}
+
+static ssize_t store_hdd_default(struct device *dev,
+   struct device_attribute *attr,
+   const char *buf, size_t len)
+{
+   struct led_classdev *cdev = dev_get_drvdata(dev);
+   struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev);
+   u8 input[NUM_INPUT_ARGS] = { 0 };
+   int ctrl, val, ret;
+   const char *tmp;
+
+   if (led->indicator != LED_IND_HDD_ACTIVITY)
+   return -EINVAL;
+
+   ctrl = led->reg_table[led->indicator][LED_FUNC_HDD_BEHAVIOR];
+
+   if (!nuc_wmi_test_control(dev, led, ctrl))
+   return -ENODEV;
+
+   tmp = strsep((char **)&buf, "\n");
+   if (!strcmp(tmp, "on"))
+   val = 1;
+   else if (!strcmp(tmp, "off"))
+   val = 0;
+   else
+   return -EINVAL;
+
+   input[0] = led->id;
+   input[1] = led->indicator;
+   input[2] = ctrl;
+   input[3] = val;
+
+   ret = nuc_nmi_cmd(dev, LED_SET_VALUE, input, NULL);
+   if (ret)
+   return ret;
+
+   return len;
+}
+
+
 static LED_ATTR_RW(indicator);
 static LED_ATTR_RW(color);
 static LED_ATTR_RW(blink_behavior);
 static LED_ATTR_RW(blink_frequency);
+static LED_ATTR_RW(hdd_default);
 
 LED_ATTR_POWER_STATE_RW(s0_brightness, brightness, 0);
 LED_ATTR_POWER_STATE_RW(s0_blink_behavior, blink_behavior, 0);
@@ -1657,6 +1733,7 @@ LED_ATTR_POWER_STATE_RW(standby_blink_frequency, 
blink_frequency, 2);
 
 static struct attribute *nuc_wmi_led_attr[] = {
&dev_attr_indicator.attr,
+   &dev_attr_hdd_default.attr,
NULL,
 };
 
-- 
2.31.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 16/17] staging: nuc-wmi: add support for changing the power limit scheme

2021-05-16 Thread Mauro Carvalho Chehab
The power limit indicator may have 2 behaviors:

1. Its color gradually changes from green to red;
2. It displays a single color

Add support for it.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/nuc-led/nuc-wmi.c | 93 +++
 1 file changed, 93 insertions(+)

diff --git a/drivers/staging/nuc-led/nuc-wmi.c 
b/drivers/staging/nuc-led/nuc-wmi.c
index 9e8164cd77ec..2d9c49d72703 100644
--- a/drivers/staging/nuc-led/nuc-wmi.c
+++ b/drivers/staging/nuc-led/nuc-wmi.c
@@ -1764,6 +1764,8 @@ static ssize_t store_ethernet_type(struct device *dev,
if (!nuc_wmi_test_control(dev, led, ctrl))
return -ENODEV;
 
+   tmp = strsep((char **)&buf, "\n");
+
for (val = 0; val < ARRAY_SIZE(ethernet_type); val++)
if (!strcasecmp(tmp, ethernet_type[val]))
break;
@@ -1783,12 +1785,102 @@ static ssize_t store_ethernet_type(struct device *dev,
return len;
 }
 
+/* Power Limit Indication scheme  */
+static const char * const power_limit_scheme[] = {
+   "green to red",
+   "single color"
+};
+
+static ssize_t show_power_limit_scheme(struct device *dev,
+  struct device_attribute *attr,
+  char *buf)
+{
+   struct led_classdev *cdev = dev_get_drvdata(dev);
+   struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev);
+   u8 input[NUM_INPUT_ARGS] = { 0 };
+   u8 output[NUM_OUTPUT_ARGS];
+   int ctrl, ret, val, i, n;
+   int size = PAGE_SIZE;
+   char *p = buf;
+
+   if (led->indicator != LED_IND_POWER_LIMIT)
+   return -EINVAL;
+
+   ctrl = led->reg_table[led->indicator][LED_FUNC_POWER_STATE_NUM_CTRLS];
+
+   if (!nuc_wmi_test_control(dev, led, ctrl))
+   return -ENODEV;
+
+   input[0] = LED_NEW_GET_CONTROL_ITEM;
+   input[1] = led->id;
+   input[2] = led->indicator;
+   input[3] = ctrl;
+
+   ret = nuc_nmi_cmd(dev, LED_NEW_GET_STATUS, input, output);
+   if (ret)
+   return ret;
+
+   val = output[0];
+
+   for (i = 0; i < ARRAY_SIZE(power_limit_scheme); i++) {
+   if (i == val)
+   n = scnprintf(p, size, "[%s]  ", power_limit_scheme[i]);
+   else
+   n = scnprintf(p, size, "%s  ", power_limit_scheme[i]);
+   p += n;
+   size -= n;
+   }
+   size -= scnprintf(p, size, "\n");
+
+   return PAGE_SIZE - size;
+}
+
+static ssize_t store_power_limit_scheme(struct device *dev,
+   struct device_attribute *attr,
+   const char *buf, size_t len)
+{
+   struct led_classdev *cdev = dev_get_drvdata(dev);
+   struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev);
+   u8 input[NUM_INPUT_ARGS] = { 0 };
+   int ctrl, val, ret;
+   const char *tmp;
+
+   if (led->indicator != LED_IND_POWER_LIMIT)
+   return -EINVAL;
+
+   ctrl = led->reg_table[led->indicator][LED_FUNC_POWER_STATE_NUM_CTRLS];
+
+   if (!nuc_wmi_test_control(dev, led, ctrl))
+   return -ENODEV;
+
+   tmp = strsep((char **)&buf, "\n");
+
+   for (val = 0; val < ARRAY_SIZE(power_limit_scheme); val++)
+   if (!strcasecmp(tmp, power_limit_scheme[val]))
+   break;
+
+   if (val >= ARRAY_SIZE(power_limit_scheme))
+   return -EINVAL;
+
+   input[0] = led->id;
+   input[1] = led->indicator;
+   input[2] = ctrl;
+   input[3] = val;
+
+   ret = nuc_nmi_cmd(dev, LED_SET_VALUE, input, NULL);
+   if (ret)
+   return ret;
+
+   return len;
+}
+
 static LED_ATTR_RW(indicator);
 static LED_ATTR_RW(color);
 static LED_ATTR_RW(blink_behavior);
 static LED_ATTR_RW(blink_frequency);
 static LED_ATTR_RW(hdd_default);
 static LED_ATTR_RW(ethernet_type);
+static LED_ATTR_RW(power_limit_scheme);
 
 LED_ATTR_POWER_STATE_RW(s0_brightness, brightness, 0);
 LED_ATTR_POWER_STATE_RW(s0_blink_behavior, blink_behavior, 0);
@@ -1818,6 +1910,7 @@ static struct attribute *nuc_wmi_led_attr[] = {
&dev_attr_indicator.attr,
&dev_attr_hdd_default.attr,
&dev_attr_ethernet_type.attr,
+   &dev_attr_power_limit_scheme.attr,
NULL,
 };
 
-- 
2.31.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 15/17] staging: nuc-wmi: add support for changing the ethernet type indicator

2021-05-16 Thread Mauro Carvalho Chehab
The Ethernet type indicator can be configured to show the status
of LAN1, LAN1 or both. Add support for it.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/nuc-led/nuc-wmi.c | 89 +++
 1 file changed, 89 insertions(+)

diff --git a/drivers/staging/nuc-led/nuc-wmi.c 
b/drivers/staging/nuc-led/nuc-wmi.c
index fab0094a20e4..9e8164cd77ec 100644
--- a/drivers/staging/nuc-led/nuc-wmi.c
+++ b/drivers/staging/nuc-led/nuc-wmi.c
@@ -1695,12 +1695,100 @@ static ssize_t store_hdd_default(struct device *dev,
return len;
 }
 
+/* Ethernet type  */
+static const char * const ethernet_type[] = {
+   "LAN1",
+   "LAN2",
+   "LAN1+LAN2"
+};
+
+static ssize_t show_ethernet_type(struct device *dev,
+  struct device_attribute *attr,
+  char *buf)
+{
+   struct led_classdev *cdev = dev_get_drvdata(dev);
+   struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev);
+   u8 input[NUM_INPUT_ARGS] = { 0 };
+   u8 output[NUM_OUTPUT_ARGS];
+   int ctrl, ret, val, i, n;
+   int size = PAGE_SIZE;
+   char *p = buf;
+
+   if (led->indicator != LED_IND_ETHERNET)
+   return -EINVAL;
+
+   ctrl = led->reg_table[led->indicator][LED_FUNC_ETH_TYPE];
+
+   if (!nuc_wmi_test_control(dev, led, ctrl))
+   return -ENODEV;
+
+   input[0] = LED_NEW_GET_CONTROL_ITEM;
+   input[1] = led->id;
+   input[2] = led->indicator;
+   input[3] = ctrl;
+
+   ret = nuc_nmi_cmd(dev, LED_NEW_GET_STATUS, input, output);
+   if (ret)
+   return ret;
+
+   val = output[0];
+
+   for (i = 0; i < ARRAY_SIZE(ethernet_type); i++) {
+   if (i == val)
+   n = scnprintf(p, size, "[%s]  ", ethernet_type[i]);
+   else
+   n = scnprintf(p, size, "%s  ", ethernet_type[i]);
+   p += n;
+   size -= n;
+   }
+   size -= scnprintf(p, size, "\n");
+
+   return PAGE_SIZE - size;
+}
+
+static ssize_t store_ethernet_type(struct device *dev,
+   struct device_attribute *attr,
+   const char *buf, size_t len)
+{
+   struct led_classdev *cdev = dev_get_drvdata(dev);
+   struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev);
+   u8 input[NUM_INPUT_ARGS] = { 0 };
+   int ctrl, val, ret;
+   const char *tmp;
+
+   if (led->indicator != LED_IND_ETHERNET)
+   return -EINVAL;
+
+   ctrl = led->reg_table[led->indicator][LED_FUNC_ETH_TYPE];
+
+   if (!nuc_wmi_test_control(dev, led, ctrl))
+   return -ENODEV;
+
+   for (val = 0; val < ARRAY_SIZE(ethernet_type); val++)
+   if (!strcasecmp(tmp, ethernet_type[val]))
+   break;
+
+   if (val >= ARRAY_SIZE(ethernet_type))
+   return -EINVAL;
+
+   input[0] = led->id;
+   input[1] = led->indicator;
+   input[2] = ctrl;
+   input[3] = val;
+
+   ret = nuc_nmi_cmd(dev, LED_SET_VALUE, input, NULL);
+   if (ret)
+   return ret;
+
+   return len;
+}
 
 static LED_ATTR_RW(indicator);
 static LED_ATTR_RW(color);
 static LED_ATTR_RW(blink_behavior);
 static LED_ATTR_RW(blink_frequency);
 static LED_ATTR_RW(hdd_default);
+static LED_ATTR_RW(ethernet_type);
 
 LED_ATTR_POWER_STATE_RW(s0_brightness, brightness, 0);
 LED_ATTR_POWER_STATE_RW(s0_blink_behavior, blink_behavior, 0);
@@ -1729,6 +1817,7 @@ LED_ATTR_POWER_STATE_RW(standby_blink_frequency, 
blink_frequency, 2);
 static struct attribute *nuc_wmi_led_attr[] = {
&dev_attr_indicator.attr,
&dev_attr_hdd_default.attr,
+   &dev_attr_ethernet_type.attr,
NULL,
 };
 
-- 
2.31.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 00/17] Add an experimental driver for Intel NUC leds

2021-05-16 Thread Mauro Carvalho Chehab
Hi Greg,

This series add support for the LEDs found at Intel NUCs since
NUC version 6.

On several NUC models, the function of the LEDs are programmable,
which allow them to indicate several different hardware events.

They can even be programmed to represent an userspace-driven event.

Some models come with single colored or dual-colored LEDs, but
high end models have RGB LEDs.

Programming them can ether be done via BIOS or by the OS.

There are 3 different API types, and there is already some OOT
drivers that were written to support them, using procfs, each
one using a different (and IMO confusing) API.

After looking at the existing drivers and not liking the uAPI
interfaces there, I opted to write a new driver from scratch,
unifying support for all different versions and using sysfs
via the leds class.

It should be noticed that those devices use the Windows Management
Interface (WMI). There are actually 3 different implementations for it:

- one for NUC6/NUC7, which has limited support for programming just
  two LEDs;
- a complely re-written interface for NUC8, which can program up to
  seven LEDs, named version 0.64;
- an extended version of the NUC8 API, added for NUC10, called version 
  1.0, with has a few differences from version 0.64.

Such WMI APIs are documented at:
  - 
https://www.intel.com/content/www/us/en/support/articles/23426/intel-nuc/intel-nuc-kits.html
  - 
https://raw.githubusercontent.com/nomego/intel_nuc_led/master/specs/INTEL_WMI_LED_0.64.pdf
  - 
https://www.intel.com/content/dam/support/us/en/documents/intel-nuc/WMI-Spec-Intel-NUC-NUC10ixFNx.pdf

I wrote this driver mainly for my NUC8 (NUC8i7HNK), but I used a NUC6
in order to double-check if NUC6 support was not crashing.  Yet, while
the NUC6 model I have accepts the WMI LED API, it doesn't work, as it
seems that the BIOS of my NUC6 doesn't let userspace to program the LEDs.

I don't have any devices using NUC10 API.

Due to the lack of full tests on NUC6 and NUC10, and because I
wrote a new uAPI that's different than the procfs-based ones found
at the OOT drivers, I'm opting to submit this first to staging.

This should allow adjusting the uAPI if needed, and to get feedback from
people using it on NUC6, NUC10 and on other NUC models that would be
compatible with it.

Mauro Carvalho Chehab (17):
  staging: add support for NUC WMI LEDs
  staging: nuc-wmi: detect WMI API detection
  staging: nuc-wmi: add support for changing S0 brightness
  staging: nuc-wmi: add all types of brightness
  staging: nuc-wmi: allow changing the LED colors
  staging: nuc-wmi: add support for WMI API version 1.0
  staging: nuc-wmi: add basic support for NUC6 WMI
  staging: muc-wmi: add brightness and color for NUC6 API
  staging: nuc-wmi: Add support to blink behavior for NUC8/10
  staging: nuc-wmi: get rid of an unused variable
  staging: nuc-wmi: implement blink control for NUC6
  staging: nuc-wmi: better detect NUC6/NUC7 devices
  staging: nuc-led: add support for HDD activity default
  staging: nuc-wmi: fix software blink behavior logic
  staging: nuc-wmi: add support for changing the ethernet type indicator
  staging: nuc-wmi: add support for changing the power limit scheme
  staging: nuc-led: update the TODOs

 MAINTAINERS   |6 +
 drivers/staging/Kconfig   |2 +
 drivers/staging/Makefile  |1 +
 drivers/staging/nuc-led/Kconfig   |   11 +
 drivers/staging/nuc-led/Makefile  |3 +
 drivers/staging/nuc-led/TODO  |8 +
 drivers/staging/nuc-led/nuc-wmi.c | 2100 +
 7 files changed, 2131 insertions(+)
 create mode 100644 drivers/staging/nuc-led/Kconfig
 create mode 100644 drivers/staging/nuc-led/Makefile
 create mode 100644 drivers/staging/nuc-led/TODO
 create mode 100644 drivers/staging/nuc-led/nuc-wmi.c

-- 
2.31.1


___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 12/17] staging: nuc-wmi: better detect NUC6/NUC7 devices

2021-05-16 Thread Mauro Carvalho Chehab
There's no documented way to detect if the WMI API is valid,
as, when it is not valid, it just returns 4 zeros.

However, as having a value of 0x00 for the blinking state
is not valid, we can check for it at detection time, in
order to disable LEDs control on devices that won't
support it.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/nuc-led/nuc-wmi.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/staging/nuc-led/nuc-wmi.c 
b/drivers/staging/nuc-led/nuc-wmi.c
index 5bc4dcec3ea8..1a6e2b17c888 100644
--- a/drivers/staging/nuc-led/nuc-wmi.c
+++ b/drivers/staging/nuc-led/nuc-wmi.c
@@ -312,6 +312,13 @@ static int nuc_wmi_query_leds_nuc6(struct device *dev)
return ret;
}
 
+   /*
+* Detect if NUC6/NUC7 supports the WMI API by checking the
+* returned blink state, as valid values range from 0x01 to 0x07.
+*/
+   if (output[1] == 0x00)
+   return -ENODEV;
+
led = &priv->led[priv->num_leds];
led->id = POWER_LED;
led->color_type = LED_BLUE_AMBER;
@@ -325,6 +332,14 @@ static int nuc_wmi_query_leds_nuc6(struct device *dev)
dev_warn(dev, "Get S0 Ring: error %d\n", ret);
return ret;
}
+
+   /*
+* Detect if NUC6/NUC7 supports the WMI API by checking the
+* returned blink state, as valid values range from 0x01 to 0x07.
+*/
+   if (output[1] == 0x00)
+   return -ENODEV;
+
led = &priv->led[priv->num_leds];
led->id = RING_LED;
led->color_type = LED_BLUE_AMBER;
-- 
2.31.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 10/17] staging: nuc-wmi: get rid of an unused variable

2021-05-16 Thread Mauro Carvalho Chehab
drivers/staging/nuc-led/nuc-wmi.c: In function ‘nuc_nmi_cmd’:
drivers/staging/nuc-led/nuc-wmi.c:242:6: warning: variable ‘size’ set 
but not used [-Wunused-but-set-variable]
  242 |  int size, ret;
  |  ^~~~

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/nuc-led/nuc-wmi.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/staging/nuc-led/nuc-wmi.c 
b/drivers/staging/nuc-led/nuc-wmi.c
index 8967c8d54dac..78b0a3279f25 100644
--- a/drivers/staging/nuc-led/nuc-wmi.c
+++ b/drivers/staging/nuc-led/nuc-wmi.c
@@ -239,7 +239,7 @@ static int nuc_nmi_cmd(struct device *dev,
struct acpi_buffer input;
union acpi_object *obj;
acpi_status status;
-   int size, ret;
+   int ret;
u8 *p;
 
input.length = NUM_INPUT_ARGS;
@@ -281,8 +281,6 @@ static int nuc_nmi_cmd(struct device *dev,
goto err;
}
 
-   size = NUM_OUTPUT_ARGS + 1;
-
if (output_args) {
memcpy(output_args, p + 1, NUM_OUTPUT_ARGS);
 
-- 
2.31.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 02/17] staging: nuc-wmi: detect WMI API detection

2021-05-16 Thread Mauro Carvalho Chehab
There are currently 3 known API releases:
- 
https://www.intel.com/content/www/us/en/support/articles/23426/intel-nuc/intel-nuc-kits.html
- 
https://raw.githubusercontent.com/nomego/intel_nuc_led/master/specs/INTEL_WMI_LED_0.64.pdf
- 
https://www.intel.com/content/dam/support/us/en/documents/intel-nuc/WMI-Spec-Intel-NUC-NUC10ixFNx.pdf

Add a logic to detect between them, preventing the driver
to work with an unsupported version.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/nuc-led/nuc-wmi.c | 30 +++---
 1 file changed, 27 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/nuc-led/nuc-wmi.c 
b/drivers/staging/nuc-led/nuc-wmi.c
index 15d956ad8556..b75ddd47e443 100644
--- a/drivers/staging/nuc-led/nuc-wmi.c
+++ b/drivers/staging/nuc-led/nuc-wmi.c
@@ -26,6 +26,13 @@
 #define NUM_INPUT_ARGS 4
 #define NUM_OUTPUT_ARGS3
 
+enum led_api_rev {
+   LED_API_UNKNOWN,
+   LED_API_NUC6,
+   LED_API_REV_0_64,
+   LED_API_REV_1_0,
+};
+
 enum led_cmds {
LED_QUERY   = 0x03,
LED_NEW_GET_STATUS  = 0x04,
@@ -33,6 +40,7 @@ enum led_cmds {
LED_SET_VALUE   = 0x06,
LED_NOTIFICATION= 0x07,
LED_SWITCH_TYPE = 0x08,
+   LED_VERSION_CONTROL = 0x09,
 };
 
 enum led_query_subcmd {
@@ -195,7 +203,7 @@ static int nuc_wmi_query_leds(struct device *dev)
struct nuc_wmi *priv = dev_get_drvdata(dev);
u8 cmd, input[NUM_INPUT_ARGS] = { 0 };
u8 output[NUM_OUTPUT_ARGS];
-   int i, id, ret;
+   int i, id, ret, ver = LED_API_UNKNOWN;
u8 leds;
 
/*
@@ -209,12 +217,28 @@ static int nuc_wmi_query_leds(struct device *dev)
cmd = LED_QUERY;
input[0] = LED_QUERY_LIST_ALL;
ret = nuc_nmi_cmd(dev, cmd, input, output);
-   if (ret) {
+   if (ret == -ENOENT) {
+   ver = LED_API_NUC6;
+   } else if (ret) {
dev_warn(dev, "error %d while listing all LEDs\n", ret);
return ret;
+   } else {
+   leds = output[0];
}
 
-   leds = output[0];
+   if (ver != LED_API_NUC6) {
+   ret = nuc_nmi_cmd(dev, LED_VERSION_CONTROL, input, output);
+   ver = output[0] | output[1] << 16;
+   if (!ver)
+   ver = LED_API_REV_0_64;
+   else if (ver == 0x0126)
+   ver = LED_API_REV_1_0;
+   }
+
+   /* Currently, only API Revision 0.64 is supported */
+   if (ver != LED_API_REV_0_64)
+   return -ENODEV;
+
if (!leds) {
dev_warn(dev, "No LEDs found\n");
return -ENODEV;
-- 
2.31.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 03/17] staging: nuc-wmi: add support for changing S0 brightness

2021-05-16 Thread Mauro Carvalho Chehab
Now that the core logic is in place, let's add support to
adjust the S0 brightness level.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/nuc-led/nuc-wmi.c | 79 +++
 1 file changed, 79 insertions(+)

diff --git a/drivers/staging/nuc-led/nuc-wmi.c 
b/drivers/staging/nuc-led/nuc-wmi.c
index b75ddd47e443..62c2764814dd 100644
--- a/drivers/staging/nuc-led/nuc-wmi.c
+++ b/drivers/staging/nuc-led/nuc-wmi.c
@@ -392,7 +392,85 @@ static ssize_t store_indicator(struct device *dev,
return -EINVAL;
 }
 
+/* Get S0 brightness */
+static ssize_t show_s0_brightness(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+   struct led_classdev *cdev = dev_get_drvdata(dev);
+   struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev);
+   u8 cmd, input[NUM_INPUT_ARGS] = { 0 };
+   u8 output[NUM_OUTPUT_ARGS];
+   int ret;
+
+   cmd = LED_NEW_GET_STATUS;
+   input[0] = LED_NEW_GET_CONTROL_ITEM;
+   input[1] = led->id;
+   input[2] = led->indicator;
+   input[3] = 0;
+
+   ret = nuc_nmi_cmd(dev, cmd, input, output);
+   if (ret)
+   return ret;
+
+   /* Multicolor uses a scale from 0 to 100 */
+   if (led->color_type & (LED_BLUE_AMBER | LED_BLUE_WHITE | LED_RGB))
+   return scnprintf(buf, PAGE_SIZE, "%d%%\n", output[0]);
+
+   /* single color uses 0, 50% and 100% */
+   return scnprintf(buf, PAGE_SIZE, "%d%%\n", output[0] * 50);
+}
+
+/* Change S0 brightness */
+static ssize_t store_s0_brightness(struct device *dev,
+  struct device_attribute *attr,
+  const char *buf, size_t len)
+{
+   struct led_classdev *cdev = dev_get_drvdata(dev);
+   struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev);
+   u8 cmd, input[NUM_INPUT_ARGS] = { 0 };
+   int ret;
+   u8 val;
+
+   if (led->indicator == LED_IND_DISABLE) {
+   dev_dbg(dev, "Led %s is disabled. ignoring it.\n", cdev->name);
+   return -EACCES;
+   }
+
+   if (kstrtou8(buf, 0, &val) || val > 100)
+   return -EINVAL;
+
+   /*
+* For single-color LEDs, the value should be between 0 to 2, but,
+* in order to have a consistent API, let's always handle it as if
+* it is a percentage, for both multicolor and single color LEDs.
+* So:
+*  value == 0 will disable the LED
+*  value up to 74% will set it the brightness to 50%
+*  value equal or above 75% will use the maximum brightness.
+*/
+   if (!(led->color_type & (LED_BLUE_AMBER | LED_BLUE_WHITE | LED_RGB))) {
+   if (val > 0 && val < 75)
+   val = 1;
+   if (val >= 75)
+   val = 2;
+   }
+
+   cmd = LED_SET_VALUE;
+   input[0] = led->id;
+   input[1] = led->indicator;
+   input[2] = 0;   /* FIXME: replace by an enum */
+   input[3] = val;
+
+   ret = nuc_nmi_cmd(dev, cmd, input, NULL);
+   if (ret)
+   return ret;
+
+   return len;
+}
+
 static LED_ATTR_RW(indicator);
+static LED_ATTR_RW(s0_brightness);
 
 /*
  * Attributes for multicolor LEDs
@@ -400,6 +478,7 @@ static LED_ATTR_RW(indicator);
 
 static struct attribute *nuc_wmi_multicolor_led_attr[] = {
&dev_attr_indicator.attr,
+   &dev_attr_s0_brightness.attr,
NULL,
 };
 
-- 
2.31.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH v4 00/79] Address some issues with PM runtime at media subsystem

2021-04-29 Thread Mauro Carvalho Chehab
Em Wed, 28 Apr 2021 17:50:08 +0200
Johan Hovold  escreveu:

> On Wed, Apr 28, 2021 at 04:51:21PM +0200, Mauro Carvalho Chehab wrote:

> > 1. despite its name, this is actually a PM runtime resume call,
> >but some developers didn't seem to realize that, as I got this
> >pattern on some drivers:
> > 
> > pm_runtime_get_sync(&client->dev);
> > pm_runtime_disable(&client->dev);
> > pm_runtime_set_suspended(&client->dev);
> > pm_runtime_put_noidle(&client->dev);
> > 
> >It makes no sense to resume PM just to suspend it again ;-)  
> 
> This is perfectly alright. Take a look at ov7740_remove() for example:
> 
>   pm_runtime_get_sync(&client->dev);
>   pm_runtime_disable(&client->dev);
>   pm_runtime_set_suspended(&client->dev);
>   pm_runtime_put_noidle(&client->dev);
>   
>   ov7740_set_power(ov7740, 0);
> 
> There's an explicit power-off after balancing the PM count and this will
> work regardless of the power state when entering this function.

Ok, but this should equally work:

pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);

ov7740_set_power(ov7740, 0);

as there's no additional cleanup made on this particular driver
between pm_runtime_get_sync() and pm_runtime_put_noidle().

> So this has nothing to do with pm_runtime_get_sync() per se.

Yes, but some patches on this series are cleaning up the driver release
logic.

> 
> > 2. Usual *_get() methods only increment their use count on success,
> >but pm_runtime_get_sync() increments it unconditionally. Due to
> >that, several drivers were mistakenly not calling
> >pm_runtime_put_noidle() when it fails;  
> 
> Sure, but pm_runtime_get_async() also works this way. You just won't be
> notified if the async resume fails.

Granted, it makes sense along the pm_runtime kAPI.

It is inconsistent with the behavior of kobject_get*() and other
*_get*() methods that are based or inspired on it, as, on those, the
operations are atomic: either everything succeeds and it doesn't return
an error, or the usage counter is not incremented and the object
state doesn't change after the call.

> > 3. The name of the new variant is a lot clearer:
> > pm_runtime_resume_and_get()
> > As its same clearly says that this is a PM runtime resume function,
> > that also increments the usage counter on success;  
> 
> It also introduced an inconsistency in the API and does not pair as well
> with the pm_runtime_put variants.

Agreed. A name that would be more consistent with PM runtime would
probably be:

pm_runtime_resume_if_get()

as there are already:

pm_runtime_get_if_in_use()
pm_runtime_get_if_active()

But any such discussions are out of the scope of this patchset ;-)

> 
> > 4. Consistency: we did similar changes subsystem wide with
> >for instance strlcpy() and strcpy() that got replaced by
> >strscpy(). Having all drivers using the same known-to-be-safe
> >methods is a good thing;  
> 
> It's not known to be safe; there are ways to get also this interface
> wrong as for example this series has shown.

Very true. Yet, it is a lot simpler to use functions that won't change
the state of the objects when returning an error, as this is by far
the most common pattern within the Kernel.

Human brains are trained to identify certain patterns. When there's
something using a similar pattern, but with a different behavior, 
our brains are more subject to fail identifying problems.

> > 5. Prevent newer drivers to copy-and-paste a code that it would
> >be easier to break if they don't truly understand what's behind
> >the scenes.  
> 
> Cargo-cult programming always runs that risk.

True.

> > This series replace places  pm_runtime_get_sync(), by calling
> > pm_runtime_resume_and_get() instead.
> > 
> > This should help to avoid future mistakes like that, as people
> > tend to use the existing drivers as examples for newer ones.  
> 
> The only valid point about and use for pm_runtime_resume_and_get() is to
> avoid leaking a PM usage count reference in the unlikely case that
> resume fails (something which hardly any driver implements recovery
> from anyway).
> 
> It's a convenience wrapper that saves you from writing one extra line in
> some cases (depending on how you implement runtime-pm support) and not a
> silver bullet against bugs.
>  
> > compile-tested only.
> > 
> > Patches 1 to 7 fix some issues that already exists at the current
> > PM runtime code;
>

Re: [PATCH v4 20/79] staging: media: rkvdec: fix pm_runtime_get_sync() usage count

2021-04-29 Thread Mauro Carvalho Chehab
Em Wed, 28 Apr 2021 17:09:57 +0200
Johan Hovold  escreveu:

> On Wed, Apr 28, 2021 at 04:51:41PM +0200, Mauro Carvalho Chehab wrote:
> > The pm_runtime_get_sync() internally increments the
> > dev->power.usage_count without decrementing it, even on errors.
> > Replace it by the new pm_runtime_resume_and_get(), introduced by:
> > commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal 
> > with usage counter")
> > in order to properly decrement the usage counter and avoid memory
> > leaks.  
> 
> Again, there is no memory leak here either. Just a potential PM usage
> counter leak.

True. Will fix it at the entire series with:

FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch -f --msg-filter 
"cat|perl -0pe 's/ and avoid memory\n\s*leaks./, avoiding\na potential PM usage 
counter leak./igs'" BASE..

Regards,
Mauro
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH v4 79/79] media: hantro: do a PM resume earlier

2021-04-29 Thread Mauro Carvalho Chehab
Em Wed, 28 Apr 2021 14:17:50 -0300
Ezequiel Garcia  escreveu:

> Hi Mauro,
> 
> Thanks a lot for taking care of this.
> 
> On Wed, 2021-04-28 at 16:52 +0200, Mauro Carvalho Chehab wrote:
> > The device_run() first enables the clock and then
> > tries to resume PM runtime, checking for errors.
> > 
> > Well, if for some reason the pm_runtime can not resume,
> > it would be better to detect it beforehand.
> > 
> > So, change the order inside device_run().
> > 
> > Signed-off-by: Mauro Carvalho Chehab   
> 
> Clocks could be behind power-domains, IIRC, so this change
> is fixing that.
> 
> However, this has ever been a problem for this driver,
> so I don't think it makes sense to bother with Fixes tag.

I would prefer to move this patch to the first part of this
series, together with other fixes, rebasing it to apply cleanly
before the pm_runtime_resume_and_get() patch, with:

Fixes: 775fec69008d ("media: add Rockchip VPU JPEG encoder driver")

This way, people that could be interested on backporting it will be
capable to apply it as is to stable Kernel releases that came
with this driver.

> 
> Reviewed-by: Ezequiel Garcia 
> 
> Thanks,
> Ezequiel
> 
> > ---
> >  drivers/staging/media/hantro/hantro_drv.c | 8 
> >  1 file changed, 4 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/staging/media/hantro/hantro_drv.c 
> > b/drivers/staging/media/hantro/hantro_drv.c
> > index 25fa36e7e773..67de6b15236d 100644
> > --- a/drivers/staging/media/hantro/hantro_drv.c
> > +++ b/drivers/staging/media/hantro/hantro_drv.c
> > @@ -160,14 +160,14 @@ static void device_run(void *priv)
> > src = hantro_get_src_buf(ctx);
> > dst = hantro_get_dst_buf(ctx);
> >  
> > -   ret = clk_bulk_enable(ctx->dev->variant->num_clocks, 
> > ctx->dev->clocks);
> > -   if (ret)
> > -   goto err_cancel_job;
> > -
> > ret = pm_runtime_resume_and_get(ctx->dev->dev);
> > if (ret < 0)
> > goto err_cancel_job;
> >  
> > +   ret = clk_bulk_enable(ctx->dev->variant->num_clocks, 
> > ctx->dev->clocks);
> > +   if (ret)
> > +   goto err_cancel_job;
> > +
> > v4l2_m2m_buf_copy_metadata(src, dst, true);
> >  
> > ctx->codec_ops->run(ctx);  
> 
> 



Thanks,
Mauro
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v4 25/79] staging: media: tegra-vde: use pm_runtime_resume_and_get()

2021-04-28 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/tegra-vde/vde.c | 19 ---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/media/tegra-vde/vde.c 
b/drivers/staging/media/tegra-vde/vde.c
index 28845b5bafaf..1cdacb3f781c 100644
--- a/drivers/staging/media/tegra-vde/vde.c
+++ b/drivers/staging/media/tegra-vde/vde.c
@@ -775,9 +775,9 @@ static int tegra_vde_ioctl_decode_h264(struct tegra_vde 
*vde,
if (ret)
goto release_dpb_frames;
 
-   ret = pm_runtime_get_sync(dev);
+   ret = pm_runtime_resume_and_get(dev);
if (ret < 0)
-   goto put_runtime_pm;
+   goto unlock;
 
/*
 * We rely on the VDE registers reset value, otherwise VDE
@@ -843,6 +843,8 @@ static int tegra_vde_ioctl_decode_h264(struct tegra_vde 
*vde,
 put_runtime_pm:
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
+
+unlock:
mutex_unlock(&vde->lock);
 
 release_dpb_frames:
@@ -1069,11 +1071,17 @@ static int tegra_vde_probe(struct platform_device *pdev)
 * power-cycle it in order to put hardware into a predictable lower
 * power state.
 */
-   pm_runtime_get_sync(dev);
+   if (pm_runtime_resume_and_get(dev) < 0)
+   goto err_pm_runtime;
+
pm_runtime_put(dev);
 
return 0;
 
+err_pm_runtime:
+   pm_runtime_dont_use_autosuspend(dev);
+   pm_runtime_disable(dev);
+
 err_deinit_iommu:
tegra_vde_iommu_deinit(vde);
 
@@ -1089,7 +1097,12 @@ static int tegra_vde_remove(struct platform_device *pdev)
struct tegra_vde *vde = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
 
+   /*
+* As it increments RPM usage_count even on errors, we don't need to
+* check the returned code here.
+*/
pm_runtime_get_sync(dev);
+
pm_runtime_dont_use_autosuspend(dev);
pm_runtime_disable(dev);
 
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v4 20/79] staging: media: rkvdec: fix pm_runtime_get_sync() usage count

2021-04-28 Thread Mauro Carvalho Chehab
The pm_runtime_get_sync() internally increments the
dev->power.usage_count without decrementing it, even on errors.
Replace it by the new pm_runtime_resume_and_get(), introduced by:
commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
in order to properly decrement the usage counter and avoid memory
leaks.

Reviewed-by: Ezequiel Garcia 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/rkvdec/rkvdec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/media/rkvdec/rkvdec.c 
b/drivers/staging/media/rkvdec/rkvdec.c
index d821661d30f3..8c17615f3a7a 100644
--- a/drivers/staging/media/rkvdec/rkvdec.c
+++ b/drivers/staging/media/rkvdec/rkvdec.c
@@ -658,7 +658,7 @@ static void rkvdec_device_run(void *priv)
if (WARN_ON(!desc))
return;
 
-   ret = pm_runtime_get_sync(rkvdec->dev);
+   ret = pm_runtime_resume_and_get(rkvdec->dev);
if (ret < 0) {
rkvdec_job_finish_no_pm(ctx, VB2_BUF_STATE_ERROR);
return;
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v4 78/79] media: hantro: use pm_runtime_resume_and_get()

2021-04-28 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

While there's nothing wrong with the current usage on this driver,
as we're getting rid of the pm_runtime_get_sync() call all over
the media subsystem, let's remove the last occurrence on this
driver.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/hantro/hantro_drv.c | 23 ---
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/media/hantro/hantro_drv.c 
b/drivers/staging/media/hantro/hantro_drv.c
index 595e82a82728..25fa36e7e773 100644
--- a/drivers/staging/media/hantro/hantro_drv.c
+++ b/drivers/staging/media/hantro/hantro_drv.c
@@ -56,14 +56,12 @@ dma_addr_t hantro_get_ref(struct hantro_ctx *ctx, u64 ts)
return hantro_get_dec_buf_addr(ctx, buf);
 }
 
-static void hantro_job_finish(struct hantro_dev *vpu,
- struct hantro_ctx *ctx,
- enum vb2_buffer_state result)
+static void hantro_job_finish_no_pm(struct hantro_dev *vpu,
+   struct hantro_ctx *ctx,
+   enum vb2_buffer_state result)
 {
struct vb2_v4l2_buffer *src, *dst;
 
-   pm_runtime_mark_last_busy(vpu->dev);
-   pm_runtime_put_autosuspend(vpu->dev);
clk_bulk_disable(vpu->variant->num_clocks, vpu->clocks);
 
src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
@@ -81,6 +79,16 @@ static void hantro_job_finish(struct hantro_dev *vpu,
 result);
 }
 
+static void hantro_job_finish(struct hantro_dev *vpu,
+ struct hantro_ctx *ctx,
+ enum vb2_buffer_state result)
+{
+   pm_runtime_mark_last_busy(vpu->dev);
+   pm_runtime_put_autosuspend(vpu->dev);
+
+   hantro_job_finish_no_pm(vpu, ctx, result);
+}
+
 void hantro_irq_done(struct hantro_dev *vpu,
 enum vb2_buffer_state result)
 {
@@ -155,7 +163,8 @@ static void device_run(void *priv)
ret = clk_bulk_enable(ctx->dev->variant->num_clocks, ctx->dev->clocks);
if (ret)
goto err_cancel_job;
-   ret = pm_runtime_get_sync(ctx->dev->dev);
+
+   ret = pm_runtime_resume_and_get(ctx->dev->dev);
if (ret < 0)
goto err_cancel_job;
 
@@ -165,7 +174,7 @@ static void device_run(void *priv)
return;
 
 err_cancel_job:
-   hantro_job_finish(ctx->dev, ctx, VB2_BUF_STATE_ERROR);
+   hantro_job_finish_no_pm(ctx->dev, ctx, VB2_BUF_STATE_ERROR);
 }
 
 static struct v4l2_m2m_ops vpu_m2m_ops = {
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v4 26/79] staging: media: tegra-video: use pm_runtime_resume_and_get()

2021-04-28 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/tegra-video/csi.c | 3 +--
 drivers/staging/media/tegra-video/vi.c  | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/media/tegra-video/csi.c 
b/drivers/staging/media/tegra-video/csi.c
index 033a6935c26d..e938bf4c48b6 100644
--- a/drivers/staging/media/tegra-video/csi.c
+++ b/drivers/staging/media/tegra-video/csi.c
@@ -298,10 +298,9 @@ static int tegra_csi_enable_stream(struct v4l2_subdev 
*subdev)
struct tegra_csi *csi = csi_chan->csi;
int ret, err;
 
-   ret = pm_runtime_get_sync(csi->dev);
+   ret = pm_runtime_resume_and_get(csi->dev);
if (ret < 0) {
dev_err(csi->dev, "failed to get runtime PM: %d\n", ret);
-   pm_runtime_put_noidle(csi->dev);
return ret;
}
 
diff --git a/drivers/staging/media/tegra-video/vi.c 
b/drivers/staging/media/tegra-video/vi.c
index 7a09061cda57..1298740a9c6c 100644
--- a/drivers/staging/media/tegra-video/vi.c
+++ b/drivers/staging/media/tegra-video/vi.c
@@ -297,10 +297,9 @@ static int tegra_channel_start_streaming(struct vb2_queue 
*vq, u32 count)
struct tegra_vi_channel *chan = vb2_get_drv_priv(vq);
int ret;
 
-   ret = pm_runtime_get_sync(chan->vi->dev);
+   ret = pm_runtime_resume_and_get(chan->vi->dev);
if (ret < 0) {
dev_err(chan->vi->dev, "failed to get runtime PM: %d\n", ret);
-   pm_runtime_put_noidle(chan->vi->dev);
return ret;
}
 
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v4 79/79] media: hantro: do a PM resume earlier

2021-04-28 Thread Mauro Carvalho Chehab
The device_run() first enables the clock and then
tries to resume PM runtime, checking for errors.

Well, if for some reason the pm_runtime can not resume,
it would be better to detect it beforehand.

So, change the order inside device_run().

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/hantro/hantro_drv.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/media/hantro/hantro_drv.c 
b/drivers/staging/media/hantro/hantro_drv.c
index 25fa36e7e773..67de6b15236d 100644
--- a/drivers/staging/media/hantro/hantro_drv.c
+++ b/drivers/staging/media/hantro/hantro_drv.c
@@ -160,14 +160,14 @@ static void device_run(void *priv)
src = hantro_get_src_buf(ctx);
dst = hantro_get_dst_buf(ctx);
 
-   ret = clk_bulk_enable(ctx->dev->variant->num_clocks, ctx->dev->clocks);
-   if (ret)
-   goto err_cancel_job;
-
ret = pm_runtime_resume_and_get(ctx->dev->dev);
if (ret < 0)
goto err_cancel_job;
 
+   ret = clk_bulk_enable(ctx->dev->variant->num_clocks, ctx->dev->clocks);
+   if (ret)
+   goto err_cancel_job;
+
v4l2_m2m_buf_copy_metadata(src, dst, true);
 
ctx->codec_ops->run(ctx);
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v4 00/79] Address some issues with PM runtime at media subsystem

2021-04-28 Thread Mauro Carvalho Chehab
During the review of the patches from unm.edu, one of the patterns
I noticed is the amount of patches trying to fix pm_runtime_get_sync()
calls.

After analyzing the feedback from version 1 of this series, I noticed
a few other weird behaviors at the PM runtime resume code. So, this
series start addressing some bugs and issues at the current code.
Then, it gets rid of pm_runtime_get_sync() at the media subsystem
(with 2 exceptions).

It should be noticed that
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added a new method to does a pm_runtime get, which increments
the usage count only on success.

The rationale of getting rid of pm_runtime_get_sync() is:

1. despite its name, this is actually a PM runtime resume call,
   but some developers didn't seem to realize that, as I got this
   pattern on some drivers:

pm_runtime_get_sync(&client->dev);
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
pm_runtime_put_noidle(&client->dev);

   It makes no sense to resume PM just to suspend it again ;-)

2. Usual *_get() methods only increment their use count on success,
   but pm_runtime_get_sync() increments it unconditionally. Due to
   that, several drivers were mistakenly not calling
   pm_runtime_put_noidle() when it fails;

3. The name of the new variant is a lot clearer:
pm_runtime_resume_and_get()
As its same clearly says that this is a PM runtime resume function,
that also increments the usage counter on success;

4. Consistency: we did similar changes subsystem wide with
   for instance strlcpy() and strcpy() that got replaced by
   strscpy(). Having all drivers using the same known-to-be-safe
   methods is a good thing;

5. Prevent newer drivers to copy-and-paste a code that it would
   be easier to break if they don't truly understand what's behind
   the scenes.

This series replace places  pm_runtime_get_sync(), by calling
pm_runtime_resume_and_get() instead.

This should help to avoid future mistakes like that, as people
tend to use the existing drivers as examples for newer ones.

compile-tested only.

Patches 1 to 7 fix some issues that already exists at the current
PM runtime code;

patches 8 to 20 fix some usage_count problems that still exists
at the media subsystem;

patches 21 to 78 repaces pm_runtime_get_sync() by 
pm_runtime_resume_and_get();

Patch 79 (and a hunk on patch 78) documents the two exceptions
where pm_runtime_get_sync() will still be used for now.

---

v4:
- Added a couple of additional fixes at existing PM runtime code;
- Some patches are now more conservative in order to avoid causing
 regressions.
v3:
- fix a compilation error;
v2:
- addressed pointed issues and fixed a few other PM issues.


Mauro Carvalho Chehab (79):
  media: venus: fix PM runtime logic at venus_sys_error_handler()
  media: s6p_cec: decrement usage count if disabled
  media: i2c: ccs-core: return the right error code at suspend
  media: i2c: ov7740: don't resume at remove time
  media: i2c: video-i2c: don't resume at remove time
  media: i2c: imx334: fix the pm runtime get logic
  media: exynos-gsc: don't resume at remove time
  media: atmel: properly get pm_runtime
  media: marvel-ccic: fix some issues when getting pm_runtime
  media: mdk-mdp: fix pm_runtime_get_sync() usage count
  media: rcar_fdp1: fix pm_runtime_get_sync() usage count
  media: renesas-ceu: Properly check for PM errors
  media: s5p: fix pm_runtime_get_sync() usage count
  media: am437x: fix pm_runtime_get_sync() usage count
  media: sh_vou: fix pm_runtime_get_sync() usage count
  media: mtk-vcodec: fix pm_runtime_get_sync() usage count
  media: s5p-jpeg: fix pm_runtime_get_sync() usage count
  media: sti/delta: fix pm_runtime_get_sync() usage count
  media: sunxi: fix pm_runtime_get_sync() usage count
  staging: media: rkvdec: fix pm_runtime_get_sync() usage count
  staging: media: atomisp: use pm_runtime_resume_and_get()
  staging: media: imx7-mipi-csis: use pm_runtime_resume_and_get()
  staging: media: ipu3: use pm_runtime_resume_and_get()
  staging: media: cedrus_video: use pm_runtime_resume_and_get()
  staging: media: tegra-vde: use pm_runtime_resume_and_get()
  staging: media: tegra-video: use pm_runtime_resume_and_get()
  media: i2c: ak7375: use pm_runtime_resume_and_get()
  media: i2c: ccs-core: use pm_runtime_resume_and_get()
  media: i2c: dw9714: use pm_runtime_resume_and_get()
  media: i2c: dw9768: use pm_runtime_resume_and_get()
  media: i2c: dw9807-vcm: use pm_runtime_resume_and_get()
  media: i2c: hi556: use pm_runtime_resume_and_get()
  media: i2c: imx214: use pm_runtime_resume_and_get()
  media: i2c: imx219: use pm_runtime_resume_and_get()
  media: i2c: imx258: use pm_runtime_resume_and_get()
  media: i2c: imx274: use pm_runtime_resume_and_get()
  media: i2c: imx290: use pm_runtime_resume_and_get()
  media: i2

[PATCH v4 24/79] staging: media: cedrus_video: use pm_runtime_resume_and_get()

2021-04-28 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/sunxi/cedrus/cedrus_video.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
index b62eb8e84057..9ddd789d0b1f 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
@@ -490,11 +490,9 @@ static int cedrus_start_streaming(struct vb2_queue *vq, 
unsigned int count)
}
 
if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
-   ret = pm_runtime_get_sync(dev->dev);
-   if (ret < 0) {
-   pm_runtime_put_noidle(dev->dev);
+   ret = pm_runtime_resume_and_get(dev->dev);
+   if (ret < 0)
goto err_cleanup;
-   }
 
if (dev->dec_ops[ctx->current_codec]->start) {
ret = dev->dec_ops[ctx->current_codec]->start(ctx);
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v4 22/79] staging: media: imx7-mipi-csis: use pm_runtime_resume_and_get()

2021-04-28 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Acked-by: Rui Miguel Silva 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/imx/imx7-mipi-csis.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c 
b/drivers/staging/media/imx/imx7-mipi-csis.c
index 025fdc488bd6..1dc680d94a46 100644
--- a/drivers/staging/media/imx/imx7-mipi-csis.c
+++ b/drivers/staging/media/imx/imx7-mipi-csis.c
@@ -695,11 +695,10 @@ static int mipi_csis_s_stream(struct v4l2_subdev 
*mipi_sd, int enable)
 
mipi_csis_clear_counters(state);
 
-   ret = pm_runtime_get_sync(&state->pdev->dev);
-   if (ret < 0) {
-   pm_runtime_put_noidle(&state->pdev->dev);
+   ret = pm_runtime_resume_and_get(&state->pdev->dev);
+   if (ret < 0)
return ret;
-   }
+
ret = v4l2_subdev_call(state->src_sd, core, s_power, 1);
if (ret < 0 && ret != -ENOIOCTLCMD)
goto done;
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v4 21/79] staging: media: atomisp: use pm_runtime_resume_and_get()

2021-04-28 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/atomisp/pci/atomisp_fops.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c 
b/drivers/staging/media/atomisp/pci/atomisp_fops.c
index f1e6b2597853..26d05474a035 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_fops.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c
@@ -837,7 +837,7 @@ static int atomisp_open(struct file *file)
}
 
/* runtime power management, turn on ISP */
-   ret = pm_runtime_get_sync(vdev->v4l2_dev->dev);
+   ret = pm_runtime_resume_and_get(vdev->v4l2_dev->dev);
if (ret < 0) {
dev_err(isp->dev, "Failed to power on device\n");
goto error;
@@ -881,9 +881,9 @@ static int atomisp_open(struct file *file)
 
 css_error:
atomisp_css_uninit(isp);
-error:
-   hmm_pool_unregister(HMM_POOL_TYPE_DYNAMIC);
pm_runtime_put(vdev->v4l2_dev->dev);
+error:
+   hmm_pool_unregister(HMM_POOL_TYPE_DYNAMIC);
rt_mutex_unlock(&isp->mutex);
return ret;
 }
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v4 23/79] staging: media: ipu3: use pm_runtime_resume_and_get()

2021-04-28 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/ipu3/ipu3.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/staging/media/ipu3/ipu3.c 
b/drivers/staging/media/ipu3/ipu3.c
index ee1bba6bdcac..8e1e9e46e604 100644
--- a/drivers/staging/media/ipu3/ipu3.c
+++ b/drivers/staging/media/ipu3/ipu3.c
@@ -392,10 +392,9 @@ int imgu_s_stream(struct imgu_device *imgu, int enable)
}
 
/* Set Power */
-   r = pm_runtime_get_sync(dev);
+   r = pm_runtime_resume_and_get(dev);
if (r < 0) {
dev_err(dev, "failed to set imgu power\n");
-   pm_runtime_put(dev);
return r;
}
 
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH v3 25/79] staging: media: vde: use pm_runtime_resume_and_get()

2021-04-28 Thread Mauro Carvalho Chehab
Em Tue, 27 Apr 2021 14:47:01 +0300
Dmitry Osipenko  escreveu:

> 27.04.2021 13:26, Mauro Carvalho Chehab пишет:
> > @@ -1088,8 +1090,9 @@ static int tegra_vde_remove(struct platform_device 
> > *pdev)
> >  {
> > struct tegra_vde *vde = platform_get_drvdata(pdev);
> > struct device *dev = &pdev->dev;
> > +   int ret;
> >  
> > -   pm_runtime_get_sync(dev);
> > +   ret = pm_runtime_resume_and_get(dev);  
> 
> Should be cleaner to return error directly here, IMO.

I double-checked how drivers/base/platform.c deals with non-zero
returns at the .remove method:

static int platform_remove(struct device *_dev)
{
struct platform_driver *drv = to_platform_driver(_dev->driver);
struct platform_device *dev = to_platform_device(_dev);

if (drv->remove) {
int ret = drv->remove(dev);

if (ret)
dev_warn(_dev, "remove callback returned a 
non-zero value. This will be ignored.\n");
}
dev_pm_domain_detach(_dev, true);

return 0;
}

Basically, it will print a message but will ignore whatever happens
afterwards.

So, if the driver is changed to return an error there, it will leak
resources.

Thanks,
Mauro
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH v3 79/79] media: hantro: document the usage of pm_runtime_get_sync()

2021-04-27 Thread Mauro Carvalho Chehab
Em Wed, 28 Apr 2021 08:27:42 +0200
Mauro Carvalho Chehab  escreveu:

> Em Tue, 27 Apr 2021 12:18:32 -0300
> Ezequiel Garcia  escreveu:
> 
> > On Tue, 2021-04-27 at 16:08 +0100, Robin Murphy wrote:  
> > > On 2021-04-27 11:27, Mauro Carvalho Chehab wrote:
> > > > Despite other *_get()/*_put() functions, where usage count is
> > > > incremented only if not errors, the pm_runtime_get_sync() has
> > > > a different behavior, incrementing the counter *even* on
> > > > errors.
> > > > 
> > > > That's an error prone behavior, as people often forget to
> > > > decrement the usage counter.
> > > > 
> > > > However, the hantro driver depends on this behavior, as it
> > > > will decrement the usage_count unconditionally at the m2m
> > > > job finish time, which makes sense.
> > > > 
> > > > So, intead of using the pm_runtime_resume_and_get() that
> > > > would decrement the counter on error, keep the current
> > > > API, but add a documentation explaining the rationale for
> > > > keep using pm_runtime_get_sync().
> > > > 
> > > > Signed-off-by: Mauro Carvalho Chehab 
> > > > ---
> > > >   drivers/staging/media/hantro/hantro_drv.c | 7 +++
> > > >   1 file changed, 7 insertions(+)
> > > > 
> > > > diff --git a/drivers/staging/media/hantro/hantro_drv.c 
> > > > b/drivers/staging/media/hantro/hantro_drv.c
> > > > index 595e82a82728..96f940c1c85c 100644
> > > > --- a/drivers/staging/media/hantro/hantro_drv.c
> > > > +++ b/drivers/staging/media/hantro/hantro_drv.c
> > > > @@ -155,6 +155,13 @@ static void device_run(void *priv)
> > > > ret = clk_bulk_enable(ctx->dev->variant->num_clocks, 
> > > > ctx->dev->clocks);
> > > > if (ret)
> > > > goto err_cancel_job;
> > > 
> > > ..except this can also cause the same pm_runtime_put_autosuspend() call 
> > > without even reaching the "matching" get below, so rather than some kind 
> > > of cleverness it seems more like it's just broken :/
> > > 
> > 
> > Indeed, I was trying to find time to cook a quick patch, but kept
> > getting preempted.
> > 
> > Feel free to submit a fix for this, otherwise, I'll try to find
> > time later this week.  
> 
> What about doing this instead:
> 
> diff --git a/drivers/staging/media/hantro/hantro_drv.c 
> b/drivers/staging/media/hantro/hantro_drv.c
> index 595e82a82728..67de6b15236d 100644
> --- a/drivers/staging/media/hantro/hantro_drv.c
> +++ b/drivers/staging/media/hantro/hantro_drv.c
> @@ -56,14 +56,12 @@ dma_addr_t hantro_get_ref(struct hantro_ctx *ctx, u64 ts)
>   return hantro_get_dec_buf_addr(ctx, buf);
>  }
>  
> -static void hantro_job_finish(struct hantro_dev *vpu,
> -   struct hantro_ctx *ctx,
> -   enum vb2_buffer_state result)
> +static void hantro_job_finish_no_pm(struct hantro_dev *vpu,
> + struct hantro_ctx *ctx,
> + enum vb2_buffer_state result)
>  {
>   struct vb2_v4l2_buffer *src, *dst;
>  
> - pm_runtime_mark_last_busy(vpu->dev);
> - pm_runtime_put_autosuspend(vpu->dev);
>   clk_bulk_disable(vpu->variant->num_clocks, vpu->clocks);
>  
>   src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
> @@ -81,6 +79,16 @@ static void hantro_job_finish(struct hantro_dev *vpu,
>result);
>  }
>  
> +static void hantro_job_finish(struct hantro_dev *vpu,
> +   struct hantro_ctx *ctx,
> +   enum vb2_buffer_state result)
> +{
> + pm_runtime_mark_last_busy(vpu->dev);
> + pm_runtime_put_autosuspend(vpu->dev);
> +
> + hantro_job_finish_no_pm(vpu, ctx, result);
> +}
> +
>  void hantro_irq_done(struct hantro_dev *vpu,
>enum vb2_buffer_state result)
>  {
> @@ -152,12 +160,13 @@ static void device_run(void *priv)
>   src = hantro_get_src_buf(ctx);
>   dst = hantro_get_dst_buf(ctx);
>  
> + ret = pm_runtime_resume_and_get(ctx->dev->dev);
> + if (ret < 0)
> + goto err_cancel_job;
> +
>   ret = clk_bulk_enable(ctx->dev->variant->num_clocks, ctx->dev->clocks);
>   if (ret)
>   goto err_cancel_job;
> - ret = pm_runtime_get_sync(ctx->dev->dev);
> - if (ret < 0)
&

Re: [PATCH v3 79/79] media: hantro: document the usage of pm_runtime_get_sync()

2021-04-27 Thread Mauro Carvalho Chehab
Em Tue, 27 Apr 2021 12:18:32 -0300
Ezequiel Garcia  escreveu:

> On Tue, 2021-04-27 at 16:08 +0100, Robin Murphy wrote:
> > On 2021-04-27 11:27, Mauro Carvalho Chehab wrote:  
> > > Despite other *_get()/*_put() functions, where usage count is
> > > incremented only if not errors, the pm_runtime_get_sync() has
> > > a different behavior, incrementing the counter *even* on
> > > errors.
> > > 
> > > That's an error prone behavior, as people often forget to
> > > decrement the usage counter.
> > > 
> > > However, the hantro driver depends on this behavior, as it
> > > will decrement the usage_count unconditionally at the m2m
> > > job finish time, which makes sense.
> > > 
> > > So, intead of using the pm_runtime_resume_and_get() that
> > > would decrement the counter on error, keep the current
> > > API, but add a documentation explaining the rationale for
> > > keep using pm_runtime_get_sync().
> > > 
> > > Signed-off-by: Mauro Carvalho Chehab 
> > > ---
> > >   drivers/staging/media/hantro/hantro_drv.c | 7 +++
> > >   1 file changed, 7 insertions(+)
> > > 
> > > diff --git a/drivers/staging/media/hantro/hantro_drv.c 
> > > b/drivers/staging/media/hantro/hantro_drv.c
> > > index 595e82a82728..96f940c1c85c 100644
> > > --- a/drivers/staging/media/hantro/hantro_drv.c
> > > +++ b/drivers/staging/media/hantro/hantro_drv.c
> > > @@ -155,6 +155,13 @@ static void device_run(void *priv)
> > > ret = clk_bulk_enable(ctx->dev->variant->num_clocks, 
> > > ctx->dev->clocks);
> > > if (ret)
> > > goto err_cancel_job;  
> > 
> > ..except this can also cause the same pm_runtime_put_autosuspend() call 
> > without even reaching the "matching" get below, so rather than some kind 
> > of cleverness it seems more like it's just broken :/
> >   
> 
> Indeed, I was trying to find time to cook a quick patch, but kept
> getting preempted.
> 
> Feel free to submit a fix for this, otherwise, I'll try to find
> time later this week.

What about doing this instead:

diff --git a/drivers/staging/media/hantro/hantro_drv.c 
b/drivers/staging/media/hantro/hantro_drv.c
index 595e82a82728..67de6b15236d 100644
--- a/drivers/staging/media/hantro/hantro_drv.c
+++ b/drivers/staging/media/hantro/hantro_drv.c
@@ -56,14 +56,12 @@ dma_addr_t hantro_get_ref(struct hantro_ctx *ctx, u64 ts)
return hantro_get_dec_buf_addr(ctx, buf);
 }
 
-static void hantro_job_finish(struct hantro_dev *vpu,
- struct hantro_ctx *ctx,
- enum vb2_buffer_state result)
+static void hantro_job_finish_no_pm(struct hantro_dev *vpu,
+   struct hantro_ctx *ctx,
+   enum vb2_buffer_state result)
 {
struct vb2_v4l2_buffer *src, *dst;
 
-   pm_runtime_mark_last_busy(vpu->dev);
-   pm_runtime_put_autosuspend(vpu->dev);
clk_bulk_disable(vpu->variant->num_clocks, vpu->clocks);
 
src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
@@ -81,6 +79,16 @@ static void hantro_job_finish(struct hantro_dev *vpu,
 result);
 }
 
+static void hantro_job_finish(struct hantro_dev *vpu,
+ struct hantro_ctx *ctx,
+ enum vb2_buffer_state result)
+{
+   pm_runtime_mark_last_busy(vpu->dev);
+   pm_runtime_put_autosuspend(vpu->dev);
+
+   hantro_job_finish_no_pm(vpu, ctx, result);
+}
+
 void hantro_irq_done(struct hantro_dev *vpu,
 enum vb2_buffer_state result)
 {
@@ -152,12 +160,13 @@ static void device_run(void *priv)
src = hantro_get_src_buf(ctx);
dst = hantro_get_dst_buf(ctx);
 
+   ret = pm_runtime_resume_and_get(ctx->dev->dev);
+   if (ret < 0)
+   goto err_cancel_job;
+
ret = clk_bulk_enable(ctx->dev->variant->num_clocks, ctx->dev->clocks);
if (ret)
goto err_cancel_job;
-   ret = pm_runtime_get_sync(ctx->dev->dev);
-   if (ret < 0)
-   goto err_cancel_job;
 
v4l2_m2m_buf_copy_metadata(src, dst, true);
 
@@ -165,7 +174,7 @@ static void device_run(void *priv)
return;
 
 err_cancel_job:
-   hantro_job_finish(ctx->dev, ctx, VB2_BUF_STATE_ERROR);
+   hantro_job_finish_no_pm(ctx->dev, ctx, VB2_BUF_STATE_ERROR);
 }
 
 static struct v4l2_m2m_ops vpu_m2m_ops = {

Thanks,
Mauro
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 25/79] staging: media: vde: use pm_runtime_resume_and_get()

2021-04-27 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/tegra-vde/vde.c | 16 ++--
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/staging/media/tegra-vde/vde.c 
b/drivers/staging/media/tegra-vde/vde.c
index 28845b5bafaf..8936f140a246 100644
--- a/drivers/staging/media/tegra-vde/vde.c
+++ b/drivers/staging/media/tegra-vde/vde.c
@@ -775,9 +775,9 @@ static int tegra_vde_ioctl_decode_h264(struct tegra_vde 
*vde,
if (ret)
goto release_dpb_frames;
 
-   ret = pm_runtime_get_sync(dev);
+   ret = pm_runtime_resume_and_get(dev);
if (ret < 0)
-   goto put_runtime_pm;
+   goto unlock;
 
/*
 * We rely on the VDE registers reset value, otherwise VDE
@@ -843,6 +843,8 @@ static int tegra_vde_ioctl_decode_h264(struct tegra_vde 
*vde,
 put_runtime_pm:
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
+
+unlock:
mutex_unlock(&vde->lock);
 
 release_dpb_frames:
@@ -1069,8 +1071,8 @@ static int tegra_vde_probe(struct platform_device *pdev)
 * power-cycle it in order to put hardware into a predictable lower
 * power state.
 */
-   pm_runtime_get_sync(dev);
-   pm_runtime_put(dev);
+   if (pm_runtime_resume_and_get(dev) >= 0)
+   pm_runtime_put(dev);
 
return 0;
 
@@ -1088,8 +1090,9 @@ static int tegra_vde_remove(struct platform_device *pdev)
 {
struct tegra_vde *vde = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
+   int ret;
 
-   pm_runtime_get_sync(dev);
+   ret = pm_runtime_resume_and_get(dev);
pm_runtime_dont_use_autosuspend(dev);
pm_runtime_disable(dev);
 
@@ -1097,7 +1100,8 @@ static int tegra_vde_remove(struct platform_device *pdev)
 * Balance RPM state, the VDE power domain is left ON and hardware
 * is clock-gated. It's safe to reboot machine now.
 */
-   pm_runtime_put_noidle(dev);
+   if (ret >= 0)
+   pm_runtime_put_noidle(dev);
clk_disable_unprepare(vde->clk);
 
misc_deregister(&vde->miscdev);
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 27/79] staging: media: vi: use pm_runtime_resume_and_get()

2021-04-27 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/tegra-video/vi.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/staging/media/tegra-video/vi.c 
b/drivers/staging/media/tegra-video/vi.c
index 7a09061cda57..1298740a9c6c 100644
--- a/drivers/staging/media/tegra-video/vi.c
+++ b/drivers/staging/media/tegra-video/vi.c
@@ -297,10 +297,9 @@ static int tegra_channel_start_streaming(struct vb2_queue 
*vq, u32 count)
struct tegra_vi_channel *chan = vb2_get_drv_priv(vq);
int ret;
 
-   ret = pm_runtime_get_sync(chan->vi->dev);
+   ret = pm_runtime_resume_and_get(chan->vi->dev);
if (ret < 0) {
dev_err(chan->vi->dev, "failed to get runtime PM: %d\n", ret);
-   pm_runtime_put_noidle(chan->vi->dev);
return ret;
}
 
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 22/79] staging: media: imx7-mipi-csis: use pm_runtime_resume_and_get()

2021-04-27 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Acked-by: Rui Miguel Silva 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/imx/imx7-mipi-csis.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c 
b/drivers/staging/media/imx/imx7-mipi-csis.c
index 025fdc488bd6..1dc680d94a46 100644
--- a/drivers/staging/media/imx/imx7-mipi-csis.c
+++ b/drivers/staging/media/imx/imx7-mipi-csis.c
@@ -695,11 +695,10 @@ static int mipi_csis_s_stream(struct v4l2_subdev 
*mipi_sd, int enable)
 
mipi_csis_clear_counters(state);
 
-   ret = pm_runtime_get_sync(&state->pdev->dev);
-   if (ret < 0) {
-   pm_runtime_put_noidle(&state->pdev->dev);
+   ret = pm_runtime_resume_and_get(&state->pdev->dev);
+   if (ret < 0)
return ret;
-   }
+
ret = v4l2_subdev_call(state->src_sd, core, s_power, 1);
if (ret < 0 && ret != -ENOIOCTLCMD)
goto done;
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 00/79] Address some issues with PM runtime at media subsystem

2021-04-27 Thread Mauro Carvalho Chehab
During the review of the patches from unm.edu, one of the patterns
I noticed is the amount of patches trying to fix pm_runtime_get_sync()
calls.

After analyzing the feedback from version 1 of this series, I noticed
a few other weird behaviors at the PM runtime resume code. So, this
series start addressing some bugs and issues at the current code.
Then, it gets rid of pm_runtime_get_sync() at the media subsystem
(with 2 exceptions).

It should be noticed that
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added a new method to does a pm_runtime get, which increments
the usage count only on success.

The rationale of getting rid of pm_runtime_get_sync() is:

1. despite its name, this is actually a PM runtime resume call,
   but some developers didn't seem to realize that, as I got this
   pattern on some drivers:

pm_runtime_get_sync(&client->dev);
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
pm_runtime_put_noidle(&client->dev);

   It makes no sense to resume PM just to suspend it again ;-)

2. Usual *_get() methods only increment their use count on success,
   but pm_runtime_get_sync() increments it unconditionally. Due to
   that, several drivers were mistakenly not calling
   pm_runtime_put_noidle() when it fails;

3. The name of the new variant is a lot clearer:
pm_runtime_resume_and_get()
As its same clearly says that this is a PM runtime resume function,
that also increments the usage counter on success;

4. Consistency: we did similar changes subsystem wide with
   for instance strlcpy() and strcpy() that got replaced by
   strscpy(). Having all drivers using the same known-to-be-safe
   methods is a good thing;

5. Prevent newer drivers to copy-and-paste a code that it would
   be easier to break if they don't truly understand what's behind
   the scenes.

This series replace places  pm_runtime_get_sync(), by calling
pm_runtime_resume_and_get() instead.

This should help to avoid future mistakes like that, as people
tend to use the existing drivers as examples for newer ones.

compile-tested only.

Patches 1 to 7 fix some issues that already exists at the current
PM runtime code;

patches 8 to 20 fix some usage_count problems that still exists
at the media subsystem;

patches 21 to 78 repaces pm_runtime_get_sync() by 
pm_runtime_resume_and_get();

Patch 79 (and a hunk on patch 78) documents the two exceptions
where pm_runtime_get_sync() will still be used for now.

---

v3: - fix a compilation error;
v2: - addressed pointed issues and fixed a few other PM issues.

Mauro Carvalho Chehab (79):
  media: venus: fix PM runtime logic at venus_sys_error_handler()
  media: i2c: ccs-core: return the right error code at suspend
  media: i2c: mt9m001: don't resume at remove time
  media: i2c: ov7740: don't resume at remove time
  media: i2c: video-i2c: don't resume at remove time
  media: exynos-gsc: don't resume at remove time
  media: atmel: properly get pm_runtime
  media: marvel-ccic: fix some issues when getting pm_runtime
  media: mdk-mdp: fix pm_runtime_get_sync() usage count
  media: rcar_fdp1: fix pm_runtime_get_sync() usage count
  media: rga-buf: use pm_runtime_resume_and_get()
  media: renesas-ceu: Properly check for PM errors
  media: s5p: fix pm_runtime_get_sync() usage count
  media: am437x: fix pm_runtime_get_sync() usage count
  media: sh_vou: fix pm_runtime_get_sync() usage count
  media: mtk-vcodec: fix pm_runtime_get_sync() usage count
  media: s5p-jpeg: fix pm_runtime_get_sync() usage count
  media: delta-v4l2: fix pm_runtime_get_sync() usage count
  media: sun8i_rotate: fix pm_runtime_get_sync() usage count
  staging: media: rkvdec: fix pm_runtime_get_sync() usage count
  staging: media: atomisp_fops: use pm_runtime_resume_and_get()
  staging: media: imx7-mipi-csis: use pm_runtime_resume_and_get()
  staging: media: ipu3: use pm_runtime_resume_and_get()
  staging: media: cedrus_video: use pm_runtime_resume_and_get()
  staging: media: vde: use pm_runtime_resume_and_get()
  staging: media: csi: use pm_runtime_resume_and_get()
  staging: media: vi: use pm_runtime_resume_and_get()
  media: i2c: ak7375: use pm_runtime_resume_and_get()
  media: i2c: ccs-core: use pm_runtime_resume_and_get()
  media: i2c: dw9714: use pm_runtime_resume_and_get()
  media: i2c: dw9768: use pm_runtime_resume_and_get()
  media: i2c: dw9807-vcm: use pm_runtime_resume_and_get()
  media: i2c: hi556: use pm_runtime_resume_and_get()
  media: i2c: imx214: use pm_runtime_resume_and_get()
  media: i2c: imx219: use pm_runtime_resume_and_get()
  media: i2c: imx258: use pm_runtime_resume_and_get()
  media: i2c: imx274: use pm_runtime_resume_and_get()
  media: i2c: imx290: use pm_runtime_resume_and_get()
  media: i2c: imx319: use pm_runtime_resume_and_get()
  media: i2c: imx334: use pm_runtime_resume_and_get()
  media

[PATCH v3 23/79] staging: media: ipu3: use pm_runtime_resume_and_get()

2021-04-27 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/ipu3/ipu3.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/staging/media/ipu3/ipu3.c 
b/drivers/staging/media/ipu3/ipu3.c
index ee1bba6bdcac..8e1e9e46e604 100644
--- a/drivers/staging/media/ipu3/ipu3.c
+++ b/drivers/staging/media/ipu3/ipu3.c
@@ -392,10 +392,9 @@ int imgu_s_stream(struct imgu_device *imgu, int enable)
}
 
/* Set Power */
-   r = pm_runtime_get_sync(dev);
+   r = pm_runtime_resume_and_get(dev);
if (r < 0) {
dev_err(dev, "failed to set imgu power\n");
-   pm_runtime_put(dev);
return r;
}
 
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 79/79] media: hantro: document the usage of pm_runtime_get_sync()

2021-04-27 Thread Mauro Carvalho Chehab
Despite other *_get()/*_put() functions, where usage count is
incremented only if not errors, the pm_runtime_get_sync() has
a different behavior, incrementing the counter *even* on
errors.

That's an error prone behavior, as people often forget to
decrement the usage counter.

However, the hantro driver depends on this behavior, as it
will decrement the usage_count unconditionally at the m2m
job finish time, which makes sense.

So, intead of using the pm_runtime_resume_and_get() that
would decrement the counter on error, keep the current
API, but add a documentation explaining the rationale for
keep using pm_runtime_get_sync().

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/hantro/hantro_drv.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/staging/media/hantro/hantro_drv.c 
b/drivers/staging/media/hantro/hantro_drv.c
index 595e82a82728..96f940c1c85c 100644
--- a/drivers/staging/media/hantro/hantro_drv.c
+++ b/drivers/staging/media/hantro/hantro_drv.c
@@ -155,6 +155,13 @@ static void device_run(void *priv)
ret = clk_bulk_enable(ctx->dev->variant->num_clocks, ctx->dev->clocks);
if (ret)
goto err_cancel_job;
+
+   /*
+* The pm_runtime_get_sync() will increment dev->power.usage_count,
+* even on errors. That's the expected behavior here, since the
+* hantro_job_finish() function at the error handling code
+* will internally call pm_runtime_put_autosuspend().
+*/
ret = pm_runtime_get_sync(ctx->dev->dev);
if (ret < 0)
goto err_cancel_job;
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 26/79] staging: media: csi: use pm_runtime_resume_and_get()

2021-04-27 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/tegra-video/csi.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/staging/media/tegra-video/csi.c 
b/drivers/staging/media/tegra-video/csi.c
index 033a6935c26d..e938bf4c48b6 100644
--- a/drivers/staging/media/tegra-video/csi.c
+++ b/drivers/staging/media/tegra-video/csi.c
@@ -298,10 +298,9 @@ static int tegra_csi_enable_stream(struct v4l2_subdev 
*subdev)
struct tegra_csi *csi = csi_chan->csi;
int ret, err;
 
-   ret = pm_runtime_get_sync(csi->dev);
+   ret = pm_runtime_resume_and_get(csi->dev);
if (ret < 0) {
dev_err(csi->dev, "failed to get runtime PM: %d\n", ret);
-   pm_runtime_put_noidle(csi->dev);
return ret;
}
 
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 20/79] staging: media: rkvdec: fix pm_runtime_get_sync() usage count

2021-04-27 Thread Mauro Carvalho Chehab
The pm_runtime_get_sync() internally increments the
dev->power.usage_count without decrementing it, even on errors.
Replace it by the new pm_runtime_resume_and_get(), introduced by:
commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
in order to properly decrement the usage counter and avoid memory
leaks.

Reviewed-by: Ezequiel Garcia 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/rkvdec/rkvdec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/media/rkvdec/rkvdec.c 
b/drivers/staging/media/rkvdec/rkvdec.c
index d821661d30f3..8c17615f3a7a 100644
--- a/drivers/staging/media/rkvdec/rkvdec.c
+++ b/drivers/staging/media/rkvdec/rkvdec.c
@@ -658,7 +658,7 @@ static void rkvdec_device_run(void *priv)
if (WARN_ON(!desc))
return;
 
-   ret = pm_runtime_get_sync(rkvdec->dev);
+   ret = pm_runtime_resume_and_get(rkvdec->dev);
if (ret < 0) {
rkvdec_job_finish_no_pm(ctx, VB2_BUF_STATE_ERROR);
return;
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 24/79] staging: media: cedrus_video: use pm_runtime_resume_and_get()

2021-04-27 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/sunxi/cedrus/cedrus_video.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
index b62eb8e84057..9ddd789d0b1f 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
@@ -490,11 +490,9 @@ static int cedrus_start_streaming(struct vb2_queue *vq, 
unsigned int count)
}
 
if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
-   ret = pm_runtime_get_sync(dev->dev);
-   if (ret < 0) {
-   pm_runtime_put_noidle(dev->dev);
+   ret = pm_runtime_resume_and_get(dev->dev);
+   if (ret < 0)
goto err_cleanup;
-   }
 
if (dev->dec_ops[ctx->current_codec]->start) {
ret = dev->dec_ops[ctx->current_codec]->start(ctx);
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 21/79] staging: media: atomisp_fops: use pm_runtime_resume_and_get()

2021-04-27 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/atomisp/pci/atomisp_fops.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c 
b/drivers/staging/media/atomisp/pci/atomisp_fops.c
index f1e6b2597853..26d05474a035 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_fops.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c
@@ -837,7 +837,7 @@ static int atomisp_open(struct file *file)
}
 
/* runtime power management, turn on ISP */
-   ret = pm_runtime_get_sync(vdev->v4l2_dev->dev);
+   ret = pm_runtime_resume_and_get(vdev->v4l2_dev->dev);
if (ret < 0) {
dev_err(isp->dev, "Failed to power on device\n");
goto error;
@@ -881,9 +881,9 @@ static int atomisp_open(struct file *file)
 
 css_error:
atomisp_css_uninit(isp);
-error:
-   hmm_pool_unregister(HMM_POOL_TYPE_DYNAMIC);
pm_runtime_put(vdev->v4l2_dev->dev);
+error:
+   hmm_pool_unregister(HMM_POOL_TYPE_DYNAMIC);
rt_mutex_unlock(&isp->mutex);
return ret;
 }
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 26/79] staging: media: csi: use pm_runtime_resume_and_get()

2021-04-27 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/tegra-video/csi.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/staging/media/tegra-video/csi.c 
b/drivers/staging/media/tegra-video/csi.c
index 033a6935c26d..e938bf4c48b6 100644
--- a/drivers/staging/media/tegra-video/csi.c
+++ b/drivers/staging/media/tegra-video/csi.c
@@ -298,10 +298,9 @@ static int tegra_csi_enable_stream(struct v4l2_subdev 
*subdev)
struct tegra_csi *csi = csi_chan->csi;
int ret, err;
 
-   ret = pm_runtime_get_sync(csi->dev);
+   ret = pm_runtime_resume_and_get(csi->dev);
if (ret < 0) {
dev_err(csi->dev, "failed to get runtime PM: %d\n", ret);
-   pm_runtime_put_noidle(csi->dev);
return ret;
}
 
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 79/79] media: hantro: document the usage of pm_runtime_get_sync()

2021-04-27 Thread Mauro Carvalho Chehab
Despite other *_get()/*_put() functions, where usage count is
incremented only if not errors, the pm_runtime_get_sync() has
a different behavior, incrementing the counter *even* on
errors.

That's an error prone behavior, as people often forget to
decrement the usage counter.

However, the hantro driver depends on this behavior, as it
will decrement the usage_count unconditionally at the m2m
job finish time, which makes sense.

So, intead of using the pm_runtime_resume_and_get() that
would decrement the counter on error, keep the current
API, but add a documentation explaining the rationale for
keep using pm_runtime_get_sync().

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/hantro/hantro_drv.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/staging/media/hantro/hantro_drv.c 
b/drivers/staging/media/hantro/hantro_drv.c
index 595e82a82728..96f940c1c85c 100644
--- a/drivers/staging/media/hantro/hantro_drv.c
+++ b/drivers/staging/media/hantro/hantro_drv.c
@@ -155,6 +155,13 @@ static void device_run(void *priv)
ret = clk_bulk_enable(ctx->dev->variant->num_clocks, ctx->dev->clocks);
if (ret)
goto err_cancel_job;
+
+   /*
+* The pm_runtime_get_sync() will increment dev->power.usage_count,
+* even on errors. That's the expected behavior here, since the
+* hantro_job_finish() function at the error handling code
+* will internally call pm_runtime_put_autosuspend().
+*/
ret = pm_runtime_get_sync(ctx->dev->dev);
if (ret < 0)
goto err_cancel_job;
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 20/79] staging: media: rkvdec: fix pm_runtime_get_sync() usage count

2021-04-27 Thread Mauro Carvalho Chehab
The pm_runtime_get_sync() internally increments the
dev->power.usage_count without decrementing it, even on errors.
Replace it by the new pm_runtime_resume_and_get(), introduced by:
commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
in order to properly decrement the usage counter and avoid memory
leaks.

Reviewed-by: Ezequiel Garcia 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/rkvdec/rkvdec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/media/rkvdec/rkvdec.c 
b/drivers/staging/media/rkvdec/rkvdec.c
index d821661d30f3..8c17615f3a7a 100644
--- a/drivers/staging/media/rkvdec/rkvdec.c
+++ b/drivers/staging/media/rkvdec/rkvdec.c
@@ -658,7 +658,7 @@ static void rkvdec_device_run(void *priv)
if (WARN_ON(!desc))
return;
 
-   ret = pm_runtime_get_sync(rkvdec->dev);
+   ret = pm_runtime_resume_and_get(rkvdec->dev);
if (ret < 0) {
rkvdec_job_finish_no_pm(ctx, VB2_BUF_STATE_ERROR);
return;
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 27/79] staging: media: vi: use pm_runtime_resume_and_get()

2021-04-27 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/tegra-video/vi.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/staging/media/tegra-video/vi.c 
b/drivers/staging/media/tegra-video/vi.c
index 7a09061cda57..1298740a9c6c 100644
--- a/drivers/staging/media/tegra-video/vi.c
+++ b/drivers/staging/media/tegra-video/vi.c
@@ -297,10 +297,9 @@ static int tegra_channel_start_streaming(struct vb2_queue 
*vq, u32 count)
struct tegra_vi_channel *chan = vb2_get_drv_priv(vq);
int ret;
 
-   ret = pm_runtime_get_sync(chan->vi->dev);
+   ret = pm_runtime_resume_and_get(chan->vi->dev);
if (ret < 0) {
dev_err(chan->vi->dev, "failed to get runtime PM: %d\n", ret);
-   pm_runtime_put_noidle(chan->vi->dev);
return ret;
}
 
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 22/79] staging: media: imx7-mipi-csis: use pm_runtime_resume_and_get()

2021-04-27 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Acked-by: Rui Miguel Silva 
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/imx/imx7-mipi-csis.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c 
b/drivers/staging/media/imx/imx7-mipi-csis.c
index 025fdc488bd6..1dc680d94a46 100644
--- a/drivers/staging/media/imx/imx7-mipi-csis.c
+++ b/drivers/staging/media/imx/imx7-mipi-csis.c
@@ -695,11 +695,10 @@ static int mipi_csis_s_stream(struct v4l2_subdev 
*mipi_sd, int enable)
 
mipi_csis_clear_counters(state);
 
-   ret = pm_runtime_get_sync(&state->pdev->dev);
-   if (ret < 0) {
-   pm_runtime_put_noidle(&state->pdev->dev);
+   ret = pm_runtime_resume_and_get(&state->pdev->dev);
+   if (ret < 0)
return ret;
-   }
+
ret = v4l2_subdev_call(state->src_sd, core, s_power, 1);
if (ret < 0 && ret != -ENOIOCTLCMD)
goto done;
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 00/79] Address some issues with PM runtime at media subsystem

2021-04-27 Thread Mauro Carvalho Chehab
During the review of the patches from unm.edu, one of the patterns
I noticed is the amount of patches trying to fix pm_runtime_get_sync()
calls.

After analyzing the feedback from version 1 of this series, I noticed
a few other weird behaviors at the PM runtime resume code. So, this
series start addressing some bugs and issues at the current code.
Then, it gets rid of pm_runtime_get_sync() at the media subsystem
(with 2 exceptions).

It should be noticed that
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added a new method to does a pm_runtime get, which increments
the usage count only on success.

The rationale of getting rid of pm_runtime_get_sync() is:

1. despite its name, this is actually a PM runtime resume call,
   but some developers didn't seem to realize that, as I got this
   pattern on some drivers:

pm_runtime_get_sync(&client->dev);
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
pm_runtime_put_noidle(&client->dev);

   It makes no sense to resume PM just to suspend it again ;-)

2. Usual *_get() methods only increment their use count on success,
   but pm_runtime_get_sync() increments it unconditionally. Due to
   that, several drivers were mistakenly not calling
   pm_runtime_put_noidle() when it fails;

3. The name of the new variant is a lot clearer:
pm_runtime_resume_and_get()
As its same clearly says that this is a PM runtime resume function,
that also increments the usage counter on success;

4. Consistency: we did similar changes subsystem wide with
   for instance strlcpy() and strcpy() that got replaced by
   strscpy(). Having all drivers using the same known-to-be-safe
   methods is a good thing;

5. Prevent newer drivers to copy-and-paste a code that it would
   be easier to break if they don't truly understand what's behind
   the scenes.

This series replace places  pm_runtime_get_sync(), by calling
pm_runtime_resume_and_get() instead.

This should help to avoid future mistakes like that, as people
tend to use the existing drivers as examples for newer ones.

compile-tested only.

Patches 1 to 7 fix some issues that already exists at the current
PM runtime code;

patches 8 to 20 fix some usage_count problems that still exists
at the media subsystem;

patches 21 to 78 repaces pm_runtime_get_sync() by 
pm_runtime_resume_and_get();

Patch 79 (and a hunk on patch 78) documents the two exceptions
where pm_runtime_get_sync() will still be used for now.

Mauro Carvalho Chehab (79):
  media: venus: fix PM runtime logic at venus_sys_error_handler()
  media: i2c: ccs-core: return the right error code at suspend
  media: i2c: mt9m001: don't resume at remove time
  media: i2c: ov7740: don't resume at remove time
  media: i2c: video-i2c: don't resume at remove time
  media: exynos-gsc: don't resume at remove time
  media: atmel: properly get pm_runtime
  media: marvel-ccic: fix some issues when getting pm_runtime
  media: mdk-mdp: fix pm_runtime_get_sync() usage count
  media: rcar_fdp1: fix pm_runtime_get_sync() usage count
  media: rga-buf: use pm_runtime_resume_and_get()
  media: renesas-ceu: Properly check for PM errors
  media: s5p: fix pm_runtime_get_sync() usage count
  media: am437x: fix pm_runtime_get_sync() usage count
  media: sh_vou: fix pm_runtime_get_sync() usage count
  media: mtk-vcodec: fix pm_runtime_get_sync() usage count
  media: s5p-jpeg: fix pm_runtime_get_sync() usage count
  media: delta-v4l2: fix pm_runtime_get_sync() usage count
  media: sun8i_rotate: fix pm_runtime_get_sync() usage count
  staging: media: rkvdec: fix pm_runtime_get_sync() usage count
  staging: media: atomisp_fops: use pm_runtime_resume_and_get()
  staging: media: imx7-mipi-csis: use pm_runtime_resume_and_get()
  staging: media: ipu3: use pm_runtime_resume_and_get()
  staging: media: cedrus_video: use pm_runtime_resume_and_get()
  staging: media: vde: use pm_runtime_resume_and_get()
  staging: media: csi: use pm_runtime_resume_and_get()
  staging: media: vi: use pm_runtime_resume_and_get()
  media: i2c: ak7375: use pm_runtime_resume_and_get()
  media: i2c: ccs-core: use pm_runtime_resume_and_get()
  media: i2c: dw9714: use pm_runtime_resume_and_get()
  media: i2c: dw9768: use pm_runtime_resume_and_get()
  media: i2c: dw9807-vcm: use pm_runtime_resume_and_get()
  media: i2c: hi556: use pm_runtime_resume_and_get()
  media: i2c: imx214: use pm_runtime_resume_and_get()
  media: i2c: imx219: use pm_runtime_resume_and_get()
  media: i2c: imx258: use pm_runtime_resume_and_get()
  media: i2c: imx274: use pm_runtime_resume_and_get()
  media: i2c: imx290: use pm_runtime_resume_and_get()
  media: i2c: imx319: use pm_runtime_resume_and_get()
  media: i2c: imx334: use pm_runtime_resume_and_get()
  media: i2c: imx355: use pm_runtime_resume_and_get()
  media: i2c: mt9m001: use pm_runtime_resume_and_get()
  media:

[PATCH v2 24/79] staging: media: cedrus_video: use pm_runtime_resume_and_get()

2021-04-27 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/sunxi/cedrus/cedrus_video.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
index b62eb8e84057..9ddd789d0b1f 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
@@ -490,11 +490,9 @@ static int cedrus_start_streaming(struct vb2_queue *vq, 
unsigned int count)
}
 
if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
-   ret = pm_runtime_get_sync(dev->dev);
-   if (ret < 0) {
-   pm_runtime_put_noidle(dev->dev);
+   ret = pm_runtime_resume_and_get(dev->dev);
+   if (ret < 0)
goto err_cleanup;
-   }
 
if (dev->dec_ops[ctx->current_codec]->start) {
ret = dev->dec_ops[ctx->current_codec]->start(ctx);
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 21/79] staging: media: atomisp_fops: use pm_runtime_resume_and_get()

2021-04-27 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/atomisp/pci/atomisp_fops.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c 
b/drivers/staging/media/atomisp/pci/atomisp_fops.c
index f1e6b2597853..26d05474a035 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_fops.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c
@@ -837,7 +837,7 @@ static int atomisp_open(struct file *file)
}
 
/* runtime power management, turn on ISP */
-   ret = pm_runtime_get_sync(vdev->v4l2_dev->dev);
+   ret = pm_runtime_resume_and_get(vdev->v4l2_dev->dev);
if (ret < 0) {
dev_err(isp->dev, "Failed to power on device\n");
goto error;
@@ -881,9 +881,9 @@ static int atomisp_open(struct file *file)
 
 css_error:
atomisp_css_uninit(isp);
-error:
-   hmm_pool_unregister(HMM_POOL_TYPE_DYNAMIC);
pm_runtime_put(vdev->v4l2_dev->dev);
+error:
+   hmm_pool_unregister(HMM_POOL_TYPE_DYNAMIC);
rt_mutex_unlock(&isp->mutex);
return ret;
 }
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 25/79] staging: media: vde: use pm_runtime_resume_and_get()

2021-04-27 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/tegra-vde/vde.c | 16 ++--
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/staging/media/tegra-vde/vde.c 
b/drivers/staging/media/tegra-vde/vde.c
index 28845b5bafaf..8936f140a246 100644
--- a/drivers/staging/media/tegra-vde/vde.c
+++ b/drivers/staging/media/tegra-vde/vde.c
@@ -775,9 +775,9 @@ static int tegra_vde_ioctl_decode_h264(struct tegra_vde 
*vde,
if (ret)
goto release_dpb_frames;
 
-   ret = pm_runtime_get_sync(dev);
+   ret = pm_runtime_resume_and_get(dev);
if (ret < 0)
-   goto put_runtime_pm;
+   goto unlock;
 
/*
 * We rely on the VDE registers reset value, otherwise VDE
@@ -843,6 +843,8 @@ static int tegra_vde_ioctl_decode_h264(struct tegra_vde 
*vde,
 put_runtime_pm:
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
+
+unlock:
mutex_unlock(&vde->lock);
 
 release_dpb_frames:
@@ -1069,8 +1071,8 @@ static int tegra_vde_probe(struct platform_device *pdev)
 * power-cycle it in order to put hardware into a predictable lower
 * power state.
 */
-   pm_runtime_get_sync(dev);
-   pm_runtime_put(dev);
+   if (pm_runtime_resume_and_get(dev) >= 0)
+   pm_runtime_put(dev);
 
return 0;
 
@@ -1088,8 +1090,9 @@ static int tegra_vde_remove(struct platform_device *pdev)
 {
struct tegra_vde *vde = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
+   int ret;
 
-   pm_runtime_get_sync(dev);
+   ret = pm_runtime_resume_and_get(dev);
pm_runtime_dont_use_autosuspend(dev);
pm_runtime_disable(dev);
 
@@ -1097,7 +1100,8 @@ static int tegra_vde_remove(struct platform_device *pdev)
 * Balance RPM state, the VDE power domain is left ON and hardware
 * is clock-gated. It's safe to reboot machine now.
 */
-   pm_runtime_put_noidle(dev);
+   if (ret >= 0)
+   pm_runtime_put_noidle(dev);
clk_disable_unprepare(vde->clk);
 
misc_deregister(&vde->miscdev);
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 23/79] staging: media: ipu3: use pm_runtime_resume_and_get()

2021-04-27 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/ipu3/ipu3.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/staging/media/ipu3/ipu3.c 
b/drivers/staging/media/ipu3/ipu3.c
index ee1bba6bdcac..8e1e9e46e604 100644
--- a/drivers/staging/media/ipu3/ipu3.c
+++ b/drivers/staging/media/ipu3/ipu3.c
@@ -392,10 +392,9 @@ int imgu_s_stream(struct imgu_device *imgu, int enable)
}
 
/* Set Power */
-   r = pm_runtime_get_sync(dev);
+   r = pm_runtime_resume_and_get(dev);
if (r < 0) {
dev_err(dev, "failed to set imgu power\n");
-   pm_runtime_put(dev);
return r;
}
 
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 17/78] staging: media: vde: use pm_runtime_resume_and_get()

2021-04-27 Thread Mauro Carvalho Chehab
Hi Dmitry,

Em Sat, 24 Apr 2021 10:35:22 +0300
Dmitry Osipenko  escreveu:

> 24.04.2021 09:44, Mauro Carvalho Chehab пишет:
> > Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal 
> > with usage counter")
> > added pm_runtime_resume_and_get() in order to automatically handle
> > dev->power.usage_count decrement on errors.
> > 
> > Use the new API, in order to cleanup the error check logic.
> > 
> > Signed-off-by: Mauro Carvalho Chehab 
> > ---
> >  drivers/staging/media/tegra-vde/vde.c | 16 ++--
> >  1 file changed, 10 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/staging/media/tegra-vde/vde.c 
> > b/drivers/staging/media/tegra-vde/vde.c
> > index 28845b5bafaf..8936f140a246 100644
> > --- a/drivers/staging/media/tegra-vde/vde.c
> > +++ b/drivers/staging/media/tegra-vde/vde.c
> > @@ -775,9 +775,9 @@ static int tegra_vde_ioctl_decode_h264(struct tegra_vde 
> > *vde,
> > if (ret)
> > goto release_dpb_frames;
> >  
> > -   ret = pm_runtime_get_sync(dev);
> > +   ret = pm_runtime_resume_and_get(dev);
> > if (ret < 0)
> > -   goto put_runtime_pm;
> > +   goto unlock;
> >  
> > /*
> >  * We rely on the VDE registers reset value, otherwise VDE
> > @@ -843,6 +843,8 @@ static int tegra_vde_ioctl_decode_h264(struct tegra_vde 
> > *vde,
> >  put_runtime_pm:
> > pm_runtime_mark_last_busy(dev);
> > pm_runtime_put_autosuspend(dev);
> > +
> > +unlock:
> > mutex_unlock(&vde->lock);
> >  
> >  release_dpb_frames:
> > @@ -1069,8 +1071,8 @@ static int tegra_vde_probe(struct platform_device 
> > *pdev)
> >  * power-cycle it in order to put hardware into a predictable lower
> >  * power state.
> >  */
> > -   pm_runtime_get_sync(dev);
> > -   pm_runtime_put(dev);
> > +   if (pm_runtime_resume_and_get(dev) >= 0)
> > +   pm_runtime_put(dev);
> >  
> > return 0;
> >  
> > @@ -1088,8 +1090,9 @@ static int tegra_vde_remove(struct platform_device 
> > *pdev)
> >  {
> > struct tegra_vde *vde = platform_get_drvdata(pdev);
> > struct device *dev = &pdev->dev;
> > +   int ret;
> >  
> > -   pm_runtime_get_sync(dev);
> > +   ret = pm_runtime_resume_and_get(dev);
> > pm_runtime_dont_use_autosuspend(dev);
> > pm_runtime_disable(dev);
> >  
> > @@ -1097,7 +1100,8 @@ static int tegra_vde_remove(struct platform_device 
> > *pdev)
> >  * Balance RPM state, the VDE power domain is left ON and hardware
> >  * is clock-gated. It's safe to reboot machine now.
> >  */
> > -   pm_runtime_put_noidle(dev);
> > +   if (ret >= 0)
> > +   pm_runtime_put_noidle(dev);
> > clk_disable_unprepare(vde->clk);
> >  
> > misc_deregister(&vde->miscdev);
> >   
> 
> Hello Mauro,
> 
> Thank you very much for the patch. It looks to me that the original
> variant was a bit simpler, this patch adds more code lines without
> changing the previous behaviour. Or am I missing something?

While on several places the newer code is simpler, the end goal here is
to replace all occurrences of pm_runtime_get_sync() from the media 
subsystem, due to the number of problems we're having with this:

1. despite its name, this is actually a PM runtime resume call,
   but some developers didn't seem to realize that, as I got this
   pattern on some drivers:

pm_runtime_get_sync(&client->dev);
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
pm_runtime_put_noidle(&client->dev);

   It makes no sense to resume PM just to suspend it again ;-)

   The name of the new variant is a lot clearer:
pm_runtime_resume_and_get()

2. Usual *_get() methods only increment their use count on success,
   but pm_runtime_get_sync() increments it unconditionally. Due to
   that, several drivers were mistakenly not calling
   pm_runtime_put_noidle() when it fails;

3. Consistency: we did similar changes subsystem wide with
   for instance strlcpy() and strcpy() that got replaced by
   strscpy(). Having all drivers using the same known-to-be-safe
   methods is a good thing;

4. Prevent newer drivers to copy-and-paste a code that it would
   be easier to break if they don't truly understand what's behind
   the scenes.

Thanks,
Mauro
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 13/78] staging: media: hantro_drv: use pm_runtime_resume_and_get()

2021-04-26 Thread Mauro Carvalho Chehab
Em Mon, 26 Apr 2021 14:33:27 +0200
Mauro Carvalho Chehab  escreveu:

> Em Sat, 24 Apr 2021 20:23:53 -0300
> Ezequiel Garcia  escreveu:
> 
> > Hi Mauro,
> > 
> > On Sat, 2021-04-24 at 08:44 +0200, Mauro Carvalho Chehab wrote:  
> > > Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal 
> > > with usage counter")
> > > added pm_runtime_resume_and_get() in order to automatically handle
> > > dev->power.usage_count decrement on errors.
> > > 
> > > Use the new API, in order to cleanup the error check logic.
> > > 
> > > Signed-off-by: Mauro Carvalho Chehab 
> > > ---
> > >  drivers/staging/media/hantro/hantro_drv.c | 2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > 
> > > diff --git a/drivers/staging/media/hantro/hantro_drv.c 
> > > b/drivers/staging/media/hantro/hantro_drv.c
> > > index 595e82a82728..3147dcbebeb9 100644
> > > --- a/drivers/staging/media/hantro/hantro_drv.c
> > > +++ b/drivers/staging/media/hantro/hantro_drv.c
> > > @@ -155,7 +155,7 @@ static void device_run(void *priv)
> > > ret = clk_bulk_enable(ctx->dev->variant->num_clocks, 
> > > ctx->dev->clocks);
> > > if (ret)
> > > goto err_cancel_job;
> > > -   ret = pm_runtime_get_sync(ctx->dev->dev);
> > > +   ret = pm_runtime_resume_and_get(ctx->dev->dev);
> > > if (ret < 0)
> > > goto err_cancel_job;
> > >  
> > 
> > Seems this one needs a different fix: err_cancel_job
> > will call hantro_job_finish which has a pm_runtime put.  
> 
> Good point. Thanks for reviewing it!
> 
> It sounds that this is a place where the best seems
> to keep using pm_runtime_get_sync(), but let's at least add a
> comment explaining why it should be kept here. This should
> help to avoid people to copy-and-paste the code on situations
> where pm_runtime_resume_and_get() should be used instead.
> 
> See enclosed patch.
> 
> Thanks,
> Mauro
> 
> [PATCH] media: hantro: document the usage of pm_runtime_get_sync()
> 
> Despite other *_get()/*_put() functions, where usage count is
> incremented only if not errors, the pm_runtime_get_sync() has
> a different behavior, incrementing the counter *even* on
> errors.
> 
> That's an error prone behavior, as people often forget to
> decrement the usage counter.
> 
> However, the hantro driver depends on this behavior, as it
> will decrement the usage_count unconditionally at the m2m
> job finish time, which makes sense.
> 
> So, intead of using the pm_runtime_resume_and_get() that
> would decrement the counter on error, keep the current
> API, but add a documentation explaining the rationale for
> keep using pm_runtime_get_sync().
> 
> Signed-off-by: Mauro Carvalho Chehab 

Hmm... maybe it can, instead, use the same solution as the
rkvdec driver does, having a job_finish_no_pm() plus the normal
job_finish().

What do you think?

Regards,
Mauro

> 
> diff --git a/drivers/staging/media/hantro/hantro_drv.c 
> b/drivers/staging/media/hantro/hantro_drv.c
> index 595e82a82728..96f940c1c85c 100644
> --- a/drivers/staging/media/hantro/hantro_drv.c
> +++ b/drivers/staging/media/hantro/hantro_drv.c
> @@ -155,6 +155,13 @@ static void device_run(void *priv)
>   ret = clk_bulk_enable(ctx->dev->variant->num_clocks, ctx->dev->clocks);
>   if (ret)
>   goto err_cancel_job;
> +
> + /*
> +  * The pm_runtime_get_sync() will increment dev->power.usage_count,
> +  * even on errors. That's the expected behavior here, since the
> +  * hantro_job_finish() function at the error handling code
> +  * will internally call pm_runtime_put_autosuspend().
> +  */
>   ret = pm_runtime_get_sync(ctx->dev->dev);
>   if (ret < 0)
>   goto err_cancel_job;
> 
> 



Thanks,
Mauro
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 13/78] staging: media: hantro_drv: use pm_runtime_resume_and_get()

2021-04-26 Thread Mauro Carvalho Chehab
Em Sat, 24 Apr 2021 20:23:53 -0300
Ezequiel Garcia  escreveu:

> Hi Mauro,
> 
> On Sat, 2021-04-24 at 08:44 +0200, Mauro Carvalho Chehab wrote:
> > Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal 
> > with usage counter")
> > added pm_runtime_resume_and_get() in order to automatically handle
> > dev->power.usage_count decrement on errors.
> > 
> > Use the new API, in order to cleanup the error check logic.
> > 
> > Signed-off-by: Mauro Carvalho Chehab 
> > ---
> >  drivers/staging/media/hantro/hantro_drv.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/drivers/staging/media/hantro/hantro_drv.c 
> > b/drivers/staging/media/hantro/hantro_drv.c
> > index 595e82a82728..3147dcbebeb9 100644
> > --- a/drivers/staging/media/hantro/hantro_drv.c
> > +++ b/drivers/staging/media/hantro/hantro_drv.c
> > @@ -155,7 +155,7 @@ static void device_run(void *priv)
> > ret = clk_bulk_enable(ctx->dev->variant->num_clocks, 
> > ctx->dev->clocks);
> > if (ret)
> > goto err_cancel_job;
> > -   ret = pm_runtime_get_sync(ctx->dev->dev);
> > +   ret = pm_runtime_resume_and_get(ctx->dev->dev);
> > if (ret < 0)
> > goto err_cancel_job;
> >    
> 
> Seems this one needs a different fix: err_cancel_job
> will call hantro_job_finish which has a pm_runtime put.

Good point. Thanks for reviewing it!

It sounds that this is a place where the best seems
to keep using pm_runtime_get_sync(), but let's at least add a
comment explaining why it should be kept here. This should
help to avoid people to copy-and-paste the code on situations
where pm_runtime_resume_and_get() should be used instead.

See enclosed patch.

Thanks,
Mauro

[PATCH] media: hantro: document the usage of pm_runtime_get_sync()

Despite other *_get()/*_put() functions, where usage count is
incremented only if not errors, the pm_runtime_get_sync() has
a different behavior, incrementing the counter *even* on
errors.

That's an error prone behavior, as people often forget to
decrement the usage counter.

However, the hantro driver depends on this behavior, as it
will decrement the usage_count unconditionally at the m2m
job finish time, which makes sense.

So, intead of using the pm_runtime_resume_and_get() that
would decrement the counter on error, keep the current
API, but add a documentation explaining the rationale for
keep using pm_runtime_get_sync().

Signed-off-by: Mauro Carvalho Chehab 

diff --git a/drivers/staging/media/hantro/hantro_drv.c 
b/drivers/staging/media/hantro/hantro_drv.c
index 595e82a82728..96f940c1c85c 100644
--- a/drivers/staging/media/hantro/hantro_drv.c
+++ b/drivers/staging/media/hantro/hantro_drv.c
@@ -155,6 +155,13 @@ static void device_run(void *priv)
ret = clk_bulk_enable(ctx->dev->variant->num_clocks, ctx->dev->clocks);
if (ret)
goto err_cancel_job;
+
+   /*
+* The pm_runtime_get_sync() will increment dev->power.usage_count,
+* even on errors. That's the expected behavior here, since the
+* hantro_job_finish() function at the error handling code
+* will internally call pm_runtime_put_autosuspend().
+*/
ret = pm_runtime_get_sync(ctx->dev->dev);
if (ret < 0)
goto err_cancel_job;


___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 00/78] media: use pm_runtime_resume_and_get() instead of pm_runtime_get_sync()

2021-04-23 Thread Mauro Carvalho Chehab
During the review of the patches from unm.edu, one of the patterns
I noticed is the amount of patches trying to fix pm_runtime_get_sync()
calls.

On contrary of the common sense that a foo_get() function will
only increment the usage on success,  pm_runtime_get_sync()
increments it unconditionally.

Due to that, there are bugs on lots of places, that ended being
gradually fixed, but, still there are a few places on media where
this is still broken.

Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added a new method to does a pm_runtime get, which increments
the usage count only on success.

This series replace all places where the old  pm_runtime_get_sync()
is called, using  pm_runtime_resume_and_get() instead.

This should help to avoid future mistakes like that, as people
tend to use the existing drivers as examples for newer ones.

compile-tested only.

Mauro Carvalho Chehab (78):
  media: atmel: properly get pm_runtime
  media: marvel-ccic: fix some issues when getting pm_runtime
  media: mdk-mdp: fix pm_runtime_get_sync() usage count
  media: rcar_fdp1: fix  usage count
  media: mdk-mdp: fix pm_runtime_get_sync() usage count
  media: renesas-ceu: fix pm_runtime_get_sync() usage count
  media: s5p: fix pm_runtime_get_sync() usage count
  media: am437x:: fix pm_runtime_get_sync() usage count
  media: sh_vou: fix pm_runtime_get_sync() usage count
  media: sti/hva: use pm_runtime_resume_and_get()
  staging: media: rkvdec: fix pm_runtime_get_sync() usage count
  staging: media: atomisp_fops: use pm_runtime_resume_and_get()
  staging: media: hantro_drv: use pm_runtime_resume_and_get()
  staging: media: imx7-mipi-csis: use pm_runtime_resume_and_get()
  staging: media: ipu3: use pm_runtime_resume_and_get()
  staging: media: cedrus_video: use pm_runtime_resume_and_get()
  staging: media: vde: use pm_runtime_resume_and_get()
  staging: media: csi: use pm_runtime_resume_and_get()
  staging: media: vi: use pm_runtime_resume_and_get()
  media: mtk-vcodec: fix pm_runtime_get_sync() usage count
  media: s5p-jpeg: fix pm_runtime_get_sync() usage count
  media: delta-v4l2: fix pm_runtime_get_sync() usage count
  media: sun8i_rotate: fix pm_runtime_get_sync() usage count
  media: i2c: ak7375: use pm_runtime_resume_and_get()
  media: i2c: ccs-core: use pm_runtime_resume_and_get()
  media: i2c: dw9714: use pm_runtime_resume_and_get()
  media: i2c: dw9768: use pm_runtime_resume_and_get()
  media: i2c: dw9807-vcm: use pm_runtime_resume_and_get()
  media: i2c: hi556: use pm_runtime_resume_and_get()
  media: i2c: imx214: use pm_runtime_resume_and_get()
  media: i2c: imx219: use pm_runtime_resume_and_get()
  media: i2c: imx258: use pm_runtime_resume_and_get()
  media: i2c: imx274: use pm_runtime_resume_and_get()
  media: i2c: imx290: use pm_runtime_resume_and_get()
  media: i2c: imx319: use pm_runtime_resume_and_get()
  media: i2c: imx334: use pm_runtime_resume_and_get()
  media: i2c: imx355: use pm_runtime_resume_and_get()
  media: i2c: mt9m001: use pm_runtime_resume_and_get()
  media: i2c: ov02a10: use pm_runtime_resume_and_get()
  media: i2c: ov13858: use pm_runtime_resume_and_get()
  media: i2c: ov2659: use pm_runtime_resume_and_get()
  media: i2c: ov2685: use pm_runtime_resume_and_get()
  media: i2c: ov2740: use pm_runtime_resume_and_get()
  media: i2c: ov5647: use pm_runtime_resume_and_get()
  media: i2c: ov5648: use pm_runtime_resume_and_get()
  media: i2c: ov5670: use pm_runtime_resume_and_get()
  media: i2c: ov5675: use pm_runtime_resume_and_get()
  media: i2c: ov5695: use pm_runtime_resume_and_get()
  media: i2c: ov7740: use pm_runtime_resume_and_get()
  media: i2c: ov8856: use pm_runtime_resume_and_get()
  media: i2c: ov8865: use pm_runtime_resume_and_get()
  media: i2c: ov9734: use pm_runtime_resume_and_get()
  media: i2c: tvp5150: use pm_runtime_resume_and_get()
  media: i2c: video-i2c: use pm_runtime_resume_and_get()
  media: ipu3: use pm_runtime_resume_and_get()
  media: coda: use pm_runtime_resume_and_get()
  media: exynos4-is: use pm_runtime_resume_and_get()
  media: exynos-gsc: use pm_runtime_resume_and_get()
  media: mtk-jpeg: use pm_runtime_resume_and_get()
  media: camss-csid: use pm_runtime_resume_and_get()
  media: camss-csiphy: use pm_runtime_resume_and_get()
  media: camss-ispif: use pm_runtime_resume_and_get()
  media: camss-vfe: use pm_runtime_resume_and_get()
  media: core: use pm_runtime_resume_and_get()
  media: pm_helpers: use pm_runtime_resume_and_get()
  media: vdec: use pm_runtime_resume_and_get()
  media: venc: use pm_runtime_resume_and_get()
  media: rcar-fcp: use pm_runtime_resume_and_get()
  media: rcar-vin: use pm_runtime_resume_and_get()
  media: rga-buf: use pm_runtime_resume_and_get()
  media: rkisp1-capture: use pm_runtime_resume_and_get()
  media: s3c-camif: use pm_runtime_resume_and_get()
  media: s5p-mfc: use pm_runtime_resume_and_get()
  media: bdisp-v4l2: use pm_runtime_resume_and_get()
  media: stm32: use pm_runtime_resu

[PATCH 19/78] staging: media: vi: use pm_runtime_resume_and_get()

2021-04-23 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/tegra-video/vi.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/staging/media/tegra-video/vi.c 
b/drivers/staging/media/tegra-video/vi.c
index 7a09061cda57..1298740a9c6c 100644
--- a/drivers/staging/media/tegra-video/vi.c
+++ b/drivers/staging/media/tegra-video/vi.c
@@ -297,10 +297,9 @@ static int tegra_channel_start_streaming(struct vb2_queue 
*vq, u32 count)
struct tegra_vi_channel *chan = vb2_get_drv_priv(vq);
int ret;
 
-   ret = pm_runtime_get_sync(chan->vi->dev);
+   ret = pm_runtime_resume_and_get(chan->vi->dev);
if (ret < 0) {
dev_err(chan->vi->dev, "failed to get runtime PM: %d\n", ret);
-   pm_runtime_put_noidle(chan->vi->dev);
return ret;
}
 
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 18/78] staging: media: csi: use pm_runtime_resume_and_get()

2021-04-23 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/tegra-video/csi.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/staging/media/tegra-video/csi.c 
b/drivers/staging/media/tegra-video/csi.c
index 033a6935c26d..e938bf4c48b6 100644
--- a/drivers/staging/media/tegra-video/csi.c
+++ b/drivers/staging/media/tegra-video/csi.c
@@ -298,10 +298,9 @@ static int tegra_csi_enable_stream(struct v4l2_subdev 
*subdev)
struct tegra_csi *csi = csi_chan->csi;
int ret, err;
 
-   ret = pm_runtime_get_sync(csi->dev);
+   ret = pm_runtime_resume_and_get(csi->dev);
if (ret < 0) {
dev_err(csi->dev, "failed to get runtime PM: %d\n", ret);
-   pm_runtime_put_noidle(csi->dev);
return ret;
}
 
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 12/78] staging: media: atomisp_fops: use pm_runtime_resume_and_get()

2021-04-23 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/atomisp/pci/atomisp_fops.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c 
b/drivers/staging/media/atomisp/pci/atomisp_fops.c
index f1e6b2597853..26d05474a035 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_fops.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c
@@ -837,7 +837,7 @@ static int atomisp_open(struct file *file)
}
 
/* runtime power management, turn on ISP */
-   ret = pm_runtime_get_sync(vdev->v4l2_dev->dev);
+   ret = pm_runtime_resume_and_get(vdev->v4l2_dev->dev);
if (ret < 0) {
dev_err(isp->dev, "Failed to power on device\n");
goto error;
@@ -881,9 +881,9 @@ static int atomisp_open(struct file *file)
 
 css_error:
atomisp_css_uninit(isp);
-error:
-   hmm_pool_unregister(HMM_POOL_TYPE_DYNAMIC);
pm_runtime_put(vdev->v4l2_dev->dev);
+error:
+   hmm_pool_unregister(HMM_POOL_TYPE_DYNAMIC);
rt_mutex_unlock(&isp->mutex);
return ret;
 }
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 16/78] staging: media: cedrus_video: use pm_runtime_resume_and_get()

2021-04-23 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/sunxi/cedrus/cedrus_video.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c 
b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
index b62eb8e84057..9ddd789d0b1f 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
@@ -490,11 +490,9 @@ static int cedrus_start_streaming(struct vb2_queue *vq, 
unsigned int count)
}
 
if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
-   ret = pm_runtime_get_sync(dev->dev);
-   if (ret < 0) {
-   pm_runtime_put_noidle(dev->dev);
+   ret = pm_runtime_resume_and_get(dev->dev);
+   if (ret < 0)
goto err_cleanup;
-   }
 
if (dev->dec_ops[ctx->current_codec]->start) {
ret = dev->dec_ops[ctx->current_codec]->start(ctx);
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 17/78] staging: media: vde: use pm_runtime_resume_and_get()

2021-04-23 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/tegra-vde/vde.c | 16 ++--
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/staging/media/tegra-vde/vde.c 
b/drivers/staging/media/tegra-vde/vde.c
index 28845b5bafaf..8936f140a246 100644
--- a/drivers/staging/media/tegra-vde/vde.c
+++ b/drivers/staging/media/tegra-vde/vde.c
@@ -775,9 +775,9 @@ static int tegra_vde_ioctl_decode_h264(struct tegra_vde 
*vde,
if (ret)
goto release_dpb_frames;
 
-   ret = pm_runtime_get_sync(dev);
+   ret = pm_runtime_resume_and_get(dev);
if (ret < 0)
-   goto put_runtime_pm;
+   goto unlock;
 
/*
 * We rely on the VDE registers reset value, otherwise VDE
@@ -843,6 +843,8 @@ static int tegra_vde_ioctl_decode_h264(struct tegra_vde 
*vde,
 put_runtime_pm:
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
+
+unlock:
mutex_unlock(&vde->lock);
 
 release_dpb_frames:
@@ -1069,8 +1071,8 @@ static int tegra_vde_probe(struct platform_device *pdev)
 * power-cycle it in order to put hardware into a predictable lower
 * power state.
 */
-   pm_runtime_get_sync(dev);
-   pm_runtime_put(dev);
+   if (pm_runtime_resume_and_get(dev) >= 0)
+   pm_runtime_put(dev);
 
return 0;
 
@@ -1088,8 +1090,9 @@ static int tegra_vde_remove(struct platform_device *pdev)
 {
struct tegra_vde *vde = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
+   int ret;
 
-   pm_runtime_get_sync(dev);
+   ret = pm_runtime_resume_and_get(dev);
pm_runtime_dont_use_autosuspend(dev);
pm_runtime_disable(dev);
 
@@ -1097,7 +1100,8 @@ static int tegra_vde_remove(struct platform_device *pdev)
 * Balance RPM state, the VDE power domain is left ON and hardware
 * is clock-gated. It's safe to reboot machine now.
 */
-   pm_runtime_put_noidle(dev);
+   if (ret >= 0)
+   pm_runtime_put_noidle(dev);
clk_disable_unprepare(vde->clk);
 
misc_deregister(&vde->miscdev);
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 15/78] staging: media: ipu3: use pm_runtime_resume_and_get()

2021-04-23 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/ipu3/ipu3.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/staging/media/ipu3/ipu3.c 
b/drivers/staging/media/ipu3/ipu3.c
index ee1bba6bdcac..8e1e9e46e604 100644
--- a/drivers/staging/media/ipu3/ipu3.c
+++ b/drivers/staging/media/ipu3/ipu3.c
@@ -392,10 +392,9 @@ int imgu_s_stream(struct imgu_device *imgu, int enable)
}
 
/* Set Power */
-   r = pm_runtime_get_sync(dev);
+   r = pm_runtime_resume_and_get(dev);
if (r < 0) {
dev_err(dev, "failed to set imgu power\n");
-   pm_runtime_put(dev);
return r;
}
 
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 14/78] staging: media: imx7-mipi-csis: use pm_runtime_resume_and_get()

2021-04-23 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/imx/imx7-mipi-csis.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c 
b/drivers/staging/media/imx/imx7-mipi-csis.c
index 025fdc488bd6..1dc680d94a46 100644
--- a/drivers/staging/media/imx/imx7-mipi-csis.c
+++ b/drivers/staging/media/imx/imx7-mipi-csis.c
@@ -695,11 +695,10 @@ static int mipi_csis_s_stream(struct v4l2_subdev 
*mipi_sd, int enable)
 
mipi_csis_clear_counters(state);
 
-   ret = pm_runtime_get_sync(&state->pdev->dev);
-   if (ret < 0) {
-   pm_runtime_put_noidle(&state->pdev->dev);
+   ret = pm_runtime_resume_and_get(&state->pdev->dev);
+   if (ret < 0)
return ret;
-   }
+
ret = v4l2_subdev_call(state->src_sd, core, s_power, 1);
if (ret < 0 && ret != -ENOIOCTLCMD)
goto done;
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 13/78] staging: media: hantro_drv: use pm_runtime_resume_and_get()

2021-04-23 Thread Mauro Carvalho Chehab
Commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
added pm_runtime_resume_and_get() in order to automatically handle
dev->power.usage_count decrement on errors.

Use the new API, in order to cleanup the error check logic.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/hantro/hantro_drv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/media/hantro/hantro_drv.c 
b/drivers/staging/media/hantro/hantro_drv.c
index 595e82a82728..3147dcbebeb9 100644
--- a/drivers/staging/media/hantro/hantro_drv.c
+++ b/drivers/staging/media/hantro/hantro_drv.c
@@ -155,7 +155,7 @@ static void device_run(void *priv)
ret = clk_bulk_enable(ctx->dev->variant->num_clocks, ctx->dev->clocks);
if (ret)
goto err_cancel_job;
-   ret = pm_runtime_get_sync(ctx->dev->dev);
+   ret = pm_runtime_resume_and_get(ctx->dev->dev);
if (ret < 0)
goto err_cancel_job;
 
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 11/78] staging: media: rkvdec: fix pm_runtime_get_sync() usage count

2021-04-23 Thread Mauro Carvalho Chehab
The pm_runtime_get_sync() internally increments the
dev->power.usage_count without decrementing it, even on errors.
replace it by the new pm_runtime_resume_and_get(), introduced by:
commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with 
usage counter")
in order to properly decrement the usage counter and avoid memory
leaks.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/rkvdec/rkvdec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/media/rkvdec/rkvdec.c 
b/drivers/staging/media/rkvdec/rkvdec.c
index d821661d30f3..8c17615f3a7a 100644
--- a/drivers/staging/media/rkvdec/rkvdec.c
+++ b/drivers/staging/media/rkvdec/rkvdec.c
@@ -658,7 +658,7 @@ static void rkvdec_device_run(void *priv)
if (WARN_ON(!desc))
return;
 
-   ret = pm_runtime_get_sync(rkvdec->dev);
+   ret = pm_runtime_resume_and_get(rkvdec->dev);
if (ret < 0) {
rkvdec_job_finish_no_pm(ctx, VB2_BUF_STATE_ERROR);
return;
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH] media: atomisp: silence "dubious: !x | !y" warning

2021-04-17 Thread Mauro Carvalho Chehab
Em Sat, 17 Apr 2021 21:06:27 +0530
Ashish Kalra  escreveu:

> Upon running sparse, "warning: dubious: !x | !y" is brought to notice
> for this file.  Logical and bitwise OR are basically the same in this
> context so it doesn't cause a runtime bug.  But let's change it to
> logical OR to make it cleaner and silence the Sparse warning.
> 
> Signed-off-by: Ashish Kalra 
> ---
>  .../media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf.host.c| 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git 
> a/drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf.host.c 
> b/drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf.host.c
> index 358cb7d2cd4c..3b850bb2d39d 100644
> --- a/drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf.host.c
> +++ b/drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf.host.c
> @@ -58,7 +58,7 @@ sh_css_vf_downscale_log2(
>   unsigned int ds_log2 = 0;
>   unsigned int out_width;
>  
> - if ((!out_info) | (!vf_info))
> + if ((!out_info) || (!vf_info))


While here, please get rid of the unneeded parenthesis:

if (!out_info || !vf_info)


>   return -EINVAL;
>  
>   out_width = out_info->res.width;



Thanks,
Mauro
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH v4 17/21] spmi: hisi-spmi-controller: move driver from staging

2021-03-25 Thread Mauro Carvalho Chehab
Em Fri, 5 Feb 2021 16:19:47 -0600
Rob Herring  escreveu:

> On Tue, Jan 19, 2021 at 05:10:43PM +0100, Mauro Carvalho Chehab wrote:
> > The Hisilicon 6421v600 SPMI driver is ready for mainstream.
> > 
> > So, move it from staging.
> > 
> > Signed-off-by: Mauro Carvalho Chehab 
> > ---
> >  .../spmi/hisilicon,hisi-spmi-controller.yaml  |  75 
> >  MAINTAINERS   |   7 +
> >  drivers/spmi/Kconfig  |   9 +
> >  drivers/spmi/Makefile |   1 +
> >  drivers/spmi/hisi-spmi-controller.c   | 358 ++
> >  drivers/staging/hikey9xx/Kconfig  |  11 -
> >  drivers/staging/hikey9xx/Makefile |   1 -
> >  .../staging/hikey9xx/hisi-spmi-controller.c   | 358 --
> >  .../hisilicon,hisi-spmi-controller.yaml   |  75 
> >  9 files changed, 450 insertions(+), 445 deletions(-)
> >  create mode 100644 
> > Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
> >  create mode 100644 drivers/spmi/hisi-spmi-controller.c
> >  delete mode 100644 drivers/staging/hikey9xx/hisi-spmi-controller.c
> >  delete mode 100644 
> > drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml
> > 
> > diff --git 
> > a/Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
> >  
> > b/Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
> > new file mode 100644
> > index ..21f68a9c2df1
> > --- /dev/null
> > +++ 
> > b/Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
> > @@ -0,0 +1,75 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +%YAML 1.2
> > +---
> > +$id: 
> > http://devicetree.org/schemas/spmi/hisilicon,hisi-spmi-controller.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: HiSilicon SPMI controller
> > +
> > +maintainers:
> > +  - Mauro Carvalho Chehab 
> > +
> > +description: |
> > +  The HiSilicon SPMI BUS controller is found on some Kirin-based designs.
> > +  It is a MIPI System Power Management (SPMI) controller.
> > +
> > +  The PMIC part is provided by
> > +  drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml.
> > +
> > +properties:
> > +  $nodename:
> > +pattern: "spmi@[0-9a-f]"
> > +
> > +  compatible:
> > +const: hisilicon,kirin970-spmi-controller  
> 
> '-controller' is kind of redundant.

Ok. Will drop it.

> 
> > +
> > +  reg:
> > +maxItems: 1
> > +  
> 
> > +  "#address-cells":
> > +const: 2
> > +
> > +  "#size-cells":
> > +const: 0  
> 
> These 2 are covered by spmi.yaml

Ok.

> 
> > +
> > +  spmi-channel:
> > +description: |
> > +  number of the Kirin 970 SPMI channel where the SPMI devices are 
> > connected.  
> 
> Common to SPMI? If not, needs a vendor prefix.

That's an interesting question. My understanding is that this is not
vendor-specific, but maybe Stephen can give us more details.

The spmi.h header calls it "nr", and documents it at include/linux/spmi.h
as:

/**
 * struct spmi_controller - interface to the SPMI master controller
 * @dev:Driver model representation of the device.
 * @nr: board-specific number identifier for this controller/bus
 * @cmd:sends a non-data command sequence on the SPMI bus.
 * @read_cmd:   sends a register read command sequence on the SPMI bus.
 * @write_cmd:  sends a register write command sequence on the SPMI bus.
 */

There, it says that this is "board-specific number identifier".

Yet, as the SPMI is a serial bus with up to 4 masters (controller), I 
suspect that the idea is to associate it with the master ID.

This is used on boards with multiple SoCs. See, for instance, slide 5 of:


https://www.mipi.org/sites/default/files/Bangalore-Qualcomm-SPMI-1.0-Multi-master-Verification.pdf

However, it is hard to know for sure, as no drivers use it, except by
Hikey 970 controller:

$ grep "\b\->nr\b" $(git grep -l spmi.h)
drivers/spmi/spmi.c:ida_simple_remove(&ctrl_ida, ctrl->nr);
drivers/spmi/spmi.c:dev_set_name(&sdev->dev, "%d-%02x", ctrl->nr, 
sdev->usid);
drivers/spmi/spmi.c:ctrl->nr = id;
drivers/spmi/spmi.c:ctrl->nr, &ctrl->dev);
drivers/staging/hikey9xx/hisi-spmi-controller.c:ctrl->nr = 
spmi_controller->channel;

>

Re: [PATCH v2 12/12] media: atomisp: Fix LOGICAL_CONTINUATIONS

2021-03-23 Thread Mauro Carvalho Chehab
Em Mon, 14 Dec 2020 12:01:56 +0100
Philipp Gerlesberger  escreveu:

> Logical continuations should be on the previous line
> 
> Co-developed-by: Andrey Khlopkov 
> Signed-off-by: Andrey Khlopkov 
> Signed-off-by: Philipp Gerlesberger 
> ---
>  drivers/staging/media/atomisp/pci/runtime/queue/src/queue.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/staging/media/atomisp/pci/runtime/queue/src/queue.c 
> b/drivers/staging/media/atomisp/pci/runtime/queue/src/queue.c
> index 2f1c2df59f71..7d44070c7114 100644
> --- a/drivers/staging/media/atomisp/pci/runtime/queue/src/queue.c
> +++ b/drivers/staging/media/atomisp/pci/runtime/queue/src/queue.c
> @@ -24,8 +24,8 @@
>   
> */
>  int ia_css_queue_local_init(ia_css_queue_t *qhandle, ia_css_queue_local_t 
> *desc)
>  {
> - if (NULL == qhandle || NULL == desc
> - || NULL == desc->cb_elems || NULL == desc->cb_desc) {
> + if (NULL == qhandle || NULL == desc ||
> + NULL == desc->cb_elems || NULL == desc->cb_desc) {

Nah, there are coding style issues here... we usually do:

if (foo == CONSTANT)

instead of:

if (CONSTANT == foo)

Also, we usually simplify checks for null. So, the above should
be, instead, just:

if (!qhandle || !desc || !desc->cb_elements || !desc->cb_desc)


>   /* Invalid parameters, return error*/
>   return -EINVAL;
>   }



Thanks,
Mauro
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH v2 06/12] media: atomisp: Remove defines

2021-03-23 Thread Mauro Carvalho Chehab
Em Mon, 14 Dec 2020 12:01:50 +0100
Philipp Gerlesberger  escreveu:

> Remov defines, they don't make sense.
> The programmer should know what things need to be static and what not.
> Also leave "inline" out and let the compiler decide
> 
> Co-developed-by: Andrey Khlopkov 
> Signed-off-by: Andrey Khlopkov 
> Signed-off-by: Philipp Gerlesberger 
> ---
>  .../media/atomisp/pci/runtime/rmgr/interface/ia_css_rmgr.h   | 5 +
>  1 file changed, 1 insertion(+), 4 deletions(-)
> 
> diff --git 
> a/drivers/staging/media/atomisp/pci/runtime/rmgr/interface/ia_css_rmgr.h 
> b/drivers/staging/media/atomisp/pci/runtime/rmgr/interface/ia_css_rmgr.h
> index 9cd3d92b34c9..45b72e98bc9f 100644
> --- a/drivers/staging/media/atomisp/pci/runtime/rmgr/interface/ia_css_rmgr.h
> +++ b/drivers/staging/media/atomisp/pci/runtime/rmgr/interface/ia_css_rmgr.h
> @@ -21,10 +21,7 @@
>  #ifndef __INLINE_RMGR__
>  #define STORAGE_CLASS_RMGR_H extern
>  #define STORAGE_CLASS_RMGR_C
> -#else/* __INLINE_RMGR__ */
> -#define STORAGE_CLASS_RMGR_H static inline
> -#define STORAGE_CLASS_RMGR_C static inline
> -#endif   /* __INLINE_RMGR__ */
> +#endif


No, that's not the right way to address it. Instead, you should
replace the occurrences of those macros at the code and get rid
of them.


Thanks,
Mauro
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH] atomisp: remove a now unused var

2021-03-22 Thread Mauro Carvalho Chehab
A previous cleanup patch removed the usage of the ret var.

So, drop it.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/atomisp/i2c/atomisp-lm3554.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c 
b/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c
index ebe3c618051f..e444c0129f5d 100644
--- a/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c
+++ b/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c
@@ -904,7 +904,6 @@ static int lm3554_remove(struct i2c_client *client)
 {
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct lm3554 *flash = to_lm3554(sd);
-   int ret;
 
media_entity_cleanup(&flash->sd.entity);
v4l2_ctrl_handler_free(&flash->ctrl_handler);
-- 
2.30.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v8 00/14] Move Hisilicon 6421v600 SPMI and USB drivers out of staging

2021-01-29 Thread Mauro Carvalho Chehab
Hi Greg/Mark/Lee/Vinod,

Another rebase , also the top of staging-testing.

This series contain the remaining patches for USB to start working,
except for a final DTS patch.

Patches 1 and 2 convert the SPMI and regulator
drivers to use regmap and simplifies the logic by using
regmap helpers.

Patches 3 to 9 address some issues pointed by Lee at the MFD driver.

I guess the best would be if Greg could apply patches 1 to 9
via the staging tree.

Patches 10 to 13 move the drivers and their corresponding
DT documentation bindings out of staging.

Patch 14 contains the DT which describes the regulator,
SPMI controller and MFD.

I'll submit the final patch with USB bindings after having
everything set (e.g. after 5.12-rc1).

-

v8: contains a fix for REGMAP dependencies and for a build breakage.

Mauro Carvalho Chehab (14):
  staging: hikey9xx: spmi driver: convert to regmap
  staging: hikey9xx: hi6421v600-regulator: use some regmap helpers
  staging: hikey9xx: hi6421-spmi-pmic: rename some vars
  staging: hikey9xx: hi6421-spmi-pmic: cleanup probe code
  staging: hikey9xx: hi6421-spmi-pmic: cleanup header file
  staging: hikey9xx: hi6421-spmi-pmic: fix IRQ handler code
  staging: hikey9xx: hi6421-spmi-pmic: cleanup IRQ handling code
  staging: hikey9xx: hi6421-spmi-pmic: document registers
  staging: hikey9xx: hi6421-spmi-pmic: update copyright notes
  phy: phy-hi3670-usb3: move driver from staging into phy
  spmi: hisi-spmi-controller: move driver from staging
  mfd: hi6421-spmi-pmic: move driver from staging
  regulator: hi6421v600-regulator: move it from staging
  dts: hisilicon: add support for the PMIC found on Hikey 970

 .../mfd}/hisilicon,hi6421-spmi-pmic.yaml  |   0
 .../bindings/phy/hisilicon,hi3670-usb3.yaml   |   0
 .../spmi}/hisilicon,hisi-spmi-controller.yaml |   0
 MAINTAINERS   |  24 +-
 .../boot/dts/hisilicon/hi3670-hikey970.dts|  22 +-
 .../boot/dts/hisilicon/hikey970-pmic.dtsi |  87 +
 drivers/mfd/Kconfig   |  16 +
 drivers/mfd/Makefile  |   1 +
 drivers/mfd/hi6421-spmi-pmic.c| 297 
 drivers/phy/hisilicon/Kconfig |  10 +
 drivers/phy/hisilicon/Makefile|   1 +
 .../hisilicon}/phy-hi3670-usb3.c  |   0
 drivers/regulator/Kconfig |   9 +
 drivers/regulator/Makefile|   1 +
 .../hi6421v600-regulator.c|  63 +---
 drivers/spmi/Kconfig  |   9 +
 drivers/spmi/Makefile |   1 +
 .../hikey9xx => spmi}/hisi-spmi-controller.c  |   0
 drivers/staging/Kconfig   |   2 -
 drivers/staging/Makefile  |   1 -
 drivers/staging/hikey9xx/Kconfig  |  50 ---
 drivers/staging/hikey9xx/Makefile |   7 -
 drivers/staging/hikey9xx/TODO |   5 -
 drivers/staging/hikey9xx/hi6421-spmi-pmic.c   | 326 --
 include/linux/mfd/hi6421-spmi-pmic.h  |  28 +-
 25 files changed, 471 insertions(+), 489 deletions(-)
 rename {drivers/staging/hikey9xx => 
Documentation/devicetree/bindings/mfd}/hisilicon,hi6421-spmi-pmic.yaml (100%)
 rename drivers/staging/hikey9xx/phy-hi3670-usb3.yaml => 
Documentation/devicetree/bindings/phy/hisilicon,hi3670-usb3.yaml (100%)
 rename {drivers/staging/hikey9xx => 
Documentation/devicetree/bindings/spmi}/hisilicon,hisi-spmi-controller.yaml 
(100%)
 create mode 100644 arch/arm64/boot/dts/hisilicon/hikey970-pmic.dtsi
 create mode 100644 drivers/mfd/hi6421-spmi-pmic.c
 rename drivers/{staging/hikey9xx => phy/hisilicon}/phy-hi3670-usb3.c (100%)
 rename drivers/{staging/hikey9xx => regulator}/hi6421v600-regulator.c (81%)
 rename drivers/{staging/hikey9xx => spmi}/hisi-spmi-controller.c (100%)
 delete mode 100644 drivers/staging/hikey9xx/Kconfig
 delete mode 100644 drivers/staging/hikey9xx/Makefile
 delete mode 100644 drivers/staging/hikey9xx/TODO
 delete mode 100644 drivers/staging/hikey9xx/hi6421-spmi-pmic.c

-- 
2.29.2


___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v8 02/14] staging: hikey9xx: hi6421v600-regulator: use some regmap helpers

2021-01-29 Thread Mauro Carvalho Chehab
Now that the driver was ported to use regmap, let's use
some help functions in order to simplify the code a little
bit.

Suggested-by: Mark Brown 
Signed-off-by: Mauro Carvalho Chehab 
---
 .../staging/hikey9xx/hi6421v600-regulator.c   | 45 ++-
 1 file changed, 3 insertions(+), 42 deletions(-)

diff --git a/drivers/staging/hikey9xx/hi6421v600-regulator.c 
b/drivers/staging/hikey9xx/hi6421v600-regulator.c
index 9e319fa11137..7090107b9ec2 100644
--- a/drivers/staging/hikey9xx/hi6421v600-regulator.c
+++ b/drivers/staging/hikey9xx/hi6421v600-regulator.c
@@ -95,17 +95,6 @@ static const unsigned int ldo34_voltages[] = {
.eco_uA = ecoamp,  \
}
 
-static int hi6421_spmi_regulator_is_enabled(struct regulator_dev *rdev)
-{
-   struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
-   struct hi6421_spmi_pmic *pmic = sreg->pmic;
-   u32 reg_val;
-
-   regmap_read(pmic->map, rdev->desc->enable_reg, ®_val);
-
-   return ((reg_val & rdev->desc->enable_mask) != 0);
-}
-
 static int hi6421_spmi_regulator_enable(struct regulator_dev *rdev)
 {
struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
@@ -136,34 +125,6 @@ static int hi6421_spmi_regulator_disable(struct 
regulator_dev *rdev)
  rdev->desc->enable_mask, 0);
 }
 
-static int hi6421_spmi_regulator_get_voltage_sel(struct regulator_dev *rdev)
-{
-   struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
-   struct hi6421_spmi_pmic *pmic = sreg->pmic;
-   u32 reg_val;
-
-   regmap_read(pmic->map, rdev->desc->vsel_reg, ®_val);
-
-   return (reg_val & rdev->desc->vsel_mask) >> (ffs(rdev->desc->vsel_mask) 
- 1);
-}
-
-static int hi6421_spmi_regulator_set_voltage_sel(struct regulator_dev *rdev,
-unsigned int selector)
-{
-   struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
-   struct hi6421_spmi_pmic *pmic = sreg->pmic;
-   u32 reg_val;
-
-   if (selector >= rdev->desc->n_voltages)
-   return -EINVAL;
-
-   reg_val = selector << (ffs(rdev->desc->vsel_mask) - 1);
-
-   /* set voltage selector */
-   return regmap_update_bits(pmic->map, rdev->desc->vsel_reg,
- rdev->desc->vsel_mask, reg_val);
-}
-
 static unsigned int hi6421_spmi_regulator_get_mode(struct regulator_dev *rdev)
 {
struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
@@ -214,13 +175,13 @@ hi6421_spmi_regulator_get_optimum_mode(struct 
regulator_dev *rdev,
 }
 
 static const struct regulator_ops hi6421_spmi_ldo_rops = {
-   .is_enabled = hi6421_spmi_regulator_is_enabled,
+   .is_enabled = regulator_is_enabled_regmap,
.enable = hi6421_spmi_regulator_enable,
.disable = hi6421_spmi_regulator_disable,
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_iterate,
-   .get_voltage_sel = hi6421_spmi_regulator_get_voltage_sel,
-   .set_voltage_sel = hi6421_spmi_regulator_set_voltage_sel,
+   .get_voltage_sel = regulator_get_voltage_sel_regmap,
+   .set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_mode = hi6421_spmi_regulator_get_mode,
.set_mode = hi6421_spmi_regulator_set_mode,
.get_optimum_mode = hi6421_spmi_regulator_get_optimum_mode,
-- 
2.29.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v8 12/14] mfd: hi6421-spmi-pmic: move driver from staging

2021-01-29 Thread Mauro Carvalho Chehab
This driver is ready for mainstream. So, move it out of staging.

Signed-off-by: Mauro Carvalho Chehab 
---
 .../mfd}/hisilicon,hi6421-spmi-pmic.yaml   |  0
 MAINTAINERS|  7 +++
 drivers/mfd/Kconfig| 16 
 drivers/mfd/Makefile   |  1 +
 .../hikey9xx => mfd}/hi6421-spmi-pmic.c|  0
 drivers/staging/hikey9xx/Kconfig   | 18 --
 drivers/staging/hikey9xx/Makefile  |  1 -
 7 files changed, 24 insertions(+), 19 deletions(-)
 rename {drivers/staging/hikey9xx => 
Documentation/devicetree/bindings/mfd}/hisilicon,hi6421-spmi-pmic.yaml (100%)
 rename drivers/{staging/hikey9xx => mfd}/hi6421-spmi-pmic.c (100%)

diff --git a/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml 
b/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
similarity index 100%
rename from drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
rename to Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
diff --git a/MAINTAINERS b/MAINTAINERS
index 406c2340f221..241f11b7d48a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8085,6 +8085,13 @@ S:   Maintained
 F: 
Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
 F: drivers/spmi/hisi-spmi-controller.c
 
+HISILICON SPMI PMIC DRIVER FOR HIKEY 6421v600
+M:     Mauro Carvalho Chehab 
+L: linux-ker...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
+F: drivers/mfd/hi6421-spmi-pmic.c
+
 HISILICON STAGING DRIVERS FOR HIKEY 960/970
 M:     Mauro Carvalho Chehab 
 L: de...@driverdev.osuosl.org
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index bdfce7b15621..1ad04fb6eefa 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -509,6 +509,22 @@ config MFD_HI6421_PMIC
  menus in order to enable them.
  We communicate with the Hi6421 via memory-mapped I/O.
 
+config MFD_HI6421_SPMI
+   tristate "HiSilicon Hi6421v600 SPMI PMU/Codec IC"
+   depends on OF
+   depends on SPMI
+   select MFD_CORE
+   select REGMAP_SPMI
+   help
+ Add support for HiSilicon Hi6421v600 SPMI PMIC. Hi6421 includes
+ multi-functions, such as regulators, RTC, codec, Coulomb counter,
+ etc.
+
+ This driver includes core APIs _only_. You have to select
+ individual components like voltage regulators under corresponding
+ menus in order to enable them.
+ We communicate with the Hi6421v600 via a SPMI bus.
+
 config MFD_HI655X_PMIC
tristate "HiSilicon Hi655X series PMU/Codec IC"
depends on ARCH_HISI || COMPILE_TEST
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 14fdb188af02..b64e89ade44b 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -234,6 +234,7 @@ obj-$(CONFIG_MFD_IPAQ_MICRO)+= ipaq-micro.o
 obj-$(CONFIG_MFD_IQS62X)   += iqs62x.o
 obj-$(CONFIG_MFD_MENF21BMC)+= menf21bmc.o
 obj-$(CONFIG_MFD_HI6421_PMIC)  += hi6421-pmic-core.o
+obj-$(CONFIG_MFD_HI6421_SPMI)  += hi6421-spmi-pmic.o
 obj-$(CONFIG_MFD_HI655X_PMIC)   += hi655x-pmic.o
 obj-$(CONFIG_MFD_DLN2) += dln2.o
 obj-$(CONFIG_MFD_RT5033)   += rt5033.o
diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c 
b/drivers/mfd/hi6421-spmi-pmic.c
similarity index 100%
rename from drivers/staging/hikey9xx/hi6421-spmi-pmic.c
rename to drivers/mfd/hi6421-spmi-pmic.c
diff --git a/drivers/staging/hikey9xx/Kconfig b/drivers/staging/hikey9xx/Kconfig
index 49ce28ff55b2..b17c047aa700 100644
--- a/drivers/staging/hikey9xx/Kconfig
+++ b/drivers/staging/hikey9xx/Kconfig
@@ -1,23 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
 
-# to be placed at drivers/mfd
-config MFD_HI6421_SPMI
-   tristate "HiSilicon Hi6421v600 SPMI PMU/Codec IC"
-   depends on HAS_IOMEM
-   depends on OF
-   depends on SPMI
-   select MFD_CORE
-   select REGMAP_SPMI
-   help
- Add support for HiSilicon Hi6421v600 SPMI PMIC. Hi6421 includes
- multi-functions, such as regulators, RTC, codec, Coulomb counter,
- etc.
-
- This driver includes core APIs _only_. You have to select
- individual components like voltage regulators under corresponding
- menus in order to enable them.
- We communicate with the Hi6421v600 via a SPMI bus.
-
 # to be placed at drivers/regulator
 config REGULATOR_HI6421V600
tristate "HiSilicon Hi6421v600 PMIC voltage regulator support"
diff --git a/drivers/staging/hikey9xx/Makefile 
b/drivers/staging/hikey9xx/Makefile
index 347880fd378f..4d63184e6086 100644
--- a/drivers/staging/hikey9xx/Makefile
+++ b/drivers/staging/hikey9xx/Makefile
@@ -1,4 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0
 
-obj-$(CONFIG_MFD_HI6421_SPMI)  += hi6421-spmi-pmic.o
 obj-$(CONFIG_REGULATOR_HI6

[PATCH v8 10/14] phy: phy-hi3670-usb3: move driver from staging into phy

2021-01-29 Thread Mauro Carvalho Chehab
The phy USB3 driver for Hisilicon 970 (hi3670) is ready
for mainstream. Mode it from staging into the main driver's
phy/ directory.

Signed-off-by: Mauro Carvalho Chehab 
---
 .../bindings/phy/hisilicon,hi3670-usb3.yaml   |  0
 MAINTAINERS   |  9 -
 drivers/phy/hisilicon/Kconfig | 10 ++
 drivers/phy/hisilicon/Makefile|  1 +
 .../hikey9xx => phy/hisilicon}/phy-hi3670-usb3.c  |  0
 drivers/staging/hikey9xx/Kconfig  | 11 ---
 drivers/staging/hikey9xx/Makefile |  2 --
 7 files changed, 19 insertions(+), 14 deletions(-)
 rename drivers/staging/hikey9xx/phy-hi3670-usb3.yaml => 
Documentation/devicetree/bindings/phy/hisilicon,hi3670-usb3.yaml (100%)
 rename drivers/{staging/hikey9xx => phy/hisilicon}/phy-hi3670-usb3.c (100%)

diff --git a/drivers/staging/hikey9xx/phy-hi3670-usb3.yaml 
b/Documentation/devicetree/bindings/phy/hisilicon,hi3670-usb3.yaml
similarity index 100%
rename from drivers/staging/hikey9xx/phy-hi3670-usb3.yaml
rename to Documentation/devicetree/bindings/phy/hisilicon,hi3670-usb3.yaml
diff --git a/MAINTAINERS b/MAINTAINERS
index 992fe3b0900a..fb49e654a1db 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -18371,7 +18371,7 @@ L:  linux-...@vger.kernel.org
 S: Maintained
 F: drivers/usb/roles/intel-xhci-usb-role-switch.c
 
-USB IP DRIVER FOR HISILICON KIRIN
+USB IP DRIVER FOR HISILICON KIRIN 960
 M: Yu Chen 
 M: Binghui Wang 
 L: linux-...@vger.kernel.org
@@ -18379,6 +18379,13 @@ S: Maintained
 F: Documentation/devicetree/bindings/phy/hisilicon,hi3660-usb3.yaml
 F: drivers/phy/hisilicon/phy-hi3660-usb3.c
 
+USB IP DRIVER FOR HISILICON KIRIN 970
+M: Mauro Carvalho Chehab 
+L: linux-...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/phy/hisilicon,kirin970-usb3.yaml
+F: drivers/phy/hisilicon/phy-kirin970-usb3.c
+
 USB ISP116X DRIVER
 M: Olav Kongas 
 L: linux-...@vger.kernel.org
diff --git a/drivers/phy/hisilicon/Kconfig b/drivers/phy/hisilicon/Kconfig
index 1c73053bcc98..4d008cfc279c 100644
--- a/drivers/phy/hisilicon/Kconfig
+++ b/drivers/phy/hisilicon/Kconfig
@@ -23,6 +23,16 @@ config PHY_HI3660_USB
 
  To compile this driver as a module, choose M here.
 
+config PHY_HI3670_USB
+   tristate "hi3670 USB PHY support"
+   depends on (ARCH_HISI && ARM64) || COMPILE_TEST
+   select GENERIC_PHY
+   select MFD_SYSCON
+   help
+ Enable this to support the HISILICON HI3670 USB PHY.
+
+ To compile this driver as a module, choose M here.
+
 config PHY_HISTB_COMBPHY
tristate "HiSilicon STB SoCs COMBPHY support"
depends on (ARCH_HISI && ARM64) || COMPILE_TEST
diff --git a/drivers/phy/hisilicon/Makefile b/drivers/phy/hisilicon/Makefile
index 92e874ae9c74..51729868145b 100644
--- a/drivers/phy/hisilicon/Makefile
+++ b/drivers/phy/hisilicon/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_PHY_HI6220_USB)   += phy-hi6220-usb.o
 obj-$(CONFIG_PHY_HI3660_USB)   += phy-hi3660-usb3.o
+obj-$(CONFIG_PHY_HI3670_USB)   += phy-hi3670-usb3.o
 obj-$(CONFIG_PHY_HISTB_COMBPHY)+= phy-histb-combphy.o
 obj-$(CONFIG_PHY_HISI_INNO_USB2)   += phy-hisi-inno-usb2.o
 obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o
diff --git a/drivers/staging/hikey9xx/phy-hi3670-usb3.c 
b/drivers/phy/hisilicon/phy-hi3670-usb3.c
similarity index 100%
rename from drivers/staging/hikey9xx/phy-hi3670-usb3.c
rename to drivers/phy/hisilicon/phy-hi3670-usb3.c
diff --git a/drivers/staging/hikey9xx/Kconfig b/drivers/staging/hikey9xx/Kconfig
index 82bb4a22b286..88bdf5655d20 100644
--- a/drivers/staging/hikey9xx/Kconfig
+++ b/drivers/staging/hikey9xx/Kconfig
@@ -1,16 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
 
-# to be placed at drivers/phy
-config PHY_HI3670_USB
-   tristate "hi3670 USB PHY support"
-   depends on (ARCH_HISI && ARM64) || COMPILE_TEST
-   select GENERIC_PHY
-   select MFD_SYSCON
-   help
- Enable this to support the HISILICON HI3670 USB PHY.
-
- To compile this driver as a module, choose M here.
-
 # to be placed at drivers/spmi
 config SPMI_HISI3670
tristate "Hisilicon 3670 SPMI Controller"
diff --git a/drivers/staging/hikey9xx/Makefile 
b/drivers/staging/hikey9xx/Makefile
index 1924fadac952..9371dcc3d35b 100644
--- a/drivers/staging/hikey9xx/Makefile
+++ b/drivers/staging/hikey9xx/Makefile
@@ -1,7 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
 
-obj-$(CONFIG_PHY_HI3670_USB)   += phy-hi3670-usb3.o
-
 obj-$(CONFIG_SPMI_HISI3670)+= hisi-spmi-controller.o
 obj-$(CONFIG_MFD_HI6421_SPMI)  += hi6421-spmi-pmic.o
 obj-$(CONFIG_REGULATOR_HI6421V600) += hi6421v600-regulator.o
-- 
2.29.2

__

[PATCH v8 11/14] spmi: hisi-spmi-controller: move driver from staging

2021-01-29 Thread Mauro Carvalho Chehab
The Hisilicon 6421v600 SPMI driver is ready for mainstream.

So, move it from staging.

Signed-off-by: Mauro Carvalho Chehab 
---
 .../spmi}/hisilicon,hisi-spmi-controller.yaml |  0
 MAINTAINERS   |  7 +++
 drivers/spmi/Kconfig  |  9 +
 drivers/spmi/Makefile |  1 +
 .../{staging/hikey9xx => spmi}/hisi-spmi-controller.c |  0
 drivers/staging/hikey9xx/Kconfig  | 11 ---
 drivers/staging/hikey9xx/Makefile |  1 -
 7 files changed, 17 insertions(+), 12 deletions(-)
 rename {drivers/staging/hikey9xx => 
Documentation/devicetree/bindings/spmi}/hisilicon,hisi-spmi-controller.yaml 
(100%)
 rename drivers/{staging/hikey9xx => spmi}/hisi-spmi-controller.c (100%)

diff --git a/drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml 
b/Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
similarity index 100%
rename from drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml
rename to 
Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
diff --git a/MAINTAINERS b/MAINTAINERS
index fb49e654a1db..406c2340f221 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8078,6 +8078,13 @@ F:   drivers/crypto/hisilicon/sec2/sec_crypto.c
 F: drivers/crypto/hisilicon/sec2/sec_crypto.h
 F: drivers/crypto/hisilicon/sec2/sec_main.c
 
+HISILICON SPMI CONTROLLER DRIVER FOR HIKEY 970
+M:     Mauro Carvalho Chehab 
+L: linux-ker...@vger.kernel.org
+S: Maintained
+F: 
Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
+F: drivers/spmi/hisi-spmi-controller.c
+
 HISILICON STAGING DRIVERS FOR HIKEY 960/970
 M:     Mauro Carvalho Chehab 
 L: de...@driverdev.osuosl.org
diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
index a53bad541f1a..2874b6c26028 100644
--- a/drivers/spmi/Kconfig
+++ b/drivers/spmi/Kconfig
@@ -11,6 +11,15 @@ menuconfig SPMI
 
 if SPMI
 
+config SPMI_HISI3670
+   tristate "Hisilicon 3670 SPMI Controller"
+   select IRQ_DOMAIN_HIERARCHY
+   depends on HAS_IOMEM
+   help
+ If you say yes to this option, support will be included for the
+ built-in SPMI PMIC Arbiter interface on Hisilicon 3670
+ processors.
+
 config SPMI_MSM_PMIC_ARB
tristate "Qualcomm MSM SPMI Controller (PMIC Arbiter)"
select IRQ_DOMAIN_HIERARCHY
diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile
index 55a94cadeffe..6e092e6f290c 100644
--- a/drivers/spmi/Makefile
+++ b/drivers/spmi/Makefile
@@ -4,4 +4,5 @@
 #
 obj-$(CONFIG_SPMI) += spmi.o
 
+obj-$(CONFIG_SPMI_HISI3670)+= hisi-spmi-controller.o
 obj-$(CONFIG_SPMI_MSM_PMIC_ARB)+= spmi-pmic-arb.o
diff --git a/drivers/staging/hikey9xx/hisi-spmi-controller.c 
b/drivers/spmi/hisi-spmi-controller.c
similarity index 100%
rename from drivers/staging/hikey9xx/hisi-spmi-controller.c
rename to drivers/spmi/hisi-spmi-controller.c
diff --git a/drivers/staging/hikey9xx/Kconfig b/drivers/staging/hikey9xx/Kconfig
index 88bdf5655d20..49ce28ff55b2 100644
--- a/drivers/staging/hikey9xx/Kconfig
+++ b/drivers/staging/hikey9xx/Kconfig
@@ -1,16 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
 
-# to be placed at drivers/spmi
-config SPMI_HISI3670
-   tristate "Hisilicon 3670 SPMI Controller"
-   select IRQ_DOMAIN_HIERARCHY
-   depends on HAS_IOMEM
-   depends on SPMI
-   help
- If you say yes to this option, support will be included for the
- built-in SPMI PMIC Arbiter interface on Hisilicon 3670
- processors.
-
 # to be placed at drivers/mfd
 config MFD_HI6421_SPMI
tristate "HiSilicon Hi6421v600 SPMI PMU/Codec IC"
diff --git a/drivers/staging/hikey9xx/Makefile 
b/drivers/staging/hikey9xx/Makefile
index 9371dcc3d35b..347880fd378f 100644
--- a/drivers/staging/hikey9xx/Makefile
+++ b/drivers/staging/hikey9xx/Makefile
@@ -1,5 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
 
-obj-$(CONFIG_SPMI_HISI3670)+= hisi-spmi-controller.o
 obj-$(CONFIG_MFD_HI6421_SPMI)  += hi6421-spmi-pmic.o
 obj-$(CONFIG_REGULATOR_HI6421V600) += hi6421v600-regulator.o
-- 
2.29.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v8 13/14] regulator: hi6421v600-regulator: move it from staging

2021-01-29 Thread Mauro Carvalho Chehab
This driver is ready for mainstream. Move it out of staging.

Signed-off-by: Mauro Carvalho Chehab 
---
 MAINTAINERS  |  7 +--
 drivers/regulator/Kconfig|  9 +
 drivers/regulator/Makefile   |  1 +
 .../hikey9xx => regulator}/hi6421v600-regulator.c|  0
 drivers/staging/Kconfig  |  2 --
 drivers/staging/Makefile |  1 -
 drivers/staging/hikey9xx/Kconfig | 12 
 drivers/staging/hikey9xx/Makefile|  3 ---
 drivers/staging/hikey9xx/TODO|  5 -
 9 files changed, 11 insertions(+), 29 deletions(-)
 rename drivers/{staging/hikey9xx => regulator}/hi6421v600-regulator.c (100%)
 delete mode 100644 drivers/staging/hikey9xx/Kconfig
 delete mode 100644 drivers/staging/hikey9xx/Makefile
 delete mode 100644 drivers/staging/hikey9xx/TODO

diff --git a/MAINTAINERS b/MAINTAINERS
index 241f11b7d48a..5c5ad946c5d5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8091,12 +8091,7 @@ L:   linux-ker...@vger.kernel.org
 S: Maintained
 F: Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
 F: drivers/mfd/hi6421-spmi-pmic.c
-
-HISILICON STAGING DRIVERS FOR HIKEY 960/970
-M: Mauro Carvalho Chehab 
-L: de...@driverdev.osuosl.org
-S: Maintained
-F: drivers/staging/hikey9xx/
+F: drivers/regulator/hi6421v600-regulator.c
 
 HISILICON TRUE RANDOM NUMBER GENERATOR V2 SUPPORT
 M: Zaibo Xu 
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 5abdd29fb9f3..a520c313a00d 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -423,6 +423,15 @@ config REGULATOR_HI655X
  This driver provides support for the voltage regulators of the
  Hisilicon Hi655x PMIC device.
 
+config REGULATOR_HI6421V600
+   tristate "HiSilicon Hi6421v600 PMIC voltage regulator support"
+   depends on MFD_HI6421_SPMI && OF
+   select REGMAP
+   help
+ This driver provides support for the voltage regulators on
+ HiSilicon Hi6421v600 PMU / Codec IC.
+ This is used on Kirin 3670 boards, like HiKey 970.
+
 config REGULATOR_ISL9305
tristate "Intersil ISL9305 regulator"
depends on I2C
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 680e539f6579..77e519d2bc68 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_REGULATOR_FAN53880) += fan53880.o
 obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
 obj-$(CONFIG_REGULATOR_HI6421) += hi6421-regulator.o
 obj-$(CONFIG_REGULATOR_HI6421V530) += hi6421v530-regulator.o
+obj-$(CONFIG_REGULATOR_HI6421V600) += hi6421v600-regulator.o
 obj-$(CONFIG_REGULATOR_HI655X) += hi655x-regulator.o
 obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
 obj-$(CONFIG_REGULATOR_ISL9305) += isl9305.o
diff --git a/drivers/staging/hikey9xx/hi6421v600-regulator.c 
b/drivers/regulator/hi6421v600-regulator.c
similarity index 100%
rename from drivers/staging/hikey9xx/hi6421v600-regulator.c
rename to drivers/regulator/hi6421v600-regulator.c
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index b22f73d7bfc4..db7ec218644f 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -112,6 +112,4 @@ source "drivers/staging/wimax/Kconfig"
 
 source "drivers/staging/wfx/Kconfig"
 
-source "drivers/staging/hikey9xx/Kconfig"
-
 endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 2245059e69c7..7b0ef538dcce 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -46,4 +46,3 @@ obj-$(CONFIG_KPC2000) += kpc2000/
 obj-$(CONFIG_QLGE) += qlge/
 obj-$(CONFIG_WIMAX)+= wimax/
 obj-$(CONFIG_WFX)  += wfx/
-obj-y  += hikey9xx/
diff --git a/drivers/staging/hikey9xx/Kconfig b/drivers/staging/hikey9xx/Kconfig
deleted file mode 100644
index b17c047aa700..
--- a/drivers/staging/hikey9xx/Kconfig
+++ /dev/null
@@ -1,12 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-# to be placed at drivers/regulator
-config REGULATOR_HI6421V600
-   tristate "HiSilicon Hi6421v600 PMIC voltage regulator support"
-   depends on MFD_HI6421_SPMI && OF
-   depends on REGULATOR
-   select REGMAP
-   help
- This driver provides support for the voltage regulators on
- HiSilicon Hi6421v600 PMU / Codec IC.
- This is used on Kirin 3670 boards, like HiKey 970.
diff --git a/drivers/staging/hikey9xx/Makefile 
b/drivers/staging/hikey9xx/Makefile
deleted file mode 100644
index 4d63184e6086..
--- a/drivers/staging/hikey9xx/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-obj-$(CONFIG_REGULATOR_HI6421V600) += hi6421v600-regu

[PATCH v8 06/14] staging: hikey9xx: hi6421-spmi-pmic: fix IRQ handler code

2021-01-29 Thread Mauro Carvalho Chehab
The conversion to regmap introduced a regression at the code
which reads from the IRQ register. Address that.

Fixes: 8148fe6afb24 ("staging: hikey9xx: spmi driver: convert to regmap")
Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c 
b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
index 909f7b106af4..48e4f92f7d1e 100644
--- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
+++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
@@ -66,7 +66,7 @@ static irqreturn_t hi6421_spmi_irq_handler(int irq, void 
*priv)
int i, offset;
 
for (i = 0; i < HISI_IRQ_ARRAY; i++) {
-   regmap_read(ddata->regmap, offset, &data);
+   regmap_read(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, &data);
data &= HISI_MASK_FIELD;
if (data != 0)
pr_debug("data[%d]=0x%d\n\r", i, data);
-- 
2.29.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v8 04/14] staging: hikey9xx: hi6421-spmi-pmic: cleanup probe code

2021-01-29 Thread Mauro Carvalho Chehab
Cleanup the error handling code, making the messages more
consistent and removing an uneeded call to free_irq().

While here, also remove debug messages and make the
error messages more consistent.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 50 +++--
 1 file changed, 16 insertions(+), 34 deletions(-)

diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c 
b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
index a4ffeb06ed6a..c8e55b7b08e2 100644
--- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
+++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
@@ -154,7 +154,7 @@ static void hi6421_spmi_pmic_irq_prc(struct 
hi6421_spmi_pmic *ddata)
}
 }
 
-static const struct regmap_config spmi_regmap_config = {
+static const struct regmap_config regmap_config = {
.reg_bits   = 16,
.val_bits   = 8,
.max_register   = 0x,
@@ -166,7 +166,6 @@ static int hi6421_spmi_pmic_probe(struct spmi_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct hi6421_spmi_pmic *ddata;
-   struct regmap *map;
unsigned int virq;
int ret, i;
 
@@ -174,14 +173,13 @@ static int hi6421_spmi_pmic_probe(struct spmi_device 
*pdev)
if (!ddata)
return -ENOMEM;
 
-   map = devm_regmap_init_spmi_ext(pdev, &spmi_regmap_config);
-   if (IS_ERR(map))
-   return PTR_ERR(map);
+   ddata->regmap = devm_regmap_init_spmi_ext(pdev, ®map_config);
+   if (IS_ERR(ddata->regmap))
+   return PTR_ERR(ddata->regmap);
 
spin_lock_init(&ddata->lock);
 
ddata->dev = dev;
-   ddata->regmap = map;
 
ddata->gpio = of_get_gpio(np, 0);
if (ddata->gpio < 0)
@@ -192,7 +190,7 @@ static int hi6421_spmi_pmic_probe(struct spmi_device *pdev)
 
ret = devm_gpio_request_one(dev, ddata->gpio, GPIOF_IN, "pmic");
if (ret < 0) {
-   dev_err(dev, "failed to request gpio%d\n", ddata->gpio);
+   dev_err(dev, "Failed to request gpio%d\n", ddata->gpio);
return ret;
}
 
@@ -201,57 +199,41 @@ static int hi6421_spmi_pmic_probe(struct spmi_device 
*pdev)
hi6421_spmi_pmic_irq_prc(ddata);
 
ddata->irqs = devm_kzalloc(dev, HISI_IRQ_NUM * sizeof(int), GFP_KERNEL);
-   if (!ddata->irqs) {
-   ret = -ENOMEM;
-   goto irq_malloc;
-   }
+   if (!ddata->irqs)
+   return -ENOMEM;
 
ddata->domain = irq_domain_add_simple(np, HISI_IRQ_NUM, 0,
 &hi6421_spmi_domain_ops, ddata);
if (!ddata->domain) {
-   dev_err(dev, "failed irq domain add simple!\n");
-   ret = -ENODEV;
-   goto irq_malloc;
+   dev_err(dev, "Failed to create IRQ domain\n");
+   return -ENODEV;
}
 
for (i = 0; i < HISI_IRQ_NUM; i++) {
virq = irq_create_mapping(ddata->domain, i);
if (!virq) {
-   dev_err(dev, "Failed mapping hwirq\n");
-   ret = -ENOSPC;
-   goto irq_malloc;
+   dev_err(dev, "Failed to map H/W IRQ\n");
+   return -ENOSPC;
}
ddata->irqs[i] = virq;
-   dev_dbg(dev, "%s: ddata->irqs[%d] = %d\n",
-   __func__, i, ddata->irqs[i]);
}
 
ret = request_threaded_irq(ddata->irq, hi6421_spmi_irq_handler, NULL,
   IRQF_TRIGGER_LOW | IRQF_SHARED | 
IRQF_NO_SUSPEND,
   "pmic", ddata);
if (ret < 0) {
-   dev_err(dev, "could not claim pmic IRQ: error %d\n", ret);
-   goto irq_malloc;
+   dev_err(dev, "Failed to start IRQ handling thread: error %d\n",
+   ret);
+   return ret;
}
 
dev_set_drvdata(&pdev->dev, ddata);
 
-   /*
-* The logic below will rely that the ddata is already stored at
-* drvdata.
-*/
-   dev_dbg(&pdev->dev, "SPMI-PMIC: adding children for %pOF\n",
-   pdev->dev.of_node);
ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
   hi6421v600_devs, ARRAY_SIZE(hi6421v600_devs),
   NULL, 0, NULL);
-   if (!ret)
-   return 0;
-
-   dev_err(dev, "Failed to add child devices: %d\n", ret);
-
-irq_malloc:
-   free_irq(ddata->irq, ddata);
+   if (ret < 0)
+   dev_err(dev, "Failed to add child devices: %d\n", ret);
 
return ret;
 }
-- 
2.29.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v8 03/14] staging: hikey9xx: hi6421-spmi-pmic: rename some vars

2021-01-29 Thread Mauro Carvalho Chehab
- When referring to regmap, rename map to regmap
- inside hi6421-spmi-pmic, call private data struct as
  ddata.

No functional changes.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/hikey9xx/hi6421-spmi-pmic.c   | 104 +-
 .../staging/hikey9xx/hi6421v600-regulator.c   |  10 +-
 include/linux/mfd/hi6421-spmi-pmic.h  |   2 +-
 3 files changed, 58 insertions(+), 58 deletions(-)

diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c 
b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
index 3d612bd46231..a4ffeb06ed6a 100644
--- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
+++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
@@ -43,17 +43,17 @@ static const struct mfd_cell hi6421v600_devs[] = {
 
 static irqreturn_t hi6421_spmi_irq_handler(int irq, void *priv)
 {
-   struct hi6421_spmi_pmic *pmic = (struct hi6421_spmi_pmic *)priv;
+   struct hi6421_spmi_pmic *ddata = (struct hi6421_spmi_pmic *)priv;
unsigned long pending;
unsigned int data;
int i, offset;
 
for (i = 0; i < HISI_IRQ_ARRAY; i++) {
-   regmap_read(pmic->map, offset, &data);
+   regmap_read(ddata->regmap, offset, &data);
data &= HISI_MASK_FIELD;
if (data != 0)
pr_debug("data[%d]=0x%d\n\r", i, data);
-   regmap_write(pmic->map, i + SOC_PMIC_IRQ0_ADDR, data);
+   regmap_write(ddata->regmap, i + SOC_PMIC_IRQ0_ADDR, data);
 
/* for_each_set_bit() macro requires unsigned long */
pending = data;
@@ -61,14 +61,14 @@ static irqreturn_t hi6421_spmi_irq_handler(int irq, void 
*priv)
/* solve powerkey order */
if ((i == HISI_IRQ_KEY_NUM) &&
((pending & HISI_IRQ_KEY_VALUE) == HISI_IRQ_KEY_VALUE)) {
-   generic_handle_irq(pmic->irqs[HISI_IRQ_KEY_DOWN]);
-   generic_handle_irq(pmic->irqs[HISI_IRQ_KEY_UP]);
+   generic_handle_irq(ddata->irqs[HISI_IRQ_KEY_DOWN]);
+   generic_handle_irq(ddata->irqs[HISI_IRQ_KEY_UP]);
pending &= (~HISI_IRQ_KEY_VALUE);
}
 
if (pending) {
for_each_set_bit(offset, &pending, HISI_BITS)
-   generic_handle_irq(pmic->irqs[offset + i * 
HISI_BITS]);
+   generic_handle_irq(ddata->irqs[offset + i * 
HISI_BITS]);
}
}
 
@@ -77,7 +77,7 @@ static irqreturn_t hi6421_spmi_irq_handler(int irq, void 
*priv)
 
 static void hi6421_spmi_irq_mask(struct irq_data *d)
 {
-   struct hi6421_spmi_pmic *pmic = irq_data_get_irq_chip_data(d);
+   struct hi6421_spmi_pmic *ddata = irq_data_get_irq_chip_data(d);
unsigned long flags;
unsigned int data;
u32 offset;
@@ -85,28 +85,28 @@ static void hi6421_spmi_irq_mask(struct irq_data *d)
offset = (irqd_to_hwirq(d) >> 3);
offset += SOC_PMIC_IRQ_MASK_0_ADDR;
 
-   spin_lock_irqsave(&pmic->lock, flags);
+   spin_lock_irqsave(&ddata->lock, flags);
 
-   regmap_read(pmic->map, offset, &data);
+   regmap_read(ddata->regmap, offset, &data);
data |= (1 << (irqd_to_hwirq(d) & 0x07));
-   regmap_write(pmic->map, offset, data);
-   spin_unlock_irqrestore(&pmic->lock, flags);
+   regmap_write(ddata->regmap, offset, data);
+   spin_unlock_irqrestore(&ddata->lock, flags);
 }
 
 static void hi6421_spmi_irq_unmask(struct irq_data *d)
 {
-   struct hi6421_spmi_pmic *pmic = irq_data_get_irq_chip_data(d);
+   struct hi6421_spmi_pmic *ddata = irq_data_get_irq_chip_data(d);
u32 data, offset;
unsigned long flags;
 
offset = (irqd_to_hwirq(d) >> 3);
offset += SOC_PMIC_IRQ_MASK_0_ADDR;
 
-   spin_lock_irqsave(&pmic->lock, flags);
-   regmap_read(pmic->map, offset, &data);
+   spin_lock_irqsave(&ddata->lock, flags);
+   regmap_read(ddata->regmap, offset, &data);
data &= ~(1 << (irqd_to_hwirq(d) & 0x07));
-   regmap_write(pmic->map, offset, data);
-   spin_unlock_irqrestore(&pmic->lock, flags);
+   regmap_write(ddata->regmap, offset, data);
+   spin_unlock_irqrestore(&ddata->lock, flags);
 }
 
 static struct irq_chip hi6421_spmi_pmu_irqchip = {
@@ -120,11 +120,11 @@ static struct irq_chip hi6421_spmi_pmu_irqchip = {
 static int hi6421_spmi_irq_map(struct irq_domain *d, unsigned int virq,
   irq_hw_number_t hw)
 {
-   struct hi6421_spmi_pmic *pmic = d->host_data;
+   struct hi6421_spmi_pmic *ddata = d->host_data;
 
irq_set_chip_and_handler_name(virq, &hi6421_spmi_pmu_irqchip,
  handle_simple

[PATCH v8 09/14] staging: hikey9xx: hi6421-spmi-pmic: update copyright notes

2021-01-29 Thread Mauro Carvalho Chehab
At PMIC subsystem, C89 comments are preferred over C99.
While here, also update the copyrights of the header file.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 14 +++---
 include/linux/mfd/hi6421-spmi-pmic.h|  1 +
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c 
b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
index 9c10f7c4e7c9..2301f4fcd48d 100644
--- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
+++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
@@ -1,11 +1,11 @@
 // SPDX-License-Identifier: GPL-2.0
-//
-// Device driver for regulators in HISI PMIC IC
-//
-// Copyright (c) 2013 Linaro Ltd.
-// Copyright (c) 2011 Hisilicon.
-//
-// Copyright (c) 2020-2021 Huawei Technologies Co., Ltd
+/*
+ * Device driver for regulators in HISI PMIC IC
+ *
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2011 Hisilicon.
+ * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd
+ */
 
 #include 
 #include 
diff --git a/include/linux/mfd/hi6421-spmi-pmic.h 
b/include/linux/mfd/hi6421-spmi-pmic.h
index 4d61cb266a18..2660226138b8 100644
--- a/include/linux/mfd/hi6421-spmi-pmic.h
+++ b/include/linux/mfd/hi6421-spmi-pmic.h
@@ -4,6 +4,7 @@
  *
  * Copyright (c) 2013 Linaro Ltd.
  * Copyright (C) 2011 Hisilicon.
+ * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd
  *
  * Guodong Xu 
  */
-- 
2.29.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v8 05/14] staging: hikey9xx: hi6421-spmi-pmic: cleanup header file

2021-01-29 Thread Mauro Carvalho Chehab
Remove the IRQ list from the header, as this is used only
inside the driver itself. Also, get rid of two unused
defines.

The net result is that only struct hi6421_spmi_pmic remains
on it, as this is used by the regulator driver.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 17 +
 include/linux/mfd/hi6421-spmi-pmic.h| 20 
 2 files changed, 17 insertions(+), 20 deletions(-)

diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c 
b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
index c8e55b7b08e2..909f7b106af4 100644
--- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
+++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
@@ -17,6 +17,23 @@
 #include 
 #include 
 
+enum hi6421_spmi_pmic_irq_list {
+   OTMP = 0,
+   VBUS_CONNECT,
+   VBUS_DISCONNECT,
+   ALARMON_R,
+   HOLD_6S,
+   HOLD_1S,
+   POWERKEY_UP,
+   POWERKEY_DOWN,
+   OCP_SCP_R,
+   COUL_R,
+   SIM0_HPD_R,
+   SIM0_HPD_F,
+   SIM1_HPD_R,
+   SIM1_HPD_F,
+   PMIC_IRQ_LIST_MAX,
+};
 /* 8-bit register offset in PMIC */
 #define HISI_MASK_STATE0xff
 
diff --git a/include/linux/mfd/hi6421-spmi-pmic.h 
b/include/linux/mfd/hi6421-spmi-pmic.h
index aa8d5382f559..4d61cb266a18 100644
--- a/include/linux/mfd/hi6421-spmi-pmic.h
+++ b/include/linux/mfd/hi6421-spmi-pmic.h
@@ -14,9 +14,6 @@
 #include 
 #include 
 
-#define HISI_ECO_MODE_ENABLE   (1)
-#define HISI_ECO_MODE_DISABLE  (0)
-
 struct hi6421_spmi_pmic {
struct resource *res;
struct device   *dev;
@@ -29,21 +26,4 @@ struct hi6421_spmi_pmic {
struct regmap   *regmap;
 };
 
-enum hi6421_spmi_pmic_irq_list {
-   OTMP = 0,
-   VBUS_CONNECT,
-   VBUS_DISCONNECT,
-   ALARMON_R,
-   HOLD_6S,
-   HOLD_1S,
-   POWERKEY_UP,
-   POWERKEY_DOWN,
-   OCP_SCP_R,
-   COUL_R,
-   SIM0_HPD_R,
-   SIM0_HPD_F,
-   SIM1_HPD_R,
-   SIM1_HPD_F,
-   PMIC_IRQ_LIST_MAX,
-};
 #endif /* __HISI_PMIC_H */
-- 
2.29.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v8 07/14] staging: hikey9xx: hi6421-spmi-pmic: cleanup IRQ handling code

2021-01-29 Thread Mauro Carvalho Chehab
- Use BIT() and GENMASK();
- Remove duplicated mask definitions;
- Simplify the code under IRQ handler;
- Add a few extra blank lines to make easier to see
  spin_lock/spin_unlock;
- Remove debug code;
- Fix a few minor coding style issues.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 66 +
 1 file changed, 28 insertions(+), 38 deletions(-)

diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c 
b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
index 48e4f92f7d1e..f2af1760add9 100644
--- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
+++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
@@ -7,6 +7,7 @@
 //
 // Copyright (c) 2020-2021 Huawei Technologies Co., Ltd
 
+#include 
 #include 
 #include 
 #include 
@@ -34,25 +35,19 @@ enum hi6421_spmi_pmic_irq_list {
SIM1_HPD_F,
PMIC_IRQ_LIST_MAX,
 };
-/* 8-bit register offset in PMIC */
-#define HISI_MASK_STATE0xff
 
 #define HISI_IRQ_ARRAY 2
 #define HISI_IRQ_NUM   (HISI_IRQ_ARRAY * 8)
+#define HISI_IRQ_MASK  GENMASK(1, 0)
 
 #define SOC_PMIC_IRQ_MASK_0_ADDR   0x0202
 #define SOC_PMIC_IRQ0_ADDR 0x0212
 
 #define HISI_IRQ_KEY_NUM   0
-#define HISI_IRQ_KEY_VALUE 0xc0
-#define HISI_IRQ_KEY_DOWN  7
-#define HISI_IRQ_KEY_UP6
 
-#define HISI_MASK_FIELD0xFF
 #define HISI_BITS  8
-
-/*define the first group interrupt register number*/
-#define HISI_PMIC_FIRST_GROUP_INT_NUM  2
+#define HISI_IRQ_KEY_VALUE (BIT(POWERKEY_DOWN) | BIT(POWERKEY_UP))
+#define HISI_MASK  GENMASK(HISI_BITS - 1, 0)
 
 static const struct mfd_cell hi6421v600_devs[] = {
{ .name = "hi6421v600-regulator", },
@@ -62,31 +57,26 @@ static irqreturn_t hi6421_spmi_irq_handler(int irq, void 
*priv)
 {
struct hi6421_spmi_pmic *ddata = (struct hi6421_spmi_pmic *)priv;
unsigned long pending;
-   unsigned int data;
+   unsigned int in;
int i, offset;
 
for (i = 0; i < HISI_IRQ_ARRAY; i++) {
-   regmap_read(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, &data);
-   data &= HISI_MASK_FIELD;
-   if (data != 0)
-   pr_debug("data[%d]=0x%d\n\r", i, data);
-   regmap_write(ddata->regmap, i + SOC_PMIC_IRQ0_ADDR, data);
+   regmap_read(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, &in);
+   pending = HISI_MASK & in;
+   regmap_write(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, pending);
 
-   /* for_each_set_bit() macro requires unsigned long */
-   pending = data;
-
-   /* solve powerkey order */
-   if ((i == HISI_IRQ_KEY_NUM) &&
-   ((pending & HISI_IRQ_KEY_VALUE) == HISI_IRQ_KEY_VALUE)) {
-   generic_handle_irq(ddata->irqs[HISI_IRQ_KEY_DOWN]);
-   generic_handle_irq(ddata->irqs[HISI_IRQ_KEY_UP]);
+   if (i == HISI_IRQ_KEY_NUM &&
+   (pending & HISI_IRQ_KEY_VALUE) == HISI_IRQ_KEY_VALUE) {
+   generic_handle_irq(ddata->irqs[POWERKEY_DOWN]);
+   generic_handle_irq(ddata->irqs[POWERKEY_UP]);
pending &= (~HISI_IRQ_KEY_VALUE);
}
 
-   if (pending) {
-   for_each_set_bit(offset, &pending, HISI_BITS)
-   generic_handle_irq(ddata->irqs[offset + i * 
HISI_BITS]);
-   }
+   if (!pending)
+   continue;
+
+   for_each_set_bit(offset, &pending, HISI_BITS)
+   generic_handle_irq(ddata->irqs[offset + i * HISI_BITS]);
}
 
return IRQ_HANDLED;
@@ -99,7 +89,7 @@ static void hi6421_spmi_irq_mask(struct irq_data *d)
unsigned int data;
u32 offset;
 
-   offset = (irqd_to_hwirq(d) >> 3);
+   offset = (irqd_to_hwirq(d) >> HISI_IRQ_MASK);
offset += SOC_PMIC_IRQ_MASK_0_ADDR;
 
spin_lock_irqsave(&ddata->lock, flags);
@@ -107,6 +97,7 @@ static void hi6421_spmi_irq_mask(struct irq_data *d)
regmap_read(ddata->regmap, offset, &data);
data |= (1 << (irqd_to_hwirq(d) & 0x07));
regmap_write(ddata->regmap, offset, data);
+
spin_unlock_irqrestore(&ddata->lock, flags);
 }
 
@@ -120,9 +111,11 @@ static void hi6421_spmi_irq_unmask(struct irq_data *d)
offset += SOC_PMIC_IRQ_MASK_0_ADDR;
 
spin_lock_irqsave(&ddata->lock, flags);
+
regmap_read(ddata->regmap, offset, &data);
data &= ~(1 << (irqd_to_hwirq(d) & 0x07));
regmap_write(ddata->regmap, offset, data);
+
spin_unlock_irq

[PATCH v8 08/14] staging: hikey9xx: hi6421-spmi-pmic: document registers

2021-01-29 Thread Mauro Carvalho Chehab
Make it clearer about how the IRQ registers are filled by adding
a table with them, with two macros used to calculate the mask
register.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 39 +
 1 file changed, 32 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c 
b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
index f2af1760add9..9c10f7c4e7c9 100644
--- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
+++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
@@ -38,10 +38,6 @@ enum hi6421_spmi_pmic_irq_list {
 
 #define HISI_IRQ_ARRAY 2
 #define HISI_IRQ_NUM   (HISI_IRQ_ARRAY * 8)
-#define HISI_IRQ_MASK  GENMASK(1, 0)
-
-#define SOC_PMIC_IRQ_MASK_0_ADDR   0x0202
-#define SOC_PMIC_IRQ0_ADDR 0x0212
 
 #define HISI_IRQ_KEY_NUM   0
 
@@ -49,6 +45,36 @@ enum hi6421_spmi_pmic_irq_list {
 #define HISI_IRQ_KEY_VALUE (BIT(POWERKEY_DOWN) | BIT(POWERKEY_UP))
 #define HISI_MASK  GENMASK(HISI_BITS - 1, 0)
 
+/*
+ * The IRQs are mapped as:
+ *
+ * ==  =   =
+ * IRQ MASK REGISTER   IRQ REGISTERBIT
+ * ==  =   =
+ * OTMP0x0202  0x212   bit 0
+ * VBUS_CONNECT0x0202  0x212   bit 1
+ * VBUS_DISCONNECT 0x0202  0x212   bit 2
+ * ALARMON_R   0x0202  0x212   bit 3
+ * HOLD_6S 0x0202  0x212   bit 4
+ * HOLD_1S 0x0202  0x212   bit 5
+ * POWERKEY_UP 0x0202  0x212   bit 6
+ * POWERKEY_DOWN   0x0202  0x212   bit 7
+ *
+ * OCP_SCP_R   0x0203  0x213   bit 0
+ * COUL_R  0x0203  0x213   bit 1
+ * SIM0_HPD_R  0x0203  0x213   bit 2
+ * SIM0_HPD_F  0x0203  0x213   bit 3
+ * SIM1_HPD_R  0x0203  0x213   bit 4
+ * SIM1_HPD_F  0x0203  0x213   bit 5
+ * ==  =   =
+ */
+#define SOC_PMIC_IRQ_MASK_0_ADDR   0x0202
+#define SOC_PMIC_IRQ0_ADDR 0x0212
+
+#define IRQ_MASK_REGISTER(irq_data)(SOC_PMIC_IRQ_MASK_0_ADDR + \
+(irqd_to_hwirq(irq_data) >> 3))
+#define IRQ_MASK_BIT(irq_data) BIT(irqd_to_hwirq(irq_data) & 0x07)
+
 static const struct mfd_cell hi6421v600_devs[] = {
{ .name = "hi6421v600-regulator", },
 };
@@ -89,13 +115,12 @@ static void hi6421_spmi_irq_mask(struct irq_data *d)
unsigned int data;
u32 offset;
 
-   offset = (irqd_to_hwirq(d) >> HISI_IRQ_MASK);
-   offset += SOC_PMIC_IRQ_MASK_0_ADDR;
+   offset = IRQ_MASK_REGISTER(d);
 
spin_lock_irqsave(&ddata->lock, flags);
 
regmap_read(ddata->regmap, offset, &data);
-   data |= (1 << (irqd_to_hwirq(d) & 0x07));
+   data |= IRQ_MASK_BIT(d);
regmap_write(ddata->regmap, offset, data);
 
spin_unlock_irqrestore(&ddata->lock, flags);
-- 
2.29.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v8 01/14] staging: hikey9xx: spmi driver: convert to regmap

2021-01-29 Thread Mauro Carvalho Chehab
Instead of doing its own SPMI I/O implementation, use the
already-existing regmap one.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/hikey9xx/Kconfig  |   2 +
 drivers/staging/hikey9xx/hi6421-spmi-pmic.c   | 115 ++
 .../staging/hikey9xx/hi6421v600-regulator.c   |  26 ++--
 include/linux/mfd/hi6421-spmi-pmic.h  |   7 +-
 4 files changed, 54 insertions(+), 96 deletions(-)

diff --git a/drivers/staging/hikey9xx/Kconfig b/drivers/staging/hikey9xx/Kconfig
index 2e48ded92a7e..82bb4a22b286 100644
--- a/drivers/staging/hikey9xx/Kconfig
+++ b/drivers/staging/hikey9xx/Kconfig
@@ -29,6 +29,7 @@ config MFD_HI6421_SPMI
depends on OF
depends on SPMI
select MFD_CORE
+   select REGMAP_SPMI
help
  Add support for HiSilicon Hi6421v600 SPMI PMIC. Hi6421 includes
  multi-functions, such as regulators, RTC, codec, Coulomb counter,
@@ -44,6 +45,7 @@ config REGULATOR_HI6421V600
tristate "HiSilicon Hi6421v600 PMIC voltage regulator support"
depends on MFD_HI6421_SPMI && OF
depends on REGULATOR
+   select REGMAP
help
  This driver provides support for the voltage regulators on
  HiSilicon Hi6421v600 PMU / Codec IC.
diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c 
b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
index 69570876f93e..3d612bd46231 100644
--- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
+++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
@@ -41,81 +41,22 @@ static const struct mfd_cell hi6421v600_devs[] = {
{ .name = "hi6421v600-regulator", },
 };
 
-/*
- * The PMIC register is only 8-bit.
- * Hisilicon SoC use hardware to map PMIC register into SoC mapping.
- * At here, we are accessing SoC register with 32-bit.
- */
-int hi6421_spmi_pmic_read(struct hi6421_spmi_pmic *pmic, int reg)
+static irqreturn_t hi6421_spmi_irq_handler(int irq, void *priv)
 {
-   struct spmi_device *pdev;
-   u8 read_value = 0;
-   u32 ret;
-
-   pdev = to_spmi_device(pmic->dev);
-   if (!pdev) {
-   pr_err("%s: pdev get failed!\n", __func__);
-   return -ENODEV;
-   }
-
-   ret = spmi_ext_register_readl(pdev, reg, &read_value, 1);
-   if (ret) {
-   pr_err("%s: spmi_ext_register_readl failed!\n", __func__);
-   return ret;
-   }
-   return read_value;
-}
-EXPORT_SYMBOL(hi6421_spmi_pmic_read);
-
-int hi6421_spmi_pmic_write(struct hi6421_spmi_pmic *pmic, int reg, u32 val)
-{
-   struct spmi_device *pdev;
-   u32 ret;
-
-   pdev = to_spmi_device(pmic->dev);
-   if (!pdev) {
-   pr_err("%s: pdev get failed!\n", __func__);
-   return -ENODEV;
-   }
-
-   ret = spmi_ext_register_writel(pdev, reg, (unsigned char *)&val, 1);
-   if (ret)
-   pr_err("%s: spmi_ext_register_writel failed!\n", __func__);
-
-   return ret;
-}
-EXPORT_SYMBOL(hi6421_spmi_pmic_write);
-
-int hi6421_spmi_pmic_rmw(struct hi6421_spmi_pmic *pmic, int reg,
-u32 mask, u32 bits)
-{
-   unsigned long flags;
-   u32 data;
-   int ret;
-
-   spin_lock_irqsave(&pmic->lock, flags);
-   data = hi6421_spmi_pmic_read(pmic, reg) & ~mask;
-   data |= mask & bits;
-   ret = hi6421_spmi_pmic_write(pmic, reg, data);
-   spin_unlock_irqrestore(&pmic->lock, flags);
-
-   return ret;
-}
-EXPORT_SYMBOL(hi6421_spmi_pmic_rmw);
-
-static irqreturn_t hi6421_spmi_irq_handler(int irq, void *data)
-{
-   struct hi6421_spmi_pmic *pmic = (struct hi6421_spmi_pmic *)data;
+   struct hi6421_spmi_pmic *pmic = (struct hi6421_spmi_pmic *)priv;
unsigned long pending;
+   unsigned int data;
int i, offset;
 
for (i = 0; i < HISI_IRQ_ARRAY; i++) {
-   pending = hi6421_spmi_pmic_read(pmic, (i + SOC_PMIC_IRQ0_ADDR));
-   pending &= HISI_MASK_FIELD;
-   if (pending != 0)
-   pr_debug("pending[%d]=0x%lx\n\r", i, pending);
+   regmap_read(pmic->map, offset, &data);
+   data &= HISI_MASK_FIELD;
+   if (data != 0)
+   pr_debug("data[%d]=0x%d\n\r", i, data);
+   regmap_write(pmic->map, i + SOC_PMIC_IRQ0_ADDR, data);
 
-   hi6421_spmi_pmic_write(pmic, (i + SOC_PMIC_IRQ0_ADDR), pending);
+   /* for_each_set_bit() macro requires unsigned long */
+   pending = data;
 
/* solve powerkey order */
if ((i == HISI_IRQ_KEY_NUM) &&
@@ -137,16 +78,18 @@ static irqreturn_t hi6421_spmi_irq_handler(int irq, void 
*data)
 static void hi6421_spmi_irq_mask(struct irq_data *d)
 {
struct hi6421_spmi_pmic *pmic = irq_data_get_irq_chip_data(d);
-   u32 data, offset;
u

Re: [PATCH v7 01/14] staging: hikey9xx: spmi driver: convert to regmap

2021-01-29 Thread Mauro Carvalho Chehab
Em Fri, 29 Jan 2021 16:45:11 +0100
Greg Kroah-Hartman  escreveu:

> On Fri, Jan 29, 2021 at 04:03:36PM +0100, Mauro Carvalho Chehab wrote:
> > Instead of doing its own SPMI I/O implementation, use the
> > already-existing regmap one.
> > 
> > Signed-off-by: Mauro Carvalho Chehab 
> > ---
> >  drivers/staging/hikey9xx/hi6421-spmi-pmic.c   | 115 ++
> >  .../staging/hikey9xx/hi6421v600-regulator.c   |  26 ++--
> >  include/linux/mfd/hi6421-spmi-pmic.h  |   7 +-
> >  3 files changed, 52 insertions(+), 96 deletions(-)  
> 
> After applying this, I get a build failure:
> 
> ERROR: modpost: "__devm_regmap_init_spmi_ext" 
> [drivers/staging/hikey9xx/hi6421-spmi-pmic.ko] undefined!
> 
> So you need some sort of build dependancy here :(

It seems that it is missing REGMAP_SPMI.

> Also, when I apply the first 9 patches and stop, I get a build error
> that you should see as well, so I can't take any of these right now,
> sorry.

Gah, there was a rename patch which a hunk that went into the
following patch. Sorry. 

Added the missing select REGMAP_SPMI / REGMAP, fixed it and
tested, patch-per-patch.

I'll run a new test at the hardware to double-check if everything is
OK at the hardware and should be re-submitting the series soon enough.

Thanks,
Mauro
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v7 11/14] spmi: hisi-spmi-controller: move driver from staging

2021-01-29 Thread Mauro Carvalho Chehab
The Hisilicon 6421v600 SPMI driver is ready for mainstream.

So, move it from staging.

Signed-off-by: Mauro Carvalho Chehab 
---
 .../spmi/hisilicon,hisi-spmi-controller.yaml  |  75 
 MAINTAINERS   |   7 +
 drivers/spmi/Kconfig  |   9 +
 drivers/spmi/Makefile |   1 +
 drivers/spmi/hisi-spmi-controller.c   | 367 ++
 drivers/staging/hikey9xx/Kconfig  |  11 -
 drivers/staging/hikey9xx/Makefile |   1 -
 .../staging/hikey9xx/hisi-spmi-controller.c   | 367 --
 .../hisilicon,hisi-spmi-controller.yaml   |  75 
 9 files changed, 459 insertions(+), 454 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
 create mode 100644 drivers/spmi/hisi-spmi-controller.c
 delete mode 100644 drivers/staging/hikey9xx/hisi-spmi-controller.c
 delete mode 100644 drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml

diff --git 
a/Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml 
b/Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
new file mode 100644
index ..21f68a9c2df1
--- /dev/null
+++ b/Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
@@ -0,0 +1,75 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spmi/hisilicon,hisi-spmi-controller.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: HiSilicon SPMI controller
+
+maintainers:
+  - Mauro Carvalho Chehab 
+
+description: |
+  The HiSilicon SPMI BUS controller is found on some Kirin-based designs.
+  It is a MIPI System Power Management (SPMI) controller.
+
+  The PMIC part is provided by
+  drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml.
+
+properties:
+  $nodename:
+pattern: "spmi@[0-9a-f]"
+
+  compatible:
+const: hisilicon,kirin970-spmi-controller
+
+  reg:
+maxItems: 1
+
+  "#address-cells":
+const: 2
+
+  "#size-cells":
+const: 0
+
+  spmi-channel:
+description: |
+  number of the Kirin 970 SPMI channel where the SPMI devices are 
connected.
+
+required:
+  - compatible
+  - reg
+  - spmi-channel
+  - "#address-cells"
+  - "#size-cells"
+
+patternProperties:
+  "^pmic@[0-9a-f]$":
+description: |
+  PMIC properties, which are specific to the used SPMI PMIC device(s).
+  When used in combination with HiSilicon 6421v600, the properties
+  are documented at
+  drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml.
+
+additionalProperties: false
+
+examples:
+  - |
+bus {
+  #address-cells = <2>;
+  #size-cells = <2>;
+
+  spmi: spmi@fff24000 {
+compatible = "hisilicon,kirin970-spmi-controller";
+#address-cells = <2>;
+#size-cells = <0>;
+status = "ok";
+reg = <0x0 0xfff24000 0x0 0x1000>;
+spmi-channel = <2>;
+
+pmic@0 {
+  reg = <0 0>;
+  /* pmic properties */
+};
+  };
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index fb49e654a1db..406c2340f221 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8078,6 +8078,13 @@ F:   drivers/crypto/hisilicon/sec2/sec_crypto.c
 F: drivers/crypto/hisilicon/sec2/sec_crypto.h
 F:     drivers/crypto/hisilicon/sec2/sec_main.c
 
+HISILICON SPMI CONTROLLER DRIVER FOR HIKEY 970
+M: Mauro Carvalho Chehab 
+L: linux-ker...@vger.kernel.org
+S: Maintained
+F: 
Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
+F: drivers/spmi/hisi-spmi-controller.c
+
 HISILICON STAGING DRIVERS FOR HIKEY 960/970
 M: Mauro Carvalho Chehab 
 L: de...@driverdev.osuosl.org
diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
index a53bad541f1a..2874b6c26028 100644
--- a/drivers/spmi/Kconfig
+++ b/drivers/spmi/Kconfig
@@ -11,6 +11,15 @@ menuconfig SPMI
 
 if SPMI
 
+config SPMI_HISI3670
+   tristate "Hisilicon 3670 SPMI Controller"
+   select IRQ_DOMAIN_HIERARCHY
+   depends on HAS_IOMEM
+   help
+ If you say yes to this option, support will be included for the
+ built-in SPMI PMIC Arbiter interface on Hisilicon 3670
+ processors.
+
 config SPMI_MSM_PMIC_ARB
tristate "Qualcomm MSM SPMI Controller (PMIC Arbiter)"
select IRQ_DOMAIN_HIERARCHY
diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile
index 55a94cadeffe..6e092e6f290c 100644
--- a/drivers/spmi/Makefile
+++ b/drivers/spmi/Makefile
@@ -4,4 +4,5 @@
 #
 obj-$(CONFIG_SPMI) += spmi.o
 
+obj-$(CONFIG_SPMI_HISI3670)+= hisi-spmi-controller.o
 obj-$(CONFIG_SPMI_MSM_PMIC_ARB)+= spmi-pmic-arb.o
diff --git a/drivers/spmi/hisi-spmi-controller.c 
b/drivers/spmi/hisi-spmi-controller.c
new file mode 100644
index ..0d42bc65f39b
--

[PATCH v7 00/14] Move Hisilicon 6421v600 SPMI and USB drivers out of staging

2021-01-29 Thread Mauro Carvalho Chehab
Hi Greg/Mark/Lee/Vinod,

Another rebase , also the top of staging-testing,

This series contain the remaining patches for USB to start working,
except for a final DTS patch.

Patches 1 and 2 convert the SPMI and regulator
drivers to use regmap and simplifies the logic by using
regmap helpers.

Patches 3 to 9 address some issues pointed by Lee at the MFD driver.

I guess the best would be if Greg could apply both patches
also via the staging tree.

Patches 10 to 13 move the drivers and their corresponding
DT documentation bindings out of staging.

Patch 14 contains the DT which describes the regulator,
SPMI controller and MFD.

I'll submit the final patch with USB bindings after having
everything set (e.g. after 5.12-rc1).


Mauro Carvalho Chehab (14):
  staging: hikey9xx: spmi driver: convert to regmap
  staging: hikey9xx: hi6421v600-regulator: use some regmap helpers
  staging: hikey9xx: hi6421-spmi-pmic: rename some vars
  staging: hikey9xx: hi6421-spmi-pmic: cleanup probe code
  staging: hikey9xx: hi6421-spmi-pmic: cleanup header file
  staging: hikey9xx: hi6421-spmi-pmic: fix IRQ handler code
  staging: hikey9xx: hi6421-spmi-pmic: cleanup IRQ handling code
  staging: hikey9xx: hi6421-spmi-pmic: document registers
  staging: hikey9xx: hi6421-spmi-pmic: update copyright notes
  phy: phy-hi3670-usb3: move driver from staging into phy
  spmi: hisi-spmi-controller: move driver from staging
  mfd: hi6421-spmi-pmic: move driver from staging
  regulator: hi6421v600-regulator: move it from staging
  dts: hisilicon: add support for the PMIC found on Hikey 970

 .../mfd/hisilicon,hi6421-spmi-pmic.yaml   | 135 
 .../bindings/phy/hisilicon,hi3670-usb3.yaml   |  73 ++
 .../spmi/hisilicon,hisi-spmi-controller.yaml  |  75 ++
 MAINTAINERS   |  24 +-
 .../boot/dts/hisilicon/hi3670-hikey970.dts|  22 +-
 .../boot/dts/hisilicon/hikey970-pmic.dtsi |  87 +++
 drivers/mfd/Kconfig   |  15 +
 drivers/mfd/Makefile  |   1 +
 drivers/mfd/hi6421-spmi-pmic.c| 296 
 drivers/phy/hisilicon/Kconfig |  10 +
 drivers/phy/hisilicon/Makefile|   1 +
 drivers/phy/hisilicon/phy-hi3670-usb3.c   | 668 ++
 drivers/regulator/Kconfig |   8 +
 drivers/regulator/Makefile|   1 +
 drivers/regulator/hi6421v600-regulator.c  | 299 
 drivers/spmi/Kconfig  |   9 +
 drivers/spmi/Makefile |   1 +
 drivers/spmi/hisi-spmi-controller.c   | 367 ++
 drivers/staging/Kconfig   |   2 -
 drivers/staging/Makefile  |   1 -
 drivers/staging/hikey9xx/Kconfig  |  50 --
 drivers/staging/hikey9xx/Makefile |   7 -
 drivers/staging/hikey9xx/TODO |   5 -
 drivers/staging/hikey9xx/hi6421-spmi-pmic.c   | 326 -
 .../staging/hikey9xx/hi6421v600-regulator.c   | 336 -
 .../staging/hikey9xx/hisi-spmi-controller.c   | 367 --
 .../hikey9xx/hisilicon,hi6421-spmi-pmic.yaml  | 135 
 .../hisilicon,hisi-spmi-controller.yaml   |  75 --
 drivers/staging/hikey9xx/phy-hi3670-usb3.c| 668 --
 drivers/staging/hikey9xx/phy-hi3670-usb3.yaml |  73 --
 include/linux/mfd/hi6421-spmi-pmic.h  |  28 +-
 31 files changed, 2072 insertions(+), 2093 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
 create mode 100644 
Documentation/devicetree/bindings/phy/hisilicon,hi3670-usb3.yaml
 create mode 100644 
Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
 create mode 100644 arch/arm64/boot/dts/hisilicon/hikey970-pmic.dtsi
 create mode 100644 drivers/mfd/hi6421-spmi-pmic.c
 create mode 100644 drivers/phy/hisilicon/phy-hi3670-usb3.c
 create mode 100644 drivers/regulator/hi6421v600-regulator.c
 create mode 100644 drivers/spmi/hisi-spmi-controller.c
 delete mode 100644 drivers/staging/hikey9xx/Kconfig
 delete mode 100644 drivers/staging/hikey9xx/Makefile
 delete mode 100644 drivers/staging/hikey9xx/TODO
 delete mode 100644 drivers/staging/hikey9xx/hi6421-spmi-pmic.c
 delete mode 100644 drivers/staging/hikey9xx/hi6421v600-regulator.c
 delete mode 100644 drivers/staging/hikey9xx/hisi-spmi-controller.c
 delete mode 100644 drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
 delete mode 100644 drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml
 delete mode 100644 drivers/staging/hikey9xx/phy-hi3670-usb3.c
 delete mode 100644 drivers/staging/hikey9xx/phy-hi3670-usb3.yaml

-- 
2.29.2


___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v7 10/14] phy: phy-hi3670-usb3: move driver from staging into phy

2021-01-29 Thread Mauro Carvalho Chehab
The phy USB3 driver for Hisilicon 970 (hi3670) is ready
for mainstream. Mode it from staging into the main driver's
phy/ directory.

Signed-off-by: Mauro Carvalho Chehab 
---
 .../bindings/phy/hisilicon,hi3670-usb3.yaml   |  73 ++
 MAINTAINERS   |   9 +-
 drivers/phy/hisilicon/Kconfig |  10 +
 drivers/phy/hisilicon/Makefile|   1 +
 drivers/phy/hisilicon/phy-hi3670-usb3.c   | 668 ++
 drivers/staging/hikey9xx/Kconfig  |  11 -
 drivers/staging/hikey9xx/Makefile |   2 -
 drivers/staging/hikey9xx/phy-hi3670-usb3.c| 668 --
 drivers/staging/hikey9xx/phy-hi3670-usb3.yaml |  73 --
 9 files changed, 760 insertions(+), 755 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/phy/hisilicon,hi3670-usb3.yaml
 create mode 100644 drivers/phy/hisilicon/phy-hi3670-usb3.c
 delete mode 100644 drivers/staging/hikey9xx/phy-hi3670-usb3.c
 delete mode 100644 drivers/staging/hikey9xx/phy-hi3670-usb3.yaml

diff --git a/Documentation/devicetree/bindings/phy/hisilicon,hi3670-usb3.yaml 
b/Documentation/devicetree/bindings/phy/hisilicon,hi3670-usb3.yaml
new file mode 100644
index ..ebd78acfe2de
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/hisilicon,hi3670-usb3.yaml
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/hisilicon,hi3670-usb3.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Hisilicon Kirin970 USB PHY
+
+maintainers:
+  - Mauro Carvalho Chehab 
+
+description: |+
+  Bindings for USB3 PHY on HiSilicon Kirin 970.
+
+properties:
+  compatible:
+const: hisilicon,hi3670-usb-phy
+
+  "#phy-cells":
+const: 0
+
+  hisilicon,pericrg-syscon:
+$ref: '/schemas/types.yaml#/definitions/phandle'
+description: phandle of syscon used to control iso refclk.
+
+  hisilicon,pctrl-syscon:
+$ref: '/schemas/types.yaml#/definitions/phandle'
+description: phandle of syscon used to control usb tcxo.
+
+  hisilicon,sctrl-syscon:
+$ref: '/schemas/types.yaml#/definitions/phandle'
+description: phandle of syscon used to control phy deep sleep.
+
+  hisilicon,eye-diagram-param:
+$ref: /schemas/types.yaml#/definitions/uint32
+description: Eye diagram for phy.
+
+  hisilicon,tx-vboost-lvl:
+$ref: /schemas/types.yaml#/definitions/uint32
+description: TX level vboost for phy.
+
+required:
+  - compatible
+  - hisilicon,pericrg-syscon
+  - hisilicon,pctrl-syscon
+  - hisilicon,sctrl-syscon
+  - hisilicon,eye-diagram-param
+  - hisilicon,tx-vboost-lvl
+  - "#phy-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+bus {
+  #address-cells = <2>;
+  #size-cells = <2>;
+
+  usb3_otg_bc: usb3_otg_bc@ff20 {
+compatible = "syscon", "simple-mfd";
+reg = <0x0 0xff20 0x0 0x1000>;
+
+usb_phy {
+  compatible = "hisilicon,hi3670-usb-phy";
+  #phy-cells = <0>;
+  hisilicon,pericrg-syscon = <&crg_ctrl>;
+  hisilicon,pctrl-syscon = <&pctrl>;
+  hisilicon,sctrl-syscon = <&sctrl>;
+  hisilicon,eye-diagram-param = <0xfdfee4>;
+  hisilicon,tx-vboost-lvl = <0x5>;
+};
+  };
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index 992fe3b0900a..fb49e654a1db 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -18371,7 +18371,7 @@ L:  linux-...@vger.kernel.org
 S: Maintained
 F: drivers/usb/roles/intel-xhci-usb-role-switch.c
 
-USB IP DRIVER FOR HISILICON KIRIN
+USB IP DRIVER FOR HISILICON KIRIN 960
 M: Yu Chen 
 M: Binghui Wang 
 L: linux-...@vger.kernel.org
@@ -18379,6 +18379,13 @@ S: Maintained
 F: Documentation/devicetree/bindings/phy/hisilicon,hi3660-usb3.yaml
 F: drivers/phy/hisilicon/phy-hi3660-usb3.c
 
+USB IP DRIVER FOR HISILICON KIRIN 970
+M: Mauro Carvalho Chehab 
+L: linux-...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/phy/hisilicon,kirin970-usb3.yaml
+F: drivers/phy/hisilicon/phy-kirin970-usb3.c
+
 USB ISP116X DRIVER
 M: Olav Kongas 
 L: linux-...@vger.kernel.org
diff --git a/drivers/phy/hisilicon/Kconfig b/drivers/phy/hisilicon/Kconfig
index 1c73053bcc98..4d008cfc279c 100644
--- a/drivers/phy/hisilicon/Kconfig
+++ b/drivers/phy/hisilicon/Kconfig
@@ -23,6 +23,16 @@ config PHY_HI3660_USB
 
  To compile this driver as a module, choose M here.
 
+config PHY_HI3670_USB
+   tristate "hi3670 USB PHY support"
+   depends on (ARCH_HISI && ARM64) || COMPILE_TEST
+   select GENERIC_PHY
+   select MFD_SYSCON
+   help
+ Enable this to support the HISILICON HI3670 USB PHY.
+
+ To compile this driver as a module, choose M here.
+
 config PHY_HISTB_COMBPHY
tristate "

[PATCH v7 12/14] mfd: hi6421-spmi-pmic: move driver from staging

2021-01-29 Thread Mauro Carvalho Chehab
This driver is ready for mainstream. So, move it out of staging.

Signed-off-by: Mauro Carvalho Chehab 
---
 .../mfd/hisilicon,hi6421-spmi-pmic.yaml   | 135 
 MAINTAINERS   |   7 +
 drivers/mfd/Kconfig   |  15 +
 drivers/mfd/Makefile  |   1 +
 drivers/mfd/hi6421-spmi-pmic.c| 296 ++
 drivers/staging/hikey9xx/Kconfig  |  17 -
 drivers/staging/hikey9xx/Makefile |   1 -
 drivers/staging/hikey9xx/hi6421-spmi-pmic.c   | 296 --
 .../hikey9xx/hisilicon,hi6421-spmi-pmic.yaml  | 135 
 9 files changed, 454 insertions(+), 449 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
 create mode 100644 drivers/mfd/hi6421-spmi-pmic.c
 delete mode 100644 drivers/staging/hikey9xx/hi6421-spmi-pmic.c
 delete mode 100644 drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml

diff --git 
a/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml 
b/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
new file mode 100644
index ..3b23ad56b31a
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
@@ -0,0 +1,135 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/hisilicon,hi6421-spmi-pmic.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: HiSilicon 6421v600 SPMI PMIC
+
+maintainers:
+  - Mauro Carvalho Chehab 
+
+description: |
+  HiSilicon 6421v600 should be connected inside a MIPI System Power Management
+  (SPMI) bus. It provides interrupts and power supply.
+
+  The GPIO and interrupt settings are represented as part of the top-level PMIC
+  node.
+
+  The SPMI controller part is provided by
+  drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml.
+
+properties:
+  $nodename:
+pattern: "pmic@[0-9a-f]"
+
+  compatible:
+const: hisilicon,hi6421v600-spmi
+
+  reg:
+maxItems: 1
+
+  '#interrupt-cells':
+const: 2
+
+  interrupt-controller:
+description:
+  Identify that the PMIC is capable of behaving as an interrupt controller.
+
+  gpios:
+maxItems: 1
+
+  regulators:
+type: object
+
+properties:
+  '#address-cells':
+const: 1
+
+  '#size-cells':
+const: 0
+
+patternProperties:
+  '^ldo[0-9]+@[0-9a-f]$':
+type: object
+
+$ref: "/schemas/regulator/regulator.yaml#"
+
+required:
+  - compatible
+  - reg
+  - regulators
+
+additionalProperties: false
+
+examples:
+  - |
+/* pmic properties */
+
+pmic: pmic@0 {
+  compatible = "hisilicon,hi6421-spmi";
+  reg = <0 0>;
+
+  #interrupt-cells = <2>;
+  interrupt-controller;
+  gpios = <&gpio28 0 0>;
+
+  regulators {
+#address-cells = <1>;
+#size-cells = <0>;
+
+ldo3: LDO3 {
+  regulator-name = "ldo3";
+  regulator-min-microvolt = <150>;
+  regulator-max-microvolt = <200>;
+  regulator-boot-on;
+};
+
+ldo4: LDO4 {
+  regulator-name = "ldo4";
+  regulator-min-microvolt = <1725000>;
+  regulator-max-microvolt = <190>;
+  regulator-boot-on;
+};
+
+ldo9: LDO9 {
+  regulator-name = "ldo9";
+  regulator-min-microvolt = <175>;
+  regulator-max-microvolt = <330>;
+  regulator-boot-on;
+};
+
+ldo15: LDO15 {
+  regulator-name = "ldo15";
+  regulator-min-microvolt = <180>;
+  regulator-max-microvolt = <300>;
+  regulator-always-on;
+};
+
+ldo16: LDO16 {
+  regulator-name = "ldo16";
+  regulator-min-microvolt = <180>;
+  regulator-max-microvolt = <300>;
+  regulator-boot-on;
+};
+
+ldo17: LDO17 {
+  regulator-name = "ldo17";
+  regulator-min-microvolt = <250>;
+  regulator-max-microvolt = <330>;
+};
+
+ldo33: LDO33 {
+  regulator-name = "ldo33";
+  regulator-min-microvolt = <250>;
+  regulator-max-microvolt = <330>;
+  regulator-boot-on;
+};
+
+ldo34: LDO34 {
+  regulator-name = "ldo34";
+  regulator-min-microvolt = <260>;
+  regulator-max-microvolt = <330>;
+};
+  };
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index 406c2340f221..241f11b7d48a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8085,6 +8085,13 @@ S:   Maintained
 F: 
Documentation/devicetree/bindings/spmi/hisilicon,hisi-s

[PATCH v7 08/14] staging: hikey9xx: hi6421-spmi-pmic: document registers

2021-01-29 Thread Mauro Carvalho Chehab
Make it clearer about how the IRQ registers are filled by adding
a table with them, with two macros used to calculate the mask
register.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 38 +
 1 file changed, 31 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c 
b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
index f2af1760add9..b11401ebcc03 100644
--- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
+++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
@@ -38,10 +38,6 @@ enum hi6421_spmi_pmic_irq_list {
 
 #define HISI_IRQ_ARRAY 2
 #define HISI_IRQ_NUM   (HISI_IRQ_ARRAY * 8)
-#define HISI_IRQ_MASK  GENMASK(1, 0)
-
-#define SOC_PMIC_IRQ_MASK_0_ADDR   0x0202
-#define SOC_PMIC_IRQ0_ADDR 0x0212
 
 #define HISI_IRQ_KEY_NUM   0
 
@@ -49,6 +45,35 @@ enum hi6421_spmi_pmic_irq_list {
 #define HISI_IRQ_KEY_VALUE (BIT(POWERKEY_DOWN) | BIT(POWERKEY_UP))
 #define HISI_MASK  GENMASK(HISI_BITS - 1, 0)
 
+/*
+ * The IRQs are mapped as:
+ *
+ * ==  =   =
+ * IRQ MASK REGISTER   IRQ REGISTERBIT
+ * ==  =   =
+ * OTMP0x0202  0x212   bit 0
+ * VBUS_CONNECT0x0202  0x212   bit 1
+ * VBUS_DISCONNECT 0x0202  0x212   bit 2
+ * ALARMON_R   0x0202  0x212   bit 3
+ * HOLD_6S 0x0202  0x212   bit 4
+ * HOLD_1S 0x0202  0x212   bit 5
+ * POWERKEY_UP 0x0202  0x212   bit 6
+ * POWERKEY_DOWN   0x0202  0x212   bit 7
+ *
+ * OCP_SCP_R   0x0203  0x213   bit 0
+ * COUL_R  0x0203  0x213   bit 1
+ * SIM0_HPD_R  0x0203  0x213   bit 2
+ * SIM0_HPD_F  0x0203  0x213   bit 3
+ * SIM1_HPD_R  0x0203  0x213   bit 4
+ * SIM1_HPD_F  0x0203  0x213   bit 5
+ * ==  =   =
+ */
+#define SOC_PMIC_IRQ_MASK_0_ADDR   0x0202
+#define SOC_PMIC_IRQ0_ADDR 0x0212
+
+#define IRQ_MASK_REGISTER(irq_data)(SOC_PMIC_IRQ_MASK_0_ADDR + \   
 irqd_to_hwirq(irq_data) >> 3)
+#define IRQ_MASK_BIT(irq_data) BIT(irqd_to_hwirq(irq_data) & 0x07)
+
 static const struct mfd_cell hi6421v600_devs[] = {
{ .name = "hi6421v600-regulator", },
 };
@@ -89,13 +114,12 @@ static void hi6421_spmi_irq_mask(struct irq_data *d)
unsigned int data;
u32 offset;
 
-   offset = (irqd_to_hwirq(d) >> HISI_IRQ_MASK);
-   offset += SOC_PMIC_IRQ_MASK_0_ADDR;
+   offset = IRQ_MASK_REGISTER(d);
 
spin_lock_irqsave(&ddata->lock, flags);
 
regmap_read(ddata->regmap, offset, &data);
-   data |= (1 << (irqd_to_hwirq(d) & 0x07));
+   data |= IRQ_MASK_BIT(d);
regmap_write(ddata->regmap, offset, data);
 
spin_unlock_irqrestore(&ddata->lock, flags);
-- 
2.29.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v7 02/14] staging: hikey9xx: hi6421v600-regulator: use some regmap helpers

2021-01-29 Thread Mauro Carvalho Chehab
Now that the driver was ported to use regmap, let's use
some help functions in order to simplify the code a little
bit.

Suggested-by: Mark Brown 
Signed-off-by: Mauro Carvalho Chehab 
---
 .../staging/hikey9xx/hi6421v600-regulator.c   | 45 ++-
 1 file changed, 3 insertions(+), 42 deletions(-)

diff --git a/drivers/staging/hikey9xx/hi6421v600-regulator.c 
b/drivers/staging/hikey9xx/hi6421v600-regulator.c
index 9e319fa11137..7090107b9ec2 100644
--- a/drivers/staging/hikey9xx/hi6421v600-regulator.c
+++ b/drivers/staging/hikey9xx/hi6421v600-regulator.c
@@ -95,17 +95,6 @@ static const unsigned int ldo34_voltages[] = {
.eco_uA = ecoamp,  \
}
 
-static int hi6421_spmi_regulator_is_enabled(struct regulator_dev *rdev)
-{
-   struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
-   struct hi6421_spmi_pmic *pmic = sreg->pmic;
-   u32 reg_val;
-
-   regmap_read(pmic->map, rdev->desc->enable_reg, ®_val);
-
-   return ((reg_val & rdev->desc->enable_mask) != 0);
-}
-
 static int hi6421_spmi_regulator_enable(struct regulator_dev *rdev)
 {
struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
@@ -136,34 +125,6 @@ static int hi6421_spmi_regulator_disable(struct 
regulator_dev *rdev)
  rdev->desc->enable_mask, 0);
 }
 
-static int hi6421_spmi_regulator_get_voltage_sel(struct regulator_dev *rdev)
-{
-   struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
-   struct hi6421_spmi_pmic *pmic = sreg->pmic;
-   u32 reg_val;
-
-   regmap_read(pmic->map, rdev->desc->vsel_reg, ®_val);
-
-   return (reg_val & rdev->desc->vsel_mask) >> (ffs(rdev->desc->vsel_mask) 
- 1);
-}
-
-static int hi6421_spmi_regulator_set_voltage_sel(struct regulator_dev *rdev,
-unsigned int selector)
-{
-   struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
-   struct hi6421_spmi_pmic *pmic = sreg->pmic;
-   u32 reg_val;
-
-   if (selector >= rdev->desc->n_voltages)
-   return -EINVAL;
-
-   reg_val = selector << (ffs(rdev->desc->vsel_mask) - 1);
-
-   /* set voltage selector */
-   return regmap_update_bits(pmic->map, rdev->desc->vsel_reg,
- rdev->desc->vsel_mask, reg_val);
-}
-
 static unsigned int hi6421_spmi_regulator_get_mode(struct regulator_dev *rdev)
 {
struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
@@ -214,13 +175,13 @@ hi6421_spmi_regulator_get_optimum_mode(struct 
regulator_dev *rdev,
 }
 
 static const struct regulator_ops hi6421_spmi_ldo_rops = {
-   .is_enabled = hi6421_spmi_regulator_is_enabled,
+   .is_enabled = regulator_is_enabled_regmap,
.enable = hi6421_spmi_regulator_enable,
.disable = hi6421_spmi_regulator_disable,
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_iterate,
-   .get_voltage_sel = hi6421_spmi_regulator_get_voltage_sel,
-   .set_voltage_sel = hi6421_spmi_regulator_set_voltage_sel,
+   .get_voltage_sel = regulator_get_voltage_sel_regmap,
+   .set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_mode = hi6421_spmi_regulator_get_mode,
.set_mode = hi6421_spmi_regulator_set_mode,
.get_optimum_mode = hi6421_spmi_regulator_get_optimum_mode,
-- 
2.29.2

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v7 03/14] staging: hikey9xx: hi6421-spmi-pmic: rename some vars

2021-01-29 Thread Mauro Carvalho Chehab
- When referring to regmap, rename map to regmap
- inside hi6421-spmi-pmic, call private data struct as
  ddata.

No functional changes.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/hikey9xx/hi6421-spmi-pmic.c   | 104 +-
 .../staging/hikey9xx/hi6421v600-regulator.c   |  10 +-
 include/linux/mfd/hi6421-spmi-pmic.h  |   2 +-
 3 files changed, 58 insertions(+), 58 deletions(-)

diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c 
b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
index 3d612bd46231..a4ffeb06ed6a 100644
--- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
+++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
@@ -43,17 +43,17 @@ static const struct mfd_cell hi6421v600_devs[] = {
 
 static irqreturn_t hi6421_spmi_irq_handler(int irq, void *priv)
 {
-   struct hi6421_spmi_pmic *pmic = (struct hi6421_spmi_pmic *)priv;
+   struct hi6421_spmi_pmic *ddata = (struct hi6421_spmi_pmic *)priv;
unsigned long pending;
unsigned int data;
int i, offset;
 
for (i = 0; i < HISI_IRQ_ARRAY; i++) {
-   regmap_read(pmic->map, offset, &data);
+   regmap_read(ddata->regmap, offset, &data);
data &= HISI_MASK_FIELD;
if (data != 0)
pr_debug("data[%d]=0x%d\n\r", i, data);
-   regmap_write(pmic->map, i + SOC_PMIC_IRQ0_ADDR, data);
+   regmap_write(ddata->regmap, i + SOC_PMIC_IRQ0_ADDR, data);
 
/* for_each_set_bit() macro requires unsigned long */
pending = data;
@@ -61,14 +61,14 @@ static irqreturn_t hi6421_spmi_irq_handler(int irq, void 
*priv)
/* solve powerkey order */
if ((i == HISI_IRQ_KEY_NUM) &&
((pending & HISI_IRQ_KEY_VALUE) == HISI_IRQ_KEY_VALUE)) {
-   generic_handle_irq(pmic->irqs[HISI_IRQ_KEY_DOWN]);
-   generic_handle_irq(pmic->irqs[HISI_IRQ_KEY_UP]);
+   generic_handle_irq(ddata->irqs[HISI_IRQ_KEY_DOWN]);
+   generic_handle_irq(ddata->irqs[HISI_IRQ_KEY_UP]);
pending &= (~HISI_IRQ_KEY_VALUE);
}
 
if (pending) {
for_each_set_bit(offset, &pending, HISI_BITS)
-   generic_handle_irq(pmic->irqs[offset + i * 
HISI_BITS]);
+   generic_handle_irq(ddata->irqs[offset + i * 
HISI_BITS]);
}
}
 
@@ -77,7 +77,7 @@ static irqreturn_t hi6421_spmi_irq_handler(int irq, void 
*priv)
 
 static void hi6421_spmi_irq_mask(struct irq_data *d)
 {
-   struct hi6421_spmi_pmic *pmic = irq_data_get_irq_chip_data(d);
+   struct hi6421_spmi_pmic *ddata = irq_data_get_irq_chip_data(d);
unsigned long flags;
unsigned int data;
u32 offset;
@@ -85,28 +85,28 @@ static void hi6421_spmi_irq_mask(struct irq_data *d)
offset = (irqd_to_hwirq(d) >> 3);
offset += SOC_PMIC_IRQ_MASK_0_ADDR;
 
-   spin_lock_irqsave(&pmic->lock, flags);
+   spin_lock_irqsave(&ddata->lock, flags);
 
-   regmap_read(pmic->map, offset, &data);
+   regmap_read(ddata->regmap, offset, &data);
data |= (1 << (irqd_to_hwirq(d) & 0x07));
-   regmap_write(pmic->map, offset, data);
-   spin_unlock_irqrestore(&pmic->lock, flags);
+   regmap_write(ddata->regmap, offset, data);
+   spin_unlock_irqrestore(&ddata->lock, flags);
 }
 
 static void hi6421_spmi_irq_unmask(struct irq_data *d)
 {
-   struct hi6421_spmi_pmic *pmic = irq_data_get_irq_chip_data(d);
+   struct hi6421_spmi_pmic *ddata = irq_data_get_irq_chip_data(d);
u32 data, offset;
unsigned long flags;
 
offset = (irqd_to_hwirq(d) >> 3);
offset += SOC_PMIC_IRQ_MASK_0_ADDR;
 
-   spin_lock_irqsave(&pmic->lock, flags);
-   regmap_read(pmic->map, offset, &data);
+   spin_lock_irqsave(&ddata->lock, flags);
+   regmap_read(ddata->regmap, offset, &data);
data &= ~(1 << (irqd_to_hwirq(d) & 0x07));
-   regmap_write(pmic->map, offset, data);
-   spin_unlock_irqrestore(&pmic->lock, flags);
+   regmap_write(ddata->regmap, offset, data);
+   spin_unlock_irqrestore(&ddata->lock, flags);
 }
 
 static struct irq_chip hi6421_spmi_pmu_irqchip = {
@@ -120,11 +120,11 @@ static struct irq_chip hi6421_spmi_pmu_irqchip = {
 static int hi6421_spmi_irq_map(struct irq_domain *d, unsigned int virq,
   irq_hw_number_t hw)
 {
-   struct hi6421_spmi_pmic *pmic = d->host_data;
+   struct hi6421_spmi_pmic *ddata = d->host_data;
 
irq_set_chip_and_handler_name(virq, &hi6421_spmi_pmu_irqchip,
  handle_simple

[PATCH v7 13/14] regulator: hi6421v600-regulator: move it from staging

2021-01-29 Thread Mauro Carvalho Chehab
This driver is ready for mainstream. Move it out of staging.

Signed-off-by: Mauro Carvalho Chehab 
---
 MAINTAINERS   |   7 +-
 drivers/regulator/Kconfig |   8 +
 drivers/regulator/Makefile|   1 +
 drivers/regulator/hi6421v600-regulator.c  | 299 ++
 drivers/staging/Kconfig   |   2 -
 drivers/staging/Makefile  |   1 -
 drivers/staging/hikey9xx/Kconfig  |  11 -
 drivers/staging/hikey9xx/Makefile |   3 -
 drivers/staging/hikey9xx/TODO |   5 -
 .../staging/hikey9xx/hi6421v600-regulator.c   | 299 --
 10 files changed, 309 insertions(+), 327 deletions(-)
 create mode 100644 drivers/regulator/hi6421v600-regulator.c
 delete mode 100644 drivers/staging/hikey9xx/Kconfig
 delete mode 100644 drivers/staging/hikey9xx/Makefile
 delete mode 100644 drivers/staging/hikey9xx/TODO
 delete mode 100644 drivers/staging/hikey9xx/hi6421v600-regulator.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 241f11b7d48a..5c5ad946c5d5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8091,12 +8091,7 @@ L:   linux-ker...@vger.kernel.org
 S: Maintained
 F: Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
 F: drivers/mfd/hi6421-spmi-pmic.c
-
-HISILICON STAGING DRIVERS FOR HIKEY 960/970
-M: Mauro Carvalho Chehab 
-L: de...@driverdev.osuosl.org
-S: Maintained
-F: drivers/staging/hikey9xx/
+F: drivers/regulator/hi6421v600-regulator.c
 
 HISILICON TRUE RANDOM NUMBER GENERATOR V2 SUPPORT
 M: Zaibo Xu 
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 5abdd29fb9f3..088474391da8 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -423,6 +423,14 @@ config REGULATOR_HI655X
  This driver provides support for the voltage regulators of the
  Hisilicon Hi655x PMIC device.
 
+config REGULATOR_HI6421V600
+   tristate "HiSilicon Hi6421v600 PMIC voltage regulator support"
+   depends on MFD_HI6421_SPMI && OF
+   help
+ This driver provides support for the voltage regulators on
+ HiSilicon Hi6421v600 PMU / Codec IC.
+ This is used on Kirin 3670 boards, like HiKey 970.
+
 config REGULATOR_ISL9305
tristate "Intersil ISL9305 regulator"
depends on I2C
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 680e539f6579..77e519d2bc68 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_REGULATOR_FAN53880) += fan53880.o
 obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
 obj-$(CONFIG_REGULATOR_HI6421) += hi6421-regulator.o
 obj-$(CONFIG_REGULATOR_HI6421V530) += hi6421v530-regulator.o
+obj-$(CONFIG_REGULATOR_HI6421V600) += hi6421v600-regulator.o
 obj-$(CONFIG_REGULATOR_HI655X) += hi655x-regulator.o
 obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
 obj-$(CONFIG_REGULATOR_ISL9305) += isl9305.o
diff --git a/drivers/regulator/hi6421v600-regulator.c 
b/drivers/regulator/hi6421v600-regulator.c
new file mode 100644
index ..c801bb840962
--- /dev/null
+++ b/drivers/regulator/hi6421v600-regulator.c
@@ -0,0 +1,299 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Device driver for regulators in Hisi IC
+//
+// Copyright (c) 2013 Linaro Ltd.
+// Copyright (c) 2011 Hisilicon.
+// Copyright (c) 2020-2021 Huawei Technologies Co., Ltd
+//
+// Guodong Xu 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct hi6421_spmi_reg_info {
+   struct regulator_desc   desc;
+   struct hi6421_spmi_pmic *pmic;
+   u8  eco_mode_mask;
+   u32 eco_uA;
+
+   /* Serialize regulator enable logic */
+   struct mutex enable_mutex;
+};
+
+static const unsigned int ldo3_voltages[] = {
+   150, 155, 160, 165,
+   170, 1725000, 175, 1775000,
+   180, 1825000, 185, 1875000,
+   190, 1925000, 195, 200
+};
+
+static const unsigned int ldo4_voltages[] = {
+   1725000, 175, 1775000, 180,
+   1825000, 185, 1875000, 190
+};
+
+static const unsigned int ldo9_voltages[] = {
+   175, 180, 1825000, 280,
+   285, 295, 300, 330
+};
+
+static const unsigned int ldo15_voltages[] = {
+   180, 185, 240, 260,
+   270, 285, 295, 300
+};
+
+static const unsigned int ldo17_voltages[] = {
+   250, 260, 270, 280,
+   300, 310, 320, 330
+};
+
+static const unsigned int ldo34_voltages[] = {
+   260, 270, 280, 290,
+   300, 310, 320, 330
+};
+
+/**
+ * HI6421V600_LDO() - specify a LDO power line
+ * @_id: LDO id name string
+ * @vtable: voltage table
+ * @ereg: enable register
+ * @emask: enable mask
+ * @vreg: voltage select regist

  1   2   3   4   5   6   7   8   9   10   >