Re: [PATCH v4 06/10] mfd: Add support for the MediaTek MT6358 PMIC
Hi, On Mon, 2019-08-12 at 11:59 +0100, Lee Jones wrote: > On Mon, 05 Aug 2019, Hsin-Hsiung Wang wrote: > > > This adds support for the MediaTek MT6358 PMIC. This is a > > multifunction device with the following sub modules: > > > > - Regulator > > - RTC > > - Codec > > - Interrupt > > > > It is interfaced to the host controller using SPI interface > > by a proprietary hardware called PMIC wrapper or pwrap. > > MT6358 MFD is a child device of the pwrap. > > > > Signed-off-by: Hsin-Hsiung Wang > > --- > > drivers/mfd/Makefile | 3 +- > > drivers/mfd/mt6358-irq.c | 229 > > drivers/mfd/mt6397-core.c| 52 ++- > > include/linux/mfd/mt6358/core.h | 158 > > include/linux/mfd/mt6358/registers.h | 282 > > +++ > > include/linux/mfd/mt6397/core.h | 3 + > > 6 files changed, 725 insertions(+), 2 deletions(-) > > create mode 100644 drivers/mfd/mt6358-irq.c > > create mode 100644 include/linux/mfd/mt6358/core.h > > create mode 100644 include/linux/mfd/mt6358/registers.h > > > > diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile > > index 9a96325..36d088b 100644 > > --- a/drivers/mfd/Makefile > > +++ b/drivers/mfd/Makefile > > @@ -241,7 +241,8 @@ obj-$(CONFIG_INTEL_SOC_PMIC)+= intel-soc-pmic.o > > obj-$(CONFIG_INTEL_SOC_PMIC_BXTWC) += intel_soc_pmic_bxtwc.o > > obj-$(CONFIG_INTEL_SOC_PMIC_CHTWC) += intel_soc_pmic_chtwc.o > > obj-$(CONFIG_INTEL_SOC_PMIC_CHTDC_TI) += intel_soc_pmic_chtdc_ti.o > > -mt6397-objs:= mt6397-core.o mt6397-irq.o > > + > > +mt6397-objs:= mt6397-core.o mt6397-irq.o > > mt6358-irq.o > > obj-$(CONFIG_MFD_MT6397) += mt6397.o > > > > obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o > > diff --git a/drivers/mfd/mt6358-irq.c b/drivers/mfd/mt6358-irq.c > > new file mode 100644 > > index 000..2f55079 > > --- /dev/null > > +++ b/drivers/mfd/mt6358-irq.c > > @@ -0,0 +1,229 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +// > > +// Copyright (c) 2019 MediaTek Inc. > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > [...] > > > +static void pmic_irq_sync_unlock(struct irq_data *data) > > +{ > > + unsigned int i, top_gp, en_reg, int_regs, shift; > > + struct mt6397_chip *chip = irq_data_get_irq_chip_data(data); > > + struct pmic_irq_data *irqd = chip->irq_data; > > + > > + for (i = 0; i < irqd->num_pmic_irqs; i++) { > > + if (irqd->enable_hwirq[i] == irqd->cache_hwirq[i]) > > + continue; > > + > > + top_gp = 0; > > + while ((top_gp + 1) < ARRAY_SIZE(mt6358_ints) && > > + i >= mt6358_ints[top_gp + 1].hwirq_base) > > + top_gp++; > > A comment here would make this easier to follow. > I will add it in next version. > > + if (top_gp >= ARRAY_SIZE(mt6358_ints)) { > > + mutex_unlock(>irqlock); > > + dev_err(chip->dev, > > + "Failed to get top_group: %d\n", top_gp); > > + return; > > + } > > + > > + int_regs = (i - mt6358_ints[top_gp].hwirq_base) / > > + MT6358_REG_WIDTH; > > + en_reg = mt6358_ints[top_gp].en_reg + > > + mt6358_ints[top_gp].en_reg_shift * int_regs; > > + shift = (i - mt6358_ints[top_gp].hwirq_base) % MT6358_REG_WIDTH; > > + regmap_update_bits(chip->regmap, en_reg, BIT(shift), > > + irqd->enable_hwirq[i] << shift); > > + irqd->cache_hwirq[i] = irqd->enable_hwirq[i]; > > + } > > + mutex_unlock(>irqlock); > > +} > > [...] > > > +int mt6358_irq_init(struct mt6397_chip *chip) > > +{ > > + int i, j, ret; > > + struct pmic_irq_data *irqd; > > + > > + irqd = devm_kzalloc(chip->dev, sizeof(struct pmic_irq_data *), > > + GFP_KERNEL); > > + if (!irqd) > > + return -ENOMEM; > > + > > + chip->irq_data = irqd; > > + > > + mutex_init(>irqlock); > > + irqd->top_int_status_reg = MT6358_TOP_INT_STATUS0; > > + irqd->num_pmic_irqs = MT6358_IRQ_NR; > > + irqd->num_top = ARRAY_SIZE(mt6358_ints); > > + > > + irqd->enable_hwirq = devm_kcalloc(chip->dev, > > + irqd->num_pmic_irqs, > > + sizeof(bool), > > + GFP_KERNEL); > > + if (!irqd->enable_hwirq) > > + return -ENOMEM; > > + > > + irqd->cache_hwirq = devm_kcalloc(chip->dev, > > +irqd->num_pmic_irqs, > > +sizeof(bool), > > +GFP_KERNEL); > > + if (!irqd->cache_hwirq) > > + return -ENOMEM; > > + > > + /* Disable all interrupt for initializing */ > >
Re: [PATCH v4 06/10] mfd: Add support for the MediaTek MT6358 PMIC
On Mon, 05 Aug 2019, Hsin-Hsiung Wang wrote: > This adds support for the MediaTek MT6358 PMIC. This is a > multifunction device with the following sub modules: > > - Regulator > - RTC > - Codec > - Interrupt > > It is interfaced to the host controller using SPI interface > by a proprietary hardware called PMIC wrapper or pwrap. > MT6358 MFD is a child device of the pwrap. > > Signed-off-by: Hsin-Hsiung Wang > --- > drivers/mfd/Makefile | 3 +- > drivers/mfd/mt6358-irq.c | 229 > drivers/mfd/mt6397-core.c| 52 ++- > include/linux/mfd/mt6358/core.h | 158 > include/linux/mfd/mt6358/registers.h | 282 > +++ > include/linux/mfd/mt6397/core.h | 3 + > 6 files changed, 725 insertions(+), 2 deletions(-) > create mode 100644 drivers/mfd/mt6358-irq.c > create mode 100644 include/linux/mfd/mt6358/core.h > create mode 100644 include/linux/mfd/mt6358/registers.h > > diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile > index 9a96325..36d088b 100644 > --- a/drivers/mfd/Makefile > +++ b/drivers/mfd/Makefile > @@ -241,7 +241,8 @@ obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o > obj-$(CONFIG_INTEL_SOC_PMIC_BXTWC) += intel_soc_pmic_bxtwc.o > obj-$(CONFIG_INTEL_SOC_PMIC_CHTWC) += intel_soc_pmic_chtwc.o > obj-$(CONFIG_INTEL_SOC_PMIC_CHTDC_TI)+= intel_soc_pmic_chtdc_ti.o > -mt6397-objs := mt6397-core.o mt6397-irq.o > + > +mt6397-objs := mt6397-core.o mt6397-irq.o mt6358-irq.o > obj-$(CONFIG_MFD_MT6397) += mt6397.o > > obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o > diff --git a/drivers/mfd/mt6358-irq.c b/drivers/mfd/mt6358-irq.c > new file mode 100644 > index 000..2f55079 > --- /dev/null > +++ b/drivers/mfd/mt6358-irq.c > @@ -0,0 +1,229 @@ > +// SPDX-License-Identifier: GPL-2.0 > +// > +// Copyright (c) 2019 MediaTek Inc. > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include [...] > +static void pmic_irq_sync_unlock(struct irq_data *data) > +{ > + unsigned int i, top_gp, en_reg, int_regs, shift; > + struct mt6397_chip *chip = irq_data_get_irq_chip_data(data); > + struct pmic_irq_data *irqd = chip->irq_data; > + > + for (i = 0; i < irqd->num_pmic_irqs; i++) { > + if (irqd->enable_hwirq[i] == irqd->cache_hwirq[i]) > + continue; > + > + top_gp = 0; > + while ((top_gp + 1) < ARRAY_SIZE(mt6358_ints) && > +i >= mt6358_ints[top_gp + 1].hwirq_base) > + top_gp++; A comment here would make this easier to follow. > + if (top_gp >= ARRAY_SIZE(mt6358_ints)) { > + mutex_unlock(>irqlock); > + dev_err(chip->dev, > + "Failed to get top_group: %d\n", top_gp); > + return; > + } > + > + int_regs = (i - mt6358_ints[top_gp].hwirq_base) / > + MT6358_REG_WIDTH; > + en_reg = mt6358_ints[top_gp].en_reg + > + mt6358_ints[top_gp].en_reg_shift * int_regs; > + shift = (i - mt6358_ints[top_gp].hwirq_base) % MT6358_REG_WIDTH; > + regmap_update_bits(chip->regmap, en_reg, BIT(shift), > +irqd->enable_hwirq[i] << shift); > + irqd->cache_hwirq[i] = irqd->enable_hwirq[i]; > + } > + mutex_unlock(>irqlock); > +} [...] > +int mt6358_irq_init(struct mt6397_chip *chip) > +{ > + int i, j, ret; > + struct pmic_irq_data *irqd; > + > + irqd = devm_kzalloc(chip->dev, sizeof(struct pmic_irq_data *), > + GFP_KERNEL); > + if (!irqd) > + return -ENOMEM; > + > + chip->irq_data = irqd; > + > + mutex_init(>irqlock); > + irqd->top_int_status_reg = MT6358_TOP_INT_STATUS0; > + irqd->num_pmic_irqs = MT6358_IRQ_NR; > + irqd->num_top = ARRAY_SIZE(mt6358_ints); > + > + irqd->enable_hwirq = devm_kcalloc(chip->dev, > + irqd->num_pmic_irqs, > + sizeof(bool), > + GFP_KERNEL); > + if (!irqd->enable_hwirq) > + return -ENOMEM; > + > + irqd->cache_hwirq = devm_kcalloc(chip->dev, > + irqd->num_pmic_irqs, > + sizeof(bool), > + GFP_KERNEL); > + if (!irqd->cache_hwirq) > + return -ENOMEM; > + > + /* Disable all interrupt for initializing */ s/interrupt/interrupts/ > + for (i = 0; i < irqd->num_top; i++) { > + for (j = 0; j < mt6358_ints[i].num_int_regs; j++) > + regmap_write(chip->regmap, > + mt6358_ints[i].en_reg + > +
[PATCH v4 06/10] mfd: Add support for the MediaTek MT6358 PMIC
This adds support for the MediaTek MT6358 PMIC. This is a multifunction device with the following sub modules: - Regulator - RTC - Codec - Interrupt It is interfaced to the host controller using SPI interface by a proprietary hardware called PMIC wrapper or pwrap. MT6358 MFD is a child device of the pwrap. Signed-off-by: Hsin-Hsiung Wang --- drivers/mfd/Makefile | 3 +- drivers/mfd/mt6358-irq.c | 229 drivers/mfd/mt6397-core.c| 52 ++- include/linux/mfd/mt6358/core.h | 158 include/linux/mfd/mt6358/registers.h | 282 +++ include/linux/mfd/mt6397/core.h | 3 + 6 files changed, 725 insertions(+), 2 deletions(-) create mode 100644 drivers/mfd/mt6358-irq.c create mode 100644 include/linux/mfd/mt6358/core.h create mode 100644 include/linux/mfd/mt6358/registers.h diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 9a96325..36d088b 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -241,7 +241,8 @@ obj-$(CONFIG_INTEL_SOC_PMIC)+= intel-soc-pmic.o obj-$(CONFIG_INTEL_SOC_PMIC_BXTWC) += intel_soc_pmic_bxtwc.o obj-$(CONFIG_INTEL_SOC_PMIC_CHTWC) += intel_soc_pmic_chtwc.o obj-$(CONFIG_INTEL_SOC_PMIC_CHTDC_TI) += intel_soc_pmic_chtdc_ti.o -mt6397-objs:= mt6397-core.o mt6397-irq.o + +mt6397-objs:= mt6397-core.o mt6397-irq.o mt6358-irq.o obj-$(CONFIG_MFD_MT6397) += mt6397.o obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o diff --git a/drivers/mfd/mt6358-irq.c b/drivers/mfd/mt6358-irq.c new file mode 100644 index 000..2f55079 --- /dev/null +++ b/drivers/mfd/mt6358-irq.c @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2019 MediaTek Inc. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct irq_top_t mt6358_ints[] = { + MT6358_TOP_GEN(BUCK), + MT6358_TOP_GEN(LDO), + MT6358_TOP_GEN(PSC), + MT6358_TOP_GEN(SCK), + MT6358_TOP_GEN(BM), + MT6358_TOP_GEN(HK), + MT6358_TOP_GEN(AUD), + MT6358_TOP_GEN(MISC), +}; + +static void pmic_irq_enable(struct irq_data *data) +{ + unsigned int hwirq = irqd_to_hwirq(data); + struct mt6397_chip *chip = irq_data_get_irq_chip_data(data); + struct pmic_irq_data *irqd = chip->irq_data; + + irqd->enable_hwirq[hwirq] = true; +} + +static void pmic_irq_disable(struct irq_data *data) +{ + unsigned int hwirq = irqd_to_hwirq(data); + struct mt6397_chip *chip = irq_data_get_irq_chip_data(data); + struct pmic_irq_data *irqd = chip->irq_data; + + irqd->enable_hwirq[hwirq] = false; +} + +static void pmic_irq_lock(struct irq_data *data) +{ + struct mt6397_chip *chip = irq_data_get_irq_chip_data(data); + + mutex_lock(>irqlock); +} + +static void pmic_irq_sync_unlock(struct irq_data *data) +{ + unsigned int i, top_gp, en_reg, int_regs, shift; + struct mt6397_chip *chip = irq_data_get_irq_chip_data(data); + struct pmic_irq_data *irqd = chip->irq_data; + + for (i = 0; i < irqd->num_pmic_irqs; i++) { + if (irqd->enable_hwirq[i] == irqd->cache_hwirq[i]) + continue; + + top_gp = 0; + while ((top_gp + 1) < ARRAY_SIZE(mt6358_ints) && + i >= mt6358_ints[top_gp + 1].hwirq_base) + top_gp++; + + if (top_gp >= ARRAY_SIZE(mt6358_ints)) { + mutex_unlock(>irqlock); + dev_err(chip->dev, + "Failed to get top_group: %d\n", top_gp); + return; + } + + int_regs = (i - mt6358_ints[top_gp].hwirq_base) / + MT6358_REG_WIDTH; + en_reg = mt6358_ints[top_gp].en_reg + + mt6358_ints[top_gp].en_reg_shift * int_regs; + shift = (i - mt6358_ints[top_gp].hwirq_base) % MT6358_REG_WIDTH; + regmap_update_bits(chip->regmap, en_reg, BIT(shift), + irqd->enable_hwirq[i] << shift); + irqd->cache_hwirq[i] = irqd->enable_hwirq[i]; + } + mutex_unlock(>irqlock); +} + +static struct irq_chip mt6358_irq_chip = { + .name = "mt6358-irq", + .flags = IRQCHIP_SKIP_SET_WAKE, + .irq_enable = pmic_irq_enable, + .irq_disable = pmic_irq_disable, + .irq_bus_lock = pmic_irq_lock, + .irq_bus_sync_unlock = pmic_irq_sync_unlock, +}; + +static void mt6358_irq_sp_handler(struct mt6397_chip *chip, + unsigned int top_gp) +{ + unsigned int sta_reg, irq_status; + unsigned int hwirq, virq; + int ret, i, j; + + for (i = 0; i < mt6358_ints[top_gp].num_int_regs; i++) { + sta_reg = mt6358_ints[top_gp].sta_reg + +