From f36e789a1f8d0b75ee2b459dfac10efd7d299a6d Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Mon, 11 Mar 2019 17:18:03 -0500 Subject: mfd: altera-sysmgr: Add SOCFPGA System Manager The SOCFPGA System Manager register block aggregates different peripheral functions into one area. On 32 bit ARM parts, handle in the same way as syscon. On 64 bit ARM parts, the System Manager can only be accessed by EL3 secure mode. Since a SMC call to EL3 is required, this new driver uses regmaps similar to syscon to handle the SMC call. Since regmaps abstract out the underlying register access, the changes to drivers accessing the System Manager are minimal. Signed-off-by: Thor Thayer Reviewed-by: Arnd Bergmann Signed-off-by: Lee Jones --- include/linux/mfd/altera-sysmgr.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 include/linux/mfd/altera-sysmgr.h (limited to 'include/linux') diff --git a/include/linux/mfd/altera-sysmgr.h b/include/linux/mfd/altera-sysmgr.h new file mode 100644 index 000000000000..b1ef11a83872 --- /dev/null +++ b/include/linux/mfd/altera-sysmgr.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2018-2019 Intel Corporation + * Copyright (C) 2012 Freescale Semiconductor, Inc. + * Copyright (C) 2012 Linaro Ltd. + */ + +#ifndef __LINUX_MFD_ALTERA_SYSMGR_H__ +#define __LINUX_MFD_ALTERA_SYSMGR_H__ + +#include +#include +#include + +struct device_node; + +#ifdef CONFIG_MFD_ALTERA_SYSMGR +struct regmap *altr_sysmgr_regmap_lookup_by_phandle(struct device_node *np, + const char *property); +#else +static inline struct regmap * +altr_sysmgr_regmap_lookup_by_phandle(struct device_node *np, + const char *property) +{ + return ERR_PTR(-ENOTSUPP); +} +#endif + +#endif /* __LINUX_MFD_ALTERA_SYSMGR_H__ */ -- cgit v1.2.3-71-gd317 From d0f60334500b0fe54e55c2df7029b02d8682c6c0 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 23 Apr 2019 11:04:46 +0200 Subject: mfd: Add new driver for MAX77650 PMIC Add the core MFD driver for max77650 PMIC. We define five sub-devices for which the drivers will be added in subsequent patches. Signed-off-by: Bartosz Golaszewski Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 14 +++ drivers/mfd/Makefile | 1 + drivers/mfd/max77650.c | 232 +++++++++++++++++++++++++++++++++++++++++++ include/linux/mfd/max77650.h | 59 +++++++++++ 4 files changed, 306 insertions(+) create mode 100644 drivers/mfd/max77650.c create mode 100644 include/linux/mfd/max77650.h (limited to 'include/linux') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 26ad6468d13a..0f394f08db6f 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -733,6 +733,20 @@ config MFD_MAX77620 provides common support for accessing the device; additional drivers must be enabled in order to use the functionality of the device. +config MFD_MAX77650 + tristate "Maxim MAX77650/77651 PMIC Support" + depends on I2C + depends on OF || COMPILE_TEST + select MFD_CORE + select REGMAP_I2C + help + Say Y here to add support for Maxim Semiconductor MAX77650 and + MAX77651 Power Management ICs. This is the core multifunction + driver for interacting with the device. The module name is + 'max77650'. Additional drivers can be enabled in order to use + the following functionalities of the device: GPIO, regulator, + charger, LED, onkey. + config MFD_MAX77686 tristate "Maxim Semiconductor MAX77686/802 PMIC Support" depends on I2C diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index b4569ed7f3f3..5727d099c16f 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -155,6 +155,7 @@ obj-$(CONFIG_MFD_DA9150) += da9150-core.o obj-$(CONFIG_MFD_MAX14577) += max14577.o obj-$(CONFIG_MFD_MAX77620) += max77620.o +obj-$(CONFIG_MFD_MAX77650) += max77650.o obj-$(CONFIG_MFD_MAX77686) += max77686.o obj-$(CONFIG_MFD_MAX77693) += max77693.o obj-$(CONFIG_MFD_MAX77843) += max77843.o diff --git a/drivers/mfd/max77650.c b/drivers/mfd/max77650.c new file mode 100644 index 000000000000..60e07aca6ae5 --- /dev/null +++ b/drivers/mfd/max77650.c @@ -0,0 +1,232 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2018 BayLibre SAS +// Author: Bartosz Golaszewski +// +// Core MFD driver for MAXIM 77650/77651 charger/power-supply. +// Programming manual: https://pdfserv.maximintegrated.com/en/an/AN6428.pdf + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX77650_INT_GPI_F_MSK BIT(0) +#define MAX77650_INT_GPI_R_MSK BIT(1) +#define MAX77650_INT_GPI_MSK \ + (MAX77650_INT_GPI_F_MSK | MAX77650_INT_GPI_R_MSK) +#define MAX77650_INT_nEN_F_MSK BIT(2) +#define MAX77650_INT_nEN_R_MSK BIT(3) +#define MAX77650_INT_TJAL1_R_MSK BIT(4) +#define MAX77650_INT_TJAL2_R_MSK BIT(5) +#define MAX77650_INT_DOD_R_MSK BIT(6) + +#define MAX77650_INT_THM_MSK BIT(0) +#define MAX77650_INT_CHG_MSK BIT(1) +#define MAX77650_INT_CHGIN_MSK BIT(2) +#define MAX77650_INT_TJ_REG_MSK BIT(3) +#define MAX77650_INT_CHGIN_CTRL_MSK BIT(4) +#define MAX77650_INT_SYS_CTRL_MSK BIT(5) +#define MAX77650_INT_SYS_CNFG_MSK BIT(6) + +#define MAX77650_INT_GLBL_OFFSET 0 +#define MAX77650_INT_CHG_OFFSET 1 + +#define MAX77650_SBIA_LPM_MASK BIT(5) +#define MAX77650_SBIA_LPM_DISABLED 0x00 + +enum { + MAX77650_INT_GPI, + MAX77650_INT_nEN_F, + MAX77650_INT_nEN_R, + MAX77650_INT_TJAL1_R, + MAX77650_INT_TJAL2_R, + MAX77650_INT_DOD_R, + MAX77650_INT_THM, + MAX77650_INT_CHG, + MAX77650_INT_CHGIN, + MAX77650_INT_TJ_REG, + MAX77650_INT_CHGIN_CTRL, + MAX77650_INT_SYS_CTRL, + MAX77650_INT_SYS_CNFG, +}; + +static const struct resource max77650_charger_resources[] = { + DEFINE_RES_IRQ_NAMED(MAX77650_INT_CHG, "CHG"), + DEFINE_RES_IRQ_NAMED(MAX77650_INT_CHGIN, "CHGIN"), +}; + +static const struct resource max77650_gpio_resources[] = { + DEFINE_RES_IRQ_NAMED(MAX77650_INT_GPI, "GPI"), +}; + +static const struct resource max77650_onkey_resources[] = { + DEFINE_RES_IRQ_NAMED(MAX77650_INT_nEN_F, "nEN_F"), + DEFINE_RES_IRQ_NAMED(MAX77650_INT_nEN_R, "nEN_R"), +}; + +static const struct mfd_cell max77650_cells[] = { + { + .name = "max77650-regulator", + .of_compatible = "maxim,max77650-regulator", + }, { + .name = "max77650-charger", + .of_compatible = "maxim,max77650-charger", + .resources = max77650_charger_resources, + .num_resources = ARRAY_SIZE(max77650_charger_resources), + }, { + .name = "max77650-gpio", + .of_compatible = "maxim,max77650-gpio", + .resources = max77650_gpio_resources, + .num_resources = ARRAY_SIZE(max77650_gpio_resources), + }, { + .name = "max77650-led", + .of_compatible = "maxim,max77650-led", + }, { + .name = "max77650-onkey", + .of_compatible = "maxim,max77650-onkey", + .resources = max77650_onkey_resources, + .num_resources = ARRAY_SIZE(max77650_onkey_resources), + }, +}; + +static const struct regmap_irq max77650_irqs[] = { + [MAX77650_INT_GPI] = { + .reg_offset = MAX77650_INT_GLBL_OFFSET, + .mask = MAX77650_INT_GPI_MSK, + .type = { + .type_falling_val = MAX77650_INT_GPI_F_MSK, + .type_rising_val = MAX77650_INT_GPI_R_MSK, + .types_supported = IRQ_TYPE_EDGE_BOTH, + }, + }, + REGMAP_IRQ_REG(MAX77650_INT_nEN_F, + MAX77650_INT_GLBL_OFFSET, MAX77650_INT_nEN_F_MSK), + REGMAP_IRQ_REG(MAX77650_INT_nEN_R, + MAX77650_INT_GLBL_OFFSET, MAX77650_INT_nEN_R_MSK), + REGMAP_IRQ_REG(MAX77650_INT_TJAL1_R, + MAX77650_INT_GLBL_OFFSET, MAX77650_INT_TJAL1_R_MSK), + REGMAP_IRQ_REG(MAX77650_INT_TJAL2_R, + MAX77650_INT_GLBL_OFFSET, MAX77650_INT_TJAL2_R_MSK), + REGMAP_IRQ_REG(MAX77650_INT_DOD_R, + MAX77650_INT_GLBL_OFFSET, MAX77650_INT_DOD_R_MSK), + REGMAP_IRQ_REG(MAX77650_INT_THM, + MAX77650_INT_CHG_OFFSET, MAX77650_INT_THM_MSK), + REGMAP_IRQ_REG(MAX77650_INT_CHG, + MAX77650_INT_CHG_OFFSET, MAX77650_INT_CHG_MSK), + REGMAP_IRQ_REG(MAX77650_INT_CHGIN, + MAX77650_INT_CHG_OFFSET, MAX77650_INT_CHGIN_MSK), + REGMAP_IRQ_REG(MAX77650_INT_TJ_REG, + MAX77650_INT_CHG_OFFSET, MAX77650_INT_TJ_REG_MSK), + REGMAP_IRQ_REG(MAX77650_INT_CHGIN_CTRL, + MAX77650_INT_CHG_OFFSET, MAX77650_INT_CHGIN_CTRL_MSK), + REGMAP_IRQ_REG(MAX77650_INT_SYS_CTRL, + MAX77650_INT_CHG_OFFSET, MAX77650_INT_SYS_CTRL_MSK), + REGMAP_IRQ_REG(MAX77650_INT_SYS_CNFG, + MAX77650_INT_CHG_OFFSET, MAX77650_INT_SYS_CNFG_MSK), +}; + +static const struct regmap_irq_chip max77650_irq_chip = { + .name = "max77650-irq", + .irqs = max77650_irqs, + .num_irqs = ARRAY_SIZE(max77650_irqs), + .num_regs = 2, + .status_base = MAX77650_REG_INT_GLBL, + .mask_base = MAX77650_REG_INTM_GLBL, + .type_in_mask = true, + .type_invert = true, + .init_ack_masked = true, + .clear_on_unmask = true, +}; + +static const struct regmap_config max77650_regmap_config = { + .name = "max77650", + .reg_bits = 8, + .val_bits = 8, +}; + +static int max77650_i2c_probe(struct i2c_client *i2c) +{ + struct regmap_irq_chip_data *irq_data; + struct device *dev = &i2c->dev; + struct irq_domain *domain; + struct regmap *map; + unsigned int val; + int rv, id; + + map = devm_regmap_init_i2c(i2c, &max77650_regmap_config); + if (IS_ERR(map)) { + dev_err(dev, "Unable to initialise I2C Regmap\n"); + return PTR_ERR(map); + } + + rv = regmap_read(map, MAX77650_REG_CID, &val); + if (rv) { + dev_err(dev, "Unable to read Chip ID\n"); + return rv; + } + + id = MAX77650_CID_BITS(val); + switch (id) { + case MAX77650_CID_77650A: + case MAX77650_CID_77650C: + case MAX77650_CID_77651A: + case MAX77650_CID_77651B: + break; + default: + dev_err(dev, "Chip not supported - ID: 0x%02x\n", id); + return -ENODEV; + } + + /* + * This IC has a low-power mode which reduces the quiescent current + * consumption to ~5.6uA but is only suitable for systems consuming + * less than ~2mA. Since this is not likely the case even on + * linux-based wearables - keep the chip in normal power mode. + */ + rv = regmap_update_bits(map, + MAX77650_REG_CNFG_GLBL, + MAX77650_SBIA_LPM_MASK, + MAX77650_SBIA_LPM_DISABLED); + if (rv) { + dev_err(dev, "Unable to change the power mode\n"); + return rv; + } + + rv = devm_regmap_add_irq_chip(dev, map, i2c->irq, + IRQF_ONESHOT | IRQF_SHARED, 0, + &max77650_irq_chip, &irq_data); + if (rv) { + dev_err(dev, "Unable to add Regmap IRQ chip\n"); + return rv; + } + + domain = regmap_irq_get_domain(irq_data); + + return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, + max77650_cells, ARRAY_SIZE(max77650_cells), + NULL, 0, domain); +} + +static const struct of_device_id max77650_of_match[] = { + { .compatible = "maxim,max77650" }, + { } +}; +MODULE_DEVICE_TABLE(of, max77650_of_match); + +static struct i2c_driver max77650_i2c_driver = { + .driver = { + .name = "max77650", + .of_match_table = of_match_ptr(max77650_of_match), + }, + .probe_new = max77650_i2c_probe, +}; +module_i2c_driver(max77650_i2c_driver); + +MODULE_DESCRIPTION("MAXIM 77650/77651 multi-function core driver"); +MODULE_AUTHOR("Bartosz Golaszewski "); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/mfd/max77650.h b/include/linux/mfd/max77650.h new file mode 100644 index 000000000000..c809e211a8cd --- /dev/null +++ b/include/linux/mfd/max77650.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2018 BayLibre SAS + * Author: Bartosz Golaszewski + * + * Common definitions for MAXIM 77650/77651 charger/power-supply. + */ + +#ifndef MAX77650_H +#define MAX77650_H + +#include + +#define MAX77650_REG_INT_GLBL 0x00 +#define MAX77650_REG_INT_CHG 0x01 +#define MAX77650_REG_STAT_CHG_A 0x02 +#define MAX77650_REG_STAT_CHG_B 0x03 +#define MAX77650_REG_ERCFLAG 0x04 +#define MAX77650_REG_STAT_GLBL 0x05 +#define MAX77650_REG_INTM_GLBL 0x06 +#define MAX77650_REG_INTM_CHG 0x07 +#define MAX77650_REG_CNFG_GLBL 0x10 +#define MAX77650_REG_CID 0x11 +#define MAX77650_REG_CNFG_GPIO 0x12 +#define MAX77650_REG_CNFG_CHG_A 0x18 +#define MAX77650_REG_CNFG_CHG_B 0x19 +#define MAX77650_REG_CNFG_CHG_C 0x1a +#define MAX77650_REG_CNFG_CHG_D 0x1b +#define MAX77650_REG_CNFG_CHG_E 0x1c +#define MAX77650_REG_CNFG_CHG_F 0x1d +#define MAX77650_REG_CNFG_CHG_G 0x1e +#define MAX77650_REG_CNFG_CHG_H 0x1f +#define MAX77650_REG_CNFG_CHG_I 0x20 +#define MAX77650_REG_CNFG_SBB_TOP 0x28 +#define MAX77650_REG_CNFG_SBB0_A 0x29 +#define MAX77650_REG_CNFG_SBB0_B 0x2a +#define MAX77650_REG_CNFG_SBB1_A 0x2b +#define MAX77650_REG_CNFG_SBB1_B 0x2c +#define MAX77650_REG_CNFG_SBB2_A 0x2d +#define MAX77650_REG_CNFG_SBB2_B 0x2e +#define MAX77650_REG_CNFG_LDO_A 0x38 +#define MAX77650_REG_CNFG_LDO_B 0x39 +#define MAX77650_REG_CNFG_LED0_A 0x40 +#define MAX77650_REG_CNFG_LED1_A 0x41 +#define MAX77650_REG_CNFG_LED2_A 0x42 +#define MAX77650_REG_CNFG_LED0_B 0x43 +#define MAX77650_REG_CNFG_LED1_B 0x44 +#define MAX77650_REG_CNFG_LED2_B 0x45 +#define MAX77650_REG_CNFG_LED_TOP 0x46 + +#define MAX77650_CID_MASK GENMASK(3, 0) +#define MAX77650_CID_BITS(_reg) (_reg & MAX77650_CID_MASK) + +#define MAX77650_CID_77650A 0x03 +#define MAX77650_CID_77650C 0x0a +#define MAX77650_CID_77651A 0x06 +#define MAX77650_CID_77651B 0x08 + +#endif /* MAX77650_H */ -- cgit v1.2.3-71-gd317 From ea611d1cc180fbb56982c83cd5142a2b34881f5c Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 5 May 2019 18:43:22 +0300 Subject: mfd: max77620: Fix swapped FPS_PERIOD_MAX_US values The FPS_PERIOD_MAX_US definitions are swapped for MAX20024 and MAX77620, fix it. Cc: stable Signed-off-by: Dmitry Osipenko Signed-off-by: Lee Jones --- include/linux/mfd/max77620.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/mfd/max77620.h b/include/linux/mfd/max77620.h index ad2a9a852aea..b4fd5a7c2aaa 100644 --- a/include/linux/mfd/max77620.h +++ b/include/linux/mfd/max77620.h @@ -136,8 +136,8 @@ #define MAX77620_FPS_PERIOD_MIN_US 40 #define MAX20024_FPS_PERIOD_MIN_US 20 -#define MAX77620_FPS_PERIOD_MAX_US 2560 -#define MAX20024_FPS_PERIOD_MAX_US 5120 +#define MAX20024_FPS_PERIOD_MAX_US 2560 +#define MAX77620_FPS_PERIOD_MAX_US 5120 #define MAX77620_REG_FPS_GPIO1 0x54 #define MAX77620_REG_FPS_GPIO2 0x55 -- cgit v1.2.3-71-gd317 From 4c58f7012f15a71f05cd447f7658a61376d11591 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 5 May 2019 18:43:23 +0300 Subject: mfd: max77620: Support Maxim 77663 Add support for Maxim 77663 using the Max77620 driver. The hardware is very similar to Max77663/20024, although there are couple minor differences. Signed-off-by: Dmitry Osipenko Signed-off-by: Lee Jones --- drivers/mfd/max77620.c | 69 +++++++++++++++++++++++++++++++++++++++++++- include/linux/mfd/max77620.h | 1 + 2 files changed, 69 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c index d8ddd1a6f304..c2d88a5eca7a 100644 --- a/drivers/mfd/max77620.c +++ b/drivers/mfd/max77620.c @@ -111,6 +111,26 @@ static const struct mfd_cell max20024_children[] = { }, }; +static const struct mfd_cell max77663_children[] = { + { .name = "max77620-pinctrl", }, + { .name = "max77620-clock", }, + { .name = "max77663-pmic", }, + { .name = "max77620-watchdog", }, + { + .name = "max77620-gpio", + .resources = gpio_resources, + .num_resources = ARRAY_SIZE(gpio_resources), + }, { + .name = "max77620-rtc", + .resources = rtc_resources, + .num_resources = ARRAY_SIZE(rtc_resources), + }, { + .name = "max77663-power", + .resources = power_resources, + .num_resources = ARRAY_SIZE(power_resources), + }, +}; + static const struct regmap_range max77620_readable_ranges[] = { regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_DVSSD4), }; @@ -171,6 +191,35 @@ static const struct regmap_config max20024_regmap_config = { .volatile_table = &max77620_volatile_table, }; +static const struct regmap_range max77663_readable_ranges[] = { + regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_CID5), +}; + +static const struct regmap_access_table max77663_readable_table = { + .yes_ranges = max77663_readable_ranges, + .n_yes_ranges = ARRAY_SIZE(max77663_readable_ranges), +}; + +static const struct regmap_range max77663_writable_ranges[] = { + regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_CID5), +}; + +static const struct regmap_access_table max77663_writable_table = { + .yes_ranges = max77663_writable_ranges, + .n_yes_ranges = ARRAY_SIZE(max77663_writable_ranges), +}; + +static const struct regmap_config max77663_regmap_config = { + .name = "power-slave", + .reg_bits = 8, + .val_bits = 8, + .max_register = MAX77620_REG_CID5 + 1, + .cache_type = REGCACHE_RBTREE, + .rd_table = &max77663_readable_table, + .wr_table = &max77663_writable_table, + .volatile_table = &max77620_volatile_table, +}; + /* * MAX77620 and MAX20024 has the following steps of the interrupt handling * for TOP interrupts: @@ -240,6 +289,9 @@ static int max77620_get_fps_period_reg_value(struct max77620_chip *chip, case MAX77620: fps_min_period = MAX77620_FPS_PERIOD_MIN_US; break; + case MAX77663: + fps_min_period = MAX20024_FPS_PERIOD_MIN_US; + break; default: return -EINVAL; } @@ -274,6 +326,9 @@ static int max77620_config_fps(struct max77620_chip *chip, case MAX77620: fps_max_period = MAX77620_FPS_PERIOD_MAX_US; break; + case MAX77663: + fps_max_period = MAX20024_FPS_PERIOD_MAX_US; + break; default: return -EINVAL; } @@ -375,6 +430,9 @@ static int max77620_initialise_fps(struct max77620_chip *chip) } skip_fps: + if (chip->chip_id == MAX77663) + return 0; + /* Enable wake on EN0 pin */ ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2, MAX77620_ONOFFCNFG2_WK_EN0, @@ -453,6 +511,11 @@ static int max77620_probe(struct i2c_client *client, n_mfd_cells = ARRAY_SIZE(max20024_children); rmap_config = &max20024_regmap_config; break; + case MAX77663: + mfd_cells = max77663_children; + n_mfd_cells = ARRAY_SIZE(max77663_children); + rmap_config = &max77663_regmap_config; + break; default: dev_err(chip->dev, "ChipID is invalid %d\n", chip->chip_id); return -EINVAL; @@ -546,6 +609,9 @@ static int max77620_i2c_suspend(struct device *dev) return ret; } + if (chip->chip_id == MAX77663) + goto out; + /* Disable WK_EN0 */ ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2, MAX77620_ONOFFCNFG2_WK_EN0, 0); @@ -581,7 +647,7 @@ static int max77620_i2c_resume(struct device *dev) * For MAX20024: No need to configure WKEN0 on resume as * it is configured on Init. */ - if (chip->chip_id == MAX20024) + if (chip->chip_id == MAX20024 || chip->chip_id == MAX77663) goto out; /* Enable WK_EN0 */ @@ -603,6 +669,7 @@ out: static const struct i2c_device_id max77620_id[] = { {"max77620", MAX77620}, {"max20024", MAX20024}, + {"max77663", MAX77663}, {}, }; diff --git a/include/linux/mfd/max77620.h b/include/linux/mfd/max77620.h index b4fd5a7c2aaa..82407fe85ca2 100644 --- a/include/linux/mfd/max77620.h +++ b/include/linux/mfd/max77620.h @@ -324,6 +324,7 @@ enum max77620_fps_src { enum max77620_chip_id { MAX77620, MAX20024, + MAX77663, }; struct max77620_chip { -- cgit v1.2.3-71-gd317 From 06252ade91566574c900975037aaa33d6c4f9818 Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Thu, 9 May 2019 10:58:49 +0200 Subject: mfd: Add ST Multi-Function eXpander (STMFX) core driver STMicroelectronics Multi-Function eXpander (STMFX) is a slave controller using I2C for communication with the main MCU. Main features are: - 16 fast GPIOs individually configurable in input/output - 8 alternate GPIOs individually configurable in input/output when other STMFX functions are not used - Main MCU IDD measurement - Resistive touchscreen controller Signed-off-by: Amelie Delaunay Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 13 ++ drivers/mfd/Makefile | 2 +- drivers/mfd/stmfx.c | 545 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/mfd/stmfx.h | 123 +++++++++++ 4 files changed, 682 insertions(+), 1 deletion(-) create mode 100644 drivers/mfd/stmfx.c create mode 100644 include/linux/mfd/stmfx.h (limited to 'include/linux') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 26ad6468d13a..87c55249dff2 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1907,6 +1907,19 @@ config MFD_STPMIC1 To compile this driver as a module, choose M here: the module will be called stpmic1. +config MFD_STMFX + tristate "Support for STMicroelectronics Multi-Function eXpander (STMFX)" + depends on I2C + depends on OF || COMPILE_TEST + select MFD_CORE + select REGMAP_I2C + help + Support for the STMicroelectronics Multi-Function eXpander. + + This driver provides common support for accessing the device, + additional drivers must be enabled in order to use the functionality + of the device. + menu "Multimedia Capabilities Port drivers" depends on ARCH_SA1100 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index b4569ed7f3f3..614eea87990e 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -246,4 +246,4 @@ 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_BD718XX) += rohm-bd718x7.o - +obj-$(CONFIG_MFD_STMFX) += stmfx.o diff --git a/drivers/mfd/stmfx.c b/drivers/mfd/stmfx.c new file mode 100644 index 000000000000..fe8efba2d45f --- /dev/null +++ b/drivers/mfd/stmfx.c @@ -0,0 +1,545 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for STMicroelectronics Multi-Function eXpander (STMFX) core + * + * Copyright (C) 2019 STMicroelectronics + * Author(s): Amelie Delaunay . + */ +#include +#include +#include +#include +#include +#include +#include +#include + +static bool stmfx_reg_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case STMFX_REG_SYS_CTRL: + case STMFX_REG_IRQ_SRC_EN: + case STMFX_REG_IRQ_PENDING: + case STMFX_REG_IRQ_GPI_PENDING1: + case STMFX_REG_IRQ_GPI_PENDING2: + case STMFX_REG_IRQ_GPI_PENDING3: + case STMFX_REG_GPIO_STATE1: + case STMFX_REG_GPIO_STATE2: + case STMFX_REG_GPIO_STATE3: + case STMFX_REG_IRQ_GPI_SRC1: + case STMFX_REG_IRQ_GPI_SRC2: + case STMFX_REG_IRQ_GPI_SRC3: + case STMFX_REG_GPO_SET1: + case STMFX_REG_GPO_SET2: + case STMFX_REG_GPO_SET3: + case STMFX_REG_GPO_CLR1: + case STMFX_REG_GPO_CLR2: + case STMFX_REG_GPO_CLR3: + return true; + default: + return false; + } +} + +static bool stmfx_reg_writeable(struct device *dev, unsigned int reg) +{ + return (reg >= STMFX_REG_SYS_CTRL); +} + +static const struct regmap_config stmfx_regmap_config = { + .reg_bits = 8, + .reg_stride = 1, + .val_bits = 8, + .max_register = STMFX_REG_MAX, + .volatile_reg = stmfx_reg_volatile, + .writeable_reg = stmfx_reg_writeable, + .cache_type = REGCACHE_RBTREE, +}; + +static const struct resource stmfx_pinctrl_resources[] = { + DEFINE_RES_IRQ(STMFX_REG_IRQ_SRC_EN_GPIO), +}; + +static const struct resource stmfx_idd_resources[] = { + DEFINE_RES_IRQ(STMFX_REG_IRQ_SRC_EN_IDD), + DEFINE_RES_IRQ(STMFX_REG_IRQ_SRC_EN_ERROR), +}; + +static const struct resource stmfx_ts_resources[] = { + DEFINE_RES_IRQ(STMFX_REG_IRQ_SRC_EN_TS_DET), + DEFINE_RES_IRQ(STMFX_REG_IRQ_SRC_EN_TS_NE), + DEFINE_RES_IRQ(STMFX_REG_IRQ_SRC_EN_TS_TH), + DEFINE_RES_IRQ(STMFX_REG_IRQ_SRC_EN_TS_FULL), + DEFINE_RES_IRQ(STMFX_REG_IRQ_SRC_EN_TS_OVF), +}; + +static struct mfd_cell stmfx_cells[] = { + { + .of_compatible = "st,stmfx-0300-pinctrl", + .name = "stmfx-pinctrl", + .resources = stmfx_pinctrl_resources, + .num_resources = ARRAY_SIZE(stmfx_pinctrl_resources), + }, + { + .of_compatible = "st,stmfx-0300-idd", + .name = "stmfx-idd", + .resources = stmfx_idd_resources, + .num_resources = ARRAY_SIZE(stmfx_idd_resources), + }, + { + .of_compatible = "st,stmfx-0300-ts", + .name = "stmfx-ts", + .resources = stmfx_ts_resources, + .num_resources = ARRAY_SIZE(stmfx_ts_resources), + }, +}; + +static u8 stmfx_func_to_mask(u32 func) +{ + u8 mask = 0; + + if (func & STMFX_FUNC_GPIO) + mask |= STMFX_REG_SYS_CTRL_GPIO_EN; + + if ((func & STMFX_FUNC_ALTGPIO_LOW) || (func & STMFX_FUNC_ALTGPIO_HIGH)) + mask |= STMFX_REG_SYS_CTRL_ALTGPIO_EN; + + if (func & STMFX_FUNC_TS) + mask |= STMFX_REG_SYS_CTRL_TS_EN; + + if (func & STMFX_FUNC_IDD) + mask |= STMFX_REG_SYS_CTRL_IDD_EN; + + return mask; +} + +int stmfx_function_enable(struct stmfx *stmfx, u32 func) +{ + u32 sys_ctrl; + u8 mask; + int ret; + + ret = regmap_read(stmfx->map, STMFX_REG_SYS_CTRL, &sys_ctrl); + if (ret) + return ret; + + /* + * IDD and TS have priority in STMFX FW, so if IDD and TS are enabled, + * ALTGPIO function is disabled by STMFX FW. If IDD or TS is enabled, + * the number of aGPIO available decreases. To avoid GPIO management + * disturbance, abort IDD or TS function enable in this case. + */ + if (((func & STMFX_FUNC_IDD) || (func & STMFX_FUNC_TS)) && + (sys_ctrl & STMFX_REG_SYS_CTRL_ALTGPIO_EN)) { + dev_err(stmfx->dev, "ALTGPIO function already enabled\n"); + return -EBUSY; + } + + /* If TS is enabled, aGPIO[3:0] cannot be used */ + if ((func & STMFX_FUNC_ALTGPIO_LOW) && + (sys_ctrl & STMFX_REG_SYS_CTRL_TS_EN)) { + dev_err(stmfx->dev, "TS in use, aGPIO[3:0] unavailable\n"); + return -EBUSY; + } + + /* If IDD is enabled, aGPIO[7:4] cannot be used */ + if ((func & STMFX_FUNC_ALTGPIO_HIGH) && + (sys_ctrl & STMFX_REG_SYS_CTRL_IDD_EN)) { + dev_err(stmfx->dev, "IDD in use, aGPIO[7:4] unavailable\n"); + return -EBUSY; + } + + mask = stmfx_func_to_mask(func); + + return regmap_update_bits(stmfx->map, STMFX_REG_SYS_CTRL, mask, mask); +} +EXPORT_SYMBOL_GPL(stmfx_function_enable); + +int stmfx_function_disable(struct stmfx *stmfx, u32 func) +{ + u8 mask = stmfx_func_to_mask(func); + + return regmap_update_bits(stmfx->map, STMFX_REG_SYS_CTRL, mask, 0); +} +EXPORT_SYMBOL_GPL(stmfx_function_disable); + +static void stmfx_irq_bus_lock(struct irq_data *data) +{ + struct stmfx *stmfx = irq_data_get_irq_chip_data(data); + + mutex_lock(&stmfx->lock); +} + +static void stmfx_irq_bus_sync_unlock(struct irq_data *data) +{ + struct stmfx *stmfx = irq_data_get_irq_chip_data(data); + + regmap_write(stmfx->map, STMFX_REG_IRQ_SRC_EN, stmfx->irq_src); + + mutex_unlock(&stmfx->lock); +} + +static void stmfx_irq_mask(struct irq_data *data) +{ + struct stmfx *stmfx = irq_data_get_irq_chip_data(data); + + stmfx->irq_src &= ~BIT(data->hwirq % 8); +} + +static void stmfx_irq_unmask(struct irq_data *data) +{ + struct stmfx *stmfx = irq_data_get_irq_chip_data(data); + + stmfx->irq_src |= BIT(data->hwirq % 8); +} + +static struct irq_chip stmfx_irq_chip = { + .name = "stmfx-core", + .irq_bus_lock = stmfx_irq_bus_lock, + .irq_bus_sync_unlock = stmfx_irq_bus_sync_unlock, + .irq_mask = stmfx_irq_mask, + .irq_unmask = stmfx_irq_unmask, +}; + +static irqreturn_t stmfx_irq_handler(int irq, void *data) +{ + struct stmfx *stmfx = data; + unsigned long n, pending; + u32 ack; + int ret; + + ret = regmap_read(stmfx->map, STMFX_REG_IRQ_PENDING, + (u32 *)&pending); + if (ret) + return IRQ_NONE; + + /* + * There is no ACK for GPIO, MFX_REG_IRQ_PENDING_GPIO is a logical OR + * of MFX_REG_IRQ_GPI _PENDING1/_PENDING2/_PENDING3 + */ + ack = pending & ~BIT(STMFX_REG_IRQ_SRC_EN_GPIO); + if (ack) { + ret = regmap_write(stmfx->map, STMFX_REG_IRQ_ACK, ack); + if (ret) + return IRQ_NONE; + } + + for_each_set_bit(n, &pending, STMFX_REG_IRQ_SRC_MAX) + handle_nested_irq(irq_find_mapping(stmfx->irq_domain, n)); + + return IRQ_HANDLED; +} + +static int stmfx_irq_map(struct irq_domain *d, unsigned int virq, + irq_hw_number_t hwirq) +{ + irq_set_chip_data(virq, d->host_data); + irq_set_chip_and_handler(virq, &stmfx_irq_chip, handle_simple_irq); + irq_set_nested_thread(virq, 1); + irq_set_noprobe(virq); + + return 0; +} + +static void stmfx_irq_unmap(struct irq_domain *d, unsigned int virq) +{ + irq_set_chip_and_handler(virq, NULL, NULL); + irq_set_chip_data(virq, NULL); +} + +static const struct irq_domain_ops stmfx_irq_ops = { + .map = stmfx_irq_map, + .unmap = stmfx_irq_unmap, +}; + +static void stmfx_irq_exit(struct i2c_client *client) +{ + struct stmfx *stmfx = i2c_get_clientdata(client); + int hwirq; + + for (hwirq = 0; hwirq < STMFX_REG_IRQ_SRC_MAX; hwirq++) + irq_dispose_mapping(irq_find_mapping(stmfx->irq_domain, hwirq)); + + irq_domain_remove(stmfx->irq_domain); +} + +static int stmfx_irq_init(struct i2c_client *client) +{ + struct stmfx *stmfx = i2c_get_clientdata(client); + u32 irqoutpin = 0, irqtrigger; + int ret; + + stmfx->irq_domain = irq_domain_add_simple(stmfx->dev->of_node, + STMFX_REG_IRQ_SRC_MAX, 0, + &stmfx_irq_ops, stmfx); + if (!stmfx->irq_domain) { + dev_err(stmfx->dev, "Failed to create IRQ domain\n"); + return -EINVAL; + } + + if (!of_property_read_bool(stmfx->dev->of_node, "drive-open-drain")) + irqoutpin |= STMFX_REG_IRQ_OUT_PIN_TYPE; + + irqtrigger = irq_get_trigger_type(client->irq); + if ((irqtrigger & IRQ_TYPE_EDGE_RISING) || + (irqtrigger & IRQ_TYPE_LEVEL_HIGH)) + irqoutpin |= STMFX_REG_IRQ_OUT_PIN_POL; + + ret = regmap_write(stmfx->map, STMFX_REG_IRQ_OUT_PIN, irqoutpin); + if (ret) + return ret; + + ret = devm_request_threaded_irq(stmfx->dev, client->irq, + NULL, stmfx_irq_handler, + irqtrigger | IRQF_ONESHOT, + "stmfx", stmfx); + if (ret) + stmfx_irq_exit(client); + + return ret; +} + +static int stmfx_chip_reset(struct stmfx *stmfx) +{ + int ret; + + ret = regmap_write(stmfx->map, STMFX_REG_SYS_CTRL, + STMFX_REG_SYS_CTRL_SWRST); + if (ret) + return ret; + + msleep(STMFX_BOOT_TIME_MS); + + return ret; +} + +static int stmfx_chip_init(struct i2c_client *client) +{ + struct stmfx *stmfx = i2c_get_clientdata(client); + u32 id; + u8 version[2]; + int ret; + + stmfx->vdd = devm_regulator_get_optional(&client->dev, "vdd"); + ret = PTR_ERR_OR_ZERO(stmfx->vdd); + if (ret == -ENODEV) { + stmfx->vdd = NULL; + } else if (ret == -EPROBE_DEFER) { + return ret; + } else if (ret) { + dev_err(&client->dev, "Failed to get VDD regulator: %d\n", ret); + return ret; + } + + if (stmfx->vdd) { + ret = regulator_enable(stmfx->vdd); + if (ret) { + dev_err(&client->dev, "VDD enable failed: %d\n", ret); + return ret; + } + } + + ret = regmap_read(stmfx->map, STMFX_REG_CHIP_ID, &id); + if (ret) { + dev_err(&client->dev, "Error reading chip ID: %d\n", ret); + goto err; + } + + /* + * Check that ID is the complement of the I2C address: + * STMFX I2C address follows the 7-bit format (MSB), that's why + * client->addr is shifted. + * + * STMFX_I2C_ADDR| STMFX | Linux + * input pin | I2C device address | I2C device address + *--------------------------------------------------------- + * 0 | b: 1000 010x h:0x84 | 0x42 + * 1 | b: 1000 011x h:0x86 | 0x43 + */ + if (FIELD_GET(STMFX_REG_CHIP_ID_MASK, ~id) != (client->addr << 1)) { + dev_err(&client->dev, "Unknown chip ID: %#x\n", id); + ret = -EINVAL; + goto err; + } + + ret = regmap_bulk_read(stmfx->map, STMFX_REG_FW_VERSION_MSB, + version, ARRAY_SIZE(version)); + if (ret) { + dev_err(&client->dev, "Error reading FW version: %d\n", ret); + goto err; + } + + dev_info(&client->dev, "STMFX id: %#x, fw version: %x.%02x\n", + id, version[0], version[1]); + + ret = stmfx_chip_reset(stmfx); + if (ret) { + dev_err(&client->dev, "Failed to reset chip: %d\n", ret); + goto err; + } + + return 0; + +err: + if (stmfx->vdd) + return regulator_disable(stmfx->vdd); + + return ret; +} + +static int stmfx_chip_exit(struct i2c_client *client) +{ + struct stmfx *stmfx = i2c_get_clientdata(client); + + regmap_write(stmfx->map, STMFX_REG_IRQ_SRC_EN, 0); + regmap_write(stmfx->map, STMFX_REG_SYS_CTRL, 0); + + if (stmfx->vdd) + return regulator_disable(stmfx->vdd); + + return 0; +} + +static int stmfx_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct stmfx *stmfx; + int ret; + + stmfx = devm_kzalloc(dev, sizeof(*stmfx), GFP_KERNEL); + if (!stmfx) + return -ENOMEM; + + i2c_set_clientdata(client, stmfx); + + stmfx->dev = dev; + + stmfx->map = devm_regmap_init_i2c(client, &stmfx_regmap_config); + if (IS_ERR(stmfx->map)) { + ret = PTR_ERR(stmfx->map); + dev_err(dev, "Failed to allocate register map: %d\n", ret); + return ret; + } + + mutex_init(&stmfx->lock); + + ret = stmfx_chip_init(client); + if (ret) { + if (ret == -ETIMEDOUT) + return -EPROBE_DEFER; + return ret; + } + + if (client->irq < 0) { + dev_err(dev, "Failed to get IRQ: %d\n", client->irq); + ret = client->irq; + goto err_chip_exit; + } + + ret = stmfx_irq_init(client); + if (ret) + goto err_chip_exit; + + ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, + stmfx_cells, ARRAY_SIZE(stmfx_cells), NULL, + 0, stmfx->irq_domain); + if (ret) + goto err_irq_exit; + + return 0; + +err_irq_exit: + stmfx_irq_exit(client); +err_chip_exit: + stmfx_chip_exit(client); + + return ret; +} + +static int stmfx_remove(struct i2c_client *client) +{ + stmfx_irq_exit(client); + + return stmfx_chip_exit(client); +} + +#ifdef CONFIG_PM_SLEEP +static int stmfx_suspend(struct device *dev) +{ + struct stmfx *stmfx = dev_get_drvdata(dev); + int ret; + + ret = regmap_raw_read(stmfx->map, STMFX_REG_SYS_CTRL, + &stmfx->bkp_sysctrl, sizeof(stmfx->bkp_sysctrl)); + if (ret) + return ret; + + ret = regmap_raw_read(stmfx->map, STMFX_REG_IRQ_OUT_PIN, + &stmfx->bkp_irqoutpin, + sizeof(stmfx->bkp_irqoutpin)); + if (ret) + return ret; + + if (stmfx->vdd) + return regulator_disable(stmfx->vdd); + + return 0; +} + +static int stmfx_resume(struct device *dev) +{ + struct stmfx *stmfx = dev_get_drvdata(dev); + int ret; + + if (stmfx->vdd) { + ret = regulator_enable(stmfx->vdd); + if (ret) { + dev_err(stmfx->dev, + "VDD enable failed: %d\n", ret); + return ret; + } + } + + ret = regmap_raw_write(stmfx->map, STMFX_REG_SYS_CTRL, + &stmfx->bkp_sysctrl, sizeof(stmfx->bkp_sysctrl)); + if (ret) + return ret; + + ret = regmap_raw_write(stmfx->map, STMFX_REG_IRQ_OUT_PIN, + &stmfx->bkp_irqoutpin, + sizeof(stmfx->bkp_irqoutpin)); + if (ret) + return ret; + + ret = regmap_raw_write(stmfx->map, STMFX_REG_IRQ_SRC_EN, + &stmfx->irq_src, sizeof(stmfx->irq_src)); + if (ret) + return ret; + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(stmfx_dev_pm_ops, stmfx_suspend, stmfx_resume); + +static const struct of_device_id stmfx_of_match[] = { + { .compatible = "st,stmfx-0300", }, + {}, +}; +MODULE_DEVICE_TABLE(of, stmfx_of_match); + +static struct i2c_driver stmfx_driver = { + .driver = { + .name = "stmfx-core", + .of_match_table = of_match_ptr(stmfx_of_match), + .pm = &stmfx_dev_pm_ops, + }, + .probe = stmfx_probe, + .remove = stmfx_remove, +}; +module_i2c_driver(stmfx_driver); + +MODULE_DESCRIPTION("STMFX core driver"); +MODULE_AUTHOR("Amelie Delaunay "); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/mfd/stmfx.h b/include/linux/mfd/stmfx.h new file mode 100644 index 000000000000..d890595b89b6 --- /dev/null +++ b/include/linux/mfd/stmfx.h @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2019 STMicroelectronics + * Author(s): Amelie Delaunay . + */ + +#ifndef MFD_STMFX_H +#define MFX_STMFX_H + +#include + +/* General */ +#define STMFX_REG_CHIP_ID 0x00 /* R */ +#define STMFX_REG_FW_VERSION_MSB 0x01 /* R */ +#define STMFX_REG_FW_VERSION_LSB 0x02 /* R */ +#define STMFX_REG_SYS_CTRL 0x40 /* RW */ +/* IRQ output management */ +#define STMFX_REG_IRQ_OUT_PIN 0x41 /* RW */ +#define STMFX_REG_IRQ_SRC_EN 0x42 /* RW */ +#define STMFX_REG_IRQ_PENDING 0x08 /* R */ +#define STMFX_REG_IRQ_ACK 0x44 /* RW */ +/* GPIO management */ +#define STMFX_REG_IRQ_GPI_PENDING1 0x0C /* R */ +#define STMFX_REG_IRQ_GPI_PENDING2 0x0D /* R */ +#define STMFX_REG_IRQ_GPI_PENDING3 0x0E /* R */ +#define STMFX_REG_GPIO_STATE1 0x10 /* R */ +#define STMFX_REG_GPIO_STATE2 0x11 /* R */ +#define STMFX_REG_GPIO_STATE3 0x12 /* R */ +#define STMFX_REG_IRQ_GPI_SRC1 0x48 /* RW */ +#define STMFX_REG_IRQ_GPI_SRC2 0x49 /* RW */ +#define STMFX_REG_IRQ_GPI_SRC3 0x4A /* RW */ +#define STMFX_REG_IRQ_GPI_EVT1 0x4C /* RW */ +#define STMFX_REG_IRQ_GPI_EVT2 0x4D /* RW */ +#define STMFX_REG_IRQ_GPI_EVT3 0x4E /* RW */ +#define STMFX_REG_IRQ_GPI_TYPE1 0x50 /* RW */ +#define STMFX_REG_IRQ_GPI_TYPE2 0x51 /* RW */ +#define STMFX_REG_IRQ_GPI_TYPE3 0x52 /* RW */ +#define STMFX_REG_IRQ_GPI_ACK1 0x54 /* RW */ +#define STMFX_REG_IRQ_GPI_ACK2 0x55 /* RW */ +#define STMFX_REG_IRQ_GPI_ACK3 0x56 /* RW */ +#define STMFX_REG_GPIO_DIR1 0x60 /* RW */ +#define STMFX_REG_GPIO_DIR2 0x61 /* RW */ +#define STMFX_REG_GPIO_DIR3 0x62 /* RW */ +#define STMFX_REG_GPIO_TYPE1 0x64 /* RW */ +#define STMFX_REG_GPIO_TYPE2 0x65 /* RW */ +#define STMFX_REG_GPIO_TYPE3 0x66 /* RW */ +#define STMFX_REG_GPIO_PUPD1 0x68 /* RW */ +#define STMFX_REG_GPIO_PUPD2 0x69 /* RW */ +#define STMFX_REG_GPIO_PUPD3 0x6A /* RW */ +#define STMFX_REG_GPO_SET1 0x6C /* RW */ +#define STMFX_REG_GPO_SET2 0x6D /* RW */ +#define STMFX_REG_GPO_SET3 0x6E /* RW */ +#define STMFX_REG_GPO_CLR1 0x70 /* RW */ +#define STMFX_REG_GPO_CLR2 0x71 /* RW */ +#define STMFX_REG_GPO_CLR3 0x72 /* RW */ + +#define STMFX_REG_MAX 0xB0 + +/* MFX boot time is around 10ms, so after reset, we have to wait this delay */ +#define STMFX_BOOT_TIME_MS 10 + +/* STMFX_REG_CHIP_ID bitfields */ +#define STMFX_REG_CHIP_ID_MASK GENMASK(7, 0) + +/* STMFX_REG_SYS_CTRL bitfields */ +#define STMFX_REG_SYS_CTRL_GPIO_EN BIT(0) +#define STMFX_REG_SYS_CTRL_TS_EN BIT(1) +#define STMFX_REG_SYS_CTRL_IDD_EN BIT(2) +#define STMFX_REG_SYS_CTRL_ALTGPIO_EN BIT(3) +#define STMFX_REG_SYS_CTRL_SWRST BIT(7) + +/* STMFX_REG_IRQ_OUT_PIN bitfields */ +#define STMFX_REG_IRQ_OUT_PIN_TYPE BIT(0) /* 0-OD 1-PP */ +#define STMFX_REG_IRQ_OUT_PIN_POL BIT(1) /* 0-active LOW 1-active HIGH */ + +/* STMFX_REG_IRQ_(SRC_EN/PENDING/ACK) bit shift */ +enum stmfx_irqs { + STMFX_REG_IRQ_SRC_EN_GPIO = 0, + STMFX_REG_IRQ_SRC_EN_IDD, + STMFX_REG_IRQ_SRC_EN_ERROR, + STMFX_REG_IRQ_SRC_EN_TS_DET, + STMFX_REG_IRQ_SRC_EN_TS_NE, + STMFX_REG_IRQ_SRC_EN_TS_TH, + STMFX_REG_IRQ_SRC_EN_TS_FULL, + STMFX_REG_IRQ_SRC_EN_TS_OVF, + STMFX_REG_IRQ_SRC_MAX, +}; + +enum stmfx_functions { + STMFX_FUNC_GPIO = BIT(0), /* GPIO[15:0] */ + STMFX_FUNC_ALTGPIO_LOW = BIT(1), /* aGPIO[3:0] */ + STMFX_FUNC_ALTGPIO_HIGH = BIT(2), /* aGPIO[7:4] */ + STMFX_FUNC_TS = BIT(3), + STMFX_FUNC_IDD = BIT(4), +}; + +/** + * struct stmfx_ddata - STMFX MFD structure + * @device: device reference used for logs + * @map: register map + * @vdd: STMFX power supply + * @irq_domain: IRQ domain + * @lock: IRQ bus lock + * @irq_src: cache of IRQ_SRC_EN register for bus_lock + * @bkp_sysctrl: backup of SYS_CTRL register for suspend/resume + * @bkp_irqoutpin: backup of IRQ_OUT_PIN register for suspend/resume + */ +struct stmfx { + struct device *dev; + struct regmap *map; + struct regulator *vdd; + struct irq_domain *irq_domain; + struct mutex lock; /* IRQ bus lock */ + u8 irq_src; +#ifdef CONFIG_PM + u8 bkp_sysctrl; + u8 bkp_irqoutpin; +#endif +}; + +int stmfx_function_enable(struct stmfx *stmfx, u32 func); +int stmfx_function_disable(struct stmfx *stmfx, u32 func); +#endif -- cgit v1.2.3-71-gd317 From d4cee9509e508df34d1dbfad6b42e5bf907d20fd Mon Sep 17 00:00:00 2001 From: Rushikesh S Kadam Date: Fri, 1 Mar 2019 13:50:54 +0530 Subject: mfd: cros_ec: Instantiate properly CrOS ISH MCU device Integrated Sensor Hub (ISH) is also a MCU running EC having feature bit EC_FEATURE_ISH. Instantiate it as a special CrOS EC device with device name 'cros_ish'. Signed-off-by: Rushikesh S Kadam Reviewed-by: Andy Shevchenko Acked-by: Enric Balletbo i Serra Reviewed-by: Gwendal Grignou Signed-off-by: Lee Jones --- drivers/mfd/cros_ec_dev.c | 13 +++++++++++++ include/linux/mfd/cros_ec.h | 1 + include/linux/mfd/cros_ec_commands.h | 2 ++ 3 files changed, 16 insertions(+) (limited to 'include/linux') diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c index d275deaecb12..596f124f2a54 100644 --- a/drivers/mfd/cros_ec_dev.c +++ b/drivers/mfd/cros_ec_dev.c @@ -418,6 +418,19 @@ static int ec_device_probe(struct platform_device *pdev) device_initialize(&ec->class_dev); cdev_init(&ec->cdev, &fops); + /* + * Check whether this is actually an Integrated Sensor Hub (ISH) + * rather than an EC. + */ + if (cros_ec_check_features(ec, EC_FEATURE_ISH)) { + dev_info(dev, "CrOS ISH MCU detected.\n"); + /* + * Help userspace differentiating ECs from ISH MCU, + * regardless of the probing order. + */ + ec_platform->ec_name = CROS_EC_DEV_ISH_NAME; + } + /* * Add the class device * Link to the character device for creating the /dev entry diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h index 8f2a8918bfa3..109292a60499 100644 --- a/include/linux/mfd/cros_ec.h +++ b/include/linux/mfd/cros_ec.h @@ -24,6 +24,7 @@ #define CROS_EC_DEV_NAME "cros_ec" #define CROS_EC_DEV_PD_NAME "cros_pd" +#define CROS_EC_DEV_ISH_NAME "cros_ish" /* * The EC is unresponsive for a time after a reboot command. Add a diff --git a/include/linux/mfd/cros_ec_commands.h b/include/linux/mfd/cros_ec_commands.h index fc91082d4c35..43bee4f7d137 100644 --- a/include/linux/mfd/cros_ec_commands.h +++ b/include/linux/mfd/cros_ec_commands.h @@ -856,6 +856,8 @@ enum ec_feature_code { EC_FEATURE_RTC = 27, /* EC supports CEC commands */ EC_FEATURE_CEC = 35, + /* The MCU is an Integrated Sensor Hub */ + EC_FEATURE_ISH = 40, }; #define EC_FEATURE_MASK_0(event_code) (1UL << (event_code % 32)) -- cgit v1.2.3-71-gd317 From 9efbc6f175c017324befce493d2962109a216552 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 18 Mar 2019 16:57:24 +0100 Subject: mfd: da9063: Convert headers to SPDX Covnert the headers of the source and include files to SPDX. And fix some typos in the descriptions ("interrupt" instead of "I2C"). Signed-off-by: Wolfram Sang Acked-by: Steve Twiss Reviewed-by: Simon Horman Signed-off-by: Lee Jones --- drivers/mfd/da9063-core.c | 8 ++------ drivers/mfd/da9063-i2c.c | 9 ++------- drivers/mfd/da9063-irq.c | 9 ++------- include/linux/mfd/da9063/core.h | 7 +------ include/linux/mfd/da9063/registers.h | 7 +------ 5 files changed, 8 insertions(+), 32 deletions(-) (limited to 'include/linux') diff --git a/drivers/mfd/da9063-core.c b/drivers/mfd/da9063-core.c index 6e4ce49b4405..4e5ebb7f2ef0 100644 --- a/drivers/mfd/da9063-core.c +++ b/drivers/mfd/da9063-core.c @@ -1,5 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * da9063-core.c: Device access for Dialog DA9063 modules + * Device access for Dialog DA9063 modules * * Copyright 2012 Dialog Semiconductors Ltd. * Copyright 2013 Philipp Zabel, Pengutronix @@ -7,11 +8,6 @@ * Author: Krystian Garbaciak, Dialog Semiconductor * Author: Michal Hajduk, Dialog Semiconductor * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * */ #include diff --git a/drivers/mfd/da9063-i2c.c b/drivers/mfd/da9063-i2c.c index 50a24b1921d0..4a97ba0a35bb 100644 --- a/drivers/mfd/da9063-i2c.c +++ b/drivers/mfd/da9063-i2c.c @@ -1,15 +1,10 @@ -/* da9063-i2c.c: Interrupt support for Dialog DA9063 +// SPDX-License-Identifier: GPL-2.0+ +/* I2C support for Dialog DA9063 * * Copyright 2012 Dialog Semiconductor Ltd. * Copyright 2013 Philipp Zabel, Pengutronix * * Author: Krystian Garbaciak, Dialog Semiconductor - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * */ #include diff --git a/drivers/mfd/da9063-irq.c b/drivers/mfd/da9063-irq.c index ecc0c8ce6c58..e12b3dd0c99b 100644 --- a/drivers/mfd/da9063-irq.c +++ b/drivers/mfd/da9063-irq.c @@ -1,15 +1,10 @@ -/* da9063-irq.c: Interrupts support for Dialog DA9063 +// SPDX-License-Identifier: GPL-2.0+ +/* Interrupt support for Dialog DA9063 * * Copyright 2012 Dialog Semiconductor Ltd. * Copyright 2013 Philipp Zabel, Pengutronix * * Author: Michal Hajduk, Dialog Semiconductor - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * */ #include diff --git a/include/linux/mfd/da9063/core.h b/include/linux/mfd/da9063/core.h index 71b09154e2db..5cd06ab26352 100644 --- a/include/linux/mfd/da9063/core.h +++ b/include/linux/mfd/da9063/core.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Definitions for DA9063 MFD driver * @@ -5,12 +6,6 @@ * * Author: Michal Hajduk, Dialog Semiconductor * Author: Krystian Garbaciak, Dialog Semiconductor - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * */ #ifndef __MFD_DA9063_CORE_H__ diff --git a/include/linux/mfd/da9063/registers.h b/include/linux/mfd/da9063/registers.h index 5d42859cb441..272f984b766d 100644 --- a/include/linux/mfd/da9063/registers.h +++ b/include/linux/mfd/da9063/registers.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Registers definition for DA9063 modules * @@ -5,12 +6,6 @@ * * Author: Michal Hajduk, Dialog Semiconductor * Author: Krystian Garbaciak, Dialog Semiconductor - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * */ #ifndef _DA9063_REG_H -- cgit v1.2.3-71-gd317 From 993c0ba7e410bb7fc62d3dc89c842a7a9d031384 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 13 Feb 2019 09:00:11 +0000 Subject: mfd: syscon: atmel: Switch to SPDX license identifiers Adopt the SPDX license identifiers to ease license compliance management. Signed-off-by: Tudor Ambarus Signed-off-by: Lee Jones --- include/linux/mfd/syscon/atmel-matrix.h | 6 +----- include/linux/mfd/syscon/atmel-mc.h | 6 +----- include/linux/mfd/syscon/atmel-smc.h | 5 +---- include/linux/mfd/syscon/atmel-st.h | 6 +----- 4 files changed, 4 insertions(+), 19 deletions(-) (limited to 'include/linux') diff --git a/include/linux/mfd/syscon/atmel-matrix.h b/include/linux/mfd/syscon/atmel-matrix.h index 8293c3e2a82a..f61cd127a852 100644 --- a/include/linux/mfd/syscon/atmel-matrix.h +++ b/include/linux/mfd/syscon/atmel-matrix.h @@ -1,12 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2014 Atmel Corporation. * * Memory Controllers (MATRIX, EBI) - System peripherals registers. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef _LINUX_MFD_SYSCON_ATMEL_MATRIX_H diff --git a/include/linux/mfd/syscon/atmel-mc.h b/include/linux/mfd/syscon/atmel-mc.h index afd9b8f1e363..99c56205c410 100644 --- a/include/linux/mfd/syscon/atmel-mc.h +++ b/include/linux/mfd/syscon/atmel-mc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2005 Ivan Kokshaysky * Copyright (C) SAN People @@ -5,11 +6,6 @@ * Memory Controllers (MC, EBI, SMC, SDRAMC, BFC) - System peripherals * registers. * Based on AT91RM9200 datasheet revision E. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef _LINUX_MFD_SYSCON_ATMEL_MC_H_ diff --git a/include/linux/mfd/syscon/atmel-smc.h b/include/linux/mfd/syscon/atmel-smc.h index 7a367f34b66a..e9e24f4c4578 100644 --- a/include/linux/mfd/syscon/atmel-smc.h +++ b/include/linux/mfd/syscon/atmel-smc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Atmel SMC (Static Memory Controller) register offsets and bit definitions. * @@ -5,10 +6,6 @@ * Copyright (C) 2014 Free Electrons * * Author: Boris Brezillon - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #ifndef _LINUX_MFD_SYSCON_ATMEL_SMC_H_ diff --git a/include/linux/mfd/syscon/atmel-st.h b/include/linux/mfd/syscon/atmel-st.h index 8acf1ec1fa32..5b6013d0c440 100644 --- a/include/linux/mfd/syscon/atmel-st.h +++ b/include/linux/mfd/syscon/atmel-st.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2005 Ivan Kokshaysky * Copyright (C) SAN People * * System Timer (ST) - System peripherals registers. * Based on AT91RM9200 datasheet revision E. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef _LINUX_MFD_SYSCON_ATMEL_ST_H -- cgit v1.2.3-71-gd317 From afe2bb5c4b6227a347be60c70df2890c3f57553d Mon Sep 17 00:00:00 2001 From: Evan Green Date: Wed, 3 Apr 2019 14:34:27 -0700 Subject: mfd: cros_ec: Add host_sleep_event_v1 command Introduce the command and response structures for the second revision of the host sleep event. These structures are part of a new EC change that enables detection of failure to enter S0ix. The EC waits a kernel-specified timeout (or a default amount of time) for the S0_SLP pin to change, and wakes the system if that change does not occur in time. Signed-off-by: Evan Green Reviewed-by: Rajat Jain Reviewed-by: Guenter Roeck Acked-by: Enric Balletbo i Serra Signed-off-by: Lee Jones --- include/linux/mfd/cros_ec_commands.h | 57 ++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'include/linux') diff --git a/include/linux/mfd/cros_ec_commands.h b/include/linux/mfd/cros_ec_commands.h index 43bee4f7d137..0e91f13dd4bf 100644 --- a/include/linux/mfd/cros_ec_commands.h +++ b/include/linux/mfd/cros_ec_commands.h @@ -2731,6 +2731,63 @@ struct ec_params_host_sleep_event { uint8_t sleep_event; } __packed; +/* + * Use a default timeout value (CONFIG_SLEEP_TIMEOUT_MS) for detecting sleep + * transition failures + */ +#define EC_HOST_SLEEP_TIMEOUT_DEFAULT 0 + +/* Disable timeout detection for this sleep transition */ +#define EC_HOST_SLEEP_TIMEOUT_INFINITE 0xFFFF + +struct ec_params_host_sleep_event_v1 { + /* The type of sleep being entered or exited. */ + uint8_t sleep_event; + + /* Padding */ + uint8_t reserved; + union { + /* Parameters that apply for suspend messages. */ + struct { + /* + * The timeout in milliseconds between when this message + * is received and when the EC will declare sleep + * transition failure if the sleep signal is not + * asserted. + */ + uint16_t sleep_timeout_ms; + } suspend_params; + + /* No parameters for non-suspend messages. */ + }; +} __packed; + +/* A timeout occurred when this bit is set */ +#define EC_HOST_RESUME_SLEEP_TIMEOUT 0x80000000 + +/* + * The mask defining which bits correspond to the number of sleep transitions, + * as well as the maximum number of suspend line transitions that will be + * reported back to the host. + */ +#define EC_HOST_RESUME_SLEEP_TRANSITIONS_MASK 0x7FFFFFFF + +struct ec_response_host_sleep_event_v1 { + union { + /* Response fields that apply for resume messages. */ + struct { + /* + * The number of sleep power signal transitions that + * occurred since the suspend message. The high bit + * indicates a timeout occurred. + */ + uint32_t sleep_transitions; + } resume_response; + + /* No response fields for non-resume messages. */ + }; +} __packed; + /*****************************************************************************/ /* Smart battery pass-through */ -- cgit v1.2.3-71-gd317 From 7235560ac77a2516b84b86946debaa4fb951ed9b Mon Sep 17 00:00:00 2001 From: Evan Green Date: Wed, 3 Apr 2019 14:34:28 -0700 Subject: platform/chrome: Add support for v1 of host sleep event Add support in code for the new forms of the host sleep event. Detects the presence of this version of the command at runtime, and use whichever form the EC supports. At this time, always request the default timeout, and only report the failing response via a WARN_ONCE(). Future versions could accept the sleep parameter from outside the driver, and return the response information to usermode or elsewhere. Signed-off-by: Evan Green Reviewed-by: Rajat Jain Reviewed-by: Guenter Roeck Acked-by: Enric Balletbo i Serra Signed-off-by: Lee Jones --- drivers/mfd/cros_ec.c | 39 ++++++++++++++++++++++++++++----- drivers/platform/chrome/cros_ec_proto.c | 6 +++++ include/linux/mfd/cros_ec.h | 2 ++ 3 files changed, 42 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c index 6acfe036d522..bd2bcdd4718b 100644 --- a/drivers/mfd/cros_ec.c +++ b/drivers/mfd/cros_ec.c @@ -75,20 +75,49 @@ static irqreturn_t ec_irq_thread(int irq, void *data) static int cros_ec_sleep_event(struct cros_ec_device *ec_dev, u8 sleep_event) { + int ret; struct { struct cros_ec_command msg; - struct ec_params_host_sleep_event req; + union { + struct ec_params_host_sleep_event req0; + struct ec_params_host_sleep_event_v1 req1; + struct ec_response_host_sleep_event_v1 resp1; + } u; } __packed buf; memset(&buf, 0, sizeof(buf)); - buf.req.sleep_event = sleep_event; + if (ec_dev->host_sleep_v1) { + buf.u.req1.sleep_event = sleep_event; + buf.u.req1.suspend_params.sleep_timeout_ms = + EC_HOST_SLEEP_TIMEOUT_DEFAULT; + + buf.msg.outsize = sizeof(buf.u.req1); + if ((sleep_event == HOST_SLEEP_EVENT_S3_RESUME) || + (sleep_event == HOST_SLEEP_EVENT_S0IX_RESUME)) + buf.msg.insize = sizeof(buf.u.resp1); + + buf.msg.version = 1; + + } else { + buf.u.req0.sleep_event = sleep_event; + buf.msg.outsize = sizeof(buf.u.req0); + } buf.msg.command = EC_CMD_HOST_SLEEP_EVENT; - buf.msg.version = 0; - buf.msg.outsize = sizeof(buf.req); - return cros_ec_cmd_xfer(ec_dev, &buf.msg); + ret = cros_ec_cmd_xfer(ec_dev, &buf.msg); + + /* For now, report failure to transition to S0ix with a warning. */ + if (ret >= 0 && ec_dev->host_sleep_v1 && + (sleep_event == HOST_SLEEP_EVENT_S0IX_RESUME)) + WARN_ONCE(buf.u.resp1.resume_response.sleep_transitions & + EC_HOST_RESUME_SLEEP_TIMEOUT, + "EC detected sleep transition timeout. Total slp_s0 transitions: %d", + buf.u.resp1.resume_response.sleep_transitions & + EC_HOST_RESUME_SLEEP_TRANSITIONS_MASK); + + return ret; } int cros_ec_register(struct cros_ec_device *ec_dev) diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c index 97a068dff192..52ca564a64e7 100644 --- a/drivers/platform/chrome/cros_ec_proto.c +++ b/drivers/platform/chrome/cros_ec_proto.c @@ -414,6 +414,12 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev) else ec_dev->mkbp_event_supported = 1; + /* Probe if host sleep v1 is supported for S0ix failure detection. */ + ret = cros_ec_get_host_command_version_mask(ec_dev, + EC_CMD_HOST_SLEEP_EVENT, + &ver_mask); + ec_dev->host_sleep_v1 = (ret >= 0 && (ver_mask & EC_VER_MASK(1))); + /* * Get host event wake mask, assume all events are wake events * if unavailable. diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h index 109292a60499..31c88a0070a3 100644 --- a/include/linux/mfd/cros_ec.h +++ b/include/linux/mfd/cros_ec.h @@ -121,6 +121,7 @@ struct cros_ec_command { * @pkt_xfer: Send packet to EC and get response. * @lock: One transaction at a time. * @mkbp_event_supported: True if this EC supports the MKBP event protocol. + * @host_sleep_v1: True if this EC supports the sleep v1 command. * @event_notifier: Interrupt event notifier for transport devices. * @event_data: Raw payload transferred with the MKBP event. * @event_size: Size in bytes of the event data. @@ -154,6 +155,7 @@ struct cros_ec_device { struct cros_ec_command *msg); struct mutex lock; bool mkbp_event_supported; + bool host_sleep_v1; struct blocking_notifier_head event_notifier; struct ec_response_get_next_event_v1 event_data; -- cgit v1.2.3-71-gd317 From 6b4814a9451add06d457e198be418bf6a3e6a990 Mon Sep 17 00:00:00 2001 From: Steve Twiss Date: Fri, 26 Apr 2019 14:33:35 +0100 Subject: mfd: da9063: Fix OTP control register names to match datasheets for DA9063/63L Mismatch between what is found in the Datasheets for DA9063 and DA9063L provided by Dialog Semiconductor, and the register names provided in the MFD registers file. The changes are for the OTP (one-time-programming) control registers. The two naming errors are OPT instead of OTP, and COUNT instead of CONT (i.e. control). Cc: Stable Signed-off-by: Steve Twiss Signed-off-by: Lee Jones --- include/linux/mfd/da9063/registers.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/mfd/da9063/registers.h b/include/linux/mfd/da9063/registers.h index 272f984b766d..ba706b0e28c2 100644 --- a/include/linux/mfd/da9063/registers.h +++ b/include/linux/mfd/da9063/registers.h @@ -210,9 +210,9 @@ /* DA9063 Configuration registers */ /* OTP */ -#define DA9063_REG_OPT_COUNT 0x101 -#define DA9063_REG_OPT_ADDR 0x102 -#define DA9063_REG_OPT_DATA 0x103 +#define DA9063_REG_OTP_CONT 0x101 +#define DA9063_REG_OTP_ADDR 0x102 +#define DA9063_REG_OTP_DATA 0x103 /* Customer Trim and Configuration */ #define DA9063_REG_T_OFFSET 0x104 -- cgit v1.2.3-71-gd317 From 13d72945323c33680433bc92ffe1465a59599993 Mon Sep 17 00:00:00 2001 From: "S.j. Wang" Date: Sun, 28 Apr 2019 09:52:48 +0000 Subject: mfd: imx6sx: Add MQS register definition for iomuxc gpr Add macros to define masks and bits for imx6sx MQS registers Signed-off-by: Shengjiu Wang Signed-off-by: Lee Jones --- include/linux/mfd/syscon/imx6q-iomuxc-gpr.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'include/linux') diff --git a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h index c1b25f5e386d..f232c8130d00 100644 --- a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h +++ b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h @@ -410,6 +410,15 @@ #define IMX6SX_GPR1_FEC_CLOCK_PAD_DIR_MASK (0x3 << 17) #define IMX6SX_GPR1_FEC_CLOCK_MUX_SEL_EXT (0x3 << 13) +#define IMX6SX_GPR2_MQS_OVERSAMPLE_MASK (0x1 << 26) +#define IMX6SX_GPR2_MQS_OVERSAMPLE_SHIFT (26) +#define IMX6SX_GPR2_MQS_EN_MASK (0x1 << 25) +#define IMX6SX_GPR2_MQS_EN_SHIFT (25) +#define IMX6SX_GPR2_MQS_SW_RST_MASK (0x1 << 24) +#define IMX6SX_GPR2_MQS_SW_RST_SHIFT (24) +#define IMX6SX_GPR2_MQS_CLK_DIV_MASK (0xFF << 16) +#define IMX6SX_GPR2_MQS_CLK_DIV_SHIFT (16) + #define IMX6SX_GPR4_FEC_ENET1_STOP_REQ (0x1 << 3) #define IMX6SX_GPR4_FEC_ENET2_STOP_REQ (0x1 << 4) -- cgit v1.2.3-71-gd317 From 93abf68b6bcb50481d84db41e4d7e7e143f24757 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Wed, 8 May 2019 11:19:54 +0200 Subject: mfd: cros_ec: Update the EC feature codes Update the feature enum for the Chromebook Embedded Controller to the latest version. Some of these enums are still not used in the kernel but we might be also interested on have these enums up to date. Userspace can use them to query the features to the EC via the cros-ec character device. While here, also fix a typo in one comment in the enum. Signed-off-by: Enric Balletbo i Serra Signed-off-by: Lee Jones --- include/linux/mfd/cros_ec_commands.h | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/mfd/cros_ec_commands.h b/include/linux/mfd/cros_ec_commands.h index 0e91f13dd4bf..dcec96f01879 100644 --- a/include/linux/mfd/cros_ec_commands.h +++ b/include/linux/mfd/cros_ec_commands.h @@ -840,7 +840,7 @@ enum ec_feature_code { * (Common Smart Battery System Interface Specification) */ EC_FEATURE_SMART_BATTERY = 18, - /* EC can dectect when the host hangs. */ + /* EC can detect when the host hangs. */ EC_FEATURE_HANG_DETECT = 19, /* Report power information, for pit only */ EC_FEATURE_PMU = 20, @@ -852,10 +852,40 @@ enum ec_feature_code { EC_FEATURE_USB_MUX = 23, /* Motion Sensor code has an internal software FIFO */ EC_FEATURE_MOTION_SENSE_FIFO = 24, + /* Support temporary secure vstore */ + EC_FEATURE_VSTORE = 25, + /* EC decides on USB-C SS mux state, muxes configured by host */ + EC_FEATURE_USBC_SS_MUX_VIRTUAL = 26, /* EC has RTC feature that can be controlled by host commands */ EC_FEATURE_RTC = 27, + /* The MCU exposes a Fingerprint sensor */ + EC_FEATURE_FINGERPRINT = 28, + /* The MCU exposes a Touchpad */ + EC_FEATURE_TOUCHPAD = 29, + /* The MCU has RWSIG task enabled */ + EC_FEATURE_RWSIG = 30, + /* EC has device events support */ + EC_FEATURE_DEVICE_EVENT = 31, + /* EC supports the unified wake masks for LPC/eSPI systems */ + EC_FEATURE_UNIFIED_WAKE_MASKS = 32, + /* EC supports 64-bit host events */ + EC_FEATURE_HOST_EVENT64 = 33, + /* EC runs code in RAM (not in place, a.k.a. XIP) */ + EC_FEATURE_EXEC_IN_RAM = 34, /* EC supports CEC commands */ EC_FEATURE_CEC = 35, + /* EC supports tight sensor timestamping. */ + EC_FEATURE_MOTION_SENSE_TIGHT_TIMESTAMPS = 36, + /* + * EC supports tablet mode detection aligned to Chrome and allows + * setting of threshold by host command using + * MOTIONSENSE_CMD_TABLET_MODE_LID_ANGLE. + */ + EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS = 37, + /* EC supports audio codec. */ + EC_FEATURE_AUDIO_CODEC = 38, + /* EC Supports SCP. */ + EC_FEATURE_SCP = 39, /* The MCU is an Integrated Sensor Hub */ EC_FEATURE_ISH = 40, }; -- cgit v1.2.3-71-gd317 From 90486af5e0f7334091b94264a84713611933e97e Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Wed, 8 May 2019 11:19:55 +0200 Subject: mfd: cros_ec: Instantiate properly CrOS FP MCU device Support Fingerprint MCU as a special of CrOS EC devices. The current FP MCU uses the same EC SPI protocol v3 as other CrOS EC devices on a SPI bus. When a MCU has fingerprint support (aka EC_FEATURE_FINGERPRINT), it is instantiated as a special CrOS EC device with device name 'cros_fp'. So regardless of the probing order between the actual cros_ec and cros_fp, the userspace and other kernel drivers should not confuse them. Signed-off-by: Vincent Palatin Signed-off-by: Enric Balletbo i Serra Signed-off-by: Lee Jones --- drivers/mfd/cros_ec_dev.c | 10 ++++++++++ include/linux/mfd/cros_ec.h | 1 + 2 files changed, 11 insertions(+) (limited to 'include/linux') diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c index a3b319913097..71a01a096595 100644 --- a/drivers/mfd/cros_ec_dev.c +++ b/drivers/mfd/cros_ec_dev.c @@ -419,6 +419,16 @@ static int ec_device_probe(struct platform_device *pdev) device_initialize(&ec->class_dev); cdev_init(&ec->cdev, &fops); + /* Check whether this is actually a Fingerprint MCU rather than an EC */ + if (cros_ec_check_features(ec, EC_FEATURE_FINGERPRINT)) { + dev_info(dev, "CrOS Fingerprint MCU detected.\n"); + /* + * Help userspace differentiating ECs from FP MCU, + * regardless of the probing order. + */ + ec_platform->ec_name = CROS_EC_DEV_FP_NAME; + } + /* * Check whether this is actually an Integrated Sensor Hub (ISH) * rather than an EC. diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h index 31c88a0070a3..276079699504 100644 --- a/include/linux/mfd/cros_ec.h +++ b/include/linux/mfd/cros_ec.h @@ -23,6 +23,7 @@ #include #define CROS_EC_DEV_NAME "cros_ec" +#define CROS_EC_DEV_FP_NAME "cros_fp" #define CROS_EC_DEV_PD_NAME "cros_pd" #define CROS_EC_DEV_ISH_NAME "cros_ish" -- cgit v1.2.3-71-gd317 From 4f8f2bb7ab032150ba94cf60ea5aaf3e3ac3d2ca Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Wed, 8 May 2019 11:19:56 +0200 Subject: mfd: cros_ec: Instantiate properly CrOS Touchpad MCU device Support Touchpad MCU as a special of CrOS EC devices. The current Touchpad MCU is used on Eve Chromebook and used the same protocol as other CrOS EC devices. When a MCU has touchpad support (aka EC_FEATURE_TOUCHPAD), it is instantiated as a special CrOS EC device with device name 'cros_tp'. So regardless of the probing order between the actual cros_ec and cros_tp, the userspace and other kernel drivers should not confuse them. Signed-off-by: Wei-Ning Huang Signed-off-by: Enric Balletbo i Serra Signed-off-by: Lee Jones --- drivers/mfd/cros_ec_dev.c | 10 ++++++++++ include/linux/mfd/cros_ec.h | 1 + 2 files changed, 11 insertions(+) (limited to 'include/linux') diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c index 71a01a096595..54a58df571b6 100644 --- a/drivers/mfd/cros_ec_dev.c +++ b/drivers/mfd/cros_ec_dev.c @@ -442,6 +442,16 @@ static int ec_device_probe(struct platform_device *pdev) ec_platform->ec_name = CROS_EC_DEV_ISH_NAME; } + /* Check whether this is actually a Touchpad MCU rather than an EC */ + if (cros_ec_check_features(ec, EC_FEATURE_TOUCHPAD)) { + dev_info(dev, "CrOS Touchpad MCU detected.\n"); + /* + * Help userspace differentiating ECs from TP MCU, + * regardless of the probing order. + */ + ec_platform->ec_name = CROS_EC_DEV_TP_NAME; + } + /* * Add the class device * Link to the character device for creating the /dev entry diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h index 276079699504..cfa78bb4990f 100644 --- a/include/linux/mfd/cros_ec.h +++ b/include/linux/mfd/cros_ec.h @@ -25,6 +25,7 @@ #define CROS_EC_DEV_NAME "cros_ec" #define CROS_EC_DEV_FP_NAME "cros_fp" #define CROS_EC_DEV_PD_NAME "cros_pd" +#define CROS_EC_DEV_TP_NAME "cros_tp" #define CROS_EC_DEV_ISH_NAME "cros_ish" /* -- cgit v1.2.3-71-gd317