From: Hsin-hsiung Wang <hsin-hsiung.wang@mediatek.com>
To: Pi-Hsun Shih <pihsun@chromium.org>
Cc: Mark Rutland <mark.rutland@arm.com>,
Alessandro Zummo <a.zummo@towertech.it>,
Alexandre Belloni <alexandre.belloni@bootlin.com>,
srv_heupstream@mediatek.com,
"open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS"
<devicetree@vger.kernel.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Mark Brown <broonie@kernel.org>,
Sean Wang <sean.wang@mediatek.com>,
Liam Girdwood <lgirdwood@gmail.com>,
open list <linux-kernel@vger.kernel.org>,
Richard Fontana <rfontana@redhat.com>,
Rob Herring <robh+dt@kernel.org>,
"moderated list:ARM/Mediatek SoC support"
<linux-mediatek@lists.infradead.org>,
Kate Stewart <kstewart@linuxfoundation.org>,
Matthias Brugger <matthias.bgg@gmail.com>,
Thomas Gleixner <tglx@linutronix.de>,
Eddie Huang <eddie.huang@mediatek.com>,
Lee Jones <lee.jones@linaro.org>,
"moderated list:ARM/Mediatek SoC support"
<linux-arm-kernel@lists.infradead.org>,
"open list:REAL TIME CLOCK \(RTC\) SUBSYSTEM"
<linux-rtc@vger.kernel.org>
Subject: Re: [PATCH v5 06/10] mfd: Add support for the MediaTek MT6358 PMIC
Date: Fri, 6 Dec 2019 16:55:58 +0800 [thread overview]
Message-ID: <1575622558.17300.5.camel@mtksdaap41> (raw)
In-Reply-To: <CANdKZ0eUDhhQPBBiOWZ0u03SFoFQM6b=ED9AGe+JtBSr_zeJKQ@mail.gmail.com>
Hi,
On Mon, 2019-12-02 at 16:06 +0800, Pi-Hsun Shih wrote:
> Hi,
>
> On Fri, Aug 23, 2019 at 11:46 AM Hsin-Hsiung Wang
> <hsin-hsiung.wang@mediatek.com> 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 <hsin-hsiung.wang@mediatek.com>
> > ---
> > drivers/mfd/Makefile | 3 +-
> > drivers/mfd/mt6358-irq.c | 231 ++++++++++++++++++++++++++++
> > 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, 727 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/mt6358-irq.c b/drivers/mfd/mt6358-irq.c
> > new file mode 100644
> > index 0000000..760b72f
> > --- /dev/null
> > +++ b/drivers/mfd/mt6358-irq.c
> > @@ -0,0 +1,231 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// Copyright (c) 2019 MediaTek Inc.
...
> > +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;
> > +
> > + /* Find out the irq group */
> > + 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)) {
>
> Would this condition ever be true? The while loop before this always
> break when top_gp == ARRAY_SIZE(mt6358_ints) - 1.
>
Thanks for reviewing. I will remove this part in next patch.
> > + mutex_unlock(&chip->irqlock);
> > + dev_err(chip->dev,
> > + "Failed to get top_group: %d\n", top_gp);
> > + return;
> > + }
> > +
> > + /* Find the irq registers */
> > + 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(&chip->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 +
> > + mt6358_ints[top_gp].sta_reg_shift * i;
> > + ret = regmap_read(chip->regmap, sta_reg, &irq_status);
> > + if (ret) {
> > + dev_err(chip->dev,
> > + "Failed to read irq status: %d\n", ret);
> > + return;
> > + }
> > +
> > + if (!irq_status)
> > + continue;
> > +
> > + for (j = 0; j < MT6358_REG_WIDTH ; j++) {
> > + if ((irq_status & BIT(j)) == 0)
> > + continue;
> > + hwirq = mt6358_ints[top_gp].hwirq_base +
> > + MT6358_REG_WIDTH * i + j;
> > + virq = irq_find_mapping(chip->irq_domain, hwirq);
> > + if (virq)
> > + handle_nested_irq(virq);
> > + }
> > +
> > + regmap_write(chip->regmap, sta_reg, irq_status);
> > + }
> > +}
> > +
> > +static irqreturn_t mt6358_irq_handler(int irq, void *data)
> > +{
> > + struct mt6397_chip *chip = data;
> > + struct pmic_irq_data *mt6358_irq_data = chip->irq_data;
> > + unsigned int top_irq_status;
> > + unsigned int i;
> > + int ret;
> > +
> > + ret = regmap_read(chip->regmap,
> > + mt6358_irq_data->top_int_status_reg,
> > + &top_irq_status);
> > + if (ret) {
> > + dev_err(chip->dev, "Can't read TOP_INT_STATUS ret=%d\n", ret);
> > + return IRQ_NONE;
> > + }
> > +
> > + for (i = 0; i < mt6358_irq_data->num_top; i++) {
> > + if (top_irq_status & BIT(mt6358_ints[i].top_offset))
> > + mt6358_irq_sp_handler(chip, i);
> > + }
> > +
> > + return IRQ_HANDLED;
> > +}
> > +
> > +static int pmic_irq_domain_map(struct irq_domain *d, unsigned int irq,
> > + irq_hw_number_t hw)
> > +{
> > + struct mt6397_chip *mt6397 = d->host_data;
> > +
> > + irq_set_chip_data(irq, mt6397);
> > + irq_set_chip_and_handler(irq, &mt6358_irq_chip, handle_level_irq);
> > + irq_set_nested_thread(irq, 1);
> > + irq_set_noprobe(irq);
> > +
> > + return 0;
> > +}
> > +
> > +static const struct irq_domain_ops mt6358_irq_domain_ops = {
> > + .map = pmic_irq_domain_map,
> > + .xlate = irq_domain_xlate_twocell,
> > +};
> > +
> > +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(&chip->irqlock);
> > + irqd->top_int_status_reg = MT6358_TOP_INT_STATUS0;
> > + irqd->num_pmic_irqs = MT6358_IRQ_NR;
> > + irqd->num_top = ARRAY_SIZE(mt6358_ints);
>
> ARRAY_SIZE(mt6358_ints) is still used in pmic_irq_sync_unlock. Is this
> variable needed, or should the ARRAY_SIZE(mt6358_ints) in
> pmic_irq_sync_unlock be changed to irqd->num_top too?
>
I will update to irqd->num_top from ARRAY_SIZE(mt6358_ints) in
pmic_irq_sync_unlock.
> > +
> > + 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 interrupts for initializing */
> > + 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 +
> > + mt6358_ints[i].en_reg_shift * j, 0);
> > + }
> > +
> > + chip->irq_domain = irq_domain_add_linear(chip->dev->of_node,
> > + irqd->num_pmic_irqs,
> > + &mt6358_irq_domain_ops, chip);
> > + if (!chip->irq_domain) {
> > + dev_err(chip->dev, "could not create IRQ domain\n");
> > + return -ENODEV;
> > + }
> > +
> > + ret = devm_request_threaded_irq(chip->dev, chip->irq, NULL,
> > + mt6358_irq_handler, IRQF_ONESHOT,
> > + mt6358_irq_chip.name, chip);
> > + if (ret) {
> > + dev_err(chip->dev, "failed to register irq=%d; err: %d\n",
> > + chip->irq, ret);
> > + return ret;
> > + }
> > +
> > + enable_irq_wake(chip->irq);
> > + return ret;
> > +}
> > (...)
>
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
WARNING: multiple messages have this Message-ID (diff)
From: Hsin-hsiung Wang <hsin-hsiung.wang@mediatek.com>
To: Pi-Hsun Shih <pihsun@chromium.org>
Cc: Mark Rutland <mark.rutland@arm.com>,
Alessandro Zummo <a.zummo@towertech.it>,
Alexandre Belloni <alexandre.belloni@bootlin.com>,
<srv_heupstream@mediatek.com>,
"open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS"
<devicetree@vger.kernel.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Sean Wang <sean.wang@mediatek.com>,
"Liam Girdwood" <lgirdwood@gmail.com>,
Rob Herring <robh+dt@kernel.org>,
open list <linux-kernel@vger.kernel.org>,
Richard Fontana <rfontana@redhat.com>,
"Mark Brown" <broonie@kernel.org>,
"moderated list:ARM/Mediatek SoC support"
<linux-mediatek@lists.infradead.org>,
"moderated list:ARM/Mediatek SoC support"
<linux-arm-kernel@lists.infradead.org>,
Matthias Brugger <matthias.bgg@gmail.com>,
Thomas Gleixner <tglx@linutronix.de>,
Eddie Huang <eddie.huang@mediatek.com>,
Lee Jones <lee.jones@linaro.org>,
Kate Stewart <kstewart@linuxfoundation.org>,
"open list:REAL TIME CLOCK (RTC) SUBSYSTEM"
<linux-rtc@vger.kernel.org>
Subject: Re: [PATCH v5 06/10] mfd: Add support for the MediaTek MT6358 PMIC
Date: Fri, 6 Dec 2019 16:55:58 +0800 [thread overview]
Message-ID: <1575622558.17300.5.camel@mtksdaap41> (raw)
In-Reply-To: <CANdKZ0eUDhhQPBBiOWZ0u03SFoFQM6b=ED9AGe+JtBSr_zeJKQ@mail.gmail.com>
Hi,
On Mon, 2019-12-02 at 16:06 +0800, Pi-Hsun Shih wrote:
> Hi,
>
> On Fri, Aug 23, 2019 at 11:46 AM Hsin-Hsiung Wang
> <hsin-hsiung.wang@mediatek.com> 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 <hsin-hsiung.wang@mediatek.com>
> > ---
> > drivers/mfd/Makefile | 3 +-
> > drivers/mfd/mt6358-irq.c | 231 ++++++++++++++++++++++++++++
> > 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, 727 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/mt6358-irq.c b/drivers/mfd/mt6358-irq.c
> > new file mode 100644
> > index 0000000..760b72f
> > --- /dev/null
> > +++ b/drivers/mfd/mt6358-irq.c
> > @@ -0,0 +1,231 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// Copyright (c) 2019 MediaTek Inc.
...
> > +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;
> > +
> > + /* Find out the irq group */
> > + 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)) {
>
> Would this condition ever be true? The while loop before this always
> break when top_gp == ARRAY_SIZE(mt6358_ints) - 1.
>
Thanks for reviewing. I will remove this part in next patch.
> > + mutex_unlock(&chip->irqlock);
> > + dev_err(chip->dev,
> > + "Failed to get top_group: %d\n", top_gp);
> > + return;
> > + }
> > +
> > + /* Find the irq registers */
> > + 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(&chip->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 +
> > + mt6358_ints[top_gp].sta_reg_shift * i;
> > + ret = regmap_read(chip->regmap, sta_reg, &irq_status);
> > + if (ret) {
> > + dev_err(chip->dev,
> > + "Failed to read irq status: %d\n", ret);
> > + return;
> > + }
> > +
> > + if (!irq_status)
> > + continue;
> > +
> > + for (j = 0; j < MT6358_REG_WIDTH ; j++) {
> > + if ((irq_status & BIT(j)) == 0)
> > + continue;
> > + hwirq = mt6358_ints[top_gp].hwirq_base +
> > + MT6358_REG_WIDTH * i + j;
> > + virq = irq_find_mapping(chip->irq_domain, hwirq);
> > + if (virq)
> > + handle_nested_irq(virq);
> > + }
> > +
> > + regmap_write(chip->regmap, sta_reg, irq_status);
> > + }
> > +}
> > +
> > +static irqreturn_t mt6358_irq_handler(int irq, void *data)
> > +{
> > + struct mt6397_chip *chip = data;
> > + struct pmic_irq_data *mt6358_irq_data = chip->irq_data;
> > + unsigned int top_irq_status;
> > + unsigned int i;
> > + int ret;
> > +
> > + ret = regmap_read(chip->regmap,
> > + mt6358_irq_data->top_int_status_reg,
> > + &top_irq_status);
> > + if (ret) {
> > + dev_err(chip->dev, "Can't read TOP_INT_STATUS ret=%d\n", ret);
> > + return IRQ_NONE;
> > + }
> > +
> > + for (i = 0; i < mt6358_irq_data->num_top; i++) {
> > + if (top_irq_status & BIT(mt6358_ints[i].top_offset))
> > + mt6358_irq_sp_handler(chip, i);
> > + }
> > +
> > + return IRQ_HANDLED;
> > +}
> > +
> > +static int pmic_irq_domain_map(struct irq_domain *d, unsigned int irq,
> > + irq_hw_number_t hw)
> > +{
> > + struct mt6397_chip *mt6397 = d->host_data;
> > +
> > + irq_set_chip_data(irq, mt6397);
> > + irq_set_chip_and_handler(irq, &mt6358_irq_chip, handle_level_irq);
> > + irq_set_nested_thread(irq, 1);
> > + irq_set_noprobe(irq);
> > +
> > + return 0;
> > +}
> > +
> > +static const struct irq_domain_ops mt6358_irq_domain_ops = {
> > + .map = pmic_irq_domain_map,
> > + .xlate = irq_domain_xlate_twocell,
> > +};
> > +
> > +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(&chip->irqlock);
> > + irqd->top_int_status_reg = MT6358_TOP_INT_STATUS0;
> > + irqd->num_pmic_irqs = MT6358_IRQ_NR;
> > + irqd->num_top = ARRAY_SIZE(mt6358_ints);
>
> ARRAY_SIZE(mt6358_ints) is still used in pmic_irq_sync_unlock. Is this
> variable needed, or should the ARRAY_SIZE(mt6358_ints) in
> pmic_irq_sync_unlock be changed to irqd->num_top too?
>
I will update to irqd->num_top from ARRAY_SIZE(mt6358_ints) in
pmic_irq_sync_unlock.
> > +
> > + 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 interrupts for initializing */
> > + 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 +
> > + mt6358_ints[i].en_reg_shift * j, 0);
> > + }
> > +
> > + chip->irq_domain = irq_domain_add_linear(chip->dev->of_node,
> > + irqd->num_pmic_irqs,
> > + &mt6358_irq_domain_ops, chip);
> > + if (!chip->irq_domain) {
> > + dev_err(chip->dev, "could not create IRQ domain\n");
> > + return -ENODEV;
> > + }
> > +
> > + ret = devm_request_threaded_irq(chip->dev, chip->irq, NULL,
> > + mt6358_irq_handler, IRQF_ONESHOT,
> > + mt6358_irq_chip.name, chip);
> > + if (ret) {
> > + dev_err(chip->dev, "failed to register irq=%d; err: %d\n",
> > + chip->irq, ret);
> > + return ret;
> > + }
> > +
> > + enable_irq_wake(chip->irq);
> > + return ret;
> > +}
> > (...)
>
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek
WARNING: multiple messages have this Message-ID (diff)
From: Hsin-hsiung Wang <hsin-hsiung.wang@mediatek.com>
To: Pi-Hsun Shih <pihsun@chromium.org>
Cc: Mark Rutland <mark.rutland@arm.com>,
Alessandro Zummo <a.zummo@towertech.it>,
Alexandre Belloni <alexandre.belloni@bootlin.com>,
srv_heupstream@mediatek.com,
"open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS"
<devicetree@vger.kernel.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Mark Brown <broonie@kernel.org>,
Sean Wang <sean.wang@mediatek.com>,
Liam Girdwood <lgirdwood@gmail.com>,
open list <linux-kernel@vger.kernel.org>,
Richard Fontana <rfontana@redhat.com>,
Rob Herring <robh+dt@kernel.org>,
"moderated list:ARM/Mediatek SoC support"
<linux-mediatek@lists.infradead.org>,
Kate Stewart <kstewart@linuxfoundation.org>,
Matthias Brugger <matthias.bgg@gmail.com>,
Thomas Gleixner <tglx@linutronix.de>,
Eddie Huang <eddie.huang@mediatek.com>,
Lee Jones <lee.jones@linaro.org>,
"moderated list:ARM/Mediatek SoC support"
<linux-arm-kernel@lists.infradead.org>,
"open list:REAL TIME CLOCK \(RTC\) SUBSYSTEM"
<linux-rtc@vger.kernel.org>
Subject: Re: [PATCH v5 06/10] mfd: Add support for the MediaTek MT6358 PMIC
Date: Fri, 6 Dec 2019 16:55:58 +0800 [thread overview]
Message-ID: <1575622558.17300.5.camel@mtksdaap41> (raw)
In-Reply-To: <CANdKZ0eUDhhQPBBiOWZ0u03SFoFQM6b=ED9AGe+JtBSr_zeJKQ@mail.gmail.com>
Hi,
On Mon, 2019-12-02 at 16:06 +0800, Pi-Hsun Shih wrote:
> Hi,
>
> On Fri, Aug 23, 2019 at 11:46 AM Hsin-Hsiung Wang
> <hsin-hsiung.wang@mediatek.com> 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 <hsin-hsiung.wang@mediatek.com>
> > ---
> > drivers/mfd/Makefile | 3 +-
> > drivers/mfd/mt6358-irq.c | 231 ++++++++++++++++++++++++++++
> > 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, 727 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/mt6358-irq.c b/drivers/mfd/mt6358-irq.c
> > new file mode 100644
> > index 0000000..760b72f
> > --- /dev/null
> > +++ b/drivers/mfd/mt6358-irq.c
> > @@ -0,0 +1,231 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// Copyright (c) 2019 MediaTek Inc.
...
> > +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;
> > +
> > + /* Find out the irq group */
> > + 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)) {
>
> Would this condition ever be true? The while loop before this always
> break when top_gp == ARRAY_SIZE(mt6358_ints) - 1.
>
Thanks for reviewing. I will remove this part in next patch.
> > + mutex_unlock(&chip->irqlock);
> > + dev_err(chip->dev,
> > + "Failed to get top_group: %d\n", top_gp);
> > + return;
> > + }
> > +
> > + /* Find the irq registers */
> > + 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(&chip->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 +
> > + mt6358_ints[top_gp].sta_reg_shift * i;
> > + ret = regmap_read(chip->regmap, sta_reg, &irq_status);
> > + if (ret) {
> > + dev_err(chip->dev,
> > + "Failed to read irq status: %d\n", ret);
> > + return;
> > + }
> > +
> > + if (!irq_status)
> > + continue;
> > +
> > + for (j = 0; j < MT6358_REG_WIDTH ; j++) {
> > + if ((irq_status & BIT(j)) == 0)
> > + continue;
> > + hwirq = mt6358_ints[top_gp].hwirq_base +
> > + MT6358_REG_WIDTH * i + j;
> > + virq = irq_find_mapping(chip->irq_domain, hwirq);
> > + if (virq)
> > + handle_nested_irq(virq);
> > + }
> > +
> > + regmap_write(chip->regmap, sta_reg, irq_status);
> > + }
> > +}
> > +
> > +static irqreturn_t mt6358_irq_handler(int irq, void *data)
> > +{
> > + struct mt6397_chip *chip = data;
> > + struct pmic_irq_data *mt6358_irq_data = chip->irq_data;
> > + unsigned int top_irq_status;
> > + unsigned int i;
> > + int ret;
> > +
> > + ret = regmap_read(chip->regmap,
> > + mt6358_irq_data->top_int_status_reg,
> > + &top_irq_status);
> > + if (ret) {
> > + dev_err(chip->dev, "Can't read TOP_INT_STATUS ret=%d\n", ret);
> > + return IRQ_NONE;
> > + }
> > +
> > + for (i = 0; i < mt6358_irq_data->num_top; i++) {
> > + if (top_irq_status & BIT(mt6358_ints[i].top_offset))
> > + mt6358_irq_sp_handler(chip, i);
> > + }
> > +
> > + return IRQ_HANDLED;
> > +}
> > +
> > +static int pmic_irq_domain_map(struct irq_domain *d, unsigned int irq,
> > + irq_hw_number_t hw)
> > +{
> > + struct mt6397_chip *mt6397 = d->host_data;
> > +
> > + irq_set_chip_data(irq, mt6397);
> > + irq_set_chip_and_handler(irq, &mt6358_irq_chip, handle_level_irq);
> > + irq_set_nested_thread(irq, 1);
> > + irq_set_noprobe(irq);
> > +
> > + return 0;
> > +}
> > +
> > +static const struct irq_domain_ops mt6358_irq_domain_ops = {
> > + .map = pmic_irq_domain_map,
> > + .xlate = irq_domain_xlate_twocell,
> > +};
> > +
> > +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(&chip->irqlock);
> > + irqd->top_int_status_reg = MT6358_TOP_INT_STATUS0;
> > + irqd->num_pmic_irqs = MT6358_IRQ_NR;
> > + irqd->num_top = ARRAY_SIZE(mt6358_ints);
>
> ARRAY_SIZE(mt6358_ints) is still used in pmic_irq_sync_unlock. Is this
> variable needed, or should the ARRAY_SIZE(mt6358_ints) in
> pmic_irq_sync_unlock be changed to irqd->num_top too?
>
I will update to irqd->num_top from ARRAY_SIZE(mt6358_ints) in
pmic_irq_sync_unlock.
> > +
> > + 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 interrupts for initializing */
> > + 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 +
> > + mt6358_ints[i].en_reg_shift * j, 0);
> > + }
> > +
> > + chip->irq_domain = irq_domain_add_linear(chip->dev->of_node,
> > + irqd->num_pmic_irqs,
> > + &mt6358_irq_domain_ops, chip);
> > + if (!chip->irq_domain) {
> > + dev_err(chip->dev, "could not create IRQ domain\n");
> > + return -ENODEV;
> > + }
> > +
> > + ret = devm_request_threaded_irq(chip->dev, chip->irq, NULL,
> > + mt6358_irq_handler, IRQF_ONESHOT,
> > + mt6358_irq_chip.name, chip);
> > + if (ret) {
> > + dev_err(chip->dev, "failed to register irq=%d; err: %d\n",
> > + chip->irq, ret);
> > + return ret;
> > + }
> > +
> > + enable_irq_wake(chip->irq);
> > + return ret;
> > +}
> > (...)
>
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2019-12-06 8:58 UTC|newest]
Thread overview: 89+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-08-23 3:45 [PATCH v5 00/10] Add Support for MediaTek PMIC MT6358 Hsin-Hsiung Wang
2019-08-23 3:45 ` Hsin-Hsiung Wang
2019-08-23 3:45 ` Hsin-Hsiung Wang
2019-08-23 3:45 ` [PATCH v5 01/10] mfd: mt6397: clean up code Hsin-Hsiung Wang
2019-08-23 3:45 ` Hsin-Hsiung Wang
2019-08-23 3:45 ` Hsin-Hsiung Wang
2019-08-23 3:45 ` [PATCH v5 02/10] mfd: mt6397: extract irq related code from core driver Hsin-Hsiung Wang
2019-08-23 3:45 ` Hsin-Hsiung Wang
2019-08-23 3:45 ` Hsin-Hsiung Wang
2019-08-23 12:13 ` [BUG] " Frank Wunderlich
2019-08-23 12:13 ` Frank Wunderlich
2019-08-23 12:13 ` Frank Wunderlich
2019-08-23 14:56 ` Matthias Brugger
2019-08-23 14:56 ` Matthias Brugger
2019-08-23 15:26 ` Frank Wunderlich
2019-08-23 15:26 ` Frank Wunderlich
2019-08-23 15:26 ` Frank Wunderlich
2019-08-23 15:42 ` Matthias Brugger
2019-08-23 15:42 ` Matthias Brugger
[not found] ` <b5a21908-faee-17d1-ce26-99b941c0fa70-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2019-08-23 17:16 ` Aw: " Frank Wunderlich
2019-08-23 17:16 ` Frank Wunderlich
2019-08-23 17:16 ` Frank Wunderlich
2019-08-29 6:24 ` Hsin-hsiung Wang
2019-08-29 6:24 ` Hsin-hsiung Wang
2019-08-29 6:24 ` Hsin-hsiung Wang
2019-09-19 18:59 ` Frank Wunderlich
2019-09-19 18:59 ` Frank Wunderlich
2019-09-30 19:44 ` Aw: " Frank Wunderlich
2019-09-30 19:44 ` Frank Wunderlich
2019-09-30 19:44 ` Frank Wunderlich
2019-08-24 7:04 ` Frank Wunderlich
[not found] ` <725410A8-8B5B-472A-8904-57B912475783-SipyoOjXbOMoAHOVJHB0wA@public.gmane.org>
2019-08-24 9:16 ` Frank Wunderlich
2019-08-23 15:35 ` Frank Wunderlich
2019-08-23 15:35 ` Frank Wunderlich
2019-08-23 15:35 ` Frank Wunderlich
2019-08-23 15:53 ` Frank Wunderlich
2019-08-23 15:53 ` Frank Wunderlich
2019-08-23 14:53 ` Matthias Brugger
2019-08-23 14:53 ` Matthias Brugger
2019-08-23 3:45 ` [PATCH v5 03/10] mfd: mt6397: modify suspend/resume behavior Hsin-Hsiung Wang
2019-08-23 3:45 ` Hsin-Hsiung Wang
2019-08-23 3:45 ` Hsin-Hsiung Wang
2019-08-23 15:12 ` Matthias Brugger
2019-08-23 15:12 ` Matthias Brugger
2019-08-23 3:45 ` [PATCH v5 04/10] dt-bindings: mfd: Add compatible for the MediaTek MT6358 PMIC Hsin-Hsiung Wang
2019-08-23 3:45 ` Hsin-Hsiung Wang
2019-08-23 3:45 ` Hsin-Hsiung Wang
2019-08-23 3:45 ` [PATCH v5 05/10] regulator: Add document for MT6358 regulator Hsin-Hsiung Wang
2019-08-23 3:45 ` Hsin-Hsiung Wang
2019-08-23 3:45 ` Hsin-Hsiung Wang
2019-08-28 10:44 ` Mark Brown
2019-08-28 10:44 ` Mark Brown
2019-08-28 13:13 ` Applied "regulator: Add document for MT6358 regulator" to the regulator tree Mark Brown
2019-08-28 13:13 ` Mark Brown
2019-08-28 13:13 ` Mark Brown
2019-08-23 3:45 ` [PATCH v5 06/10] mfd: Add support for the MediaTek MT6358 PMIC Hsin-Hsiung Wang
2019-08-23 3:45 ` Hsin-Hsiung Wang
2019-08-23 3:45 ` Hsin-Hsiung Wang
2019-12-02 8:06 ` Pi-Hsun Shih
2019-12-02 8:06 ` Pi-Hsun Shih
2019-12-02 8:06 ` Pi-Hsun Shih
2019-12-06 8:55 ` Hsin-hsiung Wang [this message]
2019-12-06 8:55 ` Hsin-hsiung Wang
2019-12-06 8:55 ` Hsin-hsiung Wang
2019-08-23 3:45 ` [PATCH v5 07/10] regulator: mt6358: Add support for MT6358 regulator Hsin-Hsiung Wang
2019-08-23 3:45 ` Hsin-Hsiung Wang
2019-08-23 3:45 ` Hsin-Hsiung Wang
2019-08-28 10:45 ` Mark Brown
2019-08-28 10:45 ` Mark Brown
2019-08-29 6:09 ` Hsin-hsiung Wang
2019-08-29 6:09 ` Hsin-hsiung Wang
2019-08-29 6:09 ` Hsin-hsiung Wang
2019-08-28 13:13 ` Applied "regulator: mt6358: Add support for MT6358 regulator" to the regulator tree Mark Brown
2019-08-28 13:13 ` Mark Brown
2019-08-28 13:13 ` Mark Brown
2019-08-23 3:45 ` [PATCH v5 08/10] arm64: dts: mt6358: add PMIC MT6358 related nodes Hsin-Hsiung Wang
2019-08-23 3:45 ` Hsin-Hsiung Wang
2019-08-23 3:45 ` Hsin-Hsiung Wang
2019-08-23 3:45 ` [PATCH v5 09/10] rtc: mt6397: fix alarm register overwrite Hsin-Hsiung Wang
2019-08-23 3:45 ` Hsin-Hsiung Wang
2019-08-23 3:45 ` Hsin-Hsiung Wang
2019-08-23 15:35 ` Matthias Brugger
2019-08-23 15:35 ` Matthias Brugger
2019-08-29 5:34 ` Hsin-hsiung Wang
2019-08-29 5:34 ` Hsin-hsiung Wang
2019-08-29 5:34 ` Hsin-hsiung Wang
[not found] ` <1566531931-9772-1-git-send-email-hsin-hsiung.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
2019-08-23 3:45 ` [PATCH v5 10/10] rtc: mt6397: Add support for the MediaTek MT6358 RTC Hsin-Hsiung Wang
2019-08-23 3:45 ` Hsin-Hsiung Wang
2019-08-23 3:45 ` Hsin-Hsiung Wang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1575622558.17300.5.camel@mtksdaap41 \
--to=hsin-hsiung.wang@mediatek.com \
--cc=a.zummo@towertech.it \
--cc=alexandre.belloni@bootlin.com \
--cc=broonie@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=eddie.huang@mediatek.com \
--cc=gregkh@linuxfoundation.org \
--cc=kstewart@linuxfoundation.org \
--cc=lee.jones@linaro.org \
--cc=lgirdwood@gmail.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mediatek@lists.infradead.org \
--cc=linux-rtc@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=matthias.bgg@gmail.com \
--cc=pihsun@chromium.org \
--cc=rfontana@redhat.com \
--cc=robh+dt@kernel.org \
--cc=sean.wang@mediatek.com \
--cc=srv_heupstream@mediatek.com \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.