Re: [PATCH 17/17] staging: nuc-led: update the TODOs
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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()
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
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()
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()
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
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
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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
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()
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()
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()
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
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()
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()
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()
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()
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
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()
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()
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
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
- 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
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
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
- 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
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
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
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
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
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
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
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
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
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
- 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
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