From 1b1c26b24a6e75d96967515e55fba6c9954d4009 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Mon, 20 Jan 2020 15:42:38 +0200 Subject: mfd: Rohm PMICs: Use platform_device_id to match MFD sub-devices Thanks to Stephen Boyd I today learned we can use platform_device_id to do device and module matching for MFD sub-devices! Do device matching using the platform_device_id instead of using explicit module_aliases to load modules and custom parent-data field to do module loading and sub-device matching. Cc: Stephen Boyd Signed-off-by: Matti Vaittinen Acked-by: Mark Brown Signed-off-by: Lee Jones --- include/linux/mfd/rohm-generic.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/mfd/rohm-generic.h b/include/linux/mfd/rohm-generic.h index bff15ac26f2c..922f88008232 100644 --- a/include/linux/mfd/rohm-generic.h +++ b/include/linux/mfd/rohm-generic.h @@ -4,7 +4,7 @@ #ifndef __LINUX_MFD_ROHM_H__ #define __LINUX_MFD_ROHM_H__ -enum { +enum rohm_chip_type { ROHM_CHIP_TYPE_BD71837 = 0, ROHM_CHIP_TYPE_BD71847, ROHM_CHIP_TYPE_BD70528, @@ -12,7 +12,6 @@ enum { }; struct rohm_regmap_dev { - unsigned int chip_type; struct device *dev; struct regmap *regmap; }; -- cgit v1.2.3-59-g8ed1b From 1c743ad523bb2f77a43a740a43c3b5bb9cbd82cd Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Mon, 20 Jan 2020 15:43:28 +0200 Subject: mfd: bd71828: Support ROHM BD71828 PMIC - core 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 Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 15 ++ drivers/mfd/Makefile | 1 + drivers/mfd/rohm-bd71828.c | 318 +++++++++++++++++++++++++++++ include/linux/mfd/rohm-bd71828.h | 425 +++++++++++++++++++++++++++++++++++++++ include/linux/mfd/rohm-generic.h | 1 + 5 files changed, 760 insertions(+) create mode 100644 drivers/mfd/rohm-bd71828.c create mode 100644 include/linux/mfd/rohm-bd71828.h (limited to 'include/linux') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 420900852166..c3c9432ef51c 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1906,6 +1906,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 aed99f08739f..61b3093af39d 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -252,6 +252,7 @@ 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..0ec386c9f26b --- /dev/null +++ b/drivers/mfd/rohm-bd71828.c @@ -0,0 +1,318 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// 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", .of_compatible = "rohm,bd71828-leds" }, + /* + * We use BD71837 driver to drive the clock block. Only differences to + * BD70528 clock gate are the register address and mask. + */ + { .name = "bd71828-clk", }, + { .name = "bd71827-power", }, + { + .name = "bd71828-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. + */ + .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. + */ + +static unsigned int bit0_offsets[] = {11}; /* RTC IRQ */ +static unsigned int bit1_offsets[] = {10}; /* TEMP IRQ */ +static unsigned int bit2_offsets[] = {6, 7, 8, 9}; /* BAT MON IRQ */ +static unsigned int bit3_offsets[] = {5}; /* BAT IRQ */ +static unsigned int bit4_offsets[] = {4}; /* CHG IRQ */ +static unsigned int bit5_offsets[] = {3}; /* VSYS IRQ */ +static unsigned int bit6_offsets[] = {1, 2}; /* DCIN IRQ */ +static unsigned int bit7_offsets[] = {0}; /* BUCK IRQ */ + +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) +{ + 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->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_new = &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 922f88008232..ff3dd7578fd3 100644 --- a/include/linux/mfd/rohm-generic.h +++ b/include/linux/mfd/rohm-generic.h @@ -8,6 +8,7 @@ enum rohm_chip_type { ROHM_CHIP_TYPE_BD71837 = 0, ROHM_CHIP_TYPE_BD71847, ROHM_CHIP_TYPE_BD70528, + ROHM_CHIP_TYPE_BD71828, ROHM_CHIP_TYPE_AMOUNT }; -- cgit v1.2.3-59-g8ed1b From ae866dec742687b0bff407013b91badba524f7ee Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Mon, 20 Jan 2020 15:44:19 +0200 Subject: clk: bd718x7: Support ROHM BD71828 clk block 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 Acked-by: Stephen Boyd Signed-off-by: Lee Jones --- drivers/clk/Kconfig | 6 +++--- drivers/clk/clk-bd718x7.c | 38 ++++++++++++++++++++++++++++---------- include/linux/mfd/rohm-bd70528.h | 6 ------ include/linux/mfd/rohm-bd71828.h | 4 ---- include/linux/mfd/rohm-bd718x7.h | 6 ------ 5 files changed, 31 insertions(+), 29 deletions(-) (limited to 'include/linux') diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 45653a0e6ecd..ac5981ce2477 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -305,10 +305,10 @@ config COMMON_CLK_MMP2 Support for Marvell MMP2 and MMP3 SoC 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 33699ee1bdf3..b52e8d6f660c 100644 --- a/drivers/clk/clk-bd718x7.c +++ b/drivers/clk/clk-bd718x7.c @@ -7,12 +7,25 @@ #include #include #include -#include -#include +#include #include #include #include +/* clk control registers */ +/* BD70528 */ +#define BD70528_REG_OUT32K 0x2c +/* BD71828 */ +#define BD71828_REG_OUT32K 0x4B +/* BD71837 and BD71847 */ +#define BD718XX_REG_OUT32K 0x2E + +/* + * BD71837, BD71847, BD70528 and BD71828 all use bit [0] to clk output control + */ +#define CLK_OUT_EN_MASK BIT(0) + + struct bd718xx_clk { struct clk_hw hw; u8 reg; @@ -21,10 +34,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, unsigned 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 +44,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) @@ -92,11 +105,15 @@ static int bd71837_clk_probe(struct platform_device *pdev) case ROHM_CHIP_TYPE_BD71837: case ROHM_CHIP_TYPE_BD71847: c->reg = BD718XX_REG_OUT32K; - c->mask = BD718XX_OUT32K_EN; + c->mask = CLK_OUT_EN_MASK; + break; + case ROHM_CHIP_TYPE_BD71828: + c->reg = BD71828_REG_OUT32K; + c->mask = CLK_OUT_EN_MASK; break; case ROHM_CHIP_TYPE_BD70528: - c->reg = BD70528_REG_CLK_OUT; - c->mask = BD70528_CLK_OUT_EN_MASK; + c->reg = BD70528_REG_OUT32K; + c->mask = CLK_OUT_EN_MASK; break; default: dev_err(&pdev->dev, "Unknown clk chip\n"); @@ -126,6 +143,7 @@ static const struct platform_device_id bd718x7_clk_id[] = { { "bd71837-clk", ROHM_CHIP_TYPE_BD71837 }, { "bd71847-clk", ROHM_CHIP_TYPE_BD71847 }, { "bd70528-clk", ROHM_CHIP_TYPE_BD70528 }, + { "bd71828-clk", ROHM_CHIP_TYPE_BD71828 }, { }, }; MODULE_DEVICE_TABLE(platform, bd718x7_clk_id); diff --git a/include/linux/mfd/rohm-bd70528.h b/include/linux/mfd/rohm-bd70528.h index 1013e60c5b25..2ad2320d0a96 100644 --- a/include/linux/mfd/rohm-bd70528.h +++ b/include/linux/mfd/rohm-bd70528.h @@ -89,10 +89,6 @@ struct bd70528_data { #define BD70528_REG_GPIO3_OUT 0x52 #define BD70528_REG_GPIO4_OUT 0x54 -/* clk control */ - -#define BD70528_REG_CLK_OUT 0x2c - /* RTC */ #define BD70528_REG_RTC_COUNT_H 0x2d @@ -309,8 +305,6 @@ enum { #define BD70528_GPIO_IN_STATE_BASE 1 -#define BD70528_CLK_OUT_EN_MASK 0x1 - /* RTC masks to mask out reserved bits */ #define BD70528_MASK_RTC_SEC 0x7f diff --git a/include/linux/mfd/rohm-bd71828.h b/include/linux/mfd/rohm-bd71828.h index eb0557eb5314..d013e03f742d 100644 --- a/include/linux/mfd/rohm-bd71828.h +++ b/include/linux/mfd/rohm-bd71828.h @@ -183,9 +183,6 @@ enum { #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 @@ -417,7 +414,6 @@ enum { #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 diff --git a/include/linux/mfd/rohm-bd718x7.h b/include/linux/mfd/rohm-bd718x7.h index 7f2dbde402a1..bee2474a8f9f 100644 --- a/include/linux/mfd/rohm-bd718x7.h +++ b/include/linux/mfd/rohm-bd718x7.h @@ -191,12 +191,6 @@ enum { #define IRQ_ON_REQ 0x02 #define IRQ_STBY_REQ 0x01 -/* BD718XX_REG_OUT32K bits */ -#define BD718XX_OUT32K_EN 0x01 - -/* BD7183XX gated clock rate */ -#define BD718XX_CLK_RATE 32768 - /* ROHM BD718XX irqs */ enum { BD718XX_INT_STBY_REQ, -- cgit v1.2.3-59-g8ed1b From 21b72156ede8b7da0367c6338574c1bc40439157 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Mon, 20 Jan 2020 15:44:45 +0200 Subject: regulator: bd718x7: Split driver to common and bd718x7 specific parts 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 Acked-by: Mark Brown Signed-off-by: Lee Jones --- 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 | 66 ++++++++++++ 5 files changed, 221 insertions(+), 128 deletions(-) create mode 100644 drivers/regulator/rohm-regulator.c (limited to 'include/linux') diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 74eb5af7295f..a4897ae52f14 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -197,6 +197,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 @@ -790,6 +791,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 2210ba56f9bd..6bcab72c1fc7 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -99,6 +99,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 6beaf867d9cb..55decb58c777 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..399002383b28 --- /dev/null +++ b/drivers/regulator/rohm-regulator.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2020 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 ff3dd7578fd3..4283b5b33e04 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 { ROHM_CHIP_TYPE_BD71837 = 0, ROHM_CHIP_TYPE_BD71847, @@ -17,4 +20,67 @@ 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, + ROHM_DVS_LEVEL_MAX = ROHM_DVS_LEVEL_LPSR, +}; + +/** + * struct rohm_dvs_config - dynamic voltage scaling register descriptions + * + * @level_map: bitmap representing supported run-levels for this + * regulator + * @run_reg: register address for regulator config at 'run' state + * @run_mask: value mask for regulator voltages at 'run' state + * @run_on_mask: enable mask for regulator at 'run' state + * @idle_reg: register address for regulator config at 'idle' state + * @idle_mask: value mask for regulator voltages at 'idle' state + * @idle_on_mask: enable mask for regulator at 'idle' state + * @suspend_reg: register address for regulator config at 'suspend' state + * @suspend_mask: value mask for regulator voltages at 'suspend' state + * @suspend_on_mask: enable mask for regulator at 'suspend' state + * @lpsr_reg: register address for regulator config at 'lpsr' state + * @lpsr_mask: value mask for regulator voltages at 'lpsr' state + * @lpsr_on_mask: enable mask for regulator at 'lpsr' state + * + * Description of ROHM PMICs voltage configuration registers for different + * system states. This is used to correctly configure the PMIC at startup + * based on values read from DT. + */ +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 + #endif -- cgit v1.2.3-59-g8ed1b From 6c883472e1c11cb05561b6dd0c28bb037c2bf2de Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Mon, 20 Jan 2020 15:45:11 +0200 Subject: mfd: bd70528: Fix hour register mask When RTC is used in 24H mode (and it is by this driver) the maximum hour value is 24 in BCD. This occupies bits [5:0] - which means correct mask for HOUR register is 0x3f not 0x1f. Fix the mask Fixes: 32a4a4ebf768 ("rtc: bd70528: Initial support for ROHM bd70528 RTC") Signed-off-by: Matti Vaittinen Acked-by: Alexandre Belloni Signed-off-by: Lee Jones --- include/linux/mfd/rohm-bd70528.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/mfd/rohm-bd70528.h b/include/linux/mfd/rohm-bd70528.h index 2ad2320d0a96..edae6f7afd8e 100644 --- a/include/linux/mfd/rohm-bd70528.h +++ b/include/linux/mfd/rohm-bd70528.h @@ -311,7 +311,7 @@ enum { #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_HOUR 0x3f #define BD70528_MASK_RTC_DAY 0x3f #define BD70528_MASK_RTC_WEEK 0x07 #define BD70528_MASK_RTC_MONTH 0x1f -- cgit v1.2.3-59-g8ed1b From fe5a591b7814ffbc90aff661aeb8264937002f54 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Mon, 20 Jan 2020 15:45:36 +0200 Subject: rtc: bd70528: add BD71828 support 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 Acked-by: Alexandre Belloni Signed-off-by: Lee Jones --- drivers/rtc/Kconfig | 3 +- drivers/rtc/rtc-bd70528.c | 220 +++++++++++++++++++++++++++++++-------- include/linux/mfd/rohm-bd70528.h | 13 +-- include/linux/mfd/rohm-bd71828.h | 4 +- include/linux/mfd/rohm-shared.h | 21 ++++ 5 files changed, 206 insertions(+), 55 deletions(-) create mode 100644 include/linux/mfd/rohm-shared.h (limited to 'include/linux') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index d77515d8382c..df7a3843069d 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -498,12 +498,13 @@ 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" depends on MFD_ROHM_BD70528 && (BD70528_WATCHDOG || !BD70528_WATCHDOG) 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 627037aa66a8..bbbb1f07c91f 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; @@ -43,8 +51,10 @@ struct bd70528_rtc_alm { } __packed; struct bd70528_rtc { - struct rohm_regmap_dev *mfd; + struct rohm_regmap_dev *parent; struct device *dev; + u8 reg_time_start; + bool has_rtc_timers; }; static int bd70528_set_wake(struct rohm_regmap_dev *bd70528, @@ -123,14 +133,14 @@ static int bd70528_set_rtc_based_timers(struct bd70528_rtc *r, int new_state, { int ret; - ret = bd70528_wdt_set(r->mfd, new_state & BD70528_WDT_STATE_BIT, + ret = bd70528_wdt_set(r->parent, new_state & BD70528_WDT_STATE_BIT, old_state); if (ret) { dev_err(r->dev, "Failed to disable WDG for RTC setting (%d)\n", ret); return ret; } - ret = bd70528_set_elapsed_tmr(r->mfd, + ret = bd70528_set_elapsed_tmr(r->parent, new_state & BD70528_ELAPSED_STATE_BIT, old_state); if (ret) { @@ -138,7 +148,7 @@ static int bd70528_set_rtc_based_timers(struct bd70528_rtc *r, int new_state, "Failed to disable 'elapsed timer' for RTC setting\n"); return ret; } - ret = bd70528_set_wake(r->mfd, new_state & BD70528_WAKE_STATE_BIT, + ret = bd70528_set_wake(r->parent, new_state & BD70528_WAKE_STATE_BIT, old_state); if (ret) { dev_err(r->dev, @@ -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,22 +229,52 @@ 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 *parent = r->parent; + + ret = regmap_bulk_read(parent->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(parent->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; struct bd70528_rtc_alm alm; int ret; struct bd70528_rtc *r = dev_get_drvdata(dev); - struct rohm_regmap_dev *bd70528 = r->mfd; + struct rohm_regmap_dev *parent = r->parent; - ret = regmap_bulk_read(bd70528->regmap, BD70528_REG_RTC_WAKE_START, + ret = regmap_bulk_read(parent->regmap, BD70528_REG_RTC_WAKE_START, &wake, sizeof(wake)); if (ret) { dev_err(dev, "Failed to read wake regs\n"); return ret; } - ret = regmap_bulk_read(bd70528->regmap, BD70528_REG_RTC_ALM_START, + ret = regmap_bulk_read(parent->regmap, BD70528_REG_RTC_ALM_START, &alm, sizeof(alm)); if (ret) { dev_err(dev, "Failed to read alarm regs\n"); @@ -246,14 +292,14 @@ static int bd70528_set_alarm(struct device *dev, struct rtc_wkalrm *a) wake.ctrl &= ~BD70528_MASK_WAKE_EN; } - ret = regmap_bulk_write(bd70528->regmap, + ret = regmap_bulk_write(parent->regmap, BD70528_REG_RTC_WAKE_START, &wake, sizeof(wake)); if (ret) { dev_err(dev, "Failed to set wake time\n"); return ret; } - ret = regmap_bulk_write(bd70528->regmap, BD70528_REG_RTC_ALM_START, + ret = regmap_bulk_write(parent->regmap, BD70528_REG_RTC_ALM_START, &alm, sizeof(alm)); if (ret) dev_err(dev, "Failed to set alarm time\n"); @@ -261,14 +307,38 @@ 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 *parent = r->parent; + + ret = regmap_bulk_read(parent->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; int ret; struct bd70528_rtc *r = dev_get_drvdata(dev); - struct rohm_regmap_dev *bd70528 = r->mfd; + struct rohm_regmap_dev *parent = r->parent; - ret = regmap_bulk_read(bd70528->regmap, BD70528_REG_RTC_ALM_START, + ret = regmap_bulk_read(parent->regmap, BD70528_REG_RTC_ALM_START, &alm, sizeof(alm)); if (ret) { dev_err(dev, "Failed to read alarm regs\n"); @@ -290,14 +360,14 @@ static int bd70528_set_time_locked(struct device *dev, struct rtc_time *t) int ret, tmpret, old_states; struct bd70528_rtc_data rtc_data; struct bd70528_rtc *r = dev_get_drvdata(dev); - struct rohm_regmap_dev *bd70528 = r->mfd; + struct rohm_regmap_dev *parent = r->parent; ret = bd70528_disable_rtc_based_timers(r, &old_states); if (ret) return ret; - tmpret = regmap_bulk_read(bd70528->regmap, - BD70528_REG_RTC_START, &rtc_data, + tmpret = regmap_bulk_read(parent->regmap, + r->reg_time_start, &rtc_data, sizeof(rtc_data)); if (tmpret) { dev_err(dev, "Failed to read RTC time registers\n"); @@ -305,8 +375,8 @@ 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, + tmpret = regmap_bulk_write(parent->regmap, + r->reg_time_start, &rtc_data, sizeof(rtc_data)); if (tmpret) { dev_err(dev, "Failed to set RTC time\n"); @@ -321,27 +391,32 @@ renable_out: return ret; } +static int bd71828_set_time(struct device *dev, struct rtc_time *t) +{ + return bd70528_set_time_locked(dev, t); +} + static int bd70528_set_time(struct device *dev, struct rtc_time *t) { int ret; struct bd70528_rtc *r = dev_get_drvdata(dev); - bd70528_wdt_lock(r->mfd); + bd70528_wdt_lock(r->parent); ret = bd70528_set_time_locked(dev, t); - bd70528_wdt_unlock(r->mfd); + bd70528_wdt_unlock(r->parent); return ret; } static int bd70528_get_time(struct device *dev, struct rtc_time *t) { struct bd70528_rtc *r = dev_get_drvdata(dev); - struct rohm_regmap_dev *bd70528 = r->mfd; + struct rohm_regmap_dev *parent = r->parent; struct bd70528_rtc_data rtc_data; int ret; /* read the RTC date and time registers all at once */ - ret = regmap_bulk_read(bd70528->regmap, - BD70528_REG_RTC_START, &rtc_data, + ret = regmap_bulk_read(parent->regmap, + r->reg_time_start, &rtc_data, sizeof(rtc_data)); if (ret) { dev_err(dev, "Failed to read RTC time (err %d)\n", ret); @@ -362,19 +437,36 @@ static int bd70528_alm_enable(struct device *dev, unsigned int enabled) if (enabled) enableval = 0; - bd70528_wdt_lock(r->mfd); - ret = bd70528_set_wake(r->mfd, enabled, NULL); + bd70528_wdt_lock(r->parent); + ret = bd70528_set_wake(r->parent, enabled, NULL); if (ret) { dev_err(dev, "Failed to change wake state\n"); goto out_unlock; } - ret = regmap_update_bits(r->mfd->regmap, BD70528_REG_RTC_ALM_MASK, + ret = regmap_update_bits(r->parent->regmap, BD70528_REG_RTC_ALM_MASK, BD70528_MASK_ALM_EN, enableval); if (ret) dev_err(dev, "Failed to change alarm state\n"); out_unlock: - bd70528_wdt_unlock(r->mfd); + bd70528_wdt_unlock(r->parent); + 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->parent->regmap, BD71828_REG_RTC_ALM0_MASK, + BD70528_MASK_ALM_EN, enableval); + if (ret) + dev_err(dev, "Failed to change alarm state\n"); + return ret; } @@ -386,6 +478,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 = bd71828_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,14 +497,19 @@ static irqreturn_t alm_hndlr(int irq, void *data) static int bd70528_probe(struct platform_device *pdev) { struct bd70528_rtc *bd_rtc; - struct rohm_regmap_dev *mfd; + const struct rtc_class_ops *rtc_ops; + struct rohm_regmap_dev *parent; + const char *irq_name; int ret; struct rtc_device *rtc; int irq; unsigned int hr; + bool enable_main_irq = false; + u8 hour_reg; + enum rohm_chip_type chip = platform_get_device_id(pdev)->driver_data; - mfd = dev_get_drvdata(pdev->dev.parent); - if (!mfd) { + parent = dev_get_drvdata(pdev->dev.parent); + if (!parent) { dev_err(&pdev->dev, "No MFD driver data\n"); return -EINVAL; } @@ -412,16 +517,39 @@ static int bd70528_probe(struct platform_device *pdev) if (!bd_rtc) return -ENOMEM; - bd_rtc->mfd = mfd; + bd_rtc->parent = parent; bd_rtc->dev = &pdev->dev; - irq = platform_get_irq_byname(pdev, "bd70528-rtc-alm"); - if (irq < 0) + switch (chip) { + 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"); return irq; + } platform_set_drvdata(pdev, bd_rtc); - ret = regmap_read(mfd->regmap, BD70528_REG_RTC_HOUR, &hr); + ret = regmap_read(parent->regmap, hour_reg, &hr); if (ret) { dev_err(&pdev->dev, "Failed to reag RTC clock\n"); @@ -431,10 +559,10 @@ static int bd70528_probe(struct platform_device *pdev) if (!(hr & BD70528_MASK_RTC_HOUR_24H)) { struct rtc_time t; - ret = bd70528_get_time(&pdev->dev, &t); + ret = rtc_ops->read_time(&pdev->dev, &t); if (!ret) - ret = bd70528_set_time(&pdev->dev, &t); + ret = rtc_ops->set_time(&pdev->dev, &t); if (ret) { dev_err(&pdev->dev, @@ -454,7 +582,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, @@ -468,27 +596,37 @@ 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(parent->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; + } } return rtc_register_device(rtc); } +static const struct platform_device_id bd718x7_rtc_id[] = { + { "bd70528-rtc", ROHM_CHIP_TYPE_BD70528 }, + { "bd71828-rtc", ROHM_CHIP_TYPE_BD71828 }, + { }, +}; +MODULE_DEVICE_TABLE(platform, bd718x7_rtc_id); + static struct platform_driver bd70528_rtc = { .driver = { .name = "bd70528-rtc" }, .probe = bd70528_probe, + .id_table = bd718x7_rtc_id, }; 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"); MODULE_ALIAS("platform:bd70528-rtc"); diff --git a/include/linux/mfd/rohm-bd70528.h b/include/linux/mfd/rohm-bd70528.h index edae6f7afd8e..a57af878fd0c 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 { @@ -307,17 +308,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 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_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 @@ -326,7 +316,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 d013e03f742d..017a4c01cb31 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 @@ -204,7 +207,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..53dd7f638bfd --- /dev/null +++ b/include/linux/mfd/rohm-shared.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* Copyright (C) 2020 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__ */ -- cgit v1.2.3-59-g8ed1b From f41810921bdca37161a63f689cdcb36155f0fad6 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 28 Dec 2019 23:26:14 +0100 Subject: mfd: dbx500-prcmu: Drop set_display_clocks() The display clocks are handled by the generic clock framework since ages, this code is completely unused and misleading. Delete it. Cc: Stephan Gerhold Cc: Ulf Hansson Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/db8500-prcmu.c | 30 ------------------------------ include/linux/mfd/db8500-prcmu.h | 6 ------ include/linux/mfd/dbx500-prcmu.h | 10 ---------- 3 files changed, 46 deletions(-) (limited to 'include/linux') diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 26d967a1a046..5f0cfeec8b6a 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -555,14 +555,6 @@ static struct dsiescclk dsiescclk[3] = { #define PRCMU_CLK_38_SRC (1 << 10) #define PRCMU_CLK_38_DIV (1 << 11) -/* PLLDIV=12, PLLSW=4 (PLLDDR) */ -#define PRCMU_DSI_CLOCK_SETTING 0x0000008C - -/* DPI 50000000 Hz */ -#define PRCMU_DPI_CLOCK_SETTING ((1 << PRCMU_CLK_PLL_SW_SHIFT) | \ - (16 << PRCMU_CLK_PLL_DIV_SHIFT)) -#define PRCMU_DSI_LP_CLOCK_SETTING 0x00000E00 - /* D=101, N=1, R=4, SELDIV2=0 */ #define PRCMU_PLLDSI_FREQ_SETTING 0x00040165 @@ -616,28 +608,6 @@ int db8500_prcmu_disable_dsipll(void) return 0; } -int db8500_prcmu_set_display_clocks(void) -{ - unsigned long flags; - - spin_lock_irqsave(&clk_mgt_lock, flags); - - /* Grab the HW semaphore. */ - while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) - cpu_relax(); - - writel(PRCMU_DSI_CLOCK_SETTING, prcmu_base + PRCM_HDMICLK_MGT); - writel(PRCMU_DSI_LP_CLOCK_SETTING, prcmu_base + PRCM_TVCLK_MGT); - writel(PRCMU_DPI_CLOCK_SETTING, prcmu_base + PRCM_LCDCLK_MGT); - - /* Release the HW semaphore. */ - writel(0, PRCM_SEM); - - spin_unlock_irqrestore(&clk_mgt_lock, flags); - - return 0; -} - u32 db8500_prcmu_read(unsigned int reg) { return readl(prcmu_base + reg); diff --git a/include/linux/mfd/db8500-prcmu.h b/include/linux/mfd/db8500-prcmu.h index 1fc75d2b4a38..7d0c442e0c25 100644 --- a/include/linux/mfd/db8500-prcmu.h +++ b/include/linux/mfd/db8500-prcmu.h @@ -525,7 +525,6 @@ u8 db8500_prcmu_get_power_state_result(void); void db8500_prcmu_enable_wakeups(u32 wakeups); int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state); int db8500_prcmu_request_clock(u8 clock, bool enable); -int db8500_prcmu_set_display_clocks(void); int db8500_prcmu_disable_dsipll(void); int db8500_prcmu_enable_dsipll(void); void db8500_prcmu_config_abb_event_readout(u32 abb_events); @@ -682,11 +681,6 @@ static inline int db8500_prcmu_request_clock(u8 clock, bool enable) return 0; } -static inline int db8500_prcmu_set_display_clocks(void) -{ - return 0; -} - static inline int db8500_prcmu_disable_dsipll(void) { return 0; diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h index e2571040c7e8..812b6c3c4ef6 100644 --- a/include/linux/mfd/dbx500-prcmu.h +++ b/include/linux/mfd/dbx500-prcmu.h @@ -321,11 +321,6 @@ static inline bool prcmu_is_ac_wake_requested(void) return db8500_prcmu_is_ac_wake_requested(); } -static inline int prcmu_set_display_clocks(void) -{ - return db8500_prcmu_set_display_clocks(); -} - static inline int prcmu_disable_dsipll(void) { return db8500_prcmu_disable_dsipll(); @@ -511,11 +506,6 @@ static inline bool prcmu_is_ac_wake_requested(void) return false; } -static inline int prcmu_set_display_clocks(void) -{ - return 0; -} - static inline int prcmu_disable_dsipll(void) { return 0; -- cgit v1.2.3-59-g8ed1b From 2cce09eb11228386260a1b73133aee41f4bb33b1 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 28 Dec 2019 23:26:15 +0100 Subject: mfd: dbx500-prcmu: Drop DSI pll clock functions The DSI PLLs are handled by the generic clock framework since ages, this code is completely unused and misleading. Delete it. Cc: Stephan Gerhold Cc: Ulf Hansson Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/db8500-prcmu.c | 66 ---------------------------------------- include/linux/mfd/db8500-prcmu.h | 12 -------- include/linux/mfd/dbx500-prcmu.h | 20 ------------ 3 files changed, 98 deletions(-) (limited to 'include/linux') diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 5f0cfeec8b6a..0452b43b0423 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -542,72 +542,6 @@ static struct dsiescclk dsiescclk[3] = { } }; - -/* -* Used by MCDE to setup all necessary PRCMU registers -*/ -#define PRCMU_RESET_DSIPLL 0x00004000 -#define PRCMU_UNCLAMP_DSIPLL 0x00400800 - -#define PRCMU_CLK_PLL_DIV_SHIFT 0 -#define PRCMU_CLK_PLL_SW_SHIFT 5 -#define PRCMU_CLK_38 (1 << 9) -#define PRCMU_CLK_38_SRC (1 << 10) -#define PRCMU_CLK_38_DIV (1 << 11) - -/* D=101, N=1, R=4, SELDIV2=0 */ -#define PRCMU_PLLDSI_FREQ_SETTING 0x00040165 - -#define PRCMU_ENABLE_PLLDSI 0x00000001 -#define PRCMU_DISABLE_PLLDSI 0x00000000 -#define PRCMU_RELEASE_RESET_DSS 0x0000400C -#define PRCMU_DSI_PLLOUT_SEL_SETTING 0x00000202 -/* ESC clk, div0=1, div1=1, div2=3 */ -#define PRCMU_ENABLE_ESCAPE_CLOCK_DIV 0x07030101 -#define PRCMU_DISABLE_ESCAPE_CLOCK_DIV 0x00030101 -#define PRCMU_DSI_RESET_SW 0x00000007 - -#define PRCMU_PLLDSI_LOCKP_LOCKED 0x3 - -int db8500_prcmu_enable_dsipll(void) -{ - int i; - - /* Clear DSIPLL_RESETN */ - writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_CLR); - /* Unclamp DSIPLL in/out */ - writel(PRCMU_UNCLAMP_DSIPLL, PRCM_MMIP_LS_CLAMP_CLR); - - /* Set DSI PLL FREQ */ - writel(PRCMU_PLLDSI_FREQ_SETTING, PRCM_PLLDSI_FREQ); - writel(PRCMU_DSI_PLLOUT_SEL_SETTING, PRCM_DSI_PLLOUT_SEL); - /* Enable Escape clocks */ - writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV); - - /* Start DSI PLL */ - writel(PRCMU_ENABLE_PLLDSI, PRCM_PLLDSI_ENABLE); - /* Reset DSI PLL */ - writel(PRCMU_DSI_RESET_SW, PRCM_DSI_SW_RESET); - for (i = 0; i < 10; i++) { - if ((readl(PRCM_PLLDSI_LOCKP) & PRCMU_PLLDSI_LOCKP_LOCKED) - == PRCMU_PLLDSI_LOCKP_LOCKED) - break; - udelay(100); - } - /* Set DSIPLL_RESETN */ - writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_SET); - return 0; -} - -int db8500_prcmu_disable_dsipll(void) -{ - /* Disable dsi pll */ - writel(PRCMU_DISABLE_PLLDSI, PRCM_PLLDSI_ENABLE); - /* Disable escapeclock */ - writel(PRCMU_DISABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV); - return 0; -} - u32 db8500_prcmu_read(unsigned int reg) { return readl(prcmu_base + reg); diff --git a/include/linux/mfd/db8500-prcmu.h b/include/linux/mfd/db8500-prcmu.h index 7d0c442e0c25..4b63d3ecdcff 100644 --- a/include/linux/mfd/db8500-prcmu.h +++ b/include/linux/mfd/db8500-prcmu.h @@ -525,8 +525,6 @@ u8 db8500_prcmu_get_power_state_result(void); void db8500_prcmu_enable_wakeups(u32 wakeups); int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state); int db8500_prcmu_request_clock(u8 clock, bool enable); -int db8500_prcmu_disable_dsipll(void); -int db8500_prcmu_enable_dsipll(void); void db8500_prcmu_config_abb_event_readout(u32 abb_events); void db8500_prcmu_get_abb_event_buffer(void __iomem **buf); int db8500_prcmu_config_esram0_deep_sleep(u8 state); @@ -681,16 +679,6 @@ static inline int db8500_prcmu_request_clock(u8 clock, bool enable) return 0; } -static inline int db8500_prcmu_disable_dsipll(void) -{ - return 0; -} - -static inline int db8500_prcmu_enable_dsipll(void) -{ - return 0; -} - static inline int db8500_prcmu_config_esram0_deep_sleep(u8 state) { return 0; diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h index 812b6c3c4ef6..e6ee2ec35de9 100644 --- a/include/linux/mfd/dbx500-prcmu.h +++ b/include/linux/mfd/dbx500-prcmu.h @@ -321,16 +321,6 @@ static inline bool prcmu_is_ac_wake_requested(void) return db8500_prcmu_is_ac_wake_requested(); } -static inline int prcmu_disable_dsipll(void) -{ - return db8500_prcmu_disable_dsipll(); -} - -static inline int prcmu_enable_dsipll(void) -{ - return db8500_prcmu_enable_dsipll(); -} - static inline int prcmu_config_esram0_deep_sleep(u8 state) { return db8500_prcmu_config_esram0_deep_sleep(state); @@ -506,16 +496,6 @@ static inline bool prcmu_is_ac_wake_requested(void) return false; } -static inline int prcmu_disable_dsipll(void) -{ - return 0; -} - -static inline int prcmu_enable_dsipll(void) -{ - return 0; -} - static inline int prcmu_config_esram0_deep_sleep(u8 state) { return 0; -- cgit v1.2.3-59-g8ed1b From 6a24f567af4accef6d73b0be407227c537b94a1f Mon Sep 17 00:00:00 2001 From: Orson Zhai Date: Tue, 21 Jan 2020 15:09:38 +0800 Subject: mfd: syscon: Add arguments support for syscon reference There are a lot of similar global registers being used across multiple SoCs from Unisoc. But most of these registers are assigned with different offset for different SoCs. It is hard to handle all of them in an all-in-one kernel image. Add a helper function to get regmap with arguments where we could put some extra information such as the offset value. Signed-off-by: Orson Zhai Tested-by: Baolin Wang Reviewed-by: Arnd Bergmann Signed-off-by: Lee Jones --- drivers/mfd/syscon.c | 29 +++++++++++++++++++++++++++++ include/linux/mfd/syscon.h | 14 ++++++++++++++ 2 files changed, 43 insertions(+) (limited to 'include/linux') diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c index 13626bb2d432..3a97816d0cba 100644 --- a/drivers/mfd/syscon.c +++ b/drivers/mfd/syscon.c @@ -224,6 +224,35 @@ struct regmap *syscon_regmap_lookup_by_phandle(struct device_node *np, } EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_phandle); +struct regmap *syscon_regmap_lookup_by_phandle_args(struct device_node *np, + const char *property, + int arg_count, + unsigned int *out_args) +{ + struct device_node *syscon_np; + struct of_phandle_args args; + struct regmap *regmap; + unsigned int index; + int rc; + + rc = of_parse_phandle_with_fixed_args(np, property, arg_count, + 0, &args); + if (rc) + return ERR_PTR(rc); + + syscon_np = args.np; + if (!syscon_np) + return ERR_PTR(-ENODEV); + + regmap = syscon_node_to_regmap(syscon_np); + for (index = 0; index < arg_count; index++) + out_args[index] = args.args[index]; + of_node_put(syscon_np); + + return regmap; +} +EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_phandle_args); + static int syscon_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; diff --git a/include/linux/mfd/syscon.h b/include/linux/mfd/syscon.h index 112dc66262cc..714cab1e09d3 100644 --- a/include/linux/mfd/syscon.h +++ b/include/linux/mfd/syscon.h @@ -23,6 +23,11 @@ extern struct regmap *syscon_regmap_lookup_by_compatible(const char *s); extern struct regmap *syscon_regmap_lookup_by_phandle( struct device_node *np, const char *property); +extern struct regmap *syscon_regmap_lookup_by_phandle_args( + struct device_node *np, + const char *property, + int arg_count, + unsigned int *out_args); #else static inline struct regmap *device_node_to_regmap(struct device_node *np) { @@ -45,6 +50,15 @@ static inline struct regmap *syscon_regmap_lookup_by_phandle( { return ERR_PTR(-ENOTSUPP); } + +static struct regmap *syscon_regmap_lookup_by_phandle_args( + struct device_node *np, + const char *property, + int arg_count, + unsigned int *out_args) +{ + return ERR_PTR(-ENOTSUPP); +} #endif #endif /* __LINUX_MFD_SYSCON_H__ */ -- cgit v1.2.3-59-g8ed1b From 6ac7e4d7ad70640310feedc2e5f1cb712685cb05 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 19 Dec 2019 10:31:44 +0000 Subject: mfd: wcd934x: Add support to wcd9340/wcd9341 codec Qualcomm WCD9340/WCD9341 Codec is a standalone Hi-Fi audio codec IC. This codec has integrated SoundWire controller, pin controller and interrupt controller. Signed-off-by: Srinivas Kandagatla Reviewed-by: Pierre-Louis Bossart Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 12 + drivers/mfd/Makefile | 1 + drivers/mfd/wcd934x.c | 306 ++++++++++++++++++++ include/linux/mfd/wcd934x/registers.h | 531 ++++++++++++++++++++++++++++++++++ include/linux/mfd/wcd934x/wcd934x.h | 31 ++ 5 files changed, 881 insertions(+) create mode 100644 drivers/mfd/wcd934x.c create mode 100644 include/linux/mfd/wcd934x/registers.h create mode 100644 include/linux/mfd/wcd934x/wcd934x.h (limited to 'include/linux') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 8f57b9cf9645..fa75de882737 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1976,6 +1976,18 @@ config MFD_STMFX additional drivers must be enabled in order to use the functionality of the device. +config MFD_WCD934X + tristate "Support for WCD9340/WCD9341 Codec" + depends on SLIMBUS + select REGMAP + select REGMAP_SLIMBUS + select REGMAP_IRQ + select MFD_CORE + help + Support for the Qualcomm WCD9340/WCD9341 Codec. + This driver provides common support WCD934x audio codec and its + associated Pin Controller, Soundwire Controller and Audio codec. + menu "Multimedia Capabilities Port drivers" depends on ARCH_SA1100 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 61b3093af39d..ed967af61438 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -58,6 +58,7 @@ endif ifeq ($(CONFIG_MFD_CS47L24),y) obj-$(CONFIG_MFD_ARIZONA) += cs47l24-tables.o endif +obj-$(CONFIG_MFD_WCD934X) += wcd934x.o obj-$(CONFIG_MFD_WM8400) += wm8400-core.o wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o wm831x-objs += wm831x-auxadc.o diff --git a/drivers/mfd/wcd934x.c b/drivers/mfd/wcd934x.c new file mode 100644 index 000000000000..90341f3c6810 --- /dev/null +++ b/drivers/mfd/wcd934x.c @@ -0,0 +1,306 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2019, Linaro Limited + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct mfd_cell wcd934x_devices[] = { + { + .name = "wcd934x-codec", + }, { + .name = "wcd934x-gpio", + .of_compatible = "qcom,wcd9340-gpio", + }, { + .name = "wcd934x-soundwire", + .of_compatible = "qcom,soundwire-v1.3.0", + }, +}; + +static const struct regmap_irq wcd934x_irqs[] = { + [WCD934X_IRQ_SLIMBUS] = { + .reg_offset = 0, + .mask = BIT(0), + .type = { + .type_reg_offset = 0, + .types_supported = IRQ_TYPE_EDGE_BOTH, + .type_reg_mask = BIT(0), + .type_level_low_val = BIT(0), + .type_level_high_val = BIT(0), + .type_falling_val = 0, + .type_rising_val = 0, + }, + }, + [WCD934X_IRQ_SOUNDWIRE] = { + .reg_offset = 2, + .mask = BIT(4), + .type = { + .type_reg_offset = 2, + .types_supported = IRQ_TYPE_EDGE_BOTH, + .type_reg_mask = BIT(4), + .type_level_low_val = BIT(4), + .type_level_high_val = BIT(4), + .type_falling_val = 0, + .type_rising_val = 0, + }, + }, +}; + +static const struct regmap_irq_chip wcd934x_regmap_irq_chip = { + .name = "wcd934x_irq", + .status_base = WCD934X_INTR_PIN1_STATUS0, + .mask_base = WCD934X_INTR_PIN1_MASK0, + .ack_base = WCD934X_INTR_PIN1_CLEAR0, + .type_base = WCD934X_INTR_LEVEL0, + .num_type_reg = 4, + .type_in_mask = false, + .num_regs = 4, + .irqs = wcd934x_irqs, + .num_irqs = ARRAY_SIZE(wcd934x_irqs), +}; + +static bool wcd934x_is_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case WCD934X_INTR_PIN1_STATUS0...WCD934X_INTR_PIN2_CLEAR3: + case WCD934X_SWR_AHB_BRIDGE_RD_DATA_0: + case WCD934X_SWR_AHB_BRIDGE_RD_DATA_1: + case WCD934X_SWR_AHB_BRIDGE_RD_DATA_2: + case WCD934X_SWR_AHB_BRIDGE_RD_DATA_3: + case WCD934X_SWR_AHB_BRIDGE_ACCESS_STATUS: + case WCD934X_ANA_MBHC_RESULT_3: + case WCD934X_ANA_MBHC_RESULT_2: + case WCD934X_ANA_MBHC_RESULT_1: + case WCD934X_ANA_MBHC_MECH: + case WCD934X_ANA_MBHC_ELECT: + case WCD934X_ANA_MBHC_ZDET: + case WCD934X_ANA_MICB2: + case WCD934X_ANA_RCO: + case WCD934X_ANA_BIAS: + return true; + default: + return false; + } +}; + +static const struct regmap_range_cfg wcd934x_ranges[] = { + { .name = "WCD934X", + .range_min = 0x0, + .range_max = WCD934X_MAX_REGISTER, + .selector_reg = WCD934X_SEL_REGISTER, + .selector_mask = WCD934X_SEL_MASK, + .selector_shift = WCD934X_SEL_SHIFT, + .window_start = WCD934X_WINDOW_START, + .window_len = WCD934X_WINDOW_LENGTH, + }, +}; + +static struct regmap_config wcd934x_regmap_config = { + .reg_bits = 16, + .val_bits = 8, + .cache_type = REGCACHE_RBTREE, + .max_register = 0xffff, + .can_multi_write = true, + .ranges = wcd934x_ranges, + .num_ranges = ARRAY_SIZE(wcd934x_ranges), + .volatile_reg = wcd934x_is_volatile_register, +}; + +static int wcd934x_bring_up(struct wcd934x_ddata *ddata) +{ + struct regmap *regmap = ddata->regmap; + u16 id_minor, id_major; + int ret; + + ret = regmap_bulk_read(regmap, WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE0, + (u8 *)&id_minor, sizeof(u16)); + if (ret) + return ret; + + ret = regmap_bulk_read(regmap, WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE2, + (u8 *)&id_major, sizeof(u16)); + if (ret) + return ret; + + dev_info(ddata->dev, "WCD934x chip id major 0x%x, minor 0x%x\n", + id_major, id_minor); + + regmap_write(regmap, WCD934X_CODEC_RPM_RST_CTL, 0x01); + regmap_write(regmap, WCD934X_SIDO_NEW_VOUT_A_STARTUP, 0x19); + regmap_write(regmap, WCD934X_SIDO_NEW_VOUT_D_STARTUP, 0x15); + /* Add 1msec delay for VOUT to settle */ + usleep_range(1000, 1100); + regmap_write(regmap, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x5); + regmap_write(regmap, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x7); + regmap_write(regmap, WCD934X_CODEC_RPM_RST_CTL, 0x3); + regmap_write(regmap, WCD934X_CODEC_RPM_RST_CTL, 0x7); + regmap_write(regmap, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x3); + + return 0; +} + +static int wcd934x_slim_status_up(struct slim_device *sdev) +{ + struct device *dev = &sdev->dev; + struct wcd934x_ddata *ddata; + int ret; + + ddata = dev_get_drvdata(dev); + + ddata->regmap = regmap_init_slimbus(sdev, &wcd934x_regmap_config); + if (IS_ERR(ddata->regmap)) { + dev_err(dev, "Error allocating slim regmap\n"); + return PTR_ERR(ddata->regmap); + } + + ret = wcd934x_bring_up(ddata); + if (ret) { + dev_err(dev, "Failed to bring up WCD934X: err = %d\n", ret); + return ret; + } + + ret = devm_regmap_add_irq_chip(dev, ddata->regmap, ddata->irq, + IRQF_TRIGGER_HIGH, 0, + &wcd934x_regmap_irq_chip, + &ddata->irq_data); + if (ret) { + dev_err(dev, "Failed to add IRQ chip: err = %d\n", ret); + return ret; + } + + ret = mfd_add_devices(dev, PLATFORM_DEVID_AUTO, wcd934x_devices, + ARRAY_SIZE(wcd934x_devices), NULL, 0, NULL); + if (ret) { + dev_err(dev, "Failed to add child devices: err = %d\n", + ret); + return ret; + } + + return ret; +} + +static int wcd934x_slim_status(struct slim_device *sdev, + enum slim_device_status status) +{ + switch (status) { + case SLIM_DEVICE_STATUS_UP: + return wcd934x_slim_status_up(sdev); + case SLIM_DEVICE_STATUS_DOWN: + mfd_remove_devices(&sdev->dev); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int wcd934x_slim_probe(struct slim_device *sdev) +{ + struct device *dev = &sdev->dev; + struct device_node *np = dev->of_node; + struct wcd934x_ddata *ddata; + int reset_gpio, ret; + + ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL); + if (!ddata) + return -ENOMEM; + + ddata->irq = of_irq_get(np, 0); + if (ddata->irq < 0) { + if (ddata->irq != -EPROBE_DEFER) + dev_err(ddata->dev, "Failed to get IRQ: err = %d\n", + ddata->irq); + return ddata->irq; + } + + reset_gpio = of_get_named_gpio(np, "reset-gpios", 0); + if (reset_gpio < 0) { + dev_err(dev, "Failed to get reset gpio: err = %d\n", + reset_gpio); + return reset_gpio; + } + + ddata->extclk = devm_clk_get(dev, "extclk"); + if (IS_ERR(ddata->extclk)) { + dev_err(dev, "Failed to get extclk"); + return PTR_ERR(ddata->extclk); + } + + ddata->supplies[0].supply = "vdd-buck"; + ddata->supplies[1].supply = "vdd-buck-sido"; + ddata->supplies[2].supply = "vdd-tx"; + ddata->supplies[3].supply = "vdd-rx"; + ddata->supplies[4].supply = "vdd-io"; + + ret = regulator_bulk_get(dev, WCD934X_MAX_SUPPLY, ddata->supplies); + if (ret) { + dev_err(dev, "Failed to get supplies: err = %d\n", ret); + return ret; + } + + ret = regulator_bulk_enable(WCD934X_MAX_SUPPLY, ddata->supplies); + if (ret) { + dev_err(dev, "Failed to enable supplies: err = %d\n", ret); + return ret; + } + + /* + * For WCD934X, it takes about 600us for the Vout_A and + * Vout_D to be ready after BUCK_SIDO is powered up. + * SYS_RST_N shouldn't be pulled high during this time + */ + usleep_range(600, 650); + gpio_direction_output(reset_gpio, 0); + msleep(20); + gpio_set_value(reset_gpio, 1); + msleep(20); + + ddata->dev = dev; + dev_set_drvdata(dev, ddata); + + return 0; +} + +static void wcd934x_slim_remove(struct slim_device *sdev) +{ + struct wcd934x_ddata *ddata = dev_get_drvdata(&sdev->dev); + + regulator_bulk_disable(WCD934X_MAX_SUPPLY, ddata->supplies); + mfd_remove_devices(&sdev->dev); + kfree(ddata); +} + +static const struct slim_device_id wcd934x_slim_id[] = { + { SLIM_MANF_ID_QCOM, SLIM_PROD_CODE_WCD9340, + SLIM_DEV_IDX_WCD9340, SLIM_DEV_INSTANCE_ID_WCD9340 }, + {} +}; + +static struct slim_driver wcd934x_slim_driver = { + .driver = { + .name = "wcd934x-slim", + }, + .probe = wcd934x_slim_probe, + .remove = wcd934x_slim_remove, + .device_status = wcd934x_slim_status, + .id_table = wcd934x_slim_id, +}; + +module_slim_driver(wcd934x_slim_driver); +MODULE_DESCRIPTION("WCD934X slim driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("slim:217:250:*"); +MODULE_AUTHOR("Srinivas Kandagatla "); diff --git a/include/linux/mfd/wcd934x/registers.h b/include/linux/mfd/wcd934x/registers.h new file mode 100644 index 000000000000..bb8d2e276668 --- /dev/null +++ b/include/linux/mfd/wcd934x/registers.h @@ -0,0 +1,531 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _WCD934X_REGISTERS_H +#define _WCD934X_REGISTERS_H + +#define WCD934X_CODEC_RPM_CLK_GATE 0x0002 +#define WCD934X_CODEC_RPM_CLK_GATE_MASK GENMASK(1, 0) +#define WCD934X_CODEC_RPM_CLK_MCLK_CFG 0x0003 +#define WCD934X_CODEC_RPM_CLK_MCLK_CFG_9P6MHZ BIT(0) +#define WCD934X_CODEC_RPM_CLK_MCLK_CFG_12P288MHZ BIT(1) +#define WCD934X_CODEC_RPM_CLK_MCLK_CFG_MCLK_MASK GENMASK(1, 0) +#define WCD934X_CODEC_RPM_RST_CTL 0x0009 +#define WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL 0x0011 +#define WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE0 0x0021 +#define WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE2 0x0023 +#define WCD934X_CHIP_TIER_CTRL_EFUSE_CTL 0x0025 +#define WCD934X_EFUSE_SENSE_STATE_MASK GENMASK(4, 1) +#define WCD934X_EFUSE_SENSE_STATE_DEF 0x10 +#define WCD934X_EFUSE_SENSE_EN_MASK BIT(0) +#define WCD934X_EFUSE_SENSE_ENABLE BIT(0) +#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT14 0x0037 +#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT15 0x0038 +#define WCD934X_CHIP_TIER_CTRL_EFUSE_STATUS 0x0039 +#define WCD934X_DATA_HUB_SB_TX10_INP_CFG 0x006b +#define WCD934X_DATA_HUB_SB_TX11_INP_CFG 0x006c +#define WCD934X_DATA_HUB_SB_TX13_INP_CFG 0x006e +#define WCD934X_CPE_FLL_CONFIG_CTL_2 0x0111 +#define WCD934X_CPE_SS_CPARMAD_BUFRDY_INT_PERIOD 0x0213 +#define WCD934X_CPE_SS_SVA_CFG 0x0214 +#define WCD934X_CPE_SS_DMIC0_CTL 0x0218 +#define WCD934X_CPE_SS_DMIC1_CTL 0x0219 +#define WCD934X_DMIC_RATE_MASK GENMASK(3, 1) +#define WCD934X_CPE_SS_DMIC2_CTL 0x021a +#define WCD934X_CPE_SS_DMIC_CFG 0x021b +#define WCD934X_CPE_SS_DMIC_CFG 0x021b +#define WCD934X_CPE_SS_CPAR_CFG 0x021c +#define WCD934X_INTR_PIN1_MASK0 0x0409 +#define WCD934X_INTR_PIN1_STATUS0 0x0411 +#define WCD934X_INTR_PIN1_CLEAR0 0x0419 +#define WCD934X_INTR_PIN2_CLEAR3 0x0434 +#define WCD934X_INTR_LEVEL0 0x0461 +/* INTR_REG 0 */ +#define WCD934X_IRQ_SLIMBUS 0 +#define WCD934X_IRQ_MISC 1 +#define WCD934X_IRQ_HPH_PA_OCPL_FAULT 2 +#define WCD934X_IRQ_HPH_PA_OCPR_FAULT 3 +#define WCD934X_IRQ_EAR_PA_OCP_FAULT 4 +#define WCD934X_IRQ_HPH_PA_CNPL_COMPLETE 5 +#define WCD934X_IRQ_HPH_PA_CNPR_COMPLETE 6 +#define WCD934X_IRQ_EAR_PA_CNP_COMPLETE 7 +/* INTR_REG 1 */ +#define WCD934X_IRQ_MBHC_SW_DET 8 +#define WCD934X_IRQ_MBHC_ELECT_INS_REM_DET 9 +#define WCD934X_IRQ_MBHC_BUTTON_PRESS_DET 10 +#define WCD934X_IRQ_MBHC_BUTTON_RELEASE_DET 11 +#define WCD934X_IRQ_MBHC_ELECT_INS_REM_LEG_DET 12 +#define WCD934X_IRQ_RESERVED_0 13 +#define WCD934X_IRQ_RESERVED_1 14 +#define WCD934X_IRQ_RESERVED_2 15 +/* INTR_REG 2 */ +#define WCD934X_IRQ_LINE_PA1_CNP_COMPLETE 16 +#define WCD934X_IRQ_LINE_PA2_CNP_COMPLETE 17 +#define WCD934X_IRQ_SLNQ_ANALOG_ERROR 18 +#define WCD934X_IRQ_RESERVED_3 19 +#define WCD934X_IRQ_SOUNDWIRE 20 +#define WCD934X_IRQ_VDD_DIG_RAMP_COMPLETE 21 +#define WCD934X_IRQ_RCO_ERROR 22 +#define WCD934X_IRQ_CPE_ERROR 23 +/* INTR_REG 3 */ +#define WCD934X_IRQ_MAD_AUDIO 24 +#define WCD934X_IRQ_MAD_BEACON 25 +#define WCD934X_IRQ_MAD_ULTRASOUND 26 +#define WCD934X_IRQ_VBAT_ATTACK 27 +#define WCD934X_IRQ_VBAT_RESTORE 28 +#define WCD934X_IRQ_CPE1_INTR 29 +#define WCD934X_IRQ_RESERVED_4 30 +#define WCD934X_IRQ_SLNQ_DIGITAL 31 +#define WCD934X_NUM_IRQS 32 +#define WCD934X_ANA_BIAS 0x0601 +#define WCD934X_ANA_BIAS_EN_MASK BIT(7) +#define WCD934X_ANA_BIAS_EN BIT(7) +#define WCD934X_ANA_PRECHRG_EN_MASK BIT(6) +#define WCD934X_ANA_PRECHRG_EN BIT(6) +#define WCD934X_ANA_PRECHRG_MODE_MASK BIT(5) +#define WCD934X_ANA_PRECHRG_MODE_AUTO BIT(5) +#define WCD934X_ANA_RCO 0x0603 +#define WCD934X_ANA_RCO_BG_EN_MASK BIT(7) +#define WCD934X_ANA_RCO_BG_ENABLE BIT(7) +#define WCD934X_ANA_BUCK_CTL 0x0606 +#define WCD934X_ANA_BUCK_HI_ACCU_PRE_ENX_MASK GENMASK(1, 0) +#define WCD934X_ANA_BUCK_PRE_EN2_MASK BIT(0) +#define WCD934X_ANA_BUCK_PRE_EN2_ENABLE BIT(0) +#define WCD934X_ANA_BUCK_PRE_EN1_MASK BIT(1) +#define WCD934X_ANA_BUCK_PRE_EN1_ENABLE BIT(1) +#define WCD934X_ANA_BUCK_HI_ACCU_EN_MASK BIT(2) +#define WCD934X_ANA_BUCK_HI_ACCU_ENABLE BIT(2) +#define WCD934X_ANA_RX_SUPPLIES 0x0608 +#define WCD934X_ANA_HPH 0x0609 +#define WCD934X_ANA_EAR 0x060a +#define WCD934X_ANA_LO_1_2 0x060b +#define WCD934X_ANA_AMIC1 0x060e +#define WCD934X_ANA_AMIC2 0x060f +#define WCD934X_ANA_AMIC3 0x0610 +#define WCD934X_ANA_AMIC4 0x0611 +#define WCD934X_ANA_MBHC_MECH 0x0614 +#define WCD934X_ANA_MBHC_ELECT 0x0615 +#define WCD934X_ANA_MBHC_ZDET 0x0616 +#define WCD934X_ANA_MBHC_RESULT_1 0x0617 +#define WCD934X_ANA_MBHC_RESULT_2 0x0618 +#define WCD934X_ANA_MBHC_RESULT_3 0x0619 +#define WCD934X_ANA_MICB1 0x0622 +#define WCD934X_MICB_VAL_MASK GENMASK(5, 0) +#define WCD934X_ANA_MICB_EN_MASK GENMASK(7, 6) +#define WCD934X_ANA_MICB_PULL_UP 0x80 +#define WCD934X_ANA_MICB_ENABLE 0x40 +#define WCD934X_ANA_MICB_DISABLE 0x0 +#define WCD934X_ANA_MICB2 0x0623 +#define WCD934X_ANA_MICB3 0x0625 +#define WCD934X_ANA_MICB4 0x0626 +#define WCD934X_BIAS_VBG_FINE_ADJ 0x0629 +#define WCD934X_MICB1_TEST_CTL_1 0x066b +#define WCD934X_MICB1_TEST_CTL_2 0x066c +#define WCD934X_MICB2_TEST_CTL_1 0x066e +#define WCD934X_MICB3_TEST_CTL_1 0x0671 +#define WCD934X_MICB4_TEST_CTL_1 0x0674 +#define WCD934X_CLASSH_MODE_1 0x0697 +#define WCD934X_CLASSH_MODE_2 0x0698 +#define WCD934X_CLASSH_MODE_3 0x0699 +#define WCD934X_CLASSH_CTRL_VCL_1 0x069a +#define WCD934X_CLASSH_CTRL_VCL_2 0x069b +#define WCD934X_CLASSH_CTRL_CCL_1 0x069c +#define WCD934X_CLASSH_CTRL_CCL_2 0x069d +#define WCD934X_CLASSH_CTRL_CCL_3 0x069e +#define WCD934X_CLASSH_CTRL_CCL_4 0x069f +#define WCD934X_CLASSH_CTRL_CCL_5 0x06a0 +#define WCD934X_CLASSH_BUCK_TMUX_A_D 0x06a1 +#define WCD934X_CLASSH_BUCK_SW_DRV_CNTL 0x06a2 +#define WCD934X_RX_OCP_CTL 0x06b6 +#define WCD934X_RX_OCP_COUNT 0x06b7 +#define WCD934X_HPH_CNP_EN 0x06cb +#define WCD934X_HPH_CNP_WG_CTL 0x06cc +#define WCD934X_HPH_GM3_BOOST_EN_MASK BIT(7) +#define WCD934X_HPH_GM3_BOOST_ENABLE BIT(7) +#define WCD934X_HPH_OCP_CTL 0x06ce +#define WCD934X_HPH_L_EN 0x06d3 +#define WCD934X_HPH_GAIN_SRC_SEL_MASK BIT(5) +#define WCD934X_HPH_GAIN_SRC_SEL_COMPANDER 0 +#define WCD934X_HPH_GAIN_SRC_SEL_REGISTER BIT(5) +#define WCD934X_HPH_L_TEST 0x06d4 +#define WCD934X_HPH_R_EN 0x06d6 +#define WCD934X_HPH_R_TEST 0x06d7 +#define WCD934X_HPH_OCP_DET_MASK BIT(0) +#define WCD934X_HPH_OCP_DET_ENABLE BIT(0) +#define WCD934X_HPH_OCP_DET_DISABLE 0 +#define WCD934X_DIFF_LO_LO2_COMPANDER 0x06ea +#define WCD934X_DIFF_LO_LO1_COMPANDER 0x06eb +#define WCD934X_CLK_SYS_MCLK_PRG 0x0711 +#define WCD934X_EXT_CLK_BUF_EN_MASK BIT(7) +#define WCD934X_EXT_CLK_BUF_EN BIT(7) +#define WCD934X_EXT_CLK_DIV_RATIO_MASK GENMASK(5, 4) +#define WCD934X_EXT_CLK_DIV_BY_2 0x10 +#define WCD934X_MCLK_SRC_MASK BIT(1) +#define WCD934X_MCLK_SRC_EXT_CLK 0 +#define WCD934X_MCLK_SRC_MASK BIT(1) +#define WCD934X_MCLK_EN_MASK BIT(0) +#define WCD934X_MCLK_EN BIT(0) +#define WCD934X_CLK_SYS_MCLK2_PRG1 0x0712 +#define WCD934X_CLK_SYS_MCLK2_PRG2 0x0713 +#define WCD934X_SIDO_NEW_VOUT_A_STARTUP 0x071b +#define WCD934X_SIDO_NEW_VOUT_D_STARTUP 0x071c +#define WCD934X_SIDO_NEW_VOUT_D_FREQ1 0x071d +#define WCD934X_SIDO_NEW_VOUT_D_FREQ2 0x071e +#define WCD934X_SIDO_RIPPLE_FREQ_EN_MASK BIT(0) +#define WCD934X_SIDO_RIPPLE_FREQ_ENABLE BIT(0) +#define WCD934X_MBHC_NEW_CTL_2 0x0721 +#define WCD934X_TX_NEW_AMIC_4_5_SEL 0x0727 +#define WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_L 0x0733 +#define WCD934X_HPH_NEW_INT_RDAC_OVERRIDE_CTL 0x0735 +#define WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_R 0x0736 +#define WCD934X_HPH_NEW_INT_HPH_TIMER1 0x073a +#define WCD934X_HPH_AUTOCHOP_TIMER_EN_MASK BIT(1) +#define WCD934X_HPH_AUTOCHOP_TIMER_ENABLE BIT(1) +#define WCD934X_CDC_TX0_TX_PATH_CTL 0x0a31 +#define WCD934X_CDC_TX_PATH_CTL_PCM_RATE_MASK GENMASK(3, 0) +#define WCD934X_CDC_TX_PATH_CTL(dec) (0xa31 + dec * 0x10) +#define WCD934X_CDC_TX0_TX_PATH_CFG0 0x0a32 +#define WCD934X_CDC_TX0_TX_PATH_CFG1 0x0a33 +#define WCD934X_CDC_TX0_TX_VOL_CTL 0x0a34 +#define WCD934X_CDC_TX0_TX_PATH_192_CTL 0x0a35 +#define WCD934X_CDC_TX0_TX_PATH_192_CFG 0x0a36 +#define WCD934X_CDC_TX0_TX_PATH_SEC2 0x0a39 +#define WCD934X_HPH_CUTOFF_FREQ_CHANGE_REQ_MASK BIT(1) +#define WCD934X_HPH_CUTOFF_FREQ_CHANGE_REQ BIT(1) +#define WCD934X_CDC_TX1_TX_PATH_CTL 0x0a41 +#define WCD934X_CDC_TX1_TX_PATH_CFG0 0x0a42 +#define WCD934X_CDC_TX1_TX_PATH_CFG1 0x0a43 +#define WCD934X_CDC_TX1_TX_VOL_CTL 0x0a44 +#define WCD934X_CDC_TX2_TX_PATH_CTL 0x0a51 +#define WCD934X_CDC_TX2_TX_PATH_CFG0 0x0a52 +#define WCD934X_CDC_TX2_TX_PATH_CFG1 0x0a53 +#define WCD934X_CDC_TX2_TX_VOL_CTL 0x0a54 +#define WCD934X_CDC_TX3_TX_PATH_CTL 0x0a61 +#define WCD934X_CDC_TX3_TX_PATH_CFG0 0x0a62 +#define WCD934X_CDC_TX3_TX_PATH_CFG1 0x0a63 +#define WCD934X_CDC_TX3_TX_VOL_CTL 0x0a64 +#define WCD934X_CDC_TX3_TX_PATH_192_CTL 0x0a65 +#define WCD934X_CDC_TX3_TX_PATH_192_CFG 0x0a66 +#define WCD934X_CDC_TX4_TX_PATH_CTL 0x0a71 +#define WCD934X_CDC_TX4_TX_PATH_CFG0 0x0a72 +#define WCD934X_CDC_TX4_TX_PATH_CFG1 0x0a73 +#define WCD934X_CDC_TX4_TX_VOL_CTL 0x0a74 +#define WCD934X_CDC_TX4_TX_PATH_192_CTL 0x0a75 +#define WCD934X_CDC_TX4_TX_PATH_192_CFG 0x0a76 +#define WCD934X_CDC_TX5_TX_PATH_CTL 0x0a81 +#define WCD934X_CDC_TX5_TX_PATH_CFG0 0x0a82 +#define WCD934X_CDC_TX5_TX_PATH_CFG1 0x0a83 +#define WCD934X_CDC_TX5_TX_VOL_CTL 0x0a84 +#define WCD934X_CDC_TX5_TX_PATH_192_CTL 0x0a85 +#define WCD934X_CDC_TX5_TX_PATH_192_CFG 0x0a86 +#define WCD934X_CDC_TX6_TX_PATH_CTL 0x0a91 +#define WCD934X_CDC_TX6_TX_PATH_CFG0 0x0a92 +#define WCD934X_CDC_TX6_TX_PATH_CFG1 0x0a93 +#define WCD934X_CDC_TX6_TX_VOL_CTL 0x0a94 +#define WCD934X_CDC_TX6_TX_PATH_192_CTL 0x0a95 +#define WCD934X_CDC_TX6_TX_PATH_192_CFG 0x0a96 +#define WCD934X_CDC_TX7_TX_PATH_CTL 0x0aa1 +#define WCD934X_CDC_TX7_TX_PATH_CFG0 0x0aa2 +#define WCD934X_CDC_TX7_TX_PATH_CFG1 0x0aa3 +#define WCD934X_CDC_TX7_TX_VOL_CTL 0x0aa4 +#define WCD934X_CDC_TX7_TX_PATH_192_CTL 0x0aa5 +#define WCD934X_CDC_TX7_TX_PATH_192_CFG 0x0aa6 +#define WCD934X_CDC_TX8_TX_PATH_CTL 0x0ab1 +#define WCD934X_CDC_TX8_TX_PATH_CFG0 0x0ab2 +#define WCD934X_CDC_TX8_TX_PATH_CFG1 0x0ab3 +#define WCD934X_CDC_TX8_TX_VOL_CTL 0x0ab4 +#define WCD934X_CDC_TX8_TX_PATH_192_CTL 0x0ab5 +#define WCD934X_CDC_TX8_TX_PATH_192_CFG 0x0ab6 +#define WCD934X_CDC_TX9_SPKR_PROT_PATH_CFG0 0x0ac3 +#define WCD934X_CDC_TX10_SPKR_PROT_PATH_CFG0 0x0ac7 +#define WCD934X_CDC_TX11_SPKR_PROT_PATH_CFG0 0x0acb +#define WCD934X_CDC_TX12_SPKR_PROT_PATH_CFG0 0x0acf +#define WCD934X_CDC_COMPANDER1_CTL0 0x0b01 +#define WCD934X_COMP_CLK_EN_MASK BIT(0) +#define WCD934X_COMP_CLK_ENABLE BIT(0) +#define WCD934X_COMP_SOFT_RST_MASK BIT(1) +#define WCD934X_COMP_SOFT_RST_ENABLE BIT(1) +#define WCD934X_COMP_HALT_MASK BIT(2) +#define WCD934X_COMP_HALT BIT(2) +#define WCD934X_COMP_SOFT_RST_DISABLE 0 +#define WCD934X_CDC_COMPANDER1_CTL7 0x0b08 +#define WCD934X_HPH_LOW_PWR_MODE_EN_MASK BIT(5) +#define WCD934X_CDC_COMPANDER2_CTL7 0x0b10 +#define WCD934X_CDC_COMPANDER7_CTL3 0x0b34 +#define WCD934X_CDC_COMPANDER7_CTL7 0x0b38 +#define WCD934X_CDC_COMPANDER8_CTL3 0x0b3c +#define WCD934X_CDC_COMPANDER8_CTL7 0x0b40 +#define WCD934X_CDC_RX0_RX_PATH_CTL 0x0b41 +#define WCD934X_CDC_RX_PGA_MUTE_EN_MASK BIT(4) +#define WCD934X_CDC_RX_PGA_MUTE_ENABLE BIT(4) +#define WCD934X_CDC_RX_PGA_MUTE_DISABLE 0 +#define WCD934X_RX_CLK_EN_MASK BIT(5) +#define WCD934X_RX_CLK_ENABLE BIT(5) +#define WCD934X_RX_RESET_MASK BIT(6) +#define WCD934X_RX_RESET_ENABLE BIT(6) +#define WCD934X_RX_RESET_DISABLE 0 +#define WCD934X_RX_PCM_RATE_MASK GENMASK(3, 0) +#define WCD934X_RX_PCM_RATE_F_48K 0x04 +#define WCD934X_CDC_RX_PATH_CTL(rx) (0xb41 + rx * 0x14) +#define WCD934X_CDC_MIX_PCM_RATE_MASK GENMASK(3, 0) +#define WCD934X_CDC_RX0_RX_PATH_CFG0 0x0b42 +#define WCD934X_RX_DLY_ZN_EN_MASK BIT(3) +#define WCD934X_RX_DLY_ZN_ENABLE BIT(3) +#define WCD934X_RX_DLY_ZN_DISABLE 0 +#define WCD934X_CDC_RX0_RX_PATH_CFG1 0x0b43 +#define WCD934X_CDC_RX0_RX_PATH_CFG2 0x0b44 +#define WCD934X_CDC_RX0_RX_VOL_CTL 0x0b45 +#define WCD934X_CDC_RX0_RX_PATH_MIX_CTL 0x0b46 +#define WCD934X_CDC_RX_MIX_CLK_EN_MASK BIT(5) +#define WCD934X_CDC_RX_MIX_CLK_ENABLE BIT(5) +#define WCD934X_CDC_RX_PATH_MIX_CTL(rx) (0xb46 + rx * 0x14) +#define WCD934X_CDC_RX0_RX_PATH_MIX_CFG 0x0b47 +#define WCD934X_CDC_RX0_RX_VOL_MIX_CTL 0x0b48 +#define WCD934X_CDC_RX0_RX_PATH_SEC0 0x0b49 +#define WCD934X_CDC_RX0_RX_PATH_DSMDEM_CTL 0x0b53 +#define WCD934X_CDC_RX1_RX_PATH_CTL 0x0b55 +#define WCD934X_RX_PATH_PGA_MUTE_EN_MASK BIT(4) +#define WCD934X_RX_PATH_PGA_MUTE_ENABLE BIT(4) +#define WCD934X_CDC_RX_PATH_PGA_MUTE_DISABLE 0 +#define WCD934X_CDC_RX_PATH_CLK_EN_MASK BIT(5) +#define WCD934X_CDC_RX_PATH_CLK_ENABLE BIT(5) +#define WCD934X_CDC_RX_PATH_CLK_DISABLE 0 +#define WCD934X_CDC_RX1_RX_PATH_CFG0 0x0b56 +#define WCD934X_HPH_CMP_EN_MASK BIT(1) +#define WCD934X_HPH_CMP_ENABLE BIT(1) +#define WCD934X_HPH_CMP_DISABLE 0 +#define WCD934X_CDC_RX1_RX_PATH_CFG2 0x0b58 +#define WCD934X_CDC_RX1_RX_VOL_CTL 0x0b59 +#define WCD934X_CDC_RX1_RX_PATH_MIX_CTL 0x0b5a +#define WCD934X_CDC_RX1_RX_PATH_MIX_CFG 0x0b5b +#define WCD934X_CDC_RX1_RX_VOL_MIX_CTL 0x0b5c +#define WCD934X_CDC_RX1_RX_PATH_SEC0 0x0b5d +#define WCD934X_CDC_RX1_RX_PATH_SEC3 0x0b60 +#define WCD934X_CDC_RX_PATH_SEC_HD2_ALPHA_MASK GENMASK(5, 2) +#define WCD934X_CDC_RX_PATH_SEC_HD2_ALPHA_0P3125 0x14 +#define WCD934X_CDC_RX_PATH_SEC_HD2_ALPHA_0P0000 0 +#define WCD934X_CDC_RX1_RX_PATH_DSMDEM_CTL 0x0b67 +#define WCD934X_CDC_RX2_RX_PATH_CTL 0x0b69 +#define WCD934X_CDC_RX2_RX_PATH_CFG0 0x0b6a +#define WCD934X_CDC_RX_PATH_CFG_HD2_EN_MASK BIT(2) +#define WCD934X_CDC_RX_PATH_CFG_HD2_ENABLE BIT(2) +#define WCD934X_CDC_RX_PATH_CFG_HD2_DISABLE 0 +#define WCD934X_CDC_RX2_RX_PATH_CFG2 0x0b6c +#define WCD934X_CDC_RX2_RX_VOL_CTL 0x0b6d +#define WCD934X_CDC_RX2_RX_PATH_MIX_CTL 0x0b6e +#define WCD934X_CDC_RX2_RX_PATH_MIX_CFG 0x0b6f +#define WCD934X_CDC_RX2_RX_VOL_MIX_CTL 0x0b70 +#define WCD934X_CDC_RX2_RX_PATH_SEC0 0x0b71 +#define WCD934X_CDC_RX2_RX_PATH_SEC3 0x0b74 +#define WCD934X_CDC_RX2_RX_PATH_DSMDEM_CTL 0x0b7b +#define WCD934X_CDC_RX3_RX_PATH_CTL 0x0b7d +#define WCD934X_CDC_RX3_RX_PATH_CFG0 0x0b6e +#define WCD934X_CDC_RX3_RX_PATH_CFG2 0x0b80 +#define WCD934X_CDC_RX3_RX_VOL_CTL 0x0b81 +#define WCD934X_CDC_RX3_RX_PATH_MIX_CTL 0x0b82 +#define WCD934X_CDC_RX3_RX_PATH_MIX_CFG 0x0b83 +#define WCD934X_CDC_RX3_RX_VOL_MIX_CTL 0x0b84 +#define WCD934X_CDC_RX3_RX_PATH_SEC0 0x0b85 +#define WCD934X_CDC_RX3_RX_PATH_DSMDEM_CTL 0x0b8f +#define WCD934X_CDC_RX4_RX_PATH_CTL 0x0b91 +#define WCD934X_CDC_RX4_RX_PATH_CFG0 0x0b92 +#define WCD934X_CDC_RX4_RX_PATH_CFG2 0x0b94 +#define WCD934X_CDC_RX4_RX_VOL_CTL 0x0b95 +#define WCD934X_CDC_RX4_RX_PATH_MIX_CTL 0x0b96 +#define WCD934X_CDC_RX4_RX_PATH_MIX_CFG 0x0b97 +#define WCD934X_CDC_RX4_RX_VOL_MIX_CTL 0x0b98 +#define WCD934X_CDC_RX4_RX_PATH_SEC0 0x0b99 +#define WCD934X_CDC_RX4_RX_PATH_DSMDEM_CTL 0x0ba3 +#define WCD934X_CDC_RX7_RX_PATH_CTL 0x0bcd +#define WCD934X_CDC_RX7_RX_PATH_CFG0 0x0bce +#define WCD934X_CDC_RX7_RX_PATH_CFG1 0x0bcf +#define WCD934X_CDC_RX7_RX_PATH_CFG2 0x0bd0 +#define WCD934X_CDC_RX7_RX_VOL_CTL 0x0bd1 +#define WCD934X_CDC_RX7_RX_PATH_MIX_CTL 0x0bd2 +#define WCD934X_CDC_RX7_RX_PATH_MIX_CFG 0x0bd3 +#define WCD934X_CDC_RX7_RX_VOL_MIX_CTL 0x0bd4 +#define WCD934X_CDC_RX7_RX_PATH_SEC1 0x0bd6 +#define WCD934X_CDC_RX7_RX_PATH_MIX_SEC0 0x0bdd +#define WCD934X_CDC_RX7_RX_PATH_DSMDEM_CTL 0x0bdf +#define WCD934X_CDC_RX8_RX_PATH_CTL 0x0be1 +#define WCD934X_CDC_RX8_RX_PATH_CFG0 0x0be2 +#define WCD934X_CDC_RX8_RX_PATH_CFG1 0x0be3 +#define WCD934X_RX_SMART_BOOST_EN_MASK BIT(0) +#define WCD934X_RX_SMART_BOOST_ENABLE BIT(0) +#define WCD934X_RX_SMART_BOOST_DISABLE 0 +#define WCD934X_CDC_RX8_RX_PATH_CFG2 0x0be4 +#define WCD934X_CDC_RX8_RX_VOL_CTL 0x0be5 +#define WCD934X_CDC_RX8_RX_PATH_MIX_CTL 0x0be6 +#define WCD934X_CDC_RX8_RX_PATH_MIX_CFG 0x0be7 +#define WCD934X_CDC_RX8_RX_VOL_MIX_CTL 0x0be8 +#define WCD934X_CDC_RX8_RX_PATH_SEC1 0x0bea +#define WCD934X_CDC_RX8_RX_PATH_MIX_SEC0 0x0bf1 +#define WCD934X_CDC_RX8_RX_PATH_DSMDEM_CTL 0x0bf3 +#define WCD934X_CDC_CLSH_DECAY_CTRL 0x0c03 +#define WCD934X_CDC_CLSH_K2_MSB 0x0c0a +#define WCD934X_CDC_CLSH_K2_LSB 0x0c0b +#define WCD934X_CDC_CLSH_TEST0 0x0c0f +#define WCD934X_CDC_BOOST0_BOOST_PATH_CTL 0x0c19 +#define WCD934X_BOOST_PATH_CLK_EN_MASK BIT(4) +#define WCD934X_BOOST_PATH_CLK_ENABLE BIT(4) +#define WCD934X_BOOST_PATH_CLK_DISABLE 0 +#define WCD934X_CDC_BOOST0_BOOST_CTL 0x0c1a +#define WCD934X_CDC_BOOST0_BOOST_CFG1 0x0c1b +#define WCD934X_CDC_BOOST0_BOOST_CFG2 0x0c1c +#define WCD934X_CDC_BOOST1_BOOST_PATH_CTL 0x0c21 +#define WCD934X_CDC_BOOST1_BOOST_CTL 0x0c22 +#define WCD934X_CDC_BOOST1_BOOST_CFG1 0x0c23 +#define WCD934X_CDC_BOOST1_BOOST_CFG2 0x0c24 +#define WCD934X_SWR_AHB_BRIDGE_RD_DATA_0 0x0c91 +#define WCD934X_SWR_AHB_BRIDGE_RD_DATA_1 0x0c92 +#define WCD934X_SWR_AHB_BRIDGE_RD_DATA_2 0x0c93 +#define WCD934X_SWR_AHB_BRIDGE_RD_DATA_3 0x0c94 +#define WCD934X_SWR_AHB_BRIDGE_ACCESS_STATUS 0x0c96 +#define WCD934X_CDC_SIDETONE_SRC0_ST_SRC_PATH_CTL 0x0cb5 +#define WCD934X_CDC_SIDETONE_SRC1_ST_SRC_PATH_CTL 0x0cb9 +#define WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG0 0x0d01 +#define WCD934X_CDC_RX_INP_MUX_RX_INT_CFG0(i) (0xd01 + i * 0x2) +#define WCD934X_CDC_RX_INP_MUX_RX_INT_SEL_MASK GENMASK(3, 0) +#define WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG1 0x0d02 +#define WCD934X_CDC_RX_INP_MUX_RX_INT_CFG1(i) (0xd02 + i * 0x2) +#define WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG0 0x0d03 +#define WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG1 0x0d04 +#define WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG0 0x0d05 +#define WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG1 0x0d06 +#define WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG0 0x0d07 +#define WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG1 0x0d08 +#define WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG0 0x0d09 +#define WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG1 0x0d0a +#define WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG0 0x0d0f +#define WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG1 0x0d10 +#define WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG0 0x0d11 +#define WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG1 0x0d12 +#define WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG0 0x0d13 +#define WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG1 0x0d14 +#define WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG2 0x0d15 +#define WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG3 0x0d16 +#define WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG4 0x0d17 +#define WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0 0x0d18 +#define WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG1 0x0d19 +#define WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0 0x0d1d +#define WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1 0x0d1e +#define WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG0 0x0d1f +#define WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1 0x0d20 +#define WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG0 0x0d21 +#define WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG1 0x0d22 +#define WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG0 0x0d23 +#define WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1 0x0d25 +#define WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 0x0d26 +#define WCD934X_CDC_TX_INP_MUX_ADC_MUX5_CFG0 0x0d27 +#define WCD934X_CDC_TX_INP_MUX_ADC_MUX6_CFG0 0x0d28 +#define WCD934X_CDC_TX_INP_MUX_ADC_MUX7_CFG0 0x0d29 +#define WCD934X_CDC_TX_INP_MUX_ADC_MUX8_CFG0 0x0d2a +#define WCD934X_CDC_TX_INP_MUX_ADC_MUX10_CFG0 0x0d2b +#define WCD934X_CDC_TX_INP_MUX_ADC_MUX11_CFG0 0x0d2c +#define WCD934X_CDC_TX_INP_MUX_ADC_MUX12_CFG0 0x0d2d +#define WCD934X_CDC_TX_INP_MUX_ADC_MUX13_CFG0 0x0d2e +#define WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG0 0x0d31 +#define WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG1 0x0d32 +#define WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG2 0x0d33 +#define WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG3 0x0d34 +#define WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG0 0x0d35 +#define WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG1 0x0d36 +#define WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG2 0x0d37 +#define WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG3 0x0d38 +#define WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0 0x0d3a +#define WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1 0x0d3b +#define WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2 0x0d3c +#define WCD934X_CDC_IF_ROUTER_TX_MUX_CFG3 0x0d3d +#define WCD934X_CDC_CLK_RST_CTRL_MCLK_CONTROL 0x0d41 +#define WCD934X_CDC_MCLK_EN_MASK BIT(0) +#define WCD934X_CDC_MCLK_EN_ENABLE BIT(0) +#define WCD934X_CDC_CLK_RST_CTRL_FS_CNT_CONTROL 0x0d42 +#define WCD934X_CDC_FS_MCLK_CNT_EN_MASK BIT(0) +#define WCD934X_CDC_FS_MCLK_CNT_ENABLE BIT(0) +#define WCD934X_CDC_CLK_RST_CTRL_SWR_CONTROL 0x0d43 +#define WCD934X_CDC_SWR_CLK_EN_MASK BIT(0) +#define WCD934X_CDC_SWR_CLK_ENABLE BIT(0) +#define WCD934X_CDC_CLK_RST_CTRL_DSD_CONTROL 0x0d44 +#define WCD934X_CDC_CLK_RST_CTRL_ASRC_SHARE_CONTROL 0x0d45 +#define WCD934X_CDC_CLK_RST_CTRL_GFM_CONTROL 0x0d46 +#define WCD934X_CDC_SIDETONE_IIR0_IIR_PATH_CTL 0x0d55 +#define WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL 0x0d56 +#define WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL 0x0d57 +#define WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL 0x0d58 +#define WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL 0x0d59 +#define WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B5_CTL 0x0d5a +#define WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B6_CTL 0x0d5b +#define WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B7_CTL 0x0d5c +#define WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B8_CTL 0x0d5d +#define WCD934X_CDC_SIDETONE_IIR0_IIR_CTL 0x0d5e +#define WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_TIMER_CTL 0x0d5f +#define WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL 0x0d60 +#define WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL 0x0d61 +#define WCD934X_CDC_SIDETONE_IIR1_IIR_PATH_CTL 0x0d65 +#define WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL 0x0d66 +#define WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL 0x0d67 +#define WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL 0x0d68 +#define WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B4_CTL 0x0d69 +#define WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B5_CTL 0x0d6a +#define WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B6_CTL 0x0d6b +#define WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B7_CTL 0x0d6c +#define WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B8_CTL 0x0d6d +#define WCD934X_CDC_SIDETONE_IIR1_IIR_CTL 0x0d6e +#define WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_TIMER_CTL 0x0d6f +#define WCD934X_CDC_SIDETONE_IIR1_IIR_COEF_B1_CTL 0x0d70 +#define WCD934X_CDC_SIDETONE_IIR1_IIR_COEF_B2_CTL 0x0d71 +#define WCD934X_CDC_TOP_TOP_CFG1 0x0d82 +#define WCD934X_CDC_TOP_TOP_CFG7 0x0d88 +#define WCD934X_CDC_TOP_HPHL_COMP_LUT 0x0d8b +#define WCD934X_CDC_TOP_HPHR_COMP_LUT 0x0d90 +#define WCD934X_HPH_LUT_BYPASS_MASK BIT(7) +#define WCD934X_HPH_LUT_BYPASS_ENABLE BIT(7) +#define WCD934X_HPH_LUT_BYPASS_DISABLE 0 +#define WCD934X_CODEC_CPR_WR_DATA_0 0x5001 +#define WCD934X_CODEC_CPR_WR_ADDR_0 0x5005 +#define WCD934X_CODEC_CPR_SVS_CX_VDD 0x5022 +#define WCD934X_CODEC_CPR_SVS2_CX_VDD 0x5023 +#define WCD934X_CODEC_CPR_SVS2_MIN_CX_VDD 0x5027 +#define WCD934X_TLMM_DMIC1_CLK_PINCFG 0x8015 +#define WCD934X_TLMM_DMIC1_DATA_PINCFG 0x8016 +#define WCD934X_TLMM_DMIC2_CLK_PINCFG 0x8017 +#define WCD934X_TLMM_DMIC2_DATA_PINCFG 0x8018 +#define WCD934X_TLMM_DMIC3_CLK_PINCFG 0x8019 +#define WCD934X_TLMM_DMIC3_DATA_PINCFG 0x801a +#define WCD934X_TEST_DEBUG_PAD_DRVCTL_0 0x803b +#define WCD934X_TEST_DEBUG_NPL_DLY_TEST_1 0x803e + +#define WCD934X_MAX_REGISTER 0xffff +#define WCD934X_SEL_REGISTER 0x800 +#define WCD934X_SEL_MASK 0xff +#define WCD934X_SEL_SHIFT 0x0 +#define WCD934X_WINDOW_START 0x800 +#define WCD934X_WINDOW_LENGTH 0x100 + +/* SLIMBUS Slave Registers */ +#define WCD934X_SLIM_PGD_PORT_INT_EN0 0x30 +#define WCD934X_SLIM_PGD_PORT_INT_STATUS_RX_0 0x34 +#define WCD934X_SLIM_PGD_PORT_INT_STATUS_RX_1 0x35 +#define WCD934X_SLIM_PGD_PORT_INT_STATUS_TX_0 0x36 +#define WCD934X_SLIM_PGD_PORT_INT_STATUS_TX_1 0x37 +#define WCD934X_SLIM_PGD_PORT_INT_CLR_RX_0 0x38 +#define WCD934X_SLIM_PGD_PORT_INT_CLR_RX_1 0x39 +#define WCD934X_SLIM_PGD_PORT_INT_CLR_TX_0 0x3A +#define WCD934X_SLIM_PGD_PORT_INT_CLR_TX_1 0x3B +#define WCD934X_SLIM_PGD_PORT_INT_RX_SOURCE0 0x60 +#define WCD934X_SLIM_PGD_PORT_INT_TX_SOURCE0 0x70 +#define WCD934X_SLIM_PGD_RX_PORT_CFG(p) (0x30 + p) +#define WCD934X_SLIM_PGD_PORT_CFG(p) (0x40 + p) +#define WCD934X_SLIM_PGD_TX_PORT_CFG(p) (0x50 + p) +#define WCD934X_SLIM_PGD_PORT_INT_SRC(p) (0x60 + p) +#define WCD934X_SLIM_PGD_PORT_INT_STATUS(p) (0x80 + p) +#define WCD934X_SLIM_PGD_TX_PORT_MULTI_CHNL_0(p) (0x100 + 4 * p) +/* ports range from 10-16 */ +#define WCD934X_SLIM_PGD_TX_PORT_MULTI_CHNL_1(p) (0x101 + 4 * p) +#define WCD934X_SLIM_PGD_RX_PORT_MULTI_CHNL_0(p) (0x140 + 4 * p) + +#define SLIM_MANF_ID_QCOM 0x217 +#define SLIM_PROD_CODE_WCD9340 0x250 +#define SLIM_DEV_IDX_WCD9340 0x1 +#define SLIM_DEV_INSTANCE_ID_WCD9340 0 + +#endif diff --git a/include/linux/mfd/wcd934x/wcd934x.h b/include/linux/mfd/wcd934x/wcd934x.h new file mode 100644 index 000000000000..f3c65a035150 --- /dev/null +++ b/include/linux/mfd/wcd934x/wcd934x.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __WCD934X_H__ +#define __WCD934X_H__ +#include +#include +#include +#include + +#define WCD934X_MAX_SUPPLY 5 + +/** + * struct wcd934x_ddata - wcd934x driver data + * + * @supplies: wcd934x regulator supplies + * @irq_data: wcd934x irq_chip data + * @regmap: wcd934x regmap pointer + * @extclk: External clock + * @dev: device instance of wcd934x slim device + * @irq: irq for wcd934x. + */ +struct wcd934x_ddata { + struct regulator_bulk_data supplies[WCD934X_MAX_SUPPLY]; + struct regmap_irq_chip_data *irq_data; + struct regmap *regmap; + struct clk *extclk; + struct device *dev; + int irq; +}; + +#endif /* __WCD934X_H__ */ -- cgit v1.2.3-59-g8ed1b From 5312f321a67cfee1fe4de245bc558fa857dce33b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 30 Jan 2020 13:55:29 +0100 Subject: mfd: syscon: Fix syscon_regmap_lookup_by_phandle_args() dummy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If CONFIG_MFD_SYSCON=n: include/linux/mfd/syscon.h:54:23: warning: ‘syscon_regmap_lookup_by_phandle_args’ defined but not used [-Wunused-function] Fix this by adding the missing inline keyword. Fixes: 6a24f567af4accef ("mfd: syscon: Add arguments support for syscon reference") Signed-off-by: Geert Uytterhoeven Signed-off-by: Lee Jones --- include/linux/mfd/syscon.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/mfd/syscon.h b/include/linux/mfd/syscon.h index 714cab1e09d3..7f20e9b502a5 100644 --- a/include/linux/mfd/syscon.h +++ b/include/linux/mfd/syscon.h @@ -51,7 +51,7 @@ static inline struct regmap *syscon_regmap_lookup_by_phandle( return ERR_PTR(-ENOTSUPP); } -static struct regmap *syscon_regmap_lookup_by_phandle_args( +static inline struct regmap *syscon_regmap_lookup_by_phandle_args( struct device_node *np, const char *property, int arg_count, -- cgit v1.2.3-59-g8ed1b