From patchwork Thu Oct 24 11:41:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matti Vaittinen X-Patchwork-Id: 1182928 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-rtc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=fi.rohmeurope.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46zQLX2Y0Sz9sR0 for ; Thu, 24 Oct 2019 22:41:24 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2439080AbfJXLlV (ORCPT ); Thu, 24 Oct 2019 07:41:21 -0400 Received: from mail-lf1-f68.google.com ([209.85.167.68]:42748 "EHLO mail-lf1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2439076AbfJXLlV (ORCPT ); Thu, 24 Oct 2019 07:41:21 -0400 Received: by mail-lf1-f68.google.com with SMTP id z12so18845646lfj.9; Thu, 24 Oct 2019 04:41:17 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=kw7dSBruWUrZoj5zRObRXHFH9ulr0a8JCQ689nhqK14=; b=m+aewNqUB5EXFKEatsFwHx3E80ytB6P83k1jurwSTOiNLbXNNvhzNNu1HaeDWf5mYB QZPI68SEoojHdMm5iT7Ucjx9F2rlw11MshWhpwwm7Ln/CrW9ZsdadcsDkZxO/mNj5URf LdlysaTAvjY1ny90/Qpgy8h89IHwOzqW+8iac4LqjWAXpXkAGPfU0m6UxTkgbiix/FRQ RFTkj41c8HkBcKNgDoUWQ6fqspgZBb2yNDvRHzcNV6h8myK/QNhHs2RNQSeMIXf6evCq uytq5Bm7ZczumEZYajeXOmdvw72Tw+NE9x/FID/SPkcyDTQvJsCN5YFJZ1725HLjR9Xg rX5w== X-Gm-Message-State: APjAAAU7tlGsA3Djl0UGX1MsbyuH2r7v9/8wRQ62cK4m1lXCt1PSgU/5 FPC4+mNWiG4qwssYEe6nZXI= X-Google-Smtp-Source: APXvYqzFOfe8lgMihKXF/vw7Et4tO3thPhSEYIWBSDn0cddbOFLKpzWbBBjlQx6W7FVR4BPgGOUNBw== X-Received: by 2002:ac2:44ba:: with SMTP id c26mr13969907lfm.20.1571917276266; Thu, 24 Oct 2019 04:41:16 -0700 (PDT) Received: from localhost.localdomain ([213.255.186.46]) by smtp.gmail.com with ESMTPSA id b141sm11992992lfg.67.2019.10.24.04.41.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 24 Oct 2019 04:41:15 -0700 (PDT) Date: Thu, 24 Oct 2019 14:41:03 +0300 From: Matti Vaittinen To: matti.vaittinen@fi.rohmeurope.com, mazziesaccount@gmail.com Cc: Lee Jones , Rob Herring , Mark Rutland , Liam Girdwood , Mark Brown , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Jacek Anaszewski , Pavel Machek , Dan Murphy , Alessandro Zummo , Alexandre Belloni , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-leds@vger.kernel.org, linux-rtc@vger.kernel.org Subject: [RFC PATCH v2 01/13] mfd: bd71828: Support ROHM BD71828 PMIC - core Message-ID: References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.12.1 (2019-06-15) Sender: linux-rtc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rtc@vger.kernel.org BD71828GW is a single-chip power management IC for battery-powered portable devices. The IC integrates 7 buck converters, 7 LDOs, and a 1500 mA single-cell linear charger. Also included is a Coulomb counter, a real-time clock (RTC), 3 GPO/regulator control pins, HALL input and a 32.768 kHz clock gate. Add MFD core driver providing interrupt controller facilities and i2c access to sub device drivers. Signed-off-by: Matti Vaittinen --- No changes since v1 drivers/mfd/Kconfig | 15 ++ drivers/mfd/Makefile | 2 +- drivers/mfd/rohm-bd71828.c | 322 +++++++++++++++++++++++ include/linux/mfd/rohm-bd71828.h | 425 +++++++++++++++++++++++++++++++ include/linux/mfd/rohm-generic.h | 1 + 5 files changed, 764 insertions(+), 1 deletion(-) create mode 100644 drivers/mfd/rohm-bd71828.c create mode 100644 include/linux/mfd/rohm-bd71828.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index f129f9678940..c0d6d3921f18 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1921,6 +1921,21 @@ config MFD_ROHM_BD70528 10 bits SAR ADC for battery temperature monitor and 1S battery charger. +config MFD_ROHM_BD71828 + tristate "ROHM BD71828 Power Management IC" + depends on I2C=y + depends on OF + select REGMAP_I2C + select REGMAP_IRQ + select MFD_CORE + help + Select this option to get support for the ROHM BD71828 Power + Management IC. BD71828GW is a single-chip power management IC for + battery-powered portable devices. The IC integrates 7 buck + converters, 7 LDOs, and a 1500 mA single-cell linear charger. + Also included is a Coulomb counter, a real-time clock (RTC), and + a 32.768 kHz clock gate. + config MFD_STM32_LPTIMER tristate "Support for STM32 Low-Power Timer" depends on (ARCH_STM32 && OF) || COMPILE_TEST diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index f026ada68f6a..d154dfcaf665 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -254,6 +254,6 @@ obj-$(CONFIG_MFD_MXS_LRADC) += mxs-lradc.o obj-$(CONFIG_MFD_SC27XX_PMIC) += sprd-sc27xx-spi.o obj-$(CONFIG_RAVE_SP_CORE) += rave-sp.o obj-$(CONFIG_MFD_ROHM_BD70528) += rohm-bd70528.o +obj-$(CONFIG_MFD_ROHM_BD71828) += rohm-bd71828.o obj-$(CONFIG_MFD_ROHM_BD718XX) += rohm-bd718x7.o obj-$(CONFIG_MFD_STMFX) += stmfx.o - diff --git a/drivers/mfd/rohm-bd71828.c b/drivers/mfd/rohm-bd71828.c new file mode 100644 index 000000000000..b7de79e1fcdb --- /dev/null +++ b/drivers/mfd/rohm-bd71828.c @@ -0,0 +1,322 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// +// Copyright (C) 2019 ROHM Semiconductors +// +// ROHM BD71828 PMIC driver + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct resource rtc_irqs[] = { + DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC0, "bd71828-rtc-alm-0"), + DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC1, "bd71828-rtc-alm-1"), + DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC2, "bd71828-rtc-alm-2"), +}; + +static struct mfd_cell bd71828_mfd_cells[] = { + { .name = "bd71828-pmic", }, + { .name = "bd71828-gpio", }, + { .name = "bd71828-led", }, + /* + * We use BD71837 driver to drive the clock block. Only differences to + * BD70528 clock gate are the register address and mask. + */ + { .name = "bd718xx-clk", }, + { + .name = "bd71827-power", + }, { + .name = "bd70528-rtc", + .resources = rtc_irqs, + .num_resources = ARRAY_SIZE(rtc_irqs), + }, +}; + +static const struct regmap_range volatile_ranges[] = { + { + .range_min = BD71828_REG_PS_CTRL_1, + .range_max = BD71828_REG_PS_CTRL_1, + }, { + .range_min = BD71828_REG_PS_CTRL_3, + .range_max = BD71828_REG_PS_CTRL_3, + }, { + .range_min = BD71828_REG_RTC_SEC, + .range_max = BD71828_REG_RTC_YEAR, + }, { + /* + * For now make all charger registers volatile because many + * needs to be and because the charger block is not that + * performance critical. TBD: Check which charger registers + * could be cached + */ + .range_min = BD71828_REG_CHG_STATE, + .range_max = BD71828_REG_CHG_FULL, + }, { + .range_min = BD71828_REG_INT_MAIN, + .range_max = BD71828_REG_IO_STAT, + }, +}; + +static const struct regmap_access_table volatile_regs = { + .yes_ranges = &volatile_ranges[0], + .n_yes_ranges = ARRAY_SIZE(volatile_ranges), +}; + +static struct regmap_config bd71828_regmap = { + .reg_bits = 8, + .val_bits = 8, + .volatile_table = &volatile_regs, + .max_register = BD71828_MAX_REGISTER, + .cache_type = REGCACHE_RBTREE, +}; + +/* + * Mapping of main IRQ register bits to sub-IRQ register offsets so that we can + * access corect sub-IRQ registers based on bits that are set in main IRQ + * register. + */ + +unsigned int bit0_offsets[] = {11}; /* RTC IRQ register */ +unsigned int bit1_offsets[] = {10}; /* TEMP IRQ register */ +unsigned int bit2_offsets[] = {6, 7, 8, 9}; /* BAT MON IRQ registers */ +unsigned int bit3_offsets[] = {5}; /* BAT IRQ register */ +unsigned int bit4_offsets[] = {4}; /* CHG IRQ register */ +unsigned int bit5_offsets[] = {3}; /* VSYS IRQ register */ +unsigned int bit6_offsets[] = {1, 2}; /* DCIN IRQ registers */ +unsigned int bit7_offsets[] = {0}; /* BUCK IRQ register */ + +static struct regmap_irq_sub_irq_map bd71828_sub_irq_offsets[] = { + REGMAP_IRQ_MAIN_REG_OFFSET(bit0_offsets), + REGMAP_IRQ_MAIN_REG_OFFSET(bit1_offsets), + REGMAP_IRQ_MAIN_REG_OFFSET(bit2_offsets), + REGMAP_IRQ_MAIN_REG_OFFSET(bit3_offsets), + REGMAP_IRQ_MAIN_REG_OFFSET(bit4_offsets), + REGMAP_IRQ_MAIN_REG_OFFSET(bit5_offsets), + REGMAP_IRQ_MAIN_REG_OFFSET(bit6_offsets), + REGMAP_IRQ_MAIN_REG_OFFSET(bit7_offsets), +}; + +static struct regmap_irq bd71828_irqs[] = { + REGMAP_IRQ_REG(BD71828_INT_BUCK1_OCP, 0, BD71828_INT_BUCK1_OCP_MASK), + REGMAP_IRQ_REG(BD71828_INT_BUCK2_OCP, 0, BD71828_INT_BUCK2_OCP_MASK), + REGMAP_IRQ_REG(BD71828_INT_BUCK3_OCP, 0, BD71828_INT_BUCK3_OCP_MASK), + REGMAP_IRQ_REG(BD71828_INT_BUCK4_OCP, 0, BD71828_INT_BUCK4_OCP_MASK), + REGMAP_IRQ_REG(BD71828_INT_BUCK5_OCP, 0, BD71828_INT_BUCK5_OCP_MASK), + REGMAP_IRQ_REG(BD71828_INT_BUCK6_OCP, 0, BD71828_INT_BUCK6_OCP_MASK), + REGMAP_IRQ_REG(BD71828_INT_BUCK7_OCP, 0, BD71828_INT_BUCK7_OCP_MASK), + REGMAP_IRQ_REG(BD71828_INT_PGFAULT, 0, BD71828_INT_PGFAULT_MASK), + /* DCIN1 interrupts */ + REGMAP_IRQ_REG(BD71828_INT_DCIN_DET, 1, BD71828_INT_DCIN_DET_MASK), + REGMAP_IRQ_REG(BD71828_INT_DCIN_RMV, 1, BD71828_INT_DCIN_RMV_MASK), + REGMAP_IRQ_REG(BD71828_INT_CLPS_OUT, 1, BD71828_INT_CLPS_OUT_MASK), + REGMAP_IRQ_REG(BD71828_INT_CLPS_IN, 1, BD71828_INT_CLPS_IN_MASK), + /* DCIN2 interrupts */ + REGMAP_IRQ_REG(BD71828_INT_DCIN_MON_RES, 2, + BD71828_INT_DCIN_MON_RES_MASK), + REGMAP_IRQ_REG(BD71828_INT_DCIN_MON_DET, 2, + BD71828_INT_DCIN_MON_DET_MASK), + REGMAP_IRQ_REG(BD71828_INT_LONGPUSH, 2, BD71828_INT_LONGPUSH_MASK), + REGMAP_IRQ_REG(BD71828_INT_MIDPUSH, 2, BD71828_INT_MIDPUSH_MASK), + REGMAP_IRQ_REG(BD71828_INT_SHORTPUSH, 2, BD71828_INT_SHORTPUSH_MASK), + REGMAP_IRQ_REG(BD71828_INT_PUSH, 2, BD71828_INT_PUSH_MASK), + REGMAP_IRQ_REG(BD71828_INT_WDOG, 2, BD71828_INT_WDOG_MASK), + REGMAP_IRQ_REG(BD71828_INT_SWRESET, 2, BD71828_INT_SWRESET_MASK), + /* Vsys */ + REGMAP_IRQ_REG(BD71828_INT_VSYS_UV_RES, 3, + BD71828_INT_VSYS_UV_RES_MASK), + REGMAP_IRQ_REG(BD71828_INT_VSYS_UV_DET, 3, + BD71828_INT_VSYS_UV_DET_MASK), + REGMAP_IRQ_REG(BD71828_INT_VSYS_LOW_RES, 3, + BD71828_INT_VSYS_LOW_RES_MASK), + REGMAP_IRQ_REG(BD71828_INT_VSYS_LOW_DET, 3, + BD71828_INT_VSYS_LOW_DET_MASK), + REGMAP_IRQ_REG(BD71828_INT_VSYS_HALL_IN, 3, + BD71828_INT_VSYS_HALL_IN_MASK), + REGMAP_IRQ_REG(BD71828_INT_VSYS_HALL_TOGGLE, 3, + BD71828_INT_VSYS_HALL_TOGGLE_MASK), + REGMAP_IRQ_REG(BD71828_INT_VSYS_MON_RES, 3, + BD71828_INT_VSYS_MON_RES_MASK), + REGMAP_IRQ_REG(BD71828_INT_VSYS_MON_DET, 3, + BD71828_INT_VSYS_MON_DET_MASK), + /* Charger */ + REGMAP_IRQ_REG(BD71828_INT_CHG_DCIN_ILIM, 4, + BD71828_INT_CHG_DCIN_ILIM_MASK), + REGMAP_IRQ_REG(BD71828_INT_CHG_TOPOFF_TO_DONE, 4, + BD71828_INT_CHG_TOPOFF_TO_DONE_MASK), + REGMAP_IRQ_REG(BD71828_INT_CHG_WDG_TEMP, 4, + BD71828_INT_CHG_WDG_TEMP_MASK), + REGMAP_IRQ_REG(BD71828_INT_CHG_WDG_TIME, 4, + BD71828_INT_CHG_WDG_TIME_MASK), + REGMAP_IRQ_REG(BD71828_INT_CHG_RECHARGE_RES, 4, + BD71828_INT_CHG_RECHARGE_RES_MASK), + REGMAP_IRQ_REG(BD71828_INT_CHG_RECHARGE_DET, 4, + BD71828_INT_CHG_RECHARGE_DET_MASK), + REGMAP_IRQ_REG(BD71828_INT_CHG_RANGED_TEMP_TRANSITION, 4, + BD71828_INT_CHG_RANGED_TEMP_TRANSITION_MASK), + REGMAP_IRQ_REG(BD71828_INT_CHG_STATE_TRANSITION, 4, + BD71828_INT_CHG_STATE_TRANSITION_MASK), + /* Battery */ + REGMAP_IRQ_REG(BD71828_INT_BAT_TEMP_NORMAL, 5, + BD71828_INT_BAT_TEMP_NORMAL_MASK), + REGMAP_IRQ_REG(BD71828_INT_BAT_TEMP_ERANGE, 5, + BD71828_INT_BAT_TEMP_ERANGE_MASK), + REGMAP_IRQ_REG(BD71828_INT_BAT_TEMP_WARN, 5, + BD71828_INT_BAT_TEMP_WARN_MASK), + REGMAP_IRQ_REG(BD71828_INT_BAT_REMOVED, 5, + BD71828_INT_BAT_REMOVED_MASK), + REGMAP_IRQ_REG(BD71828_INT_BAT_DETECTED, 5, + BD71828_INT_BAT_DETECTED_MASK), + REGMAP_IRQ_REG(BD71828_INT_THERM_REMOVED, 5, + BD71828_INT_THERM_REMOVED_MASK), + REGMAP_IRQ_REG(BD71828_INT_THERM_DETECTED, 5, + BD71828_INT_THERM_DETECTED_MASK), + /* Battery Mon 1 */ + REGMAP_IRQ_REG(BD71828_INT_BAT_DEAD, 6, BD71828_INT_BAT_DEAD_MASK), + REGMAP_IRQ_REG(BD71828_INT_BAT_SHORTC_RES, 6, + BD71828_INT_BAT_SHORTC_RES_MASK), + REGMAP_IRQ_REG(BD71828_INT_BAT_SHORTC_DET, 6, + BD71828_INT_BAT_SHORTC_DET_MASK), + REGMAP_IRQ_REG(BD71828_INT_BAT_LOW_VOLT_RES, 6, + BD71828_INT_BAT_LOW_VOLT_RES_MASK), + REGMAP_IRQ_REG(BD71828_INT_BAT_LOW_VOLT_DET, 6, + BD71828_INT_BAT_LOW_VOLT_DET_MASK), + REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_VOLT_RES, 6, + BD71828_INT_BAT_OVER_VOLT_RES_MASK), + REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_VOLT_DET, 6, + BD71828_INT_BAT_OVER_VOLT_DET_MASK), + /* Battery Mon 2 */ + REGMAP_IRQ_REG(BD71828_INT_BAT_MON_RES, 7, + BD71828_INT_BAT_MON_RES_MASK), + REGMAP_IRQ_REG(BD71828_INT_BAT_MON_DET, 7, + BD71828_INT_BAT_MON_DET_MASK), + /* Battery Mon 3 (Coulomb counter) */ + REGMAP_IRQ_REG(BD71828_INT_BAT_CC_MON1, 8, + BD71828_INT_BAT_CC_MON1_MASK), + REGMAP_IRQ_REG(BD71828_INT_BAT_CC_MON2, 8, + BD71828_INT_BAT_CC_MON2_MASK), + REGMAP_IRQ_REG(BD71828_INT_BAT_CC_MON3, 8, + BD71828_INT_BAT_CC_MON3_MASK), + /* Battery Mon 4 */ + REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_1_RES, 9, + BD71828_INT_BAT_OVER_CURR_1_RES_MASK), + REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_1_DET, 9, + BD71828_INT_BAT_OVER_CURR_1_DET_MASK), + REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_2_RES, 9, + BD71828_INT_BAT_OVER_CURR_2_RES_MASK), + REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_2_DET, 9, + BD71828_INT_BAT_OVER_CURR_2_DET_MASK), + REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_3_RES, 9, + BD71828_INT_BAT_OVER_CURR_3_RES_MASK), + REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_3_DET, 9, + BD71828_INT_BAT_OVER_CURR_3_DET_MASK), + /* Temperature */ + REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_LOW_RES, 10, + BD71828_INT_TEMP_BAT_LOW_RES_MASK), + REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_LOW_DET, 10, + BD71828_INT_TEMP_BAT_LOW_DET_MASK), + REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_HI_RES, 10, + BD71828_INT_TEMP_BAT_HI_RES_MASK), + REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_HI_DET, 10, + BD71828_INT_TEMP_BAT_HI_DET_MASK), + REGMAP_IRQ_REG(BD71828_INT_TEMP_CHIP_OVER_125_RES, 10, + BD71828_INT_TEMP_CHIP_OVER_125_RES_MASK), + REGMAP_IRQ_REG(BD71828_INT_TEMP_CHIP_OVER_125_DET, 10, + BD71828_INT_TEMP_CHIP_OVER_125_DET_MASK), + REGMAP_IRQ_REG(BD71828_INT_TEMP_CHIP_OVER_VF_DET, 10, + BD71828_INT_TEMP_CHIP_OVER_VF_DET_MASK), + REGMAP_IRQ_REG(BD71828_INT_TEMP_CHIP_OVER_VF_RES, 10, + BD71828_INT_TEMP_CHIP_OVER_VF_RES_MASK), + /* RTC Alarm */ + REGMAP_IRQ_REG(BD71828_INT_RTC0, 11, BD71828_INT_RTC0_MASK), + REGMAP_IRQ_REG(BD71828_INT_RTC1, 11, BD71828_INT_RTC1_MASK), + REGMAP_IRQ_REG(BD71828_INT_RTC2, 11, BD71828_INT_RTC2_MASK), +}; + +static struct regmap_irq_chip bd71828_irq_chip = { + .name = "bd71828_irq", + .main_status = BD71828_REG_INT_MAIN, + .irqs = &bd71828_irqs[0], + .num_irqs = ARRAY_SIZE(bd71828_irqs), + .status_base = BD71828_REG_INT_BUCK, + .mask_base = BD71828_REG_INT_MASK_BUCK, + .ack_base = BD71828_REG_INT_BUCK, + .mask_invert = true, + .init_ack_masked = true, + .num_regs = 12, + .num_main_regs = 1, + .sub_reg_offsets = &bd71828_sub_irq_offsets[0], + .num_main_status_bits = 8, + .irq_reg_stride = 1, +}; + +static int bd71828_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct rohm_regmap_dev *chip; + struct regmap_irq_chip_data *irq_data; + int ret; + + if (!i2c->irq) { + dev_err(&i2c->dev, "No IRQ configured\n"); + return -EINVAL; + } + + chip = devm_kzalloc(&i2c->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + dev_set_drvdata(&i2c->dev, chip); + + chip->chip_type = ROHM_CHIP_TYPE_BD71828; + chip->regmap = devm_regmap_init_i2c(i2c, &bd71828_regmap); + if (IS_ERR(chip->regmap)) { + dev_err(&i2c->dev, "Failed to initialize Regmap\n"); + return PTR_ERR(chip->regmap); + } + + ret = devm_regmap_add_irq_chip(&i2c->dev, chip->regmap, + i2c->irq, IRQF_ONESHOT, 0, + &bd71828_irq_chip, &irq_data); + if (ret) { + dev_err(&i2c->dev, "Failed to add IRQ chip\n"); + return ret; + } + dev_dbg(&i2c->dev, "Registered %d IRQs for chip\n", + bd71828_irq_chip.num_irqs); + + ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO, + bd71828_mfd_cells, + ARRAY_SIZE(bd71828_mfd_cells), NULL, 0, + regmap_irq_get_domain(irq_data)); + if (ret) + dev_err(&i2c->dev, "Failed to create subdevices\n"); + + return ret; +} + +static const struct of_device_id bd71828_of_match[] = { + { .compatible = "rohm,bd71828", }, + { }, +}; +MODULE_DEVICE_TABLE(of, bd71828_of_match); + +static struct i2c_driver bd71828_drv = { + .driver = { + .name = "rohm-bd71828", + .of_match_table = bd71828_of_match, + }, + .probe = &bd71828_i2c_probe, +}; + +module_i2c_driver(bd71828_drv); + +MODULE_AUTHOR("Matti Vaittinen "); +MODULE_DESCRIPTION("ROHM BD71828 Power Management IC driver"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/mfd/rohm-bd71828.h b/include/linux/mfd/rohm-bd71828.h new file mode 100644 index 000000000000..eb0557eb5314 --- /dev/null +++ b/include/linux/mfd/rohm-bd71828.h @@ -0,0 +1,425 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* Copyright (C) 2019 ROHM Semiconductors */ + +#ifndef __LINUX_MFD_BD71828_H__ +#define __LINUX_MFD_BD71828_H__ + +#include + +/* Regulator IDs */ +enum { + BD71828_BUCK1, + BD71828_BUCK2, + BD71828_BUCK3, + BD71828_BUCK4, + BD71828_BUCK5, + BD71828_BUCK6, + BD71828_BUCK7, + BD71828_LDO1, + BD71828_LDO2, + BD71828_LDO3, + BD71828_LDO4, + BD71828_LDO5, + BD71828_LDO6, + BD71828_LDO_SNVS, + BD71828_REGULATOR_AMOUNT, +}; + +#define BD71828_BUCK1267_VOLTS 0xEF +#define BD71828_BUCK3_VOLTS 0x10 +#define BD71828_BUCK4_VOLTS 0x20 +#define BD71828_BUCK5_VOLTS 0x10 +#define BD71828_LDO_VOLTS 0x32 +/* LDO6 is fixed 1.8V voltage */ +#define BD71828_LDO_6_VOLTAGE 1800000 + +/* Registers and masks*/ + +/* MODE control */ +#define BD71828_REG_PS_CTRL_1 0x04 +#define BD71828_REG_PS_CTRL_2 0x05 +#define BD71828_REG_PS_CTRL_3 0x06 + +//#define BD71828_REG_SWRESET 0x06 +#define BD71828_MASK_RUN_LVL_CTRL 0x30 + +/* Regulator control masks */ + +#define BD71828_MASK_RAMP_DELAY 0x6 + +#define BD71828_MASK_RUN_EN 0x08 +#define BD71828_MASK_SUSP_EN 0x04 +#define BD71828_MASK_IDLE_EN 0x02 +#define BD71828_MASK_LPSR_EN 0x01 + +#define BD71828_MASK_RUN0_EN 0x01 +#define BD71828_MASK_RUN1_EN 0x02 +#define BD71828_MASK_RUN2_EN 0x04 +#define BD71828_MASK_RUN3_EN 0x08 + +#define BD71828_MASK_DVS_BUCK1_CTRL 0x10 +#define BD71828_DVS_BUCK1_CTRL_I2C 0 +#define BD71828_DVS_BUCK1_USE_RUNLVL 0x10 + +#define BD71828_MASK_DVS_BUCK2_CTRL 0x20 +#define BD71828_DVS_BUCK2_CTRL_I2C 0 +#define BD71828_DVS_BUCK2_USE_RUNLVL 0x20 + +#define BD71828_MASK_DVS_BUCK6_CTRL 0x40 +#define BD71828_DVS_BUCK6_CTRL_I2C 0 +#define BD71828_DVS_BUCK6_USE_RUNLVL 0x40 + +#define BD71828_MASK_DVS_BUCK7_CTRL 0x80 +#define BD71828_DVS_BUCK7_CTRL_I2C 0 +#define BD71828_DVS_BUCK7_USE_RUNLVL 0x80 + +#define BD71828_MASK_BUCK1267_VOLT 0xff +#define BD71828_MASK_BUCK3_VOLT 0x1f +#define BD71828_MASK_BUCK4_VOLT 0x3f +#define BD71828_MASK_BUCK5_VOLT 0x1f +#define BD71828_MASK_LDO_VOLT 0x3f + +/* Regulator control regs */ +#define BD71828_REG_BUCK1_EN 0x08 +#define BD71828_REG_BUCK1_CTRL 0x09 +#define BD71828_REG_BUCK1_MODE 0x0a +#define BD71828_REG_BUCK1_IDLE_VOLT 0x0b +#define BD71828_REG_BUCK1_SUSP_VOLT 0x0c +#define BD71828_REG_BUCK1_VOLT 0x0d + +#define BD71828_REG_BUCK2_EN 0x12 +#define BD71828_REG_BUCK2_CTRL 0x13 +#define BD71828_REG_BUCK2_MODE 0x14 +#define BD71828_REG_BUCK2_IDLE_VOLT 0x15 +#define BD71828_REG_BUCK2_SUSP_VOLT 0x16 +#define BD71828_REG_BUCK2_VOLT 0x17 + +#define BD71828_REG_BUCK3_EN 0x1c +#define BD71828_REG_BUCK3_MODE 0x1d +#define BD71828_REG_BUCK3_VOLT 0x1e + +#define BD71828_REG_BUCK4_EN 0x1f +#define BD71828_REG_BUCK4_MODE 0x20 +#define BD71828_REG_BUCK4_VOLT 0x21 + +#define BD71828_REG_BUCK5_EN 0x22 +#define BD71828_REG_BUCK5_MODE 0x23 +#define BD71828_REG_BUCK5_VOLT 0x24 + +#define BD71828_REG_BUCK6_EN 0x25 +#define BD71828_REG_BUCK6_CTRL 0x26 +#define BD71828_REG_BUCK6_MODE 0x27 +#define BD71828_REG_BUCK6_IDLE_VOLT 0x28 +#define BD71828_REG_BUCK6_SUSP_VOLT 0x29 +#define BD71828_REG_BUCK6_VOLT 0x2a + +#define BD71828_REG_BUCK7_EN 0x2f +#define BD71828_REG_BUCK7_CTRL 0x30 +#define BD71828_REG_BUCK7_MODE 0x31 +#define BD71828_REG_BUCK7_IDLE_VOLT 0x32 +#define BD71828_REG_BUCK7_SUSP_VOLT 0x33 +#define BD71828_REG_BUCK7_VOLT 0x34 + +#define BD71828_REG_LDO1_EN 0x39 +#define BD71828_REG_LDO1_VOLT 0x3a +#define BD71828_REG_LDO2_EN 0x3b +#define BD71828_REG_LDO2_VOLT 0x3c +#define BD71828_REG_LDO3_EN 0x3d +#define BD71828_REG_LDO3_VOLT 0x3e +#define BD71828_REG_LDO4_EN 0x3f +#define BD71828_REG_LDO4_VOLT 0x40 +#define BD71828_REG_LDO5_EN 0x41 +#define BD71828_REG_LDO5_VOLT 0x43 +#define BD71828_REG_LDO5_VOLT_OPT 0x42 +#define BD71828_REG_LDO6_EN 0x44 +//#define BD71828_REG_LDO6_VOLT 0x4 +#define BD71828_REG_LDO7_EN 0x45 +#define BD71828_REG_LDO7_VOLT 0x46 + +/* GPIO */ + +#define BD71828_GPIO_DRIVE_MASK 0x2 +#define BD71828_GPIO_OPEN_DRAIN 0x0 +#define BD71828_GPIO_PUSH_PULL 0x2 +#define BD71828_GPIO_OUT_HI 0x1 +#define BD71828_GPIO_OUT_LO 0x0 +#define BD71828_GPIO_OUT_MASK 0x1 + +#define BD71828_REG_GPIO_CTRL1 0x47 +#define BD71828_REG_GPIO_CTRL2 0x48 +#define BD71828_REG_GPIO_CTRL3 0x49 +#define BD71828_REG_IO_STAT 0xed + +/* RTC */ +#define BD71828_REG_RTC_SEC 0x4c +#define BD71828_REG_RTC_MINUTE 0x4d +#define BD71828_REG_RTC_HOUR 0x4e +#define BD71828_REG_RTC_WEEK 0x4f +#define BD71828_REG_RTC_DAY 0x50 +#define BD71828_REG_RTC_MONTH 0x51 +#define BD71828_REG_RTC_YEAR 0x52 + +#define BD71828_REG_RTC_ALM0_SEC 0x53 +#define BD71828_REG_RTC_ALM0_MINUTE 0x54 +#define BD71828_REG_RTC_ALM0_HOUR 0x55 +#define BD71828_REG_RTC_ALM0_WEEK 0x56 +#define BD71828_REG_RTC_ALM0_DAY 0x57 +#define BD71828_REG_RTC_ALM0_MONTH 0x58 +#define BD71828_REG_RTC_ALM0_YEAR 0x59 +#define BD71828_REG_RTC_ALM0_MASK 0x61 + +#define BD71828_REG_RTC_ALM1_SEC 0x5a +#define BD71828_REG_RTC_ALM1_MINUTE 0x5b +#define BD71828_REG_RTC_ALM1_HOUR 0x5c +#define BD71828_REG_RTC_ALM1_WEEK 0x5d +#define BD71828_REG_RTC_ALM1_DAY 0x5e +#define BD71828_REG_RTC_ALM1_MONTH 0x5f +#define BD71828_REG_RTC_ALM1_YEAR 0x60 +#define BD71828_REG_RTC_ALM1_MASK 0x62 + +#define BD71828_REG_RTC_ALM2 0x63 + +/* Charger/Battey */ +#define BD71828_REG_CHG_STATE 0x65 +#define BD71828_REG_CHG_FULL 0xd2 + +/* CLK */ +#define BD71828_REG_OUT32K 0x4B + +/* LEDs */ +#define BD71828_REG_LED_CTRL 0x4A +#define BD71828_MASK_LED_AMBER 0x80 +#define BD71828_MASK_LED_GREEN 0x40 +#define BD71828_LED_ON 0xff +#define BD71828_LED_OFF 0x0 + +/* IRQ registers */ +#define BD71828_REG_INT_MASK_BUCK 0xd3 +#define BD71828_REG_INT_MASK_DCIN1 0xd4 +#define BD71828_REG_INT_MASK_DCIN2 0xd5 +#define BD71828_REG_INT_MASK_VSYS 0xd6 +#define BD71828_REG_INT_MASK_CHG 0xd7 +#define BD71828_REG_INT_MASK_BAT 0xd8 +#define BD71828_REG_INT_MASK_BAT_MON1 0xd9 +#define BD71828_REG_INT_MASK_BAT_MON2 0xda +#define BD71828_REG_INT_MASK_BAT_MON3 0xdb +#define BD71828_REG_INT_MASK_BAT_MON4 0xdc +#define BD71828_REG_INT_MASK_TEMP 0xdd +#define BD71828_REG_INT_MASK_RTC 0xde + + +#define BD71828_REG_INT_MAIN 0xdf +#define BD71828_REG_INT_BUCK 0xe0 +#define BD71828_REG_INT_DCIN1 0xe1 +#define BD71828_REG_INT_DCIN2 0xe2 +#define BD71828_REG_INT_VSYS 0xe3 +#define BD71828_REG_INT_CHG 0xe4 +#define BD71828_REG_INT_BAT 0xe5 +#define BD71828_REG_INT_BAT_MON1 0xe6 +#define BD71828_REG_INT_BAT_MON2 0xe7 +#define BD71828_REG_INT_BAT_MON3 0xe8 +#define BD71828_REG_INT_BAT_MON4 0xe9 +#define BD71828_REG_INT_TEMP 0xea +#define BD71828_REG_INT_RTC 0xeb +#define BD71828_REG_INT_UPDATE 0xec + +#define BD71828_MAX_REGISTER BD71828_REG_IO_STAT + +/* Masks for main IRQ register bits */ +enum { + BD71828_INT_BUCK, +#define BD71828_INT_BUCK_MASK BIT(BD71828_INT_BUCK) + BD71828_INT_DCIN, +#define BD71828_INT_DCIN_MASK BIT(BD71828_INT_DCIN) + BD71828_INT_VSYS, +#define BD71828_INT_VSYS_MASK BIT(BD71828_INT_VSYS) + BD71828_INT_CHG, +#define BD71828_INT_CHG_MASK BIT(BD71828_INT_CHG) + BD71828_INT_BAT, +#define BD71828_INT_BAT_MASK BIT(BD71828_INT_BAT) + BD71828_INT_BAT_MON, +#define BD71828_INT_BAT_MON_MASK BIT(BD71828_INT_BAT_MON) + BD71828_INT_TEMP, +#define BD71828_INT_TEMP_MASK BIT(BD71828_INT_TEMP) + BD71828_INT_RTC, +#define BD71828_INT_RTC_MASK BIT(BD71828_INT_RTC) +}; + +/* Interrupts */ +enum { + /* BUCK reg interrupts */ + BD71828_INT_BUCK1_OCP, + BD71828_INT_BUCK2_OCP, + BD71828_INT_BUCK3_OCP, + BD71828_INT_BUCK4_OCP, + BD71828_INT_BUCK5_OCP, + BD71828_INT_BUCK6_OCP, + BD71828_INT_BUCK7_OCP, + BD71828_INT_PGFAULT, + /* DCIN1 interrupts */ + BD71828_INT_DCIN_DET, + BD71828_INT_DCIN_RMV, + BD71828_INT_CLPS_OUT, + BD71828_INT_CLPS_IN, + /* DCIN2 interrupts */ + BD71828_INT_DCIN_MON_RES, + BD71828_INT_DCIN_MON_DET, + BD71828_INT_LONGPUSH, + BD71828_INT_MIDPUSH, + BD71828_INT_SHORTPUSH, + BD71828_INT_PUSH, + BD71828_INT_WDOG, + BD71828_INT_SWRESET, + /* Vsys */ + BD71828_INT_VSYS_UV_RES, + BD71828_INT_VSYS_UV_DET, + BD71828_INT_VSYS_LOW_RES, + BD71828_INT_VSYS_LOW_DET, + BD71828_INT_VSYS_HALL_IN, + BD71828_INT_VSYS_HALL_TOGGLE, + BD71828_INT_VSYS_MON_RES, + BD71828_INT_VSYS_MON_DET, + /* Charger */ + BD71828_INT_CHG_DCIN_ILIM, + BD71828_INT_CHG_TOPOFF_TO_DONE, + BD71828_INT_CHG_WDG_TEMP, + BD71828_INT_CHG_WDG_TIME, + BD71828_INT_CHG_RECHARGE_RES, + BD71828_INT_CHG_RECHARGE_DET, + BD71828_INT_CHG_RANGED_TEMP_TRANSITION, + BD71828_INT_CHG_STATE_TRANSITION, + /* Battery */ + BD71828_INT_BAT_TEMP_NORMAL, + BD71828_INT_BAT_TEMP_ERANGE, + BD71828_INT_BAT_TEMP_WARN, + BD71828_INT_BAT_REMOVED, + BD71828_INT_BAT_DETECTED, + BD71828_INT_THERM_REMOVED, + BD71828_INT_THERM_DETECTED, + /* Battery Mon 1 */ + BD71828_INT_BAT_DEAD, + BD71828_INT_BAT_SHORTC_RES, + BD71828_INT_BAT_SHORTC_DET, + BD71828_INT_BAT_LOW_VOLT_RES, + BD71828_INT_BAT_LOW_VOLT_DET, + BD71828_INT_BAT_OVER_VOLT_RES, + BD71828_INT_BAT_OVER_VOLT_DET, + /* Battery Mon 2 */ + BD71828_INT_BAT_MON_RES, + BD71828_INT_BAT_MON_DET, + /* Battery Mon 3 (Coulomb counter) */ + BD71828_INT_BAT_CC_MON1, + BD71828_INT_BAT_CC_MON2, + BD71828_INT_BAT_CC_MON3, + /* Battery Mon 4 */ + BD71828_INT_BAT_OVER_CURR_1_RES, + BD71828_INT_BAT_OVER_CURR_1_DET, + BD71828_INT_BAT_OVER_CURR_2_RES, + BD71828_INT_BAT_OVER_CURR_2_DET, + BD71828_INT_BAT_OVER_CURR_3_RES, + BD71828_INT_BAT_OVER_CURR_3_DET, + /* Temperature */ + BD71828_INT_TEMP_BAT_LOW_RES, + BD71828_INT_TEMP_BAT_LOW_DET, + BD71828_INT_TEMP_BAT_HI_RES, + BD71828_INT_TEMP_BAT_HI_DET, + BD71828_INT_TEMP_CHIP_OVER_125_RES, + BD71828_INT_TEMP_CHIP_OVER_125_DET, + BD71828_INT_TEMP_CHIP_OVER_VF_DET, + BD71828_INT_TEMP_CHIP_OVER_VF_RES, + /* RTC Alarm */ + BD71828_INT_RTC0, + BD71828_INT_RTC1, + BD71828_INT_RTC2, +}; + +#define BD71828_INT_BUCK1_OCP_MASK 0x1 +#define BD71828_INT_BUCK2_OCP_MASK 0x2 +#define BD71828_INT_BUCK3_OCP_MASK 0x4 +#define BD71828_INT_BUCK4_OCP_MASK 0x8 +#define BD71828_INT_BUCK5_OCP_MASK 0x10 +#define BD71828_INT_BUCK6_OCP_MASK 0x20 +#define BD71828_INT_BUCK7_OCP_MASK 0x40 +#define BD71828_INT_PGFAULT_MASK 0x80 + +#define BD71828_INT_DCIN_DET_MASK 0x1 +#define BD71828_INT_DCIN_RMV_MASK 0x2 +#define BD71828_INT_CLPS_OUT_MASK 0x4 +#define BD71828_INT_CLPS_IN_MASK 0x8 + /* DCIN2 interrupts */ +#define BD71828_INT_DCIN_MON_RES_MASK 0x1 +#define BD71828_INT_DCIN_MON_DET_MASK 0x2 +#define BD71828_INT_LONGPUSH_MASK 0x4 +#define BD71828_INT_MIDPUSH_MASK 0x8 +#define BD71828_INT_SHORTPUSH_MASK 0x10 +#define BD71828_INT_PUSH_MASK 0x20 +#define BD71828_INT_WDOG_MASK 0x40 +#define BD71828_INT_SWRESET_MASK 0x80 + /* Vsys */ +#define BD71828_INT_VSYS_UV_RES_MASK 0x1 +#define BD71828_INT_VSYS_UV_DET_MASK 0x2 +#define BD71828_INT_VSYS_LOW_RES_MASK 0x4 +#define BD71828_INT_VSYS_LOW_DET_MASK 0x8 +#define BD71828_INT_VSYS_HALL_IN_MASK 0x10 +#define BD71828_INT_VSYS_HALL_TOGGLE_MASK 0x20 +#define BD71828_INT_VSYS_MON_RES_MASK 0x40 +#define BD71828_INT_VSYS_MON_DET_MASK 0x80 + /* Charger */ +#define BD71828_INT_CHG_DCIN_ILIM_MASK 0x1 +#define BD71828_INT_CHG_TOPOFF_TO_DONE_MASK 0x2 +#define BD71828_INT_CHG_WDG_TEMP_MASK 0x4 +#define BD71828_INT_CHG_WDG_TIME_MASK 0x8 +#define BD71828_INT_CHG_RECHARGE_RES_MASK 0x10 +#define BD71828_INT_CHG_RECHARGE_DET_MASK 0x20 +#define BD71828_INT_CHG_RANGED_TEMP_TRANSITION_MASK 0x40 +#define BD71828_INT_CHG_STATE_TRANSITION_MASK 0x80 + /* Battery */ +#define BD71828_INT_BAT_TEMP_NORMAL_MASK 0x1 +#define BD71828_INT_BAT_TEMP_ERANGE_MASK 0x2 +#define BD71828_INT_BAT_TEMP_WARN_MASK 0x4 +#define BD71828_INT_BAT_REMOVED_MASK 0x10 +#define BD71828_INT_BAT_DETECTED_MASK 0x20 +#define BD71828_INT_THERM_REMOVED_MASK 0x40 +#define BD71828_INT_THERM_DETECTED_MASK 0x80 + /* Battery Mon 1 */ +#define BD71828_INT_BAT_DEAD_MASK 0x2 +#define BD71828_INT_BAT_SHORTC_RES_MASK 0x4 +#define BD71828_INT_BAT_SHORTC_DET_MASK 0x8 +#define BD71828_INT_BAT_LOW_VOLT_RES_MASK 0x10 +#define BD71828_INT_BAT_LOW_VOLT_DET_MASK 0x20 +#define BD71828_INT_BAT_OVER_VOLT_RES_MASK 0x40 +#define BD71828_INT_BAT_OVER_VOLT_DET_MASK 0x80 + /* Battery Mon 2 */ +#define BD71828_INT_BAT_MON_RES_MASK 0x1 +#define BD71828_INT_BAT_MON_DET_MASK 0x2 + /* Battery Mon 3 (Coulomb counter) */ +#define BD71828_INT_BAT_CC_MON1_MASK 0x1 +#define BD71828_INT_BAT_CC_MON2_MASK 0x2 +#define BD71828_INT_BAT_CC_MON3_MASK 0x4 + /* Battery Mon 4 */ +#define BD71828_INT_BAT_OVER_CURR_1_RES_MASK 0x1 +#define BD71828_INT_BAT_OVER_CURR_1_DET_MASK 0x2 +#define BD71828_INT_BAT_OVER_CURR_2_RES_MASK 0x4 +#define BD71828_INT_BAT_OVER_CURR_2_DET_MASK 0x8 +#define BD71828_INT_BAT_OVER_CURR_3_RES_MASK 0x10 +#define BD71828_INT_BAT_OVER_CURR_3_DET_MASK 0x20 + /* Temperature */ +#define BD71828_INT_TEMP_BAT_LOW_RES_MASK 0x1 +#define BD71828_INT_TEMP_BAT_LOW_DET_MASK 0x2 +#define BD71828_INT_TEMP_BAT_HI_RES_MASK 0x4 +#define BD71828_INT_TEMP_BAT_HI_DET_MASK 0x8 +#define BD71828_INT_TEMP_CHIP_OVER_125_RES_MASK 0x10 +#define BD71828_INT_TEMP_CHIP_OVER_125_DET_MASK 0x20 +#define BD71828_INT_TEMP_CHIP_OVER_VF_RES_MASK 0x40 +#define BD71828_INT_TEMP_CHIP_OVER_VF_DET_MASK 0x80 + /* RTC Alarm */ +#define BD71828_INT_RTC0_MASK 0x1 +#define BD71828_INT_RTC1_MASK 0x2 +#define BD71828_INT_RTC2_MASK 0x4 + +#define BD71828_OUT32K_EN 0x1 +#define BD71828_OUT_TYPE_MASK 0x2 +#define BD71828_OUT_TYPE_OPEN_DRAIN 0x0 +#define BD71828_OUT_TYPE_CMOS 0x2 + +#endif /* __LINUX_MFD_BD71828_H__ */ diff --git a/include/linux/mfd/rohm-generic.h b/include/linux/mfd/rohm-generic.h index bff15ac26f2c..b280f3100d6c 100644 --- a/include/linux/mfd/rohm-generic.h +++ b/include/linux/mfd/rohm-generic.h @@ -8,6 +8,7 @@ enum { ROHM_CHIP_TYPE_BD71837 = 0, ROHM_CHIP_TYPE_BD71847, ROHM_CHIP_TYPE_BD70528, + ROHM_CHIP_TYPE_BD71828, ROHM_CHIP_TYPE_AMOUNT }; From patchwork Thu Oct 24 11:41:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matti Vaittinen X-Patchwork-Id: 1182932 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-rtc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=fi.rohmeurope.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46zQMD653Kz9sRK for ; Thu, 24 Oct 2019 22:42:00 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2439107AbfJXLl7 (ORCPT ); Thu, 24 Oct 2019 07:41:59 -0400 Received: from mail-lf1-f66.google.com ([209.85.167.66]:42807 "EHLO mail-lf1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2407878AbfJXLl5 (ORCPT ); Thu, 24 Oct 2019 07:41:57 -0400 Received: by mail-lf1-f66.google.com with SMTP id z12so18847120lfj.9; Thu, 24 Oct 2019 04:41:54 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=m3o/lWfrwRFPHJi2BOThyBDN3PdB2H+vW0rhvq41yII=; b=tRjKyjUUktfzWLNXiquXV4c+n0HyyiyU1q6FIGkkxiRQ0IdBWo+bsMSfKjet62xY1B gYZISvqzoglkl1mJlfI7jV/NyiejbYPA3cSSbF2DEuH18k678LNVyUC04Ap9/Wwbaxz2 qNf/hL+QZvmusI8kMb7mOr3x6VzOVUCPfLRSmAQWr+Bexgeqpg4LFVlmMBOombibCyT/ 5R51QFyZA2sDywGIP3QasB40g6Ig+yKGKxWStiBX0mRmBo7ycYrSMTMGSemPe3fx1Nzc BA7XvO2Sx++lHTasEAXevhEB3zCTAiKLdT0nSRmxTv9xC0Vea5NTo1r7Ox1VIqsA1snR nWNA== X-Gm-Message-State: APjAAAXyFLEGVIB3A+o1ZX39jrDG3L412t6aLRrYmfCyUnpVSzY7wsRa gmP4WwNeJMTM9LJ40pX4sF8= X-Google-Smtp-Source: APXvYqzrbGQ0ttrOhQLi4AqqOXsG/uNNge6qqlhyHnCTkSlAS+M74Xd2zhLobDiLUr03QDL4RM5A4A== X-Received: by 2002:ac2:5e90:: with SMTP id b16mr13561107lfq.119.1571917313794; Thu, 24 Oct 2019 04:41:53 -0700 (PDT) Received: from localhost.localdomain ([213.255.186.46]) by smtp.gmail.com with ESMTPSA id u8sm18047678lfb.36.2019.10.24.04.41.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 24 Oct 2019 04:41:53 -0700 (PDT) Date: Thu, 24 Oct 2019 14:41:45 +0300 From: Matti Vaittinen To: matti.vaittinen@fi.rohmeurope.com, mazziesaccount@gmail.com Cc: Lee Jones , Rob Herring , Mark Rutland , Liam Girdwood , Mark Brown , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Jacek Anaszewski , Pavel Machek , Dan Murphy , Alessandro Zummo , Alexandre Belloni , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-leds@vger.kernel.org, linux-rtc@vger.kernel.org Subject: [RFC PATCH v2 02/13] dt-bindings: mfd: Document ROHM BD71828 bindings Message-ID: <0182df3c49c6c804ee20ef32fc4b85b50ff45fca.1571915550.git.matti.vaittinen@fi.rohmeurope.com> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.12.1 (2019-06-15) Sender: linux-rtc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rtc@vger.kernel.org ROHM BD71828 Power management IC integrates 7 buck converters, 7 LDOs, a real-time clock (RTC), 3 GPO/regulator control pins, HALL input and a 32.768 kHz clock gate. Document the dt bindings drivers are using. Signed-off-by: Matti Vaittinen --- No changes since v1 .../bindings/mfd/rohm,bd71828-pmic.txt | 180 ++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.txt diff --git a/Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.txt b/Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.txt new file mode 100644 index 000000000000..125efa9f3de0 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.txt @@ -0,0 +1,180 @@ +* ROHM BD71828 Power Management Integrated Circuit bindings + +BD71828GW is a single-chip power management IC for battery-powered portable +devices. The IC integrates 7 buck converters, 7 LDOs, and a 1500 mA single-cell +linear charger. Also included is a Coulomb counter, a real-time clock (RTC), +and a 32.768 kHz clock gate. + +Required properties: + - compatible : Should be "rohm,bd71828". + - reg : I2C slave address. + - interrupt-parent : Phandle to the parent interrupt controller. + - interrupts : The interrupt line the device is connected to. + - clocks : The parent clock connected to PMIC. + - #clock-cells : Should be 0. + - regulators : List of child nodes that specify the + regulators. Please see + ../regulator/rohm,bd71828-regulator.txt + - gpio-controller : To indicate BD71828 acts as a GPIO controller. + - #gpio-cells : Should be 2. The first cell is the pin number + and the second cell is used to specify flags. + See ../gpio/gpio.txt for more information. + +The BD71828 RUN state is divided into 4 configurable run-levels named RUN0, +RUN1, RUN2 and RUN3. Bucks 1, 2, 6 and 7 can be either controlled individually +via I2C, or some/all of them can be bound to run-levels and controlled as a +group. If bucks are controlled individually these run-levels are ignored. See +../regulator/rohm,bd71828-regulator.txt for how to define regulator voltages +for run-levels. Run-levels can be changed by I2C or GPIO depending on PMIC's OTP +configuration. + +Optional properties: +- clock-output-names : Should contain name for output clock. +- rohm,dvs-vsel-gpios : GPIOs used to control PMIC run-levels. Should + describe two GPIOs. (See run-level control in + data-sheet). If this property is omitted but + some bucks are marked to be controlled by + run-levels - then OTP option allowing + run-level control via I2C is assumed. +- gpio-reserved-ranges : Usage of GPIO pins can be changed via OTP. + This property can be used to mark the pins + which should not be configured for GPIO. + Please see the ../gpio/gpio.txt for more + information. + +Example: + + /* external oscillator node */ + osc: oscillator { + compatible = "fixed-clock"; + #clock-cells = <1>; + clock-frequency = <32768>; + clock-output-names = "osc"; + }; + + pmic: pmic@4b { + compatible = "rohm,bd71828"; + reg = <0x4b>; + interrupt-parent = <&gpio1>; + interrupts = <29 GPIO_ACTIVE_LOW>; + clocks = <&osc 0>; + #clock-cells = <0>; + clock-output-names = "bd71828-32k-out"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <4>; + gpio-reserved-ranges = <0 1 2 1>; + gpio-line-names = "EPDEN"; + rohm,dvs-vsel-gpios = <&gpio1 12 0>, + <&gpio1 13 0>; + regulators { + buck1: BUCK1 { + regulator-name = "buck1"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <2000000>; + regulator-ramp-delay = <2500>; + rohm,dvs-runlvl-ctrl; + rohm,dvs-runlevel0-voltage = <500000>; + rohm,dvs-runlevel1-voltage = <506250>; + rohm,dvs-runlevel2-voltage = <512500>; + rohm,dvs-runlevel3-voltage = <518750>; + regulator-boot-on; + }; + buck2: BUCK2 { + regulator-name = "buck2"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <2000000>; + regulator-ramp-delay = <2500>; + rohm,dvs-runlvl-ctrl; + rohm,dvs-runlevel0-voltage = <500000>; + rohm,dvs-runlevel1-voltage = <506250>; + rohm,dvs-runlevel2-voltage = <512500>; + rohm,dvs-runlevel3-voltage = <518750>; + regulator-boot-on; + }; + buck3: BUCK3 { + regulator-name = "buck3"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <2000000>; + regulator-boot-on; + }; + buck4: BUCK4 { + regulator-name = "buck4"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + }; + buck5: BUCK5 { + regulator-name = "buck5"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + buck6: BUCK6 { + regulator-name = "buck6"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <2000000>; + regulator-ramp-delay = <2500>; + rohm,dvs-runlvl-ctrl; + rohm,dvs-runlevel0-voltage = <500000>; + rohm,dvs-runlevel1-voltage = <506250>; + rohm,dvs-runlevel2-voltage = <512500>; + rohm,dvs-runlevel3-voltage = <518750>; + regulator-boot-on; + }; + buck7: BUCK7 { + regulator-name = "buck7"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <2000000>; + regulator-ramp-delay = <2500>; + rohm,dvs-runlvl-ctrl; + rohm,dvs-runlevel0-voltage = <500000>; + rohm,dvs-runlevel1-voltage = <506250>; + rohm,dvs-runlevel2-voltage = <512500>; + rohm,dvs-runlevel3-voltage = <518750>; + regulator-boot-on; + }; + ldo1: LDO1 { + regulator-name = "ldo1"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + ldo2: LDO2 { + regulator-name = "ldo2"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + ldo3: LDO3 { + regulator-name = "ldo3"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + ldo4: LDO4 { + regulator-name = "ldo4"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + ldo5: LDO5 { + regulator-name = "ldo5"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + ldo6: LDO6 { + regulator-name = "ldo6"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + }; + ldo7_reg: LDO7 { + regulator-name = "ldo7"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + }; + }; From patchwork Thu Oct 24 11:42:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matti Vaittinen X-Patchwork-Id: 1182935 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-rtc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=fi.rohmeurope.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46zQNQ5rHwz9sR6 for ; Thu, 24 Oct 2019 22:43:02 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2439221AbfJXLm6 (ORCPT ); Thu, 24 Oct 2019 07:42:58 -0400 Received: from mail-lj1-f193.google.com ([209.85.208.193]:46189 "EHLO mail-lj1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2439196AbfJXLm5 (ORCPT ); Thu, 24 Oct 2019 07:42:57 -0400 Received: by mail-lj1-f193.google.com with SMTP id d1so24618299ljl.13; Thu, 24 Oct 2019 04:42:54 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=iHrUaZ4QstA0A5h8AOun5nDY0whyQItP1kSFFnCdNYg=; b=AnUSRmFsp6qvC4PPsWFXad5oFZ15Cb8fay4UL02moPg4deIpnh2kw+JmfpGYtS+f8J 7Fr4XxuHtem5xsz+Ss9tsSYWunK5l6RbsYfQ2fy+ApNpZ6MCUP5G1zn457pZ7vbfkRk2 GqvzkcsVzm94ZkAizOwfwZjmivf2vqR902isSCU9M6tPLQoNwM9VlWYQnLw6744hLvlh IMyBXuFO5VzdppY3NSJFVJ72657DiYZ5aJt7pZEyQQP1ucLWI88RFeVM4jI5nrhb7/wa MocaHSN4HybY1XSs7wX0dX6qD3AopYYMic57Rb2Yu7xRCoLo+0N3XnwKKerGotCiJTyH RGAQ== X-Gm-Message-State: APjAAAUhwY3pT5BsmW4ckRTft4Isg7qWySM0bHS8aMkSZzv+FqGRAaiM 7+HDmDjNqdO6pLaEsmdGVj8= X-Google-Smtp-Source: APXvYqzSWtNXk7N5AvqLikmK+54/TI15t1pRwymcVZtHkO1OED/6sDVhBu8I48d4ZmF4x+sB35qlaw== X-Received: by 2002:a2e:29dd:: with SMTP id p90mr26102526ljp.26.1571917373202; Thu, 24 Oct 2019 04:42:53 -0700 (PDT) Received: from localhost.localdomain ([213.255.186.46]) by smtp.gmail.com with ESMTPSA id n11sm14774030lfd.88.2019.10.24.04.42.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 24 Oct 2019 04:42:52 -0700 (PDT) Date: Thu, 24 Oct 2019 14:42:40 +0300 From: Matti Vaittinen To: matti.vaittinen@fi.rohmeurope.com, mazziesaccount@gmail.com Cc: Lee Jones , Rob Herring , Mark Rutland , Liam Girdwood , Mark Brown , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Jacek Anaszewski , Pavel Machek , Dan Murphy , Alessandro Zummo , Alexandre Belloni , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-leds@vger.kernel.org, linux-rtc@vger.kernel.org Subject: [RFC PATCH v2 03/13] dt-bindings: regulator: Document ROHM BD71282 regulator bindings Message-ID: <8df1ed73e9d14f89e428039b0f5d7761c7d840a1.1571915550.git.matti.vaittinen@fi.rohmeurope.com> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.12.1 (2019-06-15) Sender: linux-rtc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rtc@vger.kernel.org Document ROHM BD71828 PMIC regulator device tree bindings. Signed-off-by: Matti Vaittinen --- Only commit title changed since v1 .../regulator/rohm,bd71828-regulator.txt | 164 ++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 Documentation/devicetree/bindings/regulator/rohm,bd71828-regulator.txt diff --git a/Documentation/devicetree/bindings/regulator/rohm,bd71828-regulator.txt b/Documentation/devicetree/bindings/regulator/rohm,bd71828-regulator.txt new file mode 100644 index 000000000000..cf6a5123b98d --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/rohm,bd71828-regulator.txt @@ -0,0 +1,164 @@ +ROHM BD71828 Power Management Integrated Circuit regulator bindings + +Required properties: + - regulator-name: should be "buck1", ..., "buck7", and "ldo1", ..., "ldo7" + +List of regulators provided by this controller. BD71828 regulators node +should be sub node of the BD71828 MFD node. See BD71828 MFD bindings at +Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.txt +Regulator nodes should be named to BUCK_ and LDO_. The +definition for each of these nodes is defined using the standard +binding for regulators at +Documentation/devicetree/bindings/regulator/regulator.txt. + +The valid names for BD71828 regulator nodes are: +BUCK1, BUCK2, BUCK3, BUCK4, BUCK5, BUCK6, BUCK7 +LDO1, LDO2, LDO3, LDO4, LDO5, LDO6, LDO7 + +Optional properties: +- rohm,dvs-run-voltage : PMIC default "RUN" state voltage in uV. + See below table for bucks which support this. +- rohm,dvs-idle-voltage : PMIC default "IDLE" state voltage in uV. + See below table for bucks which support this. +- rohm,dvs-suspend-voltage : PMIC default "SUSPEND" state voltage in uV. + See below table for bucks which support this. +- rohm,dvs-lpsr-voltage : PMIC default "LPSR" state voltage in uV. +- rohm,dvs-runlvl-ctrl : buck control is done based on run-level. + Regulator is not individually controllable. + See ../mfd/rohm,bd71828-pmic.txt for how to + specify run-level control mechanism. Only + bucks 1, 2, 6 and 7 support this. +- rohm,dvs-runlevel0-voltage : voltage for run-level 0. Microvolts. +- rohm,dvs-runlevel1-voltage : voltage for run-level 1. Microvolts. +- rohm,dvs-runlevel2-voltage : voltage for run-level 2. Microvolts. +- rohm,dvs-runlevel3-voltage : voltage for run-level 3. Microvolts. + +- Any optional property defined in bindings/regulator/regulator.txt + +Supported default DVS states: + +buck | run | idle | suspend | lpsr +----------------------------------------------------------------------------- +1, 2, 6, and 7 | supported | supported | supported (*) +---------------------------------------------------------------------------- +3, 4, and 5 | supported (**) +---------------------------------------------------------------------------- +(*) LPSR and SUSPEND states use same voltage but both states have own enable / + disable settings. Voltage 0 can be specified for a state to make regulator + disabled on that state. +(**) All states use same voltage but have own enable / disable settings. Voltage + 0 can be specified for a state to make regulator disabled on that state. + +Example: +regulators { + buck1: BUCK1 { + regulator-name = "buck1"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <2000000>; + regulator-ramp-delay = <2500>; + rohm,dvs-runlvl-ctrl; + rohm,dvs-runlevel0-voltage = <500000>; + rohm,dvs-runlevel1-voltage = <506250>; + rohm,dvs-runlevel2-voltage = <512500>; + rohm,dvs-runlevel3-voltage = <518750>; + regulator-boot-on; + }; + buck2: BUCK2 { + regulator-name = "buck2"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <2000000>; + regulator-ramp-delay = <2500>; + rohm,dvs-runlvl-ctrl; + rohm,dvs-runlevel0-voltage = <500000>; + rohm,dvs-runlevel1-voltage = <506250>; + rohm,dvs-runlevel2-voltage = <512500>; + rohm,dvs-runlevel3-voltage = <518750>; + regulator-boot-on; + }; + buck3: BUCK3 { + regulator-name = "buck3"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <2000000>; + regulator-boot-on; + }; + buck4: BUCK4 { + regulator-name = "buck4"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + }; + buck5: BUCK5 { + regulator-name = "buck5"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + buck6: BUCK6 { + regulator-name = "buck6"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <2000000>; + regulator-ramp-delay = <2500>; + rohm,dvs-runlvl-ctrl; + rohm,dvs-runlevel0-voltage = <500000>; + rohm,dvs-runlevel1-voltage = <506250>; + rohm,dvs-runlevel2-voltage = <512500>; + rohm,dvs-runlevel3-voltage = <518750>; + regulator-boot-on; + }; + buck7: BUCK7 { + regulator-name = "buck7"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <2000000>; + regulator-ramp-delay = <2500>; + rohm,dvs-runlvl-ctrl; + rohm,dvs-runlevel0-voltage = <500000>; + rohm,dvs-runlevel1-voltage = <506250>; + rohm,dvs-runlevel2-voltage = <512500>; + rohm,dvs-runlevel3-voltage = <518750>; + regulator-boot-on; + }; + ldo1: LDO1 { + regulator-name = "ldo1"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + ldo2: LDO2 { + regulator-name = "ldo2"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + ldo3: LDO3 { + regulator-name = "ldo3"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + ldo4: LDO4 { + regulator-name = "ldo4"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + ldo5: LDO5 { + regulator-name = "ldo5"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + ldo6: LDO6 { + regulator-name = "ldo6"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + }; + ldo7_reg: LDO7 { + regulator-name = "ldo7"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; +}; + + From patchwork Thu Oct 24 11:44:05 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matti Vaittinen X-Patchwork-Id: 1182940 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-rtc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=fi.rohmeurope.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46zQPw1krVz9sQv for ; Thu, 24 Oct 2019 22:44:20 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726530AbfJXLoR (ORCPT ); Thu, 24 Oct 2019 07:44:17 -0400 Received: from mail-lj1-f193.google.com ([209.85.208.193]:43488 "EHLO mail-lj1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726389AbfJXLoQ (ORCPT ); Thu, 24 Oct 2019 07:44:16 -0400 Received: by mail-lj1-f193.google.com with SMTP id n14so24644927ljj.10; Thu, 24 Oct 2019 04:44:14 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=a1r2oRD4FVn+B+uBS9ZGvqBGEqOoVXr/0y/B/AKwI18=; b=A0iUz/dq3Zys5gTTMiyVNCWgK65Qs2YfujP+5+EpnO1BKj6LVYYiCPUAUUSNg6LkLb CMJ7V+o3MWTCQDp9p2MvwwCZR6iM1pbIx10yp0Gc9Y242mG5cPC4EaGBAdE/XI6ePW9E /B9fO7/kRBtv/34RQfIUQcsIJdcqlluVg4OxdLZ4txMtrjjL1Gf1q8JFP5ZW3p0muDk3 BcxIKrlmc+PdAn9Bl7JfhoeSylgdhfz3busIH0DqlETrLUOWNEAYUlx8pAPdo8xWwpnr LPyi6pNE5WA3so4Xt5LTEXZpoga6Yo9OEn/QJ8gK46ogknjJctLm1GBKnl+UMxkbwIRj m6xA== X-Gm-Message-State: APjAAAUTTRZQ5rjjtL+m8MS8vWxzxO7qltUIeBwwZ9gmofmE1GRJbz27 ufDoWckHnoJM0G/FEfAgt2w= X-Google-Smtp-Source: APXvYqyZPgCnm8Pe2t9Mfc25yHuwJPgszDocEXDX8Fi8/IFlpoi8oV/EOirAH7oXQQmLbv++Xj+fZg== X-Received: by 2002:a2e:9f4d:: with SMTP id v13mr26446627ljk.226.1571917453620; Thu, 24 Oct 2019 04:44:13 -0700 (PDT) Received: from localhost.localdomain ([213.255.186.46]) by smtp.gmail.com with ESMTPSA id x30sm11422070ljd.39.2019.10.24.04.44.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 24 Oct 2019 04:44:13 -0700 (PDT) Date: Thu, 24 Oct 2019 14:44:05 +0300 From: Matti Vaittinen To: matti.vaittinen@fi.rohmeurope.com, mazziesaccount@gmail.com Cc: Lee Jones , Rob Herring , Mark Rutland , Liam Girdwood , Mark Brown , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Jacek Anaszewski , Pavel Machek , Dan Murphy , Alessandro Zummo , Alexandre Belloni , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-leds@vger.kernel.org, linux-rtc@vger.kernel.org, Dmitry Torokhov Subject: [RFC PATCH v2 04/13] mfd: input: bd71828: Add power-key support Message-ID: References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.12.1 (2019-06-15) Sender: linux-rtc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rtc@vger.kernel.org Use gpio_keys to send power input-event to user-space when power button (short) press is detected. Signed-off-by: Matti Vaittinen --- No changes since v1 drivers/mfd/rohm-bd71828.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/mfd/rohm-bd71828.c b/drivers/mfd/rohm-bd71828.c index b7de79e1fcdb..f77ba1ec3e99 100644 --- a/drivers/mfd/rohm-bd71828.c +++ b/drivers/mfd/rohm-bd71828.c @@ -4,7 +4,9 @@ // // ROHM BD71828 PMIC driver +#include #include +#include #include #include #include @@ -15,6 +17,18 @@ #include #include +static struct gpio_keys_button button = { + .code = KEY_POWER, + .gpio = -1, + .type = EV_KEY, +}; + +static struct gpio_keys_platform_data bd71828_powerkey_data = { + .buttons = &button, + .nbuttons = 1, + .name = "bd71828-pwrkey", +}; + static const struct resource rtc_irqs[] = { DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC0, "bd71828-rtc-alm-0"), DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC1, "bd71828-rtc-alm-1"), @@ -36,6 +50,10 @@ static struct mfd_cell bd71828_mfd_cells[] = { .name = "bd70528-rtc", .resources = rtc_irqs, .num_resources = ARRAY_SIZE(rtc_irqs), + }, { + .name = "gpio-keys", + .platform_data = &bd71828_powerkey_data, + .pdata_size = sizeof(bd71828_powerkey_data), }, }; @@ -288,9 +306,19 @@ static int bd71828_i2c_probe(struct i2c_client *i2c, dev_err(&i2c->dev, "Failed to add IRQ chip\n"); return ret; } + dev_dbg(&i2c->dev, "Registered %d IRQs for chip\n", bd71828_irq_chip.num_irqs); + ret = regmap_irq_get_virq(irq_data, BD71828_INT_SHORTPUSH); + + if (ret < 0) { + dev_err(&i2c->dev, "Failed to get the power-key IRQ\n"); + return ret; + } + + button.irq = ret; + ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO, bd71828_mfd_cells, ARRAY_SIZE(bd71828_mfd_cells), NULL, 0, From patchwork Thu Oct 24 11:44:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matti Vaittinen X-Patchwork-Id: 1182943 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-rtc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=fi.rohmeurope.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46zQQk2PV5z9sR0 for ; Thu, 24 Oct 2019 22:45:02 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726931AbfJXLo4 (ORCPT ); Thu, 24 Oct 2019 07:44:56 -0400 Received: from mail-lf1-f68.google.com ([209.85.167.68]:35002 "EHLO mail-lf1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726497AbfJXLo4 (ORCPT ); Thu, 24 Oct 2019 07:44:56 -0400 Received: by mail-lf1-f68.google.com with SMTP id y6so12596337lfj.2; Thu, 24 Oct 2019 04:44:54 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=aPuYD0Y1OwLq/YJrQ4uz9MAHyVZVeSJvf6a0mditrIY=; b=nRqLxXBkkEInW/18PbD0s5mr7GZHErRcMrY44YWl/Ecm60WZEyCfpTODNgTw6UTxi0 Fd5m8V3MQZpVEe63zqeEhuaQE+zcRZ2DuZYB8C9yDi1RB9K4YKRgMkDMhll9ESKh5RMB pAywvMw6Bj8W98UEup4zo90ev/ne5Xr0ys6DQvxtlUN7aXzCVLjhy9M12VgjhMOA4NRA r29dz3UT/P63DcLjsjLUr60uC2BfjNg7F8RsJCOnMm8r5rckaCMf9bFprGRqPg3QmIwS Leb6jqBEDYc/zaeYOYWiW8qjduWCIGpPNjGoCe+DoA/YnMbK8R26Lw2rRRqXiUX+AcIu DfEg== X-Gm-Message-State: APjAAAWcPC38thkvSAc0EhPzCrxhROk4N1mi9+upjaEw5ysvIAZQzYhu UJWFXC06tPsRpFZo1qHSMq8= X-Google-Smtp-Source: APXvYqwU7zOQZVwIIYztaUUqrwwsRQUOAq6NcR8ErtA6eJZ+8AQRs4zCLSIDdVasHCAf77BIQjJzjg== X-Received: by 2002:a19:855:: with SMTP id 82mr25699183lfi.44.1571917493250; Thu, 24 Oct 2019 04:44:53 -0700 (PDT) Received: from localhost.localdomain ([213.255.186.46]) by smtp.gmail.com with ESMTPSA id 4sm11643240ljv.87.2019.10.24.04.44.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 24 Oct 2019 04:44:52 -0700 (PDT) Date: Thu, 24 Oct 2019 14:44:40 +0300 From: Matti Vaittinen To: matti.vaittinen@fi.rohmeurope.com, mazziesaccount@gmail.com Cc: Lee Jones , Rob Herring , Mark Rutland , Liam Girdwood , Mark Brown , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Jacek Anaszewski , Pavel Machek , Dan Murphy , Alessandro Zummo , Alexandre Belloni , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-leds@vger.kernel.org, linux-rtc@vger.kernel.org Subject: [RFC PATCH v2 05/13] clk: bd718x7: Support ROHM BD71828 clk block Message-ID: <5c66ac7d43ae1f57c335b6e565553fe1df703a83.1571915550.git.matti.vaittinen@fi.rohmeurope.com> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.12.1 (2019-06-15) Sender: linux-rtc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rtc@vger.kernel.org BD71828GW is a single-chip power management IC for battery-powered portable devices. Add support for controlling BD71828 clk using bd718x7 driver. Signed-off-by: Matti Vaittinen --- No changes since v1 drivers/clk/Kconfig | 6 +++--- drivers/clk/clk-bd718x7.c | 15 ++++++++++----- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 801fa1cd0321..1d61d94cdb29 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -302,10 +302,10 @@ config COMMON_CLK_STM32H7 Support for stm32h7 SoC family clocks config COMMON_CLK_BD718XX - tristate "Clock driver for ROHM BD718x7 PMIC" - depends on MFD_ROHM_BD718XX || MFD_ROHM_BD70528 + tristate "Clock driver for 32K clk gates on ROHM PMICs" + depends on MFD_ROHM_BD718XX || MFD_ROHM_BD70528 || MFD_ROHM_BD71828 help - This driver supports ROHM BD71837, ROHM BD71847 and + This driver supports ROHM BD71837, ROHM BD71847, ROHM BD71828 and ROHM BD70528 PMICs clock gates. config COMMON_CLK_FIXED_MMIO diff --git a/drivers/clk/clk-bd718x7.c b/drivers/clk/clk-bd718x7.c index ae6e5baee330..d17a19e04592 100644 --- a/drivers/clk/clk-bd718x7.c +++ b/drivers/clk/clk-bd718x7.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -21,10 +22,8 @@ struct bd718xx_clk { struct rohm_regmap_dev *mfd; }; -static int bd71837_clk_set(struct clk_hw *hw, int status) +static int bd71837_clk_set(struct bd718xx_clk *c, int status) { - struct bd718xx_clk *c = container_of(hw, struct bd718xx_clk, hw); - return regmap_update_bits(c->mfd->regmap, c->reg, c->mask, status); } @@ -33,14 +32,16 @@ static void bd71837_clk_disable(struct clk_hw *hw) int rv; struct bd718xx_clk *c = container_of(hw, struct bd718xx_clk, hw); - rv = bd71837_clk_set(hw, 0); + rv = bd71837_clk_set(c, 0); if (rv) dev_dbg(&c->pdev->dev, "Failed to disable 32K clk (%d)\n", rv); } static int bd71837_clk_enable(struct clk_hw *hw) { - return bd71837_clk_set(hw, 1); + struct bd718xx_clk *c = container_of(hw, struct bd718xx_clk, hw); + + return bd71837_clk_set(c, 0xffffffff); } static int bd71837_clk_is_enabled(struct clk_hw *hw) @@ -93,6 +94,10 @@ static int bd71837_clk_probe(struct platform_device *pdev) c->reg = BD718XX_REG_OUT32K; c->mask = BD718XX_OUT32K_EN; break; + case ROHM_CHIP_TYPE_BD71828: + c->reg = BD71828_REG_OUT32K; + c->mask = BD71828_OUT32K_EN; + break; case ROHM_CHIP_TYPE_BD70528: c->reg = BD70528_REG_CLK_OUT; c->mask = BD70528_CLK_OUT_EN_MASK; From patchwork Thu Oct 24 11:45:21 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matti Vaittinen X-Patchwork-Id: 1182946 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-rtc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=fi.rohmeurope.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46zQRV0Qxlz9sQv for ; Thu, 24 Oct 2019 22:45:42 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2439128AbfJXLpi (ORCPT ); Thu, 24 Oct 2019 07:45:38 -0400 Received: from mail-lj1-f194.google.com ([209.85.208.194]:36548 "EHLO mail-lj1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726539AbfJXLpi (ORCPT ); Thu, 24 Oct 2019 07:45:38 -0400 Received: by mail-lj1-f194.google.com with SMTP id v24so24692430ljj.3; Thu, 24 Oct 2019 04:45:35 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=iPe9pYSdCJGOUjJsN5Ua6sbEZLC0+OhkAiUXh+LEeuI=; b=dZMYhwFOSuBy8otrCROeogNviwncwaZbmLCuqRtFV3Zs95tssF4JUwZ1sRueChi+0N HCt6DsCCRQ3CDJjyogV2eDxO6FFENFgZM0xmIc14E7KwzMweyOU71dQmMcBmcyoCZMEW JUJ7DawhcWht6B/pJEWXAzu0L6ldQbfisOESpFy6kwEH1/PLlkyzyFvQrBxsWjr2reDN gJgv9paeKxEvX4eOz2hHxR7qc5IS9PnLUcY5mkhJmxWZG2GsodECMsMBwdScC4lql6FJ d2BENNurx0HVzjOGRD6VHsEhIJ8yVxIi5FBQeNt8LRLHL1UfH2jkUvEChCn5dHBGUdwR v4vQ== X-Gm-Message-State: APjAAAW0Bk7uKVcYwDFVNaL27hYlNjEb3IG4ocJg2jI3civkBn4+ZSrg fUpY8SBjs65BeLTDRkKYpHw= X-Google-Smtp-Source: APXvYqw7ND2WXxjGA3uLnHGZDY3/NhnZQ+gEdufcr063vYkCZ7IBpVnnorFqw4pmyFwLvvi0MAFLbQ== X-Received: by 2002:a2e:7801:: with SMTP id t1mr5862871ljc.47.1571917534100; Thu, 24 Oct 2019 04:45:34 -0700 (PDT) Received: from localhost.localdomain ([213.255.186.46]) by smtp.gmail.com with ESMTPSA id c71sm1387809ljf.48.2019.10.24.04.45.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 24 Oct 2019 04:45:33 -0700 (PDT) Date: Thu, 24 Oct 2019 14:45:21 +0300 From: Matti Vaittinen To: matti.vaittinen@fi.rohmeurope.com, mazziesaccount@gmail.com Cc: Lee Jones , Rob Herring , Mark Rutland , Liam Girdwood , Mark Brown , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Jacek Anaszewski , Pavel Machek , Dan Murphy , Alessandro Zummo , Alexandre Belloni , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-leds@vger.kernel.org, linux-rtc@vger.kernel.org Subject: [RFC PATCH v2 06/13] regulator: bd718x7: Split driver to common and bd718x7 specific parts Message-ID: References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.12.1 (2019-06-15) Sender: linux-rtc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rtc@vger.kernel.org Few ROHM PMICs allow setting the voltage states for different system states like RUN, IDLE, SUSPEND and LPSR. States are then changed via SoC specific mechanisms. bd718x7 driver implemented device-tree parsing functions for these state specific voltages. The parsing functions can be re-used by other ROHM chip drivers like bd71828. Split the generic functions from bd718x7-regulator.c to rohm-regulator.c and export them for other modules to use. Signed-off-by: Matti Vaittinen --- No changes since v1 drivers/regulator/Kconfig | 4 + drivers/regulator/Makefile | 1 + drivers/regulator/bd718x7-regulator.c | 183 ++++++++------------------ drivers/regulator/rohm-regulator.c | 95 +++++++++++++ include/linux/mfd/rohm-generic.h | 44 +++++++ 5 files changed, 199 insertions(+), 128 deletions(-) create mode 100644 drivers/regulator/rohm-regulator.c diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index b57093d7c01f..74de76bf98d7 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -196,6 +196,7 @@ config REGULATOR_BD70528 config REGULATOR_BD718XX tristate "ROHM BD71837 Power Regulator" depends on MFD_ROHM_BD718XX + select REGULATOR_ROHM help This driver supports voltage regulators on ROHM BD71837 PMIC. This will enable support for the software controllable buck @@ -780,6 +781,9 @@ config REGULATOR_RN5T618 Say y here to support the regulators found on Ricoh RN5T567, RN5T618 or RC5T619 PMIC. +config REGULATOR_ROHM + tristate + config REGULATOR_RT5033 tristate "Richtek RT5033 Regulators" depends on MFD_RT5033 diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index eef73b5a35a4..41e4055d2d66 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -98,6 +98,7 @@ obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o obj-$(CONFIG_REGULATOR_RK808) += rk808-regulator.o obj-$(CONFIG_REGULATOR_RN5T618) += rn5t618-regulator.o +obj-$(CONFIG_REGULATOR_ROHM) += rohm-regulator.o obj-$(CONFIG_REGULATOR_RT5033) += rt5033-regulator.o obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o diff --git a/drivers/regulator/bd718x7-regulator.c b/drivers/regulator/bd718x7-regulator.c index bdab46a5c461..2dcb010a626c 100644 --- a/drivers/regulator/bd718x7-regulator.c +++ b/drivers/regulator/bd718x7-regulator.c @@ -318,6 +318,7 @@ struct reg_init { }; struct bd718xx_regulator_data { struct regulator_desc desc; + const struct rohm_dvs_config dvs; const struct reg_init init; const struct reg_init *additional_inits; int additional_init_amnt; @@ -349,133 +350,15 @@ static const struct reg_init bd71837_ldo6_inits[] = { }, }; -#define NUM_DVS_BUCKS 4 - -struct of_dvs_setting { - const char *prop; - unsigned int reg; -}; - -static int set_dvs_levels(const struct of_dvs_setting *dvs, - struct device_node *np, - const struct regulator_desc *desc, - struct regmap *regmap) -{ - int ret, i; - unsigned int uv; - - ret = of_property_read_u32(np, dvs->prop, &uv); - if (ret) { - if (ret != -EINVAL) - return ret; - return 0; - } - - for (i = 0; i < desc->n_voltages; i++) { - ret = regulator_desc_list_voltage_linear_range(desc, i); - if (ret < 0) - continue; - if (ret == uv) { - i <<= ffs(desc->vsel_mask) - 1; - ret = regmap_update_bits(regmap, dvs->reg, - DVS_BUCK_RUN_MASK, i); - break; - } - } - return ret; -} - -static int buck4_set_hw_dvs_levels(struct device_node *np, +static int buck_set_hw_dvs_levels(struct device_node *np, const struct regulator_desc *desc, struct regulator_config *cfg) { - int ret, i; - const struct of_dvs_setting dvs[] = { - { - .prop = "rohm,dvs-run-voltage", - .reg = BD71837_REG_BUCK4_VOLT_RUN, - }, - }; + struct bd718xx_regulator_data *data; - for (i = 0; i < ARRAY_SIZE(dvs); i++) { - ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap); - if (ret) - break; - } - return ret; -} -static int buck3_set_hw_dvs_levels(struct device_node *np, - const struct regulator_desc *desc, - struct regulator_config *cfg) -{ - int ret, i; - const struct of_dvs_setting dvs[] = { - { - .prop = "rohm,dvs-run-voltage", - .reg = BD71837_REG_BUCK3_VOLT_RUN, - }, - }; + data = container_of(desc, struct bd718xx_regulator_data, desc); - for (i = 0; i < ARRAY_SIZE(dvs); i++) { - ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap); - if (ret) - break; - } - return ret; -} - -static int buck2_set_hw_dvs_levels(struct device_node *np, - const struct regulator_desc *desc, - struct regulator_config *cfg) -{ - int ret, i; - const struct of_dvs_setting dvs[] = { - { - .prop = "rohm,dvs-run-voltage", - .reg = BD718XX_REG_BUCK2_VOLT_RUN, - }, - { - .prop = "rohm,dvs-idle-voltage", - .reg = BD718XX_REG_BUCK2_VOLT_IDLE, - }, - }; - - - - for (i = 0; i < ARRAY_SIZE(dvs); i++) { - ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap); - if (ret) - break; - } - return ret; -} - -static int buck1_set_hw_dvs_levels(struct device_node *np, - const struct regulator_desc *desc, - struct regulator_config *cfg) -{ - int ret, i; - const struct of_dvs_setting dvs[] = { - { - .prop = "rohm,dvs-run-voltage", - .reg = BD718XX_REG_BUCK1_VOLT_RUN, - }, - { - .prop = "rohm,dvs-idle-voltage", - .reg = BD718XX_REG_BUCK1_VOLT_IDLE, - }, - { - .prop = "rohm,dvs-suspend-voltage", - .reg = BD718XX_REG_BUCK1_VOLT_SUSP, - }, - }; - - for (i = 0; i < ARRAY_SIZE(dvs); i++) { - ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap); - if (ret) - break; - } - return ret; + return rohm_regulator_set_dvs_levels(&data->dvs, np, desc, cfg->regmap); } static const struct bd718xx_regulator_data bd71847_regulators[] = { @@ -496,7 +379,17 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = { .enable_reg = BD718XX_REG_BUCK1_CTRL, .enable_mask = BD718XX_BUCK_EN, .owner = THIS_MODULE, - .of_parse_cb = buck1_set_hw_dvs_levels, + .of_parse_cb = buck_set_hw_dvs_levels, + }, + .dvs = { + .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND, + .run_reg = BD718XX_REG_BUCK1_VOLT_RUN, + .run_mask = DVS_BUCK_RUN_MASK, + .idle_reg = BD718XX_REG_BUCK1_VOLT_IDLE, + .idle_mask = DVS_BUCK_RUN_MASK, + .suspend_reg = BD718XX_REG_BUCK1_VOLT_SUSP, + .suspend_mask = DVS_BUCK_RUN_MASK, }, .init = { .reg = BD718XX_REG_BUCK1_CTRL, @@ -520,7 +413,14 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = { .enable_reg = BD718XX_REG_BUCK2_CTRL, .enable_mask = BD718XX_BUCK_EN, .owner = THIS_MODULE, - .of_parse_cb = buck2_set_hw_dvs_levels, + .of_parse_cb = buck_set_hw_dvs_levels, + }, + .dvs = { + .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE, + .run_reg = BD718XX_REG_BUCK2_VOLT_RUN, + .run_mask = DVS_BUCK_RUN_MASK, + .idle_reg = BD718XX_REG_BUCK2_VOLT_IDLE, + .idle_mask = DVS_BUCK_RUN_MASK, }, .init = { .reg = BD718XX_REG_BUCK2_CTRL, @@ -792,7 +692,17 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .enable_reg = BD718XX_REG_BUCK1_CTRL, .enable_mask = BD718XX_BUCK_EN, .owner = THIS_MODULE, - .of_parse_cb = buck1_set_hw_dvs_levels, + .of_parse_cb = buck_set_hw_dvs_levels, + }, + .dvs = { + .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND, + .run_reg = BD718XX_REG_BUCK1_VOLT_RUN, + .run_mask = DVS_BUCK_RUN_MASK, + .idle_reg = BD718XX_REG_BUCK1_VOLT_IDLE, + .idle_mask = DVS_BUCK_RUN_MASK, + .suspend_reg = BD718XX_REG_BUCK1_VOLT_SUSP, + .suspend_mask = DVS_BUCK_RUN_MASK, }, .init = { .reg = BD718XX_REG_BUCK1_CTRL, @@ -816,7 +726,14 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .enable_reg = BD718XX_REG_BUCK2_CTRL, .enable_mask = BD718XX_BUCK_EN, .owner = THIS_MODULE, - .of_parse_cb = buck2_set_hw_dvs_levels, + .of_parse_cb = buck_set_hw_dvs_levels, + }, + .dvs = { + .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE, + .run_reg = BD718XX_REG_BUCK2_VOLT_RUN, + .run_mask = DVS_BUCK_RUN_MASK, + .idle_reg = BD718XX_REG_BUCK2_VOLT_IDLE, + .idle_mask = DVS_BUCK_RUN_MASK, }, .init = { .reg = BD718XX_REG_BUCK2_CTRL, @@ -840,7 +757,12 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .enable_reg = BD71837_REG_BUCK3_CTRL, .enable_mask = BD718XX_BUCK_EN, .owner = THIS_MODULE, - .of_parse_cb = buck3_set_hw_dvs_levels, + .of_parse_cb = buck_set_hw_dvs_levels, + }, + .dvs = { + .level_map = ROHM_DVS_LEVEL_RUN, + .run_reg = BD71837_REG_BUCK3_VOLT_RUN, + .run_mask = DVS_BUCK_RUN_MASK, }, .init = { .reg = BD71837_REG_BUCK3_CTRL, @@ -864,7 +786,12 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .enable_reg = BD71837_REG_BUCK4_CTRL, .enable_mask = BD718XX_BUCK_EN, .owner = THIS_MODULE, - .of_parse_cb = buck4_set_hw_dvs_levels, + .of_parse_cb = buck_set_hw_dvs_levels, + }, + .dvs = { + .level_map = ROHM_DVS_LEVEL_RUN, + .run_reg = BD71837_REG_BUCK4_VOLT_RUN, + .run_mask = DVS_BUCK_RUN_MASK, }, .init = { .reg = BD71837_REG_BUCK4_CTRL, diff --git a/drivers/regulator/rohm-regulator.c b/drivers/regulator/rohm-regulator.c new file mode 100644 index 000000000000..ca368ada53c6 --- /dev/null +++ b/drivers/regulator/rohm-regulator.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 ROHM Semiconductors + +#include +#include +#include +#include +#include +#include + +static int set_dvs_level(const struct regulator_desc *desc, + struct device_node *np, struct regmap *regmap, + char *prop, unsigned int reg, unsigned int mask, + unsigned int omask, unsigned int oreg) +{ + int ret, i; + uint32_t uv; + + ret = of_property_read_u32(np, prop, &uv); + if (ret) { + if (ret != -EINVAL) + return ret; + return 0; + } + + if (uv == 0) { + if (omask) + return regmap_update_bits(regmap, oreg, omask, 0); + } + for (i = 0; i < desc->n_voltages; i++) { + ret = regulator_desc_list_voltage_linear_range(desc, i); + if (ret < 0) + continue; + if (ret == uv) { + i <<= ffs(desc->vsel_mask) - 1; + ret = regmap_update_bits(regmap, reg, mask, i); + if (omask && !ret) + ret = regmap_update_bits(regmap, oreg, omask, + omask); + break; + } + } + return ret; +} + +int rohm_regulator_set_dvs_levels(const struct rohm_dvs_config *dvs, + struct device_node *np, + const struct regulator_desc *desc, + struct regmap *regmap) +{ + int i, ret = 0; + char *prop; + unsigned int reg, mask, omask, oreg = desc->enable_reg; + + for (i = 0; i < ROHM_DVS_LEVEL_MAX && !ret; i++) { + if (dvs->level_map & (1 << i)) { + switch (i + 1) { + case ROHM_DVS_LEVEL_RUN: + prop = "rohm,dvs-run-voltage"; + reg = dvs->run_reg; + mask = dvs->run_mask; + omask = dvs->run_on_mask; + break; + case ROHM_DVS_LEVEL_IDLE: + prop = "rohm,dvs-idle-voltage"; + reg = dvs->idle_reg; + mask = dvs->idle_mask; + omask = dvs->idle_on_mask; + break; + case ROHM_DVS_LEVEL_SUSPEND: + prop = "rohm,dvs-suspend-voltage"; + reg = dvs->suspend_reg; + mask = dvs->suspend_mask; + omask = dvs->suspend_on_mask; + break; + case ROHM_DVS_LEVEL_LPSR: + prop = "rohm,dvs-lpsr-voltage"; + reg = dvs->lpsr_reg; + mask = dvs->lpsr_mask; + omask = dvs->lpsr_on_mask; + break; + default: + return -EINVAL; + } + ret = set_dvs_level(desc, np, regmap, prop, reg, mask, + omask, oreg); + } + } + return ret; +} +EXPORT_SYMBOL(rohm_regulator_set_dvs_levels); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Matti Vaittinen "); +MODULE_DESCRIPTION("Generic helpers for ROHM PMIC regulator drivers"); diff --git a/include/linux/mfd/rohm-generic.h b/include/linux/mfd/rohm-generic.h index b280f3100d6c..86397b42e9bf 100644 --- a/include/linux/mfd/rohm-generic.h +++ b/include/linux/mfd/rohm-generic.h @@ -4,6 +4,9 @@ #ifndef __LINUX_MFD_ROHM_H__ #define __LINUX_MFD_ROHM_H__ +#include +#include + enum { ROHM_CHIP_TYPE_BD71837 = 0, ROHM_CHIP_TYPE_BD71847, @@ -18,4 +21,45 @@ struct rohm_regmap_dev { struct regmap *regmap; }; +enum { + ROHM_DVS_LEVEL_UNKNOWN, + ROHM_DVS_LEVEL_RUN, + ROHM_DVS_LEVEL_IDLE, + ROHM_DVS_LEVEL_SUSPEND, + ROHM_DVS_LEVEL_LPSR, +#define ROHM_DVS_LEVEL_MAX ROHM_DVS_LEVEL_LPSR +}; + +struct rohm_dvs_config { + uint64_t level_map; + unsigned int run_reg; + unsigned int run_mask; + unsigned int run_on_mask; + unsigned int idle_reg; + unsigned int idle_mask; + unsigned int idle_on_mask; + unsigned int suspend_reg; + unsigned int suspend_mask; + unsigned int suspend_on_mask; + unsigned int lpsr_reg; + unsigned int lpsr_mask; + unsigned int lpsr_on_mask; +}; + +#if IS_ENABLED(CONFIG_REGULATOR_ROHM) +int rohm_regulator_set_dvs_levels(const struct rohm_dvs_config *dvs, + struct device_node *np, + const struct regulator_desc *desc, + struct regmap *regmap); + +#else +static inline int rohm_regulator_set_dvs_levels(const struct rohm_dvs_config *dvs, + struct device_node *np, + const struct regulator_desc *desc, + struct regmap *regmap) +{ + return 0; +} +#endif //IS_ENABLED(CONFIG_REGULATOR_ROHM) + #endif From patchwork Thu Oct 24 11:46:11 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matti Vaittinen X-Patchwork-Id: 1182949 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-rtc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=fi.rohmeurope.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46zQST2H5Rz9sPp for ; Thu, 24 Oct 2019 22:46:33 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2439187AbfJXLqa (ORCPT ); Thu, 24 Oct 2019 07:46:30 -0400 Received: from mail-lj1-f195.google.com ([209.85.208.195]:41760 "EHLO mail-lj1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727640AbfJXLqa (ORCPT ); Thu, 24 Oct 2019 07:46:30 -0400 Received: by mail-lj1-f195.google.com with SMTP id f5so24691220ljg.8; Thu, 24 Oct 2019 04:46:25 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=C6Z4hoBYYnSNpG53wl3HJ7RNqz8c3gdp/uDqn84O8nA=; b=NwAy4EvWK6xQYN2gat+ljvJtc+yNcHu52tZWtsomRu+oNBgcboaAVvsGnpgfPQ3FUQ 81kFTr6LP33XP//guJ36bfsKVJK1ZJLPJHZhbeDnsTVUnAzRvL4uAPEIgQV6JcEW4M0H u8H5AVVtX9mpBXHyWwsBpwwImuEuLrZU+l7M8dkHu9aDvtcCizsaJ23v070csNIy/cKk /GbDyU2F756xSVyel1ip6EX91mPCOu8NKlj9cXFHCxoWpkdUEuUHA5/YK85Rbi0CZlTt dr+23wrzy54gj4T2qQgCGSWII0jE7ROBjenEC8XuAt0uvtb2S+v3NWQa/0jpiUkmG9pa I7OA== X-Gm-Message-State: APjAAAUCw/x+jyN3uV1O5UBQ7QGyZnylaL6HZcrOMiXRRx8bueyUx6aw Id4kZN18LBnhWc5Fy4X/QwQ= X-Google-Smtp-Source: APXvYqwVJ/GJ8BJBOyaSEBIIWondQ7Jp3LwZ6y55LLEd7HAoWCzcDOzXQwBcWhhIEo1+M837SUFRNw== X-Received: by 2002:a2e:89da:: with SMTP id c26mr2081044ljk.202.1571917584216; Thu, 24 Oct 2019 04:46:24 -0700 (PDT) Received: from localhost.localdomain ([213.255.186.46]) by smtp.gmail.com with ESMTPSA id d24sm7770760lfl.65.2019.10.24.04.46.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 24 Oct 2019 04:46:23 -0700 (PDT) Date: Thu, 24 Oct 2019 14:46:11 +0300 From: Matti Vaittinen To: matti.vaittinen@fi.rohmeurope.com, mazziesaccount@gmail.com Cc: Lee Jones , Rob Herring , Mark Rutland , Liam Girdwood , Mark Brown , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Jacek Anaszewski , Pavel Machek , Dan Murphy , Alessandro Zummo , Alexandre Belloni , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-leds@vger.kernel.org, linux-rtc@vger.kernel.org Subject: [RFC PATCH v2 07/13] regulator: bd71828: Basic support for ROHM bd71828 PMIC regulators Message-ID: <227cf16ac7e2950d0cb5a1e32137270d0a32a8e7.1571915550.git.matti.vaittinen@fi.rohmeurope.com> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.12.1 (2019-06-15) Sender: linux-rtc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rtc@vger.kernel.org ROHM BD71828 is a power management IC containing 7 bucks and 7 LDOs. Bucks 1,2,6 and 7 can be assigned to a regulator group controlled by run-levels. Eg. Voltages and enable/disable statuses for specific run-levels (run0 to run3) can be set via register interface and run level changes can then be done either via I2C or GPIO. This initial commit does not support assigning bucks to be controlled via run-levels but only allows them to be individually controlled. LDO5 voltage can also be controlled by GPIO2 pin and register interfaces but this driver only supports the control via register. Signed-off-by: Matti Vaittinen --- Only MODULE_ALIAS added since v1 drivers/regulator/Kconfig | 12 + drivers/regulator/Makefile | 1 + drivers/regulator/bd71828-regulator.c | 833 ++++++++++++++++++++++++++ 3 files changed, 846 insertions(+) create mode 100644 drivers/regulator/bd71828-regulator.c diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 74de76bf98d7..8c94a35d059a 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -193,6 +193,18 @@ config REGULATOR_BD70528 This driver can also be built as a module. If so, the module will be called bd70528-regulator. +config REGULATOR_BD71828 + tristate "ROHM BD71828 Power Regulator" + depends on MFD_ROHM_BD71828 + select REGULATOR_ROHM + help + This driver supports voltage regulators on ROHM BD71828 PMIC. + This will enable support for the software controllable buck + and LDO regulators. + + This driver can also be built as a module. If so, the module + will be called bd71828-regulator. + config REGULATOR_BD718XX tristate "ROHM BD71837 Power Regulator" depends on MFD_ROHM_BD718XX diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 41e4055d2d66..b363b592a429 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o obj-$(CONFIG_REGULATOR_BD70528) += bd70528-regulator.o +obj-$(CONFIG_REGULATOR_BD71828) += bd71828-regulator.o obj-$(CONFIG_REGULATOR_BD718XX) += bd718x7-regulator.o obj-$(CONFIG_REGULATOR_BD9571MWV) += bd9571mwv-regulator.o obj-$(CONFIG_REGULATOR_DA903X) += da903x.o diff --git a/drivers/regulator/bd71828-regulator.c b/drivers/regulator/bd71828-regulator.c new file mode 100644 index 000000000000..3f46658280be --- /dev/null +++ b/drivers/regulator/bd71828-regulator.c @@ -0,0 +1,833 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2019 ROHM Semiconductors +// bd71828-regulator.c ROHM BD71828GW-DS1 regulator driver +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct reg_init { + unsigned int reg; + unsigned int mask; + unsigned int val; +}; +struct bd71828_regulator_data { + struct regulator_desc desc; + const struct rohm_dvs_config dvs; + const struct reg_init *reg_inits; + int reg_init_amnt; +}; + +static const struct reg_init buck1_inits[] = { + /* + * DVS Buck voltages can be changed by register values or via GPIO. + * Use register accesses by default. + */ + { + .reg = BD71828_REG_PS_CTRL_1, + .mask = BD71828_MASK_DVS_BUCK1_CTRL, + .val = BD71828_DVS_BUCK1_CTRL_I2C, + }, +}; + +static const struct reg_init buck2_inits[] = { + { + .reg = BD71828_REG_PS_CTRL_1, + .mask = BD71828_MASK_DVS_BUCK2_CTRL, + .val = BD71828_DVS_BUCK2_CTRL_I2C, + }, +}; + +static const struct reg_init buck6_inits[] = { + { + .reg = BD71828_REG_PS_CTRL_1, + .mask = BD71828_MASK_DVS_BUCK6_CTRL, + .val = BD71828_DVS_BUCK6_CTRL_I2C, + }, +}; + +static const struct reg_init buck7_inits[] = { + { + .reg = BD71828_REG_PS_CTRL_1, + .mask = BD71828_MASK_DVS_BUCK7_CTRL, + .val = BD71828_DVS_BUCK7_CTRL_I2C, + }, +}; + +static const struct regulator_linear_range bd71828_buck1267_volts[] = { + REGULATOR_LINEAR_RANGE(500000, 0x00, 0xef, 6250), + REGULATOR_LINEAR_RANGE(2000000, 0xf0, 0xff, 0), +}; + +static const struct regulator_linear_range bd71828_buck3_volts[] = { + REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x0f, 50000), + REGULATOR_LINEAR_RANGE(2000000, 0x10, 0x1f, 0), +}; + +static const struct regulator_linear_range bd71828_buck4_volts[] = { + REGULATOR_LINEAR_RANGE(1000000, 0x00, 0x1f, 25000), + REGULATOR_LINEAR_RANGE(1800000, 0x20, 0x3f, 0), +}; + +static const struct regulator_linear_range bd71828_buck5_volts[] = { + REGULATOR_LINEAR_RANGE(2500000, 0x00, 0x0f, 50000), + REGULATOR_LINEAR_RANGE(3300000, 0x10, 0x1f, 0), +}; + +static const struct regulator_linear_range bd71828_ldo_volts[] = { + REGULATOR_LINEAR_RANGE(800000, 0x00, 0x31, 50000), + REGULATOR_LINEAR_RANGE(3300000, 0x32, 0x3f, 0), +}; + +static int ramp_delay_supported(struct regulator_dev *rdev) +{ + switch (rdev->desc->id) { + case BD71828_BUCK1: + case BD71828_BUCK2: + case BD71828_BUCK6: + case BD71828_BUCK7: + return 1; + default: + break; + } + return 0; +} + +static int bd71828_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) +{ + unsigned int val; + + if (!ramp_delay_supported(rdev)) { + dev_err(&rdev->dev, "%s: can't set ramp-delay\n", + rdev->desc->name); + return -EINVAL; + } + + switch (ramp_delay) { + case 1 ... 2500: + val = 0; + break; + case 2501 ... 5000: + val = 1; + break; + case 5001 ... 10000: + val = 2; + break; + case 10001 ... 20000: + val = 3; + break; + default: + val = 3; + dev_err(&rdev->dev, + "ramp_delay: %d not supported, setting 20mV/uS", + ramp_delay); + } + + /* + * On BD71828 the ramp delay level control reg is at offset +2 to + * enable reg + */ + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg + 2, + BD71828_MASK_RAMP_DELAY, + val << (ffs(BD71828_MASK_RAMP_DELAY) - 1)); + +} + +static int buck_set_hw_dvs_levels(struct device_node *np, + const struct regulator_desc *desc, + struct regulator_config *cfg) +{ + struct bd71828_regulator_data *data; + + data = container_of(desc, struct bd71828_regulator_data, desc); + + return rohm_regulator_set_dvs_levels(&data->dvs, np, desc, cfg->regmap); +} + +static int ldo6_parse_dt(struct device_node *np, + const struct regulator_desc *desc, + struct regulator_config *cfg) +{ + int ret, i; + uint32_t uv = 0; + unsigned int en; + struct regmap *regmap = cfg->regmap; + static const char * const props[] = { "rohm,dvs-run-voltage", + "rohm,dvs-idle-voltage", + "rohm,dvs-suspend-voltage", + "rohm,dvs-lpsr-voltage" }; + unsigned int mask[] = { BD71828_MASK_RUN_EN, BD71828_MASK_IDLE_EN, + BD71828_MASK_SUSP_EN, BD71828_MASK_LPSR_EN }; + + for (i = 0; i < ARRAY_SIZE(props); i++) { + ret = of_property_read_u32(np, props[i], &uv); + if (ret) { + if (ret != -EINVAL) + return ret; + continue; + } + if (uv) + en = 0xffffffff; + else + en = 0; + + ret = regmap_update_bits(regmap, desc->enable_reg, mask[i], en); + if (ret) + return ret; + } + return 0; +} + +static const struct regulator_ops bd71828_buck_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, +}; + +static const struct regulator_ops bd71828_dvs_buck_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_ramp_delay = bd71828_set_ramp_delay, +}; + +static const struct regulator_ops bd71828_ldo_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, +}; + +static int bd71828_ldo6_get_voltage(struct regulator_dev *rdev) +{ + return BD71828_LDO_6_VOLTAGE; +} + +static const struct regulator_ops bd71828_ldo6_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .get_voltage = bd71828_ldo6_get_voltage, + .is_enabled = regulator_is_enabled_regmap, +}; + +static const struct bd71828_regulator_data bd71828_rdata[] = { + { + .desc = { + .name = "buck1", + .of_match = of_match_ptr("BUCK1"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71828_BUCK1, + .ops = &bd71828_dvs_buck_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd71828_buck1267_volts, + .n_linear_ranges = ARRAY_SIZE(bd71828_buck1267_volts), + .n_voltages = BD71828_BUCK1267_VOLTS, + .enable_reg = BD71828_REG_BUCK1_EN, + .enable_mask = BD71828_MASK_RUN_EN, + .vsel_reg = BD71828_REG_BUCK1_VOLT, + .vsel_mask = BD71828_MASK_BUCK1267_VOLT, + .owner = THIS_MODULE, + .of_parse_cb = buck_set_hw_dvs_levels, + }, + .dvs = { + .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_BUCK1_VOLT, + .run_mask = BD71828_MASK_BUCK1267_VOLT, + .idle_reg = BD71828_REG_BUCK1_IDLE_VOLT, + .idle_mask = BD71828_MASK_BUCK1267_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_reg = BD71828_REG_BUCK1_SUSP_VOLT, + .suspend_mask = BD71828_MASK_BUCK1267_VOLT, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, + /* + * LPSR voltage is same as SUSPEND voltage. Allow + * setting it so that regulator can be set enabled at + * LPSR state + */ + .lpsr_reg = BD71828_REG_BUCK1_SUSP_VOLT, + .lpsr_mask = BD71828_MASK_BUCK1267_VOLT, + }, + .reg_inits = buck1_inits, + .reg_init_amnt = ARRAY_SIZE(buck1_inits), + }, + { + .desc = { + .name = "buck2", + .of_match = of_match_ptr("BUCK2"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71828_BUCK2, + .ops = &bd71828_dvs_buck_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd71828_buck1267_volts, + .n_linear_ranges = ARRAY_SIZE(bd71828_buck1267_volts), + .n_voltages = BD71828_BUCK1267_VOLTS, + .enable_reg = BD71828_REG_BUCK2_EN, + .enable_mask = BD71828_MASK_RUN_EN, + .vsel_reg = BD71828_REG_BUCK2_VOLT, + .vsel_mask = BD71828_MASK_BUCK1267_VOLT, + .owner = THIS_MODULE, + .of_parse_cb = buck_set_hw_dvs_levels, + }, + .dvs = { + .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_BUCK2_VOLT, + .run_mask = BD71828_MASK_BUCK1267_VOLT, + .idle_reg = BD71828_REG_BUCK2_IDLE_VOLT, + .idle_mask = BD71828_MASK_BUCK1267_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_reg = BD71828_REG_BUCK2_SUSP_VOLT, + .suspend_mask = BD71828_MASK_BUCK1267_VOLT, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, + .lpsr_reg = BD71828_REG_BUCK2_SUSP_VOLT, + .lpsr_mask = BD71828_MASK_BUCK1267_VOLT, + }, + .reg_inits = buck2_inits, + .reg_init_amnt = ARRAY_SIZE(buck2_inits), + }, + { + .desc = { + .name = "buck3", + .of_match = of_match_ptr("BUCK3"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71828_BUCK3, + .ops = &bd71828_buck_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd71828_buck3_volts, + .n_linear_ranges = ARRAY_SIZE(bd71828_buck3_volts), + .n_voltages = BD71828_BUCK3_VOLTS, + .enable_reg = BD71828_REG_BUCK3_EN, + .enable_mask = BD71828_MASK_RUN_EN, + .vsel_reg = BD71828_REG_BUCK3_VOLT, + .vsel_mask = BD71828_MASK_BUCK3_VOLT, + .owner = THIS_MODULE, + .of_parse_cb = buck_set_hw_dvs_levels, + }, + .dvs = { + /* + * BUCK3 only supports single voltage for all states. + * voltage can be individually enabled for each state + * though => allow setting all states to support + * enabling power rail on different states. + */ + .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_BUCK3_VOLT, + .idle_reg = BD71828_REG_BUCK3_VOLT, + .suspend_reg = BD71828_REG_BUCK3_VOLT, + .lpsr_reg = BD71828_REG_BUCK3_VOLT, + .run_mask = BD71828_MASK_BUCK3_VOLT, + .idle_mask = BD71828_MASK_BUCK3_VOLT, + .suspend_mask = BD71828_MASK_BUCK3_VOLT, + .lpsr_mask = BD71828_MASK_BUCK3_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, + }, + }, + { + .desc = { + .name = "buck4", + .of_match = of_match_ptr("BUCK4"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71828_BUCK4, + .ops = &bd71828_buck_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd71828_buck4_volts, + .n_linear_ranges = ARRAY_SIZE(bd71828_buck4_volts), + .n_voltages = BD71828_BUCK4_VOLTS, + .enable_reg = BD71828_REG_BUCK4_EN, + .enable_mask = BD71828_MASK_RUN_EN, + .vsel_reg = BD71828_REG_BUCK4_VOLT, + .vsel_mask = BD71828_MASK_BUCK4_VOLT, + .owner = THIS_MODULE, + .of_parse_cb = buck_set_hw_dvs_levels, + }, + .dvs = { + /* + * BUCK4 only supports single voltage for all states. + * voltage can be individually enabled for each state + * though => allow setting all states to support + * enabling power rail on different states. + */ + .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_BUCK4_VOLT, + .idle_reg = BD71828_REG_BUCK4_VOLT, + .suspend_reg = BD71828_REG_BUCK4_VOLT, + .lpsr_reg = BD71828_REG_BUCK4_VOLT, + .run_mask = BD71828_MASK_BUCK4_VOLT, + .idle_mask = BD71828_MASK_BUCK4_VOLT, + .suspend_mask = BD71828_MASK_BUCK4_VOLT, + .lpsr_mask = BD71828_MASK_BUCK4_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, + }, + }, + { + .desc = { + .name = "buck5", + .of_match = of_match_ptr("BUCK5"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71828_BUCK5, + .ops = &bd71828_buck_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd71828_buck5_volts, + .n_linear_ranges = ARRAY_SIZE(bd71828_buck5_volts), + .n_voltages = BD71828_BUCK5_VOLTS, + .enable_reg = BD71828_REG_BUCK5_EN, + .enable_mask = BD71828_MASK_RUN_EN, + .vsel_reg = BD71828_REG_BUCK5_VOLT, + .vsel_mask = BD71828_MASK_BUCK5_VOLT, + .owner = THIS_MODULE, + .of_parse_cb = buck_set_hw_dvs_levels, + }, + .dvs = { + /* + * BUCK5 only supports single voltage for all states. + * voltage can be individually enabled for each state + * though => allow setting all states to support + * enabling power rail on different states. + */ + .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_BUCK5_VOLT, + .idle_reg = BD71828_REG_BUCK5_VOLT, + .suspend_reg = BD71828_REG_BUCK5_VOLT, + .lpsr_reg = BD71828_REG_BUCK5_VOLT, + .run_mask = BD71828_MASK_BUCK5_VOLT, + .idle_mask = BD71828_MASK_BUCK5_VOLT, + .suspend_mask = BD71828_MASK_BUCK5_VOLT, + .lpsr_mask = BD71828_MASK_BUCK5_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, + }, + }, + { + .desc = { + .name = "buck6", + .of_match = of_match_ptr("BUCK6"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71828_BUCK6, + .ops = &bd71828_dvs_buck_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd71828_buck1267_volts, + .n_linear_ranges = ARRAY_SIZE(bd71828_buck1267_volts), + .n_voltages = BD71828_BUCK1267_VOLTS, + .enable_reg = BD71828_REG_BUCK6_EN, + .enable_mask = BD71828_MASK_RUN_EN, + .vsel_reg = BD71828_REG_BUCK6_VOLT, + .vsel_mask = BD71828_MASK_BUCK1267_VOLT, + .owner = THIS_MODULE, + .of_parse_cb = buck_set_hw_dvs_levels, + }, + .dvs = { + .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_BUCK6_VOLT, + .run_mask = BD71828_MASK_BUCK1267_VOLT, + .idle_reg = BD71828_REG_BUCK6_IDLE_VOLT, + .idle_mask = BD71828_MASK_BUCK1267_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_reg = BD71828_REG_BUCK6_SUSP_VOLT, + .suspend_mask = BD71828_MASK_BUCK1267_VOLT, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, + .lpsr_reg = BD71828_REG_BUCK6_SUSP_VOLT, + .lpsr_mask = BD71828_MASK_BUCK1267_VOLT, + }, + .reg_inits = buck6_inits, + .reg_init_amnt = ARRAY_SIZE(buck6_inits), + }, + { + .desc = { + .name = "buck7", + .of_match = of_match_ptr("BUCK7"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71828_BUCK7, + .ops = &bd71828_dvs_buck_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd71828_buck1267_volts, + .n_linear_ranges = ARRAY_SIZE(bd71828_buck1267_volts), + .n_voltages = BD71828_BUCK1267_VOLTS, + .enable_reg = BD71828_REG_BUCK7_EN, + .enable_mask = BD71828_MASK_RUN_EN, + .vsel_reg = BD71828_REG_BUCK7_VOLT, + .vsel_mask = BD71828_MASK_BUCK1267_VOLT, + .owner = THIS_MODULE, + .of_parse_cb = buck_set_hw_dvs_levels, + }, + .dvs = { + .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_BUCK7_VOLT, + .run_mask = BD71828_MASK_BUCK1267_VOLT, + .idle_reg = BD71828_REG_BUCK7_IDLE_VOLT, + .idle_mask = BD71828_MASK_BUCK1267_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_reg = BD71828_REG_BUCK7_SUSP_VOLT, + .suspend_mask = BD71828_MASK_BUCK1267_VOLT, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, + .lpsr_reg = BD71828_REG_BUCK7_SUSP_VOLT, + .lpsr_mask = BD71828_MASK_BUCK1267_VOLT, + }, + .reg_inits = buck7_inits, + .reg_init_amnt = ARRAY_SIZE(buck7_inits), + }, + { + .desc = { + .name = "ldo1", + .of_match = of_match_ptr("LDO1"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71828_LDO1, + .ops = &bd71828_ldo_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd71828_ldo_volts, + .n_linear_ranges = ARRAY_SIZE(bd71828_ldo_volts), + .n_voltages = BD71828_LDO_VOLTS, + .enable_reg = BD71828_REG_LDO1_EN, + .enable_mask = BD71828_MASK_RUN_EN, + .vsel_reg = BD71828_REG_LDO1_VOLT, + .vsel_mask = BD71828_MASK_LDO_VOLT, + .owner = THIS_MODULE, + .of_parse_cb = buck_set_hw_dvs_levels, + }, + .dvs = { + /* + * LDO1 only supports single voltage for all states. + * voltage can be individually enabled for each state + * though => allow setting all states to support + * enabling power rail on different states. + */ + .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_LDO1_VOLT, + .idle_reg = BD71828_REG_LDO1_VOLT, + .suspend_reg = BD71828_REG_LDO1_VOLT, + .lpsr_reg = BD71828_REG_LDO1_VOLT, + .run_mask = BD71828_MASK_LDO_VOLT, + .idle_mask = BD71828_MASK_LDO_VOLT, + .suspend_mask = BD71828_MASK_LDO_VOLT, + .lpsr_mask = BD71828_MASK_LDO_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, + }, + }, { + .desc = { + .name = "ldo2", + .of_match = of_match_ptr("LDO2"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71828_LDO2, + .ops = &bd71828_ldo_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd71828_ldo_volts, + .n_linear_ranges = ARRAY_SIZE(bd71828_ldo_volts), + .n_voltages = BD71828_LDO_VOLTS, + .enable_reg = BD71828_REG_LDO2_EN, + .enable_mask = BD71828_MASK_RUN_EN, + .vsel_reg = BD71828_REG_LDO2_VOLT, + .vsel_mask = BD71828_MASK_LDO_VOLT, + .owner = THIS_MODULE, + .of_parse_cb = buck_set_hw_dvs_levels, + }, + .dvs = { + /* + * LDO2 only supports single voltage for all states. + * voltage can be individually enabled for each state + * though => allow setting all states to support + * enabling power rail on different states. + */ + .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_LDO2_VOLT, + .idle_reg = BD71828_REG_LDO2_VOLT, + .suspend_reg = BD71828_REG_LDO2_VOLT, + .lpsr_reg = BD71828_REG_LDO2_VOLT, + .run_mask = BD71828_MASK_LDO_VOLT, + .idle_mask = BD71828_MASK_LDO_VOLT, + .suspend_mask = BD71828_MASK_LDO_VOLT, + .lpsr_mask = BD71828_MASK_LDO_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, + }, + }, { + .desc = { + .name = "ldo3", + .of_match = of_match_ptr("LDO3"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71828_LDO3, + .ops = &bd71828_ldo_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd71828_ldo_volts, + .n_linear_ranges = ARRAY_SIZE(bd71828_ldo_volts), + .n_voltages = BD71828_LDO_VOLTS, + .enable_reg = BD71828_REG_LDO3_EN, + .enable_mask = BD71828_MASK_RUN_EN, + .vsel_reg = BD71828_REG_LDO3_VOLT, + .vsel_mask = BD71828_MASK_LDO_VOLT, + .owner = THIS_MODULE, + .of_parse_cb = buck_set_hw_dvs_levels, + }, + .dvs = { + /* + * LDO3 only supports single voltage for all states. + * voltage can be individually enabled for each state + * though => allow setting all states to support + * enabling power rail on different states. + */ + .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_LDO3_VOLT, + .idle_reg = BD71828_REG_LDO3_VOLT, + .suspend_reg = BD71828_REG_LDO3_VOLT, + .lpsr_reg = BD71828_REG_LDO3_VOLT, + .run_mask = BD71828_MASK_LDO_VOLT, + .idle_mask = BD71828_MASK_LDO_VOLT, + .suspend_mask = BD71828_MASK_LDO_VOLT, + .lpsr_mask = BD71828_MASK_LDO_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, + }, + + }, { + .desc = { + .name = "ldo4", + .of_match = of_match_ptr("LDO4"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71828_LDO4, + .ops = &bd71828_ldo_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd71828_ldo_volts, + .n_linear_ranges = ARRAY_SIZE(bd71828_ldo_volts), + .n_voltages = BD71828_LDO_VOLTS, + .enable_reg = BD71828_REG_LDO4_EN, + .enable_mask = BD71828_MASK_RUN_EN, + .vsel_reg = BD71828_REG_LDO4_VOLT, + .vsel_mask = BD71828_MASK_LDO_VOLT, + .owner = THIS_MODULE, + .of_parse_cb = buck_set_hw_dvs_levels, + }, + .dvs = { + /* + * LDO1 only supports single voltage for all states. + * voltage can be individually enabled for each state + * though => allow setting all states to support + * enabling power rail on different states. + */ + .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_LDO4_VOLT, + .idle_reg = BD71828_REG_LDO4_VOLT, + .suspend_reg = BD71828_REG_LDO4_VOLT, + .lpsr_reg = BD71828_REG_LDO4_VOLT, + .run_mask = BD71828_MASK_LDO_VOLT, + .idle_mask = BD71828_MASK_LDO_VOLT, + .suspend_mask = BD71828_MASK_LDO_VOLT, + .lpsr_mask = BD71828_MASK_LDO_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, + }, + }, { + .desc = { + .name = "ldo5", + .of_match = of_match_ptr("LDO5"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71828_LDO5, + .ops = &bd71828_ldo_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd71828_ldo_volts, + .n_linear_ranges = ARRAY_SIZE(bd71828_ldo_volts), + .n_voltages = BD71828_LDO_VOLTS, + .enable_reg = BD71828_REG_LDO5_EN, + .enable_mask = BD71828_MASK_RUN_EN, + .vsel_reg = BD71828_REG_LDO5_VOLT, + .vsel_mask = BD71828_MASK_LDO_VOLT, + .of_parse_cb = buck_set_hw_dvs_levels, + .owner = THIS_MODULE, + }, + /* + * LDO5 is special. It can choose vsel settings to be configured + * from 2 different registers (by GPIO). + * + * This driver supports only configuration where + * BD71828_REG_LDO5_VOLT_L is used. + */ + .dvs = { + .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_LDO5_VOLT, + .idle_reg = BD71828_REG_LDO5_VOLT, + .suspend_reg = BD71828_REG_LDO5_VOLT, + .lpsr_reg = BD71828_REG_LDO5_VOLT, + .run_mask = BD71828_MASK_LDO_VOLT, + .idle_mask = BD71828_MASK_LDO_VOLT, + .suspend_mask = BD71828_MASK_LDO_VOLT, + .lpsr_mask = BD71828_MASK_LDO_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, + }, + + }, { + .desc = { + .name = "ldo6", + .of_match = of_match_ptr("LDO6"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71828_LDO6, + .ops = &bd71828_ldo6_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 1, + .enable_reg = BD71828_REG_LDO6_EN, + .enable_mask = BD71828_MASK_RUN_EN, + .owner = THIS_MODULE, + /* + * LDO6 only supports enable/disable for all states. + * Voltage for LDO6 is fixed. + */ + .of_parse_cb = ldo6_parse_dt, + }, + }, { + .desc = { + /* SNVS LDO in data-sheet */ + .name = "ldo7", + .of_match = of_match_ptr("LDO7"), + .regulators_node = of_match_ptr("regulators"), + .id = BD71828_LDO_SNVS, + .ops = &bd71828_ldo_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd71828_ldo_volts, + .n_linear_ranges = ARRAY_SIZE(bd71828_ldo_volts), + .n_voltages = BD71828_LDO_VOLTS, + .enable_reg = BD71828_REG_LDO7_EN, + .enable_mask = BD71828_MASK_RUN_EN, + .vsel_reg = BD71828_REG_LDO7_VOLT, + .vsel_mask = BD71828_MASK_LDO_VOLT, + .owner = THIS_MODULE, + .of_parse_cb = buck_set_hw_dvs_levels, + }, + .dvs = { + /* + * LDO7 only supports single voltage for all states. + * voltage can be individually enabled for each state + * though => allow setting all states to support + * enabling power rail on different states. + */ + .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_LDO7_VOLT, + .idle_reg = BD71828_REG_LDO7_VOLT, + .suspend_reg = BD71828_REG_LDO7_VOLT, + .lpsr_reg = BD71828_REG_LDO7_VOLT, + .run_mask = BD71828_MASK_LDO_VOLT, + .idle_mask = BD71828_MASK_LDO_VOLT, + .suspend_mask = BD71828_MASK_LDO_VOLT, + .lpsr_mask = BD71828_MASK_LDO_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, + }, + + }, +}; + +static int bd71828_probe(struct platform_device *pdev) +{ + struct rohm_regmap_dev *bd71828; + int i, j, ret; + struct regulator_config config = { + .dev = pdev->dev.parent, + }; + + bd71828 = dev_get_drvdata(pdev->dev.parent); + if (!bd71828) { + dev_err(&pdev->dev, "No MFD driver data\n"); + return -EINVAL; + } + + config.regmap = bd71828->regmap; + + for (i = 0; i < ARRAY_SIZE(bd71828_rdata); i++) { + struct regulator_dev *rdev; + const struct bd71828_regulator_data *rd; + + rd = &bd71828_rdata[i]; + rdev = devm_regulator_register(&pdev->dev, + &rd->desc, &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, + "failed to register %s regulator\n", + rd->desc.name); + return PTR_ERR(rdev); + } + for (j = 0; j < rd->reg_init_amnt; j++) { + ret = regmap_update_bits(bd71828->regmap, + rd->reg_inits[j].reg, + rd->reg_inits[j].mask, + rd->reg_inits[j].val); + if (ret) { + dev_err(&pdev->dev, + "regulator %s init failed\n", + rd->desc.name); + return ret; + } + } + } + return 0; +} + +static struct platform_driver bd71828_regulator = { + .driver = { + .name = "bd71828-pmic" + }, + .probe = bd71828_probe, +}; + +module_platform_driver(bd71828_regulator); + +MODULE_AUTHOR("Matti Vaittinen "); +MODULE_DESCRIPTION("BD71828 voltage regulator driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:bd71828-pmic"); From patchwork Thu Oct 24 11:46:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matti Vaittinen X-Patchwork-Id: 1182951 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-rtc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=fi.rohmeurope.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46zQT91T7Rz9sR6 for ; Thu, 24 Oct 2019 22:47:09 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2439232AbfJXLrG (ORCPT ); Thu, 24 Oct 2019 07:47:06 -0400 Received: from mail-lj1-f193.google.com ([209.85.208.193]:40878 "EHLO mail-lj1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726389AbfJXLrG (ORCPT ); Thu, 24 Oct 2019 07:47:06 -0400 Received: by mail-lj1-f193.google.com with SMTP id u22so6666653lji.7; Thu, 24 Oct 2019 04:47:02 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=2uBxiqFRr27NOSfDxOemThl4tT4iSqF92bbSsz0sDp4=; b=hP+chXzUHO1fIWGIpW8ttj+/zqovy/pEuV0GRDGoMdWSs/mqCAwTaCdp9TMh0Fu0T3 xT6D4MPaDQRwmhMc2mtLY4A6chhpG+zVchxwgqk2bqBnGJtIPKVEPH9AihRRILrM2Vnt +oA+HPkZW0Vf39G1vLrIxZAYjiOC+2AMsvvHbohvPIVt6NvaMada9OIPah+4/YOgvJrr qaEefcTRdEQYgjuDgmS28d/5hTK8CRtdxNNNdW/kEaCc8Fu4SU4lowqqhaOBx/hsksMY msDi8GgmIqz0dLuNxcINEV/3cr2M6UDx1Dxwg0YZ/PE9at2JpXJEVezUssI50Maqtxxp zfJA== X-Gm-Message-State: APjAAAVlEQvwnSJttzu2eGY8gIVVtjrsOYzv48sFNkaVdF7/9NrGX5bq 9VbHP4SVk4TwKxD84K3yaYc= X-Google-Smtp-Source: APXvYqwNA7MBp6o09aB3ZrXAS6ePVvAQAs/3sPMgLOK9yZQcrzCE1SIS3ObvRfzzx2x0w/2TEmIlCA== X-Received: by 2002:a2e:998a:: with SMTP id w10mr7362727lji.152.1571917621066; Thu, 24 Oct 2019 04:47:01 -0700 (PDT) Received: from localhost.localdomain ([213.255.186.46]) by smtp.gmail.com with ESMTPSA id a8sm12443810ljf.47.2019.10.24.04.46.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 24 Oct 2019 04:47:00 -0700 (PDT) Date: Thu, 24 Oct 2019 14:46:47 +0300 From: Matti Vaittinen To: matti.vaittinen@fi.rohmeurope.com, mazziesaccount@gmail.com Cc: Lee Jones , Rob Herring , Mark Rutland , Liam Girdwood , Mark Brown , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Jacek Anaszewski , Pavel Machek , Dan Murphy , Alessandro Zummo , Alexandre Belloni , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-leds@vger.kernel.org, linux-rtc@vger.kernel.org Subject: [RFC PATCH v2 08/13] regulator: bd71828: Add GPIO based run-level control for regulators Message-ID: <061d83fdf6bd274adc7e8efd6e423cdc571c26fa.1571915550.git.matti.vaittinen@fi.rohmeurope.com> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.12.1 (2019-06-15) Sender: linux-rtc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rtc@vger.kernel.org Bucks 1,2,6 and 7 on RPHM BD71828 can be either controlled as individual regulartors - or they can be grouped to a group of regulators that are controlled by 'run levels'. This can be done via I2C. Each regulator can be assigned a voltage and enable/disable status for each run-level. These statuses are also changeable via I2C. Run-levels can then be changed either by I2C or GPIO. This control mechanism is selected by data in one time programmable area (during production) and can't be changed later. Allow regulators to be controlled via run-levels and allow getting/setting the current run-level also via GPIO. Signed-off-by: Matti Vaittinen --- No changes since v1 drivers/regulator/bd71828-regulator.c | 373 +++++++++++++++++++++++++- 1 file changed, 362 insertions(+), 11 deletions(-) diff --git a/drivers/regulator/bd71828-regulator.c b/drivers/regulator/bd71828-regulator.c index 3f46658280be..e82e94ecf747 100644 --- a/drivers/regulator/bd71828-regulator.c +++ b/drivers/regulator/bd71828-regulator.c @@ -4,8 +4,10 @@ // #include +#include #include #include +#include #include #include #include @@ -17,16 +19,27 @@ #include #include +#define MAX_GPIO_DVS_BUCKS 4 +#define DVS_RUN_LEVELS 4 + struct reg_init { unsigned int reg; unsigned int mask; unsigned int val; }; + +struct run_lvl_ctrl { + unsigned int voltage; + bool enabled; +}; + struct bd71828_regulator_data { struct regulator_desc desc; - const struct rohm_dvs_config dvs; + struct rohm_dvs_config dvs; const struct reg_init *reg_inits; int reg_init_amnt; + struct run_lvl_ctrl run_lvl[DVS_RUN_LEVELS]; + struct gpio_descs *gps; }; static const struct reg_init buck1_inits[] = { @@ -41,6 +54,14 @@ static const struct reg_init buck1_inits[] = { }, }; +static const struct reg_init buck1_gpio_inits[] = { + { + .reg = BD71828_REG_PS_CTRL_1, + .mask = BD71828_MASK_DVS_BUCK1_CTRL, + .val = BD71828_DVS_BUCK1_USE_RUNLVL, + }, +}; + static const struct reg_init buck2_inits[] = { { .reg = BD71828_REG_PS_CTRL_1, @@ -49,6 +70,14 @@ static const struct reg_init buck2_inits[] = { }, }; +static const struct reg_init buck2_gpio_inits[] = { + { + .reg = BD71828_REG_PS_CTRL_1, + .mask = BD71828_MASK_DVS_BUCK2_CTRL, + .val = BD71828_DVS_BUCK2_USE_RUNLVL, + }, +}; + static const struct reg_init buck6_inits[] = { { .reg = BD71828_REG_PS_CTRL_1, @@ -57,6 +86,14 @@ static const struct reg_init buck6_inits[] = { }, }; +static const struct reg_init buck6_gpio_inits[] = { + { + .reg = BD71828_REG_PS_CTRL_1, + .mask = BD71828_MASK_DVS_BUCK6_CTRL, + .val = BD71828_DVS_BUCK6_USE_RUNLVL, + }, +}; + static const struct reg_init buck7_inits[] = { { .reg = BD71828_REG_PS_CTRL_1, @@ -65,6 +102,14 @@ static const struct reg_init buck7_inits[] = { }, }; +static const struct reg_init buck7_gpio_inits[] = { + { + .reg = BD71828_REG_PS_CTRL_1, + .mask = BD71828_MASK_DVS_BUCK7_CTRL, + .val = BD71828_DVS_BUCK7_USE_RUNLVL, + }, +}; + static const struct regulator_linear_range bd71828_buck1267_volts[] = { REGULATOR_LINEAR_RANGE(500000, 0x00, 0xef, 6250), REGULATOR_LINEAR_RANGE(2000000, 0xf0, 0xff, 0), @@ -155,6 +200,80 @@ static int buck_set_hw_dvs_levels(struct device_node *np, return rohm_regulator_set_dvs_levels(&data->dvs, np, desc, cfg->regmap); } +static int set_runlevel_voltage(struct regmap *regmap, + const struct regulator_desc *desc, + unsigned int uv, unsigned int level) +{ + int i, ret = -EINVAL; + /* + * RUN level registers are next to vsel_reg. RUN0 reg is next, then + * is the RUN 1 reg and so on... + */ + u8 reg = desc->vsel_reg + level + 1; + u8 mask = BD71828_MASK_BUCK1267_VOLT; + + for (i = 0; i < desc->n_voltages; i++) { + ret = regulator_desc_list_voltage_linear_range(desc, i); + if (ret < 0) + continue; + if (ret == uv) { + i <<= ffs(desc->vsel_mask) - 1; + ret = regmap_update_bits(regmap, reg, mask, i); + break; + } + } + return ret; +} + +static int buck_set_gpio_hw_dvs_levels(struct device_node *np, + const struct regulator_desc *desc, + struct regulator_config *cfg) +{ + struct bd71828_regulator_data *data; + uint32_t uv; + int i, ret; + /* On BD71828 the RUN level control reg is next to enable reg */ + u8 en_reg = desc->enable_reg + 1; + const char *props[DVS_RUN_LEVELS] = { "rohm,dvs-runlevel0-voltage", + "rohm,dvs-runlevel1-voltage", + "rohm,dvs-runlevel2-voltage", + "rohm,dvs-runlevel3-voltage" }; + u8 en_masks[DVS_RUN_LEVELS] = { BD71828_MASK_RUN0_EN, + BD71828_MASK_RUN1_EN, + BD71828_MASK_RUN2_EN, + BD71828_MASK_RUN3_EN }; + + data = container_of(desc, struct bd71828_regulator_data, desc); + + for (i = 0; i < DVS_RUN_LEVELS; i++) { + ret = of_property_read_u32(np, props[i], &uv); + if (ret) { + if (ret != -EINVAL) + return ret; + uv = 0; + } + if (uv) { + data->run_lvl[i].voltage = uv; + data->run_lvl[i].enabled = true; + + ret = set_runlevel_voltage(cfg->regmap, desc, uv, i); + + if (ret) + return ret; + + ret = regmap_update_bits(cfg->regmap, en_reg, + en_masks[i], en_masks[i]); + } else { + ret = regmap_update_bits(cfg->regmap, en_reg, + en_masks[i], 0); + } + if (ret) + return ret; + } + + return rohm_regulator_set_dvs_levels(&data->dvs, np, desc, cfg->regmap); +} + static int ldo6_parse_dt(struct device_node *np, const struct regulator_desc *desc, struct regulator_config *cfg) @@ -189,6 +308,85 @@ static int ldo6_parse_dt(struct device_node *np, return 0; } +static int bd71828_dvs_gpio_set_run_level(struct bd71828_regulator_data *rd, + int val) +{ + DECLARE_BITMAP(values, 2); + + if (rd->gps->ndescs != 2) + return -EINVAL; + + if (val < 0 || val > 3) + return -EINVAL; + + values[0] = val; + + return gpiod_set_array_value_cansleep(rd->gps->ndescs, rd->gps->desc, + rd->gps->info, values); +} +static int bd71828_dvs_gpio_get_run_level(struct bd71828_regulator_data *rd) +{ + int run_level; + int ret; + + DECLARE_BITMAP(values, 2); + + values[0] = 0; + + if (rd->gps->ndescs != 2) + return -EINVAL; + + ret = gpiod_get_array_value_cansleep(rd->gps->ndescs, rd->gps->desc, + rd->gps->info, values); + if (ret) + return ret; + + run_level = values[0]; + + return run_level; +} + +static int bd71828_dvs_gpio_is_enabled(struct regulator_dev *rdev) +{ + struct bd71828_regulator_data *data = rdev_get_drvdata(rdev); + int ret; + + // TODO: lock GPIO state (Is this needed) + ret = bd71828_dvs_gpio_get_run_level(data); + if (ret < 0) + goto unlock_out; + + ret = data->run_lvl[ret].enabled; + +unlock_out: + //TODO: unlock + + return ret; +} + +static int bd71828_dvs_gpio_get_voltage(struct regulator_dev *rdev) +{ + int ret; + struct bd71828_regulator_data *data = rdev_get_drvdata(rdev); + + // TODO: lock GPIO state (Is this needed) + ret = bd71828_dvs_gpio_get_run_level(data); + if (ret < 0) + goto unlock_out; + + ret = data->run_lvl[ret].voltage; + +unlock_out: + //TODO: unlock + + return ret; +} + +static const struct regulator_ops dvs_buck_gpio_ops = { + .is_enabled = bd71828_dvs_gpio_is_enabled, + .get_voltage = bd71828_dvs_gpio_get_voltage, +}; + static const struct regulator_ops bd71828_buck_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -773,6 +971,132 @@ static const struct bd71828_regulator_data bd71828_rdata[] = { }, }; +struct bd71828_gpio_cfg { + unsigned int gpiobucks; + struct gpio_descs *gps; +}; + +static int check_dt_for_gpio_controls(struct device *d, + struct bd71828_gpio_cfg *g) +{ + int ret, i; + struct device_node *np = d->of_node; + const char *prop = "rohm,dvs_gpio_bucks"; + uint32_t bucks[MAX_GPIO_DVS_BUCKS]; + + g->gps = devm_gpiod_get_array(d, "rohm,dvs-vsel", GPIOD_OUT_LOW); + + if (IS_ERR(g->gps)) { + ret = PTR_ERR(g->gps); + if (ret == -ENOENT) + return 0; + return ret; + } + + if (g->gps->ndescs != 2) + return -ENOENT; + + ret = of_property_read_variable_u32_array(np, prop, bucks, 0, + ARRAY_SIZE(bucks)); + + if (ret < 0) { + if (ret == -EOVERFLOW) + return -EINVAL; + } + for (i = 0; i < ret; i++) + g->gpiobucks |= 1 << bucks[i]; + + return 0; +} + +static void set_buck_gpio_controlled(struct rohm_regmap_dev *bd71828, + struct bd71828_regulator_data *rd, + struct bd71828_gpio_cfg *g) +{ + switch (rd->desc.id) { + case BD71828_BUCK1: + rd->reg_inits = buck1_gpio_inits; + break; + case BD71828_BUCK2: + rd->reg_inits = buck2_gpio_inits; + break; + case BD71828_BUCK6: + rd->reg_inits = buck6_gpio_inits; + break; + case BD71828_BUCK7: + rd->reg_inits = buck7_gpio_inits; + break; + default: + return; + } + /* + * Disallow setters. Get voltages/enable states based + * on current RUN level + */ + rd->gps = g->gps; + rd->desc.ops = &dvs_buck_gpio_ops; + rd->desc.of_parse_cb = buck_set_gpio_hw_dvs_levels; +} + +static ssize_t show_runlevel(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int runlevel; + struct bd71828_regulator_data *rd = dev_get_drvdata(dev); + + if (!rd || !rd->gps) + return -ENOENT; + + runlevel = bd71828_dvs_gpio_get_run_level(rd); + if (runlevel < 0) + return runlevel; + + return sprintf(buf, "0x%x\n", runlevel); +} + +static ssize_t set_runlevel(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct bd71828_regulator_data *rd = dev_get_drvdata(dev); + long val; + + if (kstrtol(buf, 0, &val) != 0) + return -EINVAL; + + val = bd71828_dvs_gpio_set_run_level(rd, val); + if (val) + return val; + + return count; +} + +static DEVICE_ATTR(runlevel, 0664, show_runlevel, set_runlevel); + +static struct attribute *runlevel_attributes[] = { + &dev_attr_runlevel.attr, + NULL +}; + +static const struct attribute_group bd71828_attr_group = { + .attrs = runlevel_attributes, +}; + +static int bd71828_create_sysfs(struct platform_device *pdev) +{ + return sysfs_create_group(&pdev->dev.kobj, &bd71828_attr_group); +} + +static int bd71828_remove_sysfs(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &bd71828_attr_group); + return 0; +} + +static int bd71828_remove(struct platform_device *pdev) +{ + return bd71828_remove_sysfs(pdev); +} + static int bd71828_probe(struct platform_device *pdev) { struct rohm_regmap_dev *bd71828; @@ -780,6 +1104,8 @@ static int bd71828_probe(struct platform_device *pdev) struct regulator_config config = { .dev = pdev->dev.parent, }; + struct bd71828_gpio_cfg gcfg = {0}; + struct bd71828_regulator_data *rd; bd71828 = dev_get_drvdata(pdev->dev.parent); if (!bd71828) { @@ -787,35 +1113,59 @@ static int bd71828_probe(struct platform_device *pdev) return -EINVAL; } + ret = check_dt_for_gpio_controls(pdev->dev.parent, &gcfg); + if (ret) { + dev_err(&pdev->dev, "Failed to get DVS gpio resources\n"); + return ret; + } + + /* + * Allocate device data to allow controlling more than one PMICs + */ + rd = devm_kmalloc_array(&pdev->dev, ARRAY_SIZE(bd71828_rdata), + sizeof(*rd), GFP_KERNEL); + if (!rd) + return -ENOMEM; + + dev_set_drvdata(&pdev->dev, rd); + + for (i = 0; i < ARRAY_SIZE(bd71828_rdata); i++) { + /* Use bd71828_rdata as template */ + rd[i] = bd71828_rdata[i]; + + if (gcfg.gpiobucks & (1 << i)) + set_buck_gpio_controlled(bd71828, &rd[i], &gcfg); + } + config.regmap = bd71828->regmap; for (i = 0; i < ARRAY_SIZE(bd71828_rdata); i++) { struct regulator_dev *rdev; - const struct bd71828_regulator_data *rd; - rd = &bd71828_rdata[i]; + config.driver_data = &rd[i]; + rdev = devm_regulator_register(&pdev->dev, - &rd->desc, &config); + &rd[i].desc, &config); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register %s regulator\n", - rd->desc.name); + rd[i].desc.name); return PTR_ERR(rdev); } - for (j = 0; j < rd->reg_init_amnt; j++) { + for (j = 0; j < rd[i].reg_init_amnt; j++) { ret = regmap_update_bits(bd71828->regmap, - rd->reg_inits[j].reg, - rd->reg_inits[j].mask, - rd->reg_inits[j].val); + rd[i].reg_inits[j].reg, + rd[i].reg_inits[j].mask, + rd[i].reg_inits[j].val); if (ret) { dev_err(&pdev->dev, "regulator %s init failed\n", - rd->desc.name); + rd[i].desc.name); return ret; } } } - return 0; + return bd71828_create_sysfs(pdev); } static struct platform_driver bd71828_regulator = { @@ -823,6 +1173,7 @@ static struct platform_driver bd71828_regulator = { .name = "bd71828-pmic" }, .probe = bd71828_probe, + .remove = bd71828_remove, }; module_platform_driver(bd71828_regulator); From patchwork Thu Oct 24 11:47:20 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matti Vaittinen X-Patchwork-Id: 1182955 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-rtc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=fi.rohmeurope.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46zQTl4vJmz9sR6 for ; Thu, 24 Oct 2019 22:47:39 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2439274AbfJXLri (ORCPT ); Thu, 24 Oct 2019 07:47:38 -0400 Received: from mail-lf1-f68.google.com ([209.85.167.68]:35271 "EHLO mail-lf1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726389AbfJXLri (ORCPT ); Thu, 24 Oct 2019 07:47:38 -0400 Received: by mail-lf1-f68.google.com with SMTP id y6so12602757lfj.2; Thu, 24 Oct 2019 04:47:35 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=AhOzH/6LDNOCbTfkz4IBFmRVWPyMAIocr0VYbUrCmMk=; b=C7uYKJ/hglOAm+sJ2caLWuX94Dfhtw5Rh6W3Stewb6sMdPrs2uVVMIPucM5k/z2G5I 0Pw7Zyk6aps/L41wXPMg74t6/twkzWFSEOm8XfkKfj8QKyiuz9zgbOqzicnRDDNlOrM9 rSaEt5aoz9VlFbjIw98LJvlhbdqMqd/BqeoPH382cYAv9290AByNjfBuIFEZbp7bbNuk 4E/6mpXoiP8+lAmQB+U4Cjj5kxJbMAQxIW452qdOo39XCJRSqsdyvE4MM1MUeaVIk/jq 71H8mHIs/gBTpqox5zw2Qh1VsV0/kZonUnu3FF1WoRmHSgQuwc8CSb8i4lQ7H+biDZhk lpEg== X-Gm-Message-State: APjAAAVo1oc+g/3cxo4UJnsiSY2IgBF2ITAPQHIDlz1MatP+D5JXv1tE DJowA1nlS2d1aikLKBomZBA= X-Google-Smtp-Source: APXvYqy6qQzYpA4U+oETrpOueNZ7x+NvuXjgV27VK/Afs4YRbz/LmtI2dJKH2caZ/+6uX56GNjafRw== X-Received: by 2002:a19:855:: with SMTP id 82mr25707266lfi.44.1571917653910; Thu, 24 Oct 2019 04:47:33 -0700 (PDT) Received: from localhost.localdomain ([213.255.186.46]) by smtp.gmail.com with ESMTPSA id u26sm11753113lfd.19.2019.10.24.04.47.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 24 Oct 2019 04:47:33 -0700 (PDT) Date: Thu, 24 Oct 2019 14:47:20 +0300 From: Matti Vaittinen To: matti.vaittinen@fi.rohmeurope.com, mazziesaccount@gmail.com Cc: Lee Jones , Rob Herring , Mark Rutland , Liam Girdwood , Mark Brown , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Jacek Anaszewski , Pavel Machek , Dan Murphy , Alessandro Zummo , Alexandre Belloni , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-leds@vger.kernel.org, linux-rtc@vger.kernel.org Subject: [RFC PATCH v2 09/13] regulator: bd71828: enhanced run-level support Message-ID: References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.12.1 (2019-06-15) Sender: linux-rtc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rtc@vger.kernel.org Support changing run-level via I2C and add in-kernel API for allowing run time changes of run-level voltages. Signed-off-by: Matti Vaittinen --- No changes since v1 drivers/regulator/bd71828-regulator.c | 266 ++++++++++++++++++++++---- include/linux/mfd/rohm-bd71828.h | 3 + 2 files changed, 232 insertions(+), 37 deletions(-) diff --git a/drivers/regulator/bd71828-regulator.c b/drivers/regulator/bd71828-regulator.c index e82e94ecf747..d9e1381b5964 100644 --- a/drivers/regulator/bd71828-regulator.c +++ b/drivers/regulator/bd71828-regulator.c @@ -19,6 +19,12 @@ #include #include +/* Drivers should not do this. But we provide this custom kernel interface + * for users to switch the run-level. Hence we need to get the rdev from + * struct regulator + */ +#include "internal.h" + #define MAX_GPIO_DVS_BUCKS 4 #define DVS_RUN_LEVELS 4 @@ -39,7 +45,10 @@ struct bd71828_regulator_data { const struct reg_init *reg_inits; int reg_init_amnt; struct run_lvl_ctrl run_lvl[DVS_RUN_LEVELS]; + struct mutex dvs_lock; struct gpio_descs *gps; + struct regmap *regmap; + bool allow_runlvl; }; static const struct reg_init buck1_inits[] = { @@ -225,7 +234,7 @@ static int set_runlevel_voltage(struct regmap *regmap, return ret; } -static int buck_set_gpio_hw_dvs_levels(struct device_node *np, +static int buck_set_runlvl_hw_dvs_levels(struct device_node *np, const struct regulator_desc *desc, struct regulator_config *cfg) { @@ -245,11 +254,12 @@ static int buck_set_gpio_hw_dvs_levels(struct device_node *np, data = container_of(desc, struct bd71828_regulator_data, desc); + mutex_lock(&data->dvs_lock); for (i = 0; i < DVS_RUN_LEVELS; i++) { ret = of_property_read_u32(np, props[i], &uv); if (ret) { if (ret != -EINVAL) - return ret; + goto unlock_out; uv = 0; } if (uv) { @@ -259,7 +269,7 @@ static int buck_set_gpio_hw_dvs_levels(struct device_node *np, ret = set_runlevel_voltage(cfg->regmap, desc, uv, i); if (ret) - return ret; + goto unlock_out; ret = regmap_update_bits(cfg->regmap, en_reg, en_masks[i], en_masks[i]); @@ -268,10 +278,15 @@ static int buck_set_gpio_hw_dvs_levels(struct device_node *np, en_masks[i], 0); } if (ret) - return ret; + goto unlock_out; } - return rohm_regulator_set_dvs_levels(&data->dvs, np, desc, cfg->regmap); + ret = rohm_regulator_set_dvs_levels(&data->dvs, np, desc, cfg->regmap); + +unlock_out: + mutex_unlock(&data->dvs_lock); + + return ret; } static int ldo6_parse_dt(struct device_node *np, @@ -324,11 +339,40 @@ static int bd71828_dvs_gpio_set_run_level(struct bd71828_regulator_data *rd, return gpiod_set_array_value_cansleep(rd->gps->ndescs, rd->gps->desc, rd->gps->info, values); } + +/* Get current run level when RUN levels are controlled using I2C */ +static int bd71828_dvs_i2c_set_run_level(struct regmap *regmap, + int lvl) +{ + unsigned int reg; + + reg = lvl << (ffs(BD71828_MASK_RUN_LVL_CTRL) - 1); + + return regmap_update_bits(regmap, BD71828_REG_PS_CTRL_3, + BD71828_MASK_RUN_LVL_CTRL, reg); +} +/* Get current run level when RUN levels are controlled using I2C */ +static int bd71828_dvs_i2c_get_run_level(struct regmap *regmap, + struct bd71828_regulator_data *rd) +{ + int ret; + unsigned int val; + + ret = regmap_read(regmap, BD71828_REG_PS_CTRL_3, &val); + if (ret) + return ret; + + ret = (val & BD71828_MASK_RUN_LVL_CTRL); + ret >>= ffs(BD71828_MASK_RUN_LVL_CTRL) - 1; + + return ret; +} + +/* Get current RUN level when run levels are controlled by GPIO */ static int bd71828_dvs_gpio_get_run_level(struct bd71828_regulator_data *rd) { int run_level; int ret; - DECLARE_BITMAP(values, 2); values[0] = 0; @@ -346,47 +390,131 @@ static int bd71828_dvs_gpio_get_run_level(struct bd71828_regulator_data *rd) return run_level; } +/* + * To be used when BD71828 regulator is controlled by RUN levels + * via I2C instead of GPIO + */ +static int bd71828_dvs_i2c_is_enabled(struct regulator_dev *rdev) +{ + struct bd71828_regulator_data *data = rdev_get_drvdata(rdev); + int ret; + + mutex_lock(&data->dvs_lock); + ret = bd71828_dvs_i2c_get_run_level(rdev->regmap, data); + if (ret < 0) + goto unlock_out; + + ret = data->run_lvl[ret].enabled; + +unlock_out: + mutex_unlock(&data->dvs_lock); + + return ret; +} + +/* + * To be used when BD71828 regulator is controlled by RUN levels + * via GPIO + */ static int bd71828_dvs_gpio_is_enabled(struct regulator_dev *rdev) { struct bd71828_regulator_data *data = rdev_get_drvdata(rdev); int ret; - // TODO: lock GPIO state (Is this needed) + mutex_lock(&data->dvs_lock); ret = bd71828_dvs_gpio_get_run_level(data); - if (ret < 0) + if (ret < 0 || ret >= DVS_RUN_LEVELS) goto unlock_out; ret = data->run_lvl[ret].enabled; unlock_out: - //TODO: unlock + mutex_unlock(&data->dvs_lock); return ret; } +/* + * To be used when BD71828 regulator is controlled by RUN levels + * via I2C instead of GPIO + */ +static int bd71828_dvs_i2c_get_voltage(struct regulator_dev *rdev) +{ + int ret; + struct bd71828_regulator_data *data = rdev_get_drvdata(rdev); + + mutex_lock(&data->dvs_lock); + ret = bd71828_dvs_i2c_get_run_level(rdev->regmap, data); + if (ret < 0) + goto unlock_out; + + ret = data->run_lvl[ret].voltage; + +unlock_out: + mutex_unlock(&data->dvs_lock); + + return ret; +} + +/* + * To be used when BD71828 regulator is controlled by RUN levels + * via GPIO + */ static int bd71828_dvs_gpio_get_voltage(struct regulator_dev *rdev) { int ret; struct bd71828_regulator_data *data = rdev_get_drvdata(rdev); - // TODO: lock GPIO state (Is this needed) + mutex_lock(&data->dvs_lock); ret = bd71828_dvs_gpio_get_run_level(data); - if (ret < 0) + if (ret < 0 || DVS_RUN_LEVELS <= ret) goto unlock_out; ret = data->run_lvl[ret].voltage; unlock_out: - //TODO: unlock + mutex_unlock(&data->dvs_lock); + + return ret; +} + +/** + * bd71828_set_runlevel_voltage - change run-level voltage + * + * @regulator: pointer to regulator for which the run-level voltage is changed + * @uv: New voltage for run-level in micro volts + * @level: run-level for which the voltage is to be changed + * + * Changes the run-level voltage for given regulator + */ +int bd71828_set_runlevel_voltage(struct regulator *regulator, unsigned int uv, + unsigned int level) +{ + struct regulator_dev *rdev = regulator->rdev; + struct bd71828_regulator_data *data = rdev_get_drvdata(rdev); + int ret; + + if (!data || !data->allow_runlvl) + return -EINVAL; + + mutex_lock(&data->dvs_lock); + ret = set_runlevel_voltage(rdev->regmap, rdev->desc, uv, level); + mutex_unlock(&data->dvs_lock); return ret; } +EXPORT_SYMBOL(bd71828_set_runlevel_voltage); static const struct regulator_ops dvs_buck_gpio_ops = { .is_enabled = bd71828_dvs_gpio_is_enabled, .get_voltage = bd71828_dvs_gpio_get_voltage, }; +static const struct regulator_ops dvs_buck_i2c_ops = { + .is_enabled = bd71828_dvs_i2c_is_enabled, + .get_voltage = bd71828_dvs_i2c_get_voltage, +}; + static const struct regulator_ops bd71828_buck_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -972,17 +1100,72 @@ static const struct bd71828_regulator_data bd71828_rdata[] = { }; struct bd71828_gpio_cfg { - unsigned int gpiobucks; + bool use_gpio; + unsigned int runlvl; struct gpio_descs *gps; }; +static void mark_regulator_runlvl_controlled(struct device *dev, + struct device_node *np, + struct bd71828_gpio_cfg *g) +{ + int i; + + for (i = 1; i <= ARRAY_SIZE(bd71828_rdata); i++) { + if (!of_node_name_eq(np, bd71828_rdata[i-1].desc.of_match)) + continue; + switch (i) { + case 1: + case 2: + case 6: + case 7: + g->runlvl |= 1 << (i - 1); + dev_dbg(dev, "buck %d runlevel controlled\n", i); + break; + default: + dev_err(dev, + "Only bucks 1,2,6,7 support run-level dvs\n"); + break; + } + } +} + +static int get_runcontrolled_bucks_dt(struct device *dev, + struct bd71828_gpio_cfg *g) +{ + struct device_node *np; + struct device_node *nproot = dev->of_node; + const char *prop = "rohm,dvs-runlvl-ctrl"; + + g->runlvl = 0; + + nproot = of_get_child_by_name(nproot, "regulators"); + if (!nproot) { + dev_err(dev, "failed to find regulators node\n"); + return -ENODEV; + } + for_each_child_of_node(nproot, np) + if (of_property_read_bool(np, prop)) + mark_regulator_runlvl_controlled(dev, np, g); + + of_node_put(nproot); + return 0; +} + static int check_dt_for_gpio_controls(struct device *d, struct bd71828_gpio_cfg *g) { - int ret, i; - struct device_node *np = d->of_node; - const char *prop = "rohm,dvs_gpio_bucks"; - uint32_t bucks[MAX_GPIO_DVS_BUCKS]; + int ret; + + ret = get_runcontrolled_bucks_dt(d, g); + if (ret) + return ret; + + g->use_gpio = false; + + /* If the run level control is not requested by any bucks we're done */ + if (!g->runlvl) + return 0; g->gps = devm_gpiod_get_array(d, "rohm,dvs-vsel", GPIOD_OUT_LOW); @@ -996,22 +1179,14 @@ static int check_dt_for_gpio_controls(struct device *d, if (g->gps->ndescs != 2) return -ENOENT; - ret = of_property_read_variable_u32_array(np, prop, bucks, 0, - ARRAY_SIZE(bucks)); - - if (ret < 0) { - if (ret == -EOVERFLOW) - return -EINVAL; - } - for (i = 0; i < ret; i++) - g->gpiobucks |= 1 << bucks[i]; + g->use_gpio = true; return 0; } -static void set_buck_gpio_controlled(struct rohm_regmap_dev *bd71828, - struct bd71828_regulator_data *rd, - struct bd71828_gpio_cfg *g) +static void set_buck_runlvl_controlled(struct rohm_regmap_dev *bd71828, + struct bd71828_regulator_data *rd, + struct bd71828_gpio_cfg *g) { switch (rd->desc.id) { case BD71828_BUCK1: @@ -1033,9 +1208,16 @@ static void set_buck_gpio_controlled(struct rohm_regmap_dev *bd71828, * Disallow setters. Get voltages/enable states based * on current RUN level */ - rd->gps = g->gps; - rd->desc.ops = &dvs_buck_gpio_ops; - rd->desc.of_parse_cb = buck_set_gpio_hw_dvs_levels; + + rd->allow_runlvl = true; + + if (g->use_gpio) { + rd->gps = g->gps; + rd->desc.ops = &dvs_buck_gpio_ops; + } else { + rd->desc.ops = &dvs_buck_i2c_ops; + } + rd->desc.of_parse_cb = buck_set_runlvl_hw_dvs_levels; } static ssize_t show_runlevel(struct device *dev, @@ -1044,10 +1226,14 @@ static ssize_t show_runlevel(struct device *dev, int runlevel; struct bd71828_regulator_data *rd = dev_get_drvdata(dev); - if (!rd || !rd->gps) + if (!rd) return -ENOENT; - runlevel = bd71828_dvs_gpio_get_run_level(rd); + if (!rd->gps) + runlevel = bd71828_dvs_i2c_get_run_level(rd->regmap, rd); + else + runlevel = bd71828_dvs_gpio_get_run_level(rd); + if (runlevel < 0) return runlevel; @@ -1063,7 +1249,10 @@ static ssize_t set_runlevel(struct device *dev, struct device_attribute *attr, if (kstrtol(buf, 0, &val) != 0) return -EINVAL; - val = bd71828_dvs_gpio_set_run_level(rd, val); + if (rd->gps) + val = bd71828_dvs_gpio_set_run_level(rd, val); + else + val = bd71828_dvs_i2c_set_run_level(rd->regmap, val); if (val) return val; @@ -1133,8 +1322,11 @@ static int bd71828_probe(struct platform_device *pdev) /* Use bd71828_rdata as template */ rd[i] = bd71828_rdata[i]; - if (gcfg.gpiobucks & (1 << i)) - set_buck_gpio_controlled(bd71828, &rd[i], &gcfg); + mutex_init(&rd[i].dvs_lock); + if (gcfg.runlvl & (1 << i)) + set_buck_runlvl_controlled(bd71828, &rd[i], &gcfg); + + rd[i].regmap = bd71828->regmap; } config.regmap = bd71828->regmap; diff --git a/include/linux/mfd/rohm-bd71828.h b/include/linux/mfd/rohm-bd71828.h index eb0557eb5314..5f15c6a309e6 100644 --- a/include/linux/mfd/rohm-bd71828.h +++ b/include/linux/mfd/rohm-bd71828.h @@ -422,4 +422,7 @@ enum { #define BD71828_OUT_TYPE_OPEN_DRAIN 0x0 #define BD71828_OUT_TYPE_CMOS 0x2 +int bd71828_set_runlevel_voltage(struct regulator *regulator, unsigned int uv, + unsigned int level); + #endif /* __LINUX_MFD_BD71828_H__ */ From patchwork Thu Oct 24 11:47:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matti Vaittinen X-Patchwork-Id: 1182957 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-rtc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=fi.rohmeurope.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46zQVS36wbz9sQv for ; Thu, 24 Oct 2019 22:48:16 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2439300AbfJXLsM (ORCPT ); Thu, 24 Oct 2019 07:48:12 -0400 Received: from mail-lj1-f193.google.com ([209.85.208.193]:32995 "EHLO mail-lj1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726389AbfJXLsM (ORCPT ); Thu, 24 Oct 2019 07:48:12 -0400 Received: by mail-lj1-f193.google.com with SMTP id a22so24685499ljd.0; Thu, 24 Oct 2019 04:48:10 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=8J2+2b/3DwPctSPRqZRS55vvq4sBN5gRrY6PrhiAAS4=; b=A6HAHYErCxIRaB9k1eW/L459j1+pyTOYnEUhX2mM28PJeGwNokJQovaqjALJlQCyn5 wbAhKey2PN/nJSHCeU2tMp3/xBGq+9k1zkr2f6mJ9XLJ8TN+Rup4RwcOaitUotKFjD9b m/3F13P8Yg7gVBrKHBZCxR6zYHSlKLyf9A35+Av2HIYFk3vaGwzZXBxN/RP30ZspAJ36 XJOp1N9yNltNGfY+xvkuTvp2B/u0LYKtZlRiCrr72hF9b0YLn2LP4SEw8WYXCCdijnr8 fvhX8pKzObFnP9543XkNi6lZDE27s7OCD7wjbJrVz0dsKGTEGKtzn+q/JEmq1S3Iucz/ KlaQ== X-Gm-Message-State: APjAAAWs1O/dh28OjIcY6dtCfZNQGqCmgOrmF15sKaTkSQer0wVijytw 6F9IiLc67YSbyvmCur/tYqs= X-Google-Smtp-Source: APXvYqxN8dcNomoDwNF2GbvvQMePhthWb0lfDLo9guH463q8RkhSVhWtxrzpFc5Fvl8TqSnHgcaACw== X-Received: by 2002:a2e:9890:: with SMTP id b16mr26169264ljj.4.1571917689423; Thu, 24 Oct 2019 04:48:09 -0700 (PDT) Received: from localhost.localdomain ([213.255.186.46]) by smtp.gmail.com with ESMTPSA id j7sm11764858lfc.16.2019.10.24.04.48.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 24 Oct 2019 04:48:08 -0700 (PDT) Date: Thu, 24 Oct 2019 14:47:56 +0300 From: Matti Vaittinen To: matti.vaittinen@fi.rohmeurope.com, mazziesaccount@gmail.com Cc: Lee Jones , Rob Herring , Mark Rutland , Liam Girdwood , Mark Brown , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Jacek Anaszewski , Pavel Machek , Dan Murphy , Alessandro Zummo , Alexandre Belloni , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-leds@vger.kernel.org, linux-rtc@vger.kernel.org Subject: [RFC PATCH v2 10/13] regulator: bd71828: Support in-kernel APIs to change run-level Message-ID: <8e97e506bab0358dbbff2786796f4123db7e3961.1571915550.git.matti.vaittinen@fi.rohmeurope.com> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.12.1 (2019-06-15) Sender: linux-rtc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rtc@vger.kernel.org Add exported functions bd71828_set_runlevel and bd71828_get_runlevel for setting and getting the system run level. Signed-off-by: Matti Vaittinen --- No changes since v1 drivers/regulator/bd71828-regulator.c | 67 +++++++++++++++++++++++++++ include/linux/mfd/rohm-bd71828.h | 2 + 2 files changed, 69 insertions(+) diff --git a/drivers/regulator/bd71828-regulator.c b/drivers/regulator/bd71828-regulator.c index d9e1381b5964..eaff9b1b20f9 100644 --- a/drivers/regulator/bd71828-regulator.c +++ b/drivers/regulator/bd71828-regulator.c @@ -505,6 +505,73 @@ int bd71828_set_runlevel_voltage(struct regulator *regulator, unsigned int uv, } EXPORT_SYMBOL(bd71828_set_runlevel_voltage); +/** + * bd71828_set_runlevel - change system run-level. + * + * @regulator: pointer to one of the BD71828 regulators obtained by + * call to regulator_get + * @level: New run-level the system should enter + * + * Changes the system to run-level which was given as argument. This + * operation will change state of all regulators which are set to be + * controlled by run-levels. Note that 'regulator' must point to a + * regulator which is controlled by run-levels. + */ +int bd71828_set_runlevel(struct regulator *regulator, unsigned int level) +{ + struct regulator_dev *rdev = regulator->rdev; + struct bd71828_regulator_data *rd = rdev_get_drvdata(rdev); + + if (!rd) + return -ENOENT; + + if (!rd || !rd->allow_runlvl) + return -EINVAL; + + if (rd->gps) + return bd71828_dvs_gpio_set_run_level(rd, level); + + return bd71828_dvs_i2c_set_run_level(rd->regmap, level); +} +EXPORT_SYMBOL(bd71828_set_runlevel); + +/** + * bd71828_get_runlevel - get the current system run-level. + * + * @regulator: pointer to one of the BD71828 regulators obtained by + * call to regulator_get + * @level: Pointer to value where current run-level is stored + * + * Returns the current system run-level. Note that 'regulator' must + * point to a regulator which is controlled by run-levels. + */ +int bd71828_get_runlevel(struct regulator *regulator, unsigned int *level) +{ + struct regulator_dev *rdev = regulator->rdev; + struct bd71828_regulator_data *rd = rdev_get_drvdata(rdev); + int ret; + + if (!rd) + return -ENOENT; + + if (!rd || !rd->allow_runlvl) + return -EINVAL; + + if (!rd->gps) + ret = bd71828_dvs_i2c_get_run_level(rd->regmap, rd); + else + ret = bd71828_dvs_gpio_get_run_level(rd); + + if (ret < 0) + return ret; + + *level = (unsigned int) ret; + + return 0; +} +EXPORT_SYMBOL(bd71828_get_runlevel); + + static const struct regulator_ops dvs_buck_gpio_ops = { .is_enabled = bd71828_dvs_gpio_is_enabled, .get_voltage = bd71828_dvs_gpio_get_voltage, diff --git a/include/linux/mfd/rohm-bd71828.h b/include/linux/mfd/rohm-bd71828.h index 5f15c6a309e6..bbbd4f118550 100644 --- a/include/linux/mfd/rohm-bd71828.h +++ b/include/linux/mfd/rohm-bd71828.h @@ -424,5 +424,7 @@ enum { int bd71828_set_runlevel_voltage(struct regulator *regulator, unsigned int uv, unsigned int level); +int bd71828_set_runlevel(struct regulator *regulator, unsigned int level); +int bd71828_get_runlevel(struct regulator *regulator, unsigned int *level); #endif /* __LINUX_MFD_BD71828_H__ */ From patchwork Thu Oct 24 11:50:00 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matti Vaittinen X-Patchwork-Id: 1182960 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-rtc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=fi.rohmeurope.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46zQXv0DHcz9sPp for ; Thu, 24 Oct 2019 22:50:23 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2439388AbfJXLuU (ORCPT ); Thu, 24 Oct 2019 07:50:20 -0400 Received: from mail-lf1-f65.google.com ([209.85.167.65]:46316 "EHLO mail-lf1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729203AbfJXLuT (ORCPT ); Thu, 24 Oct 2019 07:50:19 -0400 Received: by mail-lf1-f65.google.com with SMTP id t8so18874679lfc.13; Thu, 24 Oct 2019 04:50:15 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=mrlEms7UqZ4vGaozHLMz/3+R7IWy4VYR7Hdk5gom7nY=; b=fKcH99wMIrqrKB5Hy0RSxpAyq2MvFK8ryp/o5jmM9YXlXcxIGKfy2/sTyPS5LXp8EV vGK62faqP/dtRourQTyL4hooHTnSjrecN+4Z35eFAIIp7IFaIPAoVHcnOxlPXRH0qcdc IioNlwlh8th7mcvr0rQpjeRCg2+UCgP+xUo1/RGM6ILOjA0AZnNZtgsaK0vipqSZL28s x9N6m6zqJNdbasCSJ+DlcYCPlUmN7hlC/JmJVZj5jy4dIMsNnWy7ZvW2iBhrJOj2KLHc 5NeLtBU6USld8Lojev2bI/oHbfLF48bE4oAKBFiLv87nvgFklgvpaSkvZL5mF65LoqA/ ixLQ== X-Gm-Message-State: APjAAAVzGwldyjQf7nIZF3gi6qOLt6FQMgJygDPRObfu3gKF3gbtXjY4 dFiEHHnvdP62UJs5vBq2HbE= X-Google-Smtp-Source: APXvYqzQ8pNVyiXPYUTB870sqwDsom+UvS68qg6x5bg0H2OMKFbxqbSCSf1bD+xlw6sMxl7tPNjWdA== X-Received: by 2002:a19:6d12:: with SMTP id i18mr13795955lfc.153.1571917814820; Thu, 24 Oct 2019 04:50:14 -0700 (PDT) Received: from localhost.localdomain ([213.255.186.46]) by smtp.gmail.com with ESMTPSA id y13sm11671810ljd.51.2019.10.24.04.50.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 24 Oct 2019 04:50:14 -0700 (PDT) Date: Thu, 24 Oct 2019 14:50:00 +0300 From: Matti Vaittinen To: matti.vaittinen@fi.rohmeurope.com, mazziesaccount@gmail.com Cc: Lee Jones , Rob Herring , Mark Rutland , Liam Girdwood , Mark Brown , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Jacek Anaszewski , Pavel Machek , Dan Murphy , Alessandro Zummo , Alexandre Belloni , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-leds@vger.kernel.org, linux-rtc@vger.kernel.org Subject: [RFC PATCH v2 11/13] rtc: bd70528 add BD71828 support Message-ID: References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.12.1 (2019-06-15) Sender: linux-rtc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rtc@vger.kernel.org ROHM BD71828 PMIC RTC block is from many parts similar to one on BD70528. Support BD71828 RTC using BD70528 RTC driver and avoid re-inventing the wheel. Signed-off-by: Matti Vaittinen --- Mostly reverted naming changes since v1. Also added own rtc_ops for both PMICs. drivers/rtc/Kconfig | 5 +- drivers/rtc/rtc-bd70528.c | 145 ++++++++++++++++++++++++++++--- include/linux/mfd/rohm-bd70528.h | 13 +-- include/linux/mfd/rohm-bd71828.h | 4 +- include/linux/mfd/rohm-shared.h | 27 ++++++ 5 files changed, 167 insertions(+), 27 deletions(-) create mode 100644 include/linux/mfd/rohm-shared.h diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index e72f65b61176..5c5b18a99bf9 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -498,11 +498,12 @@ config RTC_DRV_M41T80_WDT help If you say Y here you will get support for the watchdog timer in the ST M41T60 and M41T80 RTC chips series. + config RTC_DRV_BD70528 - tristate "ROHM BD70528 PMIC RTC" + tristate "ROHM BD70528 and BD71828 PMIC RTC" help If you say Y here you will get support for the RTC - on ROHM BD70528 Power Management IC. + block on ROHM BD70528 and BD71828 Power Management IC. This driver can also be built as a module. If so, the module will be called rtc-bd70528. diff --git a/drivers/rtc/rtc-bd70528.c b/drivers/rtc/rtc-bd70528.c index f9bdd555e1a2..0975728d3cbe 100644 --- a/drivers/rtc/rtc-bd70528.c +++ b/drivers/rtc/rtc-bd70528.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -15,7 +16,7 @@ /* * We read regs RTC_SEC => RTC_YEAR * this struct is ordered according to chip registers. - * Keep it u8 only to avoid padding issues. + * Keep it u8 only (or packed) to avoid padding issues. */ struct bd70528_rtc_day { u8 sec; @@ -36,6 +37,13 @@ struct bd70528_rtc_wake { u8 ctrl; } __packed; +struct bd71828_rtc_alm { + struct bd70528_rtc_data alm0; + struct bd70528_rtc_data alm1; + u8 alm_mask; + u8 alm1_mask; +} __packed; + struct bd70528_rtc_alm { struct bd70528_rtc_data data; u8 alm_mask; @@ -45,6 +53,8 @@ struct bd70528_rtc_alm { struct bd70528_rtc { struct rohm_regmap_dev *mfd; struct device *dev; + u8 reg_time_start; + bool has_rtc_timers; }; static int bd70528_set_wake(struct rohm_regmap_dev *bd70528, @@ -152,12 +162,18 @@ static int bd70528_set_rtc_based_timers(struct bd70528_rtc *r, int new_state, static int bd70528_re_enable_rtc_based_timers(struct bd70528_rtc *r, int old_state) { + if (!r->has_rtc_timers) + return 0; + return bd70528_set_rtc_based_timers(r, old_state, NULL); } static int bd70528_disable_rtc_based_timers(struct bd70528_rtc *r, int *old_state) { + if (!r->has_rtc_timers) + return 0; + return bd70528_set_rtc_based_timers(r, 0, old_state); } @@ -213,6 +229,36 @@ static inline void rtc2tm(struct bd70528_rtc_data *r, struct rtc_time *t) t->tm_wday = bcd2bin(r->week & BD70528_MASK_RTC_WEEK); } +static int bd71828_set_alarm(struct device *dev, struct rtc_wkalrm *a) +{ + int ret; + struct bd71828_rtc_alm alm; + struct bd70528_rtc *r = dev_get_drvdata(dev); + struct rohm_regmap_dev *bd71828 = r->mfd; + + ret = regmap_bulk_read(bd71828->regmap, BD71828_REG_RTC_ALM_START, + &alm, sizeof(alm)); + if (ret) { + dev_err(dev, "Failed to read alarm regs\n"); + return ret; + } + + tm2rtc(&a->time, &alm.alm0); + + if (!a->enabled) + alm.alm_mask &= ~BD70528_MASK_ALM_EN; + else + alm.alm_mask |= BD70528_MASK_ALM_EN; + + ret = regmap_bulk_write(bd71828->regmap, BD71828_REG_RTC_ALM_START, + &alm, sizeof(alm)); + if (ret) + dev_err(dev, "Failed to set alarm time\n"); + + return ret; + +} + static int bd70528_set_alarm(struct device *dev, struct rtc_wkalrm *a) { struct bd70528_rtc_wake wake; @@ -261,6 +307,30 @@ static int bd70528_set_alarm(struct device *dev, struct rtc_wkalrm *a) return ret; } +static int bd71828_read_alarm(struct device *dev, struct rtc_wkalrm *a) +{ + int ret; + struct bd71828_rtc_alm alm; + struct bd70528_rtc *r = dev_get_drvdata(dev); + struct rohm_regmap_dev *bd71828 = r->mfd; + + ret = regmap_bulk_read(bd71828->regmap, BD71828_REG_RTC_ALM_START, + &alm, sizeof(alm)); + if (ret) { + dev_err(dev, "Failed to read alarm regs\n"); + return ret; + } + + rtc2tm(&alm.alm0, &a->time); + a->time.tm_mday = -1; + a->time.tm_mon = -1; + a->time.tm_year = -1; + a->enabled = !!(alm.alm_mask & BD70528_MASK_ALM_EN); + a->pending = 0; + + return 0; +} + static int bd70528_read_alarm(struct device *dev, struct rtc_wkalrm *a) { struct bd70528_rtc_alm alm; @@ -297,7 +367,7 @@ static int bd70528_set_time_locked(struct device *dev, struct rtc_time *t) return ret; tmpret = regmap_bulk_read(bd70528->regmap, - BD70528_REG_RTC_START, &rtc_data, + r->reg_time_start, &rtc_data, sizeof(rtc_data)); if (tmpret) { dev_err(dev, "Failed to read RTC time registers\n"); @@ -306,7 +376,7 @@ static int bd70528_set_time_locked(struct device *dev, struct rtc_time *t) tm2rtc(t, &rtc_data); tmpret = regmap_bulk_write(bd70528->regmap, - BD70528_REG_RTC_START, &rtc_data, + r->reg_time_start, &rtc_data, sizeof(rtc_data)); if (tmpret) { dev_err(dev, "Failed to set RTC time\n"); @@ -341,7 +411,7 @@ static int bd70528_get_time(struct device *dev, struct rtc_time *t) /* read the RTC date and time registers all at once */ ret = regmap_bulk_read(bd70528->regmap, - BD70528_REG_RTC_START, &rtc_data, + r->reg_time_start, &rtc_data, sizeof(rtc_data)); if (ret) { dev_err(dev, "Failed to read RTC time (err %d)\n", ret); @@ -378,6 +448,23 @@ static int bd70528_alm_enable(struct device *dev, unsigned int enabled) return ret; } +static int bd71828_alm_enable(struct device *dev, unsigned int enabled) +{ + int ret; + struct bd70528_rtc *r = dev_get_drvdata(dev); + unsigned int enableval = BD70528_MASK_ALM_EN; + + if (!enabled) + enableval = 0; + + ret = regmap_update_bits(r->mfd->regmap, BD71828_REG_RTC_ALM0_MASK, + BD70528_MASK_ALM_EN, enableval); + if (ret) + dev_err(dev, "Failed to change alarm state\n"); + + return ret; +} + static const struct rtc_class_ops bd70528_rtc_ops = { .read_time = bd70528_get_time, .set_time = bd70528_set_time, @@ -386,6 +473,14 @@ static const struct rtc_class_ops bd70528_rtc_ops = { .alarm_irq_enable = bd70528_alm_enable, }; +static const struct rtc_class_ops bd71828_rtc_ops = { + .read_time = bd70528_get_time, + .set_time = bd70528_set_time, + .read_alarm = bd71828_read_alarm, + .set_alarm = bd71828_set_alarm, + .alarm_irq_enable = bd71828_alm_enable, +}; + static irqreturn_t alm_hndlr(int irq, void *data) { struct rtc_device *rtc = data; @@ -397,11 +492,15 @@ static irqreturn_t alm_hndlr(int irq, void *data) static int bd70528_probe(struct platform_device *pdev) { struct bd70528_rtc *bd_rtc; + const struct rtc_class_ops *rtc_ops; struct rohm_regmap_dev *mfd; + const char *irq_name; int ret; struct rtc_device *rtc; int irq; unsigned int hr; + bool enable_main_irq = false; + u8 hour_reg; mfd = dev_get_drvdata(pdev->dev.parent); if (!mfd) { @@ -415,7 +514,27 @@ static int bd70528_probe(struct platform_device *pdev) bd_rtc->mfd = mfd; bd_rtc->dev = &pdev->dev; - irq = platform_get_irq_byname(pdev, "bd70528-rtc-alm"); + switch (mfd->chip_type) { + case ROHM_CHIP_TYPE_BD70528: + irq_name = "bd70528-rtc-alm"; + bd_rtc->has_rtc_timers = true; + bd_rtc->reg_time_start = BD70528_REG_RTC_START; + hour_reg = BD70528_REG_RTC_HOUR; + enable_main_irq = true; + rtc_ops = &bd70528_rtc_ops; + break; + case ROHM_CHIP_TYPE_BD71828: + irq_name = "bd71828-rtc-alm-0"; + bd_rtc->reg_time_start = BD71828_REG_RTC_START; + hour_reg = BD71828_REG_RTC_HOUR; + rtc_ops = &bd71828_rtc_ops; + break; + default: + dev_err(&pdev->dev, "Unknown chip\n"); + return -ENOENT; + } + + irq = platform_get_irq_byname(pdev, irq_name); if (irq < 0) { dev_err(&pdev->dev, "Failed to get irq\n"); @@ -424,7 +543,7 @@ static int bd70528_probe(struct platform_device *pdev) platform_set_drvdata(pdev, bd_rtc); - ret = regmap_read(mfd->regmap, BD70528_REG_RTC_HOUR, &hr); + ret = regmap_read(mfd->regmap, hour_reg, &hr); if (ret) { dev_err(&pdev->dev, "Failed to reag RTC clock\n"); @@ -457,7 +576,7 @@ static int bd70528_probe(struct platform_device *pdev) rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; rtc->range_max = RTC_TIMESTAMP_END_2099; - rtc->ops = &bd70528_rtc_ops; + rtc->ops = rtc_ops; /* Request alarm IRQ prior to registerig the RTC */ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, &alm_hndlr, @@ -471,12 +590,14 @@ static int bd70528_probe(struct platform_device *pdev) * leave them enabled as irq-controller should disable irqs * from sub-registers when IRQ is disabled or freed. */ - ret = regmap_update_bits(mfd->regmap, + if (enable_main_irq) { + ret = regmap_update_bits(mfd->regmap, BD70528_REG_INT_MAIN_MASK, BD70528_INT_RTC_MASK, 0); - if (ret) { - dev_err(&pdev->dev, "Failed to enable RTC interrupts\n"); - return ret; + if (ret) { + dev_err(&pdev->dev, "Failed to enable RTC interrupts\n"); + return ret; + } } ret = rtc_register_device(rtc); @@ -496,5 +617,5 @@ static struct platform_driver bd70528_rtc = { module_platform_driver(bd70528_rtc); MODULE_AUTHOR("Matti Vaittinen "); -MODULE_DESCRIPTION("BD70528 RTC driver"); +MODULE_DESCRIPTION("ROHM BD70528 and BD71828 PMIC RTC driver"); MODULE_LICENSE("GPL"); diff --git a/include/linux/mfd/rohm-bd70528.h b/include/linux/mfd/rohm-bd70528.h index 1013e60c5b25..e2859840b09d 100644 --- a/include/linux/mfd/rohm-bd70528.h +++ b/include/linux/mfd/rohm-bd70528.h @@ -7,6 +7,7 @@ #include #include #include +#include #include enum { @@ -313,17 +314,6 @@ enum { /* RTC masks to mask out reserved bits */ -#define BD70528_MASK_RTC_SEC 0x7f -#define BD70528_MASK_RTC_MINUTE 0x7f -#define BD70528_MASK_RTC_HOUR_24H 0x80 -#define BD70528_MASK_RTC_HOUR_PM 0x20 -#define BD70528_MASK_RTC_HOUR 0x1f -#define BD70528_MASK_RTC_DAY 0x3f -#define BD70528_MASK_RTC_WEEK 0x07 -#define BD70528_MASK_RTC_MONTH 0x1f -#define BD70528_MASK_RTC_YEAR 0xff -#define BD70528_MASK_RTC_COUNT_L 0x7f - #define BD70528_MASK_ELAPSED_TIMER_EN 0x1 /* Mask second, min and hour fields * HW would support ALM irq for over 24h @@ -332,7 +322,6 @@ enum { * wake-up we limit ALM to 24H and only * unmask sec, min and hour */ -#define BD70528_MASK_ALM_EN 0x7 #define BD70528_MASK_WAKE_EN 0x1 /* WDT masks */ diff --git a/include/linux/mfd/rohm-bd71828.h b/include/linux/mfd/rohm-bd71828.h index bbbd4f118550..bd9dfd53759d 100644 --- a/include/linux/mfd/rohm-bd71828.h +++ b/include/linux/mfd/rohm-bd71828.h @@ -5,6 +5,7 @@ #define __LINUX_MFD_BD71828_H__ #include +#include /* Regulator IDs */ enum { @@ -160,6 +161,7 @@ enum { #define BD71828_REG_RTC_YEAR 0x52 #define BD71828_REG_RTC_ALM0_SEC 0x53 +#define BD71828_REG_RTC_ALM_START BD71828_REG_RTC_ALM0_SEC #define BD71828_REG_RTC_ALM0_MINUTE 0x54 #define BD71828_REG_RTC_ALM0_HOUR 0x55 #define BD71828_REG_RTC_ALM0_WEEK 0x56 @@ -178,6 +180,7 @@ enum { #define BD71828_REG_RTC_ALM1_MASK 0x62 #define BD71828_REG_RTC_ALM2 0x63 +#define BD71828_REG_RTC_START BD71828_REG_RTC_SEC /* Charger/Battey */ #define BD71828_REG_CHG_STATE 0x65 @@ -207,7 +210,6 @@ enum { #define BD71828_REG_INT_MASK_TEMP 0xdd #define BD71828_REG_INT_MASK_RTC 0xde - #define BD71828_REG_INT_MAIN 0xdf #define BD71828_REG_INT_BUCK 0xe0 #define BD71828_REG_INT_DCIN1 0xe1 diff --git a/include/linux/mfd/rohm-shared.h b/include/linux/mfd/rohm-shared.h new file mode 100644 index 000000000000..f16fc3b5000e --- /dev/null +++ b/include/linux/mfd/rohm-shared.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* Copyright (C) 2018 ROHM Semiconductors */ + + +#ifndef __LINUX_MFD_ROHM_SHARED_H__ +#define __LINUX_MFD_ROHM_SHARED_H__ + +/* + * RTC definitions shared between + * + * BD70528 + * and BD71828 + */ + + +#define BD70528_MASK_RTC_SEC 0x7f +#define BD70528_MASK_RTC_MINUTE 0x7f +#define BD70528_MASK_RTC_HOUR_24H 0x80 +#define BD70528_MASK_RTC_HOUR_PM 0x20 +#define BD70528_MASK_RTC_HOUR 0x3f +#define BD70528_MASK_RTC_DAY 0x3f +#define BD70528_MASK_RTC_WEEK 0x07 +#define BD70528_MASK_RTC_MONTH 0x1f +#define BD70528_MASK_RTC_YEAR 0xff +#define BD70528_MASK_ALM_EN 0x7 + +#endif /* __LINUX_MFD_ROHM_SHARED_H__ */ From patchwork Thu Oct 24 11:50:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matti Vaittinen X-Patchwork-Id: 1182963 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-rtc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=fi.rohmeurope.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46zQYs6XG6z9sPp for ; Thu, 24 Oct 2019 22:51:13 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2439325AbfJXLvK (ORCPT ); Thu, 24 Oct 2019 07:51:10 -0400 Received: from mail-lf1-f67.google.com ([209.85.167.67]:46407 "EHLO mail-lf1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729203AbfJXLvK (ORCPT ); Thu, 24 Oct 2019 07:51:10 -0400 Received: by mail-lf1-f67.google.com with SMTP id t8so18876655lfc.13; Thu, 24 Oct 2019 04:51:07 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=gIphDGDSv8NEqMwF1pTBuVOoRo0AxF2fbD2h/akfGgA=; b=sj24fReXzA7sWGFNEkjl2Kqyrws38Tx73i8YjHCsICGkOQ/nd99TVnnlIYK8ExNJAa Ifo7PrV7q7x6RyUBU4ZA/FfzZs95GicBcchx4iL1krBVsVDIrhqo/aBGNRScMbmnEpEV Ur06DvyrDart167qXwuUm3oyq3lhbcpeVCbyMenPQUnWnQ7SvBLYRlw2YixDf7tTsA4h jRJktPM+vpl01xi0/IcOTWzirm9Cps3FJuIchXoUyMapzhuutlvvlLM78T0Rj5sRJCIU Jwj0MiCKet8EwL4LXEQeYGpvE5wK/mK38AU8KRPtkaxXCwd+OyO/IKj/Ar4CwKLnCjL2 bl0w== X-Gm-Message-State: APjAAAU0O/V15InyIFQ02bYGkwYTf7seLEmTQyk1lZ0Lv7atf3Kg/zNm PhC2o8Xi0klbqXjWScg+kls= X-Google-Smtp-Source: APXvYqygf6Ht6n1cD13QjE1EGDaDqzcgZ/6DNjU+ZZAYK8LNCILFz9jKtFX9dakHBc685iT3fhL4vg== X-Received: by 2002:a19:640c:: with SMTP id y12mr27584712lfb.78.1571917866217; Thu, 24 Oct 2019 04:51:06 -0700 (PDT) Received: from localhost.localdomain ([213.255.186.46]) by smtp.gmail.com with ESMTPSA id s7sm10199625ljs.16.2019.10.24.04.51.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 24 Oct 2019 04:51:05 -0700 (PDT) Date: Thu, 24 Oct 2019 14:50:53 +0300 From: Matti Vaittinen To: matti.vaittinen@fi.rohmeurope.com, mazziesaccount@gmail.com Cc: Lee Jones , Rob Herring , Mark Rutland , Liam Girdwood , Mark Brown , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Jacek Anaszewski , Pavel Machek , Dan Murphy , Alessandro Zummo , Alexandre Belloni , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-leds@vger.kernel.org, linux-rtc@vger.kernel.org Subject: [RFC PATCH v2 12/13] gpio: bd71828: Initial support for ROHM BD71828 PMIC GPIOs Message-ID: <9b53139b7043572b3846a214694dbf8fe1f56f50.1571915550.git.matti.vaittinen@fi.rohmeurope.com> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.12.1 (2019-06-15) Sender: linux-rtc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rtc@vger.kernel.org ROHM BD71828 PMIC contains 4 pins which can be configured by OTP to be used for general purposes. First 3 can be used as outputs and 4.th pin can be used as input. Allow them to be controlled via GPIO framework. The driver assumes all of the pins are configured as GPIOs and trusts that the reserved pins in other OTP configurations are excluded from control using "gpio-reserved-ranges" device tree property (or left untouched by GPIO users). Typical use for 4.th pin (input) is to use it as HALL sensor input so that this pin state is toggled when HALL sensor detects LID position change (from close to open or open to close). PMIC HW implements some extra logic which allows PMIC to power-up the system when this pin is toggled. Please see the data sheet for details of GPIO options which can be selcted by OTP settings. Signed-off-by: Matti Vaittinen --- Mainly styling fixes since v1. drivers/gpio/Kconfig | 12 +++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-bd71828.c | 151 ++++++++++++++++++++++++++++++++++++ 3 files changed, 164 insertions(+) create mode 100644 drivers/gpio/gpio-bd71828.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index bb13c266c329..fb0a099de961 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -986,6 +986,18 @@ config GPIO_BD70528 This driver can also be built as a module. If so, the module will be called gpio-bd70528. +config GPIO_BD71828 + tristate "ROHM BD71828 GPIO support" + depends on MFD_ROHM_BD71828 + help + Support for GPIOs on ROHM BD71828 PMIC. There are three GPIOs + available on the ROHM PMIC in total. The GPIOs are limited to + outputs only and pins must be configured to GPIO outputs by + OTP. Enable this only if you want to use these pins as outputs. + + This driver can also be built as a module. If so, the module + will be called gpio-bd71828. + config GPIO_BD9571MWV tristate "ROHM BD9571 GPIO support" depends on MFD_BD9571MWV diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index a4e91175c708..b11932844768 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o obj-$(CONFIG_GPIO_BD70528) += gpio-bd70528.o +obj-$(CONFIG_GPIO_BD71828) += gpio-bd71828.o obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o diff --git a/drivers/gpio/gpio-bd71828.c b/drivers/gpio/gpio-bd71828.c new file mode 100644 index 000000000000..0ec3a1d9adc0 --- /dev/null +++ b/drivers/gpio/gpio-bd71828.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 ROHM Semiconductors + +#include +#include +#include +#include +#include + +#define BD71828_OUT 0 +#define BD71828_IN 1 +#define GPIO_OUT_REG(off) (BD71828_REG_GPIO_CTRL1 + (off)) +#define HALL_GPIO_OFFSET 3 + +struct bd71828_gpio { + struct rohm_regmap_dev chip; + struct gpio_chip gpio; +}; + +static void bd71828_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) +{ + int ret; + struct bd71828_gpio *bdgpio = gpiochip_get_data(chip); + u8 val = (value) ? BD71828_GPIO_OUT_HI : BD71828_GPIO_OUT_LO; + + /* + * The HALL input pin can only be used as input. If this is the pin + * we are dealing with - then we are done + */ + if (offset == HALL_GPIO_OFFSET) + return; + + ret = regmap_update_bits(bdgpio->chip.regmap, GPIO_OUT_REG(offset), + BD71828_GPIO_OUT_MASK, val); + if (ret) + dev_err(bdgpio->chip.dev, "Could not set gpio to %d\n", value); +} + +static int bd71828_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + int ret; + unsigned int val; + struct bd71828_gpio *bdgpio = gpiochip_get_data(chip); + + if (offset == HALL_GPIO_OFFSET) + ret = regmap_read(bdgpio->chip.regmap, BD71828_REG_IO_STAT, + &val); + else + ret = regmap_read(bdgpio->chip.regmap, GPIO_OUT_REG(offset), + &val); + if (!ret) + ret = (val & BD71828_GPIO_OUT_MASK); + + return ret; +} + +static int bd71828_gpio_set_config(struct gpio_chip *chip, unsigned int offset, + unsigned long config) +{ + struct bd71828_gpio *bdgpio = gpiochip_get_data(chip); + + if (offset == HALL_GPIO_OFFSET) + return -ENOTSUPP; + + switch (pinconf_to_config_param(config)) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + return regmap_update_bits(bdgpio->chip.regmap, + GPIO_OUT_REG(offset), + BD71828_GPIO_DRIVE_MASK, + BD71828_GPIO_OPEN_DRAIN); + case PIN_CONFIG_DRIVE_PUSH_PULL: + return regmap_update_bits(bdgpio->chip.regmap, + GPIO_OUT_REG(offset), + BD71828_GPIO_DRIVE_MASK, + BD71828_GPIO_PUSH_PULL); + default: + break; + } + return -ENOTSUPP; +} + +static int bd71828_get_direction(struct gpio_chip *chip, unsigned int offset) +{ + /* + * Pin usage is selected by OTP data. We can't read it runtime. Hence + * we trust that if the pin is not excluded by "gpio-reserved-ranges" + * the OTP configuration is set to OUT. (Other pins but HALL input pin + * on BD71828 can't really be used for general purpose input - input + * states are used for specific cases like regulator control or + * PMIC_ON_REQ. + */ + if (offset == HALL_GPIO_OFFSET) + return BD71828_IN; + + return BD71828_OUT; +} + +static int bd71828_probe(struct platform_device *pdev) +{ + struct bd71828_gpio *bdgpio; + struct rohm_regmap_dev *bd71828; + + bd71828 = dev_get_drvdata(pdev->dev.parent); + if (!bd71828) { + dev_err(&pdev->dev, "No MFD driver data\n"); + return -EINVAL; + } + + bdgpio = devm_kzalloc(&pdev->dev, sizeof(*bdgpio), + GFP_KERNEL); + if (!bdgpio) + return -ENOMEM; + + bdgpio->chip.dev = &pdev->dev; + bdgpio->gpio.parent = pdev->dev.parent; + bdgpio->gpio.label = "bd71828-gpio"; + bdgpio->gpio.owner = THIS_MODULE; + bdgpio->gpio.get_direction = bd71828_get_direction; + bdgpio->gpio.set_config = bd71828_gpio_set_config; + bdgpio->gpio.can_sleep = true; + bdgpio->gpio.get = bd71828_gpio_get; + bdgpio->gpio.set = bd71828_gpio_set; + bdgpio->gpio.base = -1; + + /* + * See if we need some implementation to mark some PINs as + * not controllable based on DT info or if core can handle + * "gpio-reserved-ranges" and exclude them from control + */ + bdgpio->gpio.ngpio = 4; + bdgpio->gpio.of_node = pdev->dev.parent->of_node; + bdgpio->chip.regmap = bd71828->regmap; + + return devm_gpiochip_add_data(&pdev->dev, &bdgpio->gpio, + bdgpio); +} + +static struct platform_driver bd71828_gpio = { + .driver = { + .name = "bd71828-gpio" + }, + .probe = bd71828_probe, +}; + +module_platform_driver(bd71828_gpio); + +MODULE_AUTHOR("Matti Vaittinen "); +MODULE_DESCRIPTION("BD71828 voltage regulator driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:bd71828-gpio"); From patchwork Thu Oct 24 11:52:09 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matti Vaittinen X-Patchwork-Id: 1182966 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-rtc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=fi.rohmeurope.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46zQbD4qRTz9sPp for ; Thu, 24 Oct 2019 22:52:24 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2439453AbfJXLwV (ORCPT ); Thu, 24 Oct 2019 07:52:21 -0400 Received: from mail-lf1-f67.google.com ([209.85.167.67]:37435 "EHLO mail-lf1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726298AbfJXLwV (ORCPT ); Thu, 24 Oct 2019 07:52:21 -0400 Received: by mail-lf1-f67.google.com with SMTP id g21so17787302lfh.4; Thu, 24 Oct 2019 04:52:17 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=2xjDvDx4J/ULodwmxVgHkawtTdPLuzeZvbnwRBC/GYE=; b=SiKfvL1j7YUpf72ckuZl6oLoW61jsM1b/QjAFutJLYhXyGja53n5VapP0/EjzaBmCW eAvwchKPHpjs5GY+Zq1UKGGe+Y8RRnlYmcNdIZLJ7AMeqBsZyBPo0h4GfVk8Yb3t5CbA Cpa8szxheILXXDjIhm/NgytZ1FhkEeP1dRmoY9KJjg5tCQicbhC3Id1UQBQUGuHLO8s2 BjQyGfHmXFmtuDYEC5cMssuqiOanFy8vdHQvBCA4jA5Y1Srr4tY7WpuhRQ0dWQMICB+C Zcnbx0hENDOrjhORsklkp9H6j3MIZpoOKUuwVyBAQVvZgpQbP7sRt5sxFmszpn+FEDTY tMgQ== X-Gm-Message-State: APjAAAWXikj6Ul0QLkAwhicTlAA9GEb561mF+WlGD/rXXYielXPLQLOe OJtf3wI1GunQJTvUep37pGA= X-Google-Smtp-Source: APXvYqx9mP+SoMYyBN3oxB8WXzkporfgjl++/OEIzJCNFvjD1irkzgqzQxIdLDe5R/i+SOtx1WX/wQ== X-Received: by 2002:a19:ae18:: with SMTP id f24mr27194101lfc.186.1571917936919; Thu, 24 Oct 2019 04:52:16 -0700 (PDT) Received: from localhost.localdomain ([213.255.186.46]) by smtp.gmail.com with ESMTPSA id w28sm7984990lfq.61.2019.10.24.04.52.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 24 Oct 2019 04:52:16 -0700 (PDT) Date: Thu, 24 Oct 2019 14:52:09 +0300 From: Matti Vaittinen To: matti.vaittinen@fi.rohmeurope.com, mazziesaccount@gmail.com Cc: Lee Jones , Rob Herring , Mark Rutland , Liam Girdwood , Mark Brown , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Jacek Anaszewski , Pavel Machek , Dan Murphy , Alessandro Zummo , Alexandre Belloni , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-leds@vger.kernel.org, linux-rtc@vger.kernel.org Subject: [RFC PATCH v2 13/13] led: bd71828: Support LED outputs on ROHM BD71828 PMIC Message-ID: <8ca44c947374df2e2479e83a1eedce561cc72098.1571915550.git.matti.vaittinen@fi.rohmeurope.com> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.12.1 (2019-06-15) Sender: linux-rtc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rtc@vger.kernel.org ROHM BD71828 power management IC has two LED outputs for charge status and button pressing indications. The LED outputs can also be forced by SW so add driver allowing to use these LEDs for other indications as well. Leds are controlled by SW using 'Force ON' bits. Please note the constrains mentioned in data-sheet: 1. If one LED is forced ON - then also the other LED is forced. => You can't use SW control to force ON one LED and allow HW to control the other. 2. You can't force both LEDs OFF. If the FORCE bit for both LED's is zero, then LEDs are controlled by HW and indicate button/charger states as explained in data-sheet. Signed-off-by: Matti Vaittinen --- No changes since v1. Changes still under discussion. drivers/leds/Kconfig | 10 ++++ drivers/leds/Makefile | 1 + drivers/leds/leds-bd71828.c | 97 +++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 drivers/leds/leds-bd71828.c diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index b0fdeef10bd9..ec59f28bcb39 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -529,6 +529,16 @@ config LEDS_BD2802 This option enables support for BD2802GU RGB LED driver chips accessed via the I2C bus. +config LEDS_BD71828 + tristate "LED driver for LED pins on ROHM BD71828 PMIC" + depends on LEDS_CLASS + depends on I2C + help + This option enables support for LED outputs located on ROHM + BD71828 power management IC. ROHM BD71828 has two led output pins + which can be left to indicate HW states or controlled by SW. Say + yes here if you want to enable SW control for these LEDs. + config LEDS_INTEL_SS4200 tristate "LED driver for Intel NAS SS4200 series" depends on LEDS_CLASS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 41fb073a39c1..2a8f6a8e4c7c 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_LEDS_AN30259A) += leds-an30259a.o obj-$(CONFIG_LEDS_BCM6328) += leds-bcm6328.o obj-$(CONFIG_LEDS_BCM6358) += leds-bcm6358.o obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o +obj-$(CONFIG_LEDS_BD71828) += leds-bd71828.o obj-$(CONFIG_LEDS_CPCAP) += leds-cpcap.o obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o obj-$(CONFIG_LEDS_LM3530) += leds-lm3530.o diff --git a/drivers/leds/leds-bd71828.c b/drivers/leds/leds-bd71828.c new file mode 100644 index 000000000000..2427619444f5 --- /dev/null +++ b/drivers/leds/leds-bd71828.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2019 ROHM Semiconductors + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BD71828_LED_TO_DATA(l) ((l)->id == ID_GREEN_LED ? \ + container_of((l), struct bd71828_leds, green) : \ + container_of((l), struct bd71828_leds, amber)) + +enum { + ID_GREEN_LED, + ID_AMBER_LED, + ID_NMBR_OF, +}; + +struct bd71828_led { + int id; + struct led_classdev l; + u8 force_mask; +}; + +struct bd71828_leds { + struct rohm_regmap_dev *bd71828; + struct bd71828_led green; + struct bd71828_led amber; +}; + +static int bd71828_led_brightness_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct bd71828_led *l = container_of(led_cdev, struct bd71828_led, l); + struct bd71828_leds *data; + unsigned int val = BD71828_LED_OFF; + + data = BD71828_LED_TO_DATA(l); + if (value != LED_OFF) + val = BD71828_LED_ON; + + return regmap_update_bits(data->bd71828->regmap, BD71828_REG_LED_CTRL, + l->force_mask, val); +} + +static int bd71828_led_probe(struct platform_device *pdev) +{ + struct rohm_regmap_dev *bd71828; + struct bd71828_leds *l; + struct bd71828_led *g, *a; + static const char *GNAME = "bd71828-green-led"; + static const char *ANAME = "bd71828-amber-led"; + int ret; + + pr_info("bd71828 LED driver probed\n"); + + bd71828 = dev_get_drvdata(pdev->dev.parent); + l = devm_kzalloc(&pdev->dev, sizeof(*l), GFP_KERNEL); + if (!l) + return -ENOMEM; + l->bd71828 = bd71828; + a = &l->amber; + g = &l->green; + a->id = ID_AMBER_LED; + g->id = ID_GREEN_LED; + a->force_mask = BD71828_MASK_LED_AMBER; + g->force_mask = BD71828_MASK_LED_GREEN; + + a->l.name = ANAME; + g->l.name = GNAME; + a->l.brightness_set_blocking = bd71828_led_brightness_set; + g->l.brightness_set_blocking = bd71828_led_brightness_set; + + ret = devm_led_classdev_register(&pdev->dev, &g->l); + if (ret) + return ret; + + return devm_led_classdev_register(&pdev->dev, &a->l); +} + +static struct platform_driver bd71828_led_driver = { + .driver = { + .name = "bd71828-led", + }, + .probe = bd71828_led_probe, +}; + +module_platform_driver(bd71828_led_driver); + +MODULE_AUTHOR("Matti Vaittinen "); +MODULE_DESCRIPTION("ROHM BD71828 LED driver"); +MODULE_LICENSE("GPL");