From f736d2c0caa8348b0bcd897972e470f7a596caad Mon Sep 17 00:00:00 2001 From: David Virag Date: Tue, 31 Jan 2023 19:30:06 +0100 Subject: mfd: sec: Remove PMICs without compatibles The S5M8751 and S5M8763 PMIC chips have no corresponding compatible values, so since board file support was removed for this driver, there is no way to specify these PMICs as present in boards anymore. Remove leftovers of these chips since it's dead code. Signed-off-by: David Virag Reviewed-by: Krzysztof Kozlowski Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230131183008.4451-2-virag.david003@gmail.com --- drivers/mfd/sec-core.c | 46 ------------------- drivers/mfd/sec-irq.c | 89 ------------------------------------ include/linux/mfd/samsung/core.h | 1 - include/linux/mfd/samsung/s5m8763.h | 90 ------------------------------------- 4 files changed, 226 deletions(-) delete mode 100644 include/linux/mfd/samsung/s5m8763.h diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index b03edda56009..c2d0ed496959 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -24,22 +24,9 @@ #include #include #include -#include #include #include -static const struct mfd_cell s5m8751_devs[] = { - { .name = "s5m8751-pmic", }, - { .name = "s5m-charger", }, - { .name = "s5m8751-codec", }, -}; - -static const struct mfd_cell s5m8763_devs[] = { - { .name = "s5m8763-pmic", }, - { .name = "s5m-rtc", }, - { .name = "s5m-charger", }, -}; - static const struct mfd_cell s5m8767_devs[] = { { .name = "s5m8767-pmic", }, { .name = "s5m-rtc", }, @@ -158,19 +145,6 @@ static bool s2mpu02_volatile(struct device *dev, unsigned int reg) } } -static bool s5m8763_volatile(struct device *dev, unsigned int reg) -{ - switch (reg) { - case S5M8763_REG_IRQM1: - case S5M8763_REG_IRQM2: - case S5M8763_REG_IRQM3: - case S5M8763_REG_IRQM4: - return false; - default: - return true; - } -} - static const struct regmap_config sec_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -230,15 +204,6 @@ static const struct regmap_config s2mpu02_regmap_config = { .cache_type = REGCACHE_FLAT, }; -static const struct regmap_config s5m8763_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - - .max_register = S5M8763_REG_LBCNFG2, - .volatile_reg = s5m8763_volatile, - .cache_type = REGCACHE_FLAT, -}; - static const struct regmap_config s5m8767_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -348,9 +313,6 @@ static int sec_pmic_probe(struct i2c_client *i2c) case S2MPS15X: regmap = &s2mps15_regmap_config; break; - case S5M8763X: - regmap = &s5m8763_regmap_config; - break; case S5M8767X: regmap = &s5m8767_regmap_config; break; @@ -375,14 +337,6 @@ static int sec_pmic_probe(struct i2c_client *i2c) pm_runtime_set_active(sec_pmic->dev); switch (sec_pmic->device_type) { - case S5M8751X: - sec_devs = s5m8751_devs; - num_sec_devs = ARRAY_SIZE(s5m8751_devs); - break; - case S5M8763X: - sec_devs = s5m8763_devs; - num_sec_devs = ARRAY_SIZE(s5m8763_devs); - break; case S5M8767X: sec_devs = s5m8767_devs; num_sec_devs = ARRAY_SIZE(s5m8767_devs); diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c index f5f59fdc72fe..e191aeb0c07c 100644 --- a/drivers/mfd/sec-irq.c +++ b/drivers/mfd/sec-irq.c @@ -14,7 +14,6 @@ #include #include #include -#include #include static const struct regmap_irq s2mps11_irqs[] = { @@ -297,81 +296,6 @@ static const struct regmap_irq s5m8767_irqs[] = { }, }; -static const struct regmap_irq s5m8763_irqs[] = { - [S5M8763_IRQ_DCINF] = { - .reg_offset = 0, - .mask = S5M8763_IRQ_DCINF_MASK, - }, - [S5M8763_IRQ_DCINR] = { - .reg_offset = 0, - .mask = S5M8763_IRQ_DCINR_MASK, - }, - [S5M8763_IRQ_JIGF] = { - .reg_offset = 0, - .mask = S5M8763_IRQ_JIGF_MASK, - }, - [S5M8763_IRQ_JIGR] = { - .reg_offset = 0, - .mask = S5M8763_IRQ_JIGR_MASK, - }, - [S5M8763_IRQ_PWRONF] = { - .reg_offset = 0, - .mask = S5M8763_IRQ_PWRONF_MASK, - }, - [S5M8763_IRQ_PWRONR] = { - .reg_offset = 0, - .mask = S5M8763_IRQ_PWRONR_MASK, - }, - [S5M8763_IRQ_WTSREVNT] = { - .reg_offset = 1, - .mask = S5M8763_IRQ_WTSREVNT_MASK, - }, - [S5M8763_IRQ_SMPLEVNT] = { - .reg_offset = 1, - .mask = S5M8763_IRQ_SMPLEVNT_MASK, - }, - [S5M8763_IRQ_ALARM1] = { - .reg_offset = 1, - .mask = S5M8763_IRQ_ALARM1_MASK, - }, - [S5M8763_IRQ_ALARM0] = { - .reg_offset = 1, - .mask = S5M8763_IRQ_ALARM0_MASK, - }, - [S5M8763_IRQ_ONKEY1S] = { - .reg_offset = 2, - .mask = S5M8763_IRQ_ONKEY1S_MASK, - }, - [S5M8763_IRQ_TOPOFFR] = { - .reg_offset = 2, - .mask = S5M8763_IRQ_TOPOFFR_MASK, - }, - [S5M8763_IRQ_DCINOVPR] = { - .reg_offset = 2, - .mask = S5M8763_IRQ_DCINOVPR_MASK, - }, - [S5M8763_IRQ_CHGRSTF] = { - .reg_offset = 2, - .mask = S5M8763_IRQ_CHGRSTF_MASK, - }, - [S5M8763_IRQ_DONER] = { - .reg_offset = 2, - .mask = S5M8763_IRQ_DONER_MASK, - }, - [S5M8763_IRQ_CHGFAULT] = { - .reg_offset = 2, - .mask = S5M8763_IRQ_CHGFAULT_MASK, - }, - [S5M8763_IRQ_LOBAT1] = { - .reg_offset = 3, - .mask = S5M8763_IRQ_LOBAT1_MASK, - }, - [S5M8763_IRQ_LOBAT2] = { - .reg_offset = 3, - .mask = S5M8763_IRQ_LOBAT2_MASK, - }, -}; - static const struct regmap_irq_chip s2mps11_irq_chip = { .name = "s2mps11", .irqs = s2mps11_irqs, @@ -425,16 +349,6 @@ static const struct regmap_irq_chip s5m8767_irq_chip = { .ack_base = S5M8767_REG_INT1, }; -static const struct regmap_irq_chip s5m8763_irq_chip = { - .name = "s5m8763", - .irqs = s5m8763_irqs, - .num_irqs = ARRAY_SIZE(s5m8763_irqs), - .num_regs = 4, - .status_base = S5M8763_REG_IRQ1, - .mask_base = S5M8763_REG_IRQM1, - .ack_base = S5M8763_REG_IRQ1, -}; - int sec_irq_init(struct sec_pmic_dev *sec_pmic) { int ret = 0; @@ -448,9 +362,6 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic) } switch (type) { - case S5M8763X: - sec_irq_chip = &s5m8763_irq_chip; - break; case S5M8767X: sec_irq_chip = &s5m8767_irq_chip; break; diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h index f92fe090473d..07aae649a86f 100644 --- a/include/linux/mfd/samsung/core.h +++ b/include/linux/mfd/samsung/core.h @@ -36,7 +36,6 @@ struct gpio_desc; enum sec_device_type { - S5M8751X, S5M8763X, S5M8767X, S2MPA01, diff --git a/include/linux/mfd/samsung/s5m8763.h b/include/linux/mfd/samsung/s5m8763.h deleted file mode 100644 index c534f086ca16..000000000000 --- a/include/linux/mfd/samsung/s5m8763.h +++ /dev/null @@ -1,90 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd - * http://www.samsung.com - */ - -#ifndef __LINUX_MFD_S5M8763_H -#define __LINUX_MFD_S5M8763_H - -/* S5M8763 registers */ -enum s5m8763_reg { - S5M8763_REG_IRQ1, - S5M8763_REG_IRQ2, - S5M8763_REG_IRQ3, - S5M8763_REG_IRQ4, - S5M8763_REG_IRQM1, - S5M8763_REG_IRQM2, - S5M8763_REG_IRQM3, - S5M8763_REG_IRQM4, - S5M8763_REG_STATUS1, - S5M8763_REG_STATUS2, - S5M8763_REG_STATUSM1, - S5M8763_REG_STATUSM2, - S5M8763_REG_CHGR1, - S5M8763_REG_CHGR2, - S5M8763_REG_LDO_ACTIVE_DISCHARGE1, - S5M8763_REG_LDO_ACTIVE_DISCHARGE2, - S5M8763_REG_BUCK_ACTIVE_DISCHARGE3, - S5M8763_REG_ONOFF1, - S5M8763_REG_ONOFF2, - S5M8763_REG_ONOFF3, - S5M8763_REG_ONOFF4, - S5M8763_REG_BUCK1_VOLTAGE1, - S5M8763_REG_BUCK1_VOLTAGE2, - S5M8763_REG_BUCK1_VOLTAGE3, - S5M8763_REG_BUCK1_VOLTAGE4, - S5M8763_REG_BUCK2_VOLTAGE1, - S5M8763_REG_BUCK2_VOLTAGE2, - S5M8763_REG_BUCK3, - S5M8763_REG_BUCK4, - S5M8763_REG_LDO1_LDO2, - S5M8763_REG_LDO3, - S5M8763_REG_LDO4, - S5M8763_REG_LDO5, - S5M8763_REG_LDO6, - S5M8763_REG_LDO7, - S5M8763_REG_LDO7_LDO8, - S5M8763_REG_LDO9_LDO10, - S5M8763_REG_LDO11, - S5M8763_REG_LDO12, - S5M8763_REG_LDO13, - S5M8763_REG_LDO14, - S5M8763_REG_LDO15, - S5M8763_REG_LDO16, - S5M8763_REG_BKCHR, - S5M8763_REG_LBCNFG1, - S5M8763_REG_LBCNFG2, -}; - -/* S5M8763 regulator ids */ -enum s5m8763_regulators { - S5M8763_LDO1, - S5M8763_LDO2, - S5M8763_LDO3, - S5M8763_LDO4, - S5M8763_LDO5, - S5M8763_LDO6, - S5M8763_LDO7, - S5M8763_LDO8, - S5M8763_LDO9, - S5M8763_LDO10, - S5M8763_LDO11, - S5M8763_LDO12, - S5M8763_LDO13, - S5M8763_LDO14, - S5M8763_LDO15, - S5M8763_LDO16, - S5M8763_BUCK1, - S5M8763_BUCK2, - S5M8763_BUCK3, - S5M8763_BUCK4, - S5M8763_AP_EN32KHZ, - S5M8763_CP_EN32KHZ, - S5M8763_ENCHGVI, - S5M8763_ESAFEUSB1, - S5M8763_ESAFEUSB2, -}; - -#define S5M8763_ENRAMP (1 << 4) -#endif /* __LINUX_MFD_S5M8763_H */ -- cgit v1.2.3 From a3165abaa9bda3e729b434a3e684fcfa205f252a Mon Sep 17 00:00:00 2001 From: David Virag Date: Tue, 31 Jan 2023 19:30:07 +0100 Subject: rtc: s5m: Drop S5M8763 support The S5M8763 MFD has no device tree compatible, and since board file support for it was removed, there's no way to use this MFD. After removing the remaining code for it from the MFD driver, also remove support for it in the s5m RTC driver, and all remaining references to it. Signed-off-by: David Virag Acked-by: Alexandre Belloni Reviewed-by: Krzysztof Kozlowski Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230131183008.4451-3-virag.david003@gmail.com --- drivers/rtc/rtc-s5m.c | 82 ++-------------------------------------- include/linux/mfd/samsung/core.h | 1 - include/linux/mfd/samsung/irq.h | 50 ------------------------ 3 files changed, 3 insertions(+), 130 deletions(-) diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c index 4243fe6d3842..dad294a0ce2a 100644 --- a/drivers/rtc/rtc-s5m.c +++ b/drivers/rtc/rtc-s5m.c @@ -85,7 +85,7 @@ struct s5m_rtc_reg_config { unsigned int write_alarm_udr_mask; }; -/* Register map for S5M8763 and S5M8767 */ +/* Register map for S5M8767 */ static const struct s5m_rtc_reg_config s5m_rtc_regs = { .regs_count = 8, .time = S5M_RTC_SEC, @@ -236,7 +236,6 @@ static int s5m_check_peding_alarm_interrupt(struct s5m_rtc_info *info, switch (info->device_type) { case S5M8767X: - case S5M8763X: ret = regmap_read(info->regmap, S5M_RTC_STATUS, &val); val &= S5M_ALARM0_STATUS; break; @@ -299,7 +298,6 @@ static int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info) data |= info->regs->write_alarm_udr_mask; switch (info->device_type) { - case S5M8763X: case S5M8767X: data &= ~S5M_RTC_TIME_EN_MASK; break; @@ -329,38 +327,6 @@ static int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info) return ret; } -static void s5m8763_data_to_tm(u8 *data, struct rtc_time *tm) -{ - tm->tm_sec = bcd2bin(data[RTC_SEC]); - tm->tm_min = bcd2bin(data[RTC_MIN]); - - if (data[RTC_HOUR] & HOUR_12) { - tm->tm_hour = bcd2bin(data[RTC_HOUR] & 0x1f); - if (data[RTC_HOUR] & HOUR_PM) - tm->tm_hour += 12; - } else { - tm->tm_hour = bcd2bin(data[RTC_HOUR] & 0x3f); - } - - tm->tm_wday = data[RTC_WEEKDAY] & 0x07; - tm->tm_mday = bcd2bin(data[RTC_DATE]); - tm->tm_mon = bcd2bin(data[RTC_MONTH]); - tm->tm_year = bcd2bin(data[RTC_YEAR1]) + bcd2bin(data[RTC_YEAR2]) * 100; - tm->tm_year -= 1900; -} - -static void s5m8763_tm_to_data(struct rtc_time *tm, u8 *data) -{ - data[RTC_SEC] = bin2bcd(tm->tm_sec); - data[RTC_MIN] = bin2bcd(tm->tm_min); - data[RTC_HOUR] = bin2bcd(tm->tm_hour); - data[RTC_WEEKDAY] = tm->tm_wday; - data[RTC_DATE] = bin2bcd(tm->tm_mday); - data[RTC_MONTH] = bin2bcd(tm->tm_mon); - data[RTC_YEAR1] = bin2bcd(tm->tm_year % 100); - data[RTC_YEAR2] = bin2bcd((tm->tm_year + 1900) / 100); -} - static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm) { struct s5m_rtc_info *info = dev_get_drvdata(dev); @@ -385,10 +351,6 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm) return ret; switch (info->device_type) { - case S5M8763X: - s5m8763_data_to_tm(data, tm); - break; - case S5M8767X: case S2MPS15X: case S2MPS14X: @@ -412,9 +374,6 @@ static int s5m_rtc_set_time(struct device *dev, struct rtc_time *tm) int ret = 0; switch (info->device_type) { - case S5M8763X: - s5m8763_tm_to_data(tm, data); - break; case S5M8767X: case S2MPS15X: case S2MPS14X: @@ -444,7 +403,6 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) { struct s5m_rtc_info *info = dev_get_drvdata(dev); u8 data[RTC_MAX_NUM_TIME_REGS]; - unsigned int val; int ret, i; ret = regmap_bulk_read(info->regmap, info->regs->alarm0, data, @@ -453,15 +411,6 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) return ret; switch (info->device_type) { - case S5M8763X: - s5m8763_data_to_tm(data, &alrm->time); - ret = regmap_read(info->regmap, S5M_ALARM0_CONF, &val); - if (ret < 0) - return ret; - - alrm->enabled = !!val; - break; - case S5M8767X: case S2MPS15X: case S2MPS14X: @@ -500,10 +449,6 @@ static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info) dev_dbg(info->dev, "%s: %ptR(%d)\n", __func__, &tm, tm.tm_wday); switch (info->device_type) { - case S5M8763X: - ret = regmap_write(info->regmap, S5M_ALARM0_CONF, 0); - break; - case S5M8767X: case S2MPS15X: case S2MPS14X: @@ -531,7 +476,6 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info) { int ret; u8 data[RTC_MAX_NUM_TIME_REGS]; - u8 alarm0_conf; struct rtc_time tm; ret = regmap_bulk_read(info->regmap, info->regs->alarm0, data, @@ -543,11 +487,6 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info) dev_dbg(info->dev, "%s: %ptR(%d)\n", __func__, &tm, tm.tm_wday); switch (info->device_type) { - case S5M8763X: - alarm0_conf = 0x77; - ret = regmap_write(info->regmap, S5M_ALARM0_CONF, alarm0_conf); - break; - case S5M8767X: case S2MPS15X: case S2MPS14X: @@ -585,10 +524,6 @@ static int s5m_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) int ret; switch (info->device_type) { - case S5M8763X: - s5m8763_tm_to_data(&alrm->time, data); - break; - case S5M8767X: case S2MPS15X: case S2MPS14X: @@ -655,7 +590,6 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info) int ret; switch (info->device_type) { - case S5M8763X: case S5M8767X: /* UDR update time. Default of 7.32 ms is too long. */ ret = regmap_update_bits(info->regmap, S5M_RTC_UDR_CON, @@ -729,11 +663,6 @@ static int s5m_rtc_probe(struct platform_device *pdev) info->regs = &s2mps13_rtc_regs; alarm_irq = S2MPS14_IRQ_RTCA0; break; - case S5M8763X: - regmap_cfg = &s5m_rtc_regmap_config; - info->regs = &s5m_rtc_regs; - alarm_irq = S5M8763_IRQ_ALARM0; - break; case S5M8767X: regmap_cfg = &s5m_rtc_regmap_config; info->regs = &s5m_rtc_regs; @@ -786,13 +715,8 @@ static int s5m_rtc_probe(struct platform_device *pdev) info->rtc_dev->ops = &s5m_rtc_ops; - if (info->device_type == S5M8763X) { - info->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_0000; - info->rtc_dev->range_max = RTC_TIMESTAMP_END_9999; - } else { - info->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000; - info->rtc_dev->range_max = RTC_TIMESTAMP_END_2099; - } + info->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000; + info->rtc_dev->range_max = RTC_TIMESTAMP_END_2099; if (!info->irq) { clear_bit(RTC_FEATURE_ALARM, info->rtc_dev->features); diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h index 07aae649a86f..a212b9f72bc9 100644 --- a/include/linux/mfd/samsung/core.h +++ b/include/linux/mfd/samsung/core.h @@ -36,7 +36,6 @@ struct gpio_desc; enum sec_device_type { - S5M8763X, S5M8767X, S2MPA01, S2MPS11X, diff --git a/include/linux/mfd/samsung/irq.h b/include/linux/mfd/samsung/irq.h index 6cfe4201a106..3fd2775eb9bb 100644 --- a/include/linux/mfd/samsung/irq.h +++ b/include/linux/mfd/samsung/irq.h @@ -194,54 +194,4 @@ enum s5m8767_irq { #define S5M8767_IRQ_RTC1S_MASK (1 << 4) #define S5M8767_IRQ_WTSR_MASK (1 << 5) -enum s5m8763_irq { - S5M8763_IRQ_DCINF, - S5M8763_IRQ_DCINR, - S5M8763_IRQ_JIGF, - S5M8763_IRQ_JIGR, - S5M8763_IRQ_PWRONF, - S5M8763_IRQ_PWRONR, - - S5M8763_IRQ_WTSREVNT, - S5M8763_IRQ_SMPLEVNT, - S5M8763_IRQ_ALARM1, - S5M8763_IRQ_ALARM0, - - S5M8763_IRQ_ONKEY1S, - S5M8763_IRQ_TOPOFFR, - S5M8763_IRQ_DCINOVPR, - S5M8763_IRQ_CHGRSTF, - S5M8763_IRQ_DONER, - S5M8763_IRQ_CHGFAULT, - - S5M8763_IRQ_LOBAT1, - S5M8763_IRQ_LOBAT2, - - S5M8763_IRQ_NR, -}; - -#define S5M8763_IRQ_DCINF_MASK (1 << 2) -#define S5M8763_IRQ_DCINR_MASK (1 << 3) -#define S5M8763_IRQ_JIGF_MASK (1 << 4) -#define S5M8763_IRQ_JIGR_MASK (1 << 5) -#define S5M8763_IRQ_PWRONF_MASK (1 << 6) -#define S5M8763_IRQ_PWRONR_MASK (1 << 7) - -#define S5M8763_IRQ_WTSREVNT_MASK (1 << 0) -#define S5M8763_IRQ_SMPLEVNT_MASK (1 << 1) -#define S5M8763_IRQ_ALARM1_MASK (1 << 2) -#define S5M8763_IRQ_ALARM0_MASK (1 << 3) - -#define S5M8763_IRQ_ONKEY1S_MASK (1 << 0) -#define S5M8763_IRQ_TOPOFFR_MASK (1 << 2) -#define S5M8763_IRQ_DCINOVPR_MASK (1 << 3) -#define S5M8763_IRQ_CHGRSTF_MASK (1 << 4) -#define S5M8763_IRQ_DONER_MASK (1 << 5) -#define S5M8763_IRQ_CHGFAULT_MASK (1 << 7) - -#define S5M8763_IRQ_LOBAT1_MASK (1 << 0) -#define S5M8763_IRQ_LOBAT2_MASK (1 << 1) - -#define S5M8763_ENRAMP (1 << 4) - #endif /* __LINUX_MFD_SEC_IRQ_H */ -- cgit v1.2.3 From ded99b89d25fd73a1d7bd910378e0339fd9d4c4a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 1 Mar 2023 10:54:02 +0100 Subject: mfd: intel_soc_pmic_chtwc: Add Lenovo Yoga Book X90F to intel_cht_wc_models The Android Lenovo Yoga Book X90F / X90L uses the same charger / fuelgauge setup as the already supported Windows Lenovo Yoga Book X91F/L, add a DMI match for this to intel_cht_wc_models with driver_data set to INTEL_CHT_WC_LENOVO_YOGABOOK1. When the quirk for the X91F/L was initially added it was written to also apply to the X90F/L but this does not work because the Android version of the Yoga Book uses completely different DMI strings. Also adjust the X91F/L quirk to reflect that it only applies to the X91F/L models. Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230301095402.28582-1-hdegoede@redhat.com --- drivers/mfd/intel_soc_pmic_chtwc.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/mfd/intel_soc_pmic_chtwc.c b/drivers/mfd/intel_soc_pmic_chtwc.c index d53dae255490..871776d511e3 100644 --- a/drivers/mfd/intel_soc_pmic_chtwc.c +++ b/drivers/mfd/intel_soc_pmic_chtwc.c @@ -159,11 +159,19 @@ static const struct dmi_system_id cht_wc_model_dmi_ids[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"), }, }, { - /* Lenovo Yoga Book X90F / X91F / X91L */ + /* Lenovo Yoga Book X90F / X90L */ .driver_data = (void *)(long)INTEL_CHT_WC_LENOVO_YOGABOOK1, .matches = { - /* Non exact match to match all versions */ - DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X9"), + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"), + }, + }, { + /* Lenovo Yoga Book X91F / X91L */ + .driver_data = (void *)(long)INTEL_CHT_WC_LENOVO_YOGABOOK1, + .matches = { + /* Non exact match to match F + L versions */ + DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X91"), }, }, { /* Lenovo Yoga Tab 3 Pro YT3-X90F */ -- cgit v1.2.3 From d16fc6858777f861717f7b2c0ef3676e419f52a0 Mon Sep 17 00:00:00 2001 From: Jackie Liu Date: Mon, 6 Feb 2023 11:22:31 +0800 Subject: mfd: si476x-cmd: Fix several issues reported by codespell Fix some typo, find by 'codespell drivers/mfd/si476x-cmd.c' succsess -> success interace -> interface comand -> command failre -> failure Reported-by: k2ci Signed-off-by: Jackie Liu Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230206032231.3208296-1-liu.yun@linux.dev --- drivers/mfd/si476x-cmd.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/mfd/si476x-cmd.c b/drivers/mfd/si476x-cmd.c index f32f1fb93e37..c9a0ec084aa8 100644 --- a/drivers/mfd/si476x-cmd.c +++ b/drivers/mfd/si476x-cmd.c @@ -251,7 +251,7 @@ static int si476x_core_parse_and_nag_about_error(struct si476x_core *core) * @usecs: amount of time to wait before reading the response (in * usecs) * - * Function returns 0 on succsess and negative error code on + * Function returns 0 on success and negative error code on * failure */ static int si476x_core_send_command(struct si476x_core *core, @@ -398,7 +398,7 @@ static int si476x_cmd_tune_seek_freq(struct si476x_core *core, * The command requests the firmware and patch version for currently * loaded firmware (dependent on the function of the device FM/AM/WB) * - * Function returns 0 on succsess and negative error code on + * Function returns 0 on success and negative error code on * failure */ int si476x_core_cmd_func_info(struct si476x_core *core, @@ -429,7 +429,7 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_func_info); * @property: property address * @value: property value * - * Function returns 0 on succsess and negative error code on + * Function returns 0 on success and negative error code on * failure */ int si476x_core_cmd_set_property(struct si476x_core *core, @@ -545,13 +545,13 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_dig_audio_pin_cfg); * SI476X_IQCLK_NOOP - do not modify the behaviour * SI476X_IQCLK_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown - * SI476X_IQCLK_IQ - set pin to be a part of I/Q interace + * SI476X_IQCLK_IQ - set pin to be a part of I/Q interface * in master mode * @iqfs: - IQFS pin function configuration: * SI476X_IQFS_NOOP - do not modify the behaviour * SI476X_IQFS_TRISTATE - put the pin in tristate condition, * enable 1MOhm pulldown - * SI476X_IQFS_IQ - set pin to be a part of I/Q interace + * SI476X_IQFS_IQ - set pin to be a part of I/Q interface * in master mode * @iout: - IOUT pin function configuration: * SI476X_IOUT_NOOP - do not modify the behaviour @@ -589,7 +589,7 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_zif_pin_cfg); /** * si476x_core_cmd_ic_link_gpo_ctl_pin_cfg - send - * 'IC_LINK_GPIO_CTL_PIN_CFG' comand to the device + * 'IC_LINK_GPIO_CTL_PIN_CFG' command to the device * @core: - device to send the command to * @icin: - ICIN pin function configuration: * SI476X_ICIN_NOOP - do not modify the behaviour @@ -1014,7 +1014,7 @@ EXPORT_SYMBOL_GPL(si476x_core_cmd_fm_phase_diversity); * NOTE caller must hold core lock * * Function returns the value of the status bit in case of success and - * negative error code in case of failre. + * negative error code in case of failure. */ int si476x_core_cmd_fm_phase_div_status(struct si476x_core *core) { -- cgit v1.2.3 From 74d3de876a3aa9c91ccf8e5559f41b30ed8a9cd1 Mon Sep 17 00:00:00 2001 From: Ye Xingchen Date: Wed, 8 Feb 2023 17:33:01 +0800 Subject: mfd: hi6421-pmic: Use devm_platform_get_and_ioremap_resource() Convert platform_get_resource(), devm_ioremap_resource() to a single call to devm_platform_get_and_ioremap_resource(), as this is exactly what this function does. Signed-off-by: Ye Xingchen Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/202302081733017704501@zte.com.cn --- drivers/mfd/hi6421-pmic-core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/mfd/hi6421-pmic-core.c b/drivers/mfd/hi6421-pmic-core.c index eba88b80d969..cb5cf4a81c06 100644 --- a/drivers/mfd/hi6421-pmic-core.c +++ b/drivers/mfd/hi6421-pmic-core.c @@ -50,7 +50,6 @@ MODULE_DEVICE_TABLE(of, of_hi6421_pmic_match); static int hi6421_pmic_probe(struct platform_device *pdev) { struct hi6421_pmic *pmic; - struct resource *res; const struct of_device_id *id; const struct mfd_cell *subdevs; enum hi6421_type type; @@ -66,8 +65,7 @@ static int hi6421_pmic_probe(struct platform_device *pdev) if (!pmic) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); if (IS_ERR(base)) return PTR_ERR(base); -- cgit v1.2.3 From 4239bff3455dd28733d719b79400df1b65b4d9fa Mon Sep 17 00:00:00 2001 From: Ye Xingchen Date: Wed, 8 Feb 2023 17:33:54 +0800 Subject: mfd: ipaq-micro: Use devm_platform_get_and_ioremap_resource() Convert platform_get_resource(), devm_ioremap_resource() to a single call to devm_platform_get_and_ioremap_resource(), as this is exactly what this function does. Signed-off-by: Ye Xingchen Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/202302081733542304522@zte.com.cn --- drivers/mfd/ipaq-micro.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/mfd/ipaq-micro.c b/drivers/mfd/ipaq-micro.c index 4cd5ecc72211..6d3968458e81 100644 --- a/drivers/mfd/ipaq-micro.c +++ b/drivers/mfd/ipaq-micro.c @@ -381,7 +381,6 @@ static int __maybe_unused micro_resume(struct device *dev) static int __init micro_probe(struct platform_device *pdev) { struct ipaq_micro *micro; - struct resource *res; int ret; int irq; @@ -391,8 +390,7 @@ static int __init micro_probe(struct platform_device *pdev) micro->dev = &pdev->dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - micro->base = devm_ioremap_resource(&pdev->dev, res); + micro->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); if (IS_ERR(micro->base)) return PTR_ERR(micro->base); -- cgit v1.2.3 From 0479ed2cf70c69fa703a1e6cbb4d5c2e7e4442a2 Mon Sep 17 00:00:00 2001 From: Ye Xingchen Date: Wed, 8 Feb 2023 17:35:44 +0800 Subject: mfd: ssbi: Use devm_platform_get_and_ioremap_resource() Convert platform_get_resource(), devm_ioremap_resource() to a single call to devm_platform_get_and_ioremap_resource(), as this is exactly what this function does. Signed-off-by: Ye Xingchen Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/202302081735440864562@zte.com.cn --- drivers/mfd/ssbi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/mfd/ssbi.c b/drivers/mfd/ssbi.c index 94f60df0decd..dee89db3471d 100644 --- a/drivers/mfd/ssbi.c +++ b/drivers/mfd/ssbi.c @@ -262,7 +262,6 @@ EXPORT_SYMBOL_GPL(ssbi_write); static int ssbi_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - struct resource *mem_res; struct ssbi *ssbi; const char *type; @@ -270,8 +269,7 @@ static int ssbi_probe(struct platform_device *pdev) if (!ssbi) return -ENOMEM; - mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - ssbi->base = devm_ioremap_resource(&pdev->dev, mem_res); + ssbi->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); if (IS_ERR(ssbi->base)) return PTR_ERR(ssbi->base); -- cgit v1.2.3 From 4723d2ef5329f28f569bf9e855bd5bd4b691aa37 Mon Sep 17 00:00:00 2001 From: Ye Xingchen Date: Wed, 8 Feb 2023 17:36:50 +0800 Subject: mfd: sun4i-gpadc: Use devm_platform_get_and_ioremap_resource() Convert platform_get_resource(), devm_ioremap_resource() to a single call to devm_platform_get_and_ioremap_resource(), as this is exactly what this function does. Signed-off-by: Ye Xingchen Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/202302081736500534579@zte.com.cn --- drivers/mfd/sun4i-gpadc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/mfd/sun4i-gpadc.c b/drivers/mfd/sun4i-gpadc.c index edc180d83a4b..d1cbea27b136 100644 --- a/drivers/mfd/sun4i-gpadc.c +++ b/drivers/mfd/sun4i-gpadc.c @@ -93,7 +93,6 @@ MODULE_DEVICE_TABLE(of, sun4i_gpadc_of_match); static int sun4i_gpadc_probe(struct platform_device *pdev) { struct sun4i_gpadc_dev *dev; - struct resource *mem; const struct of_device_id *of_id; const struct mfd_cell *cells; unsigned int irq, size; @@ -124,8 +123,7 @@ static int sun4i_gpadc_probe(struct platform_device *pdev) if (!dev) return -ENOMEM; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dev->base = devm_ioremap_resource(&pdev->dev, mem); + dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); if (IS_ERR(dev->base)) return PTR_ERR(dev->base); -- cgit v1.2.3 From ccb92c4d1608eb07c0d6b677c3bc7745db7fa33d Mon Sep 17 00:00:00 2001 From: Ye Xingchen Date: Wed, 8 Feb 2023 17:31:59 +0800 Subject: mfd: atmel-flexcom: Use devm_platform_get_and_ioremap_resource() Convert platform_get_resource(), devm_ioremap_resource() to a single call to devm_platform_get_and_ioremap_resource(), as this is exactly what this function does. Signed-off-by: Ye Xingchen Reviewed-by: Claudiu Beznea Tested-by: Claudiu Beznea Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/202302081731593374472@zte.com.cn --- drivers/mfd/atmel-flexcom.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/mfd/atmel-flexcom.c b/drivers/mfd/atmel-flexcom.c index 33caa4fba6af..b52f7ffdad35 100644 --- a/drivers/mfd/atmel-flexcom.c +++ b/drivers/mfd/atmel-flexcom.c @@ -37,7 +37,6 @@ struct atmel_flexcom { static int atmel_flexcom_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - struct resource *res; struct atmel_flexcom *ddata; int err; @@ -55,8 +54,7 @@ static int atmel_flexcom_probe(struct platform_device *pdev) ddata->opmode > ATMEL_FLEXCOM_MODE_TWI) return -EINVAL; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - ddata->base = devm_ioremap_resource(&pdev->dev, res); + ddata->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); if (IS_ERR(ddata->base)) return PTR_ERR(ddata->base); -- cgit v1.2.3 From 2e9de58c65f76ac9617b0028254edaca01529208 Mon Sep 17 00:00:00 2001 From: Ye Xingchen Date: Wed, 8 Feb 2023 17:34:51 +0800 Subject: mfd: qcom_rpm: Use devm_platform_get_and_ioremap_resource() Convert platform_get_resource(), devm_ioremap_resource() to a single call to devm_platform_get_and_ioremap_resource(), as this is exactly what this function does. Signed-off-by: Ye Xingchen Reviewed-by: Konrad Dybcio Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/202302081734511884545@zte.com.cn --- drivers/mfd/qcom_rpm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/mfd/qcom_rpm.c b/drivers/mfd/qcom_rpm.c index 8fea0e511550..086611322874 100644 --- a/drivers/mfd/qcom_rpm.c +++ b/drivers/mfd/qcom_rpm.c @@ -530,7 +530,6 @@ static int qcom_rpm_probe(struct platform_device *pdev) { const struct of_device_id *match; struct device_node *syscon_np; - struct resource *res; struct qcom_rpm *rpm; u32 fw_version[3]; int irq_wakeup; @@ -576,8 +575,7 @@ static int qcom_rpm_probe(struct platform_device *pdev) return -ENODEV; rpm->data = match->data; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - rpm->status_regs = devm_ioremap_resource(&pdev->dev, res); + rpm->status_regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); if (IS_ERR(rpm->status_regs)) return PTR_ERR(rpm->status_regs); rpm->ctrl_regs = rpm->status_regs + 0x400; -- cgit v1.2.3 From b09ed62f2d985c8eb2d5d5b560bebac653fdba20 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Mon, 13 Feb 2023 21:13:37 +0100 Subject: dt-bindings: mfd: qcom,spmi-pmic: Allow RRADC as adc@ subnode This was omitted when adding the RRADC bindings. Fixes: 7ea58c951ab3 ("dt-bindings: iio: adc: document qcom-spmi-rradc") Signed-off-by: Konrad Dybcio Reviewed-by: Krzysztof Kozlowski Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230213201337.2089970-1-konrad.dybcio@linaro.org --- Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml index adf88245c409..8f076bb622b1 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml +++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml @@ -115,6 +115,7 @@ patternProperties: type: object oneOf: - $ref: /schemas/iio/adc/qcom,spmi-iadc.yaml# + - $ref: /schemas/iio/adc/qcom,spmi-rradc.yaml# - $ref: /schemas/iio/adc/qcom,spmi-vadc.yaml# "^adc-tm@[0-9a-f]+$": -- cgit v1.2.3 From 86c6bb0edffa9fc02b4e3801b48c8e82114f1352 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Tue, 14 Feb 2023 09:58:59 +0100 Subject: mfd: core: Reorder fields in 'struct mfd_cell' to save some memory Group some variables based on their sizes to reduce hole and avoid padding. On x86_64, this shrinks the size from 144 to 128 bytes. As an example: $ size drivers/mfd/as3722.o (Before) text data bss dec hex filename 9441 680 16 10137 2799 drivers/mfd/as3722.o $ size drivers/mfd/as3722.o (After) text data bss dec hex filename 9345 680 16 10041 2739 drivers/mfd/as3722.o Signed-off-by: Christophe JAILLET Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/bb631974888dfe1af593b6280cf30fb913d2d1a4.1676365116.git.christophe.jaillet@wanadoo.fr --- include/linux/mfd/core.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h index 14ca7b471576..fc4a0e9fb3bb 100644 --- a/include/linux/mfd/core.h +++ b/include/linux/mfd/core.h @@ -78,6 +78,9 @@ struct mfd_cell { void *platform_data; size_t pdata_size; + /* Matches ACPI */ + const struct mfd_cell_acpi_match *acpi_match; + /* Software node for the device. */ const struct software_node *swnode; @@ -97,9 +100,6 @@ struct mfd_cell { /* Set to 'true' to use 'of_reg' (above) - allows for of_reg=0 */ bool use_of_reg; - /* Matches ACPI */ - const struct mfd_cell_acpi_match *acpi_match; - /* * These resources can be specified relative to the parent device. * For accessing hardware you should use resources from the platform dev @@ -119,8 +119,8 @@ struct mfd_cell { /* A list of regulator supplies that should be mapped to the MFD * device rather than the child device when requested */ - const char * const *parent_supplies; int num_parent_supplies; + const char * const *parent_supplies; }; /* -- cgit v1.2.3 From c301311a523bcc48d6d626cbd4654463a105e089 Mon Sep 17 00:00:00 2001 From: Poovendhan Selvaraj Date: Wed, 8 Feb 2023 11:03:32 +0530 Subject: dt-bindings: mfd: Add the tcsr compatible for IPQ9574 Add the tcsr compatible string for IPQ9574 SoC Signed-off-by: Poovendhan Selvaraj Acked-by: Krzysztof Kozlowski Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230208053332.16537-6-quic_poovendh@quicinc.com --- Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml index 2eeebe920e6e..203fc890c9a3 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml +++ b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml @@ -31,6 +31,7 @@ properties: - qcom,tcsr-ipq5332 - qcom,tcsr-ipq6018 - qcom,tcsr-ipq8064 + - qcom,tcsr-ipq9574 - qcom,tcsr-mdm9615 - qcom,tcsr-msm8226 - qcom,tcsr-msm8660 -- cgit v1.2.3 From 172a293707a55ba62e55a386eb601c8ef4824c85 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Thu, 16 Feb 2023 22:22:11 +0000 Subject: mfd: qcom-pm8008: Fix swapped mask/unmask in irq chip The usual behavior of mask registers is writing a '1' bit to disable (mask) an interrupt; similarly, writing a '1' bit to an unmask register enables (unmasks) an interrupt. Due to a longstanding issue in regmap-irq, mask and unmask registers were inverted when both kinds of registers were present on the same chip, ie. regmap-irq actually wrote '1's to the mask register to enable an IRQ and '1's to the unmask register to disable an IRQ. This was fixed by commit e8ffb12e7f06 ("regmap-irq: Fix inverted handling of unmask registers") but the fix is opt-in via mask_unmask_non_inverted = true because it requires manual changes for each affected driver. The new behavior will become the default once all drivers have been updated. The PM8008 appears to rely on the inverted behavior. It has separate set & clear registers for a register called INT_EN, which presumably enables interrupts by writing '1's. Opt in to the new non-inverted behavior & swap mask_base/unmask_base. Signed-off-by: Aidan MacDonald Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230216222214.138671-2-aidanmacdonald.0x0@gmail.com --- drivers/mfd/qcom-pm8008.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/qcom-pm8008.c b/drivers/mfd/qcom-pm8008.c index 9f3c4a01b4c1..39fd2a792e73 100644 --- a/drivers/mfd/qcom-pm8008.c +++ b/drivers/mfd/qcom-pm8008.c @@ -45,8 +45,8 @@ enum { #define PM8008_GPIO2_ADDR PM8008_PERIPH_3_BASE #define PM8008_STATUS_BASE (PM8008_PERIPH_0_BASE | INT_LATCHED_STS_OFFSET) -#define PM8008_MASK_BASE (PM8008_PERIPH_0_BASE | INT_EN_SET_OFFSET) -#define PM8008_UNMASK_BASE (PM8008_PERIPH_0_BASE | INT_EN_CLR_OFFSET) +#define PM8008_MASK_BASE (PM8008_PERIPH_0_BASE | INT_EN_CLR_OFFSET) +#define PM8008_UNMASK_BASE (PM8008_PERIPH_0_BASE | INT_EN_SET_OFFSET) #define PM8008_TYPE_BASE (PM8008_PERIPH_0_BASE | INT_SET_TYPE_OFFSET) #define PM8008_ACK_BASE (PM8008_PERIPH_0_BASE | INT_LATCHED_CLR_OFFSET) #define PM8008_POLARITY_HI_BASE (PM8008_PERIPH_0_BASE | INT_POL_HIGH_OFFSET) @@ -131,6 +131,7 @@ static struct regmap_irq_chip pm8008_irq_chip = { .status_base = PM8008_STATUS_BASE, .mask_base = PM8008_MASK_BASE, .unmask_base = PM8008_UNMASK_BASE, + .mask_unmask_non_inverted = true, .type_base = PM8008_TYPE_BASE, .ack_base = PM8008_ACK_BASE, .virt_reg_base = pm8008_virt_regs, -- cgit v1.2.3 From fd0a2afa5ab2fb3ba5646e3bf907f2c4a8b4a291 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Thu, 16 Feb 2023 22:22:12 +0000 Subject: mfd: qcom-pm8008: Convert irq chip to config regs Replace type and virtual registers, which are both deprecated, with config registers. This also simplifies the driver because IRQ types are set in one place, the set_type_config() callback. Signed-off-by: Aidan MacDonald [Lee: Squashed in fix-up patch from Stephen Rothwell adapting to new .set_type_config() API] Signed-off-by: Stephen Rothwell Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230216222214.138671-3-aidanmacdonald.0x0@gmail.com --- drivers/mfd/qcom-pm8008.c | 51 ++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/drivers/mfd/qcom-pm8008.c b/drivers/mfd/qcom-pm8008.c index 39fd2a792e73..d502ecf05590 100644 --- a/drivers/mfd/qcom-pm8008.c +++ b/drivers/mfd/qcom-pm8008.c @@ -66,15 +66,16 @@ static struct regmap_irq_sub_irq_map pm8008_sub_reg_offsets[] = { REGMAP_IRQ_MAIN_REG_OFFSET(p3_offs), }; -static unsigned int pm8008_virt_regs[] = { - PM8008_POLARITY_HI_BASE, - PM8008_POLARITY_LO_BASE, -}; - enum { + SET_TYPE_INDEX, POLARITY_HI_INDEX, POLARITY_LO_INDEX, - PM8008_NUM_VIRT_REGS, +}; + +static unsigned int pm8008_config_regs[] = { + PM8008_TYPE_BASE, + PM8008_POLARITY_HI_BASE, + PM8008_POLARITY_LO_BASE, }; static struct regmap_irq pm8008_irqs[] = { @@ -88,32 +89,37 @@ static struct regmap_irq pm8008_irqs[] = { REGMAP_IRQ_REG(PM8008_IRQ_GPIO2, PM8008_GPIO2, BIT(0)), }; -static int pm8008_set_type_virt(unsigned int **virt_buf, - unsigned int type, unsigned long hwirq, - int reg) +static int pm8008_set_type_config(unsigned int **buf, unsigned int type, + const struct regmap_irq *irq_data, int idx, + void *irq_drv_data) { switch (type) { case IRQ_TYPE_EDGE_FALLING: case IRQ_TYPE_LEVEL_LOW: - virt_buf[POLARITY_HI_INDEX][reg] &= ~pm8008_irqs[hwirq].mask; - virt_buf[POLARITY_LO_INDEX][reg] |= pm8008_irqs[hwirq].mask; + buf[POLARITY_HI_INDEX][idx] &= ~irq_data->mask; + buf[POLARITY_LO_INDEX][idx] |= irq_data->mask; break; case IRQ_TYPE_EDGE_RISING: case IRQ_TYPE_LEVEL_HIGH: - virt_buf[POLARITY_HI_INDEX][reg] |= pm8008_irqs[hwirq].mask; - virt_buf[POLARITY_LO_INDEX][reg] &= ~pm8008_irqs[hwirq].mask; + buf[POLARITY_HI_INDEX][idx] |= irq_data->mask; + buf[POLARITY_LO_INDEX][idx] &= ~irq_data->mask; break; case IRQ_TYPE_EDGE_BOTH: - virt_buf[POLARITY_HI_INDEX][reg] |= pm8008_irqs[hwirq].mask; - virt_buf[POLARITY_LO_INDEX][reg] |= pm8008_irqs[hwirq].mask; + buf[POLARITY_HI_INDEX][idx] |= irq_data->mask; + buf[POLARITY_LO_INDEX][idx] |= irq_data->mask; break; default: return -EINVAL; } + if (type & IRQ_TYPE_EDGE_BOTH) + buf[SET_TYPE_INDEX][idx] |= irq_data->mask; + else + buf[SET_TYPE_INDEX][idx] &= ~irq_data->mask; + return 0; } @@ -121,21 +127,20 @@ static struct regmap_irq_chip pm8008_irq_chip = { .name = "pm8008_irq", .main_status = I2C_INTR_STATUS_BASE, .num_main_regs = 1, - .num_virt_regs = PM8008_NUM_VIRT_REGS, .irqs = pm8008_irqs, .num_irqs = ARRAY_SIZE(pm8008_irqs), .num_regs = PM8008_NUM_PERIPHS, .not_fixed_stride = true, .sub_reg_offsets = pm8008_sub_reg_offsets, - .set_type_virt = pm8008_set_type_virt, .status_base = PM8008_STATUS_BASE, .mask_base = PM8008_MASK_BASE, .unmask_base = PM8008_UNMASK_BASE, .mask_unmask_non_inverted = true, - .type_base = PM8008_TYPE_BASE, .ack_base = PM8008_ACK_BASE, - .virt_reg_base = pm8008_virt_regs, - .num_type_reg = PM8008_NUM_PERIPHS, + .config_base = pm8008_config_regs, + .num_config_bases = ARRAY_SIZE(pm8008_config_regs), + .num_config_regs = PM8008_NUM_PERIPHS, + .set_type_config = pm8008_set_type_config, }; static struct regmap_config qcom_mfd_regmap_cfg = { @@ -185,11 +190,7 @@ static int pm8008_probe_irq_peripherals(struct device *dev, for (i = 0; i < ARRAY_SIZE(pm8008_irqs); i++) { type = &pm8008_irqs[i].type; - type->type_reg_offset = pm8008_irqs[i].reg_offset; - type->type_rising_val = pm8008_irqs[i].mask; - type->type_falling_val = pm8008_irqs[i].mask; - type->type_level_high_val = 0; - type->type_level_low_val = 0; + type->type_reg_offset = pm8008_irqs[i].reg_offset; if (type->type_reg_offset == PM8008_MISC) type->types_supported = IRQ_TYPE_EDGE_RISING; -- cgit v1.2.3 From ba97b5a505627fc2fb9c85f06afaef918e19032e Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Thu, 16 Feb 2023 22:22:13 +0000 Subject: mfd: qcom-pm8008: Use .get_irq_reg() for irq chip Replace the deprecated not_fixed_stride flag and the associated hierarchy of offsets with a .get_irq_reg() callback. Signed-off-by: Aidan MacDonald Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230216222214.138671-4-aidanmacdonald.0x0@gmail.com --- drivers/mfd/qcom-pm8008.c | 56 +++++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/drivers/mfd/qcom-pm8008.c b/drivers/mfd/qcom-pm8008.c index d502ecf05590..54fc9c298c03 100644 --- a/drivers/mfd/qcom-pm8008.c +++ b/drivers/mfd/qcom-pm8008.c @@ -44,28 +44,6 @@ enum { #define PM8008_GPIO1_ADDR PM8008_PERIPH_2_BASE #define PM8008_GPIO2_ADDR PM8008_PERIPH_3_BASE -#define PM8008_STATUS_BASE (PM8008_PERIPH_0_BASE | INT_LATCHED_STS_OFFSET) -#define PM8008_MASK_BASE (PM8008_PERIPH_0_BASE | INT_EN_CLR_OFFSET) -#define PM8008_UNMASK_BASE (PM8008_PERIPH_0_BASE | INT_EN_SET_OFFSET) -#define PM8008_TYPE_BASE (PM8008_PERIPH_0_BASE | INT_SET_TYPE_OFFSET) -#define PM8008_ACK_BASE (PM8008_PERIPH_0_BASE | INT_LATCHED_CLR_OFFSET) -#define PM8008_POLARITY_HI_BASE (PM8008_PERIPH_0_BASE | INT_POL_HIGH_OFFSET) -#define PM8008_POLARITY_LO_BASE (PM8008_PERIPH_0_BASE | INT_POL_LOW_OFFSET) - -#define PM8008_PERIPH_OFFSET(paddr) (paddr - PM8008_PERIPH_0_BASE) - -static unsigned int p0_offs[] = {PM8008_PERIPH_OFFSET(PM8008_PERIPH_0_BASE)}; -static unsigned int p1_offs[] = {PM8008_PERIPH_OFFSET(PM8008_PERIPH_1_BASE)}; -static unsigned int p2_offs[] = {PM8008_PERIPH_OFFSET(PM8008_PERIPH_2_BASE)}; -static unsigned int p3_offs[] = {PM8008_PERIPH_OFFSET(PM8008_PERIPH_3_BASE)}; - -static struct regmap_irq_sub_irq_map pm8008_sub_reg_offsets[] = { - REGMAP_IRQ_MAIN_REG_OFFSET(p0_offs), - REGMAP_IRQ_MAIN_REG_OFFSET(p1_offs), - REGMAP_IRQ_MAIN_REG_OFFSET(p2_offs), - REGMAP_IRQ_MAIN_REG_OFFSET(p3_offs), -}; - enum { SET_TYPE_INDEX, POLARITY_HI_INDEX, @@ -73,9 +51,9 @@ enum { }; static unsigned int pm8008_config_regs[] = { - PM8008_TYPE_BASE, - PM8008_POLARITY_HI_BASE, - PM8008_POLARITY_LO_BASE, + INT_SET_TYPE_OFFSET, + INT_POL_HIGH_OFFSET, + INT_POL_LOW_OFFSET, }; static struct regmap_irq pm8008_irqs[] = { @@ -89,6 +67,23 @@ static struct regmap_irq pm8008_irqs[] = { REGMAP_IRQ_REG(PM8008_IRQ_GPIO2, PM8008_GPIO2, BIT(0)), }; +static const unsigned int pm8008_periph_base[] = { + PM8008_PERIPH_0_BASE, + PM8008_PERIPH_1_BASE, + PM8008_PERIPH_2_BASE, + PM8008_PERIPH_3_BASE, +}; + +static unsigned int pm8008_get_irq_reg(struct regmap_irq_chip_data *data, + unsigned int base, int index) +{ + /* Simple linear addressing for the main status register */ + if (base == I2C_INTR_STATUS_BASE) + return base + index; + + return pm8008_periph_base[index] + base; +} + static int pm8008_set_type_config(unsigned int **buf, unsigned int type, const struct regmap_irq *irq_data, int idx, void *irq_drv_data) @@ -130,17 +125,16 @@ static struct regmap_irq_chip pm8008_irq_chip = { .irqs = pm8008_irqs, .num_irqs = ARRAY_SIZE(pm8008_irqs), .num_regs = PM8008_NUM_PERIPHS, - .not_fixed_stride = true, - .sub_reg_offsets = pm8008_sub_reg_offsets, - .status_base = PM8008_STATUS_BASE, - .mask_base = PM8008_MASK_BASE, - .unmask_base = PM8008_UNMASK_BASE, + .status_base = INT_LATCHED_STS_OFFSET, + .mask_base = INT_EN_CLR_OFFSET, + .unmask_base = INT_EN_SET_OFFSET, .mask_unmask_non_inverted = true, - .ack_base = PM8008_ACK_BASE, + .ack_base = INT_LATCHED_CLR_OFFSET, .config_base = pm8008_config_regs, .num_config_bases = ARRAY_SIZE(pm8008_config_regs), .num_config_regs = PM8008_NUM_PERIPHS, .set_type_config = pm8008_set_type_config, + .get_irq_reg = pm8008_get_irq_reg, }; static struct regmap_config qcom_mfd_regmap_cfg = { -- cgit v1.2.3 From c8bce48225eff37d87d1eab12c907c813befa8e9 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Thu, 16 Feb 2023 22:22:14 +0000 Subject: mfd: qcom-pm8008: Remove workaround for a regmap-irq quirk Remove pm8008_init(), which according to the comments exists only as a workaround for regmap-irq's odd treatment of type registers. This workaround shouldn't be needed anymore because this driver uses config registers, which are always programmed by regmap-irq no matter what the initial register state is. Signed-off-by: Aidan MacDonald Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230216222214.138671-5-aidanmacdonald.0x0@gmail.com --- drivers/mfd/qcom-pm8008.c | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/drivers/mfd/qcom-pm8008.c b/drivers/mfd/qcom-pm8008.c index 54fc9c298c03..837246aab4ac 100644 --- a/drivers/mfd/qcom-pm8008.c +++ b/drivers/mfd/qcom-pm8008.c @@ -143,30 +143,6 @@ static struct regmap_config qcom_mfd_regmap_cfg = { .max_register = 0xFFFF, }; -static int pm8008_init(struct regmap *regmap) -{ - int rc; - - /* - * Set TEMP_ALARM peripheral's TYPE so that the regmap-irq framework - * reads this as the default value instead of zero, the HW default. - * This is required to enable the writing of TYPE registers in - * regmap_irq_sync_unlock(). - */ - rc = regmap_write(regmap, (PM8008_TEMP_ALARM_ADDR | INT_SET_TYPE_OFFSET), BIT(0)); - if (rc) - return rc; - - /* Do the same for GPIO1 and GPIO2 peripherals */ - rc = regmap_write(regmap, (PM8008_GPIO1_ADDR | INT_SET_TYPE_OFFSET), BIT(0)); - if (rc) - return rc; - - rc = regmap_write(regmap, (PM8008_GPIO2_ADDR | INT_SET_TYPE_OFFSET), BIT(0)); - - return rc; -} - static int pm8008_probe_irq_peripherals(struct device *dev, struct regmap *regmap, int client_irq) @@ -175,12 +151,6 @@ static int pm8008_probe_irq_peripherals(struct device *dev, struct regmap_irq_type *type; struct regmap_irq_chip_data *irq_data; - rc = pm8008_init(regmap); - if (rc) { - dev_err(dev, "Init failed: %d\n", rc); - return rc; - } - for (i = 0; i < ARRAY_SIZE(pm8008_irqs); i++) { type = &pm8008_irqs[i].type; -- cgit v1.2.3 From 679532c2f6df69ad65b8717c71b06e957d2f60e6 Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Fri, 24 Feb 2023 15:08:05 +0000 Subject: mfd: bcm2835-pm: Remove MODULE_LICENSE in non-modules Since commit 8b41fc4454e ("kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf"), MODULE_LICENSE declarations are used to identify modules. As a consequence, uses of the macro in non-modules will cause modprobe to misidentify their containing object file as a module when it is not (false positives), and modprobe might succeed rather than failing with a suitable error message. So remove it in the files in this commit, none of which can be built as modules. Suggested-by: Luis Chamberlain Signed-off-by: Nick Alcock Reviewed-by: Florian Fainelli Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230224150811.80316-22-nick.alcock@oracle.com --- drivers/mfd/bcm2835-pm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/bcm2835-pm.c b/drivers/mfd/bcm2835-pm.c index 49cd1f03884a..2c0aa2a2c893 100644 --- a/drivers/mfd/bcm2835-pm.c +++ b/drivers/mfd/bcm2835-pm.c @@ -123,4 +123,3 @@ module_platform_driver(bcm2835_pm_driver); MODULE_AUTHOR("Eric Anholt "); MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM MFD"); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From cf973869b9c46a9c817831bc31d89a2c38b65ba0 Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Fri, 24 Feb 2023 15:07:48 +0000 Subject: mfd: intel_soc_pmic_crc: Remove MODULE_LICENSE in non-modules Since commit 8b41fc4454e ("kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf"), MODULE_LICENSE declarations are used to identify modules. As a consequence, uses of the macro in non-modules will cause modprobe to misidentify their containing object file as a module when it is not (false positives), and modprobe might succeed rather than failing with a suitable error message. So remove it in the files in this commit, none of which can be built as modules. Suggested-by: Luis Chamberlain Signed-off-by: Nick Alcock Reviewed-by: Andy Shevchenko Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230224150811.80316-5-nick.alcock@oracle.com --- drivers/mfd/intel_soc_pmic_crc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/intel_soc_pmic_crc.c b/drivers/mfd/intel_soc_pmic_crc.c index b1548a933dc3..b745ace46e5b 100644 --- a/drivers/mfd/intel_soc_pmic_crc.c +++ b/drivers/mfd/intel_soc_pmic_crc.c @@ -271,6 +271,5 @@ static struct i2c_driver crystal_cove_i2c_driver = { module_i2c_driver(crystal_cove_i2c_driver); MODULE_DESCRIPTION("I2C driver for Intel SoC PMIC"); -MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Yang, Bin "); MODULE_AUTHOR("Zhu, Lejun "); -- cgit v1.2.3 From 4d820dda94162968ea743675d9338ff5df6f62d0 Mon Sep 17 00:00:00 2001 From: Emil Renner Berthing Date: Sat, 11 Feb 2023 05:18:15 +0200 Subject: dt-bindings: mfd: syscon: Add StarFive JH7100 sysmain compatible Document StarFive JH7100 SoC compatible for sysmain registers. Signed-off-by: Emil Renner Berthing Signed-off-by: Cristian Ciocaltea Acked-by: Krzysztof Kozlowski Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230211031821.976408-7-cristian.ciocaltea@collabora.com --- Documentation/devicetree/bindings/mfd/syscon.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml index c828c4f5e4a7..43f564be709f 100644 --- a/Documentation/devicetree/bindings/mfd/syscon.yaml +++ b/Documentation/devicetree/bindings/mfd/syscon.yaml @@ -67,6 +67,7 @@ properties: - rockchip,rk3568-qos - rockchip,rk3588-qos - rockchip,rv1126-qos + - starfive,jh7100-sysmain - const: syscon -- cgit v1.2.3 From 1be1b23696b3d4b0231c694f5e0767b4471d33a9 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 20 Feb 2023 12:25:44 +0100 Subject: mfd: tqmx86: Do not access I2C_DETECT register through io_base The I2C_DETECT register is at IO port 0x1a7, which is outside the range passed to devm_ioport_map() for io_base, and was only working because there aren't actually any bounds checks for IO port accesses. Extending the range does not seem like a good solution here, as it would then conflict with the IO resource assigned to the I2C controller. As this is just a one-off access during probe, use a simple inb() instead. While we're at it, drop the unused define TQMX86_REG_I2C_INT_EN. Fixes: 2f17dd34ffed ("mfd: tqmx86: IO controller with I2C, Wachdog and GPIO") Signed-off-by: Matthias Schiffer Reviewed-by: Andrew Lunn Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/e8300a30f0791afb67d79db8089fb6004855f378.1676892223.git.matthias.schiffer@ew.tq-group.com --- drivers/mfd/tqmx86.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/mfd/tqmx86.c b/drivers/mfd/tqmx86.c index 7ae906ff8e35..31d0efb5aacf 100644 --- a/drivers/mfd/tqmx86.c +++ b/drivers/mfd/tqmx86.c @@ -49,9 +49,8 @@ #define TQMX86_REG_IO_EXT_INT_MASK 0x3 #define TQMX86_REG_IO_EXT_INT_GPIO_SHIFT 4 -#define TQMX86_REG_I2C_DETECT 0x47 +#define TQMX86_REG_I2C_DETECT 0x1a7 #define TQMX86_REG_I2C_DETECT_SOFT 0xa5 -#define TQMX86_REG_I2C_INT_EN 0x49 static uint gpio_irq; module_param(gpio_irq, uint, 0); @@ -213,7 +212,12 @@ static int tqmx86_probe(struct platform_device *pdev) "Found %s - Board ID %d, PCB Revision %d, PLD Revision %d\n", board_name, board_id, rev >> 4, rev & 0xf); - i2c_det = ioread8(io_base + TQMX86_REG_I2C_DETECT); + /* + * The I2C_DETECT register is in the range assigned to the I2C driver + * later, so we don't extend TQMX86_IOSIZE. Use inb() for this one-off + * access instead of ioport_map + unmap. + */ + i2c_det = inb(TQMX86_REG_I2C_DETECT); if (gpio_irq_cfg) { io_ext_int_val = -- cgit v1.2.3 From 051c69ff4f607aa114c7bbdd7c41ed881367aeee Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 20 Feb 2023 12:25:45 +0100 Subject: mfd: tqmx86: Specify IO port register range more precisely Registers 0x160..0x17f are unassigned. Use 0x180 as base register and update offets accordingly. Also change the size of the range to include 0x19f. While 0x19f is currently reserved for future extensions, so are several of the previous registers up to 0x19e, and it is weird to leave out just the last one. Fixes: 2f17dd34ffed ("mfd: tqmx86: IO controller with I2C, Wachdog and GPIO") Signed-off-by: Matthias Schiffer Reviewed-by: Andrew Lunn Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/db4677ac318b1283c8956f637f409995a30a31c3.1676892223.git.matthias.schiffer@ew.tq-group.com --- drivers/mfd/tqmx86.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/mfd/tqmx86.c b/drivers/mfd/tqmx86.c index 31d0efb5aacf..958334f14eb0 100644 --- a/drivers/mfd/tqmx86.c +++ b/drivers/mfd/tqmx86.c @@ -16,8 +16,8 @@ #include #include -#define TQMX86_IOBASE 0x160 -#define TQMX86_IOSIZE 0x3f +#define TQMX86_IOBASE 0x180 +#define TQMX86_IOSIZE 0x20 #define TQMX86_IOBASE_I2C 0x1a0 #define TQMX86_IOSIZE_I2C 0xa #define TQMX86_IOBASE_WATCHDOG 0x18b @@ -25,7 +25,7 @@ #define TQMX86_IOBASE_GPIO 0x18d #define TQMX86_IOSIZE_GPIO 0x4 -#define TQMX86_REG_BOARD_ID 0x20 +#define TQMX86_REG_BOARD_ID 0x00 #define TQMX86_REG_BOARD_ID_E38M 1 #define TQMX86_REG_BOARD_ID_50UC 2 #define TQMX86_REG_BOARD_ID_E38C 3 @@ -40,8 +40,8 @@ #define TQMX86_REG_BOARD_ID_E40S 13 #define TQMX86_REG_BOARD_ID_E40C1 14 #define TQMX86_REG_BOARD_ID_E40C2 15 -#define TQMX86_REG_BOARD_REV 0x21 -#define TQMX86_REG_IO_EXT_INT 0x26 +#define TQMX86_REG_BOARD_REV 0x01 +#define TQMX86_REG_IO_EXT_INT 0x06 #define TQMX86_REG_IO_EXT_INT_NONE 0 #define TQMX86_REG_IO_EXT_INT_7 1 #define TQMX86_REG_IO_EXT_INT_9 2 -- cgit v1.2.3 From f376c479668557bcc2fd9e9fbc0f53e7819a11cd Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 20 Feb 2023 12:25:46 +0100 Subject: mfd: tqmx86: Correct board names for TQMxE39x It seems that this driver was developed based on preliminary documentation. Report the correct names for all TQMxE39x variants, as they are used by the released hardware revisions: - Fix names for TQMxE39C1/C2 board IDs - Distinguish TQMxE39M and TQMxE39S, which use the same board ID The TQMxE39M/S are distinguished using the SAUC (Sanctioned Alternate Uses Configuration) register of the GPIO controller. This also prepares for the correct handling of the differences between the GPIO controllers of our COMe and SMARC modules. Fixes: 2f17dd34ffed ("mfd: tqmx86: IO controller with I2C, Wachdog and GPIO") Signed-off-by: Matthias Schiffer Reviewed-by: Andrew Lunn Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/aca9a7cb42a85181bcb456c437554d2728e708ec.1676892223.git.matthias.schiffer@ew.tq-group.com --- drivers/mfd/tqmx86.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/drivers/mfd/tqmx86.c b/drivers/mfd/tqmx86.c index 958334f14eb0..fac02875fe7d 100644 --- a/drivers/mfd/tqmx86.c +++ b/drivers/mfd/tqmx86.c @@ -30,9 +30,9 @@ #define TQMX86_REG_BOARD_ID_50UC 2 #define TQMX86_REG_BOARD_ID_E38C 3 #define TQMX86_REG_BOARD_ID_60EB 4 -#define TQMX86_REG_BOARD_ID_E39M 5 -#define TQMX86_REG_BOARD_ID_E39C 6 -#define TQMX86_REG_BOARD_ID_E39x 7 +#define TQMX86_REG_BOARD_ID_E39MS 5 +#define TQMX86_REG_BOARD_ID_E39C1 6 +#define TQMX86_REG_BOARD_ID_E39C2 7 #define TQMX86_REG_BOARD_ID_70EB 8 #define TQMX86_REG_BOARD_ID_80UC 9 #define TQMX86_REG_BOARD_ID_110EB 11 @@ -48,6 +48,7 @@ #define TQMX86_REG_IO_EXT_INT_12 3 #define TQMX86_REG_IO_EXT_INT_MASK 0x3 #define TQMX86_REG_IO_EXT_INT_GPIO_SHIFT 4 +#define TQMX86_REG_SAUC 0x17 #define TQMX86_REG_I2C_DETECT 0x1a7 #define TQMX86_REG_I2C_DETECT_SOFT 0xa5 @@ -110,7 +111,7 @@ static const struct mfd_cell tqmx86_devs[] = { }, }; -static const char *tqmx86_board_id_to_name(u8 board_id) +static const char *tqmx86_board_id_to_name(u8 board_id, u8 sauc) { switch (board_id) { case TQMX86_REG_BOARD_ID_E38M: @@ -121,12 +122,12 @@ static const char *tqmx86_board_id_to_name(u8 board_id) return "TQMxE38C"; case TQMX86_REG_BOARD_ID_60EB: return "TQMx60EB"; - case TQMX86_REG_BOARD_ID_E39M: - return "TQMxE39M"; - case TQMX86_REG_BOARD_ID_E39C: - return "TQMxE39C"; - case TQMX86_REG_BOARD_ID_E39x: - return "TQMxE39x"; + case TQMX86_REG_BOARD_ID_E39MS: + return (sauc == 0xff) ? "TQMxE39M" : "TQMxE39S"; + case TQMX86_REG_BOARD_ID_E39C1: + return "TQMxE39C1"; + case TQMX86_REG_BOARD_ID_E39C2: + return "TQMxE39C2"; case TQMX86_REG_BOARD_ID_70EB: return "TQMx70EB"; case TQMX86_REG_BOARD_ID_80UC: @@ -159,9 +160,9 @@ static int tqmx86_board_id_to_clk_rate(struct device *dev, u8 board_id) case TQMX86_REG_BOARD_ID_E40C1: case TQMX86_REG_BOARD_ID_E40C2: return 24000; - case TQMX86_REG_BOARD_ID_E39M: - case TQMX86_REG_BOARD_ID_E39C: - case TQMX86_REG_BOARD_ID_E39x: + case TQMX86_REG_BOARD_ID_E39MS: + case TQMX86_REG_BOARD_ID_E39C1: + case TQMX86_REG_BOARD_ID_E39C2: return 25000; case TQMX86_REG_BOARD_ID_E38M: case TQMX86_REG_BOARD_ID_E38C: @@ -175,7 +176,7 @@ static int tqmx86_board_id_to_clk_rate(struct device *dev, u8 board_id) static int tqmx86_probe(struct platform_device *pdev) { - u8 board_id, rev, i2c_det, io_ext_int_val; + u8 board_id, sauc, rev, i2c_det, io_ext_int_val; struct device *dev = &pdev->dev; u8 gpio_irq_cfg, readback; const char *board_name; @@ -205,7 +206,8 @@ static int tqmx86_probe(struct platform_device *pdev) return -ENOMEM; board_id = ioread8(io_base + TQMX86_REG_BOARD_ID); - board_name = tqmx86_board_id_to_name(board_id); + sauc = ioread8(io_base + TQMX86_REG_SAUC); + board_name = tqmx86_board_id_to_name(board_id, sauc); rev = ioread8(io_base + TQMX86_REG_BOARD_REV); dev_info(dev, -- cgit v1.2.3 From 21a8d573d967214e66abe2a1d69152d59e2a3521 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Thu, 2 Feb 2023 16:41:24 +0530 Subject: dt-bindings: mfd: qcom,tcsr: Add compatible for sm8450 Document the qcom,sm8450-tcsr compatible. Signed-off-by: Mukesh Ojha Acked-by: Krzysztof Kozlowski Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/1675336284-548-1-git-send-email-quic_mojha@quicinc.com --- Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml index 203fc890c9a3..5059bc2e676d 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml +++ b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml @@ -26,6 +26,7 @@ properties: - qcom,sdm630-tcsr - qcom,sdm845-tcsr - qcom,sm8150-tcsr + - qcom,sm8450-tcsr - qcom,tcsr-apq8064 - qcom,tcsr-apq8084 - qcom,tcsr-ipq5332 -- cgit v1.2.3 From b8fd17d9505e18001d10ceaa350c118a82b467bb Mon Sep 17 00:00:00 2001 From: Jakob Hauser Date: Tue, 28 Feb 2023 23:32:20 +0100 Subject: mfd: rt5033: Fix comments and style in includes Fix comments and remove some empty lines in rt5033-private.h. Align struct rt5033_charger in rt5033.h. Signed-off-by: Jakob Hauser Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/606950da6f4b36f5a124ff13756c78644fc89804.1677620677.git.jahau@rocketmail.com --- include/linux/mfd/rt5033-private.h | 17 +++++++---------- include/linux/mfd/rt5033.h | 7 +++---- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/include/linux/mfd/rt5033-private.h b/include/linux/mfd/rt5033-private.h index 2d1895c3efbf..6bb432f6a96c 100644 --- a/include/linux/mfd/rt5033-private.h +++ b/include/linux/mfd/rt5033-private.h @@ -107,14 +107,13 @@ enum rt5033_reg { #define RT5033_LDO_CTRL_MASK 0x1f /* RT5033 charger property - model, manufacturer */ - #define RT5033_CHARGER_MODEL "RT5033WSC Charger" #define RT5033_MANUFACTURER "Richtek Technology Corporation" /* - * RT5033 charger fast-charge current lmits (as in CHGCTRL1 register), - * AICR mode limits the input current for example, - * the AIRC 100 mode limits the input current to 100 mA. + * While RT5033 charger can limit the fast-charge current (as in CHGCTRL1 + * register), AICR mode limits the input current. For example, the AIRC 100 + * mode limits the input current to 100 mA. */ #define RT5033_AICR_100_MODE 0x20 #define RT5033_AICR_500_MODE 0x40 @@ -139,10 +138,9 @@ enum rt5033_reg { #define RT5033_TE_ENABLE_MASK 0x08 /* - * RT5033 charger opa mode. RT50300 have two opa mode charger mode - * and boost mode for OTG + * RT5033 charger opa mode. RT5033 has two opa modes for OTG: charger mode + * and boost mode. */ - #define RT5033_CHARGER_MODE 0x00 #define RT5033_BOOST_MODE 0x01 @@ -181,18 +179,17 @@ enum rt5033_reg { * RT5033 charger pre-charge threshold volt limits * (as in CHGCTRL5 register), uV */ - #define RT5033_CHARGER_PRE_THRESHOLD_LIMIT_MIN 2300000U #define RT5033_CHARGER_PRE_THRESHOLD_STEP_NUM 100000U #define RT5033_CHARGER_PRE_THRESHOLD_LIMIT_MAX 3800000U /* - * RT5033 charger enable UUG, If UUG enable MOS auto control by H/W charger + * RT5033 charger UUG. It enables MOS auto control by H/W charger * circuit. */ #define RT5033_CHARGER_UUG_ENABLE 0x02 -/* RT5033 charger High impedance mode */ +/* RT5033 charger high impedance mode */ #define RT5033_CHARGER_HZ_DISABLE 0x00 #define RT5033_CHARGER_HZ_ENABLE 0x01 diff --git a/include/linux/mfd/rt5033.h b/include/linux/mfd/rt5033.h index 3c23b6220c04..8f306ac15a27 100644 --- a/include/linux/mfd/rt5033.h +++ b/include/linux/mfd/rt5033.h @@ -49,10 +49,9 @@ struct rt5033_charger_data { }; struct rt5033_charger { - struct device *dev; - struct rt5033_dev *rt5033; - struct power_supply psy; - + struct device *dev; + struct rt5033_dev *rt5033; + struct power_supply psy; struct rt5033_charger_data *chg; }; -- cgit v1.2.3 From c5a4b6fd31e8cbc749f7ac9ff6c3a6118f3e5011 Mon Sep 17 00:00:00 2001 From: Ye Xiang Date: Sat, 25 Feb 2023 22:01:15 +0800 Subject: gpio: Add support for Intel LJCA USB GPIO driver This patch implements the GPIO function of Intel USB-I2C/GPIO/SPI adapter device named "La Jolla Cove Adapter" (LJCA). It communicate with LJCA GPIO module with specific protocol through interfaces exported by LJCA USB driver. Signed-off-by: Ye Xiang Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230225140118.2037220-3-xiang.ye@intel.com --- drivers/gpio/Kconfig | 12 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-ljca.c | 454 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 467 insertions(+) create mode 100644 drivers/gpio/gpio-ljca.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 13be729710f2..8be697f9f621 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1253,6 +1253,18 @@ config GPIO_KEMPLD This driver can also be built as a module. If so, the module will be called gpio-kempld. +config GPIO_LJCA + tristate "INTEL La Jolla Cove Adapter GPIO support" + depends on MFD_LJCA + select GPIOLIB_IRQCHIP + default MFD_LJCA + help + Select this option to enable GPIO driver for the INTEL + La Jolla Cove Adapter (LJCA) board. + + This driver can also be built as a module. If so, the module + will be called gpio-ljca. + config GPIO_LP3943 tristate "TI/National Semiconductor LP3943 GPIO expander" depends on MFD_LP3943 diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index c048ba003367..eb59524d18c0 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -77,6 +77,7 @@ obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4xx.o obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o obj-$(CONFIG_GPIO_LATCH) += gpio-latch.o +obj-$(CONFIG_GPIO_LJCA) += gpio-ljca.o obj-$(CONFIG_GPIO_LOGICVC) += gpio-logicvc.o obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o obj-$(CONFIG_GPIO_LOONGSON) += gpio-loongson.o diff --git a/drivers/gpio/gpio-ljca.c b/drivers/gpio/gpio-ljca.c new file mode 100644 index 000000000000..87863f0230f5 --- /dev/null +++ b/drivers/gpio/gpio-ljca.c @@ -0,0 +1,454 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Intel La Jolla Cove Adapter USB-GPIO driver + * + * Copyright (c) 2023, Intel Corporation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* GPIO commands */ +#define LJCA_GPIO_CONFIG 1 +#define LJCA_GPIO_READ 2 +#define LJCA_GPIO_WRITE 3 +#define LJCA_GPIO_INT_EVENT 4 +#define LJCA_GPIO_INT_MASK 5 +#define LJCA_GPIO_INT_UNMASK 6 + +#define LJCA_GPIO_CONF_DISABLE BIT(0) +#define LJCA_GPIO_CONF_INPUT BIT(1) +#define LJCA_GPIO_CONF_OUTPUT BIT(2) +#define LJCA_GPIO_CONF_PULLUP BIT(3) +#define LJCA_GPIO_CONF_PULLDOWN BIT(4) +#define LJCA_GPIO_CONF_DEFAULT BIT(5) +#define LJCA_GPIO_CONF_INTERRUPT BIT(6) +#define LJCA_GPIO_INT_TYPE BIT(7) + +#define LJCA_GPIO_CONF_EDGE FIELD_PREP(LJCA_GPIO_INT_TYPE, 1) +#define LJCA_GPIO_CONF_LEVEL FIELD_PREP(LJCA_GPIO_INT_TYPE, 0) + +/* Intentional overlap with PULLUP / PULLDOWN */ +#define LJCA_GPIO_CONF_SET BIT(3) +#define LJCA_GPIO_CONF_CLR BIT(4) + +struct gpio_op { + u8 index; + u8 value; +} __packed; + +struct gpio_packet { + u8 num; + struct gpio_op item[]; +} __packed; + +#define LJCA_GPIO_BUF_SIZE 60 +struct ljca_gpio_dev { + struct platform_device *pdev; + struct gpio_chip gc; + struct ljca_gpio_info *gpio_info; + DECLARE_BITMAP(unmasked_irqs, LJCA_MAX_GPIO_NUM); + DECLARE_BITMAP(enabled_irqs, LJCA_MAX_GPIO_NUM); + DECLARE_BITMAP(reenable_irqs, LJCA_MAX_GPIO_NUM); + u8 *connect_mode; + /* mutex to protect irq bus */ + struct mutex irq_lock; + struct work_struct work; + /* lock to protect package transfer to Hardware */ + struct mutex trans_lock; + + u8 obuf[LJCA_GPIO_BUF_SIZE]; + u8 ibuf[LJCA_GPIO_BUF_SIZE]; +}; + +static int gpio_config(struct ljca_gpio_dev *ljca_gpio, u8 gpio_id, u8 config) +{ + struct gpio_packet *packet = (struct gpio_packet *)ljca_gpio->obuf; + int ret; + + mutex_lock(&ljca_gpio->trans_lock); + packet->item[0].index = gpio_id; + packet->item[0].value = config | ljca_gpio->connect_mode[gpio_id]; + packet->num = 1; + + ret = ljca_transfer(ljca_gpio->gpio_info->ljca, LJCA_GPIO_CONFIG, packet, + struct_size(packet, item, packet->num), NULL, NULL); + mutex_unlock(&ljca_gpio->trans_lock); + return ret; +} + +static int ljca_gpio_read(struct ljca_gpio_dev *ljca_gpio, u8 gpio_id) +{ + struct gpio_packet *packet = (struct gpio_packet *)ljca_gpio->obuf; + struct gpio_packet *ack_packet = (struct gpio_packet *)ljca_gpio->ibuf; + unsigned int ibuf_len = LJCA_GPIO_BUF_SIZE; + int ret; + + mutex_lock(&ljca_gpio->trans_lock); + packet->num = 1; + packet->item[0].index = gpio_id; + ret = ljca_transfer(ljca_gpio->gpio_info->ljca, LJCA_GPIO_READ, packet, + struct_size(packet, item, packet->num), ljca_gpio->ibuf, &ibuf_len); + if (ret) + goto out_unlock; + + if (!ibuf_len || ack_packet->num != packet->num) { + dev_err(&ljca_gpio->pdev->dev, "failed gpio_id:%u %u", gpio_id, ack_packet->num); + ret = -EIO; + } + +out_unlock: + mutex_unlock(&ljca_gpio->trans_lock); + if (ret) + return ret; + return ack_packet->item[0].value > 0; +} + +static int ljca_gpio_write(struct ljca_gpio_dev *ljca_gpio, u8 gpio_id, + int value) +{ + struct gpio_packet *packet = (struct gpio_packet *)ljca_gpio->obuf; + int ret; + + mutex_lock(&ljca_gpio->trans_lock); + packet->num = 1; + packet->item[0].index = gpio_id; + packet->item[0].value = value & 1; + + ret = ljca_transfer(ljca_gpio->gpio_info->ljca, LJCA_GPIO_WRITE, packet, + struct_size(packet, item, packet->num), NULL, NULL); + mutex_unlock(&ljca_gpio->trans_lock); + return ret; +} + +static int ljca_gpio_get_value(struct gpio_chip *chip, unsigned int offset) +{ + struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(chip); + + return ljca_gpio_read(ljca_gpio, offset); +} + +static void ljca_gpio_set_value(struct gpio_chip *chip, unsigned int offset, + int val) +{ + struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(chip); + int ret; + + ret = ljca_gpio_write(ljca_gpio, offset, val); + if (ret) + dev_err(chip->parent, "offset:%u val:%d set value failed %d\n", offset, val, ret); +} + +static int ljca_gpio_direction_input(struct gpio_chip *chip, + unsigned int offset) +{ + struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(chip); + u8 config = LJCA_GPIO_CONF_INPUT | LJCA_GPIO_CONF_CLR; + + return gpio_config(ljca_gpio, offset, config); +} + +static int ljca_gpio_direction_output(struct gpio_chip *chip, + unsigned int offset, int val) +{ + struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(chip); + u8 config = LJCA_GPIO_CONF_OUTPUT | LJCA_GPIO_CONF_CLR; + int ret; + + ret = gpio_config(ljca_gpio, offset, config); + if (ret) + return ret; + + ljca_gpio_set_value(chip, offset, val); + return 0; +} + +static int ljca_gpio_set_config(struct gpio_chip *chip, unsigned int offset, + unsigned long config) +{ + struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(chip); + + ljca_gpio->connect_mode[offset] = 0; + switch (pinconf_to_config_param(config)) { + case PIN_CONFIG_BIAS_PULL_UP: + ljca_gpio->connect_mode[offset] |= LJCA_GPIO_CONF_PULLUP; + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + ljca_gpio->connect_mode[offset] |= LJCA_GPIO_CONF_PULLDOWN; + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + case PIN_CONFIG_PERSIST_STATE: + break; + default: + return -ENOTSUPP; + } + + return 0; +} + +static int ljca_gpio_init_valid_mask(struct gpio_chip *chip, unsigned long *valid_mask, + unsigned int ngpios) +{ + struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(chip); + + WARN_ON_ONCE(ngpios != ljca_gpio->gpio_info->num); + bitmap_copy(valid_mask, ljca_gpio->gpio_info->valid_pin_map, ngpios); + + return 0; +} + +static void ljca_gpio_irq_init_valid_mask(struct gpio_chip *chip, unsigned long *valid_mask, + unsigned int ngpios) +{ + ljca_gpio_init_valid_mask(chip, valid_mask, ngpios); +} + +static int ljca_enable_irq(struct ljca_gpio_dev *ljca_gpio, int gpio_id, bool enable) +{ + struct gpio_packet *packet = (struct gpio_packet *)ljca_gpio->obuf; + int ret; + + mutex_lock(&ljca_gpio->trans_lock); + packet->num = 1; + packet->item[0].index = gpio_id; + packet->item[0].value = 0; + + ret = ljca_transfer(ljca_gpio->gpio_info->ljca, + enable ? LJCA_GPIO_INT_UNMASK : LJCA_GPIO_INT_MASK, packet, + struct_size(packet, item, packet->num), NULL, NULL); + mutex_unlock(&ljca_gpio->trans_lock); + return ret; +} + +static void ljca_gpio_async(struct work_struct *work) +{ + struct ljca_gpio_dev *ljca_gpio = container_of(work, struct ljca_gpio_dev, work); + int gpio_id; + int unmasked; + + for_each_set_bit(gpio_id, ljca_gpio->reenable_irqs, ljca_gpio->gc.ngpio) { + clear_bit(gpio_id, ljca_gpio->reenable_irqs); + unmasked = test_bit(gpio_id, ljca_gpio->unmasked_irqs); + if (unmasked) + ljca_enable_irq(ljca_gpio, gpio_id, true); + } +} + +static void ljca_gpio_event_cb(void *context, u8 cmd, const void *evt_data, int len) +{ + const struct gpio_packet *packet = evt_data; + struct ljca_gpio_dev *ljca_gpio = context; + int i; + int irq; + + if (cmd != LJCA_GPIO_INT_EVENT) + return; + + for (i = 0; i < packet->num; i++) { + irq = irq_find_mapping(ljca_gpio->gc.irq.domain, packet->item[i].index); + if (!irq) { + dev_err(ljca_gpio->gc.parent, "gpio_id %u does not mapped to IRQ yet\n", + packet->item[i].index); + return; + } + + generic_handle_domain_irq(ljca_gpio->gc.irq.domain, irq); + set_bit(packet->item[i].index, ljca_gpio->reenable_irqs); + } + + schedule_work(&ljca_gpio->work); +} + +static void ljca_irq_unmask(struct irq_data *irqd) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); + struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(gc); + int gpio_id = irqd_to_hwirq(irqd); + + gpiochip_enable_irq(gc, gpio_id); + set_bit(gpio_id, ljca_gpio->unmasked_irqs); +} + +static void ljca_irq_mask(struct irq_data *irqd) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); + struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(gc); + int gpio_id = irqd_to_hwirq(irqd); + + clear_bit(gpio_id, ljca_gpio->unmasked_irqs); + gpiochip_disable_irq(gc, gpio_id); +} + +static int ljca_irq_set_type(struct irq_data *irqd, unsigned int type) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); + struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(gc); + int gpio_id = irqd_to_hwirq(irqd); + + ljca_gpio->connect_mode[gpio_id] = LJCA_GPIO_CONF_INTERRUPT; + switch (type) { + case IRQ_TYPE_LEVEL_HIGH: + ljca_gpio->connect_mode[gpio_id] |= (LJCA_GPIO_CONF_LEVEL | LJCA_GPIO_CONF_PULLUP); + break; + case IRQ_TYPE_LEVEL_LOW: + ljca_gpio->connect_mode[gpio_id] |= (LJCA_GPIO_CONF_LEVEL | LJCA_GPIO_CONF_PULLDOWN); + break; + case IRQ_TYPE_EDGE_BOTH: + break; + case IRQ_TYPE_EDGE_RISING: + ljca_gpio->connect_mode[gpio_id] |= (LJCA_GPIO_CONF_EDGE | LJCA_GPIO_CONF_PULLUP); + break; + case IRQ_TYPE_EDGE_FALLING: + ljca_gpio->connect_mode[gpio_id] |= (LJCA_GPIO_CONF_EDGE | LJCA_GPIO_CONF_PULLDOWN); + break; + default: + return -EINVAL; + } + + return 0; +} + +static void ljca_irq_bus_lock(struct irq_data *irqd) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); + struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(gc); + + mutex_lock(&ljca_gpio->irq_lock); +} + +static void ljca_irq_bus_unlock(struct irq_data *irqd) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); + struct ljca_gpio_dev *ljca_gpio = gpiochip_get_data(gc); + int gpio_id = irqd_to_hwirq(irqd); + int enabled; + int unmasked; + + enabled = test_bit(gpio_id, ljca_gpio->enabled_irqs); + unmasked = test_bit(gpio_id, ljca_gpio->unmasked_irqs); + + if (enabled != unmasked) { + if (unmasked) { + gpio_config(ljca_gpio, gpio_id, 0); + ljca_enable_irq(ljca_gpio, gpio_id, true); + set_bit(gpio_id, ljca_gpio->enabled_irqs); + } else { + ljca_enable_irq(ljca_gpio, gpio_id, false); + clear_bit(gpio_id, ljca_gpio->enabled_irqs); + } + } + + mutex_unlock(&ljca_gpio->irq_lock); +} + +static const struct irq_chip ljca_gpio_irqchip = { + .name = "ljca-irq", + .irq_mask = ljca_irq_mask, + .irq_unmask = ljca_irq_unmask, + .irq_set_type = ljca_irq_set_type, + .irq_bus_lock = ljca_irq_bus_lock, + .irq_bus_sync_unlock = ljca_irq_bus_unlock, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + +static int ljca_gpio_probe(struct platform_device *pdev) +{ + struct ljca_gpio_dev *ljca_gpio; + struct gpio_irq_chip *girq; + int ret; + + ljca_gpio = devm_kzalloc(&pdev->dev, sizeof(*ljca_gpio), GFP_KERNEL); + if (!ljca_gpio) + return -ENOMEM; + + ljca_gpio->gpio_info = dev_get_platdata(&pdev->dev); + ljca_gpio->connect_mode = devm_kcalloc(&pdev->dev, ljca_gpio->gpio_info->num, + sizeof(*ljca_gpio->connect_mode), GFP_KERNEL); + if (!ljca_gpio->connect_mode) + return -ENOMEM; + + mutex_init(&ljca_gpio->irq_lock); + mutex_init(&ljca_gpio->trans_lock); + ljca_gpio->pdev = pdev; + ljca_gpio->gc.direction_input = ljca_gpio_direction_input; + ljca_gpio->gc.direction_output = ljca_gpio_direction_output; + ljca_gpio->gc.get = ljca_gpio_get_value; + ljca_gpio->gc.set = ljca_gpio_set_value; + ljca_gpio->gc.set_config = ljca_gpio_set_config; + ljca_gpio->gc.init_valid_mask = ljca_gpio_init_valid_mask; + ljca_gpio->gc.can_sleep = true; + ljca_gpio->gc.parent = &pdev->dev; + + ljca_gpio->gc.base = -1; + ljca_gpio->gc.ngpio = ljca_gpio->gpio_info->num; + ljca_gpio->gc.label = ACPI_COMPANION(&pdev->dev) ? + acpi_dev_name(ACPI_COMPANION(&pdev->dev)) : + dev_name(&pdev->dev); + ljca_gpio->gc.owner = THIS_MODULE; + + platform_set_drvdata(pdev, ljca_gpio); + ljca_register_event_cb(ljca_gpio->gpio_info->ljca, ljca_gpio_event_cb, ljca_gpio); + + girq = &ljca_gpio->gc.irq; + gpio_irq_chip_set_chip(girq, &ljca_gpio_irqchip); + girq->parent_handler = NULL; + girq->num_parents = 0; + girq->parents = NULL; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_simple_irq; + girq->init_valid_mask = ljca_gpio_irq_init_valid_mask; + + INIT_WORK(&ljca_gpio->work, ljca_gpio_async); + ret = gpiochip_add_data(&ljca_gpio->gc, ljca_gpio); + if (ret) { + ljca_unregister_event_cb(ljca_gpio->gpio_info->ljca); + mutex_destroy(&ljca_gpio->irq_lock); + mutex_destroy(&ljca_gpio->trans_lock); + } + + return ret; +} + +static int ljca_gpio_remove(struct platform_device *pdev) +{ + struct ljca_gpio_dev *ljca_gpio = platform_get_drvdata(pdev); + + gpiochip_remove(&ljca_gpio->gc); + ljca_unregister_event_cb(ljca_gpio->gpio_info->ljca); + mutex_destroy(&ljca_gpio->irq_lock); + mutex_destroy(&ljca_gpio->trans_lock); + return 0; +} + +#define LJCA_GPIO_DRV_NAME "ljca-gpio" +static const struct platform_device_id ljca_gpio_id[] = { + { LJCA_GPIO_DRV_NAME, 0 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, ljca_gpio_id); + +static struct platform_driver ljca_gpio_driver = { + .driver.name = LJCA_GPIO_DRV_NAME, + .probe = ljca_gpio_probe, + .remove = ljca_gpio_remove, +}; +module_platform_driver(ljca_gpio_driver); + +MODULE_AUTHOR("Ye Xiang "); +MODULE_AUTHOR("Wang Zhifeng "); +MODULE_AUTHOR("Zhang Lixu "); +MODULE_DESCRIPTION("Intel La Jolla Cove Adapter USB-GPIO driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(LJCA); -- cgit v1.2.3 From 2c6a1bde024ccb0e64ea4bc112d15438abc08949 Mon Sep 17 00:00:00 2001 From: Rohit Agarwal Date: Wed, 8 Mar 2023 17:49:48 +0530 Subject: dt-bindings: mfd: qcom,tcsr: Add compatible for sdx65 Add the qcom,sdx65-tcsr compatible. Signed-off-by: Rohit Agarwal Acked-by: Krzysztof Kozlowski Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/1678277993-18836-2-git-send-email-quic_rohiagar@quicinc.com --- Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml index 5059bc2e676d..51fa614c3f51 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml +++ b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml @@ -25,6 +25,7 @@ properties: - qcom,sc8280xp-tcsr - qcom,sdm630-tcsr - qcom,sdm845-tcsr + - qcom,sdx65-tcsr - qcom,sm8150-tcsr - qcom,sm8450-tcsr - qcom,tcsr-apq8064 -- cgit v1.2.3 From ba2b13df8ab005cee919d2ca31829a3c639fded2 Mon Sep 17 00:00:00 2001 From: Marcello Sylvester Bauer Date: Tue, 7 Mar 2023 13:12:44 +0100 Subject: dt-bindings: mfd: Add MAX5970 and MAX5978 The MAX597x is a hot swap controller with configurable fault protection. It also has 10bit ADC for current & voltage measurements. ... Changes in V12: - Update title Signed-off-by: Marcello Sylvester Bauer Co-developed-by: Patrick Rudolph Signed-off-by: Patrick Rudolph Co-developed-by: Naresh Solanki Signed-off-by: Naresh Solanki Reviewed-by: Krzysztof Kozlowski Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230307121246.127425-1-Naresh.Solanki@9elements.com --- .../devicetree/bindings/mfd/maxim,max5970.yaml | 151 +++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 Documentation/devicetree/bindings/mfd/maxim,max5970.yaml diff --git a/Documentation/devicetree/bindings/mfd/maxim,max5970.yaml b/Documentation/devicetree/bindings/mfd/maxim,max5970.yaml new file mode 100644 index 000000000000..da67742c5aa9 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/maxim,max5970.yaml @@ -0,0 +1,151 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/maxim,max5970.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Regulator for MAX5970 Smart Switch from Maxim Integrated + +maintainers: + - Patrick Rudolph + +description: | + The smart switch provides no output regulation, but independent fault protection + and voltage and current sensing. + Programming is done through I2C bus. + + Datasheets: + https://datasheets.maximintegrated.com/en/ds/MAX5970.pdf + https://datasheets.maximintegrated.com/en/ds/MAX5978.pdf + +properties: + compatible: + enum: + - maxim,max5970 + - maxim,max5978 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + leds: + type: object + description: + Properties for four LEDS. + + properties: + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + patternProperties: + "^led@[0-3]$": + $ref: /schemas/leds/common.yaml# + type: object + + additionalProperties: false + + vss1-supply: + description: Supply of the first channel. + + vss2-supply: + description: Supply of the second channel. + + regulators: + type: object + description: + Properties for both hot swap control/switch. + + patternProperties: + "^sw[0-1]$": + $ref: /schemas/regulator/regulator.yaml# + type: object + properties: + shunt-resistor-micro-ohms: + description: | + The value of current sense resistor in microohms. + + required: + - shunt-resistor-micro-ohms + + unevaluatedProperties: false + + additionalProperties: false + +required: + - compatible + - reg + - regulators + - vss1-supply + +allOf: + - if: + properties: + compatible: + enum: + - maxim,max5970 + then: + required: + - vss2-supply + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + regulator@3a { + compatible = "maxim,max5978"; + reg = <0x3a>; + vss1-supply = <&p3v3>; + + regulators { + sw0_ref_0: sw0 { + shunt-resistor-micro-ohms = <12000>; + }; + }; + + leds { + #address-cells = <1>; + #size-cells = <0>; + led@0 { + reg = <0>; + label = "led0"; + default-state = "on"; + }; + led@1 { + reg = <1>; + label = "led1"; + default-state = "on"; + }; + }; + }; + }; + + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + regulator@3a { + compatible = "maxim,max5970"; + reg = <0x3a>; + vss1-supply = <&p3v3>; + vss2-supply = <&p5v>; + + regulators { + sw0_ref_1: sw0 { + shunt-resistor-micro-ohms = <12000>; + }; + sw1_ref_1: sw1 { + shunt-resistor-micro-ohms = <10000>; + }; + }; + }; + }; +... -- cgit v1.2.3 From 0742c2a6335281608ac9e9aee67493e9e30f6195 Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Tue, 7 Mar 2023 13:12:45 +0100 Subject: mfd: max597x: Add support for MAX5970 and MAX5978 Implement a regulator driver with IRQ support for fault management. Written against documentation [1] and [2] and tested on real hardware. Every channel has it's own regulator supply nammed 'vss1-supply' and 'vss2-supply'. The regulator supply is used to determine the output voltage, as the smart switch provides no output regulation. The driver requires the 'shunt-resistor-micro-ohms' to be present in the devicetree to properly calculate current related values. You must specify compatible devictree layout: regulator@3a { reg = <0x3a>; vss1-supply = <&p3v3>; compatible = "maxim,max5978"; ... regulators { sw0_ref: SW0 { regulator-compatible = "SW0"; shunt-resistor-micro-ohms = <12000>; ... } } } 1: https://datasheets.maximintegrated.com/en/ds/MAX5970.pdf 2: https://datasheets.maximintegrated.com/en/ds/MAX5978.pdf ... Changes in V12: - Use simple_mfd_i2c driver and remove previous implementation. - Remove newline - Use _MFD_MAX597X_H in header file - Successfull build need following patch from regulator: https://lore.kernel.org/r/20230216075302.68935-1-Naresh.Solanki@9elements.com https://lore.kernel.org/r/20230210163225.1208035-1-Naresh.Solanki@9elements.com Signed-off-by: Patrick Rudolph Signed-off-by: Marcello Sylvester Bauer Signed-off-by: Naresh Solanki Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230307121246.127425-2-Naresh.Solanki@9elements.com --- drivers/mfd/Kconfig | 10 +++++ drivers/mfd/simple-mfd-i2c.c | 13 ++++++ include/linux/mfd/max597x.h | 96 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 include/linux/mfd/max597x.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index fcc141e067b9..d381d0e63455 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -266,6 +266,16 @@ config MFD_MADERA_SPI Support for the Cirrus Logic Madera platform audio SoC core functionality controlled via SPI. +config MFD_MAX597X + tristate "Maxim 597x power switch and monitor" + depends on (I2C && OF) + select MFD_SIMPLE_MFD_I2C + help + This driver controls a Maxim 5970/5978 switch via I2C bus. + The MAX5970/5978 is a smart switch with no output regulation, but + fault protection and voltage and current monitoring capabilities. + Also it supports upto 4 indication leds. + config MFD_CS47L15 bool "Cirrus Logic CS47L15" select PINCTRL_CS47L15 diff --git a/drivers/mfd/simple-mfd-i2c.c b/drivers/mfd/simple-mfd-i2c.c index e31f13fd6a79..20782b4dd172 100644 --- a/drivers/mfd/simple-mfd-i2c.c +++ b/drivers/mfd/simple-mfd-i2c.c @@ -72,9 +72,22 @@ static const struct simple_mfd_data silergy_sy7636a = { .mfd_cell_size = ARRAY_SIZE(sy7636a_cells), }; +static const struct mfd_cell max597x_cells[] = { + { .name = "max597x-regulator", }, + { .name = "max597x-iio", }, + { .name = "max597x-led", }, +}; + +static const struct simple_mfd_data maxim_max597x = { + .mfd_cell = max597x_cells, + .mfd_cell_size = ARRAY_SIZE(max597x_cells), +}; + static const struct of_device_id simple_mfd_i2c_of_match[] = { { .compatible = "kontron,sl28cpld" }, { .compatible = "silergy,sy7636a", .data = &silergy_sy7636a}, + { .compatible = "maxim,max5970", .data = &maxim_max597x}, + { .compatible = "maxim,max5978", .data = &maxim_max597x}, {} }; MODULE_DEVICE_TABLE(of, simple_mfd_i2c_of_match); diff --git a/include/linux/mfd/max597x.h b/include/linux/mfd/max597x.h new file mode 100644 index 000000000000..a850b2e02e6a --- /dev/null +++ b/include/linux/mfd/max597x.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Device driver for regulators in MAX5970 and MAX5978 IC + * + * Copyright (c) 2022 9elements GmbH + * + * Author: Patrick Rudolph + */ + +#ifndef _MFD_MAX597X_H +#define _MFD_MAX597X_H + +#include + +#define MAX5970_NUM_SWITCHES 2 +#define MAX5978_NUM_SWITCHES 1 +#define MAX597X_NUM_LEDS 4 + +struct max597x_data { + int num_switches; + u32 irng[MAX5970_NUM_SWITCHES]; + u32 mon_rng[MAX5970_NUM_SWITCHES]; + u32 shunt_micro_ohms[MAX5970_NUM_SWITCHES]; +}; + +enum max597x_chip_type { + MAX597x_TYPE_MAX5978 = 1, + MAX597x_TYPE_MAX5970, +}; + +#define MAX5970_REG_CURRENT_L(ch) (0x01 + (ch) * 4) +#define MAX5970_REG_CURRENT_H(ch) (0x00 + (ch) * 4) +#define MAX5970_REG_VOLTAGE_L(ch) (0x03 + (ch) * 4) +#define MAX5970_REG_VOLTAGE_H(ch) (0x02 + (ch) * 4) +#define MAX5970_REG_MON_RANGE 0x18 +#define MAX5970_MON_MASK 0x3 +#define MAX5970_MON(reg, ch) (((reg) >> ((ch) * 2)) & MAX5970_MON_MASK) +#define MAX5970_MON_MAX_RANGE_UV 16000000 + +#define MAX5970_REG_CH_UV_WARN_H(ch) (0x1A + (ch) * 10) +#define MAX5970_REG_CH_UV_WARN_L(ch) (0x1B + (ch) * 10) +#define MAX5970_REG_CH_UV_CRIT_H(ch) (0x1C + (ch) * 10) +#define MAX5970_REG_CH_UV_CRIT_L(ch) (0x1D + (ch) * 10) +#define MAX5970_REG_CH_OV_WARN_H(ch) (0x1E + (ch) * 10) +#define MAX5970_REG_CH_OV_WARN_L(ch) (0x1F + (ch) * 10) +#define MAX5970_REG_CH_OV_CRIT_H(ch) (0x20 + (ch) * 10) +#define MAX5970_REG_CH_OV_CRIT_L(ch) (0x21 + (ch) * 10) + +#define MAX5970_VAL2REG_H(x) (((x) >> 2) & 0xFF) +#define MAX5970_VAL2REG_L(x) ((x) & 0x3) + +#define MAX5970_REG_DAC_FAST(ch) (0x2E + (ch)) + +#define MAX5970_FAST2SLOW_RATIO 200 + +#define MAX5970_REG_STATUS0 0x31 +#define MAX5970_CB_IFAULTF(ch) (1 << (ch)) +#define MAX5970_CB_IFAULTS(ch) (1 << ((ch) + 4)) + +#define MAX5970_REG_STATUS1 0x32 +#define STATUS1_PROT_MASK 0x3 +#define STATUS1_PROT(reg) \ + (((reg) >> 6) & STATUS1_PROT_MASK) +#define STATUS1_PROT_SHUTDOWN 0 +#define STATUS1_PROT_CLEAR_PG 1 +#define STATUS1_PROT_ALERT_ONLY 2 + +#define MAX5970_REG_STATUS2 0x33 +#define MAX5970_IRNG_MASK 0x3 +#define MAX5970_IRNG(reg, ch) \ + (((reg) >> ((ch) * 2)) & MAX5970_IRNG_MASK) + +#define MAX5970_REG_STATUS3 0x34 +#define MAX5970_STATUS3_ALERT BIT(4) +#define MAX5970_STATUS3_PG(ch) BIT(ch) + +#define MAX5970_REG_FAULT0 0x35 +#define UV_STATUS_WARN(ch) (1 << (ch)) +#define UV_STATUS_CRIT(ch) (1 << ((ch) + 4)) + +#define MAX5970_REG_FAULT1 0x36 +#define OV_STATUS_WARN(ch) (1 << (ch)) +#define OV_STATUS_CRIT(ch) (1 << ((ch) + 4)) + +#define MAX5970_REG_FAULT2 0x37 +#define OC_STATUS_WARN(ch) (1 << (ch)) + +#define MAX5970_REG_CHXEN 0x3b +#define CHXEN(ch) (3 << ((ch) * 2)) + +#define MAX5970_REG_LED_FLASH 0x43 + +#define MAX_REGISTERS 0x49 +#define ADC_MASK 0x3FF + +#endif /* _MFD_MAX597X_H */ -- cgit v1.2.3 From e8e9837dde98b18b694f79f6268afff7a610bf30 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 6 Mar 2023 08:26:17 +0100 Subject: dt-bindings: mfd: qcom,tcsr: Document SDX55 TCSR Add compatible for SDX55 TCSR block. Signed-off-by: Krzysztof Kozlowski Acked-by: Rob Herring Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230306072618.10770-1-krzysztof.kozlowski@linaro.org --- Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml index 51fa614c3f51..fe790af7b4fb 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml +++ b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml @@ -25,6 +25,7 @@ properties: - qcom,sc8280xp-tcsr - qcom,sdm630-tcsr - qcom,sdm845-tcsr + - qcom,sdx55-tcsr - qcom,sdx65-tcsr - qcom,sm8150-tcsr - qcom,sm8450-tcsr -- cgit v1.2.3 From a0b9becad8a7d62a81530035a69f744c0e389737 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 8 Mar 2023 10:12:57 +0100 Subject: mfd: core: Remove .enable() and .disable() callbacks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With commit dd77f5fa97d3 ("mfd: Remove toshiba tmio drivers") the last mfd driver that implements these callbacks is gone and since commit 652719b1003a ("w1: remove ds1wm driver") the last user is gone. The corresponding functions mfd_cell_enable() and mfd_cell_disable() are also unused (since commit 0ca222c81977 ("leds: Remove asic3 driver")). Signed-off-by: Uwe Kleine-König Acked-by: Arnd Bergmann Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230308091257.2404932-1-u.kleine-koenig@pengutronix.de --- drivers/mfd/mfd-core.c | 26 -------------------------- include/linux/mfd/core.h | 12 ------------ 2 files changed, 38 deletions(-) diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 16d1861e9682..695d50b3bac6 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -33,32 +33,6 @@ static struct device_type mfd_dev_type = { .name = "mfd_device", }; -int mfd_cell_enable(struct platform_device *pdev) -{ - const struct mfd_cell *cell = mfd_get_cell(pdev); - - if (!cell->enable) { - dev_dbg(&pdev->dev, "No .enable() call-back registered\n"); - return 0; - } - - return cell->enable(pdev); -} -EXPORT_SYMBOL(mfd_cell_enable); - -int mfd_cell_disable(struct platform_device *pdev) -{ - const struct mfd_cell *cell = mfd_get_cell(pdev); - - if (!cell->disable) { - dev_dbg(&pdev->dev, "No .disable() call-back registered\n"); - return 0; - } - - return cell->disable(pdev); -} -EXPORT_SYMBOL(mfd_cell_disable); - #if IS_ENABLED(CONFIG_ACPI) struct match_ids_walk_data { struct acpi_device_id *ids; diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h index fc4a0e9fb3bb..47e7a3a61ce6 100644 --- a/include/linux/mfd/core.h +++ b/include/linux/mfd/core.h @@ -68,9 +68,6 @@ struct mfd_cell { int id; int level; - int (*enable)(struct platform_device *dev); - int (*disable)(struct platform_device *dev); - int (*suspend)(struct platform_device *dev); int (*resume)(struct platform_device *dev); @@ -123,15 +120,6 @@ struct mfd_cell { const char * const *parent_supplies; }; -/* - * Convenience functions for clients using shared cells. Refcounting - * happens automatically, with the cell's enable/disable callbacks - * being called only when a device is first being enabled or no other - * clients are making use of it. - */ -extern int mfd_cell_enable(struct platform_device *pdev); -extern int mfd_cell_disable(struct platform_device *pdev); - /* * Given a platform device that's been created by mfd_add_devices(), fetch * the mfd_cell that created it. -- cgit v1.2.3 From 6e264e72299c1aff75b9cf45c4cbebaea2cb5fd6 Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Wed, 8 Mar 2023 10:55:48 -0600 Subject: dt-bindings: mfd: Add TI-Nspire misc registers The TI Nspire devices contain a set of registers with a seemingly miscellaneous set of functionality. This area is known simply as the "misc" region. Signed-off-by: Andrew Davis Reviewed-by: Rob Herring Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230308165557.2242-2-afd@ti.com --- .../devicetree/bindings/mfd/ti,nspire-misc.yaml | 51 ++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 Documentation/devicetree/bindings/mfd/ti,nspire-misc.yaml diff --git a/Documentation/devicetree/bindings/mfd/ti,nspire-misc.yaml b/Documentation/devicetree/bindings/mfd/ti,nspire-misc.yaml new file mode 100644 index 000000000000..28cd5164d46f --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/ti,nspire-misc.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (C) 2022-2023 Texas Instruments Incorporated - https://www.ti.com/ +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/ti,nspire-misc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: TI Nspire MISC hardware block + +maintainers: + - Andrew Davis + +description: + System controller node represents a register region containing a set + of miscellaneous registers. The registers are not cohesive enough to + represent as any specific type of device. Currently there is a reset + controller. + +properties: + compatible: + items: + - enum: + - ti,nspire-misc + - const: syscon + - const: simple-mfd + + reg: + maxItems: 1 + + reboot: + $ref: /schemas/power/reset/syscon-reboot.yaml# + +required: + - compatible + - reg + - reboot + +additionalProperties: false + +examples: + - | + misc: misc@900a0000 { + compatible = "ti,nspire-misc", "syscon", "simple-mfd"; + reg = <0x900a0000 0x1000>; + + reboot { + compatible = "syscon-reboot"; + offset = <0x08>; + value = <0x02>; + }; + }; -- cgit v1.2.3 From 7d61f6313e90cdbe592eba5e0ae6d1c367b03548 Mon Sep 17 00:00:00 2001 From: Christoph Niedermaier Date: Thu, 9 Mar 2023 10:22:52 +0100 Subject: mfd: da9062: Use MFD_CELL_OF macro Use MFD_CELL_OF macro helper instead of plain struct properties, which makes the code a bit shorter and to have commonly defined MFD cell attributes. Signed-off-by: Christoph Niedermaier Acked-by: Adam Ward Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230309092254.56279-1-cniedermaier@dh-electronics.com --- drivers/mfd/da9062-core.c | 92 +++++++++++++---------------------------------- 1 file changed, 24 insertions(+), 68 deletions(-) diff --git a/drivers/mfd/da9062-core.c b/drivers/mfd/da9062-core.c index 40cde51e5719..9418c58c2b06 100644 --- a/drivers/mfd/da9062-core.c +++ b/drivers/mfd/da9062-core.c @@ -182,34 +182,16 @@ static const struct resource da9061_onkey_resources[] = { }; static const struct mfd_cell da9061_devs[] = { - { - .name = "da9061-core", - .num_resources = ARRAY_SIZE(da9061_core_resources), - .resources = da9061_core_resources, - }, - { - .name = "da9062-regulators", - .num_resources = ARRAY_SIZE(da9061_regulators_resources), - .resources = da9061_regulators_resources, - }, - { - .name = "da9061-watchdog", - .num_resources = ARRAY_SIZE(da9061_wdt_resources), - .resources = da9061_wdt_resources, - .of_compatible = "dlg,da9061-watchdog", - }, - { - .name = "da9061-thermal", - .num_resources = ARRAY_SIZE(da9061_thermal_resources), - .resources = da9061_thermal_resources, - .of_compatible = "dlg,da9061-thermal", - }, - { - .name = "da9061-onkey", - .num_resources = ARRAY_SIZE(da9061_onkey_resources), - .resources = da9061_onkey_resources, - .of_compatible = "dlg,da9061-onkey", - }, + MFD_CELL_OF("da9061-core", da9061_core_resources, NULL, 0, 0, + NULL), + MFD_CELL_OF("da9062-regulators", da9061_regulators_resources, NULL, 0, 0, + NULL), + MFD_CELL_OF("da9061-watchdog", da9061_wdt_resources, NULL, 0, 0, + "dlg,da9061-watchdog"), + MFD_CELL_OF("da9061-thermal", da9061_thermal_resources, NULL, 0, 0, + "dlg,da9061-thermal"), + MFD_CELL_OF("da9061-onkey", da9061_onkey_resources, NULL, 0, 0, + "dlg,da9061-onkey"), }; static const struct resource da9062_core_resources[] = { @@ -246,46 +228,20 @@ static const struct resource da9062_gpio_resources[] = { }; static const struct mfd_cell da9062_devs[] = { - { - .name = "da9062-core", - .num_resources = ARRAY_SIZE(da9062_core_resources), - .resources = da9062_core_resources, - }, - { - .name = "da9062-regulators", - .num_resources = ARRAY_SIZE(da9062_regulators_resources), - .resources = da9062_regulators_resources, - }, - { - .name = "da9062-watchdog", - .num_resources = ARRAY_SIZE(da9062_wdt_resources), - .resources = da9062_wdt_resources, - .of_compatible = "dlg,da9062-watchdog", - }, - { - .name = "da9062-thermal", - .num_resources = ARRAY_SIZE(da9062_thermal_resources), - .resources = da9062_thermal_resources, - .of_compatible = "dlg,da9062-thermal", - }, - { - .name = "da9062-rtc", - .num_resources = ARRAY_SIZE(da9062_rtc_resources), - .resources = da9062_rtc_resources, - .of_compatible = "dlg,da9062-rtc", - }, - { - .name = "da9062-onkey", - .num_resources = ARRAY_SIZE(da9062_onkey_resources), - .resources = da9062_onkey_resources, - .of_compatible = "dlg,da9062-onkey", - }, - { - .name = "da9062-gpio", - .num_resources = ARRAY_SIZE(da9062_gpio_resources), - .resources = da9062_gpio_resources, - .of_compatible = "dlg,da9062-gpio", - }, + MFD_CELL_OF("da9062-core", da9062_core_resources, NULL, 0, 0, + NULL), + MFD_CELL_OF("da9062-regulators", da9062_regulators_resources, NULL, 0, 0, + NULL), + MFD_CELL_OF("da9062-watchdog", da9062_wdt_resources, NULL, 0, 0, + "dlg,da9062-watchdog"), + MFD_CELL_OF("da9062-thermal", da9062_thermal_resources, NULL, 0, 0, + "dlg,da9062-thermal"), + MFD_CELL_OF("da9062-rtc", da9062_rtc_resources, NULL, 0, 0, + "dlg,da9062-rtc"), + MFD_CELL_OF("da9062-onkey", da9062_onkey_resources, NULL, 0, 0, + "dlg,da9062-onkey"), + MFD_CELL_OF("da9062-gpio", da9062_gpio_resources, NULL, 0, 0, + "dlg,da9062-gpio"), }; static int da9062_clear_fault_log(struct da9062 *chip) -- cgit v1.2.3 From c923d5001ba054df10ed3441d24f8f2c01db7e00 Mon Sep 17 00:00:00 2001 From: Christoph Niedermaier Date: Thu, 9 Mar 2023 10:22:53 +0100 Subject: mfd: da9062: Remove IRQ requirement This patch removes the requirement for an IRQ, because for the core functionality IRQ isn't needed. So this makes the DA9061/62 chip usable for designs which haven't connected the IRQ pin. Signed-off-by: Christoph Niedermaier Acked-by: Adam Ward Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230309092254.56279-2-cniedermaier@dh-electronics.com --- drivers/mfd/da9062-core.c | 84 +++++++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 29 deletions(-) diff --git a/drivers/mfd/da9062-core.c b/drivers/mfd/da9062-core.c index 9418c58c2b06..d073d5f106ec 100644 --- a/drivers/mfd/da9062-core.c +++ b/drivers/mfd/da9062-core.c @@ -181,7 +181,7 @@ static const struct resource da9061_onkey_resources[] = { DEFINE_RES_IRQ_NAMED(DA9061_IRQ_ONKEY, "ONKEY"), }; -static const struct mfd_cell da9061_devs[] = { +static const struct mfd_cell da9061_devs_irq[] = { MFD_CELL_OF("da9061-core", da9061_core_resources, NULL, 0, 0, NULL), MFD_CELL_OF("da9062-regulators", da9061_regulators_resources, NULL, 0, 0, @@ -194,6 +194,14 @@ static const struct mfd_cell da9061_devs[] = { "dlg,da9061-onkey"), }; +static const struct mfd_cell da9061_devs_noirq[] = { + MFD_CELL_OF("da9061-core", NULL, NULL, 0, 0, NULL), + MFD_CELL_OF("da9062-regulators", NULL, NULL, 0, 0, NULL), + MFD_CELL_OF("da9061-watchdog", NULL, NULL, 0, 0, "dlg,da9061-watchdog"), + MFD_CELL_OF("da9061-thermal", NULL, NULL, 0, 0, "dlg,da9061-thermal"), + MFD_CELL_OF("da9061-onkey", NULL, NULL, 0, 0, "dlg,da9061-onkey"), +}; + static const struct resource da9062_core_resources[] = { DEFINE_RES_NAMED(DA9062_IRQ_VDD_WARN, 1, "VDD_WARN", IORESOURCE_IRQ), }; @@ -227,7 +235,7 @@ static const struct resource da9062_gpio_resources[] = { DEFINE_RES_NAMED(DA9062_IRQ_GPI4, 1, "GPI4", IORESOURCE_IRQ), }; -static const struct mfd_cell da9062_devs[] = { +static const struct mfd_cell da9062_devs_irq[] = { MFD_CELL_OF("da9062-core", da9062_core_resources, NULL, 0, 0, NULL), MFD_CELL_OF("da9062-regulators", da9062_regulators_resources, NULL, 0, 0, @@ -244,6 +252,16 @@ static const struct mfd_cell da9062_devs[] = { "dlg,da9062-gpio"), }; +static const struct mfd_cell da9062_devs_noirq[] = { + MFD_CELL_OF("da9062-core", NULL, NULL, 0, 0, NULL), + MFD_CELL_OF("da9062-regulators", NULL, NULL, 0, 0, NULL), + MFD_CELL_OF("da9062-watchdog", NULL, NULL, 0, 0, "dlg,da9062-watchdog"), + MFD_CELL_OF("da9062-thermal", NULL, NULL, 0, 0, "dlg,da9062-thermal"), + MFD_CELL_OF("da9062-rtc", NULL, NULL, 0, 0, "dlg,da9062-rtc"), + MFD_CELL_OF("da9062-onkey", NULL, NULL, 0, 0, "dlg,da9062-onkey"), + MFD_CELL_OF("da9062-gpio", NULL, NULL, 0, 0, "dlg,da9062-gpio"), +}; + static int da9062_clear_fault_log(struct da9062 *chip) { int ret; @@ -581,7 +599,7 @@ static int da9062_i2c_probe(struct i2c_client *i2c) { const struct i2c_device_id *id = i2c_client_get_device_id(i2c); struct da9062 *chip; - unsigned int irq_base; + unsigned int irq_base = 0; const struct mfd_cell *cell; const struct regmap_irq_chip *irq_chip; const struct regmap_config *config; @@ -601,22 +619,16 @@ static int da9062_i2c_probe(struct i2c_client *i2c) i2c_set_clientdata(i2c, chip); chip->dev = &i2c->dev; - if (!i2c->irq) { - dev_err(chip->dev, "No IRQ configured\n"); - return -EINVAL; - } - + /* Start with a base configuration without IRQ */ switch (chip->chip_type) { case COMPAT_TYPE_DA9061: - cell = da9061_devs; - cell_num = ARRAY_SIZE(da9061_devs); - irq_chip = &da9061_irq_chip; + cell = da9061_devs_noirq; + cell_num = ARRAY_SIZE(da9061_devs_noirq); config = &da9061_regmap_config; break; case COMPAT_TYPE_DA9062: - cell = da9062_devs; - cell_num = ARRAY_SIZE(da9062_devs); - irq_chip = &da9062_irq_chip; + cell = da9062_devs_noirq; + cell_num = ARRAY_SIZE(da9062_devs_noirq); config = &da9062_regmap_config; break; default: @@ -651,29 +663,43 @@ static int da9062_i2c_probe(struct i2c_client *i2c) if (ret) return ret; - ret = da9062_configure_irq_type(chip, i2c->irq, &trigger_type); - if (ret < 0) { - dev_err(chip->dev, "Failed to configure IRQ type\n"); - return ret; - } + /* If IRQ is available, reconfigure it accordingly */ + if (i2c->irq) { + if (chip->chip_type == COMPAT_TYPE_DA9061) { + cell = da9061_devs_irq; + cell_num = ARRAY_SIZE(da9061_devs_irq); + irq_chip = &da9061_irq_chip; + } else { + cell = da9062_devs_irq; + cell_num = ARRAY_SIZE(da9062_devs_irq); + irq_chip = &da9062_irq_chip; + } - ret = regmap_add_irq_chip(chip->regmap, i2c->irq, - trigger_type | IRQF_SHARED | IRQF_ONESHOT, - -1, irq_chip, &chip->regmap_irq); - if (ret) { - dev_err(chip->dev, "Failed to request IRQ %d: %d\n", - i2c->irq, ret); - return ret; - } + ret = da9062_configure_irq_type(chip, i2c->irq, &trigger_type); + if (ret < 0) { + dev_err(chip->dev, "Failed to configure IRQ type\n"); + return ret; + } - irq_base = regmap_irq_chip_get_base(chip->regmap_irq); + ret = regmap_add_irq_chip(chip->regmap, i2c->irq, + trigger_type | IRQF_SHARED | IRQF_ONESHOT, + -1, irq_chip, &chip->regmap_irq); + if (ret) { + dev_err(chip->dev, "Failed to request IRQ %d: %d\n", + i2c->irq, ret); + return ret; + } + + irq_base = regmap_irq_chip_get_base(chip->regmap_irq); + } ret = mfd_add_devices(chip->dev, PLATFORM_DEVID_NONE, cell, cell_num, NULL, irq_base, NULL); if (ret) { dev_err(chip->dev, "Cannot register child devices\n"); - regmap_del_irq_chip(i2c->irq, chip->regmap_irq); + if (i2c->irq) + regmap_del_irq_chip(i2c->irq, chip->regmap_irq); return ret; } -- cgit v1.2.3 From 75a6ff48fe16e4221be68eb354747bb207d61535 Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Wed, 8 Mar 2023 19:42:59 +0000 Subject: mfd: da9055: Do not cite as modular This driver cannot be built as a module, so don't suggest otherwise in Kconfig help. Suggested-by: Lee Jones Signed-off-by: Nick Alcock Reviewed-by: Vincenzo Palazzo Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index d381d0e63455..51d54a1b8673 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -363,9 +363,6 @@ config MFD_DA9055 Additional drivers must be enabled in order to use the functionality of the device. - This driver can be built as a module. If built as a module it will be - called "da9055" - config MFD_DA9062 tristate "Dialog Semiconductor DA9062/61 PMIC Support" select MFD_CORE -- cgit v1.2.3 From 3a101f09b1066991569ce9f4fd1e90a07e97fb3a Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Wed, 8 Mar 2023 19:43:07 +0000 Subject: mfd: twl6040: Remove MODULE_LICENSE in non-modules Since commit 8b41fc4454e ("kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf"), MODULE_LICENSE declarations are used to identify modules. As a consequence, uses of the macro in non-modules will cause modprobe to misidentify their containing object file as a module when it is not (false positives), and modprobe might succeed rather than failing with a suitable error message. So remove it in the files in this commit, none of which can be built as modules. Signed-off-by: Nick Alcock Suggested-by: Luis Chamberlain Signed-off-by: Lee Jones --- drivers/mfd/twl6040.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c index fc97fa5a2d0c..e982119bbefa 100644 --- a/drivers/mfd/twl6040.c +++ b/drivers/mfd/twl6040.c @@ -839,4 +839,3 @@ module_i2c_driver(twl6040_driver); MODULE_DESCRIPTION("TWL6040 MFD"); MODULE_AUTHOR("Misael Lopez Cruz "); MODULE_AUTHOR("Jorge Eduardo Candelaria "); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From b22f3152494e3b1e2fce4d61ad828420d16e9e5d Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Wed, 8 Mar 2023 19:43:06 +0000 Subject: mfd: twl4030-audio: Remove MODULE_LICENSE in non-modules Since commit 8b41fc4454e ("kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf"), MODULE_LICENSE declarations are used to identify modules. As a consequence, uses of the macro in non-modules will cause modprobe to misidentify their containing object file as a module when it is not (false positives), and modprobe might succeed rather than failing with a suitable error message. So remove it in the files in this commit, none of which can be built as modules. Signed-off-by: Nick Alcock Suggested-by: Luis Chamberlain Signed-off-by: Lee Jones --- drivers/mfd/twl4030-audio.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c index 4536d829b43e..88002f8941e5 100644 --- a/drivers/mfd/twl4030-audio.c +++ b/drivers/mfd/twl4030-audio.c @@ -285,5 +285,4 @@ module_platform_driver(twl4030_audio_driver); MODULE_AUTHOR("Peter Ujfalusi "); MODULE_DESCRIPTION("TWL4030 audio block MFD driver"); -MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:twl4030-audio"); -- cgit v1.2.3 From f580386425518643c4027286b48cfa545390be07 Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Wed, 8 Mar 2023 19:43:03 +0000 Subject: mfd: lp8788: Remove MODULE_LICENSE in non-modules Since commit 8b41fc4454e ("kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf"), MODULE_LICENSE declarations are used to identify modules. As a consequence, uses of the macro in non-modules will cause modprobe to misidentify their containing object file as a module when it is not (false positives), and modprobe might succeed rather than failing with a suitable error message. So remove it in the files in this commit, none of which can be built as modules. Signed-off-by: Nick Alcock Suggested-by: Luis Chamberlain Signed-off-by: Lee Jones --- drivers/mfd/lp8788.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/lp8788.c b/drivers/mfd/lp8788.c index fe809b64147e..18583addaae2 100644 --- a/drivers/mfd/lp8788.c +++ b/drivers/mfd/lp8788.c @@ -244,4 +244,3 @@ module_exit(lp8788_exit); MODULE_DESCRIPTION("TI LP8788 MFD Driver"); MODULE_AUTHOR("Milo Kim"); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From fb2455985b5981e4f8a72667bb3d4bd5b7ca2b12 Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Wed, 8 Mar 2023 19:43:01 +0000 Subject: mfd: tps6586x: Remove MODULE_LICENSE in non-modules Since commit 8b41fc4454e ("kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf"), MODULE_LICENSE declarations are used to identify modules. As a consequence, uses of the macro in non-modules will cause modprobe to misidentify their containing object file as a module when it is not (false positives), and modprobe might succeed rather than failing with a suitable error message. So remove it in the files in this commit, none of which can be built as modules. Signed-off-by: Nick Alcock Suggested-by: Luis Chamberlain Signed-off-by: Lee Jones --- drivers/mfd/tps6586x.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c index 2d947f3f606a..90e23232b6b0 100644 --- a/drivers/mfd/tps6586x.c +++ b/drivers/mfd/tps6586x.c @@ -638,4 +638,3 @@ module_exit(tps6586x_exit); MODULE_DESCRIPTION("TPS6586X core driver"); MODULE_AUTHOR("Mike Rapoport "); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 85aebcd54e2d22c00e0964442dc5330128e43f9b Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Wed, 8 Mar 2023 19:43:05 +0000 Subject: mfd: omap-usb-tll: Remove MODULE_LICENSE in non-modules Since commit 8b41fc4454e ("kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf"), MODULE_LICENSE declarations are used to identify modules. As a consequence, uses of the macro in non-modules will cause modprobe to misidentify their containing object file as a module when it is not (false positives), and modprobe might succeed rather than failing with a suitable error message. So remove it in the files in this commit, none of which can be built as modules. Signed-off-by: Nick Alcock Suggested-by: Luis Chamberlain Signed-off-by: Lee Jones --- drivers/mfd/omap-usb-tll.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c index 080d7970a377..8ca4067da6cd 100644 --- a/drivers/mfd/omap-usb-tll.c +++ b/drivers/mfd/omap-usb-tll.c @@ -450,7 +450,6 @@ EXPORT_SYMBOL_GPL(omap_tll_disable); MODULE_AUTHOR("Keshava Munegowda "); MODULE_AUTHOR("Roger Quadros "); -MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("usb tll driver for TI OMAP EHCI and OHCI controllers"); static int __init omap_usbtll_drvinit(void) -- cgit v1.2.3 From e3dfb3dbd67805914ebda52430257b370554e479 Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Wed, 8 Mar 2023 19:43:04 +0000 Subject: mfd: omap-usb-host: Remove MODULE_LICENSE in non-modules Since commit 8b41fc4454e ("kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf"), MODULE_LICENSE declarations are used to identify modules. As a consequence, uses of the macro in non-modules will cause modprobe to misidentify their containing object file as a module when it is not (false positives), and modprobe might succeed rather than failing with a suitable error message. So remove it in the files in this commit, none of which can be built as modules. Signed-off-by: Nick Alcock Suggested-by: Luis Chamberlain Signed-off-by: Lee Jones --- drivers/mfd/omap-usb-host.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index 787d2ae86375..7f5775109593 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c @@ -853,7 +853,6 @@ static struct platform_driver usbhs_omap_driver = { MODULE_AUTHOR("Keshava Munegowda "); MODULE_AUTHOR("Roger Quadros "); MODULE_ALIAS("platform:" USBHS_DRIVER_NAME); -MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("usb host common core driver for omap EHCI and OHCI"); static int omap_usbhs_drvinit(void) -- cgit v1.2.3 From 0607ad38c2fb0182eba20d4f476558b0547d58a5 Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Wed, 8 Mar 2023 19:43:02 +0000 Subject: mfd: ezx-pcap: Remove MODULE_LICENSE in non-modules Since commit 8b41fc4454e ("kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf"), MODULE_LICENSE declarations are used to identify modules. As a consequence, uses of the macro in non-modules will cause modprobe to misidentify their containing object file as a module when it is not (false positives), and modprobe might succeed rather than failing with a suitable error message. So remove it in the files in this commit, none of which can be built as modules. Signed-off-by: Nick Alcock Suggested-by: Luis Chamberlain Signed-off-by: Lee Jones --- drivers/mfd/ezx-pcap.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c index 3d5ce18aa9ae..8d006f6be48c 100644 --- a/drivers/mfd/ezx-pcap.c +++ b/drivers/mfd/ezx-pcap.c @@ -528,7 +528,6 @@ static void __exit ezx_pcap_exit(void) subsys_initcall(ezx_pcap_init); module_exit(ezx_pcap_exit); -MODULE_LICENSE("GPL"); MODULE_AUTHOR("Daniel Ribeiro / Harald Welte"); MODULE_DESCRIPTION("Motorola PCAP2 ASIC Driver"); MODULE_ALIAS("spi:ezx-pcap"); -- cgit v1.2.3 From 65edd14d790cfe076be0da58c457f75b35395c27 Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Wed, 8 Mar 2023 19:43:00 +0000 Subject: mfd: tc3589x: Remove MODULE_LICENSE in non-modules Since commit 8b41fc4454e ("kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf"), MODULE_LICENSE declarations are used to identify modules. As a consequence, uses of the macro in non-modules will cause modprobe to misidentify their containing object file as a module when it is not (false positives), and modprobe might succeed rather than failing with a suitable error message. So remove it in the files in this commit, none of which can be built as modules. Signed-off-by: Nick Alcock Suggested-by: Luis Chamberlain Signed-off-by: Lee Jones --- drivers/mfd/tc3589x.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index 1f6e0d682cd9..cbfe19d1b145 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -502,6 +502,5 @@ static void __exit tc3589x_exit(void) } module_exit(tc3589x_exit); -MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("TC3589x MFD core driver"); MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent"); -- cgit v1.2.3 From ce1b2783136a1b44b619336fbe76776ae2c8f3ab Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Wed, 8 Mar 2023 19:42:58 +0000 Subject: mfd: 88pm860x: Remove MODULE_LICENSE in non-modules Since commit 8b41fc4454e ("kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf"), MODULE_LICENSE declarations are used to identify modules. As a consequence, uses of the macro in non-modules will cause modprobe to misidentify their containing object file as a module when it is not (false positives), and modprobe might succeed rather than failing with a suitable error message. So remove it in the files in this commit, none of which can be built as modules. Signed-off-by: Nick Alcock Suggested-by: Luis Chamberlain Signed-off-by: Lee Jones --- drivers/mfd/88pm860x-core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index 6ba7169cb953..3c57e537d57f 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c @@ -1276,4 +1276,3 @@ module_exit(pm860x_i2c_exit); MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM860x"); MODULE_AUTHOR("Haojian Zhuang "); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 9ca834bd404c2b1e1e7010e7c22c5a1810fd7cd5 Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Wed, 8 Mar 2023 19:42:57 +0000 Subject: mfd: stmpe-spi: Remove MODULE_LICENSE in non-modules Since commit 8b41fc4454e ("kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf"), MODULE_LICENSE declarations are used to identify modules. As a consequence, uses of the macro in non-modules will cause modprobe to misidentify their containing object file as a module when it is not (false positives), and modprobe might succeed rather than failing with a suitable error message. So remove it in the files in this commit, none of which can be built as modules. Signed-off-by: Nick Alcock Suggested-by: Luis Chamberlain Signed-off-by: Lee Jones --- drivers/mfd/stmpe-spi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/stmpe-spi.c b/drivers/mfd/stmpe-spi.c index e9cbf33502b3..792236f56399 100644 --- a/drivers/mfd/stmpe-spi.c +++ b/drivers/mfd/stmpe-spi.c @@ -154,6 +154,5 @@ static void __exit stmpe_exit(void) } module_exit(stmpe_exit); -MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("STMPE MFD SPI Interface Driver"); MODULE_AUTHOR("Viresh Kumar "); -- cgit v1.2.3 From 9e646615df195f1864e2384133a42a832a809059 Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Wed, 8 Mar 2023 19:42:56 +0000 Subject: mfd: stmpe-i2c: Remove MODULE_LICENSE in non-modules Since commit 8b41fc4454e ("kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf"), MODULE_LICENSE declarations are used to identify modules. As a consequence, uses of the macro in non-modules will cause modprobe to misidentify their containing object file as a module when it is not (false positives), and modprobe might succeed rather than failing with a suitable error message. So remove it in the files in this commit, none of which can be built as modules. Signed-off-by: Nick Alcock Suggested-by: Luis Chamberlain Signed-off-by: Lee Jones --- drivers/mfd/stmpe-i2c.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c index d4944fc1feb1..7998e0db1e15 100644 --- a/drivers/mfd/stmpe-i2c.c +++ b/drivers/mfd/stmpe-i2c.c @@ -135,6 +135,5 @@ static void __exit stmpe_exit(void) } module_exit(stmpe_exit); -MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("STMPE MFD I2C Interface Driver"); MODULE_AUTHOR("Rabin Vincent "); -- cgit v1.2.3 From e7bf264def565d77474dd074109cc84948a5058e Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Wed, 8 Mar 2023 19:42:55 +0000 Subject: mfd: da9055-i2c: Remove MODULE_LICENSE in non-modules Since commit 8b41fc4454e ("kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf"), MODULE_LICENSE declarations are used to identify modules. As a consequence, uses of the macro in non-modules will cause modprobe to misidentify their containing object file as a module when it is not (false positives), and modprobe might succeed rather than failing with a suitable error message. So remove it in the files in this commit, none of which can be built as modules. Signed-off-by: Nick Alcock Suggested-by: Luis Chamberlain Signed-off-by: Lee Jones --- drivers/mfd/da9055-i2c.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/da9055-i2c.c b/drivers/mfd/da9055-i2c.c index 702abff506a1..537fd5de3e6d 100644 --- a/drivers/mfd/da9055-i2c.c +++ b/drivers/mfd/da9055-i2c.c @@ -97,4 +97,3 @@ module_exit(da9055_i2c_exit); MODULE_AUTHOR("David Dajun Chen "); MODULE_DESCRIPTION("I2C driver for Dialog DA9055 PMIC"); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 1247f3c3e1f29fc78027dfe4043f6c0413612126 Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Wed, 8 Mar 2023 19:42:54 +0000 Subject: mfd: da9055: Remove MODULE_LICENSE in non-modules Since commit 8b41fc4454e ("kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf"), MODULE_LICENSE declarations are used to identify modules. As a consequence, uses of the macro in non-modules will cause modprobe to misidentify their containing object file as a module when it is not (false positives), and modprobe might succeed rather than failing with a suitable error message. So remove it in the files in this commit, none of which can be built as modules. Signed-off-by: Nick Alcock Suggested-by: Luis Chamberlain Signed-off-by: Lee Jones --- drivers/mfd/da9055-core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/da9055-core.c b/drivers/mfd/da9055-core.c index c3bcbd8905c6..768302e05baa 100644 --- a/drivers/mfd/da9055-core.c +++ b/drivers/mfd/da9055-core.c @@ -398,5 +398,4 @@ void da9055_device_exit(struct da9055 *da9055) } MODULE_DESCRIPTION("Core support for the DA9055 PMIC"); -MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Dajun Chen "); -- cgit v1.2.3 From fca17373d26c5e4e98134f97601aff688d164813 Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Wed, 8 Mar 2023 19:42:53 +0000 Subject: mfd: da9052-spi: Remove MODULE_LICENSE in non-modules Since commit 8b41fc4454e ("kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf"), MODULE_LICENSE declarations are used to identify modules. As a consequence, uses of the macro in non-modules will cause modprobe to misidentify their containing object file as a module when it is not (false positives), and modprobe might succeed rather than failing with a suitable error message. So remove it in the files in this commit, none of which can be built as modules. Signed-off-by: Nick Alcock Suggested-by: Luis Chamberlain Signed-off-by: Lee Jones --- drivers/mfd/da9052-spi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/da9052-spi.c b/drivers/mfd/da9052-spi.c index b79a57b45c1e..be5f2b34e18a 100644 --- a/drivers/mfd/da9052-spi.c +++ b/drivers/mfd/da9052-spi.c @@ -102,4 +102,3 @@ module_exit(da9052_spi_exit); MODULE_AUTHOR("David Dajun Chen "); MODULE_DESCRIPTION("SPI driver for Dialog DA9052 PMIC"); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From adefecd9b506a6f9981cdcda97ae6803bdea0180 Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Wed, 8 Mar 2023 19:42:52 +0000 Subject: mfd: da9052-i2c: Remove MODULE_LICENSE in non-modules Since commit 8b41fc4454e ("kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf"), MODULE_LICENSE declarations are used to identify modules. As a consequence, uses of the macro in non-modules will cause modprobe to misidentify their containing object file as a module when it is not (false positives), and modprobe might succeed rather than failing with a suitable error message. So remove it in the files in this commit, none of which can be built as modules. Signed-off-by: Nick Alcock Suggested-by: Luis Chamberlain Signed-off-by: Lee Jones --- drivers/mfd/da9052-i2c.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c index ecb8077cdaaf..03db7a2ccf7a 100644 --- a/drivers/mfd/da9052-i2c.c +++ b/drivers/mfd/da9052-i2c.c @@ -209,4 +209,3 @@ module_exit(da9052_i2c_exit); MODULE_AUTHOR("David Dajun Chen "); MODULE_DESCRIPTION("I2C driver for Dialog DA9052 PMIC"); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From ca9642a623dfc43a8ec8b0ba4694605ea74cef20 Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Wed, 8 Mar 2023 19:42:51 +0000 Subject: mfd: da9052: Remove MODULE_LICENSE in non-modules Since commit 8b41fc4454e ("kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf"), MODULE_LICENSE declarations are used to identify modules. As a consequence, uses of the macro in non-modules will cause modprobe to misidentify their containing object file as a module when it is not (false positives), and modprobe might succeed rather than failing with a suitable error message. So remove it in the files in this commit, none of which can be built as modules. Signed-off-by: Nick Alcock Suggested-by: Luis Chamberlain Signed-off-by: Lee Jones --- drivers/mfd/da9052-core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c index 8b42d2f7024f..150448cd2eb0 100644 --- a/drivers/mfd/da9052-core.c +++ b/drivers/mfd/da9052-core.c @@ -653,4 +653,3 @@ void da9052_device_exit(struct da9052 *da9052) MODULE_AUTHOR("David Dajun Chen "); MODULE_DESCRIPTION("DA9052 MFD Core"); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 2ddbddaf19dcdc60e05c720611faca7ba5176ed9 Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Wed, 8 Mar 2023 19:42:50 +0000 Subject: mfd: da903x: Remove MODULE_LICENSE in non-modules Since commit 8b41fc4454e ("kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf"), MODULE_LICENSE declarations are used to identify modules. As a consequence, uses of the macro in non-modules will cause modprobe to misidentify their containing object file as a module when it is not (false positives), and modprobe might succeed rather than failing with a suitable error message. So remove it in the files in this commit, none of which can be built as modules. Signed-off-by: Nick Alcock Suggested-by: Luis Chamberlain Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230308194307.374789-1-nick.alcock@oracle.com --- drivers/mfd/da903x.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c index 44a25d642ce9..6570b33a5a77 100644 --- a/drivers/mfd/da903x.c +++ b/drivers/mfd/da903x.c @@ -563,4 +563,3 @@ module_exit(da903x_exit); MODULE_DESCRIPTION("PMIC Driver for Dialog Semiconductor DA9034"); MODULE_AUTHOR("Eric Miao "); MODULE_AUTHOR("Mike Rapoport "); -MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 1ba58fbbe619125af113d0583c4b6bade94168d1 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 10 Mar 2023 08:47:12 -0600 Subject: mfd: various: Use of_property_present() for testing DT property presence It is preferred to use typed property access functions (i.e. of_property_read_ functions) rather than low-level of_get_property/of_find_property functions for reading properties. As part of this, convert of_get_property/of_find_property calls to the recently added of_property_present() helper when we just want to test for presence of a property and nothing more. Signed-off-by: Rob Herring Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230310144712.1543379-1-robh@kernel.org --- drivers/mfd/bcm2835-pm.c | 2 +- drivers/mfd/khadas-mcu.c | 2 +- drivers/mfd/stmpe.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mfd/bcm2835-pm.c b/drivers/mfd/bcm2835-pm.c index 2c0aa2a2c893..3cb2b9423121 100644 --- a/drivers/mfd/bcm2835-pm.c +++ b/drivers/mfd/bcm2835-pm.c @@ -28,7 +28,7 @@ static const struct mfd_cell bcm2835_power_devs[] = { static int bcm2835_pm_get_pdata(struct platform_device *pdev, struct bcm2835_pm *pm) { - if (of_find_property(pm->dev->of_node, "reg-names", NULL)) { + if (of_property_present(pm->dev->of_node, "reg-names")) { struct resource *res; pm->base = devm_platform_ioremap_resource_byname(pdev, "pm"); diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c index 7338cc16f327..1c807c0e6d25 100644 --- a/drivers/mfd/khadas-mcu.c +++ b/drivers/mfd/khadas-mcu.c @@ -112,7 +112,7 @@ static int khadas_mcu_probe(struct i2c_client *client) if (ret) return ret; - if (of_find_property(dev->of_node, "#cooling-cells", NULL)) + if (of_property_present(dev->of_node, "#cooling-cells")) return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, khadas_mcu_fan_cells, ARRAY_SIZE(khadas_mcu_fan_cells), diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index c304d20bb988..a92301dfc712 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c @@ -1378,7 +1378,7 @@ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum) stmpe_of_probe(pdata, np); - if (of_find_property(np, "interrupts", NULL) == NULL) + if (!of_property_present(np, "interrupts")) ci->irq = -1; stmpe = devm_kzalloc(ci->dev, sizeof(struct stmpe), GFP_KERNEL); -- cgit v1.2.3 From 01330edcc5ecc92eb9152b27f326618735900502 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 10 Mar 2023 08:47:12 -0600 Subject: mfd: various: Use of_property_read_bool() for boolean properties It is preferred to use typed property access functions (i.e. of_property_read_ functions) rather than low-level of_get_property/of_find_property functions for reading properties. Convert reading boolean properties to to of_property_read_bool(). Signed-off-by: Rob Herring Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230310144712.1543449-1-robh@kernel.org --- drivers/mfd/88pm860x-core.c | 3 +-- drivers/mfd/wm8994-core.c | 19 +++++-------------- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index 3c57e537d57f..aabac37c3502 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c @@ -1117,8 +1117,7 @@ static int pm860x_dt_init(struct device_node *np, { int ret; - if (of_get_property(np, "marvell,88pm860x-irq-read-clr", NULL)) - pdata->irq_mode = 1; + pdata->irq_mode = of_property_read_bool(np, "marvell,88pm860x-irq-read-clr"); ret = of_property_read_u32(np, "marvell,88pm860x-slave-addr", &pdata->companion_addr); if (ret) { diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index a89221bffde5..c419ab0c0eae 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -279,20 +279,11 @@ static int wm8994_set_pdata_from_of(struct wm8994 *wm8994) of_property_read_u32_array(np, "wlf,micbias-cfg", pdata->micbias, ARRAY_SIZE(pdata->micbias)); - pdata->lineout1_diff = true; - pdata->lineout2_diff = true; - if (of_find_property(np, "wlf,lineout1-se", NULL)) - pdata->lineout1_diff = false; - if (of_find_property(np, "wlf,lineout2-se", NULL)) - pdata->lineout2_diff = false; - - if (of_find_property(np, "wlf,lineout1-feedback", NULL)) - pdata->lineout1fb = true; - if (of_find_property(np, "wlf,lineout2-feedback", NULL)) - pdata->lineout2fb = true; - - if (of_find_property(np, "wlf,ldoena-always-driven", NULL)) - pdata->lineout2fb = true; + pdata->lineout1_diff = !of_property_read_bool(np, "wlf,lineout1-se"); + pdata->lineout2_diff = !of_property_read_bool(np, "wlf,lineout2-se"); + pdata->lineout1fb = of_property_read_bool(np, "wlf,lineout1-feedback"); + pdata->lineout2fb = of_property_read_bool(np, "wlf,lineout2-feedback") || + of_property_read_bool(np, "wlf,ldoena-always-driven"); pdata->spkmode_pu = of_property_read_bool(np, "wlf,spkmode-pu"); -- cgit v1.2.3 From f130faebcdb6c7fd04c1db9e589d593361b81c13 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 11 Mar 2023 12:16:28 +0100 Subject: mfd: atmel-smc: Mark OF related data as maybe unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can be compile tested with !CONFIG_OF making certain data unused: drivers/mfd/atmel-smc.c:326:34: error: ‘atmel_smc_ids’ defined but not used [-Werror=unused-const-variable=] Signed-off-by: Krzysztof Kozlowski Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230311111629.251830-1-krzysztof.kozlowski@linaro.org --- drivers/mfd/atmel-smc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/atmel-smc.c b/drivers/mfd/atmel-smc.c index f3bad2b52f17..e560066e5885 100644 --- a/drivers/mfd/atmel-smc.c +++ b/drivers/mfd/atmel-smc.c @@ -323,7 +323,7 @@ static const struct atmel_hsmc_reg_layout sama5d2_reg_layout = { .timing_regs_offset = 0x700, }; -static const struct of_device_id atmel_smc_ids[] = { +static const struct of_device_id atmel_smc_ids[] __maybe_unused = { { .compatible = "atmel,at91sam9260-smc", .data = NULL }, { .compatible = "atmel,sama5d3-smc", .data = &sama5d3_reg_layout }, { .compatible = "atmel,sama5d2-smc", .data = &sama5d2_reg_layout }, -- cgit v1.2.3 From 9bb8ccead3b0162cf98091c4ff25e772fd97d953 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 11 Mar 2023 12:16:29 +0100 Subject: mfd: atc260x-i2c: Drop of_match_ptr for ID table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can match only via the DT table so the table should be always used and the of_match_ptr does not have any sense (this also allows ACPI matching via PRP0001, even though it might not be relevant here). drivers/mfd/atc260x-i2c.c:44:34: error: ‘atc260x_i2c_of_match’ defined but not used [-Werror=unused-const-variable=] Signed-off-by: Krzysztof Kozlowski Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230311111629.251830-2-krzysztof.kozlowski@linaro.org --- drivers/mfd/atc260x-i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/atc260x-i2c.c b/drivers/mfd/atc260x-i2c.c index 19e248ed7966..8e1491167160 100644 --- a/drivers/mfd/atc260x-i2c.c +++ b/drivers/mfd/atc260x-i2c.c @@ -51,7 +51,7 @@ MODULE_DEVICE_TABLE(of, atc260x_i2c_of_match); static struct i2c_driver atc260x_i2c_driver = { .driver = { .name = "atc260x", - .of_match_table = of_match_ptr(atc260x_i2c_of_match), + .of_match_table = atc260x_i2c_of_match, }, .probe_new = atc260x_i2c_probe, }; -- cgit v1.2.3 From e90978ecdf9d016e31f6aff36da77255b42fb4fd Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 13 Mar 2023 11:58:33 +0100 Subject: mfd: rsmu_spi: Remove unneeded casts of void * There is no need to cast a "void *" to a different type of pointer. Signed-off-by: Geert Uytterhoeven Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/ae84c1751e79cb49ab584557f4ecd835a8493d7c.1678704562.git.geert+renesas@glider.be --- drivers/mfd/rsmu_spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/rsmu_spi.c b/drivers/mfd/rsmu_spi.c index d2f3d8f1e05a..2428aaa9aaed 100644 --- a/drivers/mfd/rsmu_spi.c +++ b/drivers/mfd/rsmu_spi.c @@ -129,7 +129,7 @@ static int rsmu_write_page_register(struct rsmu_ddata *rsmu, u16 reg) static int rsmu_reg_read(void *context, unsigned int reg, unsigned int *val) { - struct rsmu_ddata *rsmu = spi_get_drvdata((struct spi_device *)context); + struct rsmu_ddata *rsmu = spi_get_drvdata(context); u8 addr = (u8)(reg & RSMU_LOWER_ADDR_MASK); int err; @@ -146,7 +146,7 @@ static int rsmu_reg_read(void *context, unsigned int reg, unsigned int *val) static int rsmu_reg_write(void *context, unsigned int reg, unsigned int val) { - struct rsmu_ddata *rsmu = spi_get_drvdata((struct spi_device *)context); + struct rsmu_ddata *rsmu = spi_get_drvdata(context); u8 addr = (u8)(reg & RSMU_LOWER_ADDR_MASK); u8 data = (u8)val; int err; -- cgit v1.2.3 From 44604617ce7aa0c24fd198b5a8760e018549922f Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Wed, 15 Mar 2023 19:38:19 +0100 Subject: dt-bindings: mfd: qcom,spmi-pmic: Add PM2250 Add a compatible for PM2250, commonly found with QCM2290. Signed-off-by: Konrad Dybcio Acked-by: Krzysztof Kozlowski Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230315183819.3563704-1-konrad.dybcio@linaro.org --- Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml index 8f076bb622b1..975c30aad23c 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml +++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml @@ -33,6 +33,7 @@ properties: compatible: items: - enum: + - qcom,pm2250 - qcom,pm6125 - qcom,pm6150 - qcom,pm6150l -- cgit v1.2.3 From 881656790e9bd246b7cf6eb537feb04f09140a40 Mon Sep 17 00:00:00 2001 From: André Apitzsch Date: Sun, 19 Mar 2023 13:41:53 +0100 Subject: mfd: arizona-i2c: Add the missing device table IDs for OF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds missing MODULE_DEVICE_TABLE definition which generates correct modalias for automatic loading of this driver when it is built as a module. Signed-off-by: André Apitzsch Acked-by: Charles Keepax Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230319124153.35294-1-git@apitzsch.eu --- drivers/mfd/arizona-i2c.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c index b2301586adbc..43e393c8608d 100644 --- a/drivers/mfd/arizona-i2c.c +++ b/drivers/mfd/arizona-i2c.c @@ -112,6 +112,7 @@ static const struct of_device_id arizona_i2c_of_match[] = { { .compatible = "wlf,wm1814", .data = (void *)WM1814 }, {}, }; +MODULE_DEVICE_TABLE(of, arizona_i2c_of_match); #endif static struct i2c_driver arizona_i2c_driver = { -- cgit v1.2.3 From 3e0475ec8d9114b600586b0bfb4056565a679a3d Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 14 Mar 2023 19:30:33 +0100 Subject: dt-bindings: mfd: qcom,spmi-pmic: Add compatible for pmm8654au PMM8654au is the SPMI PMIC variant used on sa8775p-ride. Add a compatible for it. Signed-off-by: Bartosz Golaszewski Acked-by: Rob Herring Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230314183043.619997-5-brgl@bgdev.pl --- Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml index 975c30aad23c..0f7dd7ac9630 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml +++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml @@ -79,6 +79,7 @@ properties: - qcom,pmk8350 - qcom,pmk8550 - qcom,pmm8155au + - qcom,pmm8654au - qcom,pmp8074 - qcom,pmr735a - qcom,pmr735b -- cgit v1.2.3 From 75c0a1b3fc1c09ed67d22235900cb7e762af1dfd Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Wed, 22 Mar 2023 07:58:38 -0400 Subject: mfd: twl-core: Remove unused add_child() and add_numbered_child() functions Clang with W=1 reports: drivers/mfd/twl-core.c:654:30: error: unused function 'add_child' [-Werror,-Wunused-function] static inline struct device *add_child(unsigned mod_no, const char *name, ^ add_numbered_child() and its only caller add_child() are not used, so remove them. Signed-off-by: Tom Rix Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230322115838.2569414-1-trix@redhat.com --- drivers/mfd/twl-core.c | 65 -------------------------------------------------- 1 file changed, 65 deletions(-) diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index e2d9a93be43b..e801b7ce010f 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -594,71 +594,6 @@ int twl_get_hfclk_rate(void) } EXPORT_SYMBOL_GPL(twl_get_hfclk_rate); -static struct device * -add_numbered_child(unsigned mod_no, const char *name, int num, - void *pdata, unsigned pdata_len, - bool can_wakeup, int irq0, int irq1) -{ - struct platform_device *pdev; - struct twl_client *twl; - int status, sid; - - if (unlikely(mod_no >= twl_get_last_module())) { - pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); - return ERR_PTR(-EPERM); - } - sid = twl_priv->twl_map[mod_no].sid; - twl = &twl_priv->twl_modules[sid]; - - pdev = platform_device_alloc(name, num); - if (!pdev) - return ERR_PTR(-ENOMEM); - - pdev->dev.parent = &twl->client->dev; - - if (pdata) { - status = platform_device_add_data(pdev, pdata, pdata_len); - if (status < 0) { - dev_dbg(&pdev->dev, "can't add platform_data\n"); - goto put_device; - } - } - - if (irq0) { - struct resource r[2] = { - { .start = irq0, .flags = IORESOURCE_IRQ, }, - { .start = irq1, .flags = IORESOURCE_IRQ, }, - }; - - status = platform_device_add_resources(pdev, r, irq1 ? 2 : 1); - if (status < 0) { - dev_dbg(&pdev->dev, "can't add irqs\n"); - goto put_device; - } - } - - status = platform_device_add(pdev); - if (status) - goto put_device; - - device_init_wakeup(&pdev->dev, can_wakeup); - - return &pdev->dev; - -put_device: - platform_device_put(pdev); - dev_err(&twl->client->dev, "failed to add device %s\n", name); - return ERR_PTR(status); -} - -static inline struct device *add_child(unsigned mod_no, const char *name, - void *pdata, unsigned pdata_len, - bool can_wakeup, int irq0, int irq1) -{ - return add_numbered_child(mod_no, name, -1, pdata, pdata_len, - can_wakeup, irq0, irq1); -} - /*----------------------------------------------------------------------*/ /* -- cgit v1.2.3 From 4363f2113d04db9bafcc79487050ee0c10875c5a Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Wed, 22 Mar 2023 08:58:03 -0400 Subject: mfd: omap-usb-tll: Remove unused usbtll_readb() function Clang with W=1 reports: drivers/mfd/omap-usb-tll.c:128:18: error: unused function 'usbtll_readb' [-Werror,-Wunused-function] static inline u8 usbtll_readb(void __iomem *base, u32 reg) ^ This function is not used so remove it. Signed-off-by: Tom Rix Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230322125803.2570968-1-trix@redhat.com --- drivers/mfd/omap-usb-tll.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c index 8ca4067da6cd..69cbc2097911 100644 --- a/drivers/mfd/omap-usb-tll.c +++ b/drivers/mfd/omap-usb-tll.c @@ -125,11 +125,6 @@ static inline void usbtll_writeb(void __iomem *base, u32 reg, u8 val) writeb_relaxed(val, base + reg); } -static inline u8 usbtll_readb(void __iomem *base, u32 reg) -{ - return readb_relaxed(base + reg); -} - /*-------------------------------------------------------------------------*/ static bool is_ohci_port(enum usbhs_omap_port_mode pmode) -- cgit v1.2.3 From f0484d2f80a72022b7fac72bcb406392900ef1eb Mon Sep 17 00:00:00 2001 From: Colin Foster Date: Wed, 22 Mar 2023 07:11:30 -0700 Subject: mfd: ocelot-spi: Fix unsupported bulk read Ocelot chips (VSC7511, VSC7512, VSC7513, VSC7514) don't support bulk read operations over SPI. Many SPI buses have hardware that can optimize consecutive reads. Essentially an address is written to the chip, and if the SPI controller continues to toggle the clock, subsequent register values are reported. This can lead to significant optimizations, because the time between "address is written to the chip" and "chip starts to report data" can often take a fixed amount of time. When support for Ocelot chips were added in commit f3e893626abe ("mfd: ocelot: Add support for the vsc7512 chip via spi") it was believed that this optimization was supported. However it is not. Most register transactions with the Ocelot chips are not done in bulk, so this bug could go unnoticed. The one scenario where bulk register operations _are_ performed is when polling port statistics counters, which was added in commit d87b1c08f38a ("net: mscc: ocelot: use bulk reads for stats"). Things get slightly more complicated here... A bug was introduced in commit d4c367650704 ("net: mscc: ocelot: keep ocelot_stat_layout by reg address, not offset") that broke the optimization of bulk reads. This means that when Ethernet support for the VSC7512 chip was added in commit 3d7316ac81ac ("net: dsa: ocelot: add external ocelot switch control") things were actually working "as expected". The bulk read opmtimization was discovered, and fixed in commit 6acc72a43eac ("net: mscc: ocelot: fix stats region batching") and the timing optimizations for SPI were noticed. A bulk read went from ~14ms to ~2ms. But this timing improvement came at the cost of every register reading zero due the fact that bulk reads don't work. The read timings increase back to 13-14ms, but that's a price worth paying in order to receive valid data. This is verified in a DSA setup (cpsw-new switch tied to port 0 on the VSC7512, after having been running overnight) Rx Octets: 16222055 # Counters from CPSW switch Tx Octets: 12034702 Net Octets: 28256757 p00_rx_octets: 12034702 # Counters from Ocelot switch p00_rx_frames_below_65_octets: 0 p00_rx_frames_65_to_127_octets: 88188 p00_rx_frames_128_to_255_octets: 13 p00_rx_frames_256_to_511_octets: 0 p00_rx_frames_512_to_1023_octets: 0 p00_rx_frames_over_1526_octets: 3306 p00_tx_octets: 16222055 Fixes: f3e893626abe ("mfd: ocelot: Add support for the vsc7512 chip via spi") Signed-off-by: Colin Foster Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230322141130.2531256-1-colin.foster@in-advantage.com --- drivers/mfd/ocelot-spi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/ocelot-spi.c b/drivers/mfd/ocelot-spi.c index 2ecd271de2fb..85021f94e587 100644 --- a/drivers/mfd/ocelot-spi.c +++ b/drivers/mfd/ocelot-spi.c @@ -130,6 +130,7 @@ static const struct regmap_config ocelot_spi_regmap_config = { .write_flag_mask = 0x80, + .use_single_read = true, .use_single_write = true, .can_multi_write = false, -- cgit v1.2.3 From 9896a19caf79f83692f13ab688d34c85ecfa92b2 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 22 Mar 2023 12:35:18 -0500 Subject: dt-bindings: mfd: Drop unneeded quotes in 'ref', 'id' and 'schema' entries Cleanup bindings dropping unneeded quotes. Once all these are fixed, checking for this can be enabled in yamllint. Signed-off-by: Rob Herring Reviewed-by: Damien Le Moal Reviewed-by: Krzysztof Kozlowski Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230322173519.3971434-1-robh@kernel.org --- .../bindings/mfd/canaan,k210-sysctl.yaml | 6 +++--- .../devicetree/bindings/mfd/google,cros-ec.yaml | 22 +++++++++++----------- .../bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml | 2 +- .../devicetree/bindings/mfd/qcom-pm8xxx.yaml | 2 +- .../devicetree/bindings/mfd/rohm,bd71815-pmic.yaml | 2 +- .../devicetree/bindings/mfd/rohm,bd71828-pmic.yaml | 2 +- .../devicetree/bindings/mfd/wlf,arizona.yaml | 2 +- .../devicetree/bindings/mfd/x-powers,ac100.yaml | 4 ++-- .../devicetree/bindings/mfd/xylon,logicvc.yaml | 4 ++-- 9 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/canaan,k210-sysctl.yaml b/Documentation/devicetree/bindings/mfd/canaan,k210-sysctl.yaml index e2046f07a40e..8459d3642205 100644 --- a/Documentation/devicetree/bindings/mfd/canaan,k210-sysctl.yaml +++ b/Documentation/devicetree/bindings/mfd/canaan,k210-sysctl.yaml @@ -36,7 +36,7 @@ properties: clock-controller: # Child node type: object - $ref: "../clock/canaan,k210-clk.yaml" + $ref: ../clock/canaan,k210-clk.yaml description: Clock controller for the SoC clocks. This child node definition should follow the bindings specified in @@ -45,7 +45,7 @@ properties: reset-controller: # Child node type: object - $ref: "../reset/canaan,k210-rst.yaml" + $ref: ../reset/canaan,k210-rst.yaml description: Reset controller for the SoC. This child node definition should follow the bindings specified in @@ -54,7 +54,7 @@ properties: syscon-reboot: # Child node type: object - $ref: "../power/reset/syscon-reboot.yaml" + $ref: ../power/reset/syscon-reboot.yaml description: Reboot method for the SoC. This child node definition should follow the bindings specified in diff --git a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml index cdf1d719efe9..456465e35114 100644 --- a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml +++ b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml @@ -65,7 +65,7 @@ properties: ARM Cortex M4 Co-processor. Contains the name of the rpmsg device. Used to match the subnode to the rpmsg device announced by the SCP. - $ref: "/schemas/types.yaml#/definitions/string" + $ref: /schemas/types.yaml#/definitions/string spi-max-frequency: true @@ -94,23 +94,23 @@ properties: const: 0 typec: - $ref: "/schemas/chrome/google,cros-ec-typec.yaml#" + $ref: /schemas/chrome/google,cros-ec-typec.yaml# ec-pwm: - $ref: "/schemas/pwm/google,cros-ec-pwm.yaml#" + $ref: /schemas/pwm/google,cros-ec-pwm.yaml# deprecated: true pwm: - $ref: "/schemas/pwm/google,cros-ec-pwm.yaml#" + $ref: /schemas/pwm/google,cros-ec-pwm.yaml# kbd-led-backlight: - $ref: "/schemas/chrome/google,cros-kbd-led-backlight.yaml#" + $ref: /schemas/chrome/google,cros-kbd-led-backlight.yaml# keyboard-controller: - $ref: "/schemas/input/google,cros-ec-keyb.yaml#" + $ref: /schemas/input/google,cros-ec-keyb.yaml# proximity: - $ref: "/schemas/iio/proximity/google,cros-ec-mkbp-proximity.yaml#" + $ref: /schemas/iio/proximity/google,cros-ec-mkbp-proximity.yaml# codecs: type: object @@ -126,7 +126,7 @@ properties: patternProperties: "^ec-codec@[a-f0-9]+$": type: object - $ref: "/schemas/sound/google,cros-ec-codec.yaml#" + $ref: /schemas/sound/google,cros-ec-codec.yaml# required: - "#address-cells" @@ -151,15 +151,15 @@ properties: patternProperties: "^i2c-tunnel[0-9]*$": type: object - $ref: "/schemas/i2c/google,cros-ec-i2c-tunnel.yaml#" + $ref: /schemas/i2c/google,cros-ec-i2c-tunnel.yaml# "^regulator@[0-9]+$": type: object - $ref: "/schemas/regulator/google,cros-ec-regulator.yaml#" + $ref: /schemas/regulator/google,cros-ec-regulator.yaml# "^extcon[0-9]*$": type: object - $ref: "/schemas/extcon/extcon-usbc-cros-ec.yaml#" + $ref: /schemas/extcon/extcon-usbc-cros-ec.yaml# required: - compatible diff --git a/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml index 22edcb4b212f..bdff5b653453 100644 --- a/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml +++ b/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml @@ -53,7 +53,7 @@ properties: '^ldo[0-9]+$': type: object - $ref: "/schemas/regulator/regulator.yaml#" + $ref: /schemas/regulator/regulator.yaml# unevaluatedProperties: false diff --git a/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.yaml b/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.yaml index 9acad9d326eb..9c51c1b19067 100644 --- a/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.yaml +++ b/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.yaml @@ -49,7 +49,7 @@ patternProperties: "rtc@[0-9a-f]+$": type: object - $ref: "../rtc/qcom-pm8xxx-rtc.yaml" + $ref: ../rtc/qcom-pm8xxx-rtc.yaml required: - compatible diff --git a/Documentation/devicetree/bindings/mfd/rohm,bd71815-pmic.yaml b/Documentation/devicetree/bindings/mfd/rohm,bd71815-pmic.yaml index d6d120a78094..05747e012516 100644 --- a/Documentation/devicetree/bindings/mfd/rohm,bd71815-pmic.yaml +++ b/Documentation/devicetree/bindings/mfd/rohm,bd71815-pmic.yaml @@ -46,7 +46,7 @@ properties: rohm,clkout-open-drain: description: clk32kout mode. Set to 1 for "open-drain" or 0 for "cmos". - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 1 diff --git a/Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.yaml b/Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.yaml index ec3adcd3483d..11089aa89ec6 100644 --- a/Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.yaml +++ b/Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.yaml @@ -46,7 +46,7 @@ properties: rohm,clkout-open-drain: description: clk32kout mode. Set to 1 for "open-drain" or 0 for "cmos". - $ref: "/schemas/types.yaml#/definitions/uint32" + $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 1 diff --git a/Documentation/devicetree/bindings/mfd/wlf,arizona.yaml b/Documentation/devicetree/bindings/mfd/wlf,arizona.yaml index ea3337dafaf5..7902f3c5d289 100644 --- a/Documentation/devicetree/bindings/mfd/wlf,arizona.yaml +++ b/Documentation/devicetree/bindings/mfd/wlf,arizona.yaml @@ -156,7 +156,7 @@ properties: entry has a value that is out of range for a 16 bit register then the chip default will be used. If present exactly five values must be specified. - $ref: "/schemas/types.yaml#/definitions/uint32-array" + $ref: /schemas/types.yaml#/definitions/uint32-array minItems: 1 maxItems: 5 diff --git a/Documentation/devicetree/bindings/mfd/x-powers,ac100.yaml b/Documentation/devicetree/bindings/mfd/x-powers,ac100.yaml index 309606d2d806..f3d8394b27e7 100644 --- a/Documentation/devicetree/bindings/mfd/x-powers,ac100.yaml +++ b/Documentation/devicetree/bindings/mfd/x-powers,ac100.yaml @@ -1,8 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 %YAML 1.2 --- -$id: "http://devicetree.org/schemas/mfd/x-powers,ac100.yaml#" -$schema: "http://devicetree.org/meta-schemas/core.yaml#" +$id: http://devicetree.org/schemas/mfd/x-powers,ac100.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# title: X-Powers AC100 diff --git a/Documentation/devicetree/bindings/mfd/xylon,logicvc.yaml b/Documentation/devicetree/bindings/mfd/xylon,logicvc.yaml index 9efd49c39bd2..6e880a46d7ee 100644 --- a/Documentation/devicetree/bindings/mfd/xylon,logicvc.yaml +++ b/Documentation/devicetree/bindings/mfd/xylon,logicvc.yaml @@ -2,8 +2,8 @@ # Copyright 2019 Bootlin %YAML 1.2 --- -$id: "http://devicetree.org/schemas/mfd/xylon,logicvc.yaml#" -$schema: "http://devicetree.org/meta-schemas/core.yaml#" +$id: http://devicetree.org/schemas/mfd/xylon,logicvc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# title: Xylon LogiCVC multi-function device -- cgit v1.2.3 From 972c91fd7beddc3f19c8c855f6e60e7dbd435cbd Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 23 Mar 2023 13:41:38 +0000 Subject: mfd: arizona-spi: Add missing MODULE_DEVICE_TABLE This patch adds missing MODULE_DEVICE_TABLE definition which generates correct modalias for automatic loading of this driver when it is built as a module. Fixes: 3f65555c417c ("mfd: arizona: Split of_match table into I2C and SPI versions") Signed-off-by: Charles Keepax Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230323134138.834369-1-ckeepax@opensource.cirrus.com --- drivers/mfd/arizona-spi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c index da05b966d48c..02cf4f3e91d7 100644 --- a/drivers/mfd/arizona-spi.c +++ b/drivers/mfd/arizona-spi.c @@ -277,6 +277,7 @@ static const struct of_device_id arizona_spi_of_match[] = { { .compatible = "cirrus,cs47l24", .data = (void *)CS47L24 }, {}, }; +MODULE_DEVICE_TABLE(of, arizona_spi_of_match); #endif static struct spi_driver arizona_spi_driver = { -- cgit v1.2.3 From fb9d4960a876e9344ab2c8a22c5c0fcd8c64210d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 20 Mar 2023 14:57:10 +0100 Subject: dt-bindings: mfd: qcom,spmi-pmic: Add nvram function Add an 'nvram' pattern property and a reference to the corresponding SDAM DT schema. Signed-off-by: Johan Hovold Acked-by: Rob Herring Reviewed-by: Krzysztof Kozlowski Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230320135710.1989-4-johan+linaro@kernel.org --- Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml index 0f7dd7ac9630..84620ebc1efe 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml +++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml @@ -138,6 +138,10 @@ patternProperties: type: object $ref: /schemas/pinctrl/qcom,pmic-gpio.yaml# + "^nvram@[0-9a-f]+$": + type: object + $ref: /schemas/nvmem/qcom,spmi-sdam.yaml# + "pon@[0-9a-f]+$": type: object $ref: /schemas/power/reset/qcom,pon.yaml# -- cgit v1.2.3 From 67d6c76fc815cddc77de9529221f9ff8dd1fb10e Mon Sep 17 00:00:00 2001 From: Min Li Date: Mon, 27 Mar 2023 14:39:53 -0400 Subject: mfd: rsmu: Support 32-bit address space We used to assume 0x2010xxxx address. Now that we need to access 0x2011xxxx address, we need to support read/write the whole 32-bit address space. Also defined RSMU_MAX_WRITE_COUNT and RSMU_MAX_READ_COUNT for readability Signed-off-by: Min Li Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/MW5PR03MB693295AF31ABCAF6AE52EE74A08B9@MW5PR03MB6932.namprd03.prod.outlook.com --- drivers/mfd/rsmu.h | 2 + drivers/mfd/rsmu_i2c.c | 171 +++++++++++++++++++++++++++++++++++++---------- drivers/mfd/rsmu_spi.c | 52 ++++++++------ include/linux/mfd/rsmu.h | 5 +- 4 files changed, 174 insertions(+), 56 deletions(-) diff --git a/drivers/mfd/rsmu.h b/drivers/mfd/rsmu.h index bb88597d189f..1bb04cafa45d 100644 --- a/drivers/mfd/rsmu.h +++ b/drivers/mfd/rsmu.h @@ -10,6 +10,8 @@ #include +#define RSMU_CM_SCSR_BASE 0x20100000 + int rsmu_core_init(struct rsmu_ddata *rsmu); void rsmu_core_exit(struct rsmu_ddata *rsmu); diff --git a/drivers/mfd/rsmu_i2c.c b/drivers/mfd/rsmu_i2c.c index 15d25b081434..221023faaadf 100644 --- a/drivers/mfd/rsmu_i2c.c +++ b/drivers/mfd/rsmu_i2c.c @@ -18,11 +18,12 @@ #include "rsmu.h" /* - * 16-bit register address: the lower 8 bits of the register address come - * from the offset addr byte and the upper 8 bits come from the page register. + * 32-bit register address: the lower 8 bits of the register address come + * from the offset addr byte and the upper 24 bits come from the page register. */ -#define RSMU_CM_PAGE_ADDR 0xFD -#define RSMU_CM_PAGE_WINDOW 256 +#define RSMU_CM_PAGE_ADDR 0xFC +#define RSMU_CM_PAGE_MASK 0xFFFFFF00 +#define RSMU_CM_ADDRESS_MASK 0x000000FF /* * 15-bit register address: the lower 7 bits of the register address come @@ -31,18 +32,6 @@ #define RSMU_SABRE_PAGE_ADDR 0x7F #define RSMU_SABRE_PAGE_WINDOW 128 -static const struct regmap_range_cfg rsmu_cm_range_cfg[] = { - { - .range_min = 0, - .range_max = 0xD000, - .selector_reg = RSMU_CM_PAGE_ADDR, - .selector_mask = 0xFF, - .selector_shift = 0, - .window_start = 0, - .window_len = RSMU_CM_PAGE_WINDOW, - } -}; - static const struct regmap_range_cfg rsmu_sabre_range_cfg[] = { { .range_min = 0, @@ -55,35 +44,141 @@ static const struct regmap_range_cfg rsmu_sabre_range_cfg[] = { } }; -static bool rsmu_cm_volatile_reg(struct device *dev, unsigned int reg) +static bool rsmu_sabre_volatile_reg(struct device *dev, unsigned int reg) { switch (reg) { - case RSMU_CM_PAGE_ADDR: + case RSMU_SABRE_PAGE_ADDR: return false; default: return true; } } -static bool rsmu_sabre_volatile_reg(struct device *dev, unsigned int reg) +static int rsmu_read_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u16 bytes) { - switch (reg) { - case RSMU_SABRE_PAGE_ADDR: - return false; - default: - return true; + struct i2c_client *client = to_i2c_client(rsmu->dev); + struct i2c_msg msg[2]; + int cnt; + + msg[0].addr = client->addr; + msg[0].flags = 0; + msg[0].len = 1; + msg[0].buf = ® + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].len = bytes; + msg[1].buf = buf; + + cnt = i2c_transfer(client->adapter, msg, 2); + + if (cnt < 0) { + dev_err(rsmu->dev, "i2c_transfer failed at addr: %04x!", reg); + return cnt; + } else if (cnt != 2) { + dev_err(rsmu->dev, + "i2c_transfer sent only %d of 2 messages", cnt); + return -EIO; + } + + return 0; +} + +static int rsmu_write_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u16 bytes) +{ + struct i2c_client *client = to_i2c_client(rsmu->dev); + u8 msg[RSMU_MAX_WRITE_COUNT + 1]; /* 1 Byte added for the device register */ + int cnt; + + if (bytes > RSMU_MAX_WRITE_COUNT) + return -EINVAL; + + msg[0] = reg; + memcpy(&msg[1], buf, bytes); + + cnt = i2c_master_send(client, msg, bytes + 1); + + if (cnt < 0) { + dev_err(&client->dev, + "i2c_master_send failed at addr: %04x!", reg); + return cnt; } + + return 0; +} + +static int rsmu_write_page_register(struct rsmu_ddata *rsmu, u32 reg) +{ + u32 page = reg & RSMU_CM_PAGE_MASK; + u8 buf[4]; + int err; + + /* Do not modify offset register for none-scsr registers */ + if (reg < RSMU_CM_SCSR_BASE) + return 0; + + /* Simply return if we are on the same page */ + if (rsmu->page == page) + return 0; + + buf[0] = 0x0; + buf[1] = (u8)((page >> 8) & 0xFF); + buf[2] = (u8)((page >> 16) & 0xFF); + buf[3] = (u8)((page >> 24) & 0xFF); + + err = rsmu_write_device(rsmu, RSMU_CM_PAGE_ADDR, buf, sizeof(buf)); + if (err) + dev_err(rsmu->dev, "Failed to set page offset 0x%x\n", page); + else + /* Remember the last page */ + rsmu->page = page; + + return err; +} + +static int rsmu_reg_read(void *context, unsigned int reg, unsigned int *val) +{ + struct rsmu_ddata *rsmu = i2c_get_clientdata((struct i2c_client *)context); + u8 addr = (u8)(reg & RSMU_CM_ADDRESS_MASK); + int err; + + err = rsmu_write_page_register(rsmu, reg); + if (err) + return err; + + err = rsmu_read_device(rsmu, addr, (u8 *)val, 1); + if (err) + dev_err(rsmu->dev, "Failed to read offset address 0x%x\n", addr); + + return err; +} + +static int rsmu_reg_write(void *context, unsigned int reg, unsigned int val) +{ + struct rsmu_ddata *rsmu = i2c_get_clientdata((struct i2c_client *)context); + u8 addr = (u8)(reg & RSMU_CM_ADDRESS_MASK); + u8 data = (u8)val; + int err; + + err = rsmu_write_page_register(rsmu, reg); + if (err) + return err; + + err = rsmu_write_device(rsmu, addr, &data, 1); + if (err) + dev_err(rsmu->dev, + "Failed to write offset address 0x%x\n", addr); + + return err; } static const struct regmap_config rsmu_cm_regmap_config = { - .reg_bits = 8, + .reg_bits = 32, .val_bits = 8, - .max_register = 0xD000, - .ranges = rsmu_cm_range_cfg, - .num_ranges = ARRAY_SIZE(rsmu_cm_range_cfg), - .volatile_reg = rsmu_cm_volatile_reg, - .cache_type = REGCACHE_RBTREE, - .can_multi_write = true, + .max_register = 0x20120000, + .reg_read = rsmu_reg_read, + .reg_write = rsmu_reg_write, + .cache_type = REGCACHE_NONE, }; static const struct regmap_config rsmu_sabre_regmap_config = { @@ -101,14 +196,14 @@ static const struct regmap_config rsmu_sl_regmap_config = { .reg_bits = 16, .val_bits = 8, .reg_format_endian = REGMAP_ENDIAN_BIG, - .max_register = 0x339, + .max_register = 0x340, .cache_type = REGCACHE_NONE, .can_multi_write = true, }; -static int rsmu_i2c_probe(struct i2c_client *client) +static int rsmu_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - const struct i2c_device_id *id = i2c_client_get_device_id(client); const struct regmap_config *cfg; struct rsmu_ddata *rsmu; int ret; @@ -136,7 +231,11 @@ static int rsmu_i2c_probe(struct i2c_client *client) dev_err(rsmu->dev, "Unsupported RSMU device type: %d\n", rsmu->type); return -ENODEV; } - rsmu->regmap = devm_regmap_init_i2c(client, cfg); + + if (rsmu->type == RSMU_CM) + rsmu->regmap = devm_regmap_init(&client->dev, NULL, client, cfg); + else + rsmu->regmap = devm_regmap_init_i2c(client, cfg); if (IS_ERR(rsmu->regmap)) { ret = PTR_ERR(rsmu->regmap); dev_err(rsmu->dev, "Failed to allocate register map: %d\n", ret); @@ -180,7 +279,7 @@ static struct i2c_driver rsmu_i2c_driver = { .name = "rsmu-i2c", .of_match_table = of_match_ptr(rsmu_i2c_of_match), }, - .probe_new = rsmu_i2c_probe, + .probe = rsmu_i2c_probe, .remove = rsmu_i2c_remove, .id_table = rsmu_i2c_id, }; diff --git a/drivers/mfd/rsmu_spi.c b/drivers/mfd/rsmu_spi.c index 2428aaa9aaed..a4a595bb8d0d 100644 --- a/drivers/mfd/rsmu_spi.c +++ b/drivers/mfd/rsmu_spi.c @@ -19,19 +19,21 @@ #define RSMU_CM_PAGE_ADDR 0x7C #define RSMU_SABRE_PAGE_ADDR 0x7F -#define RSMU_HIGHER_ADDR_MASK 0xFF80 -#define RSMU_HIGHER_ADDR_SHIFT 7 -#define RSMU_LOWER_ADDR_MASK 0x7F +#define RSMU_PAGE_MASK 0xFFFFFF80 +#define RSMU_ADDR_MASK 0x7F static int rsmu_read_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u16 bytes) { struct spi_device *client = to_spi_device(rsmu->dev); struct spi_transfer xfer = {0}; struct spi_message msg; - u8 cmd[256] = {0}; - u8 rsp[256] = {0}; + u8 cmd[RSMU_MAX_READ_COUNT + 1] = {0}; + u8 rsp[RSMU_MAX_READ_COUNT + 1] = {0}; int ret; + if (bytes > RSMU_MAX_READ_COUNT) + return -EINVAL; + cmd[0] = reg | 0x80; xfer.rx_buf = rsp; xfer.len = bytes + 1; @@ -66,7 +68,10 @@ static int rsmu_write_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u16 bytes struct spi_device *client = to_spi_device(rsmu->dev); struct spi_transfer xfer = {0}; struct spi_message msg; - u8 cmd[256] = {0}; + u8 cmd[RSMU_MAX_WRITE_COUNT + 1] = {0}; + + if (bytes > RSMU_MAX_WRITE_COUNT) + return -EINVAL; cmd[0] = reg; memcpy(&cmd[1], buf, bytes); @@ -86,26 +91,35 @@ static int rsmu_write_device(struct rsmu_ddata *rsmu, u8 reg, u8 *buf, u16 bytes * 16-bit register address: the lower 7 bits of the register address come * from the offset addr byte and the upper 9 bits come from the page register. */ -static int rsmu_write_page_register(struct rsmu_ddata *rsmu, u16 reg) +static int rsmu_write_page_register(struct rsmu_ddata *rsmu, u32 reg) { u8 page_reg; - u8 buf[2]; + u8 buf[4]; u16 bytes; - u16 page; + u32 page; int err; switch (rsmu->type) { case RSMU_CM: + /* Do not modify page register for none-scsr registers */ + if (reg < RSMU_CM_SCSR_BASE) + return 0; page_reg = RSMU_CM_PAGE_ADDR; - page = reg & RSMU_HIGHER_ADDR_MASK; + page = reg & RSMU_PAGE_MASK; buf[0] = (u8)(page & 0xff); buf[1] = (u8)((page >> 8) & 0xff); - bytes = 2; + buf[2] = (u8)((page >> 16) & 0xff); + buf[3] = (u8)((page >> 24) & 0xff); + bytes = 4; break; case RSMU_SABRE: + /* Do not modify page register if reg is page register itself */ + if ((reg & RSMU_ADDR_MASK) == RSMU_ADDR_MASK) + return 0; page_reg = RSMU_SABRE_PAGE_ADDR; - page = reg >> RSMU_HIGHER_ADDR_SHIFT; - buf[0] = (u8)(page & 0xff); + page = reg & RSMU_PAGE_MASK; + /* The three page bits are located in the single Page Register */ + buf[0] = (u8)((page >> 7) & 0x7); bytes = 1; break; default: @@ -129,8 +143,8 @@ static int rsmu_write_page_register(struct rsmu_ddata *rsmu, u16 reg) static int rsmu_reg_read(void *context, unsigned int reg, unsigned int *val) { - struct rsmu_ddata *rsmu = spi_get_drvdata(context); - u8 addr = (u8)(reg & RSMU_LOWER_ADDR_MASK); + struct rsmu_ddata *rsmu = spi_get_drvdata((struct spi_device *)context); + u8 addr = (u8)(reg & RSMU_ADDR_MASK); int err; err = rsmu_write_page_register(rsmu, reg); @@ -146,8 +160,8 @@ static int rsmu_reg_read(void *context, unsigned int reg, unsigned int *val) static int rsmu_reg_write(void *context, unsigned int reg, unsigned int val) { - struct rsmu_ddata *rsmu = spi_get_drvdata(context); - u8 addr = (u8)(reg & RSMU_LOWER_ADDR_MASK); + struct rsmu_ddata *rsmu = spi_get_drvdata((struct spi_device *)context); + u8 addr = (u8)(reg & RSMU_ADDR_MASK); u8 data = (u8)val; int err; @@ -164,9 +178,9 @@ static int rsmu_reg_write(void *context, unsigned int reg, unsigned int val) } static const struct regmap_config rsmu_cm_regmap_config = { - .reg_bits = 16, + .reg_bits = 32, .val_bits = 8, - .max_register = 0xD000, + .max_register = 0x20120000, .reg_read = rsmu_reg_read, .reg_write = rsmu_reg_write, .cache_type = REGCACHE_NONE, diff --git a/include/linux/mfd/rsmu.h b/include/linux/mfd/rsmu.h index 6870de608233..0379aa207428 100644 --- a/include/linux/mfd/rsmu.h +++ b/include/linux/mfd/rsmu.h @@ -8,6 +8,9 @@ #ifndef __LINUX_MFD_RSMU_H #define __LINUX_MFD_RSMU_H +#define RSMU_MAX_WRITE_COUNT (255) +#define RSMU_MAX_READ_COUNT (255) + /* The supported devices are ClockMatrix, Sabre and SnowLotus */ enum rsmu_type { RSMU_CM = 0x34000, @@ -31,6 +34,6 @@ struct rsmu_ddata { struct regmap *regmap; struct mutex lock; enum rsmu_type type; - u16 page; + u32 page; }; #endif /* __LINUX_MFD_RSMU_H */ -- cgit v1.2.3 From 66c8d55966fd169a36fa2ca6e80517080492e87f Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 25 Mar 2023 12:43:53 +0100 Subject: dt-bindings: mfd: x-powers,axp152: Simplify disallowing properties The syntax to disallow x-powers,drive-vbus-en, x-powers,self-working-mode and x-powers,master-mode for certain variants can be made simpler. Also this produces much nicer warning message when the condition hits wrong DTS. Signed-off-by: Krzysztof Kozlowski Acked-by: Chen-Yu Tsai Reviewed-by: Andre Przywara Tested-by: Andre Przywara Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230325114353.50293-1-krzysztof.kozlowski@linaro.org --- .../devicetree/bindings/mfd/x-powers,axp152.yaml | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml b/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml index b7a8747d5fa0..2691ac08f536 100644 --- a/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml +++ b/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml @@ -47,9 +47,8 @@ allOf: - x-powers,axp209 then: - not: - required: - - x-powers,drive-vbus-en + properties: + x-powers,drive-vbus-en: false - if: not: @@ -59,14 +58,9 @@ allOf: const: x-powers,axp806 then: - allOf: - - not: - required: - - x-powers,self-working-mode - - - not: - required: - - x-powers,master-mode + properties: + x-powers,self-working-mode: false + x-powers,master-mode: false - if: not: -- cgit v1.2.3 From 2405fbfb384ef39e9560d76d3f6e4c90519f90aa Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 29 Mar 2023 22:55:44 +0200 Subject: mfd: axp20x: Fix axp288 writable-ranges Register AXP288_POWER_REASON is writable and needs to be written to reset the reset- / power-on-reason bits. Add it to the axp288 writable-ranges so that the extcon-axp288 driver can properly clear the reset- / power-on-reason bits. Signed-off-by: Hans de Goede Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230329205544.1051393-1-hdegoede@redhat.com --- drivers/mfd/axp20x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index 01a6bbb6d266..7720ac15c7d4 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -119,6 +119,7 @@ static const struct regmap_access_table axp22x_volatile_table = { /* AXP288 ranges are shared with the AXP803, as they cover the same range */ static const struct regmap_range axp288_writeable_ranges[] = { + regmap_reg_range(AXP288_POWER_REASON, AXP288_POWER_REASON), regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ6_STATE), regmap_reg_range(AXP20X_DCDC_MODE, AXP288_FG_TUNE5), }; -- cgit v1.2.3 From 96da8f148396329ba769246cb8ceaa35f1ddfc48 Mon Sep 17 00:00:00 2001 From: Qiang Ning Date: Thu, 30 Mar 2023 10:43:53 +0800 Subject: mfd: dln2: Fix memory leak in dln2_probe() When dln2_setup_rx_urbs() in dln2_probe() fails, error out_free forgets to call usb_put_dev() to decrease the refcount of dln2->usb_dev. Fix this by adding usb_put_dev() in the error handling code of dln2_probe(). Signed-off-by: Qiang Ning Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230330024353.4503-1-qning0106@126.com --- drivers/mfd/dln2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c index 6cd0b0c752d6..c3149729cec2 100644 --- a/drivers/mfd/dln2.c +++ b/drivers/mfd/dln2.c @@ -827,6 +827,7 @@ out_stop_rx: dln2_stop_rx_urbs(dln2); out_free: + usb_put_dev(dln2->usb_dev); dln2_free(dln2); return ret; -- cgit v1.2.3 From 72d4a1683741ee578da0e265886e6a7f3d42266c Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Thu, 30 Mar 2023 16:26:18 +0300 Subject: mfd: intel-lpss: Add Intel Meteor Lake PCH-S LPSS PCI IDs Add Intel Meteor Lake PCH-S also called as Meteor Point-S LPSS PCI IDs. Signed-off-by: Jarkko Nikula Acked-by: Andy Shevchenko Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230330132618.4108665-1-jarkko.nikula@linux.intel.com --- drivers/mfd/intel-lpss-pci.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c index dde31c50a632..699f44ffff0e 100644 --- a/drivers/mfd/intel-lpss-pci.c +++ b/drivers/mfd/intel-lpss-pci.c @@ -447,6 +447,21 @@ static const struct pci_device_id intel_lpss_pci_ids[] = { { PCI_VDEVICE(INTEL, 0x7e79), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x7e7a), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x7e7b), (kernel_ulong_t)&bxt_i2c_info }, + /* MTP-S */ + { PCI_VDEVICE(INTEL, 0x7f28), (kernel_ulong_t)&bxt_uart_info }, + { PCI_VDEVICE(INTEL, 0x7f29), (kernel_ulong_t)&bxt_uart_info }, + { PCI_VDEVICE(INTEL, 0x7f2a), (kernel_ulong_t)&tgl_info }, + { PCI_VDEVICE(INTEL, 0x7f2b), (kernel_ulong_t)&tgl_info }, + { PCI_VDEVICE(INTEL, 0x7f4c), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x7f4d), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x7f4e), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x7f4f), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x7f5c), (kernel_ulong_t)&bxt_uart_info }, + { PCI_VDEVICE(INTEL, 0x7f5d), (kernel_ulong_t)&bxt_uart_info }, + { PCI_VDEVICE(INTEL, 0x7f5e), (kernel_ulong_t)&tgl_info }, + { PCI_VDEVICE(INTEL, 0x7f5f), (kernel_ulong_t)&tgl_info }, + { PCI_VDEVICE(INTEL, 0x7f7a), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x7f7b), (kernel_ulong_t)&bxt_i2c_info }, /* LKF */ { PCI_VDEVICE(INTEL, 0x98a8), (kernel_ulong_t)&bxt_uart_info }, { PCI_VDEVICE(INTEL, 0x98a9), (kernel_ulong_t)&bxt_uart_info }, -- cgit v1.2.3 From a29f5a3eeb81717245d28f9fc212229f5407c8d5 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 31 Mar 2023 09:03:44 +0200 Subject: mfd: rsmu_i2c: Convert to i2c's .probe_new() again MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit reapplies commit 601e6d48ee35 ("mfd: rsmu_i2c: Convert to i2c's .probe_new()") which was accidently reverted by commit 1b3b1d6c27cc ("mfd: rsmu: Support 32-bit address space"). Without this change the driver fails to build in combination with commit 03c835f498b5 ("i2c: Switch .probe() to not take an id parameter") which is contained in v6.3-rc2. Fixes: 1b3b1d6c27cc ("mfd: rsmu: Support 32-bit address space") Signed-off-by: Uwe Kleine-König Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230331070344.czphnnmvu2ojzo5l@pengutronix.de --- drivers/mfd/rsmu_i2c.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mfd/rsmu_i2c.c b/drivers/mfd/rsmu_i2c.c index 221023faaadf..807c32101460 100644 --- a/drivers/mfd/rsmu_i2c.c +++ b/drivers/mfd/rsmu_i2c.c @@ -201,9 +201,9 @@ static const struct regmap_config rsmu_sl_regmap_config = { .can_multi_write = true, }; -static int rsmu_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int rsmu_i2c_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); const struct regmap_config *cfg; struct rsmu_ddata *rsmu; int ret; @@ -279,7 +279,7 @@ static struct i2c_driver rsmu_i2c_driver = { .name = "rsmu-i2c", .of_match_table = of_match_ptr(rsmu_i2c_of_match), }, - .probe = rsmu_i2c_probe, + .probe_new = rsmu_i2c_probe, .remove = rsmu_i2c_remove, .id_table = rsmu_i2c_id, }; -- cgit v1.2.3 From 0a9d6b54297e216199cbfd08c5e6a35cce152477 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Thu, 30 Mar 2023 12:16:27 +0100 Subject: dt-bindings: timer: Document RZ/G2L MTU3a bindings The RZ/G2L multi-function timer pulse unit 3 (MTU3a) is embedded in the Renesas RZ/G2L family SoC's. It consists of eight 16-bit timer channels and one 32-bit timer channel. It supports the following functions - Counter - Timer - PWM Signed-off-by: Biju Das Reviewed-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230330111632.169434-2-biju.das.jz@bp.renesas.com --- .../devicetree/bindings/timer/renesas,rz-mtu3.yaml | 302 +++++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100644 Documentation/devicetree/bindings/timer/renesas,rz-mtu3.yaml diff --git a/Documentation/devicetree/bindings/timer/renesas,rz-mtu3.yaml b/Documentation/devicetree/bindings/timer/renesas,rz-mtu3.yaml new file mode 100644 index 000000000000..bffdab0b0185 --- /dev/null +++ b/Documentation/devicetree/bindings/timer/renesas,rz-mtu3.yaml @@ -0,0 +1,302 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/timer/renesas,rz-mtu3.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas RZ/G2L Multi-Function Timer Pulse Unit 3 (MTU3a) + +maintainers: + - Biju Das + +description: | + This hardware block consists of eight 16-bit timer channels and one + 32- bit timer channel. It supports the following specifications: + - Pulse input/output: 28 lines max. + - Pulse input 3 lines + - Count clock 11 clocks for each channel (14 clocks for MTU0, 12 clocks + for MTU2, and 10 clocks for MTU5, four clocks for MTU1-MTU2 combination + (when LWA = 1)) + - Operating frequency Up to 100 MHz + - Available operations [MTU0 to MTU4, MTU6, MTU7, and MTU8] + - Waveform output on compare match + - Input capture function (noise filter setting available) + - Counter-clearing operation + - Simultaneous writing to multiple timer counters (TCNT) + (excluding MTU8). + - Simultaneous clearing on compare match or input capture + (excluding MTU8). + - Simultaneous input and output to registers in synchronization with + counter operations (excluding MTU8). + - Up to 12-phase PWM output in combination with synchronous operation + (excluding MTU8) + - [MTU0 MTU3, MTU4, MTU6, MTU7, and MTU8] + - Buffer operation specifiable + - [MTU1, MTU2] + - Phase counting mode can be specified independently + - 32-bit phase counting mode can be specified for interlocked operation + of MTU1 and MTU2 (when TMDR3.LWA = 1) + - Cascade connection operation available + - [MTU3, MTU4, MTU6, and MTU7] + - Through interlocked operation of MTU3/4 and MTU6/7, the positive and + negative signals in six phases (12 phases in total) can be output in + complementary PWM and reset-synchronized PWM operation. + - In complementary PWM mode, values can be transferred from buffer + registers to temporary registers at crests and troughs of the timer- + counter values or when the buffer registers (TGRD registers in MTU4 + and MTU7) are written to. + - Double-buffering selectable in complementary PWM mode. + - [MTU3 and MTU4] + - Through interlocking with MTU0, a mode for driving AC synchronous + motors (brushless DC motors) by using complementary PWM output and + reset-synchronized PWM output is settable and allows the selection + of two types of waveform output (chopping or level). + - [MTU5] + - Capable of operation as a dead-time compensation counter. + - [MTU0/MTU5, MTU1, MTU2, and MTU8] + - 32-bit phase counting mode specifiable by combining MTU1 and MTU2 and + through interlocked operation with MTU0/MTU5 and MTU8. + - Interrupt-skipping function + - In complementary PWM mode, interrupts on crests and troughs of counter + values and triggers to start conversion by the A/D converter can be + skipped. + - Interrupt sources: 43 sources. + - Buffer operation: + - Automatic transfer of register data (transfer from the buffer + register to the timer register). + - Trigger generation + - A/D converter start triggers can be generated + - A/D converter start request delaying function enables A/D converter + to be started with any desired timing and to be synchronized with + PWM output. + - Low power consumption function + - The MTU3a can be placed in the module-stop state. + + There are two phase counting modes. 16-bit phase counting mode in which + MTU1 and MTU2 operate independently, and cascade connection 32-bit phase + counting mode in which MTU1 and MTU2 are cascaded. + + In phase counting mode, the phase difference between two external input + clocks is detected and the corresponding TCNT is incremented or + decremented. + The below counters are supported + count0 - MTU1 16-bit phase counting + count1 - MTU2 16-bit phase counting + count2 - MTU1+ MTU2 32-bit phase counting + + The module supports PWM mode{1,2}, Reset-synchronized PWM mode and + complementary PWM mode{1,2,3}. + + In complementary PWM mode, six positive-phase and six negative-phase PWM + waveforms (12 phases in total) with dead time can be output by + combining MTU{3,4} and MTU{6,7}. + + The below pwm channels are supported in pwm mode 1. + pwm0 - MTU0.MTIOC0A PWM mode 1 + pwm1 - MTU0.MTIOC0C PWM mode 1 + pwm2 - MTU1.MTIOC1A PWM mode 1 + pwm3 - MTU2.MTIOC2A PWM mode 1 + pwm4 - MTU3.MTIOC3A PWM mode 1 + pwm5 - MTU3.MTIOC3C PWM mode 1 + pwm6 - MTU4.MTIOC4A PWM mode 1 + pwm7 - MTU4.MTIOC4C PWM mode 1 + pwm8 - MTU6.MTIOC6A PWM mode 1 + pwm9 - MTU6.MTIOC6C PWM mode 1 + pwm10 - MTU7.MTIOC7A PWM mode 1 + pwm11 - MTU7.MTIOC7C PWM mode 1 + +properties: + compatible: + items: + - enum: + - renesas,r9a07g044-mtu3 # RZ/G2{L,LC} + - renesas,r9a07g054-mtu3 # RZ/V2L + - const: renesas,rz-mtu3 + + reg: + maxItems: 1 + + interrupts: + items: + - description: MTU0.TGRA input capture/compare match + - description: MTU0.TGRB input capture/compare match + - description: MTU0.TGRC input capture/compare match + - description: MTU0.TGRD input capture/compare match + - description: MTU0.TCNT overflow + - description: MTU0.TGRE compare match + - description: MTU0.TGRF compare match + - description: MTU1.TGRA input capture/compare match + - description: MTU1.TGRB input capture/compare match + - description: MTU1.TCNT overflow + - description: MTU1.TCNT underflow + - description: MTU2.TGRA input capture/compare match + - description: MTU2.TGRB input capture/compare match + - description: MTU2.TCNT overflow + - description: MTU2.TCNT underflow + - description: MTU3.TGRA input capture/compare match + - description: MTU3.TGRB input capture/compare match + - description: MTU3.TGRC input capture/compare match + - description: MTU3.TGRD input capture/compare match + - description: MTU3.TCNT overflow + - description: MTU4.TGRA input capture/compare match + - description: MTU4.TGRB input capture/compare match + - description: MTU4.TGRC input capture/compare match + - description: MTU4.TGRD input capture/compare match + - description: MTU4.TCNT overflow/underflow + - description: MTU5.TGRU input capture/compare match + - description: MTU5.TGRV input capture/compare match + - description: MTU5.TGRW input capture/compare match + - description: MTU6.TGRA input capture/compare match + - description: MTU6.TGRB input capture/compare match + - description: MTU6.TGRC input capture/compare match + - description: MTU6.TGRD input capture/compare match + - description: MTU6.TCNT overflow + - description: MTU7.TGRA input capture/compare match + - description: MTU7.TGRB input capture/compare match + - description: MTU7.TGRC input capture/compare match + - description: MTU7.TGRD input capture/compare match + - description: MTU7.TCNT overflow/underflow + - description: MTU8.TGRA input capture/compare match + - description: MTU8.TGRB input capture/compare match + - description: MTU8.TGRC input capture/compare match + - description: MTU8.TGRD input capture/compare match + - description: MTU8.TCNT overflow + - description: MTU8.TCNT underflow + + interrupt-names: + items: + - const: tgia0 + - const: tgib0 + - const: tgic0 + - const: tgid0 + - const: tgiv0 + - const: tgie0 + - const: tgif0 + - const: tgia1 + - const: tgib1 + - const: tgiv1 + - const: tgiu1 + - const: tgia2 + - const: tgib2 + - const: tgiv2 + - const: tgiu2 + - const: tgia3 + - const: tgib3 + - const: tgic3 + - const: tgid3 + - const: tgiv3 + - const: tgia4 + - const: tgib4 + - const: tgic4 + - const: tgid4 + - const: tgiv4 + - const: tgiu5 + - const: tgiv5 + - const: tgiw5 + - const: tgia6 + - const: tgib6 + - const: tgic6 + - const: tgid6 + - const: tgiv6 + - const: tgia7 + - const: tgib7 + - const: tgic7 + - const: tgid7 + - const: tgiv7 + - const: tgia8 + - const: tgib8 + - const: tgic8 + - const: tgid8 + - const: tgiv8 + - const: tgiu8 + + clocks: + maxItems: 1 + + power-domains: + maxItems: 1 + + resets: + maxItems: 1 + + "#pwm-cells": + const: 2 + +required: + - compatible + - reg + - interrupts + - interrupt-names + - clocks + - power-domains + - resets + +additionalProperties: false + +examples: + - | + #include + #include + + mtu3: timer@10001200 { + compatible = "renesas,r9a07g044-mtu3", "renesas,rz-mtu3"; + reg = <0x10001200 0xb00>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + interrupt-names = "tgia0", "tgib0", "tgic0", "tgid0", "tgiv0", "tgie0", + "tgif0", + "tgia1", "tgib1", "tgiv1", "tgiu1", + "tgia2", "tgib2", "tgiv2", "tgiu2", + "tgia3", "tgib3", "tgic3", "tgid3", "tgiv3", + "tgia4", "tgib4", "tgic4", "tgid4", "tgiv4", + "tgiu5", "tgiv5", "tgiw5", + "tgia6", "tgib6", "tgic6", "tgid6", "tgiv6", + "tgia7", "tgib7", "tgic7", "tgid7", "tgiv7", + "tgia8", "tgib8", "tgic8", "tgid8", "tgiv8", "tgiu8"; + clocks = <&cpg CPG_MOD R9A07G044_MTU_X_MCK_MTU3>; + power-domains = <&cpg>; + resets = <&cpg R9A07G044_MTU_X_PRESET_MTU3>; + #pwm-cells = <2>; + }; -- cgit v1.2.3 From 654c293e1687b31819f9bf1ac71b5a85a8053210 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Thu, 30 Mar 2023 12:16:28 +0100 Subject: mfd: Add Renesas RZ/G2L MTU3a core driver The RZ/G2L multi-function timer pulse unit 3 (MTU3a) is embedded in the Renesas RZ/G2L family SoCs. It consists of eight 16-bit timer channels and one 32-bit timer channel. It supports the following functions - Counter - Timer - PWM The 8/16/32 bit registers are mixed in each channel. Add MTU3a core driver for RZ/G2L SoC. The core driver shares the clk and channel register access for the other child devices like Counter, PWM and Clock event. Signed-off-by: Biju Das Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230330111632.169434-3-biju.das.jz@bp.renesas.com --- drivers/mfd/Kconfig | 10 ++ drivers/mfd/Makefile | 1 + drivers/mfd/rz-mtu3.c | 391 ++++++++++++++++++++++++++++++++++++++++++++ drivers/mfd/rz-mtu3.h | 147 +++++++++++++++++ include/linux/mfd/rz-mtu3.h | 257 +++++++++++++++++++++++++++++ 5 files changed, 806 insertions(+) create mode 100644 drivers/mfd/rz-mtu3.c create mode 100644 drivers/mfd/rz-mtu3.h create mode 100644 include/linux/mfd/rz-mtu3.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 51d54a1b8673..e90463c4441c 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1315,6 +1315,16 @@ config MFD_SC27XX_PMIC This driver provides common support for accessing the SC27xx PMICs, and it also adds the irq_chip parts for handling the PMIC chip events. +config RZ_MTU3 + bool "Renesas RZ/G2L MTU3a core driver" + depends on (ARCH_RZG2L && OF) || COMPILE_TEST + help + Select this option to enable Renesas RZ/G2L MTU3a core driver for + the Multi-Function Timer Pulse Unit 3 (MTU3a) hardware available + on SoCs from Renesas. The core driver shares the clk and channel + register access for the other child devices like Counter, PWM, + Clock Source, and Clock event. + config ABX500_CORE bool "ST-Ericsson ABX500 Mixed Signal Circuit register functions" depends on ARCH_U8500 || COMPILE_TEST diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 2f6c89d1e277..1d2392f06f78 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -174,6 +174,7 @@ pcf50633-objs := pcf50633-core.o pcf50633-irq.o obj-$(CONFIG_MFD_PCF50633) += pcf50633.o obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o +obj-$(CONFIG_RZ_MTU3) += rz-mtu3.o obj-$(CONFIG_ABX500_CORE) += abx500-core.o obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o # ab8500-core need to come after db8500-prcmu (which provides the channel) diff --git a/drivers/mfd/rz-mtu3.c b/drivers/mfd/rz-mtu3.c new file mode 100644 index 000000000000..04006f4aa702 --- /dev/null +++ b/drivers/mfd/rz-mtu3.c @@ -0,0 +1,391 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Renesas RZ/G2L Multi-Function Timer Pulse Unit 3(MTU3a) Core driver + * + * Copyright (C) 2023 Renesas Electronics Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rz-mtu3.h" + +struct rz_mtu3_priv { + void __iomem *mmio; + struct reset_control *rstc; + raw_spinlock_t lock; +}; + +/******* MTU3 registers (original offset is +0x1200) *******/ +static const unsigned long rz_mtu3_8bit_ch_reg_offs[][13] = { + [RZ_MTU3_CHAN_0] = MTU_8BIT_CH_0(0x104, 0x090, 0x100, 0x128, 0x101, 0x102, 0x103, 0x126), + [RZ_MTU3_CHAN_1] = MTU_8BIT_CH_1_2(0x184, 0x091, 0x185, 0x180, 0x194, 0x181, 0x182), + [RZ_MTU3_CHAN_2] = MTU_8BIT_CH_1_2(0x204, 0x092, 0x205, 0x200, 0x20c, 0x201, 0x202), + [RZ_MTU3_CHAN_3] = MTU_8BIT_CH_3_4_6_7(0x008, 0x093, 0x02c, 0x000, 0x04c, 0x002, 0x004, 0x005, 0x038), + [RZ_MTU3_CHAN_4] = MTU_8BIT_CH_3_4_6_7(0x009, 0x094, 0x02d, 0x001, 0x04d, 0x003, 0x006, 0x007, 0x039), + [RZ_MTU3_CHAN_5] = MTU_8BIT_CH_5(0xab2, 0x1eb, 0xab4, 0xab6, 0xa84, 0xa85, 0xa86, 0xa94, 0xa95, 0xa96, 0xaa4, 0xaa5, 0xaa6), + [RZ_MTU3_CHAN_6] = MTU_8BIT_CH_3_4_6_7(0x808, 0x893, 0x82c, 0x800, 0x84c, 0x802, 0x804, 0x805, 0x838), + [RZ_MTU3_CHAN_7] = MTU_8BIT_CH_3_4_6_7(0x809, 0x894, 0x82d, 0x801, 0x84d, 0x803, 0x806, 0x807, 0x839), + [RZ_MTU3_CHAN_8] = MTU_8BIT_CH_8(0x404, 0x098, 0x400, 0x406, 0x401, 0x402, 0x403) +}; + +static const unsigned long rz_mtu3_16bit_ch_reg_offs[][12] = { + [RZ_MTU3_CHAN_0] = MTU_16BIT_CH_0(0x106, 0x108, 0x10a, 0x10c, 0x10e, 0x120, 0x122), + [RZ_MTU3_CHAN_1] = MTU_16BIT_CH_1_2(0x186, 0x188, 0x18a), + [RZ_MTU3_CHAN_2] = MTU_16BIT_CH_1_2(0x206, 0x208, 0x20a), + [RZ_MTU3_CHAN_3] = MTU_16BIT_CH_3_6(0x010, 0x018, 0x01a, 0x024, 0x026, 0x072), + [RZ_MTU3_CHAN_4] = MTU_16BIT_CH_4_7(0x012, 0x01c, 0x01e, 0x028, 0x2a, 0x074, 0x076, 0x040, 0x044, 0x046, 0x048, 0x04a), + [RZ_MTU3_CHAN_5] = MTU_16BIT_CH_5(0xa80, 0xa82, 0xa90, 0xa92, 0xaa0, 0xaa2), + [RZ_MTU3_CHAN_6] = MTU_16BIT_CH_3_6(0x810, 0x818, 0x81a, 0x824, 0x826, 0x872), + [RZ_MTU3_CHAN_7] = MTU_16BIT_CH_4_7(0x812, 0x81c, 0x81e, 0x828, 0x82a, 0x874, 0x876, 0x840, 0x844, 0x846, 0x848, 0x84a) +}; + +static const unsigned long rz_mtu3_32bit_ch_reg_offs[][5] = { + [RZ_MTU3_CHAN_1] = MTU_32BIT_CH_1(0x1a0, 0x1a4, 0x1a8), + [RZ_MTU3_CHAN_8] = MTU_32BIT_CH_8(0x408, 0x40c, 0x410, 0x414, 0x418) +}; + +static bool rz_mtu3_is_16bit_shared_reg(u16 offset) +{ + return (offset == RZ_MTU3_TDDRA || offset == RZ_MTU3_TDDRB || + offset == RZ_MTU3_TCDRA || offset == RZ_MTU3_TCDRB || + offset == RZ_MTU3_TCBRA || offset == RZ_MTU3_TCBRB || + offset == RZ_MTU3_TCNTSA || offset == RZ_MTU3_TCNTSB); +} + +u16 rz_mtu3_shared_reg_read(struct rz_mtu3_channel *ch, u16 offset) +{ + struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent); + struct rz_mtu3_priv *priv = mtu->priv_data; + + if (rz_mtu3_is_16bit_shared_reg(offset)) + return readw(priv->mmio + offset); + else + return readb(priv->mmio + offset); +} +EXPORT_SYMBOL_GPL(rz_mtu3_shared_reg_read); + +u8 rz_mtu3_8bit_ch_read(struct rz_mtu3_channel *ch, u16 offset) +{ + struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent); + struct rz_mtu3_priv *priv = mtu->priv_data; + u16 ch_offs; + + ch_offs = rz_mtu3_8bit_ch_reg_offs[ch->channel_number][offset]; + + return readb(priv->mmio + ch_offs); +} +EXPORT_SYMBOL_GPL(rz_mtu3_8bit_ch_read); + +u16 rz_mtu3_16bit_ch_read(struct rz_mtu3_channel *ch, u16 offset) +{ + struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent); + struct rz_mtu3_priv *priv = mtu->priv_data; + u16 ch_offs; + + /* MTU8 doesn't have 16-bit registers */ + if (ch->channel_number == RZ_MTU3_CHAN_8) + return 0; + + ch_offs = rz_mtu3_16bit_ch_reg_offs[ch->channel_number][offset]; + + return readw(priv->mmio + ch_offs); +} +EXPORT_SYMBOL_GPL(rz_mtu3_16bit_ch_read); + +u32 rz_mtu3_32bit_ch_read(struct rz_mtu3_channel *ch, u16 offset) +{ + struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent); + struct rz_mtu3_priv *priv = mtu->priv_data; + u16 ch_offs; + + if (ch->channel_number != RZ_MTU3_CHAN_1 && ch->channel_number != RZ_MTU3_CHAN_8) + return 0; + + ch_offs = rz_mtu3_32bit_ch_reg_offs[ch->channel_number][offset]; + + return readl(priv->mmio + ch_offs); +} +EXPORT_SYMBOL_GPL(rz_mtu3_32bit_ch_read); + +void rz_mtu3_8bit_ch_write(struct rz_mtu3_channel *ch, u16 offset, u8 val) +{ + struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent); + struct rz_mtu3_priv *priv = mtu->priv_data; + u16 ch_offs; + + ch_offs = rz_mtu3_8bit_ch_reg_offs[ch->channel_number][offset]; + writeb(val, priv->mmio + ch_offs); +} +EXPORT_SYMBOL_GPL(rz_mtu3_8bit_ch_write); + +void rz_mtu3_16bit_ch_write(struct rz_mtu3_channel *ch, u16 offset, u16 val) +{ + struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent); + struct rz_mtu3_priv *priv = mtu->priv_data; + u16 ch_offs; + + /* MTU8 doesn't have 16-bit registers */ + if (ch->channel_number == RZ_MTU3_CHAN_8) + return; + + ch_offs = rz_mtu3_16bit_ch_reg_offs[ch->channel_number][offset]; + writew(val, priv->mmio + ch_offs); +} +EXPORT_SYMBOL_GPL(rz_mtu3_16bit_ch_write); + +void rz_mtu3_32bit_ch_write(struct rz_mtu3_channel *ch, u16 offset, u32 val) +{ + struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent); + struct rz_mtu3_priv *priv = mtu->priv_data; + u16 ch_offs; + + if (ch->channel_number != RZ_MTU3_CHAN_1 && ch->channel_number != RZ_MTU3_CHAN_8) + return; + + ch_offs = rz_mtu3_32bit_ch_reg_offs[ch->channel_number][offset]; + writel(val, priv->mmio + ch_offs); +} +EXPORT_SYMBOL_GPL(rz_mtu3_32bit_ch_write); + +void rz_mtu3_shared_reg_write(struct rz_mtu3_channel *ch, u16 offset, u16 value) +{ + struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent); + struct rz_mtu3_priv *priv = mtu->priv_data; + + if (rz_mtu3_is_16bit_shared_reg(offset)) + writew(value, priv->mmio + offset); + else + writeb((u8)value, priv->mmio + offset); +} +EXPORT_SYMBOL_GPL(rz_mtu3_shared_reg_write); + +void rz_mtu3_shared_reg_update_bit(struct rz_mtu3_channel *ch, u16 offset, + u16 pos, u8 val) +{ + struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent); + struct rz_mtu3_priv *priv = mtu->priv_data; + unsigned long tmdr, flags; + + raw_spin_lock_irqsave(&priv->lock, flags); + tmdr = rz_mtu3_shared_reg_read(ch, offset); + __assign_bit(pos, &tmdr, !!val); + rz_mtu3_shared_reg_write(ch, offset, tmdr); + raw_spin_unlock_irqrestore(&priv->lock, flags); +} +EXPORT_SYMBOL_GPL(rz_mtu3_shared_reg_update_bit); + +static u16 rz_mtu3_get_tstr_offset(struct rz_mtu3_channel *ch) +{ + u16 offset; + + switch (ch->channel_number) { + case RZ_MTU3_CHAN_0: + case RZ_MTU3_CHAN_1: + case RZ_MTU3_CHAN_2: + case RZ_MTU3_CHAN_3: + case RZ_MTU3_CHAN_4: + case RZ_MTU3_CHAN_8: + offset = RZ_MTU3_TSTRA; + break; + case RZ_MTU3_CHAN_5: + offset = RZ_MTU3_TSTR; + break; + case RZ_MTU3_CHAN_6: + case RZ_MTU3_CHAN_7: + offset = RZ_MTU3_TSTRB; + break; + default: + offset = 0; + break; + } + + return offset; +} + +static u8 rz_mtu3_get_tstr_bit_pos(struct rz_mtu3_channel *ch) +{ + u8 bitpos; + + switch (ch->channel_number) { + case RZ_MTU3_CHAN_0: + case RZ_MTU3_CHAN_1: + case RZ_MTU3_CHAN_2: + case RZ_MTU3_CHAN_6: + case RZ_MTU3_CHAN_7: + bitpos = ch->channel_number; + break; + case RZ_MTU3_CHAN_3: + bitpos = 6; + break; + case RZ_MTU3_CHAN_4: + bitpos = 7; + break; + case RZ_MTU3_CHAN_5: + bitpos = 2; + break; + case RZ_MTU3_CHAN_8: + bitpos = 3; + break; + default: + bitpos = 0; + break; + } + + return bitpos; +} + +static void rz_mtu3_start_stop_ch(struct rz_mtu3_channel *ch, bool start) +{ + struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent); + struct rz_mtu3_priv *priv = mtu->priv_data; + unsigned long flags, tstr; + u16 offset; + u8 bitpos; + + /* start stop register shared by multiple timer channels */ + raw_spin_lock_irqsave(&priv->lock, flags); + + offset = rz_mtu3_get_tstr_offset(ch); + bitpos = rz_mtu3_get_tstr_bit_pos(ch); + tstr = rz_mtu3_shared_reg_read(ch, offset); + __assign_bit(bitpos, &tstr, start); + rz_mtu3_shared_reg_write(ch, offset, tstr); + + raw_spin_unlock_irqrestore(&priv->lock, flags); +} + +bool rz_mtu3_is_enabled(struct rz_mtu3_channel *ch) +{ + struct rz_mtu3 *mtu = dev_get_drvdata(ch->dev->parent); + struct rz_mtu3_priv *priv = mtu->priv_data; + unsigned long flags, tstr; + bool ret = false; + u16 offset; + u8 bitpos; + + /* start stop register shared by multiple timer channels */ + raw_spin_lock_irqsave(&priv->lock, flags); + + offset = rz_mtu3_get_tstr_offset(ch); + bitpos = rz_mtu3_get_tstr_bit_pos(ch); + tstr = rz_mtu3_shared_reg_read(ch, offset); + ret = tstr & BIT(bitpos); + + raw_spin_unlock_irqrestore(&priv->lock, flags); + + return ret; +} +EXPORT_SYMBOL_GPL(rz_mtu3_is_enabled); + +int rz_mtu3_enable(struct rz_mtu3_channel *ch) +{ + /* enable channel */ + rz_mtu3_start_stop_ch(ch, true); + + return 0; +} +EXPORT_SYMBOL_GPL(rz_mtu3_enable); + +void rz_mtu3_disable(struct rz_mtu3_channel *ch) +{ + /* disable channel */ + rz_mtu3_start_stop_ch(ch, false); +} +EXPORT_SYMBOL_GPL(rz_mtu3_disable); + +static void rz_mtu3_reset_assert(void *data) +{ + struct rz_mtu3 *mtu = dev_get_drvdata(data); + struct rz_mtu3_priv *priv = mtu->priv_data; + + mfd_remove_devices(data); + reset_control_assert(priv->rstc); +} + +static const struct mfd_cell rz_mtu3_devs[] = { + { + .name = "rz-mtu3-counter", + }, + { + .name = "pwm-rz-mtu3", + }, +}; + +static int rz_mtu3_probe(struct platform_device *pdev) +{ + struct rz_mtu3_priv *priv; + struct rz_mtu3 *ddata; + unsigned int i; + int ret; + + ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL); + if (!ddata) + return -ENOMEM; + + ddata->priv_data = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!ddata->priv_data) + return -ENOMEM; + + priv = ddata->priv_data; + + priv->mmio = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(priv->mmio)) + return PTR_ERR(priv->mmio); + + priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); + if (IS_ERR(priv->rstc)) + return PTR_ERR(priv->rstc); + + ddata->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(ddata->clk)) + return PTR_ERR(ddata->clk); + + reset_control_deassert(priv->rstc); + raw_spin_lock_init(&priv->lock); + platform_set_drvdata(pdev, ddata); + + for (i = 0; i < RZ_MTU_NUM_CHANNELS; i++) { + ddata->channels[i].channel_number = i; + ddata->channels[i].is_busy = false; + mutex_init(&ddata->channels[i].lock); + } + + ret = mfd_add_devices(&pdev->dev, 0, rz_mtu3_devs, + ARRAY_SIZE(rz_mtu3_devs), NULL, 0, NULL); + if (ret < 0) + goto err_assert; + + return devm_add_action_or_reset(&pdev->dev, rz_mtu3_reset_assert, + &pdev->dev); + +err_assert: + reset_control_assert(priv->rstc); + return ret; +} + +static const struct of_device_id rz_mtu3_of_match[] = { + { .compatible = "renesas,rz-mtu3", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, rz_mtu3_of_match); + +static struct platform_driver rz_mtu3_driver = { + .probe = rz_mtu3_probe, + .driver = { + .name = "rz-mtu3", + .of_match_table = rz_mtu3_of_match, + }, +}; +module_platform_driver(rz_mtu3_driver); + +MODULE_AUTHOR("Biju Das "); +MODULE_DESCRIPTION("Renesas RZ/G2L MTU3a Core Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/rz-mtu3.h b/drivers/mfd/rz-mtu3.h new file mode 100644 index 000000000000..51a1298b0613 --- /dev/null +++ b/drivers/mfd/rz-mtu3.h @@ -0,0 +1,147 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * MFD internals for Renesas RZ/G2L MTU3 Core driver + * + * Copyright (C) 2023 Renesas Electronics Corporation + */ + +#ifndef RZ_MTU3_MFD_H +#define RZ_MTU3_MFD_H + +#define MTU_8BIT_CH_0(_tier, _nfcr, _tcr, _tcr2, _tmdr1, _tiorh, _tiorl, _tbtm) \ + { \ + [RZ_MTU3_TIER] = _tier, \ + [RZ_MTU3_NFCR] = _nfcr, \ + [RZ_MTU3_TCR] = _tcr, \ + [RZ_MTU3_TCR2] = _tcr2, \ + [RZ_MTU3_TMDR1] = _tmdr1, \ + [RZ_MTU3_TIORH] = _tiorh, \ + [RZ_MTU3_TIORL] = _tiorl, \ + [RZ_MTU3_TBTM] = _tbtm \ + } + +#define MTU_8BIT_CH_1_2(_tier, _nfcr, _tsr, _tcr, _tcr2, _tmdr1, _tior) \ + { \ + [RZ_MTU3_TIER] = _tier, \ + [RZ_MTU3_NFCR] = _nfcr, \ + [RZ_MTU3_TSR] = _tsr, \ + [RZ_MTU3_TCR] = _tcr, \ + [RZ_MTU3_TCR2] = _tcr2, \ + [RZ_MTU3_TMDR1] = _tmdr1, \ + [RZ_MTU3_TIOR] = _tior \ + } \ + +#define MTU_8BIT_CH_3_4_6_7(_tier, _nfcr, _tsr, _tcr, _tcr2, _tmdr1, _tiorh, _tiorl, _tbtm) \ + { \ + [RZ_MTU3_TIER] = _tier, \ + [RZ_MTU3_NFCR] = _nfcr, \ + [RZ_MTU3_TSR] = _tsr, \ + [RZ_MTU3_TCR] = _tcr, \ + [RZ_MTU3_TCR2] = _tcr2, \ + [RZ_MTU3_TMDR1] = _tmdr1, \ + [RZ_MTU3_TIORH] = _tiorh, \ + [RZ_MTU3_TIORL] = _tiorl, \ + [RZ_MTU3_TBTM] = _tbtm \ + } \ + +#define MTU_8BIT_CH_5(_tier, _nfcr, _tstr, _tcntcmpclr, _tcru, _tcr2u, _tioru, \ + _tcrv, _tcr2v, _tiorv, _tcrw, _tcr2w, _tiorw) \ + { \ + [RZ_MTU3_TIER] = _tier, \ + [RZ_MTU3_NFCR] = _nfcr, \ + [RZ_MTU3_TSTR] = _tstr, \ + [RZ_MTU3_TCNTCMPCLR] = _tcntcmpclr, \ + [RZ_MTU3_TCRU] = _tcru, \ + [RZ_MTU3_TCR2U] = _tcr2u, \ + [RZ_MTU3_TIORU] = _tioru, \ + [RZ_MTU3_TCRV] = _tcrv, \ + [RZ_MTU3_TCR2V] = _tcr2v, \ + [RZ_MTU3_TIORV] = _tiorv, \ + [RZ_MTU3_TCRW] = _tcrw, \ + [RZ_MTU3_TCR2W] = _tcr2w, \ + [RZ_MTU3_TIORW] = _tiorw \ + } \ + +#define MTU_8BIT_CH_8(_tier, _nfcr, _tcr, _tcr2, _tmdr1, _tiorh, _tiorl) \ + { \ + [RZ_MTU3_TIER] = _tier, \ + [RZ_MTU3_NFCR] = _nfcr, \ + [RZ_MTU3_TCR] = _tcr, \ + [RZ_MTU3_TCR2] = _tcr2, \ + [RZ_MTU3_TMDR1] = _tmdr1, \ + [RZ_MTU3_TIORH] = _tiorh, \ + [RZ_MTU3_TIORL] = _tiorl \ + } \ + +#define MTU_16BIT_CH_0(_tcnt, _tgra, _tgrb, _tgrc, _tgrd, _tgre, _tgrf) \ + { \ + [RZ_MTU3_TCNT] = _tcnt, \ + [RZ_MTU3_TGRA] = _tgra, \ + [RZ_MTU3_TGRB] = _tgrb, \ + [RZ_MTU3_TGRC] = _tgrc, \ + [RZ_MTU3_TGRD] = _tgrd, \ + [RZ_MTU3_TGRE] = _tgre, \ + [RZ_MTU3_TGRF] = _tgrf \ + } + +#define MTU_16BIT_CH_1_2(_tcnt, _tgra, _tgrb) \ + { \ + [RZ_MTU3_TCNT] = _tcnt, \ + [RZ_MTU3_TGRA] = _tgra, \ + [RZ_MTU3_TGRB] = _tgrb \ + } + +#define MTU_16BIT_CH_3_6(_tcnt, _tgra, _tgrb, _tgrc, _tgrd, _tgre) \ + { \ + [RZ_MTU3_TCNT] = _tcnt, \ + [RZ_MTU3_TGRA] = _tgra, \ + [RZ_MTU3_TGRB] = _tgrb, \ + [RZ_MTU3_TGRC] = _tgrc, \ + [RZ_MTU3_TGRD] = _tgrd, \ + [RZ_MTU3_TGRE] = _tgre \ + } + +#define MTU_16BIT_CH_4_7(_tcnt, _tgra, _tgrb, _tgrc, _tgrd, _tgre, _tgrf, \ + _tadcr, _tadcora, _tadcorb, _tadcobra, _tadcobrb) \ + { \ + [RZ_MTU3_TCNT] = _tcnt, \ + [RZ_MTU3_TGRA] = _tgra, \ + [RZ_MTU3_TGRB] = _tgrb, \ + [RZ_MTU3_TGRC] = _tgrc, \ + [RZ_MTU3_TGRD] = _tgrd, \ + [RZ_MTU3_TGRE] = _tgre, \ + [RZ_MTU3_TGRF] = _tgrf, \ + [RZ_MTU3_TADCR] = _tadcr, \ + [RZ_MTU3_TADCORA] = _tadcora, \ + [RZ_MTU3_TADCORB] = _tadcorb, \ + [RZ_MTU3_TADCOBRA] = _tadcobra, \ + [RZ_MTU3_TADCOBRB] = _tadcobrb \ + } + +#define MTU_16BIT_CH_5(_tcntu, _tgru, _tcntv, _tgrv, _tcntw, _tgrw) \ + { \ + [RZ_MTU3_TCNTU] = _tcntu, \ + [RZ_MTU3_TGRU] = _tgru, \ + [RZ_MTU3_TCNTV] = _tcntv, \ + [RZ_MTU3_TGRV] = _tgrv, \ + [RZ_MTU3_TCNTW] = _tcntw, \ + [RZ_MTU3_TGRW] = _tgrw \ + } + +#define MTU_32BIT_CH_1(_tcntlw, _tgralw, _tgrblw) \ + { \ + [RZ_MTU3_TCNTLW] = _tcntlw, \ + [RZ_MTU3_TGRALW] = _tgralw, \ + [RZ_MTU3_TGRBLW] = _tgrblw \ + } + +#define MTU_32BIT_CH_8(_tcnt, _tgra, _tgrb, _tgrc, _tgrd) \ + { \ + [RZ_MTU3_TCNT] = _tcnt, \ + [RZ_MTU3_TGRA] = _tgra, \ + [RZ_MTU3_TGRB] = _tgrb, \ + [RZ_MTU3_TGRC] = _tgrc, \ + [RZ_MTU3_TGRD] = _tgrd \ + } + +#endif diff --git a/include/linux/mfd/rz-mtu3.h b/include/linux/mfd/rz-mtu3.h new file mode 100644 index 000000000000..c5173bc06270 --- /dev/null +++ b/include/linux/mfd/rz-mtu3.h @@ -0,0 +1,257 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 Renesas Electronics Corporation + */ +#ifndef __MFD_RZ_MTU3_H__ +#define __MFD_RZ_MTU3_H__ + +#include +#include +#include + +/* 8-bit shared register offsets macros */ +#define RZ_MTU3_TSTRA 0x080 /* Timer start register A */ +#define RZ_MTU3_TSTRB 0x880 /* Timer start register B */ + +/* 16-bit shared register offset macros */ +#define RZ_MTU3_TDDRA 0x016 /* Timer dead time data register A */ +#define RZ_MTU3_TDDRB 0x816 /* Timer dead time data register B */ +#define RZ_MTU3_TCDRA 0x014 /* Timer cycle data register A */ +#define RZ_MTU3_TCDRB 0x814 /* Timer cycle data register B */ +#define RZ_MTU3_TCBRA 0x022 /* Timer cycle buffer register A */ +#define RZ_MTU3_TCBRB 0x822 /* Timer cycle buffer register B */ +#define RZ_MTU3_TCNTSA 0x020 /* Timer subcounter A */ +#define RZ_MTU3_TCNTSB 0x820 /* Timer subcounter B */ + +/* + * MTU5 contains 3 timer counter registers and is totaly different + * from other channels, so we must separate its offset + */ + +/* 8-bit register offset macros of MTU3 channels except MTU5 */ +#define RZ_MTU3_TIER 0 /* Timer interrupt register */ +#define RZ_MTU3_NFCR 1 /* Noise filter control register */ +#define RZ_MTU3_TSR 2 /* Timer status register */ +#define RZ_MTU3_TCR 3 /* Timer control register */ +#define RZ_MTU3_TCR2 4 /* Timer control register 2 */ + +/* Timer mode register 1 */ +#define RZ_MTU3_TMDR1 5 +#define RZ_MTU3_TMDR1_MD GENMASK(3, 0) +#define RZ_MTU3_TMDR1_MD_NORMAL FIELD_PREP(RZ_MTU3_TMDR1_MD, 0) +#define RZ_MTU3_TMDR1_MD_PWMMODE1 FIELD_PREP(RZ_MTU3_TMDR1_MD, 2) + +#define RZ_MTU3_TIOR 6 /* Timer I/O control register */ +#define RZ_MTU3_TIORH 6 /* Timer I/O control register H */ +#define RZ_MTU3_TIORL 7 /* Timer I/O control register L */ +/* Only MTU3/4/6/7 have TBTM registers */ +#define RZ_MTU3_TBTM 8 /* Timer buffer operation transfer mode register */ + +/* 8-bit MTU5 register offset macros */ +#define RZ_MTU3_TSTR 2 /* MTU5 Timer start register */ +#define RZ_MTU3_TCNTCMPCLR 3 /* MTU5 Timer compare match clear register */ +#define RZ_MTU3_TCRU 4 /* Timer control register U */ +#define RZ_MTU3_TCR2U 5 /* Timer control register 2U */ +#define RZ_MTU3_TIORU 6 /* Timer I/O control register U */ +#define RZ_MTU3_TCRV 7 /* Timer control register V */ +#define RZ_MTU3_TCR2V 8 /* Timer control register 2V */ +#define RZ_MTU3_TIORV 9 /* Timer I/O control register V */ +#define RZ_MTU3_TCRW 10 /* Timer control register W */ +#define RZ_MTU3_TCR2W 11 /* Timer control register 2W */ +#define RZ_MTU3_TIORW 12 /* Timer I/O control register W */ + +/* 16-bit register offset macros of MTU3 channels except MTU5 */ +#define RZ_MTU3_TCNT 0 /* Timer counter */ +#define RZ_MTU3_TGRA 1 /* Timer general register A */ +#define RZ_MTU3_TGRB 2 /* Timer general register B */ +#define RZ_MTU3_TGRC 3 /* Timer general register C */ +#define RZ_MTU3_TGRD 4 /* Timer general register D */ +#define RZ_MTU3_TGRE 5 /* Timer general register E */ +#define RZ_MTU3_TGRF 6 /* Timer general register F */ +/* Timer A/D converter start request registers */ +#define RZ_MTU3_TADCR 7 /* control register */ +#define RZ_MTU3_TADCORA 8 /* cycle set register A */ +#define RZ_MTU3_TADCORB 9 /* cycle set register B */ +#define RZ_MTU3_TADCOBRA 10 /* cycle set buffer register A */ +#define RZ_MTU3_TADCOBRB 11 /* cycle set buffer register B */ + +/* 16-bit MTU5 register offset macros */ +#define RZ_MTU3_TCNTU 0 /* MTU5 Timer counter U */ +#define RZ_MTU3_TGRU 1 /* MTU5 Timer general register U */ +#define RZ_MTU3_TCNTV 2 /* MTU5 Timer counter V */ +#define RZ_MTU3_TGRV 3 /* MTU5 Timer general register V */ +#define RZ_MTU3_TCNTW 4 /* MTU5 Timer counter W */ +#define RZ_MTU3_TGRW 5 /* MTU5 Timer general register W */ + +/* 32-bit register offset */ +#define RZ_MTU3_TCNTLW 0 /* Timer longword counter */ +#define RZ_MTU3_TGRALW 1 /* Timer longword general register A */ +#define RZ_MTU3_TGRBLW 2 /* Timer longowrd general register B */ + +#define RZ_MTU3_TMDR3 0x191 /* MTU1 Timer Mode Register 3 */ + +/* Macros for setting registers */ +#define RZ_MTU3_TCR_CCLR GENMASK(7, 5) +#define RZ_MTU3_TCR_CKEG GENMASK(4, 3) +#define RZ_MTU3_TCR_TPCS GENMASK(2, 0) +#define RZ_MTU3_TCR_CCLR_TGRA BIT(5) +#define RZ_MTU3_TCR_CCLR_TGRC FIELD_PREP(RZ_MTU3_TCR_CCLR, 5) +#define RZ_MTU3_TCR_CKEG_RISING FIELD_PREP(RZ_MTU3_TCR_CKEG, 0) + +#define RZ_MTU3_TIOR_IOB GENMASK(7, 4) +#define RZ_MTU3_TIOR_IOA GENMASK(3, 0) +#define RZ_MTU3_TIOR_OC_RETAIN 0 +#define RZ_MTU3_TIOR_OC_INIT_OUT_LO_HI_OUT 2 +#define RZ_MTU3_TIOR_OC_INIT_OUT_HI_TOGGLE_OUT 7 + +#define RZ_MTU3_TIOR_OC_IOA_H_COMP_MATCH \ + FIELD_PREP(RZ_MTU3_TIOR_IOA, RZ_MTU3_TIOR_OC_INIT_OUT_LO_HI_OUT) +#define RZ_MTU3_TIOR_OC_IOB_TOGGLE \ + FIELD_PREP(RZ_MTU3_TIOR_IOB, RZ_MTU3_TIOR_OC_INIT_OUT_HI_TOGGLE_OUT) + +enum rz_mtu3_channels { + RZ_MTU3_CHAN_0, + RZ_MTU3_CHAN_1, + RZ_MTU3_CHAN_2, + RZ_MTU3_CHAN_3, + RZ_MTU3_CHAN_4, + RZ_MTU3_CHAN_5, + RZ_MTU3_CHAN_6, + RZ_MTU3_CHAN_7, + RZ_MTU3_CHAN_8, + RZ_MTU_NUM_CHANNELS +}; + +/** + * struct rz_mtu3_channel - MTU3 channel private data + * + * @dev: device handle + * @channel_number: channel number + * @lock: Lock to protect channel state + * @is_busy: channel state + */ +struct rz_mtu3_channel { + struct device *dev; + unsigned int channel_number; + struct mutex lock; + bool is_busy; +}; + +/** + * struct rz_mtu3 - MTU3 core private data + * + * @clk: MTU3 module clock + * @rz_mtu3_channel: HW channels + * @priv_data: MTU3 core driver private data + */ +struct rz_mtu3 { + struct clk *clk; + struct rz_mtu3_channel channels[RZ_MTU_NUM_CHANNELS]; + + void *priv_data; +}; + +#if IS_ENABLED(CONFIG_RZ_MTU3) +static inline bool rz_mtu3_request_channel(struct rz_mtu3_channel *ch) +{ + mutex_lock(&ch->lock); + if (ch->is_busy) { + mutex_unlock(&ch->lock); + return false; + } + + ch->is_busy = true; + mutex_unlock(&ch->lock); + + return true; +} + +static inline void rz_mtu3_release_channel(struct rz_mtu3_channel *ch) +{ + mutex_lock(&ch->lock); + ch->is_busy = false; + mutex_unlock(&ch->lock); +} + +bool rz_mtu3_is_enabled(struct rz_mtu3_channel *ch); +void rz_mtu3_disable(struct rz_mtu3_channel *ch); +int rz_mtu3_enable(struct rz_mtu3_channel *ch); + +u8 rz_mtu3_8bit_ch_read(struct rz_mtu3_channel *ch, u16 off); +u16 rz_mtu3_16bit_ch_read(struct rz_mtu3_channel *ch, u16 off); +u32 rz_mtu3_32bit_ch_read(struct rz_mtu3_channel *ch, u16 off); +u16 rz_mtu3_shared_reg_read(struct rz_mtu3_channel *ch, u16 off); + +void rz_mtu3_8bit_ch_write(struct rz_mtu3_channel *ch, u16 off, u8 val); +void rz_mtu3_16bit_ch_write(struct rz_mtu3_channel *ch, u16 off, u16 val); +void rz_mtu3_32bit_ch_write(struct rz_mtu3_channel *ch, u16 off, u32 val); +void rz_mtu3_shared_reg_write(struct rz_mtu3_channel *ch, u16 off, u16 val); +void rz_mtu3_shared_reg_update_bit(struct rz_mtu3_channel *ch, u16 off, + u16 pos, u8 val); +#else +static inline bool rz_mtu3_request_channel(struct rz_mtu3_channel *ch) +{ + return false; +} + +static inline void rz_mtu3_release_channel(struct rz_mtu3_channel *ch) +{ +} + +static inline bool rz_mtu3_is_enabled(struct rz_mtu3_channel *ch) +{ + return false; +} + +static inline void rz_mtu3_disable(struct rz_mtu3_channel *ch) +{ +} + +static inline int rz_mtu3_enable(struct rz_mtu3_channel *ch) +{ + return 0; +} + +static inline u8 rz_mtu3_8bit_ch_read(struct rz_mtu3_channel *ch, u16 off) +{ + return 0; +} + +static inline u16 rz_mtu3_16bit_ch_read(struct rz_mtu3_channel *ch, u16 off) +{ + return 0; +} + +static inline u32 rz_mtu3_32bit_ch_read(struct rz_mtu3_channel *ch, u16 off) +{ + return 0; +} + +static inline u16 rz_mtu3_shared_reg_read(struct rz_mtu3_channel *ch, u16 off) +{ + return 0; +} + +static inline void rz_mtu3_8bit_ch_write(struct rz_mtu3_channel *ch, u16 off, u8 val) +{ +} + +static inline void rz_mtu3_16bit_ch_write(struct rz_mtu3_channel *ch, u16 off, u16 val) +{ +} + +static inline void rz_mtu3_32bit_ch_write(struct rz_mtu3_channel *ch, u16 off, u32 val) +{ +} + +static inline void rz_mtu3_shared_reg_write(struct rz_mtu3_channel *ch, u16 off, u16 val) +{ +} + +static inline void rz_mtu3_shared_reg_update_bit(struct rz_mtu3_channel *ch, + u16 off, u16 pos, u8 val) +{ +} +#endif + +#endif /* __MFD_RZ_MTU3_H__ */ -- cgit v1.2.3 From 7bb985ac03c4a91d185c006f68c4fadfb71e1cca Mon Sep 17 00:00:00 2001 From: Biju Das Date: Thu, 30 Mar 2023 12:16:29 +0100 Subject: Documentation: ABI: sysfs-bus-counter: add cascade_counts_enable and external_input_phase_clock_select This commit adds cascade_counts_enable and external_input_phase_ clock_select items to counter ABI file. (e.g. for Renesas MTU3 hardware used for phase counting). Signed-off-by: Biju Das Reviewed-by: William Breathitt Gray Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230330111632.169434-4-biju.das.jz@bp.renesas.com --- Documentation/ABI/testing/sysfs-bus-counter | 32 +++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-counter b/Documentation/ABI/testing/sysfs-bus-counter index ff83320b4255..1417c4272c6c 100644 --- a/Documentation/ABI/testing/sysfs-bus-counter +++ b/Documentation/ABI/testing/sysfs-bus-counter @@ -1,3 +1,33 @@ +What: /sys/bus/counter/devices/counterX/cascade_counts_enable +KernelVersion: 6.4 +Contact: linux-iio@vger.kernel.org +Description: + Indicates the cascading of Counts on Counter X. + + Valid attribute values are boolean. + +What: /sys/bus/counter/devices/counterX/external_input_phase_clock_select +KernelVersion: 6.4 +Contact: linux-iio@vger.kernel.org +Description: + Selects the external clock pin for phase counting mode of + Counter X. + + MTCLKA-MTCLKB: + MTCLKA and MTCLKB pins are selected for the external + phase clock. + + MTCLKC-MTCLKD: + MTCLKC and MTCLKD pins are selected for the external + phase clock. + +What: /sys/bus/counter/devices/counterX/external_input_phase_clock_select_available +KernelVersion: 6.4 +Contact: linux-iio@vger.kernel.org +Description: + Discrete set of available values for the respective device + configuration are listed in this file. + What: /sys/bus/counter/devices/counterX/countY/count KernelVersion: 5.2 Contact: linux-iio@vger.kernel.org @@ -215,6 +245,8 @@ Contact: linux-iio@vger.kernel.org Description: This attribute indicates the number of overflows of count Y. +What: /sys/bus/counter/devices/counterX/cascade_counts_enable_component_id +What: /sys/bus/counter/devices/counterX/external_input_phase_clock_select_component_id What: /sys/bus/counter/devices/counterX/countY/capture_component_id What: /sys/bus/counter/devices/counterX/countY/ceiling_component_id What: /sys/bus/counter/devices/counterX/countY/floor_component_id -- cgit v1.2.3 From 0be8907359df4c62319f5cb2c6981ff0d9ebf35a Mon Sep 17 00:00:00 2001 From: Biju Das Date: Thu, 30 Mar 2023 12:16:30 +0100 Subject: counter: Add Renesas RZ/G2L MTU3a counter driver Add RZ/G2L MTU3a counter driver. This IP supports the following phase counting modes on MTU1 and MTU2 channels 1) 16-bit phase counting modes on MTU1 and MTU2 channels. 2) 32-bit phase counting mode by cascading MTU1 and MTU2 channels. This patch adds 3 counter value channels. count0: 16-bit phase counter value channel on MTU1 count1: 16-bit phase counter value channel on MTU2 count2: 32-bit phase counter value channel by cascading MTU1 and MTU2 channels. The external input phase clock pin for the counter value channels are as follows: count0: "MTCLKA-MTCLKB" count1: "MTCLKA-MTCLKB" or "MTCLKC-MTCLKD" count2: "MTCLKA-MTCLKB" or "MTCLKC-MTCLKD" Use the sysfs variable "external_input_phase_clock_select" to select the external input phase clock pin and "cascade_counts_enable" to enable/ disable cascading of channels. Signed-off-by: Biju Das Reviewed-by: William Breathitt Gray Acked-by: William Breathitt Gray Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230330111632.169434-5-biju.das.jz@bp.renesas.com --- drivers/counter/Kconfig | 11 + drivers/counter/Makefile | 1 + drivers/counter/rz-mtu3-cnt.c | 902 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 914 insertions(+) create mode 100644 drivers/counter/rz-mtu3-cnt.c diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig index b5ba8fb02cf7..4228be917038 100644 --- a/drivers/counter/Kconfig +++ b/drivers/counter/Kconfig @@ -73,6 +73,17 @@ config MICROCHIP_TCB_CAPTURE To compile this driver as a module, choose M here: the module will be called microchip-tcb-capture. +config RZ_MTU3_CNT + tristate "Renesas RZ/G2L MTU3a counter driver" + depends on RZ_MTU3 || COMPILE_TEST + help + Enable support for MTU3a counter driver found on Renesas RZ/G2L alike + SoCs. This IP supports both 16-bit and 32-bit phase counting mode + support. + + To compile this driver as a module, choose M here: the + module will be called rz-mtu3-cnt. + config STM32_LPTIMER_CNT tristate "STM32 LP Timer encoder counter driver" depends on MFD_STM32_LPTIMER || COMPILE_TEST diff --git a/drivers/counter/Makefile b/drivers/counter/Makefile index b9a369e0d4fc..933fdd50b3e4 100644 --- a/drivers/counter/Makefile +++ b/drivers/counter/Makefile @@ -8,6 +8,7 @@ counter-y := counter-core.o counter-sysfs.o counter-chrdev.o obj-$(CONFIG_104_QUAD_8) += 104-quad-8.o obj-$(CONFIG_INTERRUPT_CNT) += interrupt-cnt.o +obj-$(CONFIG_RZ_MTU3_CNT) += rz-mtu3-cnt.o obj-$(CONFIG_STM32_TIMER_CNT) += stm32-timer-cnt.o obj-$(CONFIG_STM32_LPTIMER_CNT) += stm32-lptimer-cnt.o obj-$(CONFIG_TI_EQEP) += ti-eqep.o diff --git a/drivers/counter/rz-mtu3-cnt.c b/drivers/counter/rz-mtu3-cnt.c new file mode 100644 index 000000000000..a371bab68499 --- /dev/null +++ b/drivers/counter/rz-mtu3-cnt.c @@ -0,0 +1,902 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Renesas RZ/G2L MTU3a Counter driver + * + * Copyright (C) 2022 Renesas Electronics Corporation + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * Register descriptions + * TSR: Timer Status Register + * TMDR1: Timer Mode Register 1 + * TMDR3: Timer Mode Register 3 + * TIOR: Timer I/O Control Register + * TCR: Timer Control Register + * TCNT: Timer Counter + * TGRA: Timer general register A + * TCNTLW: Timer Longword Counter + * TGRALW: Timer longword general register A + */ + +#define RZ_MTU3_TSR_TCFD BIT(7) /* Count Direction Flag */ + +#define RZ_MTU3_TMDR1_PH_CNT_MODE_1 (4) /* Phase counting mode 1 */ +#define RZ_MTU3_TMDR1_PH_CNT_MODE_2 (5) /* Phase counting mode 2 */ +#define RZ_MTU3_TMDR1_PH_CNT_MODE_3 (6) /* Phase counting mode 3 */ +#define RZ_MTU3_TMDR1_PH_CNT_MODE_4 (7) /* Phase counting mode 4 */ +#define RZ_MTU3_TMDR1_PH_CNT_MODE_5 (9) /* Phase counting mode 5 */ +#define RZ_MTU3_TMDR1_PH_CNT_MODE_MASK (0xf) + +/* + * LWA: MTU1/MTU2 Combination Longword Access Control + * 0: 16-bit, 1: 32-bit + */ +#define RZ_MTU3_TMDR3_LWA (0) + +/* + * PHCKSEL: External Input Phase Clock Select + * 0: MTCLKA and MTCLKB, 1: MTCLKC and MTCLKD + */ +#define RZ_MTU3_TMDR3_PHCKSEL (1) + +#define RZ_MTU3_16_BIT_MTU1_CH (0) +#define RZ_MTU3_16_BIT_MTU2_CH (1) +#define RZ_MTU3_32_BIT_CH (2) + +#define RZ_MTU3_TIOR_NO_OUTPUT (0) /* Output prohibited */ +#define RZ_MTU3_TIOR_IC_BOTH (10) /* Input capture at both edges */ + +#define SIGNAL_A_ID (0) +#define SIGNAL_B_ID (1) +#define SIGNAL_C_ID (2) +#define SIGNAL_D_ID (3) + +#define RZ_MTU3_MAX_HW_CNTR_CHANNELS (2) +#define RZ_MTU3_MAX_LOGICAL_CNTR_CHANNELS (3) + +/** + * struct rz_mtu3_cnt - MTU3 counter private data + * + * @clk: MTU3 module clock + * @lock: Lock to prevent concurrent access for ceiling and count + * @ch: HW channels for the counters + * @count_is_enabled: Enabled state of Counter value channel + * @mtu_16bit_max: Cache for 16-bit counters + * @mtu_32bit_max: Cache for 32-bit counters + */ +struct rz_mtu3_cnt { + struct clk *clk; + struct mutex lock; + struct rz_mtu3_channel *ch; + bool count_is_enabled[RZ_MTU3_MAX_LOGICAL_CNTR_CHANNELS]; + union { + u16 mtu_16bit_max[RZ_MTU3_MAX_HW_CNTR_CHANNELS]; + u32 mtu_32bit_max; + }; +}; + +static const enum counter_function rz_mtu3_count_functions[] = { + COUNTER_FUNCTION_QUADRATURE_X4, + COUNTER_FUNCTION_PULSE_DIRECTION, + COUNTER_FUNCTION_QUADRATURE_X2_B, +}; + +static inline size_t rz_mtu3_get_hw_ch(const size_t id) +{ + return (id == RZ_MTU3_32_BIT_CH) ? 0 : id; +} + +static inline struct rz_mtu3_channel *rz_mtu3_get_ch(struct counter_device *counter, int id) +{ + struct rz_mtu3_cnt *const priv = counter_priv(counter); + const size_t ch_id = rz_mtu3_get_hw_ch(id); + + return &priv->ch[ch_id]; +} + +static bool rz_mtu3_is_counter_invalid(struct counter_device *counter, int id) +{ + struct rz_mtu3_cnt *const priv = counter_priv(counter); + unsigned long tmdr; + + pm_runtime_get_sync(priv->ch->dev); + tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3); + pm_runtime_put(priv->ch->dev); + + if (id == RZ_MTU3_32_BIT_CH && test_bit(RZ_MTU3_TMDR3_LWA, &tmdr)) + return false; + + if (id != RZ_MTU3_32_BIT_CH && !test_bit(RZ_MTU3_TMDR3_LWA, &tmdr)) + return false; + + return true; +} + +static int rz_mtu3_lock_if_counter_is_valid(struct counter_device *counter, + struct rz_mtu3_channel *const ch, + struct rz_mtu3_cnt *const priv, + int id) +{ + mutex_lock(&priv->lock); + + if (ch->is_busy && !priv->count_is_enabled[id]) { + mutex_unlock(&priv->lock); + return -EINVAL; + } + + if (rz_mtu3_is_counter_invalid(counter, id)) { + mutex_unlock(&priv->lock); + return -EBUSY; + } + + return 0; +} + +static int rz_mtu3_lock_if_count_is_enabled(struct rz_mtu3_channel *const ch, + struct rz_mtu3_cnt *const priv, + int id) +{ + mutex_lock(&priv->lock); + + if (ch->is_busy && !priv->count_is_enabled[id]) { + mutex_unlock(&priv->lock); + return -EINVAL; + } + + return 0; +} + +static int rz_mtu3_count_read(struct counter_device *counter, + struct counter_count *count, u64 *val) +{ + struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id); + struct rz_mtu3_cnt *const priv = counter_priv(counter); + int ret; + + ret = rz_mtu3_lock_if_counter_is_valid(counter, ch, priv, count->id); + if (ret) + return ret; + + pm_runtime_get_sync(ch->dev); + if (count->id == RZ_MTU3_32_BIT_CH) + *val = rz_mtu3_32bit_ch_read(ch, RZ_MTU3_TCNTLW); + else + *val = rz_mtu3_16bit_ch_read(ch, RZ_MTU3_TCNT); + pm_runtime_put(ch->dev); + mutex_unlock(&priv->lock); + + return 0; +} + +static int rz_mtu3_count_write(struct counter_device *counter, + struct counter_count *count, const u64 val) +{ + struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id); + struct rz_mtu3_cnt *const priv = counter_priv(counter); + int ret; + + ret = rz_mtu3_lock_if_counter_is_valid(counter, ch, priv, count->id); + if (ret) + return ret; + + pm_runtime_get_sync(ch->dev); + if (count->id == RZ_MTU3_32_BIT_CH) + rz_mtu3_32bit_ch_write(ch, RZ_MTU3_TCNTLW, val); + else + rz_mtu3_16bit_ch_write(ch, RZ_MTU3_TCNT, val); + pm_runtime_put(ch->dev); + mutex_unlock(&priv->lock); + + return 0; +} + +static int rz_mtu3_count_function_read_helper(struct rz_mtu3_channel *const ch, + struct rz_mtu3_cnt *const priv, + enum counter_function *function) +{ + u8 timer_mode; + + pm_runtime_get_sync(ch->dev); + timer_mode = rz_mtu3_8bit_ch_read(ch, RZ_MTU3_TMDR1); + pm_runtime_put(ch->dev); + + switch (timer_mode & RZ_MTU3_TMDR1_PH_CNT_MODE_MASK) { + case RZ_MTU3_TMDR1_PH_CNT_MODE_1: + *function = COUNTER_FUNCTION_QUADRATURE_X4; + return 0; + case RZ_MTU3_TMDR1_PH_CNT_MODE_2: + *function = COUNTER_FUNCTION_PULSE_DIRECTION; + return 0; + case RZ_MTU3_TMDR1_PH_CNT_MODE_4: + *function = COUNTER_FUNCTION_QUADRATURE_X2_B; + return 0; + default: + /* + * TODO: + * - need to add RZ_MTU3_TMDR1_PH_CNT_MODE_3 + * - need to add RZ_MTU3_TMDR1_PH_CNT_MODE_5 + */ + return -EINVAL; + } +} + +static int rz_mtu3_count_function_read(struct counter_device *counter, + struct counter_count *count, + enum counter_function *function) +{ + struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id); + struct rz_mtu3_cnt *const priv = counter_priv(counter); + int ret; + + ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id); + if (ret) + return ret; + + ret = rz_mtu3_count_function_read_helper(ch, priv, function); + mutex_unlock(&priv->lock); + + return ret; +} + +static int rz_mtu3_count_function_write(struct counter_device *counter, + struct counter_count *count, + enum counter_function function) +{ + struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id); + struct rz_mtu3_cnt *const priv = counter_priv(counter); + u8 timer_mode; + int ret; + + ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id); + if (ret) + return ret; + + switch (function) { + case COUNTER_FUNCTION_QUADRATURE_X4: + timer_mode = RZ_MTU3_TMDR1_PH_CNT_MODE_1; + break; + case COUNTER_FUNCTION_PULSE_DIRECTION: + timer_mode = RZ_MTU3_TMDR1_PH_CNT_MODE_2; + break; + case COUNTER_FUNCTION_QUADRATURE_X2_B: + timer_mode = RZ_MTU3_TMDR1_PH_CNT_MODE_4; + break; + default: + /* + * TODO: + * - need to add RZ_MTU3_TMDR1_PH_CNT_MODE_3 + * - need to add RZ_MTU3_TMDR1_PH_CNT_MODE_5 + */ + mutex_unlock(&priv->lock); + return -EINVAL; + } + + pm_runtime_get_sync(ch->dev); + rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TMDR1, timer_mode); + pm_runtime_put(ch->dev); + mutex_unlock(&priv->lock); + + return 0; +} + +static int rz_mtu3_count_direction_read(struct counter_device *counter, + struct counter_count *count, + enum counter_count_direction *direction) +{ + struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id); + struct rz_mtu3_cnt *const priv = counter_priv(counter); + int ret; + u8 tsr; + + ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id); + if (ret) + return ret; + + pm_runtime_get_sync(ch->dev); + tsr = rz_mtu3_8bit_ch_read(ch, RZ_MTU3_TSR); + pm_runtime_put(ch->dev); + + *direction = (tsr & RZ_MTU3_TSR_TCFD) ? + COUNTER_COUNT_DIRECTION_FORWARD : COUNTER_COUNT_DIRECTION_BACKWARD; + mutex_unlock(&priv->lock); + + return 0; +} + +static int rz_mtu3_count_ceiling_read(struct counter_device *counter, + struct counter_count *count, + u64 *ceiling) +{ + struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id); + struct rz_mtu3_cnt *const priv = counter_priv(counter); + const size_t ch_id = rz_mtu3_get_hw_ch(count->id); + int ret; + + ret = rz_mtu3_lock_if_counter_is_valid(counter, ch, priv, count->id); + if (ret) + return ret; + + switch (count->id) { + case RZ_MTU3_16_BIT_MTU1_CH: + case RZ_MTU3_16_BIT_MTU2_CH: + *ceiling = priv->mtu_16bit_max[ch_id]; + break; + case RZ_MTU3_32_BIT_CH: + *ceiling = priv->mtu_32bit_max; + break; + default: + /* should never reach this path */ + mutex_unlock(&priv->lock); + return -EINVAL; + } + + mutex_unlock(&priv->lock); + return 0; +} + +static int rz_mtu3_count_ceiling_write(struct counter_device *counter, + struct counter_count *count, + u64 ceiling) +{ + struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id); + struct rz_mtu3_cnt *const priv = counter_priv(counter); + const size_t ch_id = rz_mtu3_get_hw_ch(count->id); + int ret; + + ret = rz_mtu3_lock_if_counter_is_valid(counter, ch, priv, count->id); + if (ret) + return ret; + + switch (count->id) { + case RZ_MTU3_16_BIT_MTU1_CH: + case RZ_MTU3_16_BIT_MTU2_CH: + if (ceiling > U16_MAX) + return -ERANGE; + priv->mtu_16bit_max[ch_id] = ceiling; + break; + case RZ_MTU3_32_BIT_CH: + if (ceiling > U32_MAX) + return -ERANGE; + priv->mtu_32bit_max = ceiling; + break; + default: + /* should never reach this path */ + mutex_unlock(&priv->lock); + return -EINVAL; + } + + pm_runtime_get_sync(ch->dev); + if (count->id == RZ_MTU3_32_BIT_CH) + rz_mtu3_32bit_ch_write(ch, RZ_MTU3_TGRALW, ceiling); + else + rz_mtu3_16bit_ch_write(ch, RZ_MTU3_TGRA, ceiling); + + rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TCR, RZ_MTU3_TCR_CCLR_TGRA); + pm_runtime_put(ch->dev); + mutex_unlock(&priv->lock); + + return 0; +} + +static void rz_mtu3_32bit_cnt_setting(struct counter_device *counter) +{ + struct rz_mtu3_channel *const ch1 = rz_mtu3_get_ch(counter, 0); + struct rz_mtu3_channel *const ch2 = rz_mtu3_get_ch(counter, 1); + + /* Phase counting mode 1 is used as default in initialization. */ + rz_mtu3_8bit_ch_write(ch1, RZ_MTU3_TMDR1, RZ_MTU3_TMDR1_PH_CNT_MODE_1); + + rz_mtu3_8bit_ch_write(ch1, RZ_MTU3_TCR, RZ_MTU3_TCR_CCLR_TGRA); + rz_mtu3_8bit_ch_write(ch1, RZ_MTU3_TIOR, RZ_MTU3_TIOR_IC_BOTH); + + rz_mtu3_enable(ch1); + rz_mtu3_enable(ch2); +} + +static void rz_mtu3_16bit_cnt_setting(struct counter_device *counter, int id) +{ + struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, id); + + /* Phase counting mode 1 is used as default in initialization. */ + rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TMDR1, RZ_MTU3_TMDR1_PH_CNT_MODE_1); + + rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TCR, RZ_MTU3_TCR_CCLR_TGRA); + rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TIOR, RZ_MTU3_TIOR_NO_OUTPUT); + rz_mtu3_enable(ch); +} + +static int rz_mtu3_initialize_counter(struct counter_device *counter, int id) +{ + struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, id); + struct rz_mtu3_channel *const ch1 = rz_mtu3_get_ch(counter, 0); + struct rz_mtu3_channel *const ch2 = rz_mtu3_get_ch(counter, 1); + + switch (id) { + case RZ_MTU3_16_BIT_MTU1_CH: + case RZ_MTU3_16_BIT_MTU2_CH: + if (!rz_mtu3_request_channel(ch)) + return -EBUSY; + + rz_mtu3_16bit_cnt_setting(counter, id); + return 0; + case RZ_MTU3_32_BIT_CH: + /* + * 32-bit phase counting need MTU1 and MTU2 to create 32-bit + * cascade counter. + */ + if (!rz_mtu3_request_channel(ch1)) + return -EBUSY; + + if (!rz_mtu3_request_channel(ch2)) { + rz_mtu3_release_channel(ch1); + return -EBUSY; + } + + rz_mtu3_32bit_cnt_setting(counter); + return 0; + default: + /* should never reach this path */ + return -EINVAL; + } +} + +static void rz_mtu3_terminate_counter(struct counter_device *counter, int id) +{ + struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, id); + struct rz_mtu3_channel *const ch1 = rz_mtu3_get_ch(counter, 0); + struct rz_mtu3_channel *const ch2 = rz_mtu3_get_ch(counter, 1); + + if (id == RZ_MTU3_32_BIT_CH) { + rz_mtu3_release_channel(ch2); + rz_mtu3_release_channel(ch1); + rz_mtu3_disable(ch2); + rz_mtu3_disable(ch1); + } else { + rz_mtu3_release_channel(ch); + rz_mtu3_disable(ch); + } +} + +static int rz_mtu3_count_enable_read(struct counter_device *counter, + struct counter_count *count, u8 *enable) +{ + struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id); + struct rz_mtu3_channel *const ch1 = rz_mtu3_get_ch(counter, 0); + struct rz_mtu3_channel *const ch2 = rz_mtu3_get_ch(counter, 1); + struct rz_mtu3_cnt *const priv = counter_priv(counter); + int ret; + + ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id); + if (ret) + return ret; + + if (count->id == RZ_MTU3_32_BIT_CH) + *enable = rz_mtu3_is_enabled(ch1) && rz_mtu3_is_enabled(ch2); + else + *enable = rz_mtu3_is_enabled(ch); + + mutex_unlock(&priv->lock); + + return 0; +} + +static int rz_mtu3_count_enable_write(struct counter_device *counter, + struct counter_count *count, u8 enable) +{ + struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id); + struct rz_mtu3_cnt *const priv = counter_priv(counter); + int ret = 0; + + if (enable) { + pm_runtime_get_sync(ch->dev); + mutex_lock(&priv->lock); + ret = rz_mtu3_initialize_counter(counter, count->id); + if (ret == 0) + priv->count_is_enabled[count->id] = true; + mutex_unlock(&priv->lock); + } else { + mutex_lock(&priv->lock); + rz_mtu3_terminate_counter(counter, count->id); + priv->count_is_enabled[count->id] = false; + mutex_unlock(&priv->lock); + pm_runtime_put(ch->dev); + } + + return ret; +} + +static int rz_mtu3_lock_if_ch0_is_enabled(struct rz_mtu3_cnt *const priv) +{ + mutex_lock(&priv->lock); + if (priv->ch->is_busy && !(priv->count_is_enabled[RZ_MTU3_16_BIT_MTU1_CH] || + priv->count_is_enabled[RZ_MTU3_32_BIT_CH])) { + mutex_unlock(&priv->lock); + return -EINVAL; + } + + return 0; +} + +static int rz_mtu3_cascade_counts_enable_get(struct counter_device *counter, + u8 *cascade_enable) +{ + struct rz_mtu3_cnt *const priv = counter_priv(counter); + unsigned long tmdr; + int ret; + + ret = rz_mtu3_lock_if_ch0_is_enabled(priv); + if (ret) + return ret; + + pm_runtime_get_sync(priv->ch->dev); + tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3); + pm_runtime_put(priv->ch->dev); + *cascade_enable = test_bit(RZ_MTU3_TMDR3_LWA, &tmdr); + mutex_unlock(&priv->lock); + + return 0; +} + +static int rz_mtu3_cascade_counts_enable_set(struct counter_device *counter, + u8 cascade_enable) +{ + struct rz_mtu3_cnt *const priv = counter_priv(counter); + int ret; + + ret = rz_mtu3_lock_if_ch0_is_enabled(priv); + if (ret) + return ret; + + pm_runtime_get_sync(priv->ch->dev); + rz_mtu3_shared_reg_update_bit(priv->ch, RZ_MTU3_TMDR3, + RZ_MTU3_TMDR3_LWA, cascade_enable); + pm_runtime_put(priv->ch->dev); + mutex_unlock(&priv->lock); + + return 0; +} + +static int rz_mtu3_ext_input_phase_clock_select_get(struct counter_device *counter, + u32 *ext_input_phase_clock_select) +{ + struct rz_mtu3_cnt *const priv = counter_priv(counter); + unsigned long tmdr; + int ret; + + ret = rz_mtu3_lock_if_ch0_is_enabled(priv); + if (ret) + return ret; + + pm_runtime_get_sync(priv->ch->dev); + tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3); + pm_runtime_put(priv->ch->dev); + *ext_input_phase_clock_select = test_bit(RZ_MTU3_TMDR3_PHCKSEL, &tmdr); + mutex_unlock(&priv->lock); + + return 0; +} + +static int rz_mtu3_ext_input_phase_clock_select_set(struct counter_device *counter, + u32 ext_input_phase_clock_select) +{ + struct rz_mtu3_cnt *const priv = counter_priv(counter); + int ret; + + ret = rz_mtu3_lock_if_ch0_is_enabled(priv); + if (ret) + return ret; + + pm_runtime_get_sync(priv->ch->dev); + rz_mtu3_shared_reg_update_bit(priv->ch, RZ_MTU3_TMDR3, + RZ_MTU3_TMDR3_PHCKSEL, + ext_input_phase_clock_select); + pm_runtime_put(priv->ch->dev); + mutex_unlock(&priv->lock); + + return 0; +} + +static struct counter_comp rz_mtu3_count_ext[] = { + COUNTER_COMP_DIRECTION(rz_mtu3_count_direction_read), + COUNTER_COMP_ENABLE(rz_mtu3_count_enable_read, + rz_mtu3_count_enable_write), + COUNTER_COMP_CEILING(rz_mtu3_count_ceiling_read, + rz_mtu3_count_ceiling_write), +}; + +static const enum counter_synapse_action rz_mtu3_synapse_actions[] = { + COUNTER_SYNAPSE_ACTION_BOTH_EDGES, + COUNTER_SYNAPSE_ACTION_RISING_EDGE, + COUNTER_SYNAPSE_ACTION_NONE, +}; + +static int rz_mtu3_action_read(struct counter_device *counter, + struct counter_count *count, + struct counter_synapse *synapse, + enum counter_synapse_action *action) +{ + const bool is_signal_ab = (synapse->signal->id == SIGNAL_A_ID) || + (synapse->signal->id == SIGNAL_B_ID); + struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id); + struct rz_mtu3_cnt *const priv = counter_priv(counter); + enum counter_function function; + bool mtclkc_mtclkd; + unsigned long tmdr; + int ret; + + ret = rz_mtu3_lock_if_count_is_enabled(ch, priv, count->id); + if (ret) + return ret; + + ret = rz_mtu3_count_function_read_helper(ch, priv, &function); + if (ret) { + mutex_unlock(&priv->lock); + return ret; + } + + /* Default action mode */ + *action = COUNTER_SYNAPSE_ACTION_NONE; + + if (count->id != RZ_MTU3_16_BIT_MTU1_CH) { + tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3); + mtclkc_mtclkd = test_bit(RZ_MTU3_TMDR3_PHCKSEL, &tmdr); + if ((mtclkc_mtclkd && is_signal_ab) || + (!mtclkc_mtclkd && !is_signal_ab)) { + mutex_unlock(&priv->lock); + return 0; + } + } + + switch (function) { + case COUNTER_FUNCTION_PULSE_DIRECTION: + /* + * Rising edges on signal A (signal C) updates the respective + * count. The input level of signal B (signal D) determines + * direction. + */ + if (synapse->signal->id == SIGNAL_A_ID || + synapse->signal->id == SIGNAL_C_ID) + *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE; + break; + case COUNTER_FUNCTION_QUADRATURE_X2_B: + /* + * Any state transition on quadrature pair signal B (signal D) + * updates the respective count. + */ + if (synapse->signal->id == SIGNAL_B_ID || + synapse->signal->id == SIGNAL_D_ID) + *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES; + break; + case COUNTER_FUNCTION_QUADRATURE_X4: + /* counts up/down on both edges of A (C) and B (D) signal */ + *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES; + break; + default: + /* should never reach this path */ + mutex_unlock(&priv->lock); + return -EINVAL; + } + + mutex_unlock(&priv->lock); + + return 0; +} + +static const struct counter_ops rz_mtu3_cnt_ops = { + .count_read = rz_mtu3_count_read, + .count_write = rz_mtu3_count_write, + .function_read = rz_mtu3_count_function_read, + .function_write = rz_mtu3_count_function_write, + .action_read = rz_mtu3_action_read, +}; + +#define RZ_MTU3_PHASE_SIGNAL(_id, _name) { \ + .id = (_id), \ + .name = (_name), \ +} + +static struct counter_signal rz_mtu3_signals[] = { + RZ_MTU3_PHASE_SIGNAL(SIGNAL_A_ID, "MTU1 MTCLKA"), + RZ_MTU3_PHASE_SIGNAL(SIGNAL_B_ID, "MTU1 MTCLKB"), + RZ_MTU3_PHASE_SIGNAL(SIGNAL_C_ID, "MTU2 MTCLKC"), + RZ_MTU3_PHASE_SIGNAL(SIGNAL_D_ID, "MTU2 MTCLKD"), +}; + +static struct counter_synapse rz_mtu3_mtu1_count_synapses[] = { + { + .actions_list = rz_mtu3_synapse_actions, + .num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions), + .signal = rz_mtu3_signals, + }, + { + .actions_list = rz_mtu3_synapse_actions, + .num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions), + .signal = rz_mtu3_signals + 1, + } +}; + +static struct counter_synapse rz_mtu3_mtu2_count_synapses[] = { + { + .actions_list = rz_mtu3_synapse_actions, + .num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions), + .signal = rz_mtu3_signals, + }, + { + .actions_list = rz_mtu3_synapse_actions, + .num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions), + .signal = rz_mtu3_signals + 1, + }, + { + .actions_list = rz_mtu3_synapse_actions, + .num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions), + .signal = rz_mtu3_signals + 2, + }, + { + .actions_list = rz_mtu3_synapse_actions, + .num_actions = ARRAY_SIZE(rz_mtu3_synapse_actions), + .signal = rz_mtu3_signals + 3, + } +}; + +static struct counter_count rz_mtu3_counts[] = { + { + .id = RZ_MTU3_16_BIT_MTU1_CH, + .name = "Channel 1 Count", + .functions_list = rz_mtu3_count_functions, + .num_functions = ARRAY_SIZE(rz_mtu3_count_functions), + .synapses = rz_mtu3_mtu1_count_synapses, + .num_synapses = ARRAY_SIZE(rz_mtu3_mtu1_count_synapses), + .ext = rz_mtu3_count_ext, + .num_ext = ARRAY_SIZE(rz_mtu3_count_ext), + }, + { + .id = RZ_MTU3_16_BIT_MTU2_CH, + .name = "Channel 2 Count", + .functions_list = rz_mtu3_count_functions, + .num_functions = ARRAY_SIZE(rz_mtu3_count_functions), + .synapses = rz_mtu3_mtu2_count_synapses, + .num_synapses = ARRAY_SIZE(rz_mtu3_mtu2_count_synapses), + .ext = rz_mtu3_count_ext, + .num_ext = ARRAY_SIZE(rz_mtu3_count_ext), + }, + { + .id = RZ_MTU3_32_BIT_CH, + .name = "Channel 1 and 2 (cascaded) Count", + .functions_list = rz_mtu3_count_functions, + .num_functions = ARRAY_SIZE(rz_mtu3_count_functions), + .synapses = rz_mtu3_mtu2_count_synapses, + .num_synapses = ARRAY_SIZE(rz_mtu3_mtu2_count_synapses), + .ext = rz_mtu3_count_ext, + .num_ext = ARRAY_SIZE(rz_mtu3_count_ext), + } +}; + +static const char *const rz_mtu3_ext_input_phase_clock_select[] = { + "MTCLKA-MTCLKB", + "MTCLKC-MTCLKD", +}; + +static DEFINE_COUNTER_ENUM(rz_mtu3_ext_input_phase_clock_select_enum, + rz_mtu3_ext_input_phase_clock_select); + +static struct counter_comp rz_mtu3_device_ext[] = { + COUNTER_COMP_DEVICE_BOOL("cascade_counts_enable", + rz_mtu3_cascade_counts_enable_get, + rz_mtu3_cascade_counts_enable_set), + COUNTER_COMP_DEVICE_ENUM("external_input_phase_clock_select", + rz_mtu3_ext_input_phase_clock_select_get, + rz_mtu3_ext_input_phase_clock_select_set, + rz_mtu3_ext_input_phase_clock_select_enum), +}; + +static int rz_mtu3_cnt_pm_runtime_suspend(struct device *dev) +{ + struct clk *const clk = dev_get_drvdata(dev); + + clk_disable_unprepare(clk); + + return 0; +} + +static int rz_mtu3_cnt_pm_runtime_resume(struct device *dev) +{ + struct clk *const clk = dev_get_drvdata(dev); + + clk_prepare_enable(clk); + + return 0; +} + +static DEFINE_RUNTIME_DEV_PM_OPS(rz_mtu3_cnt_pm_ops, + rz_mtu3_cnt_pm_runtime_suspend, + rz_mtu3_cnt_pm_runtime_resume, NULL); + +static void rz_mtu3_cnt_pm_disable(void *data) +{ + struct device *dev = data; + + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); +} + +static int rz_mtu3_cnt_probe(struct platform_device *pdev) +{ + struct rz_mtu3 *ddata = dev_get_drvdata(pdev->dev.parent); + struct device *dev = &pdev->dev; + struct counter_device *counter; + struct rz_mtu3_channel *ch; + struct rz_mtu3_cnt *priv; + unsigned int i; + int ret; + + counter = devm_counter_alloc(dev, sizeof(*priv)); + if (!counter) + return -ENOMEM; + + priv = counter_priv(counter); + priv->clk = ddata->clk; + priv->mtu_32bit_max = U32_MAX; + priv->ch = &ddata->channels[RZ_MTU3_CHAN_1]; + ch = &priv->ch[0]; + for (i = 0; i < RZ_MTU3_MAX_HW_CNTR_CHANNELS; i++) { + ch->dev = dev; + priv->mtu_16bit_max[i] = U16_MAX; + ch++; + } + + mutex_init(&priv->lock); + platform_set_drvdata(pdev, priv->clk); + clk_prepare_enable(priv->clk); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + ret = devm_add_action_or_reset(&pdev->dev, rz_mtu3_cnt_pm_disable, dev); + if (ret < 0) + goto disable_clock; + + counter->name = dev_name(dev); + counter->parent = dev; + counter->ops = &rz_mtu3_cnt_ops; + counter->counts = rz_mtu3_counts; + counter->num_counts = ARRAY_SIZE(rz_mtu3_counts); + counter->signals = rz_mtu3_signals; + counter->num_signals = ARRAY_SIZE(rz_mtu3_signals); + counter->ext = rz_mtu3_device_ext; + counter->num_ext = ARRAY_SIZE(rz_mtu3_device_ext); + + /* Register Counter device */ + ret = devm_counter_add(dev, counter); + if (ret < 0) { + dev_err_probe(dev, ret, "Failed to add counter\n"); + goto disable_clock; + } + + return 0; + +disable_clock: + clk_disable_unprepare(priv->clk); + + return ret; +} + +static struct platform_driver rz_mtu3_cnt_driver = { + .probe = rz_mtu3_cnt_probe, + .driver = { + .name = "rz-mtu3-counter", + .pm = pm_ptr(&rz_mtu3_cnt_pm_ops), + }, +}; +module_platform_driver(rz_mtu3_cnt_driver); + +MODULE_AUTHOR("Biju Das "); +MODULE_ALIAS("platform:rz-mtu3-counter"); +MODULE_DESCRIPTION("Renesas RZ/G2L MTU3a counter driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(COUNTER); -- cgit v1.2.3 From 5dee9439cc2d60ff35cad04b618ee53f48a7cfc2 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Thu, 30 Mar 2023 12:16:31 +0100 Subject: MAINTAINERS: Add entries for Renesas RZ/G2L MTU3a counter driver Add the MAINTAINERS entries for the Renesas RZ/G2L MTU3a counter driver. Signed-off-by: Biju Das Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230330111632.169434-6-biju.das.jz@bp.renesas.com --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index d8ebab595b2a..734d9b8de9cb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17847,6 +17847,14 @@ S: Supported F: Documentation/devicetree/bindings/iio/adc/renesas,rzg2l-adc.yaml F: drivers/iio/adc/rzg2l_adc.c +RENESAS RZ/G2L MTU3a COUNTER DRIVER +M: Biju Das +L: linux-iio@vger.kernel.org +L: linux-renesas-soc@vger.kernel.org +S: Supported +F: Documentation/devicetree/bindings/timer/renesas,rz-mtu3.yaml +F: drivers/counter/rz-mtu3-cnt.c + RENESAS RZ/N1 A5PSW SWITCH DRIVER M: Clément Léger L: linux-renesas-soc@vger.kernel.org -- cgit v1.2.3 From dbc5e57200e9ed14f08c5493c8633200cf07d700 Mon Sep 17 00:00:00 2001 From: Jacky Huang Date: Tue, 28 Mar 2023 02:19:05 +0000 Subject: dt-bindings: mfd: syscon: Add nuvoton,ma35d1-sys compatible Add Nuvoton ma35d1 system registers compatible. Signed-off-by: Jacky Huang Reviewed-by: Krzysztof Kozlowski Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230328021912.177301-6-ychuang570808@gmail.com --- Documentation/devicetree/bindings/mfd/syscon.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml index 43f564be709f..8103154bbb52 100644 --- a/Documentation/devicetree/bindings/mfd/syscon.yaml +++ b/Documentation/devicetree/bindings/mfd/syscon.yaml @@ -56,6 +56,7 @@ properties: - microchip,lan966x-cpu-syscon - microchip,sparx5-cpu-syscon - mstar,msc313-pmsleep + - nuvoton,ma35d1-sys - nuvoton,wpcm450-shm - rockchip,px30-qos - rockchip,rk3036-qos -- cgit v1.2.3 From b24e335b7d73b5d65d09144319c62aa967b6abc8 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Mon, 10 Apr 2023 22:29:16 +0200 Subject: dt-bindings: mfd: qcom,spmi-pmic: Use generic ADC node name in examples Update the examples to reflect a future requirement for the generic `channel` node name on ADC channel nodes, while conveying the board name of the channel in a label instead. Signed-off-by: Marijn Suijten Acked-by: Krzysztof Kozlowski Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230410202917.247666-5-marijn.suijten@somainline.org --- Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml index 84620ebc1efe..9f4c75c35aae 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml +++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml @@ -283,12 +283,12 @@ examples: #size-cells = <0>; #io-channel-cells = <1>; - adc-chan@6 { + channel@6 { reg = ; label = "die_temp"; }; - adc-chan@4f { + channel@4f { reg = ; qcom,ratiometric; qcom,hw-settle-time = <200>; -- cgit v1.2.3 From 378b0e9f247450c9c4e49f02d9d79799a0c7c349 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 17 Apr 2023 18:14:06 +0200 Subject: dt-bindings: mfd: stm32: Remove unnecessary blank lines Remove double blank line. Signed-off-by: Patrick Delaunay Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230417181342.v2.1.I483a676579cc7e3ac07e1db649091553743fecc8@changeid --- include/dt-bindings/mfd/stm32f4-rcc.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/dt-bindings/mfd/stm32f4-rcc.h b/include/dt-bindings/mfd/stm32f4-rcc.h index 309e8c79f27b..36448a5619a1 100644 --- a/include/dt-bindings/mfd/stm32f4-rcc.h +++ b/include/dt-bindings/mfd/stm32f4-rcc.h @@ -34,7 +34,6 @@ #define STM32F4_AHB1_RESET(bit) (STM32F4_RCC_AHB1_##bit + (0x10 * 8)) #define STM32F4_AHB1_CLOCK(bit) (STM32F4_RCC_AHB1_##bit) - /* AHB2 */ #define STM32F4_RCC_AHB2_DCMI 0 #define STM32F4_RCC_AHB2_CRYP 4 -- cgit v1.2.3 From 1706636eafcab76e08784f66f80f00d9aa59bed1 Mon Sep 17 00:00:00 2001 From: Benjamin Bara Date: Wed, 5 Apr 2023 19:14:36 +0200 Subject: dt-bindings: mfd: dlg,da9063: Document voltage monitoring Document that the da9063 only provides under- *and* over-voltage monitoring in one, and therefore requires both to be configured with the same severity and value. Add an example for clarification. Signed-off-by: Benjamin Bara Acked-by: Krzysztof Kozlowski Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230403-da9063-disable-unused-v3-3-cc4dc698864c@skidata.com --- Documentation/devicetree/bindings/mfd/dlg,da9063.yaml | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/dlg,da9063.yaml b/Documentation/devicetree/bindings/mfd/dlg,da9063.yaml index e8e74e91070c..c5a7e10d7d80 100644 --- a/Documentation/devicetree/bindings/mfd/dlg,da9063.yaml +++ b/Documentation/devicetree/bindings/mfd/dlg,da9063.yaml @@ -12,6 +12,11 @@ maintainers: description: | For device-tree bindings of other sub-modules refer to the binding documents under the respective sub-system directories. + Using regulator-{uv,ov}-{warn,error,protection}-microvolt requires special + handling: First, when GP_FB2 is used, it must be ensured that there is no + moment where all voltage monitors are disabled. Next, as da9063 only supports + UV *and* OV monitoring, both must be set to the same severity and value + (0: disable, 1: enable). properties: compatible: @@ -121,11 +126,19 @@ examples: regulator-max-microamp = <2000000>; regulator-boot-on; }; + ldo6 { + /* UNUSED */ + regulator-name = "LDO_6"; + regulator-uv-protection-microvolt = <0>; + regulator-ov-protection-microvolt = <0>; + }; ldo11 { regulator-name = "LDO_11"; regulator-min-microvolt = <900000>; - regulator-max-microvolt = <3600000>; - regulator-boot-on; + regulator-max-microvolt = <900000>; + regulator-uv-protection-microvolt = <1>; + regulator-ov-protection-microvolt = <1>; + regulator-always-on; }; }; }; -- cgit v1.2.3 From 1e28dfdf40d7293882ba7eb70a3bc0e9ab625377 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 20 Apr 2023 18:02:11 +0300 Subject: counter: rz-mtu3-cnt: Unlock on error in rz_mtu3_count_ceiling_write() These error paths need to call mutex_unlock(&priv->lock) before returning. The lock is taken in rz_mtu3_lock_if_counter_is_valid(). Fixes: 25d21447d896 ("counter: Add Renesas RZ/G2L MTU3a counter driver") Signed-off-by: Dan Carpenter Acked-by: William Breathitt Gray Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/7b535d6b-6031-493a-84f6-82842089e637@kili.mountain --- drivers/counter/rz-mtu3-cnt.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/counter/rz-mtu3-cnt.c b/drivers/counter/rz-mtu3-cnt.c index a371bab68499..48c83933aa2f 100644 --- a/drivers/counter/rz-mtu3-cnt.c +++ b/drivers/counter/rz-mtu3-cnt.c @@ -358,13 +358,17 @@ static int rz_mtu3_count_ceiling_write(struct counter_device *counter, switch (count->id) { case RZ_MTU3_16_BIT_MTU1_CH: case RZ_MTU3_16_BIT_MTU2_CH: - if (ceiling > U16_MAX) + if (ceiling > U16_MAX) { + mutex_unlock(&priv->lock); return -ERANGE; + } priv->mtu_16bit_max[ch_id] = ceiling; break; case RZ_MTU3_32_BIT_CH: - if (ceiling > U32_MAX) + if (ceiling > U32_MAX) { + mutex_unlock(&priv->lock); return -ERANGE; + } priv->mtu_32bit_max = ceiling; break; default: -- cgit v1.2.3 From a33c6a22f6d616caab6f5a5bfaa7ee01ea567d82 Mon Sep 17 00:00:00 2001 From: Martin Botka Date: Sat, 1 Apr 2023 01:18:48 +0100 Subject: dt-bindings: mfd: x-powers,axp152: Document the AXP313a variant The X-Powers AXP313a is a PMIC used on some devices with the Allwinner H616 or H313 SoC. According to the datasheet, the DC/DC converter PWM frequency is fixed (to 3 MHz), so disallow the property that lets us set this frequency for the other PMICs. Signed-off-by: Martin Botka Signed-off-by: Andre Przywara Reviewed-by: Krzysztof Kozlowski Acked-by: Chen-Yu Tsai Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230401001850.4988-2-andre.przywara@arm.com (cherry picked from commit 2a9e8a1a7c4caadf690e5a77fe4162c5edab4a9c) Signed-off-by: Lee Jones --- Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml b/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml index 2691ac08f536..ed76b1c58cdf 100644 --- a/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml +++ b/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml @@ -73,6 +73,16 @@ allOf: required: - interrupts + - if: + properties: + compatible: + contains: + const: x-powers,axp313a + + then: + properties: + x-powers,dcdc-freq: false + properties: compatible: oneOf: @@ -82,6 +92,7 @@ properties: - x-powers,axp209 - x-powers,axp221 - x-powers,axp223 + - x-powers,axp313a - x-powers,axp803 - x-powers,axp806 - x-powers,axp809 -- cgit v1.2.3 From e0f8ad2a705367518b5c56bf9d6da89681467c02 Mon Sep 17 00:00:00 2001 From: Shengyu Qu Date: Fri, 21 Apr 2023 23:08:15 +0800 Subject: mfd: axp20x: Add support for AXP15060 PMIC The AXP15060 is a PMIC chip produced by X-Powers, and could be connected via an I2C bus. Describe the regmap and the MFD bits, along with the registers exposed via I2C. Eventually advertise the device using a new compatible string and add support for power off the system. The driver would disable PEK function if IRQ is not configured in device tree, since some boards (For example, Starfive Visionfive 2) didn't connect IRQ line of PMIC to SOC. GPIO function isn't enabled in this commit, since its configuration operation is different from any existing AXP PMICs and needs logic modification on existing driver. GPIO support might come in later patches. Signed-off-by: Shengyu Qu Reviewed-by: Krzysztof Kozlowski Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/TY3P286MB261162D57695AC8164ED50E298609@TY3P286MB2611.JPNP286.PROD.OUTLOOK.COM --- drivers/mfd/axp20x-i2c.c | 2 + drivers/mfd/axp20x.c | 107 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/mfd/axp20x.h | 85 +++++++++++++++++++++++++++++++++++ 3 files changed, 194 insertions(+) diff --git a/drivers/mfd/axp20x-i2c.c b/drivers/mfd/axp20x-i2c.c index f49fbd307958..b4f5cb457117 100644 --- a/drivers/mfd/axp20x-i2c.c +++ b/drivers/mfd/axp20x-i2c.c @@ -65,6 +65,7 @@ static const struct of_device_id axp20x_i2c_of_match[] = { { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID }, { .compatible = "x-powers,axp803", .data = (void *)AXP803_ID }, { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID }, + { .compatible = "x-powers,axp15060", .data = (void *)AXP15060_ID }, { }, }; MODULE_DEVICE_TABLE(of, axp20x_i2c_of_match); @@ -78,6 +79,7 @@ static const struct i2c_device_id axp20x_i2c_id[] = { { "axp223", 0 }, { "axp803", 0 }, { "axp806", 0 }, + { "axp15060", 0 }, { }, }; MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id); diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index 7720ac15c7d4..72b87aae60cc 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -43,6 +43,7 @@ static const char * const axp20x_model_names[] = { "AXP806", "AXP809", "AXP813", + "AXP15060", }; static const struct regmap_range axp152_writeable_ranges[] = { @@ -169,6 +170,31 @@ static const struct regmap_access_table axp806_volatile_table = { .n_yes_ranges = ARRAY_SIZE(axp806_volatile_ranges), }; +static const struct regmap_range axp15060_writeable_ranges[] = { + regmap_reg_range(AXP15060_PWR_OUT_CTRL1, AXP15060_DCDC_MODE_CTRL2), + regmap_reg_range(AXP15060_OUTPUT_MONITOR_DISCHARGE, AXP15060_CPUSLDO_V_CTRL), + regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ), + regmap_reg_range(AXP15060_PEK_KEY, AXP15060_PEK_KEY), + regmap_reg_range(AXP15060_IRQ1_EN, AXP15060_IRQ2_EN), + regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE), +}; + +static const struct regmap_range axp15060_volatile_ranges[] = { + regmap_reg_range(AXP15060_STARTUP_SRC, AXP15060_STARTUP_SRC), + regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ), + regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE), +}; + +static const struct regmap_access_table axp15060_writeable_table = { + .yes_ranges = axp15060_writeable_ranges, + .n_yes_ranges = ARRAY_SIZE(axp15060_writeable_ranges), +}; + +static const struct regmap_access_table axp15060_volatile_table = { + .yes_ranges = axp15060_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(axp15060_volatile_ranges), +}; + static const struct resource axp152_pek_resources[] = { DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_RIS_EDGE, "PEK_DBR"), DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"), @@ -237,6 +263,11 @@ static const struct resource axp809_pek_resources[] = { DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_FAL_EDGE, "PEK_DBF"), }; +static const struct resource axp15060_pek_resources[] = { + DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_RIS_EDGE, "PEK_DBR"), + DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_FAL_EDGE, "PEK_DBF"), +}; + static const struct regmap_config axp152_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -282,6 +313,15 @@ static const struct regmap_config axp806_regmap_config = { .cache_type = REGCACHE_RBTREE, }; +static const struct regmap_config axp15060_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .wr_table = &axp15060_writeable_table, + .volatile_table = &axp15060_volatile_table, + .max_register = AXP15060_IRQ2_STATE, + .cache_type = REGCACHE_RBTREE, +}; + #define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask) \ [_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) } @@ -503,6 +543,23 @@ static const struct regmap_irq axp809_regmap_irqs[] = { INIT_REGMAP_IRQ(AXP809, GPIO0_INPUT, 4, 0), }; +static const struct regmap_irq axp15060_regmap_irqs[] = { + INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV1, 0, 0), + INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV2, 0, 1), + INIT_REGMAP_IRQ(AXP15060, DCDC1_V_LOW, 0, 2), + INIT_REGMAP_IRQ(AXP15060, DCDC2_V_LOW, 0, 3), + INIT_REGMAP_IRQ(AXP15060, DCDC3_V_LOW, 0, 4), + INIT_REGMAP_IRQ(AXP15060, DCDC4_V_LOW, 0, 5), + INIT_REGMAP_IRQ(AXP15060, DCDC5_V_LOW, 0, 6), + INIT_REGMAP_IRQ(AXP15060, DCDC6_V_LOW, 0, 7), + INIT_REGMAP_IRQ(AXP15060, PEK_LONG, 1, 0), + INIT_REGMAP_IRQ(AXP15060, PEK_SHORT, 1, 1), + INIT_REGMAP_IRQ(AXP15060, GPIO1_INPUT, 1, 2), + INIT_REGMAP_IRQ(AXP15060, PEK_FAL_EDGE, 1, 3), + INIT_REGMAP_IRQ(AXP15060, PEK_RIS_EDGE, 1, 4), + INIT_REGMAP_IRQ(AXP15060, GPIO2_INPUT, 1, 5), +}; + static const struct regmap_irq_chip axp152_regmap_irq_chip = { .name = "axp152_irq_chip", .status_base = AXP152_IRQ1_STATE, @@ -582,6 +639,17 @@ static const struct regmap_irq_chip axp809_regmap_irq_chip = { .num_regs = 5, }; +static const struct regmap_irq_chip axp15060_regmap_irq_chip = { + .name = "axp15060", + .status_base = AXP15060_IRQ1_STATE, + .ack_base = AXP15060_IRQ1_STATE, + .unmask_base = AXP15060_IRQ1_EN, + .init_ack_masked = true, + .irqs = axp15060_regmap_irqs, + .num_irqs = ARRAY_SIZE(axp15060_regmap_irqs), + .num_regs = 2, +}; + static const struct mfd_cell axp20x_cells[] = { { .name = "axp20x-gpio", @@ -826,6 +894,23 @@ static const struct mfd_cell axp813_cells[] = { }, }; +static const struct mfd_cell axp15060_cells[] = { + { + .name = "axp221-pek", + .num_resources = ARRAY_SIZE(axp15060_pek_resources), + .resources = axp15060_pek_resources, + }, { + .name = "axp20x-regulator", + }, +}; + +/* For boards that don't have IRQ line connected to SOC. */ +static const struct mfd_cell axp_regulator_only_cells[] = { + { + .name = "axp20x-regulator", + }, +}; + static int axp20x_power_off(struct sys_off_data *data) { struct axp20x_dev *axp20x = data->cb_data; @@ -935,6 +1020,28 @@ int axp20x_match_device(struct axp20x_dev *axp20x) */ axp20x->regmap_irq_chip = &axp803_regmap_irq_chip; break; + case AXP15060_ID: + /* + * Don't register the power key part if there is no interrupt + * line. + * + * Since most use cases of AXP PMICs are Allwinner SOCs, board + * designers follow Allwinner's reference design and connects + * IRQ line to SOC, there's no need for those variants to deal + * with cases that IRQ isn't connected. However, AXP15660 is + * used by some other vendors' SOCs that didn't connect IRQ + * line, we need to deal with this case. + */ + if (axp20x->irq > 0) { + axp20x->nr_cells = ARRAY_SIZE(axp15060_cells); + axp20x->cells = axp15060_cells; + } else { + axp20x->nr_cells = ARRAY_SIZE(axp_regulator_only_cells); + axp20x->cells = axp_regulator_only_cells; + } + axp20x->regmap_cfg = &axp15060_regmap_config; + axp20x->regmap_irq_chip = &axp15060_regmap_irq_chip; + break; default: dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant); return -EINVAL; diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h index 2058194807bd..beb3f44f85c5 100644 --- a/include/linux/mfd/axp20x.h +++ b/include/linux/mfd/axp20x.h @@ -21,6 +21,7 @@ enum axp20x_variants { AXP806_ID, AXP809_ID, AXP813_ID, + AXP15060_ID, NR_AXP20X_VARIANTS, }; @@ -131,6 +132,39 @@ enum axp20x_variants { /* Other DCDC regulator control registers are the same as AXP803 */ #define AXP813_DCDC7_V_OUT 0x26 +#define AXP15060_STARTUP_SRC 0x00 +#define AXP15060_PWR_OUT_CTRL1 0x10 +#define AXP15060_PWR_OUT_CTRL2 0x11 +#define AXP15060_PWR_OUT_CTRL3 0x12 +#define AXP15060_DCDC1_V_CTRL 0x13 +#define AXP15060_DCDC2_V_CTRL 0x14 +#define AXP15060_DCDC3_V_CTRL 0x15 +#define AXP15060_DCDC4_V_CTRL 0x16 +#define AXP15060_DCDC5_V_CTRL 0x17 +#define AXP15060_DCDC6_V_CTRL 0x18 +#define AXP15060_ALDO1_V_CTRL 0x19 +#define AXP15060_DCDC_MODE_CTRL1 0x1a +#define AXP15060_DCDC_MODE_CTRL2 0x1b +#define AXP15060_OUTPUT_MONITOR_DISCHARGE 0x1e +#define AXP15060_IRQ_PWROK_VOFF 0x1f +#define AXP15060_ALDO2_V_CTRL 0x20 +#define AXP15060_ALDO3_V_CTRL 0x21 +#define AXP15060_ALDO4_V_CTRL 0x22 +#define AXP15060_ALDO5_V_CTRL 0x23 +#define AXP15060_BLDO1_V_CTRL 0x24 +#define AXP15060_BLDO2_V_CTRL 0x25 +#define AXP15060_BLDO3_V_CTRL 0x26 +#define AXP15060_BLDO4_V_CTRL 0x27 +#define AXP15060_BLDO5_V_CTRL 0x28 +#define AXP15060_CLDO1_V_CTRL 0x29 +#define AXP15060_CLDO2_V_CTRL 0x2a +#define AXP15060_CLDO3_V_CTRL 0x2b +#define AXP15060_CLDO4_V_CTRL 0x2d +#define AXP15060_CPUSLDO_V_CTRL 0x2e +#define AXP15060_PWR_WAKEUP_CTRL 0x31 +#define AXP15060_PWR_DISABLE_DOWN_SEQ 0x32 +#define AXP15060_PEK_KEY 0x36 + /* Interrupt */ #define AXP152_IRQ1_EN 0x40 #define AXP152_IRQ2_EN 0x41 @@ -152,6 +186,11 @@ enum axp20x_variants { #define AXP20X_IRQ5_STATE 0x4c #define AXP20X_IRQ6_STATE 0x4d +#define AXP15060_IRQ1_EN 0x40 +#define AXP15060_IRQ2_EN 0x41 +#define AXP15060_IRQ1_STATE 0x48 +#define AXP15060_IRQ2_STATE 0x49 + /* ADC */ #define AXP20X_ACIN_V_ADC_H 0x56 #define AXP20X_ACIN_V_ADC_L 0x57 @@ -222,6 +261,8 @@ enum axp20x_variants { #define AXP22X_GPIO_STATE 0x94 #define AXP22X_GPIO_PULL_DOWN 0x95 +#define AXP15060_CLDO4_GPIO2_MODESET 0x2c + /* Battery */ #define AXP20X_CHRG_CC_31_24 0xb0 #define AXP20X_CHRG_CC_23_16 0xb1 @@ -419,6 +460,33 @@ enum { AXP813_REG_ID_MAX, }; +enum { + AXP15060_DCDC1 = 0, + AXP15060_DCDC2, + AXP15060_DCDC3, + AXP15060_DCDC4, + AXP15060_DCDC5, + AXP15060_DCDC6, + AXP15060_ALDO1, + AXP15060_ALDO2, + AXP15060_ALDO3, + AXP15060_ALDO4, + AXP15060_ALDO5, + AXP15060_BLDO1, + AXP15060_BLDO2, + AXP15060_BLDO3, + AXP15060_BLDO4, + AXP15060_BLDO5, + AXP15060_CLDO1, + AXP15060_CLDO2, + AXP15060_CLDO3, + AXP15060_CLDO4, + AXP15060_CPUSLDO, + AXP15060_SW, + AXP15060_RTC_LDO, + AXP15060_REG_ID_MAX, +}; + /* IRQs */ enum { AXP152_IRQ_LDO0IN_CONNECT = 1, @@ -637,6 +705,23 @@ enum axp809_irqs { AXP809_IRQ_GPIO0_INPUT, }; +enum axp15060_irqs { + AXP15060_IRQ_DIE_TEMP_HIGH_LV1 = 1, + AXP15060_IRQ_DIE_TEMP_HIGH_LV2, + AXP15060_IRQ_DCDC1_V_LOW, + AXP15060_IRQ_DCDC2_V_LOW, + AXP15060_IRQ_DCDC3_V_LOW, + AXP15060_IRQ_DCDC4_V_LOW, + AXP15060_IRQ_DCDC5_V_LOW, + AXP15060_IRQ_DCDC6_V_LOW, + AXP15060_IRQ_PEK_LONG, + AXP15060_IRQ_PEK_SHORT, + AXP15060_IRQ_GPIO1_INPUT, + AXP15060_IRQ_PEK_FAL_EDGE, + AXP15060_IRQ_PEK_RIS_EDGE, + AXP15060_IRQ_GPIO2_INPUT, +}; + struct axp20x_dev { struct device *dev; int irq; -- cgit v1.2.3 From 34480c6e1746138880778af9b86e86a95e0264fb Mon Sep 17 00:00:00 2001 From: Shengyu Qu Date: Fri, 21 Apr 2023 23:08:14 +0800 Subject: dt-bindings: mfd: x-powers,axp152: Document the AXP15060 variant The X-Powers AXP15060 is a PMIC seen on Starfive Visionfive 2 board. Add relative compatible item and CPUSLDO support and disables DC-DC frequency setting for it. Signed-off-by: Shengyu Qu Reviewed-by: Krzysztof Kozlowski Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/TY3P286MB261177CF7AA2959BD9517DA998609@TY3P286MB2611.JPNP286.PROD.OUTLOOK.COM --- Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml b/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml index ed76b1c58cdf..9234df27c6aa 100644 --- a/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml +++ b/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml @@ -77,7 +77,9 @@ allOf: properties: compatible: contains: - const: x-powers,axp313a + enum: + - x-powers,axp313a + - x-powers,axp15060 then: properties: @@ -97,6 +99,7 @@ properties: - x-powers,axp806 - x-powers,axp809 - x-powers,axp813 + - x-powers,axp15060 - items: - const: x-powers,axp228 - const: x-powers,axp221 @@ -265,7 +268,7 @@ properties: Defines the work frequency of DC-DC in kHz. patternProperties: - "^(([a-f])?ldo[0-9]|dcdc[0-7a-e]|ldo(_|-)io(0|1)|(dc1)?sw|rtc(_|-)ldo|drivevbus|dc5ldo)$": + "^(([a-f])?ldo[0-9]|dcdc[0-7a-e]|ldo(_|-)io(0|1)|(dc1)?sw|rtc(_|-)ldo|cpusldo|drivevbus|dc5ldo)$": $ref: /schemas/regulator/regulator.yaml# type: object unevaluatedProperties: false -- cgit v1.2.3 From 9f0184ac1dcb48efe724ec6482f88d85579b52df Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 16 Apr 2023 14:32:03 +0200 Subject: dt-bindings: mfd: qcom,spmi-pmic: Document flash LED controller The Qualcomm SPMI PMIC come also with a LED controller for flash LEDs, already used in DTS: sm8250-hdk.dtb: pmic@5: 'led-controller@d300' does not match any of the regexes: ... From schema: Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml Signed-off-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230416123203.299740-1-krzysztof.kozlowski@linaro.org --- Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml index 9f4c75c35aae..36de335a33aa 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml +++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml @@ -138,6 +138,10 @@ patternProperties: type: object $ref: /schemas/pinctrl/qcom,pmic-gpio.yaml# + "^led-controller@[0-9a-f]+$": + type: object + $ref: /schemas/leds/qcom,spmi-flash-led.yaml# + "^nvram@[0-9a-f]+$": type: object $ref: /schemas/nvmem/qcom,spmi-sdam.yaml# -- cgit v1.2.3 From 3808b8424b476ceb8ac7610ff3bb377ad1893847 Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Wed, 19 Apr 2023 13:18:06 +0200 Subject: leds: bd2606mvv: Driver for the Rohm 6 Channel i2c LED driver The device provides 6 channels which can be individually turned off and on but groups of two channels share a common brightness register. Limitation: The GPIO to enable the device is not used yet. Signed-off-by: Andreas Kemnade Reviewed-by: Matti Vaittinen Acked-by: Pavel Machek Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230419111806.1100437-3-andreas@kemnade.info --- drivers/leds/Kconfig | 14 ++++ drivers/leds/Makefile | 1 + drivers/leds/leds-bd2606mvv.c | 160 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 175 insertions(+) create mode 100644 drivers/leds/leds-bd2606mvv.c diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 9dbce09eabac..09afc56f54f1 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -551,6 +551,20 @@ config LEDS_REGULATOR help This option enables support for regulator driven LEDs. +config LEDS_BD2606MVV + tristate "LED driver for BD2606MVV" + depends on LEDS_CLASS + depends on I2C + select REGMAP_I2C + help + This option enables support for BD2606MVV LED driver chips + accessed via the I2C bus. It supports setting brightness, with + the limitiation that there are groups of two channels sharing + a brightness setting, but not the on/off setting. + + To compile this driver as a module, choose M here: the module will + be called leds-bd2606mvv. + config LEDS_BD2802 tristate "LED driver for BD2802 RGB LED" depends on LEDS_CLASS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index d30395d11fd8..c07d1512c745 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_LEDS_ARIEL) += leds-ariel.o obj-$(CONFIG_LEDS_AW2013) += leds-aw2013.o obj-$(CONFIG_LEDS_BCM6328) += leds-bcm6328.o obj-$(CONFIG_LEDS_BCM6358) += leds-bcm6358.o +obj-$(CONFIG_LEDS_BD2606MVV) += leds-bd2606mvv.o obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o obj-$(CONFIG_LEDS_BLINKM) += leds-blinkm.o obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o diff --git a/drivers/leds/leds-bd2606mvv.c b/drivers/leds/leds-bd2606mvv.c new file mode 100644 index 000000000000..76f9d4d70f9a --- /dev/null +++ b/drivers/leds/leds-bd2606mvv.c @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2023 Andreas Kemnade + * + * Datasheet: + * https://fscdn.rohm.com/en/products/databook/datasheet/ic/power/led_driver/bd2606mvv_1-e.pdf + * + * If LED brightness cannot be controlled independently due to shared + * brightness registers, max_brightness is set to 1 and only on/off + * is possible for the affected LED pair. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define BD2606_MAX_LEDS 6 +#define BD2606_MAX_BRIGHTNESS 63 +#define BD2606_REG_PWRCNT 3 +#define ldev_to_led(c) container_of(c, struct bd2606mvv_led, ldev) + +struct bd2606mvv_led { + unsigned int led_no; + struct led_classdev ldev; + struct bd2606mvv_priv *priv; +}; + +struct bd2606mvv_priv { + struct bd2606mvv_led leds[BD2606_MAX_LEDS]; + struct regmap *regmap; +}; + +static int +bd2606mvv_brightness_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct bd2606mvv_led *led = ldev_to_led(led_cdev); + struct bd2606mvv_priv *priv = led->priv; + int err; + + if (brightness == 0) + return regmap_update_bits(priv->regmap, + BD2606_REG_PWRCNT, + 1 << led->led_no, + 0); + + /* shared brightness register */ + err = regmap_write(priv->regmap, led->led_no / 2, + led_cdev->max_brightness == 1 ? + BD2606_MAX_BRIGHTNESS : brightness); + if (err) + return err; + + return regmap_update_bits(priv->regmap, + BD2606_REG_PWRCNT, + 1 << led->led_no, + 1 << led->led_no); +} + +static const struct regmap_config bd2606mvv_regmap = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0x3, +}; + +static int bd2606mvv_probe(struct i2c_client *client) +{ + struct fwnode_handle *np, *child; + struct device *dev = &client->dev; + struct bd2606mvv_priv *priv; + struct fwnode_handle *led_fwnodes[BD2606_MAX_LEDS] = { 0 }; + int active_pairs[BD2606_MAX_LEDS / 2] = { 0 }; + int err, reg; + int i; + + np = dev_fwnode(dev); + if (!np) + return -ENODEV; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->regmap = devm_regmap_init_i2c(client, &bd2606mvv_regmap); + if (IS_ERR(priv->regmap)) { + err = PTR_ERR(priv->regmap); + dev_err(dev, "Failed to allocate register map: %d\n", err); + return err; + } + + i2c_set_clientdata(client, priv); + + fwnode_for_each_available_child_node(np, child) { + struct bd2606mvv_led *led; + + err = fwnode_property_read_u32(child, "reg", ®); + if (err) { + fwnode_handle_put(child); + return err; + } + if (reg < 0 || reg >= BD2606_MAX_LEDS || led_fwnodes[reg]) { + fwnode_handle_put(child); + return -EINVAL; + } + led = &priv->leds[reg]; + led_fwnodes[reg] = child; + active_pairs[reg / 2]++; + led->priv = priv; + led->led_no = reg; + led->ldev.brightness_set_blocking = bd2606mvv_brightness_set; + led->ldev.max_brightness = BD2606_MAX_BRIGHTNESS; + } + + for (i = 0; i < BD2606_MAX_LEDS; i++) { + struct led_init_data init_data = {}; + + if (!led_fwnodes[i]) + continue; + + init_data.fwnode = led_fwnodes[i]; + /* Check whether brightness can be independently adjusted. */ + if (active_pairs[i / 2] == 2) + priv->leds[i].ldev.max_brightness = 1; + + err = devm_led_classdev_register_ext(dev, + &priv->leds[i].ldev, + &init_data); + if (err < 0) { + fwnode_handle_put(child); + return dev_err_probe(dev, err, + "couldn't register LED %s\n", + priv->leds[i].ldev.name); + } + } + return 0; +} + +static const struct of_device_id __maybe_unused of_bd2606mvv_leds_match[] = { + { .compatible = "rohm,bd2606mvv", }, + {}, +}; +MODULE_DEVICE_TABLE(of, of_bd2606mvv_leds_match); + +static struct i2c_driver bd2606mvv_driver = { + .driver = { + .name = "leds-bd2606mvv", + .of_match_table = of_match_ptr(of_bd2606mvv_leds_match), + }, + .probe_new = bd2606mvv_probe, +}; + +module_i2c_driver(bd2606mvv_driver); + +MODULE_AUTHOR("Andreas Kemnade "); +MODULE_DESCRIPTION("BD2606 LED driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 9e9ff39243ea8795a4833708613f884b39dc91f9 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Mon, 17 Apr 2023 20:00:19 -0500 Subject: dt-bindings: mfd: ti,j721e-system-controller: Add SoC chip ID The system-controller node also contains the chip-id node that is used to identify the SoC specific properties. Add a pattern property to match to the same, and add to the example. Signed-off-by: Nishanth Menon Acked-by: Krzysztof Kozlowski Reviewed-by: Roger Quadros Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20230418010019.1222431-1-nm@ti.com --- .../devicetree/bindings/mfd/ti,j721e-system-controller.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Documentation/devicetree/bindings/mfd/ti,j721e-system-controller.yaml b/Documentation/devicetree/bindings/mfd/ti,j721e-system-controller.yaml index 76ef4352e13c..0c98d913747b 100644 --- a/Documentation/devicetree/bindings/mfd/ti,j721e-system-controller.yaml +++ b/Documentation/devicetree/bindings/mfd/ti,j721e-system-controller.yaml @@ -62,6 +62,12 @@ patternProperties: description: The phy node corresponding to the ethernet MAC. + "^chipid@[0-9a-f]+$": + type: object + $ref: /schemas/hwinfo/ti,k3-socinfo.yaml# + description: + The node corresponding to SoC chip identification. + required: - compatible - reg @@ -99,5 +105,10 @@ examples: reg = <0x4140 0x18>; #clock-cells = <1>; }; + + chipid@14 { + compatible = "ti,am654-chipid"; + reg = <0x14 0x4>; + }; }; ... -- cgit v1.2.3