diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-02-03 14:51:57 +0000 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-02-03 14:51:57 +0000 |
commit | af32f3a414d340b0ab92e88ffb80a19632ff345e (patch) | |
tree | aa025e8d9d39967fb36f20f7674fe360db0efb98 /drivers/mfd | |
parent | d0fa9250317ff6e92a1397ebf7cf4d83014f38a6 (diff) | |
parent | 5312f321a67cfee1fe4de245bc558fa857dce33b (diff) |
Merge tag 'mfd-next-5.6' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD updates from Lee Jones:
"New Drivers:
- Add support for ROHM BD71828 PMICs and GPIOs
- Add support for Qualcomm Aqstic Audio Codecs WCD9340 and WCD9341
New Device Support:
- Add support for BD71828 to BD70528 RTC driver
- Add support for Intel's Jasper Lake to LPSS PCI
New Functionality:
- Add support for Power Key to ROHM BD71828
- Add support for Clocks to ROHM BD71828
- Add support for GPIOs to Dialog DA9062
- Add support for USB PD Notify to ChromiumOS EC
- Allow callers to specify args when requesting regmap lookup; syscon
Fix-ups:
- Improve error handling and sanity checking; atmel-hlcdc, dln2
- Device Tree support/documentation; bd71828, da9062, xylon,logicvc,
ab8500, max14577, atmel-usart
- Match devices using platform IDs; bd7xxxx
- Refactor BD718x7 regulator component; bd718x7-regulator
- Use standard interfaces/helpers; syscon, sm501
- Trivial (whitespace, spelling, etc); ab8500-core, Kconfig
- Remove unused code; db8500-prcmu, tqmx86
- Wait until boot has finished before accessing registers;
madera-core
- Provide missing register value defaults; cs47l15-tables
- Allow more time for hardware to reset; madera-core
Bug Fixes:
- Fix erroneous register values; rohm-bd70528
- Fix register volatility; axp20x, rn5t618
- Fix Kconfig dependencies; MFD_MAX77650
- Fix incorrect compatible string; da9062-core
- Fix syscon_regmap_lookup_by_phandle_args() stub; syscon"
* tag 'mfd-next-5.6' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (41 commits)
mfd: syscon: Fix syscon_regmap_lookup_by_phandle_args() dummy
mfd: wcd934x: Add support to wcd9340/wcd9341 codec
mfd: syscon: Add arguments support for syscon reference
mfd: rn5t618: Mark ADC control register volatile
dt-bindings: atmel-usart: Add microchip,sam9x60-{usart, dbgu}
dt-bindings: atmel-usart: Remove wildcard
mfd: cros_ec: Add cros-usbpd-notify subdevice
mfd: da9062: Fix watchdog compatible string
mfd: madera: Allow more time for hardware reset
mfd: cs47l15: Add missing register default
mfd: madera: Wait for boot done before accessing any other registers
mfd: Kconfig: Rename Samsung to lowercase
mfd: tqmx86: remove set but not used variable 'i2c_ien'
mfd: dbx500-prcmu: Drop DSI pll clock functions
mfd: dbx500-prcmu: Drop set_display_clocks()
mfd: max77650: Select REGMAP_IRQ in Kconfig
mfd: axp20x: Mark AXP20X_VBUS_IPSOUT_MGMT as volatile
mfd: ab8500: Fix ab8500-clk typo
mfd: intel-lpss: Add Intel Jasper Lake PCI IDs
dt-bindings: mfd: max14577: Add reference to max14040_battery.txt descriptions
...
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/Kconfig | 30 | ||||
-rw-r--r-- | drivers/mfd/Makefile | 2 | ||||
-rw-r--r-- | drivers/mfd/ab8500-core.c | 18 | ||||
-rw-r--r-- | drivers/mfd/atmel-hlcdc.c | 18 | ||||
-rw-r--r-- | drivers/mfd/axp20x.c | 2 | ||||
-rw-r--r-- | drivers/mfd/cros_ec_dev.c | 22 | ||||
-rw-r--r-- | drivers/mfd/cs47l15-tables.c | 1 | ||||
-rw-r--r-- | drivers/mfd/da9062-core.c | 18 | ||||
-rw-r--r-- | drivers/mfd/db8500-prcmu.c | 122 | ||||
-rw-r--r-- | drivers/mfd/dln2.c | 13 | ||||
-rw-r--r-- | drivers/mfd/intel-lpss-pci.c | 13 | ||||
-rw-r--r-- | drivers/mfd/madera-core.c | 33 | ||||
-rw-r--r-- | drivers/mfd/rn5t618.c | 1 | ||||
-rw-r--r-- | drivers/mfd/rohm-bd70528.c | 3 | ||||
-rw-r--r-- | drivers/mfd/rohm-bd71828.c | 344 | ||||
-rw-r--r-- | drivers/mfd/rohm-bd718x7.c | 43 | ||||
-rw-r--r-- | drivers/mfd/sm501.c | 19 | ||||
-rw-r--r-- | drivers/mfd/syscon.c | 31 | ||||
-rw-r--r-- | drivers/mfd/tqmx86.c | 3 | ||||
-rw-r--r-- | drivers/mfd/wcd934x.c | 306 |
20 files changed, 892 insertions, 150 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 7a4a41dddc97..2b203290e7b9 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -758,6 +758,7 @@ config MFD_MAX77650 depends on OF || COMPILE_TEST select MFD_CORE select REGMAP_I2C + select REGMAP_IRQ help Say Y here to add support for Maxim Semiconductor MAX77650 and MAX77651 Power Management ICs. This is the core multifunction @@ -1065,7 +1066,7 @@ config MFD_RN5T618 functionality of the device. config MFD_SEC_CORE - tristate "SAMSUNG Electronics PMIC Series Support" + tristate "Samsung Electronics PMIC Series Support" depends on I2C=y select MFD_CORE select REGMAP_I2C @@ -1906,6 +1907,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 @@ -1960,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 5fe930c76ade..b83f172545e1 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 @@ -252,6 +253,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/ab8500-core.c b/drivers/mfd/ab8500-core.c index bafc729fc434..a3bac9da8cbb 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -631,8 +631,8 @@ static const struct mfd_cell ab8500_devs[] = { NULL, NULL, 0, 0, "stericsson,ab8500-ext-regulator"), OF_MFD_CELL("ab8500-regulator", NULL, NULL, 0, 0, "stericsson,ab8500-regulator"), - OF_MFD_CELL("abx500-clk", - NULL, NULL, 0, 0, "stericsson,abx500-clk"), + OF_MFD_CELL("ab8500-clk", + NULL, NULL, 0, 0, "stericsson,ab8500-clk"), OF_MFD_CELL("ab8500-gpadc", NULL, NULL, 0, 0, "stericsson,ab8500-gpadc"), OF_MFD_CELL("ab8500-rtc", @@ -718,17 +718,20 @@ static const struct mfd_cell ab8505_devs[] = { #ifdef CONFIG_DEBUG_FS { .name = "ab8500-debug", + .of_compatible = "stericsson,ab8500-debug", }, #endif { .name = "ab8500-sysctrl", + .of_compatible = "stericsson,ab8500-sysctrl", }, { .name = "ab8500-regulator", + .of_compatible = "stericsson,ab8505-regulator", }, { .name = "abx500-clk", - .of_compatible = "stericsson,abx500-clk", + .of_compatible = "stericsson,ab8500-clk", }, { .name = "ab8500-gpadc", @@ -736,25 +739,32 @@ static const struct mfd_cell ab8505_devs[] = { }, { .name = "ab8500-rtc", + .of_compatible = "stericsson,ab8500-rtc", }, { .name = "ab8500-acc-det", + .of_compatible = "stericsson,ab8500-acc-det", }, { .name = "ab8500-poweron-key", + .of_compatible = "stericsson,ab8500-poweron-key", }, { .name = "ab8500-pwm", + .of_compatible = "stericsson,ab8500-pwm", .id = 1, }, { .name = "pinctrl-ab8505", + .of_compatible = "stericsson,ab8505-gpio", }, { .name = "ab8500-usb", + .of_compatible = "stericsson,ab8500-usb", }, { .name = "ab8500-codec", + .of_compatible = "stericsson,ab8500-codec", }, { .name = "ab-iddet", @@ -1276,7 +1286,7 @@ static int ab8500_probe(struct platform_device *pdev) static const struct platform_device_id ab8500_id[] = { { "ab8500-core", AB8500_VERSION_AB8500 }, - { "ab8505-i2c", AB8500_VERSION_AB8505 }, + { "ab8505-core", AB8500_VERSION_AB8505 }, { "ab9540-i2c", AB8500_VERSION_AB9540 }, { "ab8540-i2c", AB8500_VERSION_AB8540 }, { } diff --git a/drivers/mfd/atmel-hlcdc.c b/drivers/mfd/atmel-hlcdc.c index 64013c57a920..3c2414ba4b01 100644 --- a/drivers/mfd/atmel-hlcdc.c +++ b/drivers/mfd/atmel-hlcdc.c @@ -19,6 +19,7 @@ struct atmel_hlcdc_regmap { void __iomem *regs; + struct device *dev; }; static const struct mfd_cell atmel_hlcdc_cells[] = { @@ -39,10 +40,17 @@ static int regmap_atmel_hlcdc_reg_write(void *context, unsigned int reg, if (reg <= ATMEL_HLCDC_DIS) { u32 status; - - readl_poll_timeout_atomic(hregmap->regs + ATMEL_HLCDC_SR, - status, !(status & ATMEL_HLCDC_SIP), - 1, 100); + int ret; + + ret = readl_poll_timeout_atomic(hregmap->regs + ATMEL_HLCDC_SR, + status, + !(status & ATMEL_HLCDC_SIP), + 1, 100); + if (ret) { + dev_err(hregmap->dev, + "Timeout! Clock domain synchronization is in progress!\n"); + return ret; + } } writel(val, hregmap->regs + reg); @@ -90,6 +98,8 @@ static int atmel_hlcdc_probe(struct platform_device *pdev) if (IS_ERR(hregmap->regs)) return PTR_ERR(hregmap->regs); + hregmap->dev = &pdev->dev; + hlcdc->irq = platform_get_irq(pdev, 0); if (hlcdc->irq < 0) return hlcdc->irq; diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index a4aaadaa0cb0..aa59496e4376 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -126,7 +126,7 @@ static const struct regmap_range axp288_writeable_ranges[] = { static const struct regmap_range axp288_volatile_ranges[] = { regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP288_POWER_REASON), regmap_reg_range(AXP288_BC_GLOBAL, AXP288_BC_GLOBAL), - regmap_reg_range(AXP288_BC_DET_STAT, AXP288_BC_DET_STAT), + regmap_reg_range(AXP288_BC_DET_STAT, AXP20X_VBUS_IPSOUT_MGMT), regmap_reg_range(AXP20X_CHRG_BAK_CTRL, AXP20X_CHRG_BAK_CTRL), regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IPSOUT_V_HIGH_L), regmap_reg_range(AXP20X_TIMER_CTRL, AXP20X_TIMER_CTRL), diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c index c4b977a5dd96..d0c28a4c10ad 100644 --- a/drivers/mfd/cros_ec_dev.c +++ b/drivers/mfd/cros_ec_dev.c @@ -5,6 +5,7 @@ * Copyright (C) 2014 Google, Inc. */ +#include <linux/kconfig.h> #include <linux/mfd/core.h> #include <linux/mfd/cros_ec.h> #include <linux/module.h> @@ -87,6 +88,10 @@ static const struct mfd_cell cros_usbpd_charger_cells[] = { { .name = "cros-usbpd-logger", }, }; +static const struct mfd_cell cros_usbpd_notify_cells[] = { + { .name = "cros-usbpd-notify", }, +}; + static const struct cros_feature_to_cells cros_subdevices[] = { { .id = EC_FEATURE_CEC, @@ -203,6 +208,23 @@ static int ec_device_probe(struct platform_device *pdev) } /* + * The PD notifier driver cell is separate since it only needs to be + * explicitly added on platforms that don't have the PD notifier ACPI + * device entry defined. + */ + if (IS_ENABLED(CONFIG_OF)) { + if (cros_ec_check_features(ec, EC_FEATURE_USB_PD)) { + retval = mfd_add_hotplug_devices(ec->dev, + cros_usbpd_notify_cells, + ARRAY_SIZE(cros_usbpd_notify_cells)); + if (retval) + dev_err(ec->dev, + "failed to add PD notify devices: %d\n", + retval); + } + } + + /* * The following subdevices cannot be detected by sending the * EC_FEATURE_GET_CMD to the Embedded Controller device. */ diff --git a/drivers/mfd/cs47l15-tables.c b/drivers/mfd/cs47l15-tables.c index f81b45336690..3c77f0a24e9b 100644 --- a/drivers/mfd/cs47l15-tables.c +++ b/drivers/mfd/cs47l15-tables.c @@ -112,6 +112,7 @@ static const struct reg_default cs47l15_reg_default[] = { { 0x000001dd, 0x0011 }, /* R477 (0x1DD) - FLL AO Control 11 */ { 0x00000218, 0x00e6 }, /* R536 (0x218) - Mic Bias Ctrl 1 */ { 0x0000021c, 0x0222 }, /* R540 (0x21C) - Mic Bias Ctrl 5 */ + { 0x00000293, 0x0080 }, /* R659 (0x293) - Accessory Detect Mode 1 */ { 0x00000299, 0x0000 }, /* R665 (0x299) - Headphone Detect 0 */ { 0x0000029b, 0x0000 }, /* R667 (0x29B) - Headphone Detect 1 */ { 0x000002a2, 0x0010 }, /* R674 (0x2A2) - Mic Detect 1 Control 0 */ diff --git a/drivers/mfd/da9062-core.c b/drivers/mfd/da9062-core.c index e69626867c26..419c73533401 100644 --- a/drivers/mfd/da9062-core.c +++ b/drivers/mfd/da9062-core.c @@ -233,6 +233,14 @@ static struct resource da9062_onkey_resources[] = { DEFINE_RES_NAMED(DA9062_IRQ_ONKEY, 1, "ONKEY", IORESOURCE_IRQ), }; +static struct resource da9062_gpio_resources[] = { + DEFINE_RES_NAMED(DA9062_IRQ_GPI0, 1, "GPI0", IORESOURCE_IRQ), + DEFINE_RES_NAMED(DA9062_IRQ_GPI1, 1, "GPI1", IORESOURCE_IRQ), + DEFINE_RES_NAMED(DA9062_IRQ_GPI2, 1, "GPI2", IORESOURCE_IRQ), + DEFINE_RES_NAMED(DA9062_IRQ_GPI3, 1, "GPI3", IORESOURCE_IRQ), + DEFINE_RES_NAMED(DA9062_IRQ_GPI4, 1, "GPI4", IORESOURCE_IRQ), +}; + static const struct mfd_cell da9062_devs[] = { { .name = "da9062-core", @@ -248,7 +256,7 @@ static const struct mfd_cell da9062_devs[] = { .name = "da9062-watchdog", .num_resources = ARRAY_SIZE(da9062_wdt_resources), .resources = da9062_wdt_resources, - .of_compatible = "dlg,da9062-wdt", + .of_compatible = "dlg,da9062-watchdog", }, { .name = "da9062-thermal", @@ -266,7 +274,13 @@ static const struct mfd_cell da9062_devs[] = { .name = "da9062-onkey", .num_resources = ARRAY_SIZE(da9062_onkey_resources), .resources = da9062_onkey_resources, - .of_compatible = "dlg,da9062-onkey", + .of_compatible = "dlg,da9062-onkey", + }, + { + .name = "da9062-gpio", + .num_resources = ARRAY_SIZE(da9062_gpio_resources), + .resources = da9062_gpio_resources, + .of_compatible = "dlg,da9062-gpio", }, }; diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 57ac58b4b5f3..0452b43b0423 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -542,102 +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) - -/* 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 - -#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; -} - -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); @@ -3060,30 +2964,44 @@ static const struct mfd_cell db8500_prcmu_devs[] = { static int db8500_prcmu_register_ab8500(struct device *parent) { struct device_node *np; - struct resource ab8500_resource; + struct resource ab850x_resource; const struct mfd_cell ab8500_cell = { .name = "ab8500-core", .of_compatible = "stericsson,ab8500", .id = AB8500_VERSION_AB8500, - .resources = &ab8500_resource, + .resources = &ab850x_resource, .num_resources = 1, }; + const struct mfd_cell ab8505_cell = { + .name = "ab8505-core", + .of_compatible = "stericsson,ab8505", + .id = AB8500_VERSION_AB8505, + .resources = &ab850x_resource, + .num_resources = 1, + }; + const struct mfd_cell *ab850x_cell; if (!parent->of_node) return -ENODEV; /* Look up the device node, sneak the IRQ out of it */ for_each_child_of_node(parent->of_node, np) { - if (of_device_is_compatible(np, ab8500_cell.of_compatible)) + if (of_device_is_compatible(np, ab8500_cell.of_compatible)) { + ab850x_cell = &ab8500_cell; break; + } + if (of_device_is_compatible(np, ab8505_cell.of_compatible)) { + ab850x_cell = &ab8505_cell; + break; + } } if (!np) { - dev_info(parent, "could not find AB8500 node in the device tree\n"); + dev_info(parent, "could not find AB850X node in the device tree\n"); return -ENODEV; } - of_irq_to_resource_table(np, &ab8500_resource, 1); + of_irq_to_resource_table(np, &ab850x_resource, 1); - return mfd_add_devices(parent, 0, &ab8500_cell, 1, NULL, 0, NULL); + return mfd_add_devices(parent, 0, ab850x_cell, 1, NULL, 0, NULL); } /** diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c index 381593fbe50f..7841c11411d0 100644 --- a/drivers/mfd/dln2.c +++ b/drivers/mfd/dln2.c @@ -722,6 +722,8 @@ static int dln2_probe(struct usb_interface *interface, const struct usb_device_id *usb_id) { struct usb_host_interface *hostif = interface->cur_altsetting; + struct usb_endpoint_descriptor *epin; + struct usb_endpoint_descriptor *epout; struct device *dev = &interface->dev; struct dln2_dev *dln2; int ret; @@ -731,12 +733,19 @@ static int dln2_probe(struct usb_interface *interface, hostif->desc.bNumEndpoints < 2) return -ENODEV; + epin = &hostif->endpoint[0].desc; + epout = &hostif->endpoint[1].desc; + if (!usb_endpoint_is_bulk_out(epout)) + return -ENODEV; + if (!usb_endpoint_is_bulk_in(epin)) + return -ENODEV; + dln2 = kzalloc(sizeof(*dln2), GFP_KERNEL); if (!dln2) return -ENOMEM; - dln2->ep_out = hostif->endpoint[0].desc.bEndpointAddress; - dln2->ep_in = hostif->endpoint[1].desc.bEndpointAddress; + dln2->ep_out = epout->bEndpointAddress; + dln2->ep_in = epin->bEndpointAddress; dln2->usb_dev = usb_get_dev(interface_to_usbdev(interface)); dln2->interface = interface; usb_set_intfdata(interface, dln2); diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c index b33030e3385c..c40a6c7d0cf8 100644 --- a/drivers/mfd/intel-lpss-pci.c +++ b/drivers/mfd/intel-lpss-pci.c @@ -240,6 +240,19 @@ static const struct pci_device_id intel_lpss_pci_ids[] = { { PCI_VDEVICE(INTEL, 0x4b79), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x4b7a), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x4b7b), (kernel_ulong_t)&bxt_i2c_info }, + /* JSL */ + { PCI_VDEVICE(INTEL, 0x4da8), (kernel_ulong_t)&spt_uart_info }, + { PCI_VDEVICE(INTEL, 0x4da9), (kernel_ulong_t)&spt_uart_info }, + { PCI_VDEVICE(INTEL, 0x4daa), (kernel_ulong_t)&spt_info }, + { PCI_VDEVICE(INTEL, 0x4dab), (kernel_ulong_t)&spt_info }, + { PCI_VDEVICE(INTEL, 0x4daf), (kernel_ulong_t)&spt_uart_info }, + { PCI_VDEVICE(INTEL, 0x4dc5), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x4dc6), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x4de8), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x4de9), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x4dea), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x4deb), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x4dfb), (kernel_ulong_t)&spt_info }, /* APL */ { PCI_VDEVICE(INTEL, 0x5aac), (kernel_ulong_t)&apl_i2c_info }, { PCI_VDEVICE(INTEL, 0x5aae), (kernel_ulong_t)&apl_i2c_info }, diff --git a/drivers/mfd/madera-core.c b/drivers/mfd/madera-core.c index a8cfadc1fc01..7e0835cb062b 100644 --- a/drivers/mfd/madera-core.c +++ b/drivers/mfd/madera-core.c @@ -35,6 +35,9 @@ #define MADERA_32KZ_MCLK2 1 +#define MADERA_RESET_MIN_US 2000 +#define MADERA_RESET_MAX_US 3000 + static const char * const madera_core_supplies[] = { "AVDD", "DBVDD1", @@ -199,7 +202,7 @@ EXPORT_SYMBOL_GPL(madera_name_from_type); #define MADERA_BOOT_POLL_INTERVAL_USEC 5000 #define MADERA_BOOT_POLL_TIMEOUT_USEC 25000 -static int madera_wait_for_boot(struct madera *madera) +static int madera_wait_for_boot_noack(struct madera *madera) { ktime_t timeout; unsigned int val = 0; @@ -226,6 +229,13 @@ static int madera_wait_for_boot(struct madera *madera) ret = -ETIMEDOUT; } + return ret; +} + +static int madera_wait_for_boot(struct madera *madera) +{ + int ret = madera_wait_for_boot_noack(madera); + /* * BOOT_DONE defaults to unmasked on boot so we must ack it. * Do this even after a timeout to avoid interrupt storms. @@ -249,16 +259,13 @@ static int madera_soft_reset(struct madera *madera) } /* Allow time for internal clocks to startup after reset */ - usleep_range(1000, 2000); + usleep_range(MADERA_RESET_MIN_US, MADERA_RESET_MAX_US); return 0; } static void madera_enable_hard_reset(struct madera *madera) { - if (!madera->pdata.reset) - return; - /* * There are many existing out-of-tree users of these codecs that we * can't break so preserve the expected behaviour of setting the line @@ -269,11 +276,9 @@ static void madera_enable_hard_reset(struct madera *madera) static void madera_disable_hard_reset(struct madera *madera) { - if (!madera->pdata.reset) - return; - gpiod_set_raw_value_cansleep(madera->pdata.reset, 1); - usleep_range(1000, 2000); + + usleep_range(MADERA_RESET_MIN_US, MADERA_RESET_MAX_US); } static int __maybe_unused madera_runtime_resume(struct device *dev) @@ -292,6 +297,8 @@ static int __maybe_unused madera_runtime_resume(struct device *dev) regcache_cache_only(madera->regmap, false); regcache_cache_only(madera->regmap_32bit, false); + usleep_range(MADERA_RESET_MIN_US, MADERA_RESET_MAX_US); + ret = madera_wait_for_boot(madera); if (ret) goto err; @@ -545,6 +552,12 @@ int madera_dev_init(struct madera *madera) regcache_cache_only(madera->regmap, false); regcache_cache_only(madera->regmap_32bit, false); + ret = madera_wait_for_boot_noack(madera); + if (ret) { + dev_err(madera->dev, "Device failed initial boot: %d\n", ret); + goto err_reset; + } + /* * Now we can power up and verify that this is a chip we know about * before we start doing any writes to its registers. @@ -650,7 +663,7 @@ int madera_dev_init(struct madera *madera) ret = madera_wait_for_boot(madera); if (ret) { - dev_err(madera->dev, "Device failed initial boot: %d\n", ret); + dev_err(madera->dev, "Failed to clear boot done: %d\n", ret); goto err_reset; } diff --git a/drivers/mfd/rn5t618.c b/drivers/mfd/rn5t618.c index da5cd9c92a59..ead2e79036a9 100644 --- a/drivers/mfd/rn5t618.c +++ b/drivers/mfd/rn5t618.c @@ -26,6 +26,7 @@ static bool rn5t618_volatile_reg(struct device *dev, unsigned int reg) case RN5T618_WATCHDOGCNT: case RN5T618_DCIRQ: case RN5T618_ILIMDATAH ... RN5T618_AIN0DATAL: + case RN5T618_ADCCNT3: case RN5T618_IR_ADC1 ... RN5T618_IR_ADC3: case RN5T618_IR_GPR: case RN5T618_IR_GPF: diff --git a/drivers/mfd/rohm-bd70528.c b/drivers/mfd/rohm-bd70528.c index ef6786fd3b00..5c44d3b77b3e 100644 --- a/drivers/mfd/rohm-bd70528.c +++ b/drivers/mfd/rohm-bd70528.c @@ -48,7 +48,7 @@ static struct mfd_cell bd70528_mfd_cells[] = { * We use BD71837 driver to drive the clock block. Only differences to * BD70528 clock gate are the register address and mask. */ - { .name = "bd718xx-clk", }, + { .name = "bd70528-clk", }, { .name = "bd70528-wdt", }, { .name = "bd70528-power", @@ -236,7 +236,6 @@ static int bd70528_i2c_probe(struct i2c_client *i2c, dev_set_drvdata(&i2c->dev, &bd70528->chip); - bd70528->chip.chip_type = ROHM_CHIP_TYPE_BD70528; bd70528->chip.regmap = devm_regmap_init_i2c(i2c, &bd70528_regmap); if (IS_ERR(bd70528->chip.regmap)) { dev_err(&i2c->dev, "Failed to initialize Regmap\n"); diff --git a/drivers/mfd/rohm-bd71828.c b/drivers/mfd/rohm-bd71828.c new file mode 100644 index 000000000000..210261d026f2 --- /dev/null +++ b/drivers/mfd/rohm-bd71828.c @@ -0,0 +1,344 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (C) 2019 ROHM Semiconductors +// +// ROHM BD71828 PMIC driver + +#include <linux/gpio_keys.h> +#include <linux/i2c.h> +#include <linux/input.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/irq.h> +#include <linux/mfd/core.h> +#include <linux/mfd/rohm-bd71828.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/regmap.h> +#include <linux/types.h> + +static struct gpio_keys_button button = { + .code = KEY_POWER, + .gpio = -1, + .type = EV_KEY, +}; + +static struct gpio_keys_platform_data bd71828_powerkey_data = { + .buttons = &button, + .nbuttons = 1, + .name = "bd71828-pwrkey", +}; + +static const struct resource rtc_irqs[] = { + DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC0, "bd71828-rtc-alm-0"), + DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC1, "bd71828-rtc-alm-1"), + 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), + }, { + .name = "gpio-keys", + .platform_data = &bd71828_powerkey_data, + .pdata_size = sizeof(bd71828_powerkey_data), + }, +}; + +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_ |