From patchwork Fri Sep 7 12:59:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pascal Paillet X-Patchwork-Id: 10592151 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 87D58139B for ; Fri, 7 Sep 2018 13:00:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 749162A58A for ; Fri, 7 Sep 2018 13:00:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 664D72B1CD; Fri, 7 Sep 2018 13:00:15 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 953F12A58A for ; Fri, 7 Sep 2018 13:00:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729582AbeIGRlE convert rfc822-to-8bit (ORCPT ); Fri, 7 Sep 2018 13:41:04 -0400 Received: from mx08-00178001.pphosted.com ([91.207.212.93]:47338 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1729579AbeIGRlE (ORCPT ); Fri, 7 Sep 2018 13:41:04 -0400 Received: from pps.filterd (m0046661.ppops.net [127.0.0.1]) by mx08-.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id w87CwdSR009161; Fri, 7 Sep 2018 14:59:44 +0200 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx08-00178001.pphosted.com with ESMTP id 2macwsnjsh-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Fri, 07 Sep 2018 14:59:44 +0200 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id AF38731; Fri, 7 Sep 2018 12:59:43 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag6node3.st.com [10.75.127.18]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 763502D4D; Fri, 7 Sep 2018 12:59:43 +0000 (GMT) Received: from SFHDAG6NODE2.st.com (10.75.127.17) by SFHDAG6NODE3.st.com (10.75.127.18) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Fri, 7 Sep 2018 14:59:42 +0200 Received: from SFHDAG6NODE2.st.com ([fe80::a56f:c186:bab7:13d6]) by SFHDAG6NODE2.st.com ([fe80::a56f:c186:bab7:13d6%20]) with mapi id 15.00.1347.000; Fri, 7 Sep 2018 14:59:43 +0200 From: Pascal PAILLET-LME 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 Subject: [PATCH V2 1/8] dt-bindings: mfd: document stpmic1 Thread-Topic: [PATCH V2 1/8] dt-bindings: mfd: document stpmic1 Thread-Index: AQHURqqlVqt95q0WBUO0V4GcSphbUQ== Date: Fri, 7 Sep 2018 12:59:43 +0000 Message-ID: <1536325173-16617-2-git-send-email-p.paillet@st.com> References: <1536325173-16617-1-git-send-email-p.paillet@st.com> In-Reply-To: <1536325173-16617-1-git-send-email-p.paillet@st.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-messagesentrepresentingtype: 1 x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [10.75.127.48] MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2018-09-07_07:,, signatures=0 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: pascal paillet stpmic1 is a pmic from STMicroelectronics. The stpmic1 integrates 10 regulators and 3 switches with various capabilities. Signed-off-by: pascal paillet --- changes in v2: * the hardware component has been renamed from stpmu1 to stpmic1 ! * replace _ with - in properties name * fix node names in example * remove regulator compatibles in example * add st,stpmic1.h to the patch Rob, I did not change the usage of the properties because it would lead to a lot of st properties; for example st,main-control-register would be replaced by: st,power_cycling_on_turn_off st,pwrctrl_enabled st,pwrctrl_active_high should I go this way ? Rob, I did not found the standard property for st,onkey-press-seconds = <10>; .../devicetree/bindings/mfd/st,stpmic1.txt | 137 +++++++++++++++++++++ include/dt-bindings/mfd/st,stpmic1.h | 46 +++++++ 2 files changed, 183 insertions(+) create mode 100644 Documentation/devicetree/bindings/mfd/st,stpmic1.txt create mode 100644 include/dt-bindings/mfd/st,stpmic1.h diff --git a/Documentation/devicetree/bindings/mfd/st,stpmic1.txt b/Documentation/devicetree/bindings/mfd/st,stpmic1.txt new file mode 100644 index 0000000..9f2c516 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/st,stpmic1.txt @@ -0,0 +1,137 @@ +* STMicroelectronics STPMIC1 Power Management IC + +Required parent device properties: +- compatible: "st,stpmic1" +- reg: the I2C slave address for the stpmic1 chip +- interrupts-extended: interrupt lines to use: second irq is for wakeup. +- #interrupt-cells: should be 2. +- interrupt-controller: describes the STPMIC1 as an interrupt + controller (has its own domain). interrupt number are the following: + /* Interrupt Register 1 (0x50 for latch) */ + IT_SWOUT_R=0 + IT_SWOUT_F=1 + IT_VBUS_OTG_R=2 + IT_VBUS_OTG_F=3 + IT_WAKEUP_R=4 + IT_WAKEUP_F=5 + IT_PONKEY_R=6 + IT_PONKEY_F=7 + /* Interrupt Register 2 (0x51 for latch) */ + IT_OVP_BOOST=8 + IT_OCP_BOOST=9 + IT_OCP_SWOUT=10 + IT_OCP_OTG=11 + IT_CURLIM_BUCK4=12 + IT_CURLIM_BUCK3=13 + IT_CURLIM_BUCK2=14 + IT_CURLIM_BUCK1=15 + /* Interrupt Register 3 (0x52 for latch) */ + IT_SHORT_SWOUT=16 + IT_SHORT_SWOTG=17 + IT_CURLIM_LDO6=18 + IT_CURLIM_LDO5=19 + IT_CURLIM_LDO4=20 + IT_CURLIM_LDO3=21 + IT_CURLIM_LDO2=22 + IT_CURLIM_LDO1=23 + /* Interrupt Register 3 (0x52 for latch) */ + IT_SWIN_R=24 + IT_SWIN_F=25 + IT_RESERVED_1=26 + IT_RESERVED_2=27 + IT_VINLOW_R=28 + IT_VINLOW_F=29 + IT_TWARN_R=30 + IT_TWARN_F=31 + +Optional parent device properties: +- st,main-control-register: + -bit 1: Power cycling will be performed on turn OFF condition + -bit 2: PWRCTRL is functional + -bit 3: PWRCTRL active high +- st,pads-pull-register: + -bit 1: WAKEUP pull down is not active + -bit 2: PWRCTRL pull up is active + -bit 3: PWRCTRL pull down is active + -bit 4: WAKEUP detector is disabled +- st,vin-control-register: + -bit 0: VINLOW monitoring is enabled + -bit [1...3]: VINLOW rising threshold + 000 VINOK_f + 50mV + 001 VINOK_f + 100mV + 010 VINOK_f + 150mV + 011 VINOK_f + 200mV + 100 VINOK_f + 250mV + 101 VINOK_f + 300mV + 110 VINOK_f + 350mV + 111 VINOK_f + 400mV + -bit [4...5]: VINLOW hyst + 00 100mV + 01 200mV + 10 300mV + 11 400mV + -bit 6: SW_OUT detector is disabled + -bit 7: SW_IN detector is enabled. +- st,usb-control-register: + -bit 3: SW_OUT current limit + 0: 600mA + 1: 1.1A + -bit 4: VBUS_OTG discharge is enabled + -bit 5: SW_OUT discharge is enabled + -bit 6: VBUS_OTG detection is enabled + -bit 7: BOOST_OVP is disabled + + +stpmic1 consists is a varied group of sub-devices: + +Device Description +------ ------------ +st,stpmic1-onkey : On key +st,stpmic1-regulators : Regulators +st,stpmic1-wdt : Watchdog + +each sub-device bindings is be described in associated driver +documentation section. + +Example: + +pmic: stpmic1@33 { + compatible = "st,stpmic1"; + reg = <0x33>; + interrupts = <0 2>; + interrupts-extended = <&intc GIC_SPI 149 IRQ_TYPE_NONE>, + <&exti 55 1>; + st,version_status = <0x10>; + st,main-control-register=<0x0c>; + interrupt-controller; + #interrupt-cells = <2>; + onkey { + compatible = "st,stpmic1-onkey"; + interrupt-parent = <&pmic>; + interrupts = ,; + interrupt-names = "onkey-falling", "onkey-rising"; + st,onkey-pwroff-enabled; + st,onkey-long-press-seconds = <10>; + }; + + watchdog { + compatible = "st,stpmic1-wdt"; + }; + + regulators { + compatible = "st,stpmic1-regulators"; + + vdd_core: buck1 { + regulator-name = "vdd_core"; + regulator-boot-on; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1200000>; + }; + vdd: buck3 { + regulator-name = "vdd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-pull-down; + }; + }; diff --git a/include/dt-bindings/mfd/st,stpmic1.h b/include/dt-bindings/mfd/st,stpmic1.h new file mode 100644 index 0000000..e32ac8f --- /dev/null +++ b/include/dt-bindings/mfd/st,stpmic1.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) STMicroelectronics 2018 - All Rights Reserved + * Author: Philippe Peurichard , + * Pascal Paillet for STMicroelectronics. + */ + +#ifndef __DT_BINDINGS_STPMIC1_H__ +#define __DT_BINDINGS_STPMIC1_H__ + +/* IRQ definitions */ +#define IT_PONKEY_F 0 +#define IT_PONKEY_R 1 +#define IT_WAKEUP_F 2 +#define IT_WAKEUP_R 3 +#define IT_VBUS_OTG_F 4 +#define IT_VBUS_OTG_R 5 +#define IT_SWOUT_F 6 +#define IT_SWOUT_R 7 + +#define IT_CURLIM_BUCK1 8 +#define IT_CURLIM_BUCK2 9 +#define IT_CURLIM_BUCK3 10 +#define IT_CURLIM_BUCK4 11 +#define IT_OCP_OTG 12 +#define IT_OCP_SWOUT 13 +#define IT_OCP_BOOST 14 +#define IT_OVP_BOOST 15 + +#define IT_CURLIM_LDO1 16 +#define IT_CURLIM_LDO2 17 +#define IT_CURLIM_LDO3 18 +#define IT_CURLIM_LDO4 19 +#define IT_CURLIM_LDO5 20 +#define IT_CURLIM_LDO6 21 +#define IT_SHORT_SWOTG 22 +#define IT_SHORT_SWOUT 23 + +#define IT_TWARN_F 24 +#define IT_TWARN_R 25 +#define IT_VINLOW_F 26 +#define IT_VINLOW_R 27 +#define IT_SWIN_F 30 +#define IT_SWIN_R 31 + +#endif /* __DT_BINDINGS_STPMIC1_H__ */ From patchwork Fri Sep 7 12:59:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pascal Paillet X-Patchwork-Id: 10592155 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 27759139B for ; Fri, 7 Sep 2018 13:00:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 167372B2D7 for ; Fri, 7 Sep 2018 13:00:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 09A5A2B2EA; Fri, 7 Sep 2018 13:00:40 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BF8822B2D7 for ; Fri, 7 Sep 2018 13:00:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729699AbeIGRlT convert rfc822-to-8bit (ORCPT ); Fri, 7 Sep 2018 13:41:19 -0400 Received: from mx07-00178001.pphosted.com ([62.209.51.94]:58438 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729514AbeIGRlS (ORCPT ); Fri, 7 Sep 2018 13:41:18 -0400 Received: from pps.filterd (m0046668.ppops.net [127.0.0.1]) by mx07-.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id w87CxOaF020864; Fri, 7 Sep 2018 14:59:48 +0200 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 2mbhwsamhy-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Fri, 07 Sep 2018 14:59:48 +0200 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 51DD938; Fri, 7 Sep 2018 12:59:44 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag6node2.st.com [10.75.127.17]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 1E8A82D4D; Fri, 7 Sep 2018 12:59:44 +0000 (GMT) Received: from SFHDAG6NODE2.st.com (10.75.127.17) by SFHDAG6NODE2.st.com (10.75.127.17) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Fri, 7 Sep 2018 14:59:43 +0200 Received: from SFHDAG6NODE2.st.com ([fe80::a56f:c186:bab7:13d6]) by SFHDAG6NODE2.st.com ([fe80::a56f:c186:bab7:13d6%20]) with mapi id 15.00.1347.000; Fri, 7 Sep 2018 14:59:43 +0200 From: Pascal PAILLET-LME 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 Subject: [PATCH V2 2/8] mfd: stpmic1: add stpmic1 driver Thread-Topic: [PATCH V2 2/8] mfd: stpmic1: add stpmic1 driver Thread-Index: AQHURqqlMNkqBQJiCUKqf39jsadGXQ== Date: Fri, 7 Sep 2018 12:59:43 +0000 Message-ID: <1536325173-16617-3-git-send-email-p.paillet@st.com> References: <1536325173-16617-1-git-send-email-p.paillet@st.com> In-Reply-To: <1536325173-16617-1-git-send-email-p.paillet@st.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-messagesentrepresentingtype: 1 x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [10.75.127.48] MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2018-09-07_07:,, signatures=0 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: pascal paillet stpmic1 is a pmic from STMicroelectronics. The stpmic1 integrates 10 regulators and 3 switches with various capabilities. Signed-off-by: pascal paillet --- changes in v2: * the hardware component has been renamed from stpmu1 to stpmic1 ! * Handle remarks from Enric * change headers * split binding description on another patch On other mfd upstreamed by us (ST) we always get the remark to use devm_of_platform_populate and not mfd_add_devices(). MFD maintainers could you please clarify wich API I should here, thanks ? drivers/mfd/Kconfig | 13 ++ drivers/mfd/Makefile | 1 + drivers/mfd/stpmic1.c | 457 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/mfd/stpmic1.h | 220 +++++++++++++++++++++ 4 files changed, 691 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 b860eb5..7984803 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1812,6 +1812,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 STMicroelectronics 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 e9fd20d..b194929 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -220,6 +220,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..ea0bff2 --- /dev/null +++ b/drivers/mfd/stpmic1.c @@ -0,0 +1,457 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) STMicroelectronics 2018 +// Author: Pascal Paillet for STMicroelectronics. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static bool stpmic1_reg_readable(struct device *dev, unsigned int reg); +static bool stpmic1_reg_writeable(struct device *dev, unsigned int reg); +static bool stpmic1_reg_volatile(struct device *dev, unsigned int reg); + +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, +}; + +#define FILL_IRQS(_index) \ + [(_index)] = { \ + .reg_offset = ((_index) >> 3), \ + .mask = (1 << (_index % 8)), \ + } + +static const struct regmap_irq stpmic1_irqs[] = { + FILL_IRQS(IT_PONKEY_F), + FILL_IRQS(IT_PONKEY_R), + FILL_IRQS(IT_WAKEUP_F), + FILL_IRQS(IT_WAKEUP_R), + FILL_IRQS(IT_VBUS_OTG_F), + FILL_IRQS(IT_VBUS_OTG_R), + FILL_IRQS(IT_SWOUT_F), + FILL_IRQS(IT_SWOUT_R), + + FILL_IRQS(IT_CURLIM_BUCK1), + FILL_IRQS(IT_CURLIM_BUCK2), + FILL_IRQS(IT_CURLIM_BUCK3), + FILL_IRQS(IT_CURLIM_BUCK4), + FILL_IRQS(IT_OCP_OTG), + FILL_IRQS(IT_OCP_SWOUT), + FILL_IRQS(IT_OCP_BOOST), + FILL_IRQS(IT_OVP_BOOST), + + FILL_IRQS(IT_CURLIM_LDO1), + FILL_IRQS(IT_CURLIM_LDO2), + FILL_IRQS(IT_CURLIM_LDO3), + FILL_IRQS(IT_CURLIM_LDO4), + FILL_IRQS(IT_CURLIM_LDO5), + FILL_IRQS(IT_CURLIM_LDO6), + FILL_IRQS(IT_SHORT_SWOTG), + FILL_IRQS(IT_SHORT_SWOUT), + + FILL_IRQS(IT_TWARN_F), + FILL_IRQS(IT_TWARN_R), + FILL_IRQS(IT_VINLOW_F), + FILL_IRQS(IT_VINLOW_R), + FILL_IRQS(IT_SWIN_F), + FILL_IRQS(IT_SWIN_R), +}; + +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 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; + } +} + +static int stpmic1_configure_from_dt(struct stpmic1_dev *pmic_dev) +{ + struct device_node *np = pmic_dev->np; + u32 reg; + int ret, irq; + + irq = of_irq_get(np, 0); + if (irq <= 0) { + dev_err(pmic_dev->dev, + "Failed to get irq config: %d\n", irq); + return irq ?: -ENODEV; + } + pmic_dev->irq = irq; + + irq = of_irq_get(np, 1); + if (irq > 0) + pmic_dev->irq_wake = irq; + else + pmic_dev->irq_wake = pmic_dev->irq; + + device_init_wakeup(pmic_dev->dev, true); + ret = dev_pm_set_dedicated_wake_irq(pmic_dev->dev, pmic_dev->irq_wake); + if (ret) + dev_warn(pmic_dev->dev, "failed to set up wakeup irq"); + + if (!of_property_read_u32(np, "st,main-control-register", ®)) { + ret = regmap_update_bits(pmic_dev->regmap, + SWOFF_PWRCTRL_CR, + PWRCTRL_POLARITY_HIGH | + PWRCTRL_PIN_VALID | + RESTART_REQUEST_ENABLED, + reg); + if (ret) { + dev_err(pmic_dev->dev, + "Failed to update main control register: %d\n", + ret); + return ret; + } + } + + if (!of_property_read_u32(np, "st,pads-pull-register", ®)) { + ret = regmap_update_bits(pmic_dev->regmap, + PADS_PULL_CR, + WAKEUP_DETECTOR_DISABLED | + PWRCTRL_PD_ACTIVE | + PWRCTRL_PU_ACTIVE | + WAKEUP_PD_ACTIVE, + reg); + if (ret) { + dev_err(pmic_dev->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(pmic_dev->regmap, + VBUS_DET_VIN_CR, + VINLOW_CTRL_REG_MASK, + reg); + if (ret) { + dev_err(pmic_dev->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(pmic_dev->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(pmic_dev->dev, + "Failed to update usb control register: %d\n", + ret); + return ret; + } + } + + return 0; +} + +int stpmic1_device_init(struct stpmic1_dev *pmic_dev) +{ + int ret; + unsigned int val; + + pmic_dev->regmap = + devm_regmap_init_i2c(pmic_dev->i2c, &stpmic1_regmap_config); + + if (IS_ERR(pmic_dev->regmap)) + return PTR_ERR(pmic_dev->regmap); + + ret = stpmic1_configure_from_dt(pmic_dev); + if (ret) { + dev_err(pmic_dev->dev, + "Unable to configure PMIC from Device Tree: %d\n", ret); + return ret; + } + + /* Read Version ID */ + ret = regmap_read(pmic_dev->regmap, VERSION_SR, &val); + if (ret) { + dev_err(pmic_dev->dev, "Unable to read pmic version\n"); + return ret; + } + dev_info(pmic_dev->dev, "PMIC Chip Version: 0x%x\n", val); + + /* Initialize PMIC IRQ Chip & IRQ domains associated */ + ret = devm_regmap_add_irq_chip(pmic_dev->dev, pmic_dev->regmap, + pmic_dev->irq, + IRQF_ONESHOT | IRQF_SHARED, + 0, &stpmic1_regmap_irq_chip, + &pmic_dev->irq_data); + if (ret) { + dev_err(pmic_dev->dev, "IRQ Chip registration failed: %d\n", + ret); + return ret; + } + + return 0; +} + +static int stpmic1_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct stpmic1_dev *pmic; + struct device *dev = &i2c->dev; + int ret; + + pmic = devm_kzalloc(dev, sizeof(struct stpmic1_dev), GFP_KERNEL); + if (!pmic) + return -ENOMEM; + + pmic->np = dev->of_node; + + dev_set_drvdata(dev, pmic); + pmic->dev = dev; + pmic->i2c = i2c; + + ret = stpmic1_device_init(pmic); + if (ret) + return ret; + + return devm_of_platform_populate(pmic->dev); +} + +static const struct i2c_device_id stpmic1_id[] = { + { "stpmic1", 0 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, stpmic1_id); + +#ifdef CONFIG_PM_SLEEP +static int stpmic1_suspend(struct device *dev) +{ + struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); + struct stpmic1_dev *pmic_dev = i2c_get_clientdata(i2c); + + if (device_may_wakeup(dev)) + enable_irq_wake(pmic_dev->irq_wake); + + disable_irq(pmic_dev->irq); + return 0; +} + +static int stpmic1_resume(struct device *dev) +{ + struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); + struct stpmic1_dev *pmic_dev = i2c_get_clientdata(i2c); + int ret; + + ret = regcache_sync(pmic_dev->regmap); + if (ret) + return ret; + + if (device_may_wakeup(dev)) + disable_irq_wake(pmic_dev->irq_wake); + + 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"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/mfd/stpmic1.h b/include/linux/mfd/stpmic1.h new file mode 100644 index 0000000..024769d --- /dev/null +++ b/include/linux/mfd/stpmic1.h @@ -0,0 +1,220 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) STMicroelectronics 2018 - All Rights Reserved + * Author: Philippe Peurichard , + * Pascal Paillet 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_ACTIVE 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_dev - stpmic1 master device for sub-drivers + * @dev: master device of the chip (can be used to access platform data) + * @i2c: i2c client private data for regulator + * @np: device DT node pointer + * @irq_base: base IRQ numbers + * @irq: generic IRQ number + * @irq_wake: wakeup IRQ number + * @regmap_irq_chip_data: irq chip data + */ +struct stpmic1_dev { + struct device *dev; + struct i2c_client *i2c; + struct regmap *regmap; + struct device_node *np; + unsigned int irq_base; + int irq; + int irq_wake; + struct regmap_irq_chip_data *irq_data; +}; + +#endif /* __LINUX_MFD_STPMIC1_H */ From patchwork Fri Sep 7 12:59:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pascal Paillet X-Patchwork-Id: 10592159 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BA4B414BD for ; Fri, 7 Sep 2018 13:01:06 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A739E2B2D7 for ; Fri, 7 Sep 2018 13:01:06 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 982F02B2EA; Fri, 7 Sep 2018 13:01:06 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 63F182B2D7 for ; Fri, 7 Sep 2018 13:01:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729739AbeIGRlk convert rfc822-to-8bit (ORCPT ); Fri, 7 Sep 2018 13:41:40 -0400 Received: from mx07-00178001.pphosted.com ([62.209.51.94]:48539 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729660AbeIGRlP (ORCPT ); Fri, 7 Sep 2018 13:41:15 -0400 Received: from pps.filterd (m0046668.ppops.net [127.0.0.1]) by mx07-.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id w87CxOKt020861; Fri, 7 Sep 2018 14:59:45 +0200 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 2mbhwsamhv-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Fri, 07 Sep 2018 14:59:45 +0200 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id A9EE03A; Fri, 7 Sep 2018 12:59:44 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag6node3.st.com [10.75.127.18]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 8242A2D4A; Fri, 7 Sep 2018 12:59:44 +0000 (GMT) Received: from SFHDAG6NODE2.st.com (10.75.127.17) by SFHDAG6NODE3.st.com (10.75.127.18) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Fri, 7 Sep 2018 14:59:44 +0200 Received: from SFHDAG6NODE2.st.com ([fe80::a56f:c186:bab7:13d6]) by SFHDAG6NODE2.st.com ([fe80::a56f:c186:bab7:13d6%20]) with mapi id 15.00.1347.000; Fri, 7 Sep 2018 14:59:44 +0200 From: Pascal PAILLET-LME 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 Subject: [PATCH V2 3/8] dt-bindings: regulator: document stpmic1 pmic regulators Thread-Topic: [PATCH V2 3/8] dt-bindings: regulator: document stpmic1 pmic regulators Thread-Index: AQHURqqlamEul0sXXU62CBrDAbuQcw== Date: Fri, 7 Sep 2018 12:59:44 +0000 Message-ID: <1536325173-16617-4-git-send-email-p.paillet@st.com> References: <1536325173-16617-1-git-send-email-p.paillet@st.com> In-Reply-To: <1536325173-16617-1-git-send-email-p.paillet@st.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-messagesentrepresentingtype: 1 x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [10.75.127.48] MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2018-09-07_07:,, signatures=0 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: pascal paillet 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 --- changes in v2: * the hardware component has been renamed from stpmu1 to stpmic1 ! * replace _ with - in properties name * remove deprecated regulator-compatible from the example Rob, the st,mask_reset name is taken from the data-sheet. I have modified the description. I hope there is no confusion with bit masking know. .../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 +- -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 = ; + interrupt-parent = <&pmic>; + st,mask-reset; + regulator-pull-down; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1200000>; + }; + + v3v3: buck4 { + regulator-name = "v3v3"; + interrupts = ; + 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; + }; +}; From patchwork Fri Sep 7 12:59:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pascal Paillet X-Patchwork-Id: 10592163 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 75710139B for ; Fri, 7 Sep 2018 13:01:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 606CC2B2D7 for ; Fri, 7 Sep 2018 13:01:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 532932B2EA; Fri, 7 Sep 2018 13:01:18 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 026072B2D7 for ; Fri, 7 Sep 2018 13:01:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729052AbeIGRmA convert rfc822-to-8bit (ORCPT ); Fri, 7 Sep 2018 13:42:00 -0400 Received: from mx08-00178001.pphosted.com ([91.207.212.93]:47353 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726587AbeIGRlM (ORCPT ); Fri, 7 Sep 2018 13:41:12 -0400 Received: from pps.filterd (m0046661.ppops.net [127.0.0.1]) by mx08-.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id w87Cwdil009164; Fri, 7 Sep 2018 14:59:46 +0200 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx08-00178001.pphosted.com with ESMTP id 2macwsnjsr-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Fri, 07 Sep 2018 14:59:46 +0200 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 620EA3D; Fri, 7 Sep 2018 12:59:45 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag6node2.st.com [10.75.127.17]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 257E32D4A; Fri, 7 Sep 2018 12:59:45 +0000 (GMT) Received: from SFHDAG6NODE2.st.com (10.75.127.17) by SFHDAG6NODE2.st.com (10.75.127.17) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Fri, 7 Sep 2018 14:59:44 +0200 Received: from SFHDAG6NODE2.st.com ([fe80::a56f:c186:bab7:13d6]) by SFHDAG6NODE2.st.com ([fe80::a56f:c186:bab7:13d6%20]) with mapi id 15.00.1347.000; Fri, 7 Sep 2018 14:59:44 +0200 From: Pascal PAILLET-LME 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 Subject: [PATCH V2 4/8] regulator: stpmic1: add stpmic1 regulator driver Thread-Topic: [PATCH V2 4/8] regulator: stpmic1: add stpmic1 regulator driver Thread-Index: AQHURqqm1EGQbqAfHECPi7txOURv7Q== Date: Fri, 7 Sep 2018 12:59:44 +0000 Message-ID: <1536325173-16617-5-git-send-email-p.paillet@st.com> References: <1536325173-16617-1-git-send-email-p.paillet@st.com> In-Reply-To: <1536325173-16617-1-git-send-email-p.paillet@st.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-messagesentrepresentingtype: 1 x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [10.75.127.48] MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2018-09-07_07:,, signatures=0 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: pascal paillet The stpmic1 PMIC embeds several regulators and witches with different capabilities. Signed-off-by: pascal paillet --- changes in v2: * the hardware component has been renamed from stpmu1 to stpmic1 ! * change headers * rework map_mode function * remove proprietary get voltage functions * do not override constraints * register all the regulators even if not described in the dt * stop resetting registers during probe * use standard pull down setting Mark, I did not change the mfd to use mfd_add_devices() yet because during our last upstream (ST), we had to use devm_of_platform_populate(). I have asked for confirmation in the mfd review message. drivers/regulator/Kconfig | 12 + drivers/regulator/Makefile | 1 + drivers/regulator/stpmic1_regulator.c | 692 ++++++++++++++++++++++++++++++++++ 3 files changed, 705 insertions(+) create mode 100644 drivers/regulator/stpmic1_regulator.c diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 5dbccf5..96f0748 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -804,6 +804,18 @@ config REGULATOR_TI_ABB on TI SoCs may be unstable without enabling this as it provides device specific optimized bias to allow/optimize functionality. +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_STW481X_VMMC bool "STMicroelectronics STW481X VMMC regulator" depends on MFD_STW481X || COMPILE_TEST diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index bd818ce..716d9ff 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -100,6 +100,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..3b32d8f --- /dev/null +++ b/drivers/regulator/stpmic1_regulator.c @@ -0,0 +1,692 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) STMicroelectronics 2018 +// Author: Pascal Paillet for STMicroelectronics. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * 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; +}; + +/** + * struct stpmic1_device_data - contains all regulators data + * @regulator_table : contains all the regulators + */ +struct stpmic1_device_data { + struct stpmic1_regulator *regulator_table; +}; + +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_dev *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 stpmic1_device_data *ddata; + struct regulator_dev *rdev; + struct stpmic1_regulator *regul; + struct regulator_init_data *init_data; + struct device_node *np; + int i, ret; + + ddata = devm_kzalloc(&pdev->dev, sizeof(struct stpmic1_device_data), + GFP_KERNEL); + if (!ddata) + return -ENOMEM; + + platform_set_drvdata(pdev, ddata); + + 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; + + ddata->regulator_table = regul; + + 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"); +MODULE_LICENSE("GPL v2"); From patchwork Fri Sep 7 12:59:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pascal Paillet X-Patchwork-Id: 10592157 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E86BA14BD for ; Fri, 7 Sep 2018 13:00:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D98582B2D7 for ; Fri, 7 Sep 2018 13:00:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CD3CD2B2EA; Fri, 7 Sep 2018 13:00:44 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6E62C2B2D7 for ; Fri, 7 Sep 2018 13:00:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729728AbeIGRl3 convert rfc822-to-8bit (ORCPT ); Fri, 7 Sep 2018 13:41:29 -0400 Received: from mx07-00178001.pphosted.com ([62.209.51.94]:52119 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729667AbeIGRlQ (ORCPT ); Fri, 7 Sep 2018 13:41:16 -0400 Received: from pps.filterd (m0046037.ppops.net [127.0.0.1]) by mx07-.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id w87Cx7Va005582; Fri, 7 Sep 2018 14:59:46 +0200 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 2mbjwpjcmf-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Fri, 07 Sep 2018 14:59:46 +0200 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 8E1043F; Fri, 7 Sep 2018 12:59:45 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag6node2.st.com [10.75.127.17]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 6E8B62D4D; Fri, 7 Sep 2018 12:59:45 +0000 (GMT) Received: from SFHDAG6NODE2.st.com (10.75.127.17) by SFHDAG6NODE2.st.com (10.75.127.17) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Fri, 7 Sep 2018 14:59:45 +0200 Received: from SFHDAG6NODE2.st.com ([fe80::a56f:c186:bab7:13d6]) by SFHDAG6NODE2.st.com ([fe80::a56f:c186:bab7:13d6%20]) with mapi id 15.00.1347.000; Fri, 7 Sep 2018 14:59:45 +0200 From: Pascal PAILLET-LME 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 Subject: [PATCH V2 5/8] dt-bindings: input: document stpmic1 pmic onkey Thread-Topic: [PATCH V2 5/8] dt-bindings: input: document stpmic1 pmic onkey Thread-Index: AQHURqqmhndlp2hGlk2oSqFoX+/HCQ== Date: Fri, 7 Sep 2018 12:59:45 +0000 Message-ID: <1536325173-16617-6-git-send-email-p.paillet@st.com> References: <1536325173-16617-1-git-send-email-p.paillet@st.com> In-Reply-To: <1536325173-16617-1-git-send-email-p.paillet@st.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-messagesentrepresentingtype: 1 x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [10.75.127.48] MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2018-09-07_07:,, signatures=0 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: pascal paillet 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 --- .../devicetree/bindings/input/st,stpmic1-onkey.txt | 31 ++++++++++++++++++++++ 1 file changed, 31 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..b0db90d --- /dev/null +++ b/Documentation/devicetree/bindings/input/st,stpmic1-onkey.txt @@ -0,0 +1,31 @@ +STMicroelectronics STPMIC1 Onkey + +Required properties: + +- compatible = "st,stpmic1-onkey"; +- interrupt-parent: phandle to the parent interrupt controller +- 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-pwroff-enabled: power off on long key-press +- st,onkey-long-press-seconds: long key-press duration from 1 to 16s + (default 16s) +- 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 + +Example: + +onkey { + compatible = "st,stpmic1-onkey"; + interrupt-parent = <&pmic>; + interrupts = ,; + interrupt-names = "onkey-falling", "onkey-rising"; + status = "okay"; + st,onkey-pwroff-enabled; + st,onkey-long-press-seconds = <10>; +}; From patchwork Fri Sep 7 12:59:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pascal Paillet X-Patchwork-Id: 10592165 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5755B14BD for ; Fri, 7 Sep 2018 13:01:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 471272B2D7 for ; Fri, 7 Sep 2018 13:01:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3AB3E2B2ED; Fri, 7 Sep 2018 13:01:22 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 73CD82B2D7 for ; Fri, 7 Sep 2018 13:01:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729643AbeIGRlL convert rfc822-to-8bit (ORCPT ); Fri, 7 Sep 2018 13:41:11 -0400 Received: from mx08-00178001.pphosted.com ([91.207.212.93]:52090 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1729066AbeIGRlK (ORCPT ); Fri, 7 Sep 2018 13:41:10 -0400 Received: from pps.filterd (m0046660.ppops.net [127.0.0.1]) by mx08-.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id w87Cx8gb028051; Fri, 7 Sep 2018 14:59:46 +0200 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx08-00178001.pphosted.com with ESMTP id 2mbpnv948f-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Fri, 07 Sep 2018 14:59:46 +0200 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 2F0F431; Fri, 7 Sep 2018 12:59:46 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag6node1.st.com [10.75.127.16]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 0190A2D4A; Fri, 7 Sep 2018 12:59:46 +0000 (GMT) Received: from SFHDAG6NODE2.st.com (10.75.127.17) by SFHDAG6NODE1.st.com (10.75.127.16) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Fri, 7 Sep 2018 14:59:46 +0200 Received: from SFHDAG6NODE2.st.com ([fe80::a56f:c186:bab7:13d6]) by SFHDAG6NODE2.st.com ([fe80::a56f:c186:bab7:13d6%20]) with mapi id 15.00.1347.000; Fri, 7 Sep 2018 14:59:45 +0200 From: Pascal PAILLET-LME 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 Subject: [PATCH V2 6/8] input: stpmic1: add stpmic1 onkey driver Thread-Topic: [PATCH V2 6/8] input: stpmic1: add stpmic1 onkey driver Thread-Index: AQHURqqmk2rxPe8flEiyU5gsj+jEjg== Date: Fri, 7 Sep 2018 12:59:45 +0000 Message-ID: <1536325173-16617-7-git-send-email-p.paillet@st.com> References: <1536325173-16617-1-git-send-email-p.paillet@st.com> In-Reply-To: <1536325173-16617-1-git-send-email-p.paillet@st.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-messagesentrepresentingtype: 1 x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [10.75.127.48] MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2018-09-07_07:,, signatures=0 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: pascal paillet 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 --- changes in v2: * the hardware component has been renamed from stpmu1 to stpmic1 ! * change headers * handle remarks from Dmitry * the irq is threaded because is is nested in a thread; I have added a comment. Dmitry, I'm sorry, but I did not catch your comment regarding usage of "generic device property API.". could you tell more ? drivers/input/misc/Kconfig | 11 ++ drivers/input/misc/Makefile | 2 + drivers/input/misc/stpmic1_onkey.c | 257 +++++++++++++++++++++++++++++++++++++ 3 files changed, 270 insertions(+) create mode 100644 drivers/input/misc/stpmic1_onkey.c diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index c25606e..cc82dad 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -841,4 +841,15 @@ config INPUT_RAVE_SP_PWRBUTTON To compile this driver as a module, choose M here: the module will be called rave-sp-pwrbutton. +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 72cde28..f0e11b0 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -70,6 +70,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 @@ -80,3 +81,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..170d879 --- /dev/null +++ b/drivers/input/misc/stpmic1_onkey.c @@ -0,0 +1,257 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) STMicroelectronics 2018 +// Author: Pascal Paillet for STMicroelectronics. + +#include +#include +#include +#include +#include +#include +#include + +/** + * struct stpmic1_onkey - OnKey data + * @pmic: pointer to STPMIC1 PMIC device + * @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 stpmic1_dev *pmic; + struct input_dev *input_dev; + int irq_falling; + int irq_rising; +}; + +/** + * struct pmic_onkey_config - configuration of pmic PONKEYn + * @turnoff_enabled: value to enable turnoff condition + * @cc_flag_clear: value to clear CC flag in case of PowerOff + * trigger by longkey press + * @onkey_pullup_val: value of PONKEY PullUp (active or inactive) + * @long_press_time_val: value for long press h/w shutdown event + */ +struct pmic_onkey_config { + bool turnoff_enabled; + bool cc_flag_clear; + u8 onkey_pullup_val; + u8 long_press_time_val; +}; + +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); + + dev_dbg(&input_dev->dev, "Pwr Onkey Falling Interrupt received\n"); + + 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); + + dev_dbg(&input_dev->dev, "Pwr Onkey Rising Interrupt received\n"); + + return IRQ_HANDLED; +} + +static int stpmic1_onkey_dt_params(struct platform_device *pdev, + struct stpmic1_onkey *onkey, + struct pmic_onkey_config *config) +{ + struct device *dev = &pdev->dev; + struct device_node *np; + u32 val; + + np = dev->of_node; + + 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 (!of_property_read_u32(np, "st,onkey-long-press-seconds", &val)) { + if (val >= 1 && val <= 16) { + config->long_press_time_val = (16 - val); + } else { + dev_warn(dev, + "Invalid range of long key pressed timer %d (<16)\n", + val); + } + } + if (of_get_property(np, "st,onkey-pwroff-enabled", NULL)) + config->turnoff_enabled = true; + + if (of_get_property(np, "st,onkey-clear-cc-flag", NULL)) + config->cc_flag_clear = true; + + if (of_get_property(np, "st,onkey-pu-inactive", NULL)) + config->onkey_pullup_val = PONKEY_PU_ACTIVE; + + dev_dbg(dev, "onkey-switch-off duration=%d seconds\n", + config->long_press_time_val); + + return 0; +} + +static int stpmic1_onkey_probe(struct platform_device *pdev) +{ + struct stpmic1_dev *pmic = dev_get_drvdata(pdev->dev.parent); + struct device *dev = &pdev->dev; + struct input_dev *input_dev; + struct stpmic1_onkey *onkey; + struct pmic_onkey_config config; + unsigned int val = 0; + int error; + + onkey = devm_kzalloc(dev, sizeof(*onkey), GFP_KERNEL); + if (!onkey) + return -ENOMEM; + + memset(&config, 0, sizeof(struct pmic_onkey_config)); + error = stpmic1_onkey_dt_params(pdev, onkey, &config); + if (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); + + /* Setup Power Onkey Hardware parameters (long key press)*/ + val = (config.long_press_time_val & PONKEY_TURNOFF_TIMER_MASK); + if (config.turnoff_enabled) + val |= PONKEY_PWR_OFF; + if (config.cc_flag_clear) + val |= PONKEY_CC_FLAG_CLEAR; + error = regmap_update_bits(pmic->regmap, PKEY_TURNOFF_CR, + PONKEY_TURNOFF_MASK, val); + if (error) { + dev_err(dev, "LONG_PRESS_KEY_UPDATE failed: %d\n", error); + return error; + } + + error = regmap_update_bits(pmic->regmap, PADS_PULL_CR, + PONKEY_PU_ACTIVE, + config.onkey_pullup_val); + if (error) { + dev_err(dev, "ONKEY Pads configuration failed: %d\n", error); + return error; + } + + onkey->pmic = pmic; + 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 stpmic1_onkey_remove(struct platform_device *pdev) +{ + struct stpmic1_onkey *onkey = platform_get_drvdata(pdev); + + input_unregister_device(onkey->input_dev); + 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, + .remove = stpmic1_onkey_remove, + .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_LICENSE("GPL v2"); +MODULE_AUTHOR("Pascal Paillet"); From patchwork Fri Sep 7 12:59:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pascal Paillet X-Patchwork-Id: 10592153 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9068A139B for ; Fri, 7 Sep 2018 13:00:27 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 812242B2D7 for ; Fri, 7 Sep 2018 13:00:27 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 751022B2EA; Fri, 7 Sep 2018 13:00:27 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2E4492B2D7 for ; Fri, 7 Sep 2018 13:00:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729662AbeIGRlQ convert rfc822-to-8bit (ORCPT ); Fri, 7 Sep 2018 13:41:16 -0400 Received: from mx07-00178001.pphosted.com ([62.209.51.94]:42550 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729677AbeIGRlP (ORCPT ); Fri, 7 Sep 2018 13:41:15 -0400 Received: from pps.filterd (m0046037.ppops.net [127.0.0.1]) by mx07-.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id w87Cx8lv005589; Fri, 7 Sep 2018 14:59:48 +0200 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 2mbjwpjcmg-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Fri, 07 Sep 2018 14:59:48 +0200 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 7D86934; Fri, 7 Sep 2018 12:59:46 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag6node3.st.com [10.75.127.18]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 5AEC82D4D; Fri, 7 Sep 2018 12:59:46 +0000 (GMT) Received: from SFHDAG6NODE2.st.com (10.75.127.17) by SFHDAG6NODE3.st.com (10.75.127.18) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Fri, 7 Sep 2018 14:59:45 +0200 Received: from SFHDAG6NODE2.st.com ([fe80::a56f:c186:bab7:13d6]) by SFHDAG6NODE2.st.com ([fe80::a56f:c186:bab7:13d6%20]) with mapi id 15.00.1347.000; Fri, 7 Sep 2018 14:59:46 +0200 From: Pascal PAILLET-LME 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 Subject: [PATCH V2 7/8] dt-bindings: watchdog: document stpmic1 pmic watchdog Thread-Topic: [PATCH V2 7/8] dt-bindings: watchdog: document stpmic1 pmic watchdog Thread-Index: AQHURqqmOE2liky850y7qYU9nulfUQ== Date: Fri, 7 Sep 2018 12:59:45 +0000 Message-ID: <1536325173-16617-8-git-send-email-p.paillet@st.com> References: <1536325173-16617-1-git-send-email-p.paillet@st.com> In-Reply-To: <1536325173-16617-1-git-send-email-p.paillet@st.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-messagesentrepresentingtype: 1 x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [10.75.127.48] MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2018-09-07_07:,, signatures=0 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: pascal paillet The stpmic1 PMIC embeds a watchdog which is disabled by default. In case of watchdog, the PMIC goes off. Signed-off-by: pascal paillet Reviewed-by: Rob Herring --- 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"; +}; From patchwork Fri Sep 7 12:59:46 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pascal Paillet X-Patchwork-Id: 10592161 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5941614BD for ; Fri, 7 Sep 2018 13:01:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 49B2D2B2EA for ; Fri, 7 Sep 2018 13:01:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3E1152B2D7; Fri, 7 Sep 2018 13:01:10 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A681C2B2D7 for ; Fri, 7 Sep 2018 13:01:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729658AbeIGRlN convert rfc822-to-8bit (ORCPT ); Fri, 7 Sep 2018 13:41:13 -0400 Received: from mx08-00178001.pphosted.com ([91.207.212.93]:47354 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1729514AbeIGRlM (ORCPT ); Fri, 7 Sep 2018 13:41:12 -0400 Received: from pps.filterd (m0046661.ppops.net [127.0.0.1]) by mx08-.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id w87Cwbc5009144; Fri, 7 Sep 2018 14:59:47 +0200 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx08-00178001.pphosted.com with ESMTP id 2macwsnjst-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Fri, 07 Sep 2018 14:59:47 +0200 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 0317C3A; Fri, 7 Sep 2018 12:59:47 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag6node1.st.com [10.75.127.16]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id CD1872D4A; Fri, 7 Sep 2018 12:59:46 +0000 (GMT) Received: from SFHDAG6NODE2.st.com (10.75.127.17) by SFHDAG6NODE1.st.com (10.75.127.16) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Fri, 7 Sep 2018 14:59:47 +0200 Received: from SFHDAG6NODE2.st.com ([fe80::a56f:c186:bab7:13d6]) by SFHDAG6NODE2.st.com ([fe80::a56f:c186:bab7:13d6%20]) with mapi id 15.00.1347.000; Fri, 7 Sep 2018 14:59:46 +0200 From: Pascal PAILLET-LME 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 Subject: [PATCH V2 8/8] watchdog: stpmic1: add stpmic1 watchdog driver Thread-Topic: [PATCH V2 8/8] watchdog: stpmic1: add stpmic1 watchdog driver Thread-Index: AQHURqqnLp+FqtH8qECfWyv/F8Lufw== Date: Fri, 7 Sep 2018 12:59:46 +0000 Message-ID: <1536325173-16617-9-git-send-email-p.paillet@st.com> References: <1536325173-16617-1-git-send-email-p.paillet@st.com> In-Reply-To: <1536325173-16617-1-git-send-email-p.paillet@st.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-messagesentrepresentingtype: 1 x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [10.75.127.48] MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2018-09-07_07:,, signatures=0 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: pascal paillet 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 --- changes in v2: * the hardware component has been renamed from stpmu1 to stpmic1 ! * change headers * handle remarks from Guenter * fix set timeout drivers/watchdog/Kconfig | 12 ++++ drivers/watchdog/Makefile | 1 + drivers/watchdog/stpmic1_wdt.c | 130 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+) create mode 100644 drivers/watchdog/stpmic1_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 9af07fd..11c5937 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -796,6 +796,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 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 1d3c6b0..a898d8f 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -216,3 +216,4 @@ obj-$(CONFIG_ZIIRAVE_WATCHDOG) += ziirave_wdt.o obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o obj-$(CONFIG_MENF21BMC_WATCHDOG) += menf21bmc_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..391e544 --- /dev/null +++ b/drivers/watchdog/stpmic1_wdt.c @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) STMicroelectronics 2018 +// Author: Pascal Paillet for STMicroelectronics. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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 PMIC_WDT_MIN_TIMEOUT 1 +#define PMIC_WDT_MAX_TIMEOUT 256 + +struct stpmic1_wdt { + struct stpmic1_dev *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_START); +} + +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); + + return regmap_write(wdt->pmic->regmap, WCHDG_TIMER_CR, timeout - 1); +} + +static const struct watchdog_info pmic_watchdog_info = { + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, + .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_dev *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_MIN_TIMEOUT; + + wdt->wdtdev.status = WATCHDOG_NOWAYOUT_INIT_STATUS; + + watchdog_set_drvdata(&wdt->wdtdev, wdt); + dev_set_drvdata(&pdev->dev, 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"); +MODULE_LICENSE("GPL v2");