From patchwork Thu Nov 11 22:58:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luca Ceresoli X-Patchwork-Id: 517840 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CC2D2C43217 for ; Thu, 11 Nov 2021 22:59:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B38F861264 for ; Thu, 11 Nov 2021 22:59:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234244AbhKKXCC (ORCPT ); Thu, 11 Nov 2021 18:02:02 -0500 Received: from hostingweb31-40.netsons.net ([89.40.174.40]:56741 "EHLO hostingweb31-40.netsons.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234098AbhKKXCB (ORCPT ); Thu, 11 Nov 2021 18:02:01 -0500 Received: from [77.244.183.192] (port=63166 helo=melee.fritz.box) by hostingweb31.netsons.net with esmtpa (Exim 4.94.2) (envelope-from ) id 1mlJ2D-0007N5-PJ; Thu, 11 Nov 2021 23:59:09 +0100 From: Luca Ceresoli To: linux-kernel@vger.kernel.org Cc: Luca Ceresoli , Lee Jones , Rob Herring , Chanwoo Choi , Krzysztof Kozlowski , Bartlomiej Zolnierkiewicz , Alessandro Zummo , Alexandre Belloni , Wim Van Sebroeck , Guenter Roeck , devicetree@vger.kernel.org, linux-rtc@vger.kernel.org, linux-watchdog@vger.kernel.org, Chiwoong Byun , Laxman Dewangan , Randy Dunlap Subject: [PATCH v3 1/8] rtc: max77686: convert comments to kernel-doc format Date: Thu, 11 Nov 2021 23:58:45 +0100 Message-Id: <20211111225852.3128201-2-luca@lucaceresoli.net> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211111225852.3128201-1-luca@lucaceresoli.net> References: <20211111225852.3128201-1-luca@lucaceresoli.net> MIME-Version: 1.0 X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - hostingweb31.netsons.net X-AntiAbuse: Original Domain - vger.kernel.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - lucaceresoli.net X-Get-Message-Sender-Via: hostingweb31.netsons.net: authenticated_id: luca+lucaceresoli.net/only user confirmed/virtual account not confirmed X-Authenticated-Sender: hostingweb31.netsons.net: luca@lucaceresoli.net X-Source: X-Source-Args: X-Source-Dir: Precedence: bulk List-ID: X-Mailing-List: linux-watchdog@vger.kernel.org Convert the comments documenting this struct to kernel-doc format for standardization and readability. Signed-off-by: Luca Ceresoli Reviewed-by: Krzysztof Kozlowski Acked-by: Alexandre Belloni --- Changes in v3: none Changes in v2: none --- drivers/rtc/rtc-max77686.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index eae7cb9faf1e..bac52cdea97d 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -61,24 +61,27 @@ enum { RTC_NR_TIME }; +/** + * struct max77686_rtc_driver_data - model-specific configuration + * @delay: Minimum usecs needed for a RTC update + * @mask: Mask used to read RTC registers value + * @map: Registers offset to I2C addresses map + * @alarm_enable_reg: Has a separate alarm enable register? + * @rtc_i2c_addr: I2C address for RTC block + * @rtc_irq_from_platform: RTC interrupt via platform resource + * @alarm_pending_status_reg: Pending alarm status register + * @rtc_irq_chip: RTC IRQ CHIP for regmap + * @regmap_config: regmap configuration for the chip + */ struct max77686_rtc_driver_data { - /* Minimum usecs needed for a RTC update */ unsigned long delay; - /* Mask used to read RTC registers value */ u8 mask; - /* Registers offset to I2C addresses map */ const unsigned int *map; - /* Has a separate alarm enable register? */ bool alarm_enable_reg; - /* I2C address for RTC block */ int rtc_i2c_addr; - /* RTC interrupt via platform resource */ bool rtc_irq_from_platform; - /* Pending alarm status register */ int alarm_pending_status_reg; - /* RTC IRQ CHIP for regmap */ const struct regmap_irq_chip *rtc_irq_chip; - /* regmap configuration for the chip */ const struct regmap_config *regmap_config; }; From patchwork Thu Nov 11 22:58:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luca Ceresoli X-Patchwork-Id: 517839 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8E047C433FE for ; Thu, 11 Nov 2021 22:59:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7781561264 for ; Thu, 11 Nov 2021 22:59:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234332AbhKKXCI (ORCPT ); Thu, 11 Nov 2021 18:02:08 -0500 Received: from hostingweb31-40.netsons.net ([89.40.174.40]:38423 "EHLO hostingweb31-40.netsons.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234353AbhKKXCG (ORCPT ); Thu, 11 Nov 2021 18:02:06 -0500 Received: from [77.244.183.192] (port=63166 helo=melee.fritz.box) by hostingweb31.netsons.net with esmtpa (Exim 4.94.2) (envelope-from ) id 1mlJ2I-0007N5-OR; Thu, 11 Nov 2021 23:59:14 +0100 From: Luca Ceresoli To: linux-kernel@vger.kernel.org Cc: Luca Ceresoli , Lee Jones , Rob Herring , Chanwoo Choi , Krzysztof Kozlowski , Bartlomiej Zolnierkiewicz , Alessandro Zummo , Alexandre Belloni , Wim Van Sebroeck , Guenter Roeck , devicetree@vger.kernel.org, linux-rtc@vger.kernel.org, linux-watchdog@vger.kernel.org, Chiwoong Byun , Laxman Dewangan , Randy Dunlap Subject: [PATCH v3 3/8] rtc: max77686: remove unused code to read in 12-hour mode Date: Thu, 11 Nov 2021 23:58:47 +0100 Message-Id: <20211111225852.3128201-4-luca@lucaceresoli.net> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211111225852.3128201-1-luca@lucaceresoli.net> References: <20211111225852.3128201-1-luca@lucaceresoli.net> MIME-Version: 1.0 X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - hostingweb31.netsons.net X-AntiAbuse: Original Domain - vger.kernel.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - lucaceresoli.net X-Get-Message-Sender-Via: hostingweb31.netsons.net: authenticated_id: luca+lucaceresoli.net/only user confirmed/virtual account not confirmed X-Authenticated-Sender: hostingweb31.netsons.net: luca@lucaceresoli.net X-Source: X-Source-Args: X-Source-Dir: Precedence: bulk List-ID: X-Mailing-List: linux-watchdog@vger.kernel.org The MAX77714 RTC chip is explicitly set to 24-hour mode in max77686_rtc_probe() -> max77686_rtc_init_reg() and never changed back to 12-hour mode. Accordingly info->rtc_24hr_mode is set to 1 in the same place and never modified later, so it is de facto a constant. Yet there is code to read 12-hour time, which is unreachable. Remove the unused variable, the unreachable code to manage 12-hour mode and the defines that become unused due to the above changes. Signed-off-by: Luca Ceresoli Reviewed-by: Krzysztof Kozlowski Acked-by: Alexandre Belloni --- Changes in v3: none Changes in v2: - remove the now-unused defines too (Alexandre Belloni) - improve the commit message --- drivers/rtc/rtc-max77686.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 7e765207f28e..5c64d08c0732 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -34,9 +34,6 @@ #define RTC_UDR_MASK BIT(RTC_UDR_SHIFT) #define RTC_RBUDR_SHIFT 4 #define RTC_RBUDR_MASK BIT(RTC_RBUDR_SHIFT) -/* RTC Hour register */ -#define HOUR_PM_SHIFT 6 -#define HOUR_PM_MASK BIT(HOUR_PM_SHIFT) /* RTC Alarm Enable */ #define ALARM_ENABLE_SHIFT 7 #define ALARM_ENABLE_MASK BIT(ALARM_ENABLE_SHIFT) @@ -99,7 +96,6 @@ struct max77686_rtc_info { int rtc_irq; int virq; - int rtc_24hr_mode; }; enum MAX77686_RTC_OP { @@ -278,13 +274,7 @@ static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm, tm->tm_sec = data[RTC_SEC] & mask; tm->tm_min = data[RTC_MIN] & mask; - if (info->rtc_24hr_mode) { - tm->tm_hour = data[RTC_HOUR] & 0x1f; - } else { - tm->tm_hour = data[RTC_HOUR] & 0x0f; - if (data[RTC_HOUR] & HOUR_PM_MASK) - tm->tm_hour += 12; - } + tm->tm_hour = data[RTC_HOUR] & 0x1f; /* Only a single bit is set in data[], so fls() would be equivalent */ tm->tm_wday = ffs(data[RTC_WEEKDAY] & mask) - 1; @@ -662,8 +652,6 @@ static int max77686_rtc_init_reg(struct max77686_rtc_info *info) data[0] = (1 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); - info->rtc_24hr_mode = 1; - ret = regmap_bulk_write(info->rtc_regmap, info->drv_data->map[REG_RTC_CONTROLM], data, ARRAY_SIZE(data)); From patchwork Thu Nov 11 22:58:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luca Ceresoli X-Patchwork-Id: 517838 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 872FEC433EF for ; Thu, 11 Nov 2021 22:59:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7294861208 for ; Thu, 11 Nov 2021 22:59:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234249AbhKKXCi (ORCPT ); Thu, 11 Nov 2021 18:02:38 -0500 Received: from hostingweb31-40.netsons.net ([89.40.174.40]:32877 "EHLO hostingweb31-40.netsons.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234240AbhKKXCh (ORCPT ); Thu, 11 Nov 2021 18:02:37 -0500 Received: from [77.244.183.192] (port=63166 helo=melee.fritz.box) by hostingweb31.netsons.net with esmtpa (Exim 4.94.2) (envelope-from ) id 1mlJ2o-0007N5-6M; Thu, 11 Nov 2021 23:59:46 +0100 From: Luca Ceresoli To: linux-kernel@vger.kernel.org Cc: Luca Ceresoli , Lee Jones , Rob Herring , Chanwoo Choi , Krzysztof Kozlowski , Bartlomiej Zolnierkiewicz , Alessandro Zummo , Alexandre Belloni , Wim Van Sebroeck , Guenter Roeck , devicetree@vger.kernel.org, linux-rtc@vger.kernel.org, linux-watchdog@vger.kernel.org, Chiwoong Byun , Laxman Dewangan , Randy Dunlap Subject: [PATCH v3 5/8] mfd: max77714: Add driver for Maxim MAX77714 PMIC Date: Thu, 11 Nov 2021 23:58:49 +0100 Message-Id: <20211111225852.3128201-6-luca@lucaceresoli.net> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211111225852.3128201-1-luca@lucaceresoli.net> References: <20211111225852.3128201-1-luca@lucaceresoli.net> MIME-Version: 1.0 X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - hostingweb31.netsons.net X-AntiAbuse: Original Domain - vger.kernel.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - lucaceresoli.net X-Get-Message-Sender-Via: hostingweb31.netsons.net: authenticated_id: luca+lucaceresoli.net/only user confirmed/virtual account not confirmed X-Authenticated-Sender: hostingweb31.netsons.net: luca@lucaceresoli.net X-Source: X-Source-Args: X-Source-Dir: Precedence: bulk List-ID: X-Mailing-List: linux-watchdog@vger.kernel.org Add a simple driver for the Maxim MAX77714 PMIC, supporting RTC and watchdog only. Signed-off-by: Luca Ceresoli --- Changes in v3: - Suggested by Lee Jones: - move struct mfd_cell to top of file - remove struct max77714 and its kmalloc, not used after probe - reword error messages - add "/* pF */" onto the end of the load_cap line Changes in v2: - fix "watchdog" word in heading comment (Guenter Roeck) - move struct max77714 to .c file (Krzysztof Kozlowski) - change include guard format (Krzysztof Kozlowski) - allow building as a module (Krzysztof Kozlowski) - remove of_match_ptr usage (Krzysztof Kozlowski / lkp) (Reported-by: kernel test robot ) --- MAINTAINERS | 2 + drivers/mfd/Kconfig | 14 ++++ drivers/mfd/Makefile | 1 + drivers/mfd/max77714.c | 152 +++++++++++++++++++++++++++++++++++ include/linux/mfd/max77714.h | 60 ++++++++++++++ 5 files changed, 229 insertions(+) create mode 100644 drivers/mfd/max77714.c create mode 100644 include/linux/mfd/max77714.h diff --git a/MAINTAINERS b/MAINTAINERS index af4e6dc948a3..1a37b9422c5f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11572,6 +11572,8 @@ MAXIM MAX77714 PMIC MFD DRIVER M: Luca Ceresoli S: Maintained F: Documentation/devicetree/bindings/mfd/maxim,max77714.yaml +F: drivers/mfd/max77714.c +F: include/linux/mfd/max77714.h MAXIM MAX77802 PMIC REGULATOR DEVICE DRIVER M: Javier Martinez Canillas diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 3fb480818599..1b9d772bdae6 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -855,6 +855,20 @@ config MFD_MAX77693 additional drivers must be enabled in order to use the functionality of the device. +config MFD_MAX77714 + tristate "Maxim Semiconductor MAX77714 PMIC Support" + depends on I2C + depends on OF || COMPILE_TEST + select MFD_CORE + select REGMAP_I2C + help + Say yes here to add support for Maxim Semiconductor MAX77714. + This is a Power Management IC with 4 buck regulators, 9 + low-dropout regulators, 8 GPIOs, RTC, watchdog etc. This driver + provides common support for accessing the device; additional + drivers must be enabled in order to use each functionality of the + device. + config MFD_MAX77843 bool "Maxim Semiconductor MAX77843 PMIC Support" depends on I2C=y diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 0b1b629aef3e..03115cf1336b 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -162,6 +162,7 @@ obj-$(CONFIG_MFD_MAX77620) += max77620.o obj-$(CONFIG_MFD_MAX77650) += max77650.o obj-$(CONFIG_MFD_MAX77686) += max77686.o obj-$(CONFIG_MFD_MAX77693) += max77693.o +obj-$(CONFIG_MFD_MAX77714) += max77714.o obj-$(CONFIG_MFD_MAX77843) += max77843.o obj-$(CONFIG_MFD_MAX8907) += max8907.o max8925-objs := max8925-core.o max8925-i2c.o diff --git a/drivers/mfd/max77714.c b/drivers/mfd/max77714.c new file mode 100644 index 000000000000..08dfb69bc6e8 --- /dev/null +++ b/drivers/mfd/max77714.c @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Maxim MAX77714 MFD Driver + * + * Copyright (C) 2021 Luca Ceresoli + * Author: Luca Ceresoli + */ + +#include +#include +#include +#include +#include +#include +#include + +static const struct mfd_cell max77714_cells[] = { + { .name = "max77714-watchdog" }, + { .name = "max77714-rtc" }, +}; + +static const struct regmap_range max77714_readable_ranges[] = { + regmap_reg_range(MAX77714_INT_TOP, MAX77714_INT_TOP), + regmap_reg_range(MAX77714_INT_TOPM, MAX77714_INT_TOPM), + regmap_reg_range(MAX77714_32K_STATUS, MAX77714_32K_CONFIG), + regmap_reg_range(MAX77714_CNFG_GLBL2, MAX77714_CNFG2_ONOFF), +}; + +static const struct regmap_range max77714_writable_ranges[] = { + regmap_reg_range(MAX77714_INT_TOPM, MAX77714_INT_TOPM), + regmap_reg_range(MAX77714_32K_CONFIG, MAX77714_32K_CONFIG), + regmap_reg_range(MAX77714_CNFG_GLBL2, MAX77714_CNFG2_ONOFF), +}; + +static const struct regmap_access_table max77714_readable_table = { + .yes_ranges = max77714_readable_ranges, + .n_yes_ranges = ARRAY_SIZE(max77714_readable_ranges), +}; + +static const struct regmap_access_table max77714_writable_table = { + .yes_ranges = max77714_writable_ranges, + .n_yes_ranges = ARRAY_SIZE(max77714_writable_ranges), +}; + +static const struct regmap_config max77714_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = MAX77714_CNFG2_ONOFF, + .rd_table = &max77714_readable_table, + .wr_table = &max77714_writable_table, +}; + +static const struct regmap_irq max77714_top_irqs[] = { + REGMAP_IRQ_REG(MAX77714_IRQ_TOP_ONOFF, 0, MAX77714_INT_TOP_ONOFF), + REGMAP_IRQ_REG(MAX77714_IRQ_TOP_RTC, 0, MAX77714_INT_TOP_RTC), + REGMAP_IRQ_REG(MAX77714_IRQ_TOP_GPIO, 0, MAX77714_INT_TOP_GPIO), + REGMAP_IRQ_REG(MAX77714_IRQ_TOP_LDO, 0, MAX77714_INT_TOP_LDO), + REGMAP_IRQ_REG(MAX77714_IRQ_TOP_SD, 0, MAX77714_INT_TOP_SD), + REGMAP_IRQ_REG(MAX77714_IRQ_TOP_GLBL, 0, MAX77714_INT_TOP_GLBL), +}; + +static const struct regmap_irq_chip max77714_irq_chip = { + .name = "max77714-pmic", + .status_base = MAX77714_INT_TOP, + .mask_base = MAX77714_INT_TOPM, + .num_regs = 1, + .irqs = max77714_top_irqs, + .num_irqs = ARRAY_SIZE(max77714_top_irqs), +}; + +/* + * MAX77714 initially uses the internal, low precision oscillator. Enable + * the external oscillator by setting the XOSC_RETRY bit. If the external + * oscillator is not OK (probably not installed) this has no effect. + */ +static int max77714_setup_xosc(struct device *dev, struct regmap *regmap) +{ + /* Internal Crystal Load Capacitance, indexed by value of 32KLOAD bits */ + static const unsigned int load_cap[4] = {0, 10, 12, 22}; /* pF */ + unsigned int load_cap_idx; + unsigned int status; + int err; + + err = regmap_update_bits(regmap, MAX77714_32K_CONFIG, + MAX77714_32K_CONFIG_XOSC_RETRY, + MAX77714_32K_CONFIG_XOSC_RETRY); + if (err) + return dev_err_probe(dev, err, "Failed to configure the external oscillator\n"); + + err = regmap_read(regmap, MAX77714_32K_STATUS, &status); + if (err) + return dev_err_probe(dev, err, "Failed to read external oscillator status\n"); + + load_cap_idx = (status >> MAX77714_32K_STATUS_32KLOAD_SHF) + & MAX77714_32K_STATUS_32KLOAD_MSK; + + dev_info(dev, "Using %s oscillator, %d pF load cap\n", + status & MAX77714_32K_STATUS_32KSOURCE ? "internal" : "external", + load_cap[load_cap_idx]); + + return 0; +} + +static int max77714_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct regmap *regmap; + struct regmap_irq_chip_data *irq_data; + int err; + + regmap = devm_regmap_init_i2c(client, &max77714_regmap_config); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), + "Failed to initialise regmap\n"); + + err = max77714_setup_xosc(dev, regmap); + if (err) + return err; + + err = devm_regmap_add_irq_chip(dev, regmap, client->irq, + IRQF_ONESHOT | IRQF_SHARED, 0, + &max77714_irq_chip, &irq_data); + if (err) + return dev_err_probe(dev, err, "Failed to add PMIC IRQ chip\n"); + + err = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, + max77714_cells, ARRAY_SIZE(max77714_cells), + NULL, 0, NULL); + if (err) + return dev_err_probe(dev, err, "Failed to register child devices\n"); + + return 0; +} + +static const struct of_device_id max77714_dt_match[] = { + { .compatible = "maxim,max77714" }, + {}, +}; +MODULE_DEVICE_TABLE(of, max77714_dt_match); + +static struct i2c_driver max77714_driver = { + .driver = { + .name = "max77714", + .of_match_table = max77714_dt_match, + }, + .probe_new = max77714_probe, +}; +module_i2c_driver(max77714_driver); + +MODULE_DESCRIPTION("Maxim MAX77714 MFD core driver"); +MODULE_AUTHOR("Luca Ceresoli "); +MODULE_LICENSE("GPL"); diff --git a/include/linux/mfd/max77714.h b/include/linux/mfd/max77714.h new file mode 100644 index 000000000000..4a274592d4f2 --- /dev/null +++ b/include/linux/mfd/max77714.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Maxim MAX77714 Register and data structures definition. + * + * Copyright (C) 2021 Luca Ceresoli + * Author: Luca Ceresoli + */ + +#ifndef __LINUX_MFD_MAX77714_H_ +#define __LINUX_MFD_MAX77714_H_ + +#include + +#define MAX77714_INT_TOP 0x00 +#define MAX77714_INT_TOPM 0x07 /* Datasheet says "read only", but it is RW */ + +#define MAX77714_INT_TOP_ONOFF BIT(1) +#define MAX77714_INT_TOP_RTC BIT(3) +#define MAX77714_INT_TOP_GPIO BIT(4) +#define MAX77714_INT_TOP_LDO BIT(5) +#define MAX77714_INT_TOP_SD BIT(6) +#define MAX77714_INT_TOP_GLBL BIT(7) + +#define MAX77714_32K_STATUS 0x30 +#define MAX77714_32K_STATUS_SIOSCOK BIT(5) +#define MAX77714_32K_STATUS_XOSCOK BIT(4) +#define MAX77714_32K_STATUS_32KSOURCE BIT(3) +#define MAX77714_32K_STATUS_32KLOAD_MSK 0x3 +#define MAX77714_32K_STATUS_32KLOAD_SHF 1 +#define MAX77714_32K_STATUS_CRYSTAL_CFG BIT(0) + +#define MAX77714_32K_CONFIG 0x31 +#define MAX77714_32K_CONFIG_XOSC_RETRY BIT(4) + +#define MAX77714_CNFG_GLBL2 0x91 +#define MAX77714_WDTEN BIT(2) +#define MAX77714_WDTSLPC BIT(3) +#define MAX77714_TWD_MASK 0x3 +#define MAX77714_TWD_2s 0x0 +#define MAX77714_TWD_16s 0x1 +#define MAX77714_TWD_64s 0x2 +#define MAX77714_TWD_128s 0x3 + +#define MAX77714_CNFG_GLBL3 0x92 +#define MAX77714_WDTC BIT(0) + +#define MAX77714_CNFG2_ONOFF 0x94 +#define MAX77714_WD_RST_WK BIT(5) + +/* Interrupts */ +enum { + MAX77714_IRQ_TOP_ONOFF, + MAX77714_IRQ_TOP_RTC, /* Real-time clock */ + MAX77714_IRQ_TOP_GPIO, /* GPIOs */ + MAX77714_IRQ_TOP_LDO, /* Low-dropout regulators */ + MAX77714_IRQ_TOP_SD, /* Step-down regulators */ + MAX77714_IRQ_TOP_GLBL, /* "Global resources": Low-Battery, overtemp... */ +}; + +#endif /* __LINUX_MFD_MAX77714_H_ */ From patchwork Thu Nov 11 22:58:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luca Ceresoli X-Patchwork-Id: 517837 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CC5D9C433FE for ; Thu, 11 Nov 2021 23:00:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B894561208 for ; Thu, 11 Nov 2021 23:00:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234473AbhKKXDD (ORCPT ); Thu, 11 Nov 2021 18:03:03 -0500 Received: from hostingweb31-40.netsons.net ([89.40.174.40]:43519 "EHLO hostingweb31-40.netsons.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234453AbhKKXDC (ORCPT ); Thu, 11 Nov 2021 18:03:02 -0500 Received: from [77.244.183.192] (port=63166 helo=melee.fritz.box) by hostingweb31.netsons.net with esmtpa (Exim 4.94.2) (envelope-from ) id 1mlJ3D-0007N5-B6; Fri, 12 Nov 2021 00:00:11 +0100 From: Luca Ceresoli To: linux-kernel@vger.kernel.org Cc: Luca Ceresoli , Lee Jones , Rob Herring , Chanwoo Choi , Krzysztof Kozlowski , Bartlomiej Zolnierkiewicz , Alessandro Zummo , Alexandre Belloni , Wim Van Sebroeck , Guenter Roeck , devicetree@vger.kernel.org, linux-rtc@vger.kernel.org, linux-watchdog@vger.kernel.org, Chiwoong Byun , Laxman Dewangan , Randy Dunlap Subject: [PATCH v3 7/8] watchdog: max77714: add driver for the watchdog in the MAX77714 PMIC Date: Thu, 11 Nov 2021 23:58:51 +0100 Message-Id: <20211111225852.3128201-8-luca@lucaceresoli.net> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211111225852.3128201-1-luca@lucaceresoli.net> References: <20211111225852.3128201-1-luca@lucaceresoli.net> MIME-Version: 1.0 X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - hostingweb31.netsons.net X-AntiAbuse: Original Domain - vger.kernel.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - lucaceresoli.net X-Get-Message-Sender-Via: hostingweb31.netsons.net: authenticated_id: luca+lucaceresoli.net/only user confirmed/virtual account not confirmed X-Authenticated-Sender: hostingweb31.netsons.net: luca@lucaceresoli.net X-Source: X-Source-Args: X-Source-Dir: Precedence: bulk List-ID: X-Mailing-List: linux-watchdog@vger.kernel.org Add a simple driver to support the watchdog embedded in the Maxim MAX77714 PMIC. Signed-off-by: Luca Ceresoli --- Changes in v3: none Changes in v2: - fix Kconfig help indentation (Randy Dunlap) - make max77714_margin_value static const (Guenter Roeck) - fix platform module instantiation --- MAINTAINERS | 1 + drivers/watchdog/Kconfig | 9 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/max77714_wdt.c | 179 ++++++++++++++++++++++++++++++++ 4 files changed, 190 insertions(+) create mode 100644 drivers/watchdog/max77714_wdt.c diff --git a/MAINTAINERS b/MAINTAINERS index 1a37b9422c5f..d182231b4bbf 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11573,6 +11573,7 @@ M: Luca Ceresoli S: Maintained F: Documentation/devicetree/bindings/mfd/maxim,max77714.yaml F: drivers/mfd/max77714.c +F: drivers/watchdog/max77714_wdt.c F: include/linux/mfd/max77714.h MAXIM MAX77802 PMIC REGULATOR DEVICE DRIVER diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index a6d97f30325a..f5100b731927 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -685,6 +685,15 @@ config MAX77620_WATCHDOG MAX77620 chips. To compile this driver as a module, choose M here: the module will be called max77620_wdt. +config MAX77714_WATCHDOG + tristate "Maxim MAX77714 Watchdog Timer" + depends on MFD_MAX77714 || COMPILE_TEST + help + This is the driver for watchdog timer in the MAX77714 PMIC. + Say 'Y' here to enable the watchdog timer support for MAX77714 + chips. To compile this driver as a module, choose M here: the + module will be called max77714_wdt. + config IMX2_WDT tristate "IMX2+ Watchdog" depends on ARCH_MXC || ARCH_LAYERSCAPE || COMPILE_TEST diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 2ee97064145b..575be33c52b8 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -214,6 +214,7 @@ obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o obj-$(CONFIG_MAX63XX_WATCHDOG) += max63xx_wdt.o obj-$(CONFIG_MAX77620_WATCHDOG) += max77620_wdt.o +obj-$(CONFIG_MAX77714_WATCHDOG) += max77714_wdt.o obj-$(CONFIG_ZIIRAVE_WATCHDOG) += ziirave_wdt.o obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o obj-$(CONFIG_MENF21BMC_WATCHDOG) += menf21bmc_wdt.o diff --git a/drivers/watchdog/max77714_wdt.c b/drivers/watchdog/max77714_wdt.c new file mode 100644 index 000000000000..cce6c13d76eb --- /dev/null +++ b/drivers/watchdog/max77714_wdt.c @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Maxim MAX77714 Watchdog Driver + * + * Copyright (C) 2021 Luca Ceresoli + * Author: Luca Ceresoli + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct max77714_wdt { + struct device *dev; + struct regmap *rmap; + struct watchdog_device wd_dev; +}; + +/* Timeout in seconds, indexed by TWD bits of CNFG_GLBL2 register */ +static const unsigned int max77714_margin_value[] = { 2, 16, 64, 128 }; + +static int max77714_wdt_start(struct watchdog_device *wd_dev) +{ + struct max77714_wdt *wdt = watchdog_get_drvdata(wd_dev); + + return regmap_update_bits(wdt->rmap, MAX77714_CNFG_GLBL2, + MAX77714_WDTEN, MAX77714_WDTEN); +} + +static int max77714_wdt_stop(struct watchdog_device *wd_dev) +{ + struct max77714_wdt *wdt = watchdog_get_drvdata(wd_dev); + + return regmap_update_bits(wdt->rmap, MAX77714_CNFG_GLBL2, + MAX77714_WDTEN, 0); +} + +static int max77714_wdt_ping(struct watchdog_device *wd_dev) +{ + struct max77714_wdt *wdt = watchdog_get_drvdata(wd_dev); + + return regmap_update_bits(wdt->rmap, MAX77714_CNFG_GLBL3, + MAX77714_WDTC, 1); +} + +static int max77714_wdt_set_timeout(struct watchdog_device *wd_dev, + unsigned int timeout) +{ + struct max77714_wdt *wdt = watchdog_get_drvdata(wd_dev); + unsigned int new_timeout, new_twd; + int err; + + for (new_twd = 0; new_twd < ARRAY_SIZE(max77714_margin_value) - 1; new_twd++) + if (timeout <= max77714_margin_value[new_twd]) + break; + + /* new_wdt is not out of bounds here due to the "- 1" in the for loop */ + new_timeout = max77714_margin_value[new_twd]; + + /* + * "If the value of TWD needs to be changed, clear the system + * watchdog timer first [...], then change the value of TWD." + * (MAX77714 datasheet) + */ + err = regmap_update_bits(wdt->rmap, MAX77714_CNFG_GLBL3, + MAX77714_WDTC, 1); + if (err) + return err; + + err = regmap_update_bits(wdt->rmap, MAX77714_CNFG_GLBL2, + MAX77714_TWD_MASK, new_twd); + if (err) + return err; + + wd_dev->timeout = new_timeout; + + dev_dbg(wdt->dev, "New timeout = %u s (WDT = 0x%x)", new_timeout, new_twd); + + return 0; +} + +static const struct watchdog_info max77714_wdt_info = { + .identity = "max77714-watchdog", + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, +}; + +static const struct watchdog_ops max77714_wdt_ops = { + .start = max77714_wdt_start, + .stop = max77714_wdt_stop, + .ping = max77714_wdt_ping, + .set_timeout = max77714_wdt_set_timeout, +}; + +static int max77714_wdt_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct max77714_wdt *wdt; + struct watchdog_device *wd_dev; + unsigned int regval; + int err; + + wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); + if (!wdt) + return -ENOMEM; + + wdt->dev = dev; + + wd_dev = &wdt->wd_dev; + wd_dev->info = &max77714_wdt_info; + wd_dev->ops = &max77714_wdt_ops; + wd_dev->min_timeout = 2; + wd_dev->max_timeout = 128; + + platform_set_drvdata(pdev, wdt); + watchdog_set_drvdata(wd_dev, wdt); + + wdt->rmap = dev_get_regmap(dev->parent, NULL); + if (!wdt->rmap) + return dev_err_probe(wdt->dev, -ENODEV, "Failed to get parent regmap\n"); + + /* WD_RST_WK: if 1 wdog restarts; if 0 wdog shuts down */ + err = regmap_update_bits(wdt->rmap, MAX77714_CNFG2_ONOFF, + MAX77714_WD_RST_WK, MAX77714_WD_RST_WK); + if (err) + return dev_err_probe(wdt->dev, err, "Error updating CNFG2_ONOFF\n"); + + err = regmap_read(wdt->rmap, MAX77714_CNFG_GLBL2, ®val); + if (err) + return dev_err_probe(wdt->dev, err, "Error reading CNFG_GLBL2\n"); + + /* enable watchdog | enable auto-clear in sleep state */ + regval |= (MAX77714_WDTEN | MAX77714_WDTSLPC); + + err = regmap_write(wdt->rmap, MAX77714_CNFG_GLBL2, regval); + if (err) + return dev_err_probe(wdt->dev, err, "Error writing CNFG_GLBL2\n"); + + wd_dev->timeout = max77714_margin_value[regval & MAX77714_TWD_MASK]; + + dev_dbg(wdt->dev, "Timeout = %u s (WDT = 0x%x)", + wd_dev->timeout, regval & MAX77714_TWD_MASK); + + set_bit(WDOG_HW_RUNNING, &wd_dev->status); + + watchdog_stop_on_unregister(wd_dev); + + err = devm_watchdog_register_device(dev, wd_dev); + if (err) + return dev_err_probe(dev, err, "Cannot register watchdog device\n"); + + dev_info(dev, "registered as /dev/watchdog%d\n", wd_dev->id); + + return 0; +} + +static const struct platform_device_id max77714_wdt_platform_id[] = { + { .name = "max77714-watchdog", }, + { }, +}; +MODULE_DEVICE_TABLE(platform, max77714_wdt_platform_id); + +static struct platform_driver max77714_wdt_driver = { + .driver = { + .name = "max77714-watchdog", + }, + .probe = max77714_wdt_probe, + .id_table = max77714_wdt_platform_id, +}; + +module_platform_driver(max77714_wdt_driver); + +MODULE_DESCRIPTION("MAX77714 watchdog timer driver"); +MODULE_AUTHOR("Luca Ceresoli "); +MODULE_LICENSE("GPL v2");