* [PATCH v2] HID: hiddev: fix potential Spectre v1
From: Breno Leitao @ 2018-10-19 20:01 UTC (permalink / raw)
To: linux-usb, linux-input; +Cc: gustavo, jkosina, Breno Leitao, stable
uref->usage_index can be indirectly controlled by userspace, hence leading
to a potential exploitation of the Spectre variant 1 vulnerability.
This field is used as an array index by the hiddev_ioctl_usage() function,
when 'cmd' is either HIDIOCGCOLLECTIONINDEX, HIDIOCGUSAGES or
HIDIOCSUSAGES.
For cmd == HIDIOCGCOLLECTIONINDEX case, uref->usage_index is compared to
field->maxusage and then used as an index to dereference field->usage
array. The same thing happens to the cmd == HIDIOC{G,S}USAGES cases, where
uref->usage_index is checked against an array maximum value and then it is
used as an index in an array.
This is a summary of the HIDIOCGCOLLECTIONINDEX case, which matches the
traditional Spectre V1 first load:
copy_from_user(uref, user_arg, sizeof(*uref))
if (uref->usage_index >= field->maxusage)
goto inval;
i = field->usage[uref->usage_index].collection_index;
return i;
This patch fixes this by sanitizing field uref->usage_index before using it
to index field->usage (HIDIOCGCOLLECTIONINDEX) or field->value in
HIDIOC{G,S}USAGES arrays, thus, avoiding speculation in the first load.
Signed-off-by: Breno Leitao <leitao@debian.org>
Cc: <stable@vger.kernel.org>
--
v2: Contemplate cmd == HIDIOC{G,S}USAGES case
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 23872d08308c..a746017fac17 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -512,14 +512,24 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd,
if (cmd == HIDIOCGCOLLECTIONINDEX) {
if (uref->usage_index >= field->maxusage)
goto inval;
+ uref->usage_index =
+ array_index_nospec(uref->usage_index,
+ field->maxusage);
} else if (uref->usage_index >= field->report_count)
goto inval;
}
- if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
- (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
- uref->usage_index + uref_multi->num_values > field->report_count))
- goto inval;
+ if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) {
+ if (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
+ uref->usage_index + uref_multi->num_values >
+ field->report_count)
+ goto inval;
+
+ uref->usage_index =
+ array_index_nospec(uref->usage_index,
+ field->report_count -
+ uref_multi->num_values);
+ }
switch (cmd) {
case HIDIOCGUSAGE:
--
2.17.1
^ permalink raw reply related
* [git pull] Input updates for v4.19-rc8
From: Dmitry Torokhov @ 2018-10-19 17:45 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: linux-kernel, linux-input, Linus Torvalds
Hi Greg,
Please pull from:
git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git for-linus
to receive updates for the input subsystem. Just an addition to elan
touchpad driver ACPI table.
Changelog:
---------
Mikhail Nikiforov (1):
Input: elan_i2c - add ACPI ID for Lenovo IdeaPad 330-15IGM
Diffstat:
--------
drivers/input/mouse/elan_i2c_core.c | 1 +
1 file changed, 1 insertion(+)
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH] platform/x86: touchscreen_dmi: Add info for the Trekstor Primetab T13B tablet
From: Andy Shevchenko @ 2018-10-19 12:48 UTC (permalink / raw)
To: marian.cepok
Cc: Hans de Goede, Darren Hart, Andy Shevchenko, linux-input,
Platform Driver, Linux Kernel Mailing List
In-Reply-To: <20181008072505.GA8334@mcepok-pc>
On Mon, Oct 8, 2018 at 10:25 AM Marian Cepok <marian.cepok@gmail.com> wrote:
>
> Add touchscreen info for the Trekstor Primetab T13B tablet.
>
Pushed to my review and testing queue, thanks!
> Reviewed-by: Hans de Goede <hdegoede@redhat.com>
> Signed-off-by: Marian Cepok <marian.cepok@gmail.com>
> ---
> drivers/platform/x86/touchscreen_dmi.c | 24 ++++++++++++++++++++++++
> 1 file changed, 24 insertions(+)
>
> diff --git a/drivers/platform/x86/touchscreen_dmi.c b/drivers/platform/x86/touchscreen_dmi.c
> index cb204f973491..c07954f0efc6 100644
> --- a/drivers/platform/x86/touchscreen_dmi.c
> +++ b/drivers/platform/x86/touchscreen_dmi.c
> @@ -381,6 +381,22 @@ static const struct ts_dmi_data trekstor_primebook_c13_data = {
> .properties = trekstor_primebook_c13_props,
> };
>
> +static const struct property_entry trekstor_primetab_t13b_props[] = {
> + PROPERTY_ENTRY_U32("touchscreen-size-x", 2500),
> + PROPERTY_ENTRY_U32("touchscreen-size-y", 1900),
> + PROPERTY_ENTRY_STRING("firmware-name",
> + "gsl1680-trekstor-primetab-t13b.fw"),
> + PROPERTY_ENTRY_U32("silead,max-fingers", 10),
> + PROPERTY_ENTRY_BOOL("silead,home-button"),
> + PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
> + { }
> +};
> +
> +static const struct ts_dmi_data trekstor_primetab_t13b_data = {
> + .acpi_name = "MSSL1680:00",
> + .properties = trekstor_primetab_t13b_props,
> +};
> +
> static const struct property_entry trekstor_surftab_twin_10_1_props[] = {
> PROPERTY_ENTRY_U32("touchscreen-size-x", 1900),
> PROPERTY_ENTRY_U32("touchscreen-size-y", 1280),
> @@ -648,6 +664,14 @@ static const struct dmi_system_id touchscreen_dmi_table[] = {
> DMI_MATCH(DMI_PRODUCT_NAME, "Primebook C13"),
> },
> },
> + {
> + /* Trekstor Primetab T13B */
> + .driver_data = (void *)&trekstor_primetab_t13b_data,
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
> + DMI_MATCH(DMI_PRODUCT_NAME, "Primetab T13B"),
> + },
> + },
> {
> /* TrekStor SurfTab twin 10.1 ST10432-8 */
> .driver_data = (void *)&trekstor_surftab_twin_10_1_data,
> --
> 2.17.1
>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v4 4/8] regulator: stpmic1: add stpmic1 regulator driver
From: Mark Brown @ 2018-10-19 11:50 UTC (permalink / raw)
To: Pascal PAILLET-LME
Cc: dmitry.torokhov@gmail.com, robh+dt@kernel.org,
mark.rutland@arm.com, lee.jones@linaro.org, lgirdwood@gmail.com,
wim@linux-watchdog.org, linux@roeck-us.net,
linux-input@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org,
benjamin.gaignard@linaro.org, eballetbo@gmail.com
In-Reply-To: <1539853324-29051-5-git-send-email-p.paillet@st.com>
[-- Attachment #1: Type: text/plain, Size: 822 bytes --]
On Thu, Oct 18, 2018 at 09:02:12AM +0000, Pascal PAILLET-LME wrote:
> + for (i = 0; i < ARRAY_SIZE(stpmic1_regulator_cfgs); i++) {
> + /* Parse DT & find regulators to register */
> + init_data = stpmic1_regulators_matches[i].init_data;
> + if (init_data)
> + init_data->regulator_init = &stpmic1_regulator_parse_dt;
> +
> + rdev = stpmic1_regulator_register(pdev, i, init_data, regul);
> + if (IS_ERR(rdev))
> + return PTR_ERR(rdev);
This looks mostly good, the only big thing is this - the default is to
just unconditionally register all the regulators that exist rather than
only those that are configured on that particular platform. This is a
bit simpler and means that all the readback of the configuration for the
unconfigured regulators is available for diagnostics. Is there a reason
not to do that?
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH] Input: pm8941-pwrkey - Add pms405 pwrkey support
From: Vinod @ 2018-10-19 9:05 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Rob Herring, Bjorn Andersson, Mark Rutland, linux-input,
devicetree, linux-kernel
In-Reply-To: <20181019000116.GD210757@dtor-ws>
On 18-10-18, 17:01, Dmitry Torokhov wrote:
> On Thu, Oct 18, 2018 at 10:54:37AM +0530, Vinod wrote:
> > On 19-09-18, 18:49, Bjorn Andersson wrote:
> > > From: Vinod Koul <vkoul@kernel.org>
> > >
> > > Update the binding and driver for pms405 pwrkey.
> >
> > Rob, Dmitry
> >
> > Gentle reminder for this patch...
> >
> > > Signed-off-by: Vinod Koul <vkoul@kernel.org>
> > > Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> > > ---
> > > Documentation/devicetree/bindings/input/qcom,pm8941-pwrkey.txt | 1 +
> > > drivers/input/misc/pm8941-pwrkey.c | 1 +
> > > 2 files changed, 2 insertions(+)
> > >
> > > diff --git a/Documentation/devicetree/bindings/input/qcom,pm8941-pwrkey.txt b/Documentation/devicetree/bindings/input/qcom,pm8941-pwrkey.txt
> > > index 34ab5763f494..736fba3bad54 100644
> > > --- a/Documentation/devicetree/bindings/input/qcom,pm8941-pwrkey.txt
> > > +++ b/Documentation/devicetree/bindings/input/qcom,pm8941-pwrkey.txt
> > > @@ -8,6 +8,7 @@ PROPERTIES
> > > Definition: must be one of:
> > > "qcom,pm8941-pwrkey"
> > > "qcom,pm8941-resin"
> > > + "qcom,pms405-pwrkey"
> > >
> > > - reg:
> > > Usage: required
> > > diff --git a/drivers/input/misc/pm8941-pwrkey.c b/drivers/input/misc/pm8941-pwrkey.c
> > > index 48153e0ca19a..fccf63263c1c 100644
> > > --- a/drivers/input/misc/pm8941-pwrkey.c
> > > +++ b/drivers/input/misc/pm8941-pwrkey.c
> > > @@ -317,6 +317,7 @@ static const struct pm8941_data resin_data = {
> > > static const struct of_device_id pm8941_pwr_key_id_table[] = {
> > > { .compatible = "qcom,pm8941-pwrkey", .data = &pwrkey_data },
> > > { .compatible = "qcom,pm8941-resin", .data = &resin_data },
> > > + { .compatible = "qcom,pms405-pwrkey", .data = &pwrkey_data },
>
> I am sure I asked this question before (in context of a different
> driver), but why do we need this compatible if we already have
> pm8941-pwrkey compatible? Isn't pms405-pwrkey compatible with
> pm8941-pwrkey as far as power key block goes? In which cases do we need
> new compatibles and when can we reuse existing ones? Rob?
Relooking I do think that reuse of pm8941-pwrkey is entirely feasible,
thanks for the suggestion. We can drop this and I will update DTS
--
~Vinod
^ permalink raw reply
* Fw: PROBLEM: Keyboard not responding after resuming from suspend/hibernate
From: Numan Demirdöğen @ 2018-10-19 7:20 UTC (permalink / raw)
To: dmitry.torokhov; +Cc: peterz, mingo, linux-kernel, linux-input
In-Reply-To: <20180831215121.1b1f66bf@korsan.localdomain>
[-- Attachment #1: Type: text/plain, Size: 5844 bytes --]
On Fri, 31 Aug 2018 21:53:11 +0300
Numan Demirdöğen <if.gnu.linux@gmail.com> wrote:
>If I put laptop to suspend or hibernate by closing lid, power
>manager or any other method and then I resume/wake up laptop, keyboard
>is not responding. My laptop is a Sony Vaio VPCEH2F1E.
>
>Steps to produce bug:
>1. Boot
>2. Put laptop to sleep
>3. Resume
>
>What I expect to happen: Keyboard responds to key press.
>What happens: Keyboard does not respond but mouse and trackball are
>working.
>
>git bisect point 9d659ae14b545c4296e812c70493bfdc999b5c1c as the first
>bad commit.
>
>Bad commit link:
>https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git/commit/?id=9d659ae14b545c4296e812c70493bfdc999b5c1c
>
> Link to actual bug report:
>https://bugzilla.kernel.org/show_bug.cgi?id=195471
>
>awk -f ver_linux
>Linux korsan 4.18.5-arch1-1-ARCH #1 SMP PREEMPT Fri Aug 24 12:48:58
>UTC 2018 x86_64 GNU/Linux GNU C 8.2.0
>GNU Make 4.2.1
>Binutils 2.31.1
>Util-linux 2.32.1
>Mount 2.32.1
>Module-init-tools 25
>E2fsprogs 1.44.4
>Jfsutils 1.1.15
>Reiserfsprogs 3.6.27
>Xfsprogs 4.17.0
>Pcmciautils 018
>Linux C Library 2.28
>Dynamic linker (ldd) 2.28
>Linux C++ Library 6.0.25
>Procps 3.3.15
>Kbd 2.0.4
>Console-tools 2.0.4
>Sh-utils 8.29
>Udev 239
>Wireless-tools 30
>Modules Loaded ac agpgart ahci arc4 ath ath3k ath9k
>ath9k_common ath9k_hw atkbd battery bluetooth bpfilter ccm cdrom
>cfg80211 coretemp crc16 crc32c_generic crc32c_intel crc32_pclmul
>crct10dif_pclmul cryptd drm drm_kms_helper ecdh_generic ehci_hcd
>ehci_pci evdev ext4 fb_sys_fops fscrypto fuse ghash_clmulni_intel
>gpio_ich hid hid_generic i2c_algo_bit i2c_i801 i8042 i915 input_leds
>intel_cstate intel_gtt intel_powerclamp intel_rapl intel_rapl_perf
>intel_uncore iptable_filter iptable_mangle iptable_nat ip_tables
>irqbypass iTCO_vendor_support iTCO_wdt jbd2 kvm kvm_intel led_class
>libahci libata libcrc32c libps2 lpc_ich mac80211 mac_hid mbcache mei
>mei_me mousedev msr nf_conntrack nf_conntrack_ipv4 nf_defrag_ipv4
>nf_nat nf_nat_ipv4 pcc_cpufreq psmouse rfkill rtc_cmos scsi_mod sd_mod
>serio serio_raw snd snd_hda_codec snd_hda_codec_conexant
>snd_hda_codec_generic snd_hda_codec_hdmi snd_hda_core snd_hda_intel
>snd_hwdep snd_pcm snd_timer sony_laptop soundcore sr_mod syscopyarea
>sysfillrect sysimgblt usb_common usbcore usbhid x86_pkg_temp_thermal
>x_tables
>
>dmesg | grep i8042
>[ 0.574078] i8042: PNP: PS/2 Controller [PNP0303:PS2K,PNP0f13:PS2M]
>at 0x60,0x64 irq 1,12 [ 0.575936] serio: i8042 KBD port at
>0x60,0x64 irq 1 [ 0.576143] serio: i8042 AUX port at 0x60,0x64 irq
>12 [ 0.618880] input: AT Translated Set 2 keyboard
>as /devices/platform/i8042/serio0/input/input3 [ 11.248435] input:
>AlpsPS/2 ALPS GlidePoint as /devices/platform/i8042/serio1/input/input5
>
>cat /proc/interrupts
> CPU0 CPU1 CPU2 CPU3
> 0: 8 0 0 0 IO-APIC
> 2-edge timer 1: 0 0 0 10286
> IO-APIC 1-edge i8042 8: 0 0
> 0 1 IO-APIC 8-edge rtc0 9: 0
> 9479 0 0 IO-APIC 9-fasteoi acpi 12:
> 0 0 370114 0 IO-APIC 12-edge i8042
> 16: 197457 0 0 0 IO-APIC
> 16-fasteoi ehci_hcd:usb1, ath9k 19: 0 0
> 0 0 IO-APIC 19-fasteoi i801_smbus 23:
> 0 0 71055 0 IO-APIC 23-fasteoi
> ehci_hcd:usb2 24: 0 74549 0 0
> PCI-MSI 512000-edge ahci[0000:00:1f.2] 25: 0
> 14 0 0 PCI-MSI 360448-edge mei_me
> 26: 0 0 138870 0 PCI-MSI
> 32768-edge i915 27: 0 0 0
> 330 PCI-MSI 442368-edge snd_hda_intel:card0
>NMI: 24 22 25 21 Non-maskable
>interrupts LOC: 534734 446934 603337 440320 Local
>timer interrupts SPU: 0 0 0 0
>Spurious interrupts PMI: 24 22 25 21
>Performance monitoring interrupts IWI: 26 12
>43115 22 IRQ work interrupts RTR: 0
>0 0 0 APIC ICR read retries RES: 95282
>76970 60242 46409 Rescheduling interrupts CAL:
>66746 75300 70554 69119 Function call interrupts
>TLB: 50929 54528 51413 48017 TLB shootdowns
>TRM: 0 0 0 0 Thermal event
>interrupts THR: 0 0 0 0
>Threshold APIC interrupts DFR: 0 0
>0 0 Deferred Error APIC interrupts MCE: 0
>0 0 0 Machine check exceptions MCP:
>18 19 19 19 Machine check polls
>HYP: 0 0 0 0 Hypervisor callback
>interrupts HRE: 0 0 0 0 Hyper-V
>reenlightenment interrupts HVS: 0 0
>0 0 Hyper-V stimer0 interrupts ERR: 0
>MIS: 0 PIN: 0 0 0 0
>Posted-interrupt notification event NPI: 0
>0 0 0 Nested posted-interrupt event PIW:
>0 0 0 0 Posted-interrupt wakeup event
>
>P.S: My native language is not English.
>
Hi,
I am forwarding this e-mail which describes a problem related to
suspend/hibernate at the advise of Pavel Machek.
--
Numan Demirdöğen
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH] Input: synaptics - avoid using uninitialized variable when probing
From: Peter Hutterer @ 2018-10-19 5:46 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input, Benjamin Tissoires, linux-kernel
In-Reply-To: <20181017001443.GA232819@dtor-ws>
On Tue, Oct 16, 2018 at 05:14:43PM -0700, Dmitry Torokhov wrote:
> synaptics_detect() does not check whether sending commands to the
> device succeeds and instead relies on getting unique data from the
> device. Let's make sure we seed entire buffer with zeroes to make sure
> we not use garbage on stack that just happen to be 0x47.
>
> Reported-by: syzbot+13cb3b01d0784e4ffc3f@syzkaller.appspotmail.com
> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
doh, was just about to send out the same patch.
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Cheers,
Peter
> ---
> drivers/input/mouse/synaptics.c | 4 +---
> 1 file changed, 1 insertion(+), 3 deletions(-)
>
> diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
> index 55d33500d55e..5e85f3cca867 100644
> --- a/drivers/input/mouse/synaptics.c
> +++ b/drivers/input/mouse/synaptics.c
> @@ -99,9 +99,7 @@ static int synaptics_mode_cmd(struct psmouse *psmouse, u8 mode)
> int synaptics_detect(struct psmouse *psmouse, bool set_properties)
> {
> struct ps2dev *ps2dev = &psmouse->ps2dev;
> - u8 param[4];
> -
> - param[0] = 0;
> + u8 param[4] = { 0 };
>
> ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
> ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
> --
> 2.19.1.331.ge82ca0e54c-goog
>
>
> --
> Dmitry
^ permalink raw reply
* Re: [PATCH] Input: pm8941-pwrkey - Add pms405 pwrkey support
From: Dmitry Torokhov @ 2018-10-19 0:01 UTC (permalink / raw)
To: Vinod, Rob Herring
Cc: Bjorn Andersson, Mark Rutland, linux-input, devicetree,
linux-kernel
In-Reply-To: <20181018052437.GW2400@vkoul-mobl>
On Thu, Oct 18, 2018 at 10:54:37AM +0530, Vinod wrote:
> On 19-09-18, 18:49, Bjorn Andersson wrote:
> > From: Vinod Koul <vkoul@kernel.org>
> >
> > Update the binding and driver for pms405 pwrkey.
>
> Rob, Dmitry
>
> Gentle reminder for this patch...
>
> > Signed-off-by: Vinod Koul <vkoul@kernel.org>
> > Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> > ---
> > Documentation/devicetree/bindings/input/qcom,pm8941-pwrkey.txt | 1 +
> > drivers/input/misc/pm8941-pwrkey.c | 1 +
> > 2 files changed, 2 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/input/qcom,pm8941-pwrkey.txt b/Documentation/devicetree/bindings/input/qcom,pm8941-pwrkey.txt
> > index 34ab5763f494..736fba3bad54 100644
> > --- a/Documentation/devicetree/bindings/input/qcom,pm8941-pwrkey.txt
> > +++ b/Documentation/devicetree/bindings/input/qcom,pm8941-pwrkey.txt
> > @@ -8,6 +8,7 @@ PROPERTIES
> > Definition: must be one of:
> > "qcom,pm8941-pwrkey"
> > "qcom,pm8941-resin"
> > + "qcom,pms405-pwrkey"
> >
> > - reg:
> > Usage: required
> > diff --git a/drivers/input/misc/pm8941-pwrkey.c b/drivers/input/misc/pm8941-pwrkey.c
> > index 48153e0ca19a..fccf63263c1c 100644
> > --- a/drivers/input/misc/pm8941-pwrkey.c
> > +++ b/drivers/input/misc/pm8941-pwrkey.c
> > @@ -317,6 +317,7 @@ static const struct pm8941_data resin_data = {
> > static const struct of_device_id pm8941_pwr_key_id_table[] = {
> > { .compatible = "qcom,pm8941-pwrkey", .data = &pwrkey_data },
> > { .compatible = "qcom,pm8941-resin", .data = &resin_data },
> > + { .compatible = "qcom,pms405-pwrkey", .data = &pwrkey_data },
I am sure I asked this question before (in context of a different
driver), but why do we need this compatible if we already have
pm8941-pwrkey compatible? Isn't pms405-pwrkey compatible with
pm8941-pwrkey as far as power key block goes? In which cases do we need
new compatibles and when can we reuse existing ones? Rob?
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v2 5/8] dt-bindings: input: touchscreen: sx8654: add sx8650 to comatibles
From: Rob Herring @ 2018-10-18 20:35 UTC (permalink / raw)
Cc: dmitry.torokhov, robh+dt, mark.rutland, linux-input, devicetree,
linux-kernel, Richard Leitner
In-Reply-To: <20181017125116.20077-6-richard.leitner@skidata.com>
On Wed, 17 Oct 2018 14:51:13 +0200, Richard Leitner wrote:
> As the sx8650 is quite similar to the sx8654 support for it will be
> added in the driver. Therefore add it to the compatibles.
>
> Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
> ---
> Documentation/devicetree/bindings/input/touchscreen/sx8654.txt | 1 +
> 1 file changed, 1 insertion(+)
>
Reviewed-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* Re: [PATCH v2 3/8] dt-bindings: input: touchscreen: sx8654: add compatible models
From: Rob Herring @ 2018-10-18 20:35 UTC (permalink / raw)
Cc: dmitry.torokhov, robh+dt, mark.rutland, linux-input, devicetree,
linux-kernel, Richard Leitner
In-Reply-To: <20181017125116.20077-4-richard.leitner@skidata.com>
On Wed, 17 Oct 2018 14:51:11 +0200, Richard Leitner wrote:
> As the sx865[456] share the same datasheet and differ only in the
> presence of a "capacitive proximity detection circuit" and a "haptics
> motor driver for LRA/ERM" add them to the compatbiles. As the driver
> doesn't implement these features it should be no problem.
>
> Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
> ---
> Documentation/devicetree/bindings/input/touchscreen/sx8654.txt | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
Reviewed-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* Re: [PATCH v2 1/8] dt-bindings: input: touchscreen: sx8654: add reset-gpio property
From: Rob Herring @ 2018-10-18 20:34 UTC (permalink / raw)
Cc: dmitry.torokhov, robh+dt, mark.rutland, linux-input, devicetree,
linux-kernel, Richard Leitner
In-Reply-To: <20181017125116.20077-2-richard.leitner@skidata.com>
On Wed, 17 Oct 2018 14:51:09 +0200, Richard Leitner wrote:
> Document the reset-gpio property for the sx8654 touchscreen controller
> driver.
>
> Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
> ---
> Documentation/devicetree/bindings/input/touchscreen/sx8654.txt | 4 ++++
> 1 file changed, 4 insertions(+)
>
Reviewed-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* Re: [PATCH] Input: uinput - fix Spectre v1 vulnerability
From: Dmitry Torokhov @ 2018-10-18 20:07 UTC (permalink / raw)
To: One Thousand Gnomes
Cc: Gustavo A. R. Silva, linux-input@vger.kernel.org, lkml
In-Reply-To: <20181018204344.4c135203@alans-desktop>
On Thu, Oct 18, 2018 at 12:43 PM Alan Cox <gnomes@lxorguk.ukuu.org.uk> wrote:
>
> On Tue, 16 Oct 2018 20:12:43 +0200
> "Gustavo A. R. Silva" <gustavo@embeddedor.com> wrote:
>
> > On 10/16/18 8:09 PM, Dmitry Torokhov wrote:
> >
> > >
> > > /dev/uinput
> >
> > I've got it. This explains it all. :)
> >
> > > must be 0600, or accessible to equally privileged user, or you'll be opening your system to much mischief.
>
> Still a correct change.
>
> CAP_SYS_RAWIO is not the same as being root, especially in a container.
Giving access to uinput in an unprivileged container is nutty as well.
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH] Input: uinput - fix Spectre v1 vulnerability
From: Alan Cox @ 2018-10-18 19:43 UTC (permalink / raw)
To: Gustavo A. R. Silva; +Cc: Dmitry Torokhov, linux-input, linux-kernel
In-Reply-To: <2856297d-9af0-e005-f926-e9596d437fad@embeddedor.com>
On Tue, 16 Oct 2018 20:12:43 +0200
"Gustavo A. R. Silva" <gustavo@embeddedor.com> wrote:
> On 10/16/18 8:09 PM, Dmitry Torokhov wrote:
>
> >
> > /dev/uinput
>
> I've got it. This explains it all. :)
>
> > must be 0600, or accessible to equally privileged user, or you'll be opening your system to much mischief.
Still a correct change.
CAP_SYS_RAWIO is not the same as being root, especially in a container.
Alan
^ permalink raw reply
* Re: [PATCH v4 1/8] dt-bindings: mfd: document stpmic1
From: Rob Herring @ 2018-10-18 18:47 UTC (permalink / raw)
Cc: dmitry.torokhov@gmail.com, robh+dt@kernel.org,
mark.rutland@arm.com, lee.jones@linaro.org, lgirdwood@gmail.com,
broonie@kernel.org, wim@linux-watchdog.org, linux@roeck-us.net,
linux-input@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org,
benjamin.gaignard@linaro.org, eballetbo@gmail.com,
Pascal PAILLET-LME
In-Reply-To: <1539853324-29051-2-git-send-email-p.paillet@st.com>
On Thu, 18 Oct 2018 09:02:11 +0000, Pascal PAILLET-LME wrote:
> From: pascal paillet <p.paillet@st.com>
>
> stpmic1 is a pmic from STMicroelectronics. The STPMIC1 integrates 10
> regulators , 3 switches, a watchdog and an input for a power on key.
>
> Signed-off-by: pascal paillet <p.paillet@st.com>
> ---
> changes in v4:
> * remove interrupt-parent description
> * pmic1@33 renamed to pmic@33
> * fix indentation
>
> .../devicetree/bindings/mfd/st,stpmic1.txt | 131 +++++++++++++++++++++
> include/dt-bindings/mfd/st,stpmic1.h | 46 ++++++++
> 2 files changed, 177 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/mfd/st,stpmic1.txt
> create mode 100644 include/dt-bindings/mfd/st,stpmic1.h
>
Reviewed-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* Re: [PATCH v4 6/8] input: stpmic1: add stpmic1 onkey driver
From: dmitry.torokhov @ 2018-10-18 18:12 UTC (permalink / raw)
To: Pascal PAILLET-LME, lee.jones
Cc: robh+dt@kernel.org, mark.rutland@arm.com, lgirdwood@gmail.com,
broonie@kernel.org, wim@linux-watchdog.org, linux@roeck-us.net,
linux-input@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org,
benjamin.gaignard@linaro.org, eballetbo@gmail.com
In-Reply-To: <1539853324-29051-7-git-send-email-p.paillet@st.com>
On Thu, Oct 18, 2018 at 09:02:13AM +0000, Pascal PAILLET-LME wrote:
> From: pascal paillet <p.paillet@st.com>
>
> The stpmic1 pmic is able to manage an onkey button. This driver exposes
> the stpmic1 onkey as an input device. It can also be configured to
> shut-down the power supplies on a long key-press with an adjustable
> duration.
>
> Signed-off-by: pascal paillet <p.paillet@st.com>
OK, so this has dependency on linux/mfd/stpmic1.h and therefore I expect
it will go in through Lee's tree.
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> ---
> changes in v4:
> * remove remove function
> * merge stpmic1_onkey_dt_params() in probe function
> * suppresse struct pmic_onkey_config
> * rename PONKEY_PU_ACTIVE to PONKEY_PU_INACTIVE
>
> drivers/input/misc/Kconfig | 11 +++
> drivers/input/misc/Makefile | 2 +
> drivers/input/misc/stpmic1_onkey.c | 197 +++++++++++++++++++++++++++++++++++++
> 3 files changed, 210 insertions(+)
> create mode 100644 drivers/input/misc/stpmic1_onkey.c
>
> diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
> index ca59a2b..279fb02 100644
> --- a/drivers/input/misc/Kconfig
> +++ b/drivers/input/misc/Kconfig
> @@ -851,4 +851,15 @@ config INPUT_SC27XX_VIBRA
> To compile this driver as a module, choose M here. The module will
> be called sc27xx_vibra.
>
> +config INPUT_STPMIC1_ONKEY
> + tristate "STPMIC1 PMIC Onkey support"
> + depends on MFD_STPMIC1
> + help
> + Say Y to enable support of onkey embedded into STPMIC1 PMIC. onkey
> + can be used to wakeup from low power modes and force a shut-down on
> + long press.
> +
> + To compile this driver as a module, choose M here: the
> + module will be called stpmic1_onkey.
> +
> endif
> diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
> index 9d0f9d1..1b44202 100644
> --- a/drivers/input/misc/Makefile
> +++ b/drivers/input/misc/Makefile
> @@ -71,6 +71,7 @@ obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
> obj-$(CONFIG_INPUT_SIRFSOC_ONKEY) += sirfsoc-onkey.o
> obj-$(CONFIG_INPUT_SOC_BUTTON_ARRAY) += soc_button_array.o
> obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o
> +obj-$(CONFIG_INPUT_STPMIC1_ONKEY) += stpmic1_onkey.o
> obj-$(CONFIG_INPUT_TPS65218_PWRBUTTON) += tps65218-pwrbutton.o
> obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o
> obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o
> @@ -81,3 +82,4 @@ obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o
> obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o
> obj-$(CONFIG_INPUT_YEALINK) += yealink.o
> obj-$(CONFIG_INPUT_IDEAPAD_SLIDEBAR) += ideapad_slidebar.o
> +
> diff --git a/drivers/input/misc/stpmic1_onkey.c b/drivers/input/misc/stpmic1_onkey.c
> new file mode 100644
> index 0000000..6a7f08b
> --- /dev/null
> +++ b/drivers/input/misc/stpmic1_onkey.c
> @@ -0,0 +1,197 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (C) STMicroelectronics 2018
> +// Author: Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
> +
> +#include <linux/input.h>
> +#include <linux/interrupt.h>
> +#include <linux/mfd/stpmic1.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/property.h>
> +#include <linux/regmap.h>
> +
> +/**
> + * struct stpmic1_onkey - OnKey data
> + * @input_dev: pointer to input device
> + * @irq_falling: irq that we are hooked on to
> + * @irq_rising: irq that we are hooked on to
> + */
> +struct stpmic1_onkey {
> + struct input_dev *input_dev;
> + int irq_falling;
> + int irq_rising;
> +};
> +
> +static irqreturn_t onkey_falling_irq(int irq, void *ponkey)
> +{
> + struct stpmic1_onkey *onkey = ponkey;
> + struct input_dev *input_dev = onkey->input_dev;
> +
> + input_report_key(input_dev, KEY_POWER, 1);
> + pm_wakeup_event(input_dev->dev.parent, 0);
> + input_sync(input_dev);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t onkey_rising_irq(int irq, void *ponkey)
> +{
> + struct stpmic1_onkey *onkey = ponkey;
> + struct input_dev *input_dev = onkey->input_dev;
> +
> + input_report_key(input_dev, KEY_POWER, 0);
> + pm_wakeup_event(input_dev->dev.parent, 0);
> + input_sync(input_dev);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int stpmic1_onkey_probe(struct platform_device *pdev)
> +{
> + struct stpmic1 *pmic = dev_get_drvdata(pdev->dev.parent);
> + struct device *dev = &pdev->dev;
> + struct input_dev *input_dev;
> + struct stpmic1_onkey *onkey;
> + unsigned int val, reg = 0;
> + int error;
> +
> + onkey = devm_kzalloc(dev, sizeof(*onkey), GFP_KERNEL);
> + if (!onkey)
> + return -ENOMEM;
> +
> + onkey->irq_falling = platform_get_irq_byname(pdev, "onkey-falling");
> + if (onkey->irq_falling < 0) {
> + dev_err(dev, "failed: request IRQ onkey-falling %d\n",
> + onkey->irq_falling);
> + return onkey->irq_falling;
> + }
> +
> + onkey->irq_rising = platform_get_irq_byname(pdev, "onkey-rising");
> + if (onkey->irq_rising < 0) {
> + dev_err(dev, "failed: request IRQ onkey-rising %d\n",
> + onkey->irq_rising);
> + return onkey->irq_rising;
> + }
> +
> + if (!device_property_read_u32(dev, "power-off-time-sec", &val)) {
> + if ((val > 0) && (val <= 16)) {
> + dev_dbg(dev, "power-off-time=%d seconds\n", val);
> + reg |= PONKEY_PWR_OFF;
> + reg |= ((16 - val) & PONKEY_TURNOFF_TIMER_MASK);
> + } else {
> + dev_err(dev, "power-off-time-sec out of range\n");
> + return -EINVAL;
> + }
> + }
> +
> + if (device_property_present(dev, "st,onkey-clear-cc-flag"))
> + reg |= PONKEY_CC_FLAG_CLEAR;
> +
> + error = regmap_update_bits(pmic->regmap, PKEY_TURNOFF_CR,
> + PONKEY_TURNOFF_MASK, reg);
> + if (error) {
> + dev_err(dev, "PKEY_TURNOFF_CR write failed: %d\n", error);
> + return error;
> + }
> +
> + if (device_property_present(dev, "st,onkey-pu-inactive")) {
> + error = regmap_update_bits(pmic->regmap, PADS_PULL_CR,
> + PONKEY_PU_INACTIVE,
> + PONKEY_PU_INACTIVE);
> + if (error) {
> + dev_err(dev, "ONKEY Pads configuration failed: %d\n", error);
> + return error;
> + }
> + }
> +
> + input_dev = devm_input_allocate_device(dev);
> + if (!input_dev) {
> + dev_err(dev, "Can't allocate Pwr Onkey Input Device\n");
> + return -ENOMEM;
> + }
> +
> + input_dev->name = "pmic_onkey";
> + input_dev->phys = "pmic_onkey/input0";
> +
> + input_set_capability(input_dev, EV_KEY, KEY_POWER);
> +
> + onkey->input_dev = input_dev;
> +
> + /* interrupt is nested in a thread */
> + error = devm_request_threaded_irq(dev, onkey->irq_falling, NULL,
> + onkey_falling_irq, IRQF_ONESHOT,
> + dev_name(dev), onkey);
> + if (error) {
> + dev_err(dev, "Can't get IRQ Onkey Falling: %d\n", error);
> + return error;
> + }
> +
> + error = devm_request_threaded_irq(dev, onkey->irq_rising, NULL,
> + onkey_rising_irq, IRQF_ONESHOT,
> + dev_name(dev), onkey);
> + if (error) {
> + dev_err(dev, "Can't get IRQ Onkey Rising: %d\n", error);
> + return error;
> + }
> +
> + error = input_register_device(input_dev);
> + if (error) {
> + dev_err(dev, "Can't register power button: %d\n", error);
> + return error;
> + }
> +
> + platform_set_drvdata(pdev, onkey);
> + device_init_wakeup(dev, true);
> +
> + return 0;
> +}
> +
> +static int __maybe_unused stpmic1_onkey_suspend(struct device *dev)
> +{
> + struct platform_device *pdev = to_platform_device(dev);
> + struct stpmic1_onkey *onkey = platform_get_drvdata(pdev);
> +
> + if (device_may_wakeup(dev)) {
> + enable_irq_wake(onkey->irq_falling);
> + enable_irq_wake(onkey->irq_rising);
> + }
> + return 0;
> +}
> +
> +static int __maybe_unused stpmic1_onkey_resume(struct device *dev)
> +{
> + struct platform_device *pdev = to_platform_device(dev);
> + struct stpmic1_onkey *onkey = platform_get_drvdata(pdev);
> +
> + if (device_may_wakeup(dev)) {
> + disable_irq_wake(onkey->irq_falling);
> + disable_irq_wake(onkey->irq_rising);
> + }
> + return 0;
> +}
> +
> +static SIMPLE_DEV_PM_OPS(stpmic1_onkey_pm,
> + stpmic1_onkey_suspend,
> + stpmic1_onkey_resume);
> +
> +static const struct of_device_id of_stpmic1_onkey_match[] = {
> + { .compatible = "st,stpmic1-onkey" },
> + { },
> +};
> +
> +MODULE_DEVICE_TABLE(of, of_stpmic1_onkey_match);
> +
> +static struct platform_driver stpmic1_onkey_driver = {
> + .probe = stpmic1_onkey_probe,
> + .driver = {
> + .name = "stpmic1_onkey",
> + .of_match_table = of_match_ptr(of_stpmic1_onkey_match),
> + .pm = &stpmic1_onkey_pm,
> + },
> +};
> +module_platform_driver(stpmic1_onkey_driver);
> +
> +MODULE_DESCRIPTION("Onkey driver for STPMIC1");
> +MODULE_AUTHOR("Pascal Paillet <p.paillet@st.com>");
> +MODULE_LICENSE("GPL v2");
> --
> 1.9.1
--
Dmitry
^ permalink raw reply
* Re: [PATCH v4 8/8] watchdog: stpmic1: add stpmic1 watchdog driver
From: Guenter Roeck @ 2018-10-18 13:34 UTC (permalink / raw)
To: Pascal PAILLET-LME, dmitry.torokhov@gmail.com, robh+dt@kernel.org,
mark.rutland@arm.com, lee.jones@linaro.org, lgirdwood@gmail.com,
broonie@kernel.org, wim@linux-watchdog.org,
linux-input@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org,
benjamin.gaignard@linaro.org, eballetbo@gmail.com
In-Reply-To: <1539853324-29051-9-git-send-email-p.paillet@st.com>
On 10/18/2018 02:02 AM, Pascal PAILLET-LME wrote:
> From: pascal paillet <p.paillet@st.com>
>
> The stpmic1 PMIC embeds a watchdog which is disabled by default. As soon
> as the watchdog is started, it must be refreshed periodically otherwise
> the PMIC goes off.
>
> Signed-off-by: pascal paillet <p.paillet@st.com>
> ---
> changes in v4:
> * fix stop watchdog function
> * Kconfig: fix grammar issue
>
> drivers/watchdog/Kconfig | 12 ++++
> drivers/watchdog/Makefile | 1 +
> drivers/watchdog/stpmic1_wdt.c | 139 +++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 152 insertions(+)
> create mode 100644 drivers/watchdog/stpmic1_wdt.c
>
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index 5ea8909..6d2ffef 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -806,6 +806,18 @@ config STM32_WATCHDOG
> To compile this driver as a module, choose M here: the
> module will be called stm32_iwdg.
>
> +config STPMIC1_WATCHDOG
> + tristate "STPMIC1 PMIC watchdog support"
> + depends on MFD_STPMIC1
> + select WATCHDOG_CORE
> + help
> + Say Y here to include watchdog support embedded into STPMIC1 PMIC.
> + If the watchdog timer expires, stpmic1 will shut down all its power
> + supplies.
> +
> + To compile this driver as a module, choose M here: the
> + module will be called spmic1_wdt.
> +
> config UNIPHIER_WATCHDOG
> tristate "UniPhier watchdog support"
> depends on ARCH_UNIPHIER || COMPILE_TEST
> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> index bf92e7b..2649cf3 100644
> --- a/drivers/watchdog/Makefile
> +++ b/drivers/watchdog/Makefile
> @@ -217,3 +217,4 @@ obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
> obj-$(CONFIG_MENF21BMC_WATCHDOG) += menf21bmc_wdt.o
> obj-$(CONFIG_MENZ069_WATCHDOG) += menz69_wdt.o
> obj-$(CONFIG_RAVE_SP_WATCHDOG) += rave-sp-wdt.o
> +obj-$(CONFIG_STPMIC1_WATCHDOG) += stpmic1_wdt.o
> diff --git a/drivers/watchdog/stpmic1_wdt.c b/drivers/watchdog/stpmic1_wdt.c
> new file mode 100644
> index 0000000..a6cbc27
> --- /dev/null
> +++ b/drivers/watchdog/stpmic1_wdt.c
> @@ -0,0 +1,139 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (C) STMicroelectronics 2018
> +// Author: Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
> +
> +#include <linux/kernel.h>
> +#include <linux/mfd/stpmic1.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/of.h>
> +#include <linux/regmap.h>
> +#include <linux/slab.h>
> +#include <linux/watchdog.h>
> +
> +/* WATCHDOG CONTROL REGISTER bit */
> +#define WDT_START BIT(0)
> +#define WDT_PING BIT(1)
> +#define WDT_START_MASK BIT(0)
> +#define WDT_PING_MASK BIT(1)
> +#define WDT_STOP 0
> +
> +#define PMIC_WDT_MIN_TIMEOUT 1
> +#define PMIC_WDT_MAX_TIMEOUT 256
> +#define PMIC_WDT_DEFAULT_TIMEOUT 30
> +
> +static bool nowayout = WATCHDOG_NOWAYOUT;
> +module_param(nowayout, bool, 0);
> +MODULE_PARM_DESC(nowayout,
> + "Watchdog cannot be stopped once started (default="
> + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
> +
> +struct stpmic1_wdt {
> + struct stpmic1 *pmic;
> + struct watchdog_device wdtdev;
> +};
> +
> +static int pmic_wdt_start(struct watchdog_device *wdd)
> +{
> + struct stpmic1_wdt *wdt = watchdog_get_drvdata(wdd);
> +
> + return regmap_update_bits(wdt->pmic->regmap,
> + WCHDG_CR, WDT_START_MASK, WDT_START);
> +}
> +
> +static int pmic_wdt_stop(struct watchdog_device *wdd)
> +{
> + struct stpmic1_wdt *wdt = watchdog_get_drvdata(wdd);
> +
> + return regmap_update_bits(wdt->pmic->regmap,
> + WCHDG_CR, WDT_START_MASK, WDT_STOP);
> +}
> +
> +static int pmic_wdt_ping(struct watchdog_device *wdd)
> +{
> + struct stpmic1_wdt *wdt = watchdog_get_drvdata(wdd);
> +
> + return regmap_update_bits(wdt->pmic->regmap,
> + WCHDG_CR, WDT_PING_MASK, WDT_PING);
> +}
> +
> +static int pmic_wdt_set_timeout(struct watchdog_device *wdd,
> + unsigned int timeout)
> +{
> + struct stpmic1_wdt *wdt = watchdog_get_drvdata(wdd);
> +
> + wdd->timeout = timeout;
> + /* timeout is equal to register value + 1 */
> + return regmap_write(wdt->pmic->regmap, WCHDG_TIMER_CR, timeout - 1);
> +}
> +
> +static const struct watchdog_info pmic_watchdog_info = {
> + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
> + .identity = "STPMIC1 PMIC Watchdog",
> +};
> +
> +static const struct watchdog_ops pmic_watchdog_ops = {
> + .owner = THIS_MODULE,
> + .start = pmic_wdt_start,
> + .stop = pmic_wdt_stop,
> + .ping = pmic_wdt_ping,
> + .set_timeout = pmic_wdt_set_timeout,
> +};
> +
> +static int pmic_wdt_probe(struct platform_device *pdev)
> +{
> + int ret;
> + struct stpmic1 *pmic;
> + struct stpmic1_wdt *wdt;
> +
> + if (!pdev->dev.parent)
> + return -EINVAL;
> +
> + pmic = dev_get_drvdata(pdev->dev.parent);
> + if (!pmic)
> + return -EINVAL;
> +
> + wdt = devm_kzalloc(&pdev->dev, sizeof(struct stpmic1_wdt), GFP_KERNEL);
> + if (!wdt)
> + return -ENOMEM;
> +
> + wdt->pmic = pmic;
> +
> + wdt->wdtdev.info = &pmic_watchdog_info;
> + wdt->wdtdev.ops = &pmic_watchdog_ops;
> + wdt->wdtdev.min_timeout = PMIC_WDT_MIN_TIMEOUT;
> + wdt->wdtdev.max_timeout = PMIC_WDT_MAX_TIMEOUT;
Sorry I missed that earlier: You'll also want to set wdtdev.parent.
Thanks,
Guenter
> +
> + wdt->wdtdev.timeout = PMIC_WDT_DEFAULT_TIMEOUT;
> + watchdog_init_timeout(&wdt->wdtdev, 0, &pdev->dev);
> +
> + watchdog_set_nowayout(&wdt->wdtdev, nowayout);
> + watchdog_set_drvdata(&wdt->wdtdev, wdt);
> +
> + ret = devm_watchdog_register_device(&pdev->dev, &wdt->wdtdev);
> + if (ret)
> + return ret;
> +
> + dev_dbg(wdt->pmic->dev, "PMIC Watchdog driver probed\n");
> + return 0;
> +}
> +
> +static const struct of_device_id of_pmic_wdt_match[] = {
> + { .compatible = "st,stpmic1-wdt" },
> + { },
> +};
> +
> +MODULE_DEVICE_TABLE(of, of_pmic_wdt_match);
> +
> +static struct platform_driver stpmic1_wdt_driver = {
> + .probe = pmic_wdt_probe,
> + .driver = {
> + .name = "stpmic1-wdt",
> + .of_match_table = of_pmic_wdt_match,
> + },
> +};
> +module_platform_driver(stpmic1_wdt_driver);
> +
> +MODULE_DESCRIPTION("Watchdog driver for STPMIC1 device");
> +MODULE_AUTHOR("Pascal Paillet <p.paillet@st.com>");
> +MODULE_LICENSE("GPL v2");
>
^ permalink raw reply
* Re: [PATCH] HID: quirks: fix support for Apple Magic Keyboards
From: Benjamin Tissoires @ 2018-10-18 13:04 UTC (permalink / raw)
To: gregkh; +Cc: ncopa, 3.8+, open list:HID CORE LAYER, Jiri Kosina, seobrien
In-Reply-To: <20181017165510.GA7468@kroah.com>
On Wed, Oct 17, 2018 at 6:55 PM Greg KH <gregkh@linuxfoundation.org> wrote:
>
> On Wed, Oct 17, 2018 at 06:49:16PM +0200, Benjamin Tissoires wrote:
> > On Wed, Oct 17, 2018 at 5:55 PM Natanael Copa <ncopa@alpinelinux.org> wrote:
> > >
> > > On Wed, 17 Oct 2018 16:59:15 +0200
> > > Benjamin Tissoires <benjamin.tissoires@redhat.com> wrote:
> > >
> > > > Hi Natanael,
> > > >
> > > > On Wed, Oct 17, 2018 at 4:52 PM Natanael Copa <ncopa@alpinelinux.org> wrote:
> > > > >
> > > > > Commit ee3454924370 ("HID: add support for Apple Magic Keyboards") added
> > > > > support for the Magic Keyboard over Bluetooth, but did not add the
> > > > > BT_VENDOR_ID_APPLE to hid-quirks. Fix this so hid-apple driver is used
> > > > > over hid-generic.
> > > > >
> > > > > This fixes the Fn key, which does not work at all with hid-generic.
> > > > >
> > > > > Fixes: ee3454924370 ("HID: add support for Apple Magic Keyboards")
> > > > > Bugzilla-id: https://bugzilla.kernel.org/show_bug.cgi?id=99881
> > > > > Signed-off-by: Natanael Copa <ncopa@alpinelinux.org>
> > > > > ---
> > > > > This should be backported to stable too.
> > > > >
> > > > > drivers/hid/hid-quirks.c | 3 +++
> > > > > 1 file changed, 3 insertions(+)
> > > > >
> > > > > diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
> > > > > index 249d49b6b16c..a3b3aecf8628 100644
> > > > > --- a/drivers/hid/hid-quirks.c
> > > > > +++ b/drivers/hid/hid-quirks.c
> > > > > @@ -270,6 +270,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
> > > > > { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) },
> > > > > { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS) },
> > > > > { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_ANSI) },
> > > > > + { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_ANSI) },
> > > > > + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_ANSI) },
> > > > > + { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_ANSI) },
> > > >
> > > > NACK, this should not be required with kernels v4.17+ IIRC.
> > > >
> > > > If it doesn't work on a recent kernel, please raise the issue, but I
> > > > am actually chasing down the new inclusions of these when we add new
> > > > device support.
> > >
> > > Fair enough. I think it may be needed for 4.14.y kernels though, to fix
> > > commit b6cc0ba2cbf4 (HID: add support for Apple Magic Keyboards).
> > >
> > > Fn key did not work without this patch on 4.14.76 for me.
> >
> > Right, b6cc0ba2cbf4 has been added to 4.14.75 and is not working
> > because tweaking hid_have_special_driver[] is not required in current
> > kernels anymore.
> >
> > @stable folks, would it be possible to take this patch in the v4.9 and
> > v4.14 trees? It can't go into Linus' tree, but I'd be glad to give my
> > Acked-by for a stable backport.
>
> Sure, if you resend it in a format that I can apply it in, with the text
> saying why this is not applicable to newer kernel versions.
>
Thanks Greg.
Natanel, can you resend this patch with the explanation to stable@ and
Cc me so I can give my Ack?
Cheers,
Benjamin
^ permalink raw reply
* Re: [PATCH 3/5] dt-bindings: add more optional properties for elan_i2c touchpads
From: Rob Herring @ 2018-10-18 13:04 UTC (permalink / raw)
To: Benjamin Tissoires
Cc: Hans de Goede, Dmitry Torokhov, KT Liao, linux-input,
linux-kernel@vger.kernel.org, devicetree
In-Reply-To: <CAO-hwJ+z6YdnLdbzeh-7f99cBBjHfbLKLzKo-fQQaC_W8bt_Uw@mail.gmail.com>
On Thu, Oct 18, 2018 at 3:10 AM Benjamin Tissoires
<benjamin.tissoires@redhat.com> wrote:
>
> On Wed, Oct 17, 2018 at 10:15 PM Rob Herring <robh@kernel.org> wrote:
> >
> > On Fri, Oct 12, 2018 at 04:24:11PM +0200, Benjamin Tissoires wrote:
> > > Some new touchpads IC are connected through PS/2 and I2C. On some of these
> > > new IC, the I2C part doesn't have all of the information available.
> > > We need to be able to forward the touchpad parameters from PS/2 and
> > > thus, we need those new optional properties.
> > >
> > > Link: https://bugzilla.redhat.com/show_bug.cgi?id=1628715
> > > Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
> > > ---
> > > Documentation/devicetree/bindings/input/elan_i2c.txt | 8 ++++++++
> > > 1 file changed, 8 insertions(+)
> > >
> > > diff --git a/Documentation/devicetree/bindings/input/elan_i2c.txt b/Documentation/devicetree/bindings/input/elan_i2c.txt
> > > index 797607460735..ace6bcb0b4eb 100644
> > > --- a/Documentation/devicetree/bindings/input/elan_i2c.txt
> > > +++ b/Documentation/devicetree/bindings/input/elan_i2c.txt
> > > @@ -13,6 +13,14 @@ Optional properties:
> > > pinctrl binding [1]).
> > > - vcc-supply: a phandle for the regulator supplying 3.3V power.
> > > - elan,trackpoint: touchpad can support a trackpoint (boolean)
> > > +- elan,clickpad: touchpad is a clickpad (the entire surface is a button)
> >
> > > +- elan,max_x: the maximum reported value on the X axis
> > > +- elan,max_y: the maximum reported value on the Y axis
> > > +- elan,min_x: the minimum reported value on the X axis
> > > +- elan,min_y: the minimum reported value on the Y axis
> > > +- elan,x_res: the resolution of the X axis (in units per mm)
> > > +- elan,y_res: the resolution of the Y axis (in units per mm)
> > > +- elan,width: max reported width of a blob
> >
> > Can't we use standard touchscreen properties here? (Yes, I get this is a
> > touchpad, not touchscreen).
>
> Hey Rob,
>
> Well, there is that (it's a touchpad driver) and we can't also really
> use the of_touchscreen.c implementation.
> If both concerns are not an issue, we can then move the [min/max/res]
> properties to the touchscreen ones.
Neither is problem for me. Bindings don't have to map 1:1 to kernel code.
> Regarding 'elan,width', this is something missing from the standard ts
> properties, and AFAICT, this controls the maximum reported
> width/height of a touch.
> I should probably rename them to max_width, max_height.
Sure, just use '-' rather than '_' in property names.
> Hans, do you think we should add such properties to of_touchscreen.c
> too? (the width/height ones)
>
> Cheers,
> Benjamin
^ permalink raw reply
* [PATCH v4 8/8] watchdog: stpmic1: add stpmic1 watchdog driver
From: Pascal PAILLET-LME @ 2018-10-18 9:02 UTC (permalink / raw)
To: dmitry.torokhov@gmail.com, robh+dt@kernel.org,
mark.rutland@arm.com, lee.jones@linaro.org, lgirdwood@gmail.com,
broonie@kernel.org, wim@linux-watchdog.org, linux@roeck-us.net,
linux-input@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org,
benjamin.gaignard@linaro.org, eballetbo@gmail.com
Cc: Pascal PAILLET-LME
In-Reply-To: <1539853324-29051-1-git-send-email-p.paillet@st.com>
From: pascal paillet <p.paillet@st.com>
The stpmic1 PMIC embeds a watchdog which is disabled by default. As soon
as the watchdog is started, it must be refreshed periodically otherwise
the PMIC goes off.
Signed-off-by: pascal paillet <p.paillet@st.com>
---
changes in v4:
* fix stop watchdog function
* Kconfig: fix grammar issue
drivers/watchdog/Kconfig | 12 ++++
drivers/watchdog/Makefile | 1 +
drivers/watchdog/stpmic1_wdt.c | 139 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 152 insertions(+)
create mode 100644 drivers/watchdog/stpmic1_wdt.c
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 5ea8909..6d2ffef 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -806,6 +806,18 @@ config STM32_WATCHDOG
To compile this driver as a module, choose M here: the
module will be called stm32_iwdg.
+config STPMIC1_WATCHDOG
+ tristate "STPMIC1 PMIC watchdog support"
+ depends on MFD_STPMIC1
+ select WATCHDOG_CORE
+ help
+ Say Y here to include watchdog support embedded into STPMIC1 PMIC.
+ If the watchdog timer expires, stpmic1 will shut down all its power
+ supplies.
+
+ To compile this driver as a module, choose M here: the
+ module will be called spmic1_wdt.
+
config UNIPHIER_WATCHDOG
tristate "UniPhier watchdog support"
depends on ARCH_UNIPHIER || COMPILE_TEST
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index bf92e7b..2649cf3 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -217,3 +217,4 @@ obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
obj-$(CONFIG_MENF21BMC_WATCHDOG) += menf21bmc_wdt.o
obj-$(CONFIG_MENZ069_WATCHDOG) += menz69_wdt.o
obj-$(CONFIG_RAVE_SP_WATCHDOG) += rave-sp-wdt.o
+obj-$(CONFIG_STPMIC1_WATCHDOG) += stpmic1_wdt.o
diff --git a/drivers/watchdog/stpmic1_wdt.c b/drivers/watchdog/stpmic1_wdt.c
new file mode 100644
index 0000000..a6cbc27
--- /dev/null
+++ b/drivers/watchdog/stpmic1_wdt.c
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) STMicroelectronics 2018
+// Author: Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
+
+#include <linux/kernel.h>
+#include <linux/mfd/stpmic1.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/watchdog.h>
+
+/* WATCHDOG CONTROL REGISTER bit */
+#define WDT_START BIT(0)
+#define WDT_PING BIT(1)
+#define WDT_START_MASK BIT(0)
+#define WDT_PING_MASK BIT(1)
+#define WDT_STOP 0
+
+#define PMIC_WDT_MIN_TIMEOUT 1
+#define PMIC_WDT_MAX_TIMEOUT 256
+#define PMIC_WDT_DEFAULT_TIMEOUT 30
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout,
+ "Watchdog cannot be stopped once started (default="
+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+struct stpmic1_wdt {
+ struct stpmic1 *pmic;
+ struct watchdog_device wdtdev;
+};
+
+static int pmic_wdt_start(struct watchdog_device *wdd)
+{
+ struct stpmic1_wdt *wdt = watchdog_get_drvdata(wdd);
+
+ return regmap_update_bits(wdt->pmic->regmap,
+ WCHDG_CR, WDT_START_MASK, WDT_START);
+}
+
+static int pmic_wdt_stop(struct watchdog_device *wdd)
+{
+ struct stpmic1_wdt *wdt = watchdog_get_drvdata(wdd);
+
+ return regmap_update_bits(wdt->pmic->regmap,
+ WCHDG_CR, WDT_START_MASK, WDT_STOP);
+}
+
+static int pmic_wdt_ping(struct watchdog_device *wdd)
+{
+ struct stpmic1_wdt *wdt = watchdog_get_drvdata(wdd);
+
+ return regmap_update_bits(wdt->pmic->regmap,
+ WCHDG_CR, WDT_PING_MASK, WDT_PING);
+}
+
+static int pmic_wdt_set_timeout(struct watchdog_device *wdd,
+ unsigned int timeout)
+{
+ struct stpmic1_wdt *wdt = watchdog_get_drvdata(wdd);
+
+ wdd->timeout = timeout;
+ /* timeout is equal to register value + 1 */
+ return regmap_write(wdt->pmic->regmap, WCHDG_TIMER_CR, timeout - 1);
+}
+
+static const struct watchdog_info pmic_watchdog_info = {
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+ .identity = "STPMIC1 PMIC Watchdog",
+};
+
+static const struct watchdog_ops pmic_watchdog_ops = {
+ .owner = THIS_MODULE,
+ .start = pmic_wdt_start,
+ .stop = pmic_wdt_stop,
+ .ping = pmic_wdt_ping,
+ .set_timeout = pmic_wdt_set_timeout,
+};
+
+static int pmic_wdt_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct stpmic1 *pmic;
+ struct stpmic1_wdt *wdt;
+
+ if (!pdev->dev.parent)
+ return -EINVAL;
+
+ pmic = dev_get_drvdata(pdev->dev.parent);
+ if (!pmic)
+ return -EINVAL;
+
+ wdt = devm_kzalloc(&pdev->dev, sizeof(struct stpmic1_wdt), GFP_KERNEL);
+ if (!wdt)
+ return -ENOMEM;
+
+ wdt->pmic = pmic;
+
+ wdt->wdtdev.info = &pmic_watchdog_info;
+ wdt->wdtdev.ops = &pmic_watchdog_ops;
+ wdt->wdtdev.min_timeout = PMIC_WDT_MIN_TIMEOUT;
+ wdt->wdtdev.max_timeout = PMIC_WDT_MAX_TIMEOUT;
+
+ wdt->wdtdev.timeout = PMIC_WDT_DEFAULT_TIMEOUT;
+ watchdog_init_timeout(&wdt->wdtdev, 0, &pdev->dev);
+
+ watchdog_set_nowayout(&wdt->wdtdev, nowayout);
+ watchdog_set_drvdata(&wdt->wdtdev, wdt);
+
+ ret = devm_watchdog_register_device(&pdev->dev, &wdt->wdtdev);
+ if (ret)
+ return ret;
+
+ dev_dbg(wdt->pmic->dev, "PMIC Watchdog driver probed\n");
+ return 0;
+}
+
+static const struct of_device_id of_pmic_wdt_match[] = {
+ { .compatible = "st,stpmic1-wdt" },
+ { },
+};
+
+MODULE_DEVICE_TABLE(of, of_pmic_wdt_match);
+
+static struct platform_driver stpmic1_wdt_driver = {
+ .probe = pmic_wdt_probe,
+ .driver = {
+ .name = "stpmic1-wdt",
+ .of_match_table = of_pmic_wdt_match,
+ },
+};
+module_platform_driver(stpmic1_wdt_driver);
+
+MODULE_DESCRIPTION("Watchdog driver for STPMIC1 device");
+MODULE_AUTHOR("Pascal Paillet <p.paillet@st.com>");
+MODULE_LICENSE("GPL v2");
--
1.9.1
^ permalink raw reply related
* [PATCH v4 7/8] dt-bindings: watchdog: document stpmic1 pmic watchdog
From: Pascal PAILLET-LME @ 2018-10-18 9:02 UTC (permalink / raw)
To: dmitry.torokhov@gmail.com, robh+dt@kernel.org,
mark.rutland@arm.com, lee.jones@linaro.org, lgirdwood@gmail.com,
broonie@kernel.org, wim@linux-watchdog.org, linux@roeck-us.net,
linux-input@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org,
benjamin.gaignard@linaro.org, eballetbo@gmail.com
Cc: Pascal PAILLET-LME
In-Reply-To: <1539853324-29051-1-git-send-email-p.paillet@st.com>
From: pascal paillet <p.paillet@st.com>
The stpmic1 PMIC embeds a watchdog which is disabled by default.
In case of watchdog, the PMIC goes off.
Signed-off-by: pascal paillet <p.paillet@st.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
Documentation/devicetree/bindings/watchdog/st,stpmic1-wdt.txt | 11 +++++++++++
1 file changed, 11 insertions(+)
create mode 100644 Documentation/devicetree/bindings/watchdog/st,stpmic1-wdt.txt
diff --git a/Documentation/devicetree/bindings/watchdog/st,stpmic1-wdt.txt b/Documentation/devicetree/bindings/watchdog/st,stpmic1-wdt.txt
new file mode 100644
index 0000000..7cc1407
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/st,stpmic1-wdt.txt
@@ -0,0 +1,11 @@
+STMicroelectronics STPMIC1 Watchdog
+
+Required properties:
+
+- compatible : should be "st,stpmic1-wdt"
+
+Example:
+
+watchdog {
+ compatible = "st,stpmic1-wdt";
+};
--
1.9.1
^ permalink raw reply related
* [PATCH v4 6/8] input: stpmic1: add stpmic1 onkey driver
From: Pascal PAILLET-LME @ 2018-10-18 9:02 UTC (permalink / raw)
To: dmitry.torokhov@gmail.com, robh+dt@kernel.org,
mark.rutland@arm.com, lee.jones@linaro.org, lgirdwood@gmail.com,
broonie@kernel.org, wim@linux-watchdog.org, linux@roeck-us.net,
linux-input@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org,
benjamin.gaignard@linaro.org, eballetbo@gmail.com
Cc: Pascal PAILLET-LME
In-Reply-To: <1539853324-29051-1-git-send-email-p.paillet@st.com>
From: pascal paillet <p.paillet@st.com>
The stpmic1 pmic is able to manage an onkey button. This driver exposes
the stpmic1 onkey as an input device. It can also be configured to
shut-down the power supplies on a long key-press with an adjustable
duration.
Signed-off-by: pascal paillet <p.paillet@st.com>
---
changes in v4:
* remove remove function
* merge stpmic1_onkey_dt_params() in probe function
* suppresse struct pmic_onkey_config
* rename PONKEY_PU_ACTIVE to PONKEY_PU_INACTIVE
drivers/input/misc/Kconfig | 11 +++
drivers/input/misc/Makefile | 2 +
drivers/input/misc/stpmic1_onkey.c | 197 +++++++++++++++++++++++++++++++++++++
3 files changed, 210 insertions(+)
create mode 100644 drivers/input/misc/stpmic1_onkey.c
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index ca59a2b..279fb02 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -851,4 +851,15 @@ config INPUT_SC27XX_VIBRA
To compile this driver as a module, choose M here. The module will
be called sc27xx_vibra.
+config INPUT_STPMIC1_ONKEY
+ tristate "STPMIC1 PMIC Onkey support"
+ depends on MFD_STPMIC1
+ help
+ Say Y to enable support of onkey embedded into STPMIC1 PMIC. onkey
+ can be used to wakeup from low power modes and force a shut-down on
+ long press.
+
+ To compile this driver as a module, choose M here: the
+ module will be called stpmic1_onkey.
+
endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 9d0f9d1..1b44202 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -71,6 +71,7 @@ obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
obj-$(CONFIG_INPUT_SIRFSOC_ONKEY) += sirfsoc-onkey.o
obj-$(CONFIG_INPUT_SOC_BUTTON_ARRAY) += soc_button_array.o
obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o
+obj-$(CONFIG_INPUT_STPMIC1_ONKEY) += stpmic1_onkey.o
obj-$(CONFIG_INPUT_TPS65218_PWRBUTTON) += tps65218-pwrbutton.o
obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o
obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o
@@ -81,3 +82,4 @@ obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o
obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o
obj-$(CONFIG_INPUT_YEALINK) += yealink.o
obj-$(CONFIG_INPUT_IDEAPAD_SLIDEBAR) += ideapad_slidebar.o
+
diff --git a/drivers/input/misc/stpmic1_onkey.c b/drivers/input/misc/stpmic1_onkey.c
new file mode 100644
index 0000000..6a7f08b
--- /dev/null
+++ b/drivers/input/misc/stpmic1_onkey.c
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) STMicroelectronics 2018
+// Author: Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
+
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/stpmic1.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+
+/**
+ * struct stpmic1_onkey - OnKey data
+ * @input_dev: pointer to input device
+ * @irq_falling: irq that we are hooked on to
+ * @irq_rising: irq that we are hooked on to
+ */
+struct stpmic1_onkey {
+ struct input_dev *input_dev;
+ int irq_falling;
+ int irq_rising;
+};
+
+static irqreturn_t onkey_falling_irq(int irq, void *ponkey)
+{
+ struct stpmic1_onkey *onkey = ponkey;
+ struct input_dev *input_dev = onkey->input_dev;
+
+ input_report_key(input_dev, KEY_POWER, 1);
+ pm_wakeup_event(input_dev->dev.parent, 0);
+ input_sync(input_dev);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t onkey_rising_irq(int irq, void *ponkey)
+{
+ struct stpmic1_onkey *onkey = ponkey;
+ struct input_dev *input_dev = onkey->input_dev;
+
+ input_report_key(input_dev, KEY_POWER, 0);
+ pm_wakeup_event(input_dev->dev.parent, 0);
+ input_sync(input_dev);
+
+ return IRQ_HANDLED;
+}
+
+static int stpmic1_onkey_probe(struct platform_device *pdev)
+{
+ struct stpmic1 *pmic = dev_get_drvdata(pdev->dev.parent);
+ struct device *dev = &pdev->dev;
+ struct input_dev *input_dev;
+ struct stpmic1_onkey *onkey;
+ unsigned int val, reg = 0;
+ int error;
+
+ onkey = devm_kzalloc(dev, sizeof(*onkey), GFP_KERNEL);
+ if (!onkey)
+ return -ENOMEM;
+
+ onkey->irq_falling = platform_get_irq_byname(pdev, "onkey-falling");
+ if (onkey->irq_falling < 0) {
+ dev_err(dev, "failed: request IRQ onkey-falling %d\n",
+ onkey->irq_falling);
+ return onkey->irq_falling;
+ }
+
+ onkey->irq_rising = platform_get_irq_byname(pdev, "onkey-rising");
+ if (onkey->irq_rising < 0) {
+ dev_err(dev, "failed: request IRQ onkey-rising %d\n",
+ onkey->irq_rising);
+ return onkey->irq_rising;
+ }
+
+ if (!device_property_read_u32(dev, "power-off-time-sec", &val)) {
+ if ((val > 0) && (val <= 16)) {
+ dev_dbg(dev, "power-off-time=%d seconds\n", val);
+ reg |= PONKEY_PWR_OFF;
+ reg |= ((16 - val) & PONKEY_TURNOFF_TIMER_MASK);
+ } else {
+ dev_err(dev, "power-off-time-sec out of range\n");
+ return -EINVAL;
+ }
+ }
+
+ if (device_property_present(dev, "st,onkey-clear-cc-flag"))
+ reg |= PONKEY_CC_FLAG_CLEAR;
+
+ error = regmap_update_bits(pmic->regmap, PKEY_TURNOFF_CR,
+ PONKEY_TURNOFF_MASK, reg);
+ if (error) {
+ dev_err(dev, "PKEY_TURNOFF_CR write failed: %d\n", error);
+ return error;
+ }
+
+ if (device_property_present(dev, "st,onkey-pu-inactive")) {
+ error = regmap_update_bits(pmic->regmap, PADS_PULL_CR,
+ PONKEY_PU_INACTIVE,
+ PONKEY_PU_INACTIVE);
+ if (error) {
+ dev_err(dev, "ONKEY Pads configuration failed: %d\n", error);
+ return error;
+ }
+ }
+
+ input_dev = devm_input_allocate_device(dev);
+ if (!input_dev) {
+ dev_err(dev, "Can't allocate Pwr Onkey Input Device\n");
+ return -ENOMEM;
+ }
+
+ input_dev->name = "pmic_onkey";
+ input_dev->phys = "pmic_onkey/input0";
+
+ input_set_capability(input_dev, EV_KEY, KEY_POWER);
+
+ onkey->input_dev = input_dev;
+
+ /* interrupt is nested in a thread */
+ error = devm_request_threaded_irq(dev, onkey->irq_falling, NULL,
+ onkey_falling_irq, IRQF_ONESHOT,
+ dev_name(dev), onkey);
+ if (error) {
+ dev_err(dev, "Can't get IRQ Onkey Falling: %d\n", error);
+ return error;
+ }
+
+ error = devm_request_threaded_irq(dev, onkey->irq_rising, NULL,
+ onkey_rising_irq, IRQF_ONESHOT,
+ dev_name(dev), onkey);
+ if (error) {
+ dev_err(dev, "Can't get IRQ Onkey Rising: %d\n", error);
+ return error;
+ }
+
+ error = input_register_device(input_dev);
+ if (error) {
+ dev_err(dev, "Can't register power button: %d\n", error);
+ return error;
+ }
+
+ platform_set_drvdata(pdev, onkey);
+ device_init_wakeup(dev, true);
+
+ return 0;
+}
+
+static int __maybe_unused stpmic1_onkey_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct stpmic1_onkey *onkey = platform_get_drvdata(pdev);
+
+ if (device_may_wakeup(dev)) {
+ enable_irq_wake(onkey->irq_falling);
+ enable_irq_wake(onkey->irq_rising);
+ }
+ return 0;
+}
+
+static int __maybe_unused stpmic1_onkey_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct stpmic1_onkey *onkey = platform_get_drvdata(pdev);
+
+ if (device_may_wakeup(dev)) {
+ disable_irq_wake(onkey->irq_falling);
+ disable_irq_wake(onkey->irq_rising);
+ }
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(stpmic1_onkey_pm,
+ stpmic1_onkey_suspend,
+ stpmic1_onkey_resume);
+
+static const struct of_device_id of_stpmic1_onkey_match[] = {
+ { .compatible = "st,stpmic1-onkey" },
+ { },
+};
+
+MODULE_DEVICE_TABLE(of, of_stpmic1_onkey_match);
+
+static struct platform_driver stpmic1_onkey_driver = {
+ .probe = stpmic1_onkey_probe,
+ .driver = {
+ .name = "stpmic1_onkey",
+ .of_match_table = of_match_ptr(of_stpmic1_onkey_match),
+ .pm = &stpmic1_onkey_pm,
+ },
+};
+module_platform_driver(stpmic1_onkey_driver);
+
+MODULE_DESCRIPTION("Onkey driver for STPMIC1");
+MODULE_AUTHOR("Pascal Paillet <p.paillet@st.com>");
+MODULE_LICENSE("GPL v2");
--
1.9.1
^ permalink raw reply related
* [PATCH v4 5/8] dt-bindings: input: document stpmic1 pmic onkey
From: Pascal PAILLET-LME @ 2018-10-18 9:02 UTC (permalink / raw)
To: dmitry.torokhov@gmail.com, robh+dt@kernel.org,
mark.rutland@arm.com, lee.jones@linaro.org, lgirdwood@gmail.com,
broonie@kernel.org, wim@linux-watchdog.org, linux@roeck-us.net,
linux-input@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org,
benjamin.gaignard@linaro.org, eballetbo@gmail.com
Cc: Pascal PAILLET-LME
In-Reply-To: <1539853324-29051-1-git-send-email-p.paillet@st.com>
From: pascal paillet <p.paillet@st.com>
The stpmic1 pmic is able to manage an onkey button. It can be configured
to shut-down the power supplies on a long key-press with an adjustable
duration.
Signed-off-by: pascal paillet <p.paillet@st.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
changes in v4:
* remove interrupt-parent description
* remove st,onkey-pwroff-enabled and power-off-time-sec properties
.../devicetree/bindings/input/st,stpmic1-onkey.txt | 28 ++++++++++++++++++++++
1 file changed, 28 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/st,stpmic1-onkey.txt
diff --git a/Documentation/devicetree/bindings/input/st,stpmic1-onkey.txt b/Documentation/devicetree/bindings/input/st,stpmic1-onkey.txt
new file mode 100644
index 0000000..4494613
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/st,stpmic1-onkey.txt
@@ -0,0 +1,28 @@
+STMicroelectronics STPMIC1 Onkey
+
+Required properties:
+
+- compatible = "st,stpmic1-onkey";
+- interrupts: interrupt line to use
+- interrupt-names = "onkey-falling", "onkey-rising"
+ onkey-falling: happens when onkey is pressed; IT_PONKEY_F of pmic
+ onkey-rising: happens when onkey is released; IT_PONKEY_R of pmic
+
+Optional properties:
+
+- st,onkey-clear-cc-flag: onkey is able power on after an
+ over-current shutdown event.
+- st,onkey-pu-inactive: onkey pull up is not active
+- power-off-time-sec: Duration in seconds which the key should be kept
+ pressed for device to power off automatically (from 1 to 16 seconds).
+ see See Documentation/devicetree/bindings/input/keys.txt
+
+Example:
+
+onkey {
+ compatible = "st,stpmic1-onkey";
+ interrupt-parent = <&pmic>;
+ interrupts = <IT_PONKEY_F 0>,<IT_PONKEY_R 1>;
+ interrupt-names = "onkey-falling", "onkey-rising";
+ power-off-time-sec = <10>;
+};
--
1.9.1
^ permalink raw reply related
* [PATCH v4 3/8] dt-bindings: regulator: document stpmic1 pmic regulators
From: Pascal PAILLET-LME @ 2018-10-18 9:02 UTC (permalink / raw)
To: dmitry.torokhov@gmail.com, robh+dt@kernel.org,
mark.rutland@arm.com, lee.jones@linaro.org, lgirdwood@gmail.com,
broonie@kernel.org, wim@linux-watchdog.org, linux@roeck-us.net,
linux-input@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org,
benjamin.gaignard@linaro.org, eballetbo@gmail.com
Cc: Pascal PAILLET-LME
In-Reply-To: <1539853324-29051-1-git-send-email-p.paillet@st.com>
From: pascal paillet <p.paillet@st.com>
The STPMIC1 regulators supply power to the application processor as well as
to the external system peripherals such as DDR, Flash memories and system
devices.
Signed-off-by: pascal paillet <p.paillet@st.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
changes in v4: nothing
.../bindings/regulator/st,stpmic1-regulator.txt | 68 ++++++++++++++++++++++
1 file changed, 68 insertions(+)
create mode 100644 Documentation/devicetree/bindings/regulator/st,stpmic1-regulator.txt
diff --git a/Documentation/devicetree/bindings/regulator/st,stpmic1-regulator.txt b/Documentation/devicetree/bindings/regulator/st,stpmic1-regulator.txt
new file mode 100644
index 0000000..a3f4762
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/st,stpmic1-regulator.txt
@@ -0,0 +1,68 @@
+STMicroelectronics STPMIC1 Voltage regulators
+
+Regulator Nodes are optional depending on needs.
+
+Available Regulators in STPMIC1 device are:
+ - buck1 for Buck BUCK1
+ - buck2 for Buck BUCK2
+ - buck3 for Buck BUCK3
+ - buck4 for Buck BUCK4
+ - ldo1 for LDO LDO1
+ - ldo2 for LDO LDO2
+ - ldo3 for LDO LDO3
+ - ldo4 for LDO LDO4
+ - ldo5 for LDO LDO5
+ - ldo6 for LDO LDO6
+ - vref_ddr for LDO Vref DDR
+ - boost for Buck BOOST
+ - pwr_sw1 for VBUS_OTG switch
+ - pwr_sw2 for SW_OUT switch
+
+Switches are fixed voltage regulators with only enable/disable capability.
+
+Optional properties:
+- st,mask-reset: mask reset for this regulator: the regulator configuration
+ is maintained during pmic reset.
+- regulator-pull-down: enable high pull down
+ if not specified light pull down is used
+- regulator-over-current-protection:
+ if set, all regulators are switched off in case of over-current detection
+ on this regulator,
+ if not set, the driver only sends an over-current event.
+- interrupt-parent: phandle to the parent interrupt controller
+- interrupts: index of current limit detection interrupt
+- <regulator>-supply: phandle to the parent supply/regulator node
+ each regulator supply can be described except vref_ddr.
+
+Example:
+regulators {
+ compatible = "st,stpmic1-regulators";
+
+ ldo6-supply = <&v3v3>;
+
+ vdd_core: buck1 {
+ regulator-name = "vdd_core";
+ interrupts = <IT_CURLIM_BUCK1 0>;
+ interrupt-parent = <&pmic>;
+ st,mask-reset;
+ regulator-pull-down;
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ v3v3: buck4 {
+ regulator-name = "v3v3";
+ interrupts = <IT_CURLIM_BUCK4 0>;
+ interrupt-parent = <&mypmic>;
+
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ v1v8: ldo6 {
+ regulator-name = "v1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-over-current-protection;
+ };
+};
--
1.9.1
^ permalink raw reply related
* [PATCH v4 4/8] regulator: stpmic1: add stpmic1 regulator driver
From: Pascal PAILLET-LME @ 2018-10-18 9:02 UTC (permalink / raw)
To: dmitry.torokhov@gmail.com, robh+dt@kernel.org,
mark.rutland@arm.com, lee.jones@linaro.org, lgirdwood@gmail.com,
broonie@kernel.org, wim@linux-watchdog.org, linux@roeck-us.net,
linux-input@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org,
benjamin.gaignard@linaro.org, eballetbo@gmail.com
Cc: Pascal PAILLET-LME
In-Reply-To: <1539853324-29051-1-git-send-email-p.paillet@st.com>
From: pascal paillet <p.paillet@st.com>
The stpmic1 PMIC embeds several regulators and switches with
different capabilities.
Signed-off-by: pascal paillet <p.paillet@st.com>
---
changes in v4: nothing
drivers/regulator/Kconfig | 12 +
drivers/regulator/Makefile | 1 +
drivers/regulator/stpmic1_regulator.c | 674 ++++++++++++++++++++++++++++++++++
3 files changed, 687 insertions(+)
create mode 100644 drivers/regulator/stpmic1_regulator.c
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 6e96ef1..026d480 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -803,6 +803,18 @@ config REGULATOR_STM32_VREFBUF
This driver can also be built as a module. If so, the module
will be called stm32-vrefbuf.
+config REGULATOR_STPMIC1
+ tristate "STMicroelectronics STPMIC1 PMIC Regulators"
+ depends on MFD_STPMIC1
+ help
+ This driver supports STMicroelectronics STPMIC1 PMIC voltage
+ regulators and switches. The STPMIC1 regulators supply power to
+ an application processor as well as to external system
+ peripherals such as DDR, Flash memories and system devices.
+
+ To compile this driver as a module, choose M here: the
+ module will be called stpmic1_regulator.
+
config REGULATOR_TI_ABB
tristate "TI Adaptive Body Bias on-chip LDO"
depends on ARCH_OMAP
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index eac4d79..300bc4c 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -101,6 +101,7 @@ obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
obj-$(CONFIG_REGULATOR_SC2731) += sc2731-regulator.o
obj-$(CONFIG_REGULATOR_SKY81452) += sky81452-regulator.o
obj-$(CONFIG_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o
+obj-$(CONFIG_REGULATOR_STPMIC1) += stpmic1_regulator.o
obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o
obj-$(CONFIG_REGULATOR_SY8106A) += sy8106a-regulator.o
obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o
diff --git a/drivers/regulator/stpmic1_regulator.c b/drivers/regulator/stpmic1_regulator.c
new file mode 100644
index 0000000..96f1808
--- /dev/null
+++ b/drivers/regulator/stpmic1_regulator.c
@@ -0,0 +1,674 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) STMicroelectronics 2018
+// Author: Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
+
+#include <linux/interrupt.h>
+#include <linux/mfd/stpmic1.h>
+#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+
+/**
+ * stpmic1 regulator description
+ * @desc: regulator framework description
+ * @mask_reset_reg: mask reset register address
+ * @mask_reset_mask: mask rank and mask reset register mask
+ * @icc_reg: icc register address
+ * @icc_mask: icc register mask
+ */
+struct stpmic1_regulator_cfg {
+ struct regulator_desc desc;
+ u8 mask_reset_reg;
+ u8 mask_reset_mask;
+ u8 icc_reg;
+ u8 icc_mask;
+};
+
+/**
+ * stpmic1 regulator data: this structure is used as driver data
+ * @regul_id: regulator id
+ * @reg_node: DT node of regulator (unused on non-DT platforms)
+ * @cfg: stpmic specific regulator description
+ * @mask_reset: mask_reset bit value
+ * @irq_curlim: current limit interrupt number
+ * @regmap: point to parent regmap structure
+ */
+struct stpmic1_regulator {
+ unsigned int regul_id;
+ struct device_node *reg_node;
+ struct stpmic1_regulator_cfg *cfg;
+ u8 mask_reset;
+ int irq_curlim;
+ struct regmap *regmap;
+};
+
+static int stpmic1_set_mode(struct regulator_dev *rdev, unsigned int mode);
+static unsigned int stpmic1_get_mode(struct regulator_dev *rdev);
+static int stpmic1_set_icc(struct regulator_dev *rdev);
+static int stpmic1_regulator_parse_dt(void *driver_data);
+static unsigned int stpmic1_map_mode(unsigned int mode);
+
+enum {
+ STPMIC1_BUCK1 = 0,
+ STPMIC1_BUCK2 = 1,
+ STPMIC1_BUCK3 = 2,
+ STPMIC1_BUCK4 = 3,
+ STPMIC1_LDO1 = 4,
+ STPMIC1_LDO2 = 5,
+ STPMIC1_LDO3 = 6,
+ STPMIC1_LDO4 = 7,
+ STPMIC1_LDO5 = 8,
+ STPMIC1_LDO6 = 9,
+ STPMIC1_VREF_DDR = 10,
+ STPMIC1_BOOST = 11,
+ STPMIC1_VBUS_OTG = 12,
+ STPMIC1_SW_OUT = 13,
+};
+
+/* Enable time worst case is 5000mV/(2250uV/uS) */
+#define PMIC_ENABLE_TIME_US 2200
+
+#define STPMIC1_BUCK_MODE_NORMAL 0
+#define STPMIC1_BUCK_MODE_LP BUCK_HPLP_ENABLE_MASK
+
+struct regulator_linear_range buck1_ranges[] = {
+ REGULATOR_LINEAR_RANGE(600000, 0, 30, 25000),
+ REGULATOR_LINEAR_RANGE(1350000, 31, 63, 0),
+};
+
+struct regulator_linear_range buck2_ranges[] = {
+ REGULATOR_LINEAR_RANGE(1000000, 0, 17, 0),
+ REGULATOR_LINEAR_RANGE(1050000, 18, 19, 0),
+ REGULATOR_LINEAR_RANGE(1100000, 20, 21, 0),
+ REGULATOR_LINEAR_RANGE(1150000, 22, 23, 0),
+ REGULATOR_LINEAR_RANGE(1200000, 24, 25, 0),
+ REGULATOR_LINEAR_RANGE(1250000, 26, 27, 0),
+ REGULATOR_LINEAR_RANGE(1300000, 28, 29, 0),
+ REGULATOR_LINEAR_RANGE(1350000, 30, 31, 0),
+ REGULATOR_LINEAR_RANGE(1400000, 32, 33, 0),
+ REGULATOR_LINEAR_RANGE(1450000, 34, 35, 0),
+ REGULATOR_LINEAR_RANGE(1500000, 36, 63, 0),
+};
+
+struct regulator_linear_range buck3_ranges[] = {
+ REGULATOR_LINEAR_RANGE(1000000, 0, 19, 0),
+ REGULATOR_LINEAR_RANGE(1100000, 20, 23, 0),
+ REGULATOR_LINEAR_RANGE(1200000, 24, 27, 0),
+ REGULATOR_LINEAR_RANGE(1300000, 28, 31, 0),
+ REGULATOR_LINEAR_RANGE(1400000, 32, 35, 0),
+ REGULATOR_LINEAR_RANGE(1500000, 36, 55, 100000),
+ REGULATOR_LINEAR_RANGE(3400000, 56, 63, 0),
+
+};
+
+struct regulator_linear_range buck4_ranges[] = {
+ REGULATOR_LINEAR_RANGE(600000, 0, 27, 25000),
+ REGULATOR_LINEAR_RANGE(1300000, 28, 29, 0),
+ REGULATOR_LINEAR_RANGE(1350000, 30, 31, 0),
+ REGULATOR_LINEAR_RANGE(1400000, 32, 33, 0),
+ REGULATOR_LINEAR_RANGE(1450000, 34, 35, 0),
+ REGULATOR_LINEAR_RANGE(1500000, 36, 60, 100000),
+ REGULATOR_LINEAR_RANGE(3900000, 61, 63, 0),
+
+};
+
+struct regulator_linear_range ldo1_ranges[] = {
+ REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
+ REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000),
+ REGULATOR_LINEAR_RANGE(3300000, 25, 31, 0),
+
+};
+
+struct regulator_linear_range ldo2_ranges[] = {
+ REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
+ REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000),
+ REGULATOR_LINEAR_RANGE(3300000, 25, 30, 0),
+
+};
+
+struct regulator_linear_range ldo3_ranges[] = {
+ REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
+ REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000),
+ REGULATOR_LINEAR_RANGE(3300000, 25, 30, 0),
+ /* with index 31 LDO3 is in DDR mode */
+ REGULATOR_LINEAR_RANGE(500000, 31, 31, 0),
+};
+
+struct regulator_linear_range ldo5_ranges[] = {
+ REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
+ REGULATOR_LINEAR_RANGE(1700000, 8, 30, 100000),
+ REGULATOR_LINEAR_RANGE(3900000, 31, 31, 0),
+};
+
+struct regulator_linear_range ldo6_ranges[] = {
+ REGULATOR_LINEAR_RANGE(900000, 0, 24, 100000),
+ REGULATOR_LINEAR_RANGE(3300000, 25, 31, 0),
+};
+
+static struct regulator_ops stpmic1_ldo_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_pull_down = regulator_set_pull_down_regmap,
+ .set_over_current_protection = stpmic1_set_icc,
+};
+
+static struct regulator_ops stpmic1_ldo3_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_iterate,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_pull_down = regulator_set_pull_down_regmap,
+ .get_bypass = regulator_get_bypass_regmap,
+ .set_bypass = regulator_set_bypass_regmap,
+ .set_over_current_protection = stpmic1_set_icc,
+};
+
+static struct regulator_ops stpmic1_ldo4_fixed_regul_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .set_pull_down = regulator_set_pull_down_regmap,
+ .set_over_current_protection = stpmic1_set_icc,
+};
+
+static struct regulator_ops stpmic1_buck_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_pull_down = regulator_set_pull_down_regmap,
+ .set_mode = stpmic1_set_mode,
+ .get_mode = stpmic1_get_mode,
+ .set_over_current_protection = stpmic1_set_icc,
+};
+
+static struct regulator_ops stpmic1_vref_ddr_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .set_pull_down = regulator_set_pull_down_regmap,
+};
+
+static struct regulator_ops stpmic1_switch_regul_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .set_over_current_protection = stpmic1_set_icc,
+};
+
+#define REG_LDO(ids, base) { \
+ .name = #ids, \
+ .id = STPMIC1_##ids, \
+ .n_voltages = 32, \
+ .ops = &stpmic1_ldo_ops, \
+ .linear_ranges = base ## _ranges, \
+ .n_linear_ranges = ARRAY_SIZE(base ## _ranges), \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .vsel_reg = ids##_ACTIVE_CR, \
+ .vsel_mask = LDO_VOLTAGE_MASK, \
+ .enable_reg = ids##_ACTIVE_CR, \
+ .enable_mask = LDO_ENABLE_MASK, \
+ .enable_val = 1, \
+ .disable_val = 0, \
+ .enable_time = PMIC_ENABLE_TIME_US, \
+ .pull_down_reg = ids##_PULL_DOWN_REG, \
+ .pull_down_mask = ids##_PULL_DOWN_MASK, \
+ .supply_name = #base, \
+}
+
+#define REG_LDO3(ids, base) { \
+ .name = #ids, \
+ .id = STPMIC1_##ids, \
+ .n_voltages = 32, \
+ .ops = &stpmic1_ldo3_ops, \
+ .linear_ranges = ldo3_ranges, \
+ .n_linear_ranges = ARRAY_SIZE(ldo3_ranges), \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .vsel_reg = LDO3_ACTIVE_CR, \
+ .vsel_mask = LDO_VOLTAGE_MASK, \
+ .enable_reg = LDO3_ACTIVE_CR, \
+ .enable_mask = LDO_ENABLE_MASK, \
+ .enable_val = 1, \
+ .disable_val = 0, \
+ .enable_time = PMIC_ENABLE_TIME_US, \
+ .bypass_reg = LDO3_ACTIVE_CR, \
+ .bypass_mask = LDO_BYPASS_MASK, \
+ .bypass_val_on = LDO_BYPASS_MASK, \
+ .bypass_val_off = 0, \
+ .pull_down_reg = ids##_PULL_DOWN_REG, \
+ .pull_down_mask = ids##_PULL_DOWN_MASK, \
+ .supply_name = #base, \
+}
+
+#define REG_LDO4(ids, base) { \
+ .name = #ids, \
+ .id = STPMIC1_##ids, \
+ .n_voltages = 1, \
+ .ops = &stpmic1_ldo4_fixed_regul_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = 3300000, \
+ .fixed_uV = 3300000, \
+ .enable_reg = LDO4_ACTIVE_CR, \
+ .enable_mask = LDO_ENABLE_MASK, \
+ .enable_val = 1, \
+ .disable_val = 0, \
+ .enable_time = PMIC_ENABLE_TIME_US, \
+ .pull_down_reg = ids##_PULL_DOWN_REG, \
+ .pull_down_mask = ids##_PULL_DOWN_MASK, \
+ .supply_name = #base, \
+}
+
+#define REG_BUCK(ids, base) { \
+ .name = #ids, \
+ .id = STPMIC1_##ids, \
+ .ops = &stpmic1_buck_ops, \
+ .n_voltages = 64, \
+ .linear_ranges = base ## _ranges, \
+ .n_linear_ranges = ARRAY_SIZE(base ## _ranges), \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .vsel_reg = ids##_ACTIVE_CR, \
+ .vsel_mask = BUCK_VOLTAGE_MASK, \
+ .enable_reg = ids##_ACTIVE_CR, \
+ .enable_mask = BUCK_ENABLE_MASK, \
+ .enable_val = 1, \
+ .disable_val = 0, \
+ .enable_time = PMIC_ENABLE_TIME_US, \
+ .of_map_mode = stpmic1_map_mode, \
+ .pull_down_reg = ids##_PULL_DOWN_REG, \
+ .pull_down_mask = ids##_PULL_DOWN_MASK, \
+ .supply_name = #base, \
+}
+
+#define REG_VREF_DDR(ids, base) { \
+ .name = #ids, \
+ .id = STPMIC1_##ids, \
+ .n_voltages = 1, \
+ .ops = &stpmic1_vref_ddr_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = 500000, \
+ .fixed_uV = 500000, \
+ .enable_reg = VREF_DDR_ACTIVE_CR, \
+ .enable_mask = BUCK_ENABLE_MASK, \
+ .enable_val = 1, \
+ .disable_val = 0, \
+ .enable_time = PMIC_ENABLE_TIME_US, \
+ .pull_down_reg = ids##_PULL_DOWN_REG, \
+ .pull_down_mask = ids##_PULL_DOWN_MASK, \
+ .supply_name = #base, \
+}
+
+#define REG_SWITCH(ids, base, reg, mask, val) { \
+ .name = #ids, \
+ .id = STPMIC1_##ids, \
+ .n_voltages = 1, \
+ .ops = &stpmic1_switch_regul_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = 0, \
+ .fixed_uV = 5000000, \
+ .enable_reg = (reg), \
+ .enable_mask = (mask), \
+ .enable_val = (val), \
+ .disable_val = 0, \
+ .enable_time = PMIC_ENABLE_TIME_US, \
+ .supply_name = #base, \
+}
+
+struct stpmic1_regulator_cfg stpmic1_regulator_cfgs[] = {
+ [STPMIC1_BUCK1] = {
+ .desc = REG_BUCK(BUCK1, buck1),
+ .icc_reg = BUCKS_ICCTO_CR,
+ .icc_mask = BIT(0),
+ .mask_reset_reg = BUCKS_MASK_RESET_CR,
+ .mask_reset_mask = BIT(0),
+ },
+ [STPMIC1_BUCK2] = {
+ .desc = REG_BUCK(BUCK2, buck2),
+ .icc_reg = BUCKS_ICCTO_CR,
+ .icc_mask = BIT(1),
+ .mask_reset_reg = BUCKS_MASK_RESET_CR,
+ .mask_reset_mask = BIT(1),
+ },
+ [STPMIC1_BUCK3] = {
+ .desc = REG_BUCK(BUCK3, buck3),
+ .icc_reg = BUCKS_ICCTO_CR,
+ .icc_mask = BIT(2),
+ .mask_reset_reg = BUCKS_MASK_RESET_CR,
+ .mask_reset_mask = BIT(2),
+ },
+ [STPMIC1_BUCK4] = {
+ .desc = REG_BUCK(BUCK4, buck4),
+ .icc_reg = BUCKS_ICCTO_CR,
+ .icc_mask = BIT(3),
+ .mask_reset_reg = BUCKS_MASK_RESET_CR,
+ .mask_reset_mask = BIT(3),
+ },
+ [STPMIC1_LDO1] = {
+ .desc = REG_LDO(LDO1, ldo1),
+ .icc_reg = LDOS_ICCTO_CR,
+ .icc_mask = BIT(0),
+ .mask_reset_reg = LDOS_MASK_RESET_CR,
+ .mask_reset_mask = BIT(0),
+ },
+ [STPMIC1_LDO2] = {
+ .desc = REG_LDO(LDO2, ldo2),
+ .icc_reg = LDOS_ICCTO_CR,
+ .icc_mask = BIT(1),
+ .mask_reset_reg = LDOS_MASK_RESET_CR,
+ .mask_reset_mask = BIT(1),
+ },
+ [STPMIC1_LDO3] = {
+ .desc = REG_LDO3(LDO3, ldo3),
+ .icc_reg = LDOS_ICCTO_CR,
+ .icc_mask = BIT(2),
+ .mask_reset_reg = LDOS_MASK_RESET_CR,
+ .mask_reset_mask = BIT(2),
+ },
+ [STPMIC1_LDO4] = {
+ .desc = REG_LDO4(LDO4, ldo4),
+ .icc_reg = LDOS_ICCTO_CR,
+ .icc_mask = BIT(3),
+ .mask_reset_reg = LDOS_MASK_RESET_CR,
+ .mask_reset_mask = BIT(3),
+ },
+ [STPMIC1_LDO5] = {
+ .desc = REG_LDO(LDO5, ldo5),
+ .icc_reg = LDOS_ICCTO_CR,
+ .icc_mask = BIT(4),
+ .mask_reset_reg = LDOS_MASK_RESET_CR,
+ .mask_reset_mask = BIT(4),
+ },
+ [STPMIC1_LDO6] = {
+ .desc = REG_LDO(LDO6, ldo6),
+ .icc_reg = LDOS_ICCTO_CR,
+ .icc_mask = BIT(5),
+ .mask_reset_reg = LDOS_MASK_RESET_CR,
+ .mask_reset_mask = BIT(5),
+ },
+ [STPMIC1_VREF_DDR] = {
+ .desc = REG_VREF_DDR(VREF_DDR, vref_ddr),
+ .mask_reset_reg = LDOS_MASK_RESET_CR,
+ .mask_reset_mask = BIT(6),
+ },
+ [STPMIC1_BOOST] = {
+ .desc = REG_SWITCH(BOOST, boost, BST_SW_CR,
+ BOOST_ENABLED,
+ BOOST_ENABLED),
+ .icc_reg = BUCKS_ICCTO_CR,
+ .icc_mask = BIT(6),
+ },
+ [STPMIC1_VBUS_OTG] = {
+ .desc = REG_SWITCH(VBUS_OTG, pwr_sw1, BST_SW_CR,
+ USBSW_OTG_SWITCH_ENABLED,
+ USBSW_OTG_SWITCH_ENABLED),
+ .icc_reg = BUCKS_ICCTO_CR,
+ .icc_mask = BIT(4),
+ },
+ [STPMIC1_SW_OUT] = {
+ .desc = REG_SWITCH(SW_OUT, pwr_sw2, BST_SW_CR,
+ SWIN_SWOUT_ENABLED,
+ SWIN_SWOUT_ENABLED),
+ .icc_reg = BUCKS_ICCTO_CR,
+ .icc_mask = BIT(5),
+ },
+};
+
+static unsigned int stpmic1_map_mode(unsigned int mode)
+{
+ switch (mode) {
+ case STPMIC1_BUCK_MODE_NORMAL:
+ return REGULATOR_MODE_NORMAL;
+ case STPMIC1_BUCK_MODE_LP:
+ return REGULATOR_MODE_STANDBY;
+ default:
+ return -EINVAL;
+ }
+}
+
+static unsigned int stpmic1_get_mode(struct regulator_dev *rdev)
+{
+ int value;
+
+ regmap_read(rdev->regmap, rdev->desc->enable_reg, &value);
+
+ if (value & STPMIC1_BUCK_MODE_LP)
+ return REGULATOR_MODE_STANDBY;
+
+ return REGULATOR_MODE_NORMAL;
+}
+
+static int stpmic1_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+ int value;
+
+ switch (mode) {
+ case REGULATOR_MODE_NORMAL:
+ value = STPMIC1_BUCK_MODE_NORMAL;
+ break;
+ case REGULATOR_MODE_STANDBY:
+ value = STPMIC1_BUCK_MODE_LP;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+ STPMIC1_BUCK_MODE_LP, value);
+}
+
+static int stpmic1_set_icc(struct regulator_dev *rdev)
+{
+ struct stpmic1_regulator *regul = rdev_get_drvdata(rdev);
+
+ /* enable switch off in case of over current */
+ return regmap_update_bits(regul->regmap, regul->cfg->icc_reg,
+ regul->cfg->icc_mask, regul->cfg->icc_mask);
+}
+
+static irqreturn_t stpmic1_curlim_irq_handler(int irq, void *data)
+{
+ struct regulator_dev *rdev = (struct regulator_dev *)data;
+
+ mutex_lock(&rdev->mutex);
+
+ /* Send an overcurrent notification */
+ regulator_notifier_call_chain(rdev,
+ REGULATOR_EVENT_OVER_CURRENT,
+ NULL);
+
+ mutex_unlock(&rdev->mutex);
+
+ return IRQ_HANDLED;
+}
+
+static int stpmic1_regulator_init(struct platform_device *pdev,
+ struct regulator_dev *rdev)
+{
+ struct stpmic1_regulator *regul = rdev_get_drvdata(rdev);
+ int ret = 0;
+
+ /* set mask reset */
+ if (regul->mask_reset && regul->cfg->mask_reset_reg != 0) {
+ ret = regmap_update_bits(regul->regmap,
+ regul->cfg->mask_reset_reg,
+ regul->cfg->mask_reset_mask,
+ regul->cfg->mask_reset_mask);
+ if (ret) {
+ dev_err(&pdev->dev, "set mask reset failed\n");
+ return ret;
+ }
+ }
+
+ /* setup an irq handler for over-current detection */
+ if (regul->irq_curlim > 0) {
+ ret = devm_request_threaded_irq(&pdev->dev,
+ regul->irq_curlim, NULL,
+ stpmic1_curlim_irq_handler,
+ IRQF_ONESHOT | IRQF_SHARED,
+ pdev->name, rdev);
+ if (ret) {
+ dev_err(&pdev->dev, "Request IRQ failed\n");
+ return ret;
+ }
+ }
+ return 0;
+}
+
+#define MATCH(_name, _id) \
+ [STPMIC1_##_id] = { \
+ .name = #_name, \
+ .desc = &stpmic1_regulator_cfgs[STPMIC1_##_id].desc, \
+ }
+
+static struct of_regulator_match stpmic1_regulators_matches[] = {
+ MATCH(buck1, BUCK1),
+ MATCH(buck2, BUCK2),
+ MATCH(buck3, BUCK3),
+ MATCH(buck4, BUCK4),
+ MATCH(ldo1, LDO1),
+ MATCH(ldo2, LDO2),
+ MATCH(ldo3, LDO3),
+ MATCH(ldo4, LDO4),
+ MATCH(ldo5, LDO5),
+ MATCH(ldo6, LDO6),
+ MATCH(vref_ddr, VREF_DDR),
+ MATCH(boost, BOOST),
+ MATCH(pwr_sw1, VBUS_OTG),
+ MATCH(pwr_sw2, SW_OUT),
+};
+
+static int stpmic1_regulator_parse_dt(void *driver_data)
+{
+ struct stpmic1_regulator *regul =
+ (struct stpmic1_regulator *)driver_data;
+
+ if (!regul)
+ return -EINVAL;
+
+ if (of_get_property(regul->reg_node, "st,mask-reset", NULL))
+ regul->mask_reset = 1;
+
+ regul->irq_curlim = of_irq_get(regul->reg_node, 0);
+
+ return 0;
+}
+
+static struct
+regulator_dev *stpmic1_regulator_register(struct platform_device *pdev, int id,
+ struct regulator_init_data *init_data,
+ struct stpmic1_regulator *regul)
+{
+ struct stpmic1 *pmic_dev = dev_get_drvdata(pdev->dev.parent);
+ struct regulator_dev *rdev;
+ struct regulator_config config = {};
+
+ config.dev = &pdev->dev;
+ config.init_data = init_data;
+ config.of_node = stpmic1_regulators_matches[id].of_node;
+ config.regmap = pmic_dev->regmap;
+ config.driver_data = regul;
+
+ regul->regul_id = id;
+ regul->reg_node = config.of_node;
+ regul->cfg = &stpmic1_regulator_cfgs[id];
+ regul->regmap = pmic_dev->regmap;
+
+ rdev = devm_regulator_register(&pdev->dev, ®ul->cfg->desc, &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "failed to register %s regulator\n",
+ regul->cfg->desc.name);
+ }
+
+ return rdev;
+}
+
+static int stpmic1_regulator_probe(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev;
+ struct stpmic1_regulator *regul;
+ struct regulator_init_data *init_data;
+ struct device_node *np;
+ int i, ret;
+
+ np = pdev->dev.of_node;
+
+ ret = of_regulator_match(&pdev->dev, np,
+ stpmic1_regulators_matches,
+ ARRAY_SIZE(stpmic1_regulators_matches));
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "Error in PMIC regulator device tree node");
+ return ret;
+ }
+
+ regul = devm_kzalloc(&pdev->dev, ARRAY_SIZE(stpmic1_regulator_cfgs) *
+ sizeof(struct stpmic1_regulator),
+ GFP_KERNEL);
+ if (!regul)
+ return -ENOMEM;
+
+ for (i = 0; i < ARRAY_SIZE(stpmic1_regulator_cfgs); i++) {
+ /* Parse DT & find regulators to register */
+ init_data = stpmic1_regulators_matches[i].init_data;
+ if (init_data)
+ init_data->regulator_init = &stpmic1_regulator_parse_dt;
+
+ rdev = stpmic1_regulator_register(pdev, i, init_data, regul);
+ if (IS_ERR(rdev))
+ return PTR_ERR(rdev);
+
+ ret = stpmic1_regulator_init(pdev, rdev);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "failed to initialize regulator %d\n", ret);
+ return ret;
+ }
+
+ regul++;
+ }
+
+ dev_dbg(&pdev->dev, "stpmic1_regulator driver probed\n");
+
+ return 0;
+}
+
+static const struct of_device_id of_pmic_regulator_match[] = {
+ { .compatible = "st,stpmic1-regulators" },
+ { },
+};
+
+MODULE_DEVICE_TABLE(of, of_pmic_regulator_match);
+
+static struct platform_driver stpmic1_regulator_driver = {
+ .driver = {
+ .name = "stpmic1-regulator",
+ .of_match_table = of_match_ptr(of_pmic_regulator_match),
+ },
+ .probe = stpmic1_regulator_probe,
+};
+
+module_platform_driver(stpmic1_regulator_driver);
+
+MODULE_DESCRIPTION("STPMIC1 PMIC voltage regulator driver");
+MODULE_AUTHOR("Pascal Paillet <p.paillet@st.com>");
+MODULE_LICENSE("GPL v2");
--
1.9.1
^ permalink raw reply related
* [PATCH v4 2/8] mfd: stpmic1: add stpmic1 driver
From: Pascal PAILLET-LME @ 2018-10-18 9:02 UTC (permalink / raw)
To: dmitry.torokhov@gmail.com, robh+dt@kernel.org,
mark.rutland@arm.com, lee.jones@linaro.org, lgirdwood@gmail.com,
broonie@kernel.org, wim@linux-watchdog.org, linux@roeck-us.net,
linux-input@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org,
benjamin.gaignard@linaro.org, eballetbo@gmail.com
Cc: Pascal PAILLET-LME
In-Reply-To: <1539853324-29051-1-git-send-email-p.paillet@st.com>
From: pascal paillet <p.paillet@st.com>
stpmic1 is a pmic from STMicroelectronics. The STPMIC1 integrates 10
regulators , 3 switches, a watchdog and an input for a power on key.
Signed-off-by: pascal paillet <p.paillet@st.com>
---
changes in v4:
* rename PONKEY_PU_ACTIVE to PONKEY_PU_INACTIVE
drivers/mfd/Kconfig | 13 ++
drivers/mfd/Makefile | 1 +
drivers/mfd/stpmic1.c | 401 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/mfd/stpmic1.h | 212 +++++++++++++++++++++++
4 files changed, 627 insertions(+)
create mode 100644 drivers/mfd/stpmic1.c
create mode 100644 include/linux/mfd/stpmic1.h
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 11841f4..b8dabc7 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1855,6 +1855,19 @@ config MFD_STM32_TIMERS
for PWM and IIO Timer. This driver allow to share the
registers between the others drivers.
+config MFD_STPMIC1
+ tristate "Support for STPMIC1 PMIC"
+ depends on (I2C=y && OF)
+ select REGMAP_I2C
+ select REGMAP_IRQ
+ select MFD_CORE
+ help
+ Support for ST Microelectronics STPMIC1 PMIC. STPMIC1 MFD driver is
+ the core driver for STPMIC1 component that mainly handles interrupts.
+
+ To compile this driver as a module, choose M here: the
+ module will be called stpmic1.
+
menu "Multimedia Capabilities Port drivers"
depends on ARCH_SA1100
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 5856a94..76fff14 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -232,6 +232,7 @@ obj-$(CONFIG_INTEL_SOC_PMIC_CHTDC_TI) += intel_soc_pmic_chtdc_ti.o
obj-$(CONFIG_MFD_MT6397) += mt6397-core.o
obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o
+obj-$(CONFIG_MFD_STPMIC1) += stpmic1.o
obj-$(CONFIG_MFD_SUN4I_GPADC) += sun4i-gpadc.o
obj-$(CONFIG_MFD_STM32_LPTIMER) += stm32-lptimer.o
diff --git a/drivers/mfd/stpmic1.c b/drivers/mfd/stpmic1.c
new file mode 100644
index 0000000..90dfee4
--- /dev/null
+++ b/drivers/mfd/stpmic1.c
@@ -0,0 +1,401 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) STMicroelectronics 2018
+// Author: Pascal Paillet <p.paillet@st.com>
+
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/stpmic1.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/pm_wakeirq.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/mfd/st,stpmic1.h>
+
+#define STPMIC1_MAIN_IRQ 0
+#define STPMIC1_WAKEUP_IRQ 1
+
+static bool stpmic1_reg_readable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case TURN_ON_SR:
+ case TURN_OFF_SR:
+ case ICC_LDO_TURN_OFF_SR:
+ case ICC_BUCK_TURN_OFF_SR:
+ case RREQ_STATE_SR:
+ case VERSION_SR:
+ case SWOFF_PWRCTRL_CR:
+ case PADS_PULL_CR:
+ case BUCKS_PD_CR:
+ case LDO14_PD_CR:
+ case LDO56_VREF_PD_CR:
+ case VBUS_DET_VIN_CR:
+ case PKEY_TURNOFF_CR:
+ case BUCKS_MASK_RANK_CR:
+ case BUCKS_MASK_RESET_CR:
+ case LDOS_MASK_RANK_CR:
+ case LDOS_MASK_RESET_CR:
+ case WCHDG_CR:
+ case WCHDG_TIMER_CR:
+ case BUCKS_ICCTO_CR:
+ case LDOS_ICCTO_CR:
+ case BUCK1_ACTIVE_CR:
+ case BUCK2_ACTIVE_CR:
+ case BUCK3_ACTIVE_CR:
+ case BUCK4_ACTIVE_CR:
+ case VREF_DDR_ACTIVE_CR:
+ case LDO1_ACTIVE_CR:
+ case LDO2_ACTIVE_CR:
+ case LDO3_ACTIVE_CR:
+ case LDO4_ACTIVE_CR:
+ case LDO5_ACTIVE_CR:
+ case LDO6_ACTIVE_CR:
+ case BUCK1_STDBY_CR:
+ case BUCK2_STDBY_CR:
+ case BUCK3_STDBY_CR:
+ case BUCK4_STDBY_CR:
+ case VREF_DDR_STDBY_CR:
+ case LDO1_STDBY_CR:
+ case LDO2_STDBY_CR:
+ case LDO3_STDBY_CR:
+ case LDO4_STDBY_CR:
+ case LDO5_STDBY_CR:
+ case LDO6_STDBY_CR:
+ case BST_SW_CR:
+ case INT_PENDING_R1:
+ case INT_PENDING_R2:
+ case INT_PENDING_R3:
+ case INT_PENDING_R4:
+ case INT_DBG_LATCH_R1:
+ case INT_DBG_LATCH_R2:
+ case INT_DBG_LATCH_R3:
+ case INT_DBG_LATCH_R4:
+ case INT_CLEAR_R1:
+ case INT_CLEAR_R2:
+ case INT_CLEAR_R3:
+ case INT_CLEAR_R4:
+ case INT_MASK_R1:
+ case INT_MASK_R2:
+ case INT_MASK_R3:
+ case INT_MASK_R4:
+ case INT_SET_MASK_R1:
+ case INT_SET_MASK_R2:
+ case INT_SET_MASK_R3:
+ case INT_SET_MASK_R4:
+ case INT_CLEAR_MASK_R1:
+ case INT_CLEAR_MASK_R2:
+ case INT_CLEAR_MASK_R3:
+ case INT_CLEAR_MASK_R4:
+ case INT_SRC_R1:
+ case INT_SRC_R2:
+ case INT_SRC_R3:
+ case INT_SRC_R4:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool stpmic1_reg_writeable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case SWOFF_PWRCTRL_CR:
+ case PADS_PULL_CR:
+ case BUCKS_PD_CR:
+ case LDO14_PD_CR:
+ case LDO56_VREF_PD_CR:
+ case VBUS_DET_VIN_CR:
+ case PKEY_TURNOFF_CR:
+ case BUCKS_MASK_RANK_CR:
+ case BUCKS_MASK_RESET_CR:
+ case LDOS_MASK_RANK_CR:
+ case LDOS_MASK_RESET_CR:
+ case WCHDG_CR:
+ case WCHDG_TIMER_CR:
+ case BUCKS_ICCTO_CR:
+ case LDOS_ICCTO_CR:
+ case BUCK1_ACTIVE_CR:
+ case BUCK2_ACTIVE_CR:
+ case BUCK3_ACTIVE_CR:
+ case BUCK4_ACTIVE_CR:
+ case VREF_DDR_ACTIVE_CR:
+ case LDO1_ACTIVE_CR:
+ case LDO2_ACTIVE_CR:
+ case LDO3_ACTIVE_CR:
+ case LDO4_ACTIVE_CR:
+ case LDO5_ACTIVE_CR:
+ case LDO6_ACTIVE_CR:
+ case BUCK1_STDBY_CR:
+ case BUCK2_STDBY_CR:
+ case BUCK3_STDBY_CR:
+ case BUCK4_STDBY_CR:
+ case VREF_DDR_STDBY_CR:
+ case LDO1_STDBY_CR:
+ case LDO2_STDBY_CR:
+ case LDO3_STDBY_CR:
+ case LDO4_STDBY_CR:
+ case LDO5_STDBY_CR:
+ case LDO6_STDBY_CR:
+ case BST_SW_CR:
+ case INT_DBG_LATCH_R1:
+ case INT_DBG_LATCH_R2:
+ case INT_DBG_LATCH_R3:
+ case INT_DBG_LATCH_R4:
+ case INT_CLEAR_R1:
+ case INT_CLEAR_R2:
+ case INT_CLEAR_R3:
+ case INT_CLEAR_R4:
+ case INT_SET_MASK_R1:
+ case INT_SET_MASK_R2:
+ case INT_SET_MASK_R3:
+ case INT_SET_MASK_R4:
+ case INT_CLEAR_MASK_R1:
+ case INT_CLEAR_MASK_R2:
+ case INT_CLEAR_MASK_R3:
+ case INT_CLEAR_MASK_R4:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool stpmic1_reg_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case TURN_ON_SR:
+ case TURN_OFF_SR:
+ case ICC_LDO_TURN_OFF_SR:
+ case ICC_BUCK_TURN_OFF_SR:
+ case RREQ_STATE_SR:
+ case INT_PENDING_R1:
+ case INT_PENDING_R2:
+ case INT_PENDING_R3:
+ case INT_PENDING_R4:
+ case INT_SRC_R1:
+ case INT_SRC_R2:
+ case INT_SRC_R3:
+ case INT_SRC_R4:
+ case WCHDG_CR:
+ return true;
+ default:
+ return false;
+ }
+}
+
+const struct regmap_config stpmic1_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .cache_type = REGCACHE_RBTREE,
+ .max_register = PMIC_MAX_REGISTER_ADDRESS,
+ .readable_reg = stpmic1_reg_readable,
+ .writeable_reg = stpmic1_reg_writeable,
+ .volatile_reg = stpmic1_reg_volatile,
+};
+
+static const struct regmap_irq stpmic1_irqs[] = {
+ [IT_PONKEY_F] = { .mask = 0x01 },
+ [IT_PONKEY_R] = { .mask = 0x02 },
+ [IT_WAKEUP_F] = { .mask = 0x04 },
+ [IT_WAKEUP_R] = { .mask = 0x08 },
+ [IT_VBUS_OTG_F] = { .mask = 0x10 },
+ [IT_VBUS_OTG_R] = { .mask = 0x20 },
+ [IT_SWOUT_F] = { .mask = 0x40 },
+ [IT_SWOUT_R] = { .mask = 0x80 },
+
+ [IT_CURLIM_BUCK1] = { .reg_offset = 1, .mask = 0x01 },
+ [IT_CURLIM_BUCK2] = { .reg_offset = 1, .mask = 0x02 },
+ [IT_CURLIM_BUCK3] = { .reg_offset = 1, .mask = 0x04 },
+ [IT_CURLIM_BUCK4] = { .reg_offset = 1, .mask = 0x08 },
+ [IT_OCP_OTG] = { .reg_offset = 1, .mask = 0x10 },
+ [IT_OCP_SWOUT] = { .reg_offset = 1, .mask = 0x20 },
+ [IT_OCP_BOOST] = { .reg_offset = 1, .mask = 0x40 },
+ [IT_OVP_BOOST] = { .reg_offset = 1, .mask = 0x80 },
+
+ [IT_CURLIM_LDO1] = { .reg_offset = 2, .mask = 0x01 },
+ [IT_CURLIM_LDO2] = { .reg_offset = 2, .mask = 0x02 },
+ [IT_CURLIM_LDO3] = { .reg_offset = 2, .mask = 0x04 },
+ [IT_CURLIM_LDO4] = { .reg_offset = 2, .mask = 0x08 },
+ [IT_CURLIM_LDO5] = { .reg_offset = 2, .mask = 0x10 },
+ [IT_CURLIM_LDO6] = { .reg_offset = 2, .mask = 0x20 },
+ [IT_SHORT_SWOTG] = { .reg_offset = 2, .mask = 0x40 },
+ [IT_SHORT_SWOUT] = { .reg_offset = 2, .mask = 0x80 },
+
+ [IT_TWARN_F] = { .reg_offset = 3, .mask = 0x01 },
+ [IT_TWARN_R] = { .reg_offset = 3, .mask = 0x02 },
+ [IT_VINLOW_F] = { .reg_offset = 3, .mask = 0x04 },
+ [IT_VINLOW_R] = { .reg_offset = 3, .mask = 0x08 },
+ [IT_SWIN_F] = { .reg_offset = 3, .mask = 0x40 },
+ [IT_SWIN_R] = { .reg_offset = 3, .mask = 0x80 },
+};
+
+static const struct regmap_irq_chip stpmic1_regmap_irq_chip = {
+ .name = "pmic_irq",
+ .status_base = INT_PENDING_R1,
+ .mask_base = INT_CLEAR_MASK_R1,
+ .unmask_base = INT_SET_MASK_R1,
+ .ack_base = INT_CLEAR_R1,
+ .num_regs = STPMIC1_PMIC_NUM_IRQ_REGS,
+ .irqs = stpmic1_irqs,
+ .num_irqs = ARRAY_SIZE(stpmic1_irqs),
+};
+
+static int stpmic1_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct stpmic1 *ddata;
+ struct device *dev = &i2c->dev;
+ int ret;
+ struct device_node *np = dev->of_node;
+ u32 reg;
+
+ ddata = devm_kzalloc(dev, sizeof(struct stpmic1), GFP_KERNEL);
+ if (!ddata)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c, ddata);
+ ddata->dev = dev;
+
+ ddata->regmap = devm_regmap_init_i2c(i2c, &stpmic1_regmap_config);
+ if (IS_ERR(ddata->regmap))
+ return PTR_ERR(ddata->regmap);
+
+ ddata->irq = of_irq_get(np, STPMIC1_MAIN_IRQ);
+ if (ddata->irq < 0) {
+ dev_err(dev, "Failed to get main IRQ: %d\n", ddata->irq);
+ return ddata->irq;
+ }
+
+ if (!of_property_read_u32(np, "st,main-control-register", ®)) {
+ ret = regmap_update_bits(ddata->regmap,
+ SWOFF_PWRCTRL_CR,
+ PWRCTRL_POLARITY_HIGH |
+ PWRCTRL_PIN_VALID |
+ RESTART_REQUEST_ENABLED,
+ reg);
+ if (ret) {
+ dev_err(dev,
+ "Failed to update main control register: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ /* Read Version ID */
+ ret = regmap_read(ddata->regmap, VERSION_SR, ®);
+ if (ret) {
+ dev_err(dev, "Unable to read pmic version\n");
+ return ret;
+ }
+ dev_info(dev, "PMIC Chip Version: 0x%x\n", reg);
+
+ if (!of_property_read_u32(np, "st,pads-pull-register", ®)) {
+ ret = regmap_update_bits(ddata->regmap,
+ PADS_PULL_CR,
+ WAKEUP_DETECTOR_DISABLED |
+ PWRCTRL_PD_ACTIVE |
+ PWRCTRL_PU_ACTIVE |
+ WAKEUP_PD_ACTIVE,
+ reg);
+ if (ret) {
+ dev_err(dev,
+ "Failed to update pads control register: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ if (!of_property_read_u32(np, "st,vin-control-register", ®)) {
+ ret = regmap_update_bits(ddata->regmap,
+ VBUS_DET_VIN_CR,
+ VINLOW_CTRL_REG_MASK,
+ reg);
+ if (ret) {
+ dev_err(dev,
+ "Failed to update vin control register: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ if (!of_property_read_u32(np, "st,usb-control-register", ®)) {
+ ret = regmap_update_bits(ddata->regmap, BST_SW_CR,
+ BOOST_OVP_DISABLED |
+ VBUS_OTG_DETECTION_DISABLED |
+ SW_OUT_DISCHARGE |
+ VBUS_OTG_DISCHARGE |
+ OCP_LIMIT_HIGH,
+ reg);
+ if (ret) {
+ dev_err(dev,
+ "Failed to update usb control register: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ /* Initialize PMIC IRQ Chip & IRQ domains associated */
+ ret = devm_regmap_add_irq_chip(dev, ddata->regmap, ddata->irq,
+ IRQF_ONESHOT | IRQF_SHARED,
+ 0, &stpmic1_regmap_irq_chip,
+ &ddata->irq_data);
+ if (ret) {
+ dev_err(dev, "IRQ Chip registration failed: %d\n", ret);
+ return ret;
+ }
+
+ return devm_of_platform_populate(dev);
+}
+
+static const struct i2c_device_id stpmic1_id[] = {
+ { "stpmic1"},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, stpmic1_id);
+
+#ifdef CONFIG_PM_SLEEP
+static int stpmic1_suspend(struct device *dev)
+{
+ struct i2c_client *i2c = to_i2c_client(dev);
+ struct stpmic1 *pmic_dev = i2c_get_clientdata(i2c);
+
+ disable_irq(pmic_dev->irq);
+
+ return 0;
+}
+
+static int stpmic1_resume(struct device *dev)
+{
+ struct i2c_client *i2c = to_i2c_client(dev);
+ struct stpmic1 *pmic_dev = i2c_get_clientdata(i2c);
+ int ret;
+
+ ret = regcache_sync(pmic_dev->regmap);
+ if (ret)
+ return ret;
+
+ enable_irq(pmic_dev->irq);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(stpmic1_pm, stpmic1_suspend, stpmic1_resume);
+
+static struct i2c_driver stpmic1_driver = {
+ .driver = {
+ .name = "stpmic1",
+ .pm = &stpmic1_pm,
+ },
+ .probe = stpmic1_probe,
+ .id_table = stpmic1_id,
+};
+
+module_i2c_driver(stpmic1_driver);
+
+MODULE_DESCRIPTION("STPMIC1 PMIC Driver");
+MODULE_AUTHOR("Pascal Paillet <p.paillet@st.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/stpmic1.h b/include/linux/mfd/stpmic1.h
new file mode 100644
index 0000000..fa3f99f
--- /dev/null
+++ b/include/linux/mfd/stpmic1.h
@@ -0,0 +1,212 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
+ * Author: Philippe Peurichard <philippe.peurichard@st.com>,
+ * Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
+ */
+
+#ifndef __LINUX_MFD_STPMIC1_H
+#define __LINUX_MFD_STPMIC1_H
+
+#define TURN_ON_SR 0x1
+#define TURN_OFF_SR 0x2
+#define ICC_LDO_TURN_OFF_SR 0x3
+#define ICC_BUCK_TURN_OFF_SR 0x4
+#define RREQ_STATE_SR 0x5
+#define VERSION_SR 0x6
+
+#define SWOFF_PWRCTRL_CR 0x10
+#define PADS_PULL_CR 0x11
+#define BUCKS_PD_CR 0x12
+#define LDO14_PD_CR 0x13
+#define LDO56_VREF_PD_CR 0x14
+#define VBUS_DET_VIN_CR 0x15
+#define PKEY_TURNOFF_CR 0x16
+#define BUCKS_MASK_RANK_CR 0x17
+#define BUCKS_MASK_RESET_CR 0x18
+#define LDOS_MASK_RANK_CR 0x19
+#define LDOS_MASK_RESET_CR 0x1A
+#define WCHDG_CR 0x1B
+#define WCHDG_TIMER_CR 0x1C
+#define BUCKS_ICCTO_CR 0x1D
+#define LDOS_ICCTO_CR 0x1E
+
+#define BUCK1_ACTIVE_CR 0x20
+#define BUCK2_ACTIVE_CR 0x21
+#define BUCK3_ACTIVE_CR 0x22
+#define BUCK4_ACTIVE_CR 0x23
+#define VREF_DDR_ACTIVE_CR 0x24
+#define LDO1_ACTIVE_CR 0x25
+#define LDO2_ACTIVE_CR 0x26
+#define LDO3_ACTIVE_CR 0x27
+#define LDO4_ACTIVE_CR 0x28
+#define LDO5_ACTIVE_CR 0x29
+#define LDO6_ACTIVE_CR 0x2A
+
+#define BUCK1_STDBY_CR 0x30
+#define BUCK2_STDBY_CR 0x31
+#define BUCK3_STDBY_CR 0x32
+#define BUCK4_STDBY_CR 0x33
+#define VREF_DDR_STDBY_CR 0x34
+#define LDO1_STDBY_CR 0x35
+#define LDO2_STDBY_CR 0x36
+#define LDO3_STDBY_CR 0x37
+#define LDO4_STDBY_CR 0x38
+#define LDO5_STDBY_CR 0x39
+#define LDO6_STDBY_CR 0x3A
+
+#define BST_SW_CR 0x40
+
+#define INT_PENDING_R1 0x50
+#define INT_PENDING_R2 0x51
+#define INT_PENDING_R3 0x52
+#define INT_PENDING_R4 0x53
+
+#define INT_DBG_LATCH_R1 0x60
+#define INT_DBG_LATCH_R2 0x61
+#define INT_DBG_LATCH_R3 0x62
+#define INT_DBG_LATCH_R4 0x63
+
+#define INT_CLEAR_R1 0x70
+#define INT_CLEAR_R2 0x71
+#define INT_CLEAR_R3 0x72
+#define INT_CLEAR_R4 0x73
+
+#define INT_MASK_R1 0x80
+#define INT_MASK_R2 0x81
+#define INT_MASK_R3 0x82
+#define INT_MASK_R4 0x83
+
+#define INT_SET_MASK_R1 0x90
+#define INT_SET_MASK_R2 0x91
+#define INT_SET_MASK_R3 0x92
+#define INT_SET_MASK_R4 0x93
+
+#define INT_CLEAR_MASK_R1 0xA0
+#define INT_CLEAR_MASK_R2 0xA1
+#define INT_CLEAR_MASK_R3 0xA2
+#define INT_CLEAR_MASK_R4 0xA3
+
+#define INT_SRC_R1 0xB0
+#define INT_SRC_R2 0xB1
+#define INT_SRC_R3 0xB2
+#define INT_SRC_R4 0xB3
+
+#define PMIC_MAX_REGISTER_ADDRESS INT_SRC_R4
+
+#define STPMIC1_PMIC_NUM_IRQ_REGS 4
+
+#define TURN_OFF_SR_ICC_EVENT 0x08
+
+#define LDO_VOLTAGE_MASK GENMASK(6, 2)
+#define BUCK_VOLTAGE_MASK GENMASK(7, 2)
+#define LDO_BUCK_VOLTAGE_SHIFT 2
+
+#define LDO_ENABLE_MASK BIT(0)
+#define BUCK_ENABLE_MASK BIT(0)
+
+#define BUCK_HPLP_ENABLE_MASK BIT(1)
+#define BUCK_HPLP_SHIFT 1
+
+#define STDBY_ENABLE_MASK BIT(0)
+
+#define BUCKS_PD_CR_REG_MASK GENMASK(7, 0)
+#define BUCK_MASK_RANK_REGISTER_MASK GENMASK(3, 0)
+#define BUCK_MASK_RESET_REGISTER_MASK GENMASK(3, 0)
+#define LDO1234_PULL_DOWN_REGISTER_MASK GENMASK(7, 0)
+#define LDO56_VREF_PD_CR_REG_MASK GENMASK(5, 0)
+#define LDO_MASK_RANK_REGISTER_MASK GENMASK(5, 0)
+#define LDO_MASK_RESET_REGISTER_MASK GENMASK(5, 0)
+
+#define BUCK1_PULL_DOWN_REG BUCKS_PD_CR
+#define BUCK1_PULL_DOWN_MASK BIT(0)
+#define BUCK2_PULL_DOWN_REG BUCKS_PD_CR
+#define BUCK2_PULL_DOWN_MASK BIT(2)
+#define BUCK3_PULL_DOWN_REG BUCKS_PD_CR
+#define BUCK3_PULL_DOWN_MASK BIT(4)
+#define BUCK4_PULL_DOWN_REG BUCKS_PD_CR
+#define BUCK4_PULL_DOWN_MASK BIT(6)
+
+#define LDO1_PULL_DOWN_REG LDO14_PD_CR
+#define LDO1_PULL_DOWN_MASK BIT(0)
+#define LDO2_PULL_DOWN_REG LDO14_PD_CR
+#define LDO2_PULL_DOWN_MASK BIT(2)
+#define LDO3_PULL_DOWN_REG LDO14_PD_CR
+#define LDO3_PULL_DOWN_MASK BIT(4)
+#define LDO4_PULL_DOWN_REG LDO14_PD_CR
+#define LDO4_PULL_DOWN_MASK BIT(6)
+#define LDO5_PULL_DOWN_REG LDO56_VREF_PD_CR
+#define LDO5_PULL_DOWN_MASK BIT(0)
+#define LDO6_PULL_DOWN_REG LDO56_VREF_PD_CR
+#define LDO6_PULL_DOWN_MASK BIT(2)
+#define VREF_DDR_PULL_DOWN_REG LDO56_VREF_PD_CR
+#define VREF_DDR_PULL_DOWN_MASK BIT(4)
+
+#define BUCKS_ICCTO_CR_REG_MASK GENMASK(6, 0)
+#define LDOS_ICCTO_CR_REG_MASK GENMASK(5, 0)
+
+#define LDO_BYPASS_MASK BIT(7)
+
+/* Main PMIC Control Register
+ * SWOFF_PWRCTRL_CR
+ * Address : 0x10
+ */
+#define ICC_EVENT_ENABLED BIT(4)
+#define PWRCTRL_POLARITY_HIGH BIT(3)
+#define PWRCTRL_PIN_VALID BIT(2)
+#define RESTART_REQUEST_ENABLED BIT(1)
+#define SOFTWARE_SWITCH_OFF_ENABLED BIT(0)
+
+/* Main PMIC PADS Control Register
+ * PADS_PULL_CR
+ * Address : 0x11
+ */
+#define WAKEUP_DETECTOR_DISABLED BIT(4)
+#define PWRCTRL_PD_ACTIVE BIT(3)
+#define PWRCTRL_PU_ACTIVE BIT(2)
+#define WAKEUP_PD_ACTIVE BIT(1)
+#define PONKEY_PU_INACTIVE BIT(0)
+
+/* Main PMIC VINLOW Control Register
+ * VBUS_DET_VIN_CRC DMSC
+ * Address : 0x15
+ */
+#define SWIN_DETECTOR_ENABLED BIT(7)
+#define SWOUT_DETECTOR_ENABLED BIT(6)
+#define VINLOW_ENABLED BIT(0)
+#define VINLOW_CTRL_REG_MASK GENMASK(7, 0)
+
+/* USB Control Register
+ * Address : 0x40
+ */
+#define BOOST_OVP_DISABLED BIT(7)
+#define VBUS_OTG_DETECTION_DISABLED BIT(6)
+#define SW_OUT_DISCHARGE BIT(5)
+#define VBUS_OTG_DISCHARGE BIT(4)
+#define OCP_LIMIT_HIGH BIT(3)
+#define SWIN_SWOUT_ENABLED BIT(2)
+#define USBSW_OTG_SWITCH_ENABLED BIT(1)
+#define BOOST_ENABLED BIT(0)
+
+/* PKEY_TURNOFF_CR
+ * Address : 0x16
+ */
+#define PONKEY_PWR_OFF BIT(7)
+#define PONKEY_CC_FLAG_CLEAR BIT(6)
+#define PONKEY_TURNOFF_TIMER_MASK GENMASK(3, 0)
+#define PONKEY_TURNOFF_MASK GENMASK(7, 0)
+
+/*
+ * struct stpmic1 - stpmic1 master device for sub-drivers
+ * @dev: master device of the chip (can be used to access platform data)
+ * @irq: main IRQ number
+ * @regmap_irq_chip_data: irq chip data
+ */
+struct stpmic1 {
+ struct device *dev;
+ struct regmap *regmap;
+ int irq;
+ struct regmap_irq_chip_data *irq_data;
+};
+
+#endif /* __LINUX_MFD_STPMIC1_H */
--
1.9.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox