Re: [PATCH v4 06/10] mfd: Add support for the MediaTek MT6358 PMIC

2019-08-22 Thread Hsin-hsiung Wang
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

2019-08-12 Thread Lee Jones
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

2019-08-04 Thread Hsin-Hsiung Wang
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 +
+