* [PATCH 2/2] rtc: brcmstb-waketimer: add range
From: Alexandre Belloni @ 2018-05-20 20:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180520202730.28172-1-alexandre.belloni@bootlin.com>
Let the core handle the range.
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
drivers/rtc/rtc-brcmstb-waketimer.c | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/drivers/rtc/rtc-brcmstb-waketimer.c b/drivers/rtc/rtc-brcmstb-waketimer.c
index ba49d9bcff12..f4010a75f2be 100644
--- a/drivers/rtc/rtc-brcmstb-waketimer.c
+++ b/drivers/rtc/rtc-brcmstb-waketimer.c
@@ -145,9 +145,6 @@ static int brcmstb_waketmr_settime(struct device *dev,
sec = rtc_tm_to_time64(tm);
- if (sec > U32_MAX || sec < 0)
- return -EINVAL;
-
writel_relaxed(sec, timer->base + BRCMSTB_WKTMR_COUNTER);
return 0;
@@ -184,9 +181,6 @@ static int brcmstb_waketmr_setalarm(struct device *dev,
else
sec = 0;
- if (sec > U32_MAX || sec < 0)
- return -EINVAL;
-
brcmstb_waketmr_set_alarm(timer, sec);
return 0;
@@ -266,6 +260,7 @@ static int brcmstb_waketmr_probe(struct platform_device *pdev)
register_reboot_notifier(&timer->reboot_notifier);
timer->rtc->ops = &brcmstb_waketmr_ops;
+ timer->rtc->range_max = U32_MAX;
ret = rtc_register_device(timer->rtc);
if (ret) {
--
2.17.0
^ permalink raw reply related
* [PATCH 1/2] rtc: brcmstb-waketimer: switch to rtc_register_device
From: Alexandre Belloni @ 2018-05-20 20:27 UTC (permalink / raw)
To: linux-arm-kernel
Switch to devm_rtc_allocate_device/rtc_register_device.
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
drivers/rtc/rtc-brcmstb-waketimer.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/rtc/rtc-brcmstb-waketimer.c b/drivers/rtc/rtc-brcmstb-waketimer.c
index bdd6674a1054..ba49d9bcff12 100644
--- a/drivers/rtc/rtc-brcmstb-waketimer.c
+++ b/drivers/rtc/rtc-brcmstb-waketimer.c
@@ -229,6 +229,10 @@ static int brcmstb_waketmr_probe(struct platform_device *pdev)
if (IS_ERR(timer->base))
return PTR_ERR(timer->base);
+ timer->rtc = devm_rtc_allocate_device(dev);
+ if (IS_ERR(timer->rtc))
+ return PTR_ERR(timer->rtc);
+
/*
* Set wakeup capability before requesting wakeup interrupt, so we can
* process boot-time "wakeups" (e.g., from S5 soft-off)
@@ -261,11 +265,11 @@ static int brcmstb_waketmr_probe(struct platform_device *pdev)
timer->reboot_notifier.notifier_call = brcmstb_waketmr_reboot;
register_reboot_notifier(&timer->reboot_notifier);
- timer->rtc = rtc_device_register("brcmstb-waketmr", dev,
- &brcmstb_waketmr_ops, THIS_MODULE);
- if (IS_ERR(timer->rtc)) {
+ timer->rtc->ops = &brcmstb_waketmr_ops;
+
+ ret = rtc_register_device(timer->rtc);
+ if (ret) {
dev_err(dev, "unable to register device\n");
- ret = PTR_ERR(timer->rtc);
goto err_notifier;
}
@@ -288,7 +292,6 @@ static int brcmstb_waketmr_remove(struct platform_device *pdev)
struct brcmstb_waketmr *timer = dev_get_drvdata(&pdev->dev);
unregister_reboot_notifier(&timer->reboot_notifier);
- rtc_device_unregister(timer->rtc);
return 0;
}
--
2.17.0
^ permalink raw reply related
* [PATCH 2/6] Input: ams_delta_serio: use GPIO lookup table
From: Dmitry Torokhov @ 2018-05-20 20:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180518210954.29044-2-jmkrzyszt@gmail.com>
Hi Janusz,
On Fri, May 18, 2018 at 11:09:50PM +0200, Janusz Krzysztofik wrote:
> Now as the Amstrad Delta board provides GPIO lookup tables, switch from
> GPIO numbers to GPIO descriptors and use the table to locate required
> GPIO pins.
>
> Declare static variables for storing GPIO descriptors and replace
> gpio_ functions with their gpiod_ equivalents.
>
> Pin naming used by the driver should be followed while respective GPIO
> lookup table is initialized by a board init code.
>
> Created and tested against linux-4.17-rc3, on top of patch 1/6 "ARM:
> OMAP1: ams-delta: add GPIO lookup tables"
>
> Signed-off-by: Janusz Krzysztofik <jmkrzyszt@gmail.com>
> ---
> drivers/input/serio/ams_delta_serio.c | 98 +++++++++++++++++++----------------
> 1 file changed, 53 insertions(+), 45 deletions(-)
>
> diff --git a/drivers/input/serio/ams_delta_serio.c b/drivers/input/serio/ams_delta_serio.c
> index 3df501c3421b..dd1f8f118c08 100644
> --- a/drivers/input/serio/ams_delta_serio.c
> +++ b/drivers/input/serio/ams_delta_serio.c
> @@ -20,14 +20,13 @@
> * However, when used with the E3 mailboard that producecs non-standard
> * scancodes, a custom key table must be prepared and loaded from userspace.
> */
> -#include <linux/gpio.h>
> +#include <linux/gpio/consumer.h>
> #include <linux/irq.h>
> #include <linux/serio.h>
> #include <linux/slab.h>
> #include <linux/module.h>
>
> #include <asm/mach-types.h>
> -#include <mach/board-ams-delta.h>
>
> #include <mach/ams-delta-fiq.h>
>
> @@ -36,6 +35,10 @@ MODULE_DESCRIPTION("AMS Delta (E3) keyboard port driver");
> MODULE_LICENSE("GPL");
>
> static struct serio *ams_delta_serio;
> +static struct gpio_desc *gpiod_data;
> +static struct gpio_desc *gpiod_clock;
> +static struct gpio_desc *gpiod_power;
> +static struct gpio_desc *gpiod_dataout;
Since you are doing the conversion: it does not appear that all these
are necessarily GPIOs; for example should not power be gpio-regulator
and data be simply expressed as IRQ resource? And the driver to be
converted into a platform driver?
I think this needs to be done first, because otherwise you are
committing to a certain binding and will have hard time changing it
later.
Thanks.
>
> static int check_data(int data)
> {
> @@ -92,7 +95,7 @@ static irqreturn_t ams_delta_serio_interrupt(int irq, void *dev_id)
> static int ams_delta_serio_open(struct serio *serio)
> {
> /* enable keyboard */
> - gpio_set_value(AMS_DELTA_GPIO_PIN_KEYBRD_PWR, 1);
> + gpiod_set_value(gpiod_power, 1);
>
> return 0;
> }
> @@ -100,32 +103,9 @@ static int ams_delta_serio_open(struct serio *serio)
> static void ams_delta_serio_close(struct serio *serio)
> {
> /* disable keyboard */
> - gpio_set_value(AMS_DELTA_GPIO_PIN_KEYBRD_PWR, 0);
> + gpiod_set_value(gpiod_power, 0);
> }
>
> -static const struct gpio ams_delta_gpios[] __initconst_or_module = {
> - {
> - .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_DATA,
> - .flags = GPIOF_DIR_IN,
> - .label = "serio-data",
> - },
> - {
> - .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_CLK,
> - .flags = GPIOF_DIR_IN,
> - .label = "serio-clock",
> - },
> - {
> - .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_PWR,
> - .flags = GPIOF_OUT_INIT_LOW,
> - .label = "serio-power",
> - },
> - {
> - .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_DATAOUT,
> - .flags = GPIOF_OUT_INIT_LOW,
> - .label = "serio-dataout",
> - },
> -};
> -
> static int __init ams_delta_serio_init(void)
> {
> int err;
> @@ -145,36 +125,62 @@ static int __init ams_delta_serio_init(void)
> strlcpy(ams_delta_serio->phys, "GPIO/serio0",
> sizeof(ams_delta_serio->phys));
>
> - err = gpio_request_array(ams_delta_gpios,
> - ARRAY_SIZE(ams_delta_gpios));
> - if (err) {
> - pr_err("ams_delta_serio: Couldn't request gpio pins\n");
> + gpiod_data = gpiod_get(NULL, "data", GPIOD_IN);
> + if (IS_ERR(gpiod_data)) {
> + err = PTR_ERR(gpiod_data);
> + pr_err("%s: 'data' GPIO request failed (%d)\n", __func__,
> + err);
> goto serio;
> }
> + gpiod_clock = gpiod_get(NULL, "clock", GPIOD_IN);
> + if (IS_ERR(gpiod_clock)) {
> + err = PTR_ERR(gpiod_clock);
> + pr_err("%s: 'clock' GPIO request failed (%d)\n", __func__,
> + err);
> + goto gpio_data;
> + }
> + gpiod_power = gpiod_get(NULL, "power", GPIOD_OUT_LOW);
> + if (IS_ERR(gpiod_power)) {
> + err = PTR_ERR(gpiod_power);
> + pr_err("%s: 'power' GPIO request failed (%d)\n", __func__,
> + err);
> + goto gpio_clock;
> + }
> + gpiod_dataout = gpiod_get(NULL, "dataout", GPIOD_OUT_LOW);
> + if (IS_ERR(gpiod_dataout)) {
> + err = PTR_ERR(gpiod_dataout);
> + pr_err("%s: 'dataout' GPIO request failed (%d)\n",
> + __func__, err);
> + goto gpio_power;
> + }
>
> - err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
> - ams_delta_serio_interrupt, IRQ_TYPE_EDGE_RISING,
> - "ams-delta-serio", 0);
> + err = request_irq(gpiod_to_irq(gpiod_clock),
> + ams_delta_serio_interrupt, IRQ_TYPE_EDGE_RISING,
> + "ams-delta-serio", 0);
> if (err < 0) {
> - pr_err("ams_delta_serio: couldn't request gpio interrupt %d\n",
> - gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK));
> - goto gpio;
> + pr_err("%s: 'clock' GPIO interrupt request failed (%d)\n",
> + __func__, err);
> + goto gpio_dataout;
> }
> /*
> * Since GPIO register handling for keyboard clock pin is performed
> * at FIQ level, switch back from edge to simple interrupt handler
> * to avoid bad interaction.
> */
> - irq_set_handler(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
> - handle_simple_irq);
> + irq_set_handler(gpiod_to_irq(gpiod_clock), handle_simple_irq);
>
> serio_register_port(ams_delta_serio);
> dev_info(&ams_delta_serio->dev, "%s\n", ams_delta_serio->name);
>
> return 0;
> -gpio:
> - gpio_free_array(ams_delta_gpios,
> - ARRAY_SIZE(ams_delta_gpios));
> +gpio_dataout:
> + gpiod_put(gpiod_dataout);
> +gpio_power:
> + gpiod_put(gpiod_power);
> +gpio_clock:
> + gpiod_put(gpiod_clock);
> +gpio_data:
> + gpiod_put(gpiod_data);
> serio:
> kfree(ams_delta_serio);
> return err;
> @@ -184,8 +190,10 @@ module_init(ams_delta_serio_init);
> static void __exit ams_delta_serio_exit(void)
> {
> serio_unregister_port(ams_delta_serio);
> - free_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 0);
> - gpio_free_array(ams_delta_gpios,
> - ARRAY_SIZE(ams_delta_gpios));
> + free_irq(gpiod_to_irq(gpiod_clock), 0);
> + gpiod_put(gpiod_dataout);
> + gpiod_put(gpiod_power);
> + gpiod_put(gpiod_clock);
> + gpiod_put(gpiod_data);
> }
> module_exit(ams_delta_serio_exit);
> --
> 2.16.1
>
--
Dmitry
^ permalink raw reply
* [alsa-devel] [PATCH 5/6] mtd: rawnand: ams-delta: use GPIO lookup table
From: Dmitry Torokhov @ 2018-05-20 20:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180520192705.GA12883@lenoch>
On Sun, May 20, 2018 at 09:27:05PM +0200, Ladislav Michl wrote:
> On Sat, May 19, 2018 at 11:55:51PM +0200, Janusz Krzysztofik wrote:
> > On Saturday, May 19, 2018 8:00:38 PM CEST Andy Shevchenko wrote:
> > > On Sat, May 19, 2018 at 2:15 AM, Janusz Krzysztofik <jmkrzyszt@gmail.com>
> > wrote:
> > > > On Friday, May 18, 2018 11:21:14 PM CEST Andy Shevchenko wrote:
> > > >> On Sat, May 19, 2018 at 12:09 AM, Janusz Krzysztofik
> > > >>
> > > >> <jmkrzyszt@gmail.com> wrote:
> > > >> > + gpiod_rdy = devm_gpiod_get_optional(&pdev->dev, "rdy",
> > > >> > GPIOD_IN);
> > > >> > + if (!IS_ERR_OR_NULL(gpiod_rdy)) {
> > > >>
> > > >> So, is it optional or not at the end?
> > > >> If it is, why do we check for NULL?
> > > >
> > > > As far as I can understand, nand_chip->dev_ready() callback is optional.
> > > > That's why I decided to use the _optional variant of devm_gpiod_get(). In
> > > > case of ams-delta, the dev_ready() callback depends on availability of
> > > > the 'rdy' GPIO pin. As a consequence, I'm checking for both NULL and ERR
> > > > in order to decide if dev_ready() will be supported.
> > > >
> > > > I can pretty well replace it with the standard form and check for ERR only
> > > > if the purpose of the _optional form is different.
> > >
> > > NULL check in practice discards the _optional part of gpiod_get(). So,
> > > either you use non-optional variant and decide how to handle an
> > > errors, or user _optional w/o NULL check.
> >
> > OK, I'm going to use something like the below while submitting v2:
> >
> > - gpiod_rdy = devm_gpiod_get_optional(&pdev->dev, "rdy", GPIOD_IN);
> > - if (!IS_ERR_OR_NULL(gpiod_rdy)) {
> > - this->dev_ready = ams_delta_nand_ready;
> > - } else {
> > - this->dev_ready = NULL;
> > - pr_notice("Couldn't request gpio for Delta NAND ready.\n");
> > + priv->gpiod_rdy = devm_gpiod_get_optional(&pdev->dev, "rdy",
> > + GPIOD_IN);
> > + if (IS_ERR(priv->gpiod_rdy)) {
> > + err = PTR_ERR(priv->gpiod_nwp);
> ??? --------------------------------^^^^^^^^^
> > + dev_warn(&pdev->dev, "RDY GPIO request failed (%d)\n", err);
> > + goto err_gpiod;
>
> Driver will just use worst case delay instead of RDY signal, so this
> is perhaps too strict. I will work with degraded performance.
If RDY signal is not available then the board should not define it.
Degrading performance and having users wondering because RDY is
sometimes not available is not great. Especially if we get -EPROBE_DEFER
here.
Thanks.
--
Dmitry
^ permalink raw reply
* [alsa-devel] [PATCH 5/6] mtd: rawnand: ams-delta: use GPIO lookup table
From: Ladislav Michl @ 2018-05-20 19:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5456625.lDWjtgZygK@z50>
On Sat, May 19, 2018 at 11:55:51PM +0200, Janusz Krzysztofik wrote:
> On Saturday, May 19, 2018 8:00:38 PM CEST Andy Shevchenko wrote:
> > On Sat, May 19, 2018 at 2:15 AM, Janusz Krzysztofik <jmkrzyszt@gmail.com>
> wrote:
> > > On Friday, May 18, 2018 11:21:14 PM CEST Andy Shevchenko wrote:
> > >> On Sat, May 19, 2018 at 12:09 AM, Janusz Krzysztofik
> > >>
> > >> <jmkrzyszt@gmail.com> wrote:
> > >> > + gpiod_rdy = devm_gpiod_get_optional(&pdev->dev, "rdy",
> > >> > GPIOD_IN);
> > >> > + if (!IS_ERR_OR_NULL(gpiod_rdy)) {
> > >>
> > >> So, is it optional or not at the end?
> > >> If it is, why do we check for NULL?
> > >
> > > As far as I can understand, nand_chip->dev_ready() callback is optional.
> > > That's why I decided to use the _optional variant of devm_gpiod_get(). In
> > > case of ams-delta, the dev_ready() callback depends on availability of
> > > the 'rdy' GPIO pin. As a consequence, I'm checking for both NULL and ERR
> > > in order to decide if dev_ready() will be supported.
> > >
> > > I can pretty well replace it with the standard form and check for ERR only
> > > if the purpose of the _optional form is different.
> >
> > NULL check in practice discards the _optional part of gpiod_get(). So,
> > either you use non-optional variant and decide how to handle an
> > errors, or user _optional w/o NULL check.
>
> OK, I'm going to use something like the below while submitting v2:
>
> - gpiod_rdy = devm_gpiod_get_optional(&pdev->dev, "rdy", GPIOD_IN);
> - if (!IS_ERR_OR_NULL(gpiod_rdy)) {
> - this->dev_ready = ams_delta_nand_ready;
> - } else {
> - this->dev_ready = NULL;
> - pr_notice("Couldn't request gpio for Delta NAND ready.\n");
> + priv->gpiod_rdy = devm_gpiod_get_optional(&pdev->dev, "rdy",
> + GPIOD_IN);
> + if (IS_ERR(priv->gpiod_rdy)) {
> + err = PTR_ERR(priv->gpiod_nwp);
??? --------------------------------^^^^^^^^^
> + dev_warn(&pdev->dev, "RDY GPIO request failed (%d)\n", err);
> + goto err_gpiod;
Driver will just use worst case delay instead of RDY signal, so this
is perhaps too strict. I will work with degraded performance.
ladis
> }
>
> + if (priv->gpiod_rdy)
> + this->dev_ready = ams_delta_nand_ready;
>
> >
> > >> > +err_gpiod:
> > >> > + if (err == -ENODEV || err == -ENOENT)
> > >> > + err = -EPROBE_DEFER;
> > >>
> > >> Hmm...
> > >
> > > Amstrad Delta uses gpio-mmio driver. Unfortunatelty that driver is not
> > > availble before device init phase, unlike other crucial GPIO drivers which
> > > are initialized earlier, e.g. during the postcore or at latetst the
> > > subsys phase. Hence, devices which depend on GPIO pins provided by
> > > gpio-mmio must either be declared late or fail softly so they get another
> > > chance of being probed succesfully.
> > >
> > > I thought of replacing the gpio-mmio platform driver with bgpio functions
> > > it exports but for now I haven't implemented it, not even shared the
> > > idea.
> > >
> > > Does it really hurt to return -EPROBE_DEFER if a GPIO pin can't be
> > > obtained?
> > I'm only concerned if it would be an infinite defer in the case when
> > driver will never appear.
> > But I don't remember the details.
>
> Deferred probes are handled effectively during late_initcall, no risk of
> infinite defer, see drivers/base/dd.c for details.
>
> Thanks,
> Janusz
>
>
>
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel at alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
^ permalink raw reply
* [PATCH 5/6] mtd: rawnand: ams-delta: use GPIO lookup table
From: Miquel Raynal @ 2018-05-20 17:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAHp75Vdp5A58JMTf8vaET84QEzzZ_T7eKLUYfWV9qpWt5ptYCA@mail.gmail.com>
Hello,
On Sun, 20 May 2018 19:17:04 +0300, Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
> >> Though, I completely dislike "rdy" name of GPIO. Where is it documented?
> >
> > No documentation files for Amstrad Delta nor for its NAND driver specifically
> > exist under Documentation/. However, there exist some for generic GPIO NAND
> > driver where the pin name "rdy" is used explicitly:
> > Documentation/driver-api/gpio/drivers-on-gpio.rst
> > Documentation/devicetree/bindings/mtd/gpio-control-nand.txt
> > You can find that mnemonic used across drivers/mtd/nand/, standalone or as a
> > suffix, including the Amstrad Delta NAND driver before the change discussed.
>
> > To be honest, I don't like it much either, but I'm just using it instead of
> > inventing something new.
>
> OK, that's what I was looking for. Since it's already in use and
> documented, then it's fine for me.
Do we actually have the possibility to rename this gpio? I guess no
since it would break DT backward compatibility. Otherwise it would have
been more descriptive to call it something like 'gpio-rb'.
Anyway, if you find the time, documentation for this controller would be
welcome!
Thanks,
Miqu?l
^ permalink raw reply
* [PATCH 2/2] ARM: meson: merge Kconfig symbol MACH_MESON8B into MACH_MESON8
From: Martin Blumenstingl @ 2018-05-20 17:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180520172353.19256-1-martin.blumenstingl@googlemail.com>
Currently there are no differences between the MACH_MESON8 and
MACH_MESON8B Kconfig symbols (except the help text). Since both
platforms are very similar (Meson8b being a slightly updated,
cost-reduced version of Meson8 which even shares some peripherals with
Meson8m2) no notable differences are expected in the future either.
Suggested-by: Kevin Hilman <khilman@baylibre.com>
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
arch/arm/mach-meson/Kconfig | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/arch/arm/mach-meson/Kconfig b/arch/arm/mach-meson/Kconfig
index 2bc630471beb..d51cfda953d4 100644
--- a/arch/arm/mach-meson/Kconfig
+++ b/arch/arm/mach-meson/Kconfig
@@ -19,14 +19,7 @@ config MACH_MESON6
select MESON6_TIMER
config MACH_MESON8
- bool "Amlogic Meson8 and Meson8m2 SoCs support"
- default ARCH_MESON
- select MESON6_TIMER
- select COMMON_CLK_MESON8B
- select MESON_IRQ_GPIO
-
-config MACH_MESON8B
- bool "Amlogic Meson8b SoCs support"
+ bool "Amlogic Meson8, Meson8b and Meson8m2 SoCs support"
default ARCH_MESON
select MESON6_TIMER
select COMMON_CLK_MESON8B
--
2.17.0
^ permalink raw reply related
* [PATCH 1/2] ARM: dts: meson: build the Meson8b .dtbs with MACH_MESON8
From: Martin Blumenstingl @ 2018-05-20 17:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180520172353.19256-1-martin.blumenstingl@googlemail.com>
Currently there are two identical Kconfig options where only differences
are the Kconfig help text and the list of .dtbs that are built:
- MACH_MESON8
- MACH_MESON8B
Build the Meson8b .dtbs when MACH_MESON8 is selected to get rid of the
latter Kconfig symbol later.
Suggested-by: Kevin Hilman <khilman@baylibre.com>
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
arch/arm/boot/dts/Makefile | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 4300e86049ee..b7f0b55e0dc5 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -313,14 +313,13 @@ dtb-$(CONFIG_MACH_MESON6) += \
meson6-atv1200.dtb
dtb-$(CONFIG_MACH_MESON8) += \
meson8-minix-neo-x8.dtb \
+ meson8b-mxq.dtb \
+ meson8b-odroidc1.dtb \
meson8m2-mxiii-plus.dtb
dtb-$(CONFIG_ARCH_MMP) += \
pxa168-aspenite.dtb \
pxa910-dkb.dtb \
mmp2-brownstone.dtb
-dtb-$(CONFIG_MACH_MESON8B) += \
- meson8b-mxq.dtb \
- meson8b-odroidc1.dtb
dtb-$(CONFIG_ARCH_MPS2) += \
mps2-an385.dtb \
mps2-an399.dtb
--
2.17.0
^ permalink raw reply related
* [PATCH 0/2] get rid of Kconfig symbol MACH_MESON8B
From: Martin Blumenstingl @ 2018-05-20 17:23 UTC (permalink / raw)
To: linux-arm-kernel
as noted by Kevin [0] there are two Kconfig symbols which only differ
in their Kconfig help text and the list of .dtbs that are being built.
the goal of this small series is to get rid of the unnecessary
MACH_MESON8B Kconfig symbol by merging it into MACH_MESON8.
[0] http://lists.infradead.org/pipermail/linux-amlogic/2018-May/007342.html
Martin Blumenstingl (2):
ARM: dts: meson: build the Meson8b .dtbs with MACH_MESON8
ARM: meson: merge Kconfig symbol MACH_MESON8B into MACH_MESON8
arch/arm/boot/dts/Makefile | 5 ++---
arch/arm/mach-meson/Kconfig | 9 +--------
2 files changed, 3 insertions(+), 11 deletions(-)
--
2.17.0
^ permalink raw reply
* [PATCH 2/2] drm/rockchip: Support 10 bits yuv format in vop
From: Randy Li @ 2018-05-20 17:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180520171705.29690-1-ayaka@soulik.info>
The rockchip use fully packed pixel format variants
for YUV 10bits.
This patch only make the VOP accept this pixel format,
but it doesn't add the converting data path for
the color gamuts that the target display are supported.
Signed-off-by: Randy Li <ayaka@soulik.info>
---
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 27 +++++++++++++++++++++++++--
drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 1 +
drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 2 ++
3 files changed, 28 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 2121345a61af..6a54b20501ac 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -232,6 +232,7 @@ static enum vop_data_format vop_convert_format(uint32_t format)
case DRM_FORMAT_BGR565:
return VOP_FMT_RGB565;
case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV12_10LE40:
return VOP_FMT_YUV420SP;
case DRM_FORMAT_NV16:
return VOP_FMT_YUV422SP;
@@ -249,6 +250,17 @@ static bool is_yuv_support(uint32_t format)
case DRM_FORMAT_NV12:
case DRM_FORMAT_NV16:
case DRM_FORMAT_NV24:
+ case DRM_FORMAT_NV12_10LE40:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool is_yuv_10bit(uint32_t format)
+{
+ switch (format) {
+ case DRM_FORMAT_NV12_10LE40:
return true;
default:
return false;
@@ -711,6 +723,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
dma_addr_t dma_addr;
uint32_t val;
bool rb_swap;
+ bool is_10_bits = false;
int win_index = VOP_WIN_TO_INDEX(vop_win);
int format;
@@ -728,6 +741,8 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
return;
}
+ is_10_bits = is_yuv_10bit(fb->format->format);
+
obj = rockchip_fb_get_gem_obj(fb, 0);
rk_obj = to_rockchip_obj(obj);
@@ -742,7 +757,11 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
dsp_sty = dest->y1 + crtc->mode.vtotal - crtc->mode.vsync_start;
dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
- offset = (src->x1 >> 16) * fb->format->cpp[0];
+ if (is_10_bits)
+ offset = (src->x1 >> 16) * (fb->format->cpp[0] * 5 / 4);
+ else
+ offset = (src->x1 >> 16) * fb->format->cpp[0];
+
offset += (src->y1 >> 16) * fb->pitches[0];
dma_addr = rk_obj->dma_addr + offset + fb->offsets[0];
@@ -753,6 +772,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
VOP_WIN_SET(vop, win, format, format);
VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4));
VOP_WIN_SET(vop, win, yrgb_mst, dma_addr);
+ VOP_WIN_SET(vop, win, fmt_10, is_10_bits);
if (is_yuv_support(fb->format->format)) {
int hsub = drm_format_horz_chroma_subsampling(fb->format->format);
int vsub = drm_format_vert_chroma_subsampling(fb->format->format);
@@ -761,7 +781,10 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
uv_obj = rockchip_fb_get_gem_obj(fb, 1);
rk_uv_obj = to_rockchip_obj(uv_obj);
- offset = (src->x1 >> 16) * bpp / hsub;
+ if (is_10_bits)
+ offset = (src->x1 >> 16) * (bpp * 5 / 4) / hsub;
+ else
+ offset = (src->x1 >> 16) * bpp / hsub;
offset += (src->y1 >> 16) * fb->pitches[1] / vsub;
dma_addr = rk_uv_obj->dma_addr + offset + fb->offsets[1];
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
index 084acdd0019a..d9ec993f420a 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
@@ -131,6 +131,7 @@ struct vop_win_phy {
struct vop_reg enable;
struct vop_reg gate;
struct vop_reg format;
+ struct vop_reg fmt_10;
struct vop_reg rb_swap;
struct vop_reg act_info;
struct vop_reg dsp_info;
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
index 08023d3ecb76..5393886ddd95 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
@@ -50,6 +50,7 @@ static const uint32_t formats_win_full[] = {
DRM_FORMAT_NV12,
DRM_FORMAT_NV16,
DRM_FORMAT_NV24,
+ DRM_FORMAT_NV12_10LE40,
};
static const uint32_t formats_win_lite[] = {
@@ -215,6 +216,7 @@ static const struct vop_win_phy rk3288_win01_data = {
.nformats = ARRAY_SIZE(formats_win_full),
.enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0),
.format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1),
+ .fmt_10 = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 4),
.rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12),
.act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0),
.dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0),
--
2.14.3
^ permalink raw reply related
* [PATCH 1/2] drm/fourcc: add a 10bits fully packed variant of NV12
From: Randy Li @ 2018-05-20 17:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180520171705.29690-1-ayaka@soulik.info>
This pixel format is a fully packed and 10bits variant of NV12.
A luma pixel would take 10bits in memory, without any
filled bits between pixels in a stride. The color gamut
follows the BT.2020 standard.
Signed-off-by: Randy Li <ayaka@soulik.info>
---
drivers/gpu/drm/drm_fourcc.c | 1 +
include/uapi/drm/drm_fourcc.h | 3 +++
2 files changed, 4 insertions(+)
diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c
index 5ca6395cd4d3..1f43967c4013 100644
--- a/drivers/gpu/drm/drm_fourcc.c
+++ b/drivers/gpu/drm/drm_fourcc.c
@@ -173,6 +173,7 @@ const struct drm_format_info *__drm_format_info(u32 format)
{ .format = DRM_FORMAT_UYVY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 },
{ .format = DRM_FORMAT_VYUY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 },
{ .format = DRM_FORMAT_AYUV, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
+ { .format = DRM_FORMAT_NV12_10LE40, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2 },
};
unsigned int i;
diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
index e04613d30a13..8eabf01e966f 100644
--- a/include/uapi/drm/drm_fourcc.h
+++ b/include/uapi/drm/drm_fourcc.h
@@ -140,6 +140,9 @@ extern "C" {
#define DRM_FORMAT_NV61 fourcc_code('N', 'V', '6', '1') /* 2x1 subsampled Cb:Cr plane */
#define DRM_FORMAT_NV24 fourcc_code('N', 'V', '2', '4') /* non-subsampled Cr:Cb plane */
#define DRM_FORMAT_NV42 fourcc_code('N', 'V', '4', '2') /* non-subsampled Cb:Cr plane */
+/* A fully packed variant of NV12_10LE32 */
+#define DRM_FORMAT_NV12_10LE40 fourcc_code('R', 'K', '2', '0') /* 2x2 subsampled Cr:Cb plane */
+
/*
* 3 plane YCbCr
--
2.14.3
^ permalink raw reply related
* [PATCH 0/2] Add support for a YUV 10bits pixel format
From: Randy Li @ 2018-05-20 17:17 UTC (permalink / raw)
To: linux-arm-kernel
This pixel format is current used in the rockchip platform. I think any model
higher than rk322x would support this pixel format. Xilinx may support
it but I am not sure.
More than a year ago, I post the patch Add pixel formats for 10/16 bits
YUV video to the mail list, it has been update to version 8, but they
are not merged yet. So I decide to submit these independent patches,
I hope that they would be reviewed and merged in a short time.
I have added a patch to Gstreamer and it is merged now.
Any future information can be found on the bugzilla of the Gstreamer:
https://bugzilla.gnome.org/show_bug.cgi?id=795462
I have verified this patch on the rk3288, with the following command:
gst-launch-1.0 filesrc location=conv_3840_2160.nv12_10le40 ! \
rawvideoparse format=81 width=3840 height=2160 ! imagefreeze ! kmssink
Also you can find video sample video on above page, but you may need to
set the plane offset and stride when you are using the other files.
Randy Li (2):
drm/fourcc: add a 10bits fully packed variant of NV12
drm/rockchip: Support 10 bits yuv format in vop
drivers/gpu/drm/drm_fourcc.c | 1 +
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 27 +++++++++++++++++++++++++--
drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 1 +
drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 2 ++
include/uapi/drm/drm_fourcc.h | 3 +++
5 files changed, 32 insertions(+), 2 deletions(-)
--
2.14.3
^ permalink raw reply
* [PATCH v1 7/7] arm64: dts: mt7622: add EINT support to pinctrl
From: sean.wang at mediatek.com @ 2018-05-20 17:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1526835466.git.sean.wang@mediatek.com>
From: Sean Wang <sean.wang@mediatek.com>
Add EINT support to pinctrl and set those GPIO keys as interrupt-driven
keys.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts | 2 +-
arch/arm64/boot/dts/mediatek/mt7622.dtsi | 8 +++++++-
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
index b783764..1ff003e 100644
--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
+++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
@@ -34,7 +34,7 @@
};
gpio-keys {
- compatible = "gpio-keys-polled";
+ compatible = "gpio-keys";
poll-interval = <100>;
factory {
diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
index 9213c96..e2c5450 100644
--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
@@ -286,9 +286,15 @@
pio: pinctrl at 10211000 {
compatible = "mediatek,mt7622-pinctrl";
- reg = <0 0x10211000 0 0x1000>;
+ reg = <0 0x10211000 0 0x1000>,
+ <0 0x10005000 0 0x1000>;
+ reg-names = "base", "eint";
gpio-controller;
#gpio-cells = <2>;
+ interrupt-controller;
+ interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+ #interrupt-cells = <2>;
};
watchdog: watchdog at 10212000 {
--
2.7.4
^ permalink raw reply related
* [PATCH v1 6/7] MAINTAINERS: update entry for PIN CONTROLLER - MEDIATEK
From: sean.wang at mediatek.com @ 2018-05-20 17:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1526835466.git.sean.wang@mediatek.com>
From: Sean Wang <sean.wang@mediatek.com>
Add new files for the entry
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
MAINTAINERS | 1 +
1 file changed, 1 insertion(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 9051a9c..7f3cced 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11193,6 +11193,7 @@ L: linux-mediatek at lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt
F: Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt
+F: drivers/pinctrl/mediatek/mtk-eint.*
F: drivers/pinctrl/mediatek/pinctrl-mtk-common.*
F: drivers/pinctrl/mediatek/pinctrl-mt2701.c
F: drivers/pinctrl/mediatek/pinctrl-mt7622.c
--
2.7.4
^ permalink raw reply related
* [PATCH v1 5/7] pinctrl: mediatek: remove unused fields in struct mtk_eint_hw
From: sean.wang at mediatek.com @ 2018-05-20 17:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1526835466.git.sean.wang@mediatek.com>
From: Sean Wang <sean.wang@mediatek.com>
The .name field has been not being used in existent code logic, so
it's better that we remove them all.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
drivers/pinctrl/mediatek/mtk-eint.h | 1 -
drivers/pinctrl/mediatek/pinctrl-mt2701.c | 1 -
drivers/pinctrl/mediatek/pinctrl-mt2712.c | 1 -
drivers/pinctrl/mediatek/pinctrl-mt8127.c | 1 -
drivers/pinctrl/mediatek/pinctrl-mt8135.c | 1 -
drivers/pinctrl/mediatek/pinctrl-mt8173.c | 1 -
6 files changed, 6 deletions(-)
diff --git a/drivers/pinctrl/mediatek/mtk-eint.h b/drivers/pinctrl/mediatek/mtk-eint.h
index 55b4d5f..c286a9b 100644
--- a/drivers/pinctrl/mediatek/mtk-eint.h
+++ b/drivers/pinctrl/mediatek/mtk-eint.h
@@ -33,7 +33,6 @@ struct mtk_eint_regs {
};
struct mtk_eint_hw {
- const char *name;
u8 port_mask;
u8 ports;
unsigned int ap_num;
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt2701.c b/drivers/pinctrl/mediatek/pinctrl-mt2701.c
index db22250..e91c314 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt2701.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt2701.c
@@ -532,7 +532,6 @@ static const struct mtk_pinctrl_devdata mt2701_pinctrl_data = {
.port_mask = 0x1f,
.port_align = 4,
.eint_hw = {
- .name = "mt2701_eint",
.port_mask = 6,
.ports = 6,
.ap_num = 169,
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt2712.c b/drivers/pinctrl/mediatek/pinctrl-mt2712.c
index 6e2acef..8398d55 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt2712.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt2712.c
@@ -577,7 +577,6 @@ static const struct mtk_pinctrl_devdata mt2712_pinctrl_data = {
.port_mask = 0xf,
.port_align = 4,
.eint_hw = {
- .name = "mt2712_eint",
.port_mask = 0xf,
.ports = 8,
.ap_num = 229,
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8127.c b/drivers/pinctrl/mediatek/pinctrl-mt8127.c
index 949a235..2e4cc92 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt8127.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt8127.c
@@ -301,7 +301,6 @@ static const struct mtk_pinctrl_devdata mt8127_pinctrl_data = {
.port_mask = 0xf,
.port_align = 4,
.eint_hw = {
- .name = "mt8127_eint",
.port_mask = 7,
.ports = 6,
.ap_num = 143,
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8135.c b/drivers/pinctrl/mediatek/pinctrl-mt8135.c
index 974a1f43..7f5edfa 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt8135.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt8135.c
@@ -314,7 +314,6 @@ static const struct mtk_pinctrl_devdata mt8135_pinctrl_data = {
.port_mask = 0xf,
.port_align = 4,
.eint_hw = {
- .name = "mt8135_eint",
.port_mask = 7,
.ports = 6,
.ap_num = 192,
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8173.c b/drivers/pinctrl/mediatek/pinctrl-mt8173.c
index a836cee3..c449c9a 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt8173.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt8173.c
@@ -341,7 +341,6 @@ static const struct mtk_pinctrl_devdata mt8173_pinctrl_data = {
.port_mask = 0xf,
.port_align = 4,
.eint_hw = {
- .name = "mt8173_eint",
.port_mask = 7,
.ports = 6,
.ap_num = 224,
--
2.7.4
^ permalink raw reply related
* [PATCH v1 4/7] pinctrl: mediatek: use generic EINT register maps for each SoC
From: sean.wang at mediatek.com @ 2018-05-20 17:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1526835466.git.sean.wang@mediatek.com>
From: Sean Wang <sean.wang@mediatek.com>
So far, EINT on each SoC all used exactly identical register map and thus
it's better that we apply generic register map already supported in EINT
library and stop copy-n-pasting the same data block and filling into its
platform data.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
drivers/pinctrl/mediatek/pinctrl-mt2701.c | 20 --------------------
drivers/pinctrl/mediatek/pinctrl-mt2712.c | 20 --------------------
drivers/pinctrl/mediatek/pinctrl-mt8127.c | 20 --------------------
drivers/pinctrl/mediatek/pinctrl-mt8135.c | 20 --------------------
drivers/pinctrl/mediatek/pinctrl-mt8173.c | 20 --------------------
drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 6 +++++-
drivers/pinctrl/mediatek/pinctrl-mtk-common.h | 2 +-
7 files changed, 6 insertions(+), 102 deletions(-)
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt2701.c b/drivers/pinctrl/mediatek/pinctrl-mt2701.c
index e0963c6..db22250 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt2701.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt2701.c
@@ -538,26 +538,6 @@ static const struct mtk_pinctrl_devdata mt2701_pinctrl_data = {
.ap_num = 169,
.db_cnt = 16,
},
- .eint_regs = {
- .stat = 0x000,
- .ack = 0x040,
- .mask = 0x080,
- .mask_set = 0x0c0,
- .mask_clr = 0x100,
- .sens = 0x140,
- .sens_set = 0x180,
- .sens_clr = 0x1c0,
- .soft = 0x200,
- .soft_set = 0x240,
- .soft_clr = 0x280,
- .pol = 0x300,
- .pol_set = 0x340,
- .pol_clr = 0x380,
- .dom_en = 0x400,
- .dbnc_ctrl = 0x500,
- .dbnc_set = 0x600,
- .dbnc_clr = 0x700,
- },
};
static int mt2701_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt2712.c b/drivers/pinctrl/mediatek/pinctrl-mt2712.c
index 02aff28..6e2acef 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt2712.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt2712.c
@@ -583,26 +583,6 @@ static const struct mtk_pinctrl_devdata mt2712_pinctrl_data = {
.ap_num = 229,
.db_cnt = 40,
},
- .eint_regs = {
- .stat = 0x000,
- .ack = 0x040,
- .mask = 0x080,
- .mask_set = 0x0c0,
- .mask_clr = 0x100,
- .sens = 0x140,
- .sens_set = 0x180,
- .sens_clr = 0x1c0,
- .soft = 0x200,
- .soft_set = 0x240,
- .soft_clr = 0x280,
- .pol = 0x300,
- .pol_set = 0x340,
- .pol_clr = 0x380,
- .dom_en = 0x400,
- .dbnc_ctrl = 0x500,
- .dbnc_set = 0x600,
- .dbnc_clr = 0x700,
- },
};
static int mt2712_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8127.c b/drivers/pinctrl/mediatek/pinctrl-mt8127.c
index 71f6258..949a235 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt8127.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt8127.c
@@ -307,26 +307,6 @@ static const struct mtk_pinctrl_devdata mt8127_pinctrl_data = {
.ap_num = 143,
.db_cnt = 16,
},
- .eint_regs = {
- .stat = 0x000,
- .ack = 0x040,
- .mask = 0x080,
- .mask_set = 0x0c0,
- .mask_clr = 0x100,
- .sens = 0x140,
- .sens_set = 0x180,
- .sens_clr = 0x1c0,
- .soft = 0x200,
- .soft_set = 0x240,
- .soft_clr = 0x280,
- .pol = 0x300,
- .pol_set = 0x340,
- .pol_clr = 0x380,
- .dom_en = 0x400,
- .dbnc_ctrl = 0x500,
- .dbnc_set = 0x600,
- .dbnc_clr = 0x700,
- },
};
static int mt8127_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8135.c b/drivers/pinctrl/mediatek/pinctrl-mt8135.c
index fdfa357..974a1f43 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt8135.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt8135.c
@@ -320,26 +320,6 @@ static const struct mtk_pinctrl_devdata mt8135_pinctrl_data = {
.ap_num = 192,
.db_cnt = 16,
},
- .eint_regs = {
- .stat = 0x000,
- .ack = 0x040,
- .mask = 0x080,
- .mask_set = 0x0c0,
- .mask_clr = 0x100,
- .sens = 0x140,
- .sens_set = 0x180,
- .sens_clr = 0x1c0,
- .soft = 0x200,
- .soft_set = 0x240,
- .soft_clr = 0x280,
- .pol = 0x300,
- .pol_set = 0x340,
- .pol_clr = 0x380,
- .dom_en = 0x400,
- .dbnc_ctrl = 0x500,
- .dbnc_set = 0x600,
- .dbnc_clr = 0x700,
- },
};
static int mt8135_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8173.c b/drivers/pinctrl/mediatek/pinctrl-mt8173.c
index 1466c95..a836cee3 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt8173.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt8173.c
@@ -347,26 +347,6 @@ static const struct mtk_pinctrl_devdata mt8173_pinctrl_data = {
.ap_num = 224,
.db_cnt = 16,
},
- .eint_regs = {
- .stat = 0x000,
- .ack = 0x040,
- .mask = 0x080,
- .mask_set = 0x0c0,
- .mask_clr = 0x100,
- .sens = 0x140,
- .sens_set = 0x180,
- .sens_clr = 0x1c0,
- .soft = 0x200,
- .soft_set = 0x240,
- .soft_clr = 0x280,
- .pol = 0x300,
- .pol_set = 0x340,
- .pol_clr = 0x380,
- .dom_en = 0x400,
- .dbnc_ctrl = 0x500,
- .dbnc_set = 0x600,
- .dbnc_clr = 0x700,
- },
};
static int mt8173_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
index 11e0d0f..b379969 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
@@ -1014,7 +1014,11 @@ static int mtk_eint_init(struct mtk_pinctrl *pctl, struct platform_device *pdev)
return -EINVAL;
pctl->eint->dev = &pdev->dev;
- pctl->eint->regs = &pctl->devdata->eint_regs;
+ /*
+ * If pctl->eint->regs == NULL, it would fall back into using a generic
+ * register map in mtk_eint_do_init calls.
+ */
+ pctl->eint->regs = pctl->devdata->eint_regs;
pctl->eint->hw = &pctl->devdata->eint_hw;
pctl->eint->pctl = pctl;
pctl->eint->gpio_xlate = &mtk_eint_xt;
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
index 346e3db..bf13eb0 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
@@ -261,7 +261,7 @@ struct mtk_pinctrl_devdata {
unsigned char port_mask;
unsigned char port_align;
struct mtk_eint_hw eint_hw;
- struct mtk_eint_regs eint_regs;
+ struct mtk_eint_regs *eint_regs;
};
struct mtk_pinctrl {
--
2.7.4
^ permalink raw reply related
* [PATCH v1 3/7] pinctrl: mediatek: add EINT support to MT7622 SoC
From: sean.wang at mediatek.com @ 2018-05-20 17:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1526835466.git.sean.wang@mediatek.com>
From: Sean Wang <sean.wang@mediatek.com>
Add EINT support to MT7622 SoC and the support is made as just an option
to MT7622 pinctrl.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
drivers/pinctrl/mediatek/Kconfig | 2 +-
drivers/pinctrl/mediatek/pinctrl-mt7622.c | 143 ++++++++++++++++++++++++++++++
2 files changed, 144 insertions(+), 1 deletion(-)
diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
index 310db42..9905dc6 100644
--- a/drivers/pinctrl/mediatek/Kconfig
+++ b/drivers/pinctrl/mediatek/Kconfig
@@ -3,7 +3,7 @@ menu "MediaTek pinctrl drivers"
config EINT_MTK
bool "MediaTek External Interrupt Support"
- depends on PINCTRL_MTK || COMPILE_TEST
+ depends on PINCTRL_MTK || PINCTRL_MT7622 || COMPILE_TEST
select IRQ_DOMAIN
config PINCTRL_MTK
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7622.c b/drivers/pinctrl/mediatek/pinctrl-mt7622.c
index 06e8406..ad6da11 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt7622.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt7622.c
@@ -19,6 +19,7 @@
#include <linux/init.h>
#include <linux/mfd/syscon.h>
#include <linux/of.h>
+#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/pinctrl.h>
@@ -30,6 +31,7 @@
#include "../core.h"
#include "../pinconf.h"
#include "../pinmux.h"
+#include "mtk-eint.h"
#define PINCTRL_PINCTRL_DEV KBUILD_MODNAME
#define MTK_RANGE(_a) { .range = (_a), .nranges = ARRAY_SIZE(_a), }
@@ -123,6 +125,8 @@ struct mtk_pin_soc {
unsigned int ngrps;
const struct function_desc *funcs;
unsigned int nfuncs;
+ const struct mtk_eint_regs *eint_regs;
+ const struct mtk_eint_hw *eint_hw;
};
struct mtk_pinctrl {
@@ -131,6 +135,7 @@ struct mtk_pinctrl {
struct device *dev;
struct gpio_chip chip;
const struct mtk_pin_soc *soc;
+ struct mtk_eint *eint;
};
static const struct mtk_pin_field_calc mt7622_pin_mode_range[] = {
@@ -913,6 +918,13 @@ static const struct pin_config_item mtk_conf_items[] = {
};
#endif
+static const struct mtk_eint_hw mt7622_eint_hw = {
+ .port_mask = 7,
+ .ports = 7,
+ .ap_num = ARRAY_SIZE(mt7622_pins),
+ .db_cnt = 20,
+};
+
static const struct mtk_pin_soc mt7622_data = {
.reg_cal = mt7622_reg_cals,
.pins = mt7622_pins,
@@ -921,6 +933,7 @@ static const struct mtk_pin_soc mt7622_data = {
.ngrps = ARRAY_SIZE(mt7622_groups),
.funcs = mt7622_functions,
.nfuncs = ARRAY_SIZE(mt7622_functions),
+ .eint_hw = &mt7622_eint_hw,
};
static void mtk_w32(struct mtk_pinctrl *pctl, u32 reg, u32 val)
@@ -1441,6 +1454,32 @@ static int mtk_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio,
return pinctrl_gpio_direction_output(chip->base + gpio);
}
+static int mtk_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
+{
+ struct mtk_pinctrl *hw = gpiochip_get_data(chip);
+ unsigned long eint_n;
+
+ eint_n = offset;
+
+ return mtk_eint_find_irq(hw->eint, eint_n);
+}
+
+static int mtk_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
+ unsigned long config)
+{
+ struct mtk_pinctrl *hw = gpiochip_get_data(chip);
+ unsigned long eint_n;
+ u32 debounce;
+
+ if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
+ return -ENOTSUPP;
+
+ debounce = pinconf_to_config_argument(config);
+ eint_n = offset;
+
+ return mtk_eint_set_debounce(hw->eint, eint_n, debounce);
+}
+
static int mtk_build_gpiochip(struct mtk_pinctrl *hw, struct device_node *np)
{
struct gpio_chip *chip = &hw->chip;
@@ -1454,6 +1493,8 @@ static int mtk_build_gpiochip(struct mtk_pinctrl *hw, struct device_node *np)
chip->direction_output = mtk_gpio_direction_output;
chip->get = mtk_gpio_get;
chip->set = mtk_gpio_set;
+ chip->to_irq = mtk_gpio_to_irq,
+ chip->set_config = mtk_gpio_set_config,
chip->base = -1;
chip->ngpio = hw->soc->npins;
chip->of_node = np;
@@ -1514,6 +1555,103 @@ static int mtk_build_functions(struct mtk_pinctrl *hw)
return 0;
}
+static int mtk_xt_get_gpio_n(void *data, unsigned long eint_n,
+ unsigned int *gpio_n,
+ struct gpio_chip **gpio_chip)
+{
+ struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data;
+
+ *gpio_chip = &hw->chip;
+ *gpio_n = eint_n;
+
+ return 0;
+}
+
+static int mtk_xt_get_gpio_state(void *data, unsigned long eint_n)
+{
+ struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data;
+ struct gpio_chip *gpio_chip;
+ unsigned int gpio_n;
+ int err;
+
+ err = mtk_xt_get_gpio_n(hw, eint_n, &gpio_n, &gpio_chip);
+ if (err)
+ return err;
+
+ return mtk_gpio_get(gpio_chip, gpio_n);
+}
+
+static int mtk_xt_set_gpio_as_eint(void *data, unsigned long eint_n)
+{
+ struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data;
+ struct gpio_chip *gpio_chip;
+ unsigned int gpio_n;
+ int err;
+
+ err = mtk_xt_get_gpio_n(hw, eint_n, &gpio_n, &gpio_chip);
+ if (err)
+ return err;
+
+ err = mtk_hw_set_value(hw, gpio_n, PINCTRL_PIN_REG_MODE,
+ MTK_GPIO_MODE);
+ if (err)
+ return err;
+
+ err = mtk_hw_set_value(hw, gpio_n, PINCTRL_PIN_REG_DIR, MTK_INPUT);
+ if (err)
+ return err;
+
+ err = mtk_hw_set_value(hw, gpio_n, PINCTRL_PIN_REG_SMT, MTK_ENABLE);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static const struct mtk_eint_xt mtk_eint_xt = {
+ .get_gpio_n = mtk_xt_get_gpio_n,
+ .get_gpio_state = mtk_xt_get_gpio_state,
+ .set_gpio_as_eint = mtk_xt_set_gpio_as_eint,
+};
+
+static int
+mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct resource *res;
+
+ if (!IS_ENABLED(CONFIG_EINT_MTK))
+ return 0;
+
+ if (!of_property_read_bool(np, "interrupt-controller"))
+ return -ENODEV;
+
+ hw->eint = devm_kzalloc(hw->dev, sizeof(*hw->eint), GFP_KERNEL);
+ if (!hw->eint)
+ return -ENOMEM;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "eint");
+ if (!res) {
+ dev_err(&pdev->dev, "Unable to get eint resource\n");
+ return -ENODEV;
+ }
+
+ hw->eint->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(hw->eint->base))
+ return PTR_ERR(hw->eint->base);
+
+ hw->eint->irq = irq_of_parse_and_map(np, 0);
+ if (!hw->eint->irq)
+ return -EINVAL;
+
+ hw->eint->dev = &pdev->dev;
+ hw->eint->hw = hw->soc->eint_hw;
+ hw->eint->pctl = hw;
+ hw->eint->gpio_xlate = &mtk_eint_xt;
+
+ return mtk_eint_do_init(hw->eint);
+}
+
static const struct of_device_id mtk_pinctrl_of_match[] = {
{ .compatible = "mediatek,mt7622-pinctrl", .data = &mt7622_data},
{ }
@@ -1577,6 +1715,11 @@ static int mtk_pinctrl_probe(struct platform_device *pdev)
return err;
}
+ err = mtk_build_eint(hw, pdev);
+ if (err)
+ dev_warn(&pdev->dev,
+ "Failed to add EINT, but pinctrl still can work\n");
+
platform_set_drvdata(pdev, hw);
return 0;
--
2.7.4
^ permalink raw reply related
* [PATCH v1 2/7] pinctrl: mediatek: refactor EINT related code for all MediaTek pinctrl can fit
From: sean.wang at mediatek.com @ 2018-05-20 17:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1526835466.git.sean.wang@mediatek.com>
From: Sean Wang <sean.wang@mediatek.com>
This patch is in preparation for adding EINT support to MT7622 pinctrl,
and the refactoring doesn't alter any existent logic.
A reason we have to refactor EINT code pieces into a generic way is that
currently, they're tightly coupled with a certain type of MediaTek pinctrl
would cause a grown in a very bad way as there is different types of
pinctrl devices getting to join.
Therefore, it is an essential or urgent thing that EINT code pieces are
refactored to eliminate any dependencies across GPIO and EINT as possible.
Additional structure mtk_eint_[xt, hw, regs] are being introduced for
indicating how maps being designed between GPIO and EINT hw number, how to
set and get GPIO state for a certain EINT pin, what characteristic on a
EINT device is present on various SoCs.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
drivers/pinctrl/mediatek/Kconfig | 6 +
drivers/pinctrl/mediatek/Makefile | 1 +
drivers/pinctrl/mediatek/mtk-eint.c | 492 +++++++++++++++++++++
drivers/pinctrl/mediatek/mtk-eint.h | 107 +++++
drivers/pinctrl/mediatek/pinctrl-mt2701.c | 12 +-
drivers/pinctrl/mediatek/pinctrl-mt2712.c | 12 +-
drivers/pinctrl/mediatek/pinctrl-mt8127.c | 12 +-
drivers/pinctrl/mediatek/pinctrl-mt8135.c | 12 +-
drivers/pinctrl/mediatek/pinctrl-mt8173.c | 12 +-
drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 604 +++++---------------------
drivers/pinctrl/mediatek/pinctrl-mtk-common.h | 13 +-
11 files changed, 756 insertions(+), 527 deletions(-)
create mode 100644 drivers/pinctrl/mediatek/mtk-eint.c
create mode 100644 drivers/pinctrl/mediatek/mtk-eint.h
diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
index 862c5db..310db42 100644
--- a/drivers/pinctrl/mediatek/Kconfig
+++ b/drivers/pinctrl/mediatek/Kconfig
@@ -1,12 +1,18 @@
menu "MediaTek pinctrl drivers"
depends on ARCH_MEDIATEK || COMPILE_TEST
+config EINT_MTK
+ bool "MediaTek External Interrupt Support"
+ depends on PINCTRL_MTK || COMPILE_TEST
+ select IRQ_DOMAIN
+
config PINCTRL_MTK
bool
depends on OF
select PINMUX
select GENERIC_PINCONF
select GPIOLIB
+ select EINT_MTK
select OF_GPIO
# For ARMv7 SoCs
diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile
index 7959e77..3de7156 100644
--- a/drivers/pinctrl/mediatek/Makefile
+++ b/drivers/pinctrl/mediatek/Makefile
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
# Core
+obj-$(CONFIG_EINT_MTK) += mtk-eint.o
obj-$(CONFIG_PINCTRL_MTK) += pinctrl-mtk-common.o
# SoC Drivers
diff --git a/drivers/pinctrl/mediatek/mtk-eint.c b/drivers/pinctrl/mediatek/mtk-eint.c
new file mode 100644
index 0000000..30f3316
--- /dev/null
+++ b/drivers/pinctrl/mediatek/mtk-eint.c
@@ -0,0 +1,492 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2014-2018 MediaTek Inc.
+
+/*
+ * Library for MediaTek External Interrupt Support
+ *
+ * Author: Maoguang Meng <maoguang.meng@mediatek.com>
+ * Sean Wang <sean.wang@mediatek.com>
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+
+#include "mtk-eint.h"
+
+#define MTK_EINT_EDGE_SENSITIVE 0
+#define MTK_EINT_LEVEL_SENSITIVE 1
+#define MTK_EINT_DBNC_SET_DBNC_BITS 4
+#define MTK_EINT_DBNC_RST_BIT (0x1 << 1)
+#define MTK_EINT_DBNC_SET_EN (0x1 << 0)
+
+static const struct mtk_eint_regs mtk_generic_eint_regs = {
+ .stat = 0x000,
+ .ack = 0x040,
+ .mask = 0x080,
+ .mask_set = 0x0c0,
+ .mask_clr = 0x100,
+ .sens = 0x140,
+ .sens_set = 0x180,
+ .sens_clr = 0x1c0,
+ .soft = 0x200,
+ .soft_set = 0x240,
+ .soft_clr = 0x280,
+ .pol = 0x300,
+ .pol_set = 0x340,
+ .pol_clr = 0x380,
+ .dom_en = 0x400,
+ .dbnc_ctrl = 0x500,
+ .dbnc_set = 0x600,
+ .dbnc_clr = 0x700,
+};
+
+static void __iomem *mtk_eint_get_offset(struct mtk_eint *eint,
+ unsigned int eint_num,
+ unsigned int offset)
+{
+ unsigned int eint_base = 0;
+ void __iomem *reg;
+
+ if (eint_num >= eint->hw->ap_num)
+ eint_base = eint->hw->ap_num;
+
+ reg = eint->base + offset + ((eint_num - eint_base) / 32) * 4;
+
+ return reg;
+}
+
+static unsigned int mtk_eint_can_en_debounce(struct mtk_eint *eint,
+ unsigned int eint_num)
+{
+ unsigned int sens;
+ unsigned int bit = BIT(eint_num % 32);
+ void __iomem *reg = mtk_eint_get_offset(eint, eint_num,
+ eint->regs->sens);
+
+ if (readl(reg) & bit)
+ sens = MTK_EINT_LEVEL_SENSITIVE;
+ else
+ sens = MTK_EINT_EDGE_SENSITIVE;
+
+ if (eint_num < eint->hw->db_cnt && sens != MTK_EINT_EDGE_SENSITIVE)
+ return 1;
+ else
+ return 0;
+}
+
+static int mtk_eint_flip_edge(struct mtk_eint *eint, int hwirq)
+{
+ int start_level, curr_level;
+ unsigned int reg_offset;
+ u32 mask = BIT(hwirq & 0x1f);
+ u32 port = (hwirq >> 5) & eint->hw->port_mask;
+ void __iomem *reg = eint->base + (port << 2);
+
+ curr_level = eint->gpio_xlate->get_gpio_state(eint->pctl, hwirq);
+
+ do {
+ start_level = curr_level;
+ if (start_level)
+ reg_offset = eint->regs->pol_clr;
+ else
+ reg_offset = eint->regs->pol_set;
+ writel(mask, reg + reg_offset);
+
+ curr_level = eint->gpio_xlate->get_gpio_state(eint->pctl,
+ hwirq);
+ } while (start_level != curr_level);
+
+ return start_level;
+}
+
+static void mtk_eint_mask(struct irq_data *d)
+{
+ struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
+ u32 mask = BIT(d->hwirq & 0x1f);
+ void __iomem *reg = mtk_eint_get_offset(eint, d->hwirq,
+ eint->regs->mask_set);
+
+ writel(mask, reg);
+}
+
+static void mtk_eint_unmask(struct irq_data *d)
+{
+ struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
+ u32 mask = BIT(d->hwirq & 0x1f);
+ void __iomem *reg = mtk_eint_get_offset(eint, d->hwirq,
+ eint->regs->mask_clr);
+
+ writel(mask, reg);
+
+ if (eint->dual_edge[d->hwirq])
+ mtk_eint_flip_edge(eint, d->hwirq);
+}
+
+static unsigned int mtk_eint_get_mask(struct mtk_eint *eint,
+ unsigned int eint_num)
+{
+ unsigned int bit = BIT(eint_num % 32);
+ void __iomem *reg = mtk_eint_get_offset(eint, eint_num,
+ eint->regs->mask);
+
+ return !!(readl(reg) & bit);
+}
+
+static void mtk_eint_ack(struct irq_data *d)
+{
+ struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
+ u32 mask = BIT(d->hwirq & 0x1f);
+ void __iomem *reg = mtk_eint_get_offset(eint, d->hwirq,
+ eint->regs->ack);
+
+ writel(mask, reg);
+}
+
+static int mtk_eint_set_type(struct irq_data *d, unsigned int type)
+{
+ struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
+ u32 mask = BIT(d->hwirq & 0x1f);
+ void __iomem *reg;
+
+ if (((type & IRQ_TYPE_EDGE_BOTH) && (type & IRQ_TYPE_LEVEL_MASK)) ||
+ ((type & IRQ_TYPE_LEVEL_MASK) == IRQ_TYPE_LEVEL_MASK)) {
+ dev_err(eint->dev,
+ "Can't configure IRQ%d (EINT%lu) for type 0x%X\n",
+ d->irq, d->hwirq, type);
+ return -EINVAL;
+ }
+
+ if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
+ eint->dual_edge[d->hwirq] = 1;
+ else
+ eint->dual_edge[d->hwirq] = 0;
+
+ if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING)) {
+ reg = mtk_eint_get_offset(eint, d->hwirq, eint->regs->pol_clr);
+ writel(mask, reg);
+ } else {
+ reg = mtk_eint_get_offset(eint, d->hwirq, eint->regs->pol_set);
+ writel(mask, reg);
+ }
+
+ if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
+ reg = mtk_eint_get_offset(eint, d->hwirq, eint->regs->sens_clr);
+ writel(mask, reg);
+ } else {
+ reg = mtk_eint_get_offset(eint, d->hwirq, eint->regs->sens_set);
+ writel(mask, reg);
+ }
+
+ if (eint->dual_edge[d->hwirq])
+ mtk_eint_flip_edge(eint, d->hwirq);
+
+ return 0;
+}
+
+static int mtk_eint_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+ struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
+ int shift = d->hwirq & 0x1f;
+ int reg = d->hwirq >> 5;
+
+ if (on)
+ eint->wake_mask[reg] |= BIT(shift);
+ else
+ eint->wake_mask[reg] &= ~BIT(shift);
+
+ return 0;
+}
+
+static void mtk_eint_chip_write_mask(const struct mtk_eint *eint,
+ void __iomem *base, u32 *buf)
+{
+ int port;
+ void __iomem *reg;
+
+ for (port = 0; port < eint->hw->ports; port++) {
+ reg = base + (port << 2);
+ writel_relaxed(~buf[port], reg + eint->regs->mask_set);
+ writel_relaxed(buf[port], reg + eint->regs->mask_clr);
+ }
+}
+
+static void mtk_eint_chip_read_mask(const struct mtk_eint *eint,
+ void __iomem *base, u32 *buf)
+{
+ int port;
+ void __iomem *reg;
+
+ for (port = 0; port < eint->hw->ports; port++) {
+ reg = base + eint->regs->mask + (port << 2);
+ buf[port] = ~readl_relaxed(reg);
+ /* Mask is 0 when irq is enabled, and 1 when disabled. */
+ }
+}
+
+static int mtk_eint_irq_request_resources(struct irq_data *d)
+{
+ struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gpio_c;
+ unsigned int gpio_n;
+ int err;
+
+ err = eint->gpio_xlate->get_gpio_n(eint->pctl, d->hwirq,
+ &gpio_n, &gpio_c);
+ if (err < 0) {
+ dev_err(eint->dev, "Can not find pin\n");
+ return err;
+ }
+
+ err = gpiochip_lock_as_irq(gpio_c, gpio_n);
+ if (err < 0) {
+ dev_err(eint->dev, "unable to lock HW IRQ %lu for IRQ\n",
+ irqd_to_hwirq(d));
+ return err;
+ }
+
+ err = eint->gpio_xlate->set_gpio_as_eint(eint->pctl, d->hwirq);
+ if (err < 0) {
+ dev_err(eint->dev, "Can not eint mode\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static void mtk_eint_irq_release_resources(struct irq_data *d)
+{
+ struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gpio_c;
+ unsigned int gpio_n;
+
+ eint->gpio_xlate->get_gpio_n(eint->pctl, d->hwirq, &gpio_n,
+ &gpio_c);
+
+ gpiochip_unlock_as_irq(gpio_c, gpio_n);
+}
+
+static struct irq_chip mtk_eint_irq_chip = {
+ .name = "mt-eint",
+ .irq_disable = mtk_eint_mask,
+ .irq_mask = mtk_eint_mask,
+ .irq_unmask = mtk_eint_unmask,
+ .irq_ack = mtk_eint_ack,
+ .irq_set_type = mtk_eint_set_type,
+ .irq_set_wake = mtk_eint_irq_set_wake,
+ .irq_request_resources = mtk_eint_irq_request_resources,
+ .irq_release_resources = mtk_eint_irq_release_resources,
+};
+
+static unsigned int mtk_eint_hw_init(struct mtk_eint *eint)
+{
+ void __iomem *reg = eint->base + eint->regs->dom_en;
+ unsigned int i;
+
+ for (i = 0; i < eint->hw->ap_num; i += 32) {
+ writel(0xffffffff, reg);
+ reg += 4;
+ }
+
+ return 0;
+}
+
+static inline void
+mtk_eint_debounce_process(struct mtk_eint *eint, int index)
+{
+ unsigned int rst, ctrl_offset;
+ unsigned int bit, dbnc;
+
+ ctrl_offset = (index / 4) * 4 + eint->regs->dbnc_ctrl;
+ dbnc = readl(eint->base + ctrl_offset);
+ bit = MTK_EINT_DBNC_SET_EN << ((index % 4) * 8);
+ if ((bit & dbnc) > 0) {
+ ctrl_offset = (index / 4) * 4 + eint->regs->dbnc_set;
+ rst = MTK_EINT_DBNC_RST_BIT << ((index % 4) * 8);
+ writel(rst, eint->base + ctrl_offset);
+ }
+}
+
+static void mtk_eint_irq_handler(struct irq_desc *desc)
+{
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct mtk_eint *eint = irq_desc_get_handler_data(desc);
+ unsigned int status, eint_num;
+ int offset, index, virq;
+ void __iomem *reg = mtk_eint_get_offset(eint, 0, eint->regs->stat);
+ int dual_edge, start_level, curr_level;
+
+ chained_irq_enter(chip, desc);
+ for (eint_num = 0; eint_num < eint->hw->ap_num; eint_num += 32,
+ reg += 4) {
+ status = readl(reg);
+ while (status) {
+ offset = __ffs(status);
+ index = eint_num + offset;
+ virq = irq_find_mapping(eint->domain, index);
+ status &= ~BIT(offset);
+
+ dual_edge = eint->dual_edge[index];
+ if (dual_edge) {
+ /*
+ * Clear soft-irq in case we raised it last
+ * time.
+ */
+ writel(BIT(offset), reg - eint->regs->stat +
+ eint->regs->soft_clr);
+
+ start_level =
+ eint->gpio_xlate->get_gpio_state(eint->pctl,
+ index);
+ }
+
+ generic_handle_irq(virq);
+
+ if (dual_edge) {
+ curr_level = mtk_eint_flip_edge(eint, index);
+
+ /*
+ * If level changed, we might lost one edge
+ * interrupt, raised it through soft-irq.
+ */
+ if (start_level != curr_level)
+ writel(BIT(offset), reg -
+ eint->regs->stat +
+ eint->regs->soft_set);
+ }
+
+ if (index < eint->hw->db_cnt)
+ mtk_eint_debounce_process(eint, index);
+ }
+ }
+ chained_irq_exit(chip, desc);
+}
+
+int mtk_eint_do_suspend(struct mtk_eint *eint)
+{
+ mtk_eint_chip_read_mask(eint, eint->base, eint->cur_mask);
+ mtk_eint_chip_write_mask(eint, eint->base, eint->wake_mask);
+
+ return 0;
+}
+
+int mtk_eint_do_resume(struct mtk_eint *eint)
+{
+ mtk_eint_chip_write_mask(eint, eint->base, eint->cur_mask);
+
+ return 0;
+}
+
+int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_num,
+ unsigned int debounce)
+{
+ int virq, eint_offset;
+ unsigned int set_offset, bit, clr_bit, clr_offset, rst, i, unmask,
+ dbnc;
+ static const unsigned int debounce_time[] = {500, 1000, 16000, 32000,
+ 64000, 128000, 256000};
+ struct irq_data *d;
+
+ virq = irq_find_mapping(eint->domain, eint_num);
+ eint_offset = (eint_num % 4) * 8;
+ d = irq_get_irq_data(virq);
+
+ set_offset = (eint_num / 4) * 4 + eint->regs->dbnc_set;
+ clr_offset = (eint_num / 4) * 4 + eint->regs->dbnc_clr;
+
+ if (!mtk_eint_can_en_debounce(eint, eint_num))
+ return -EINVAL;
+
+ dbnc = ARRAY_SIZE(debounce_time);
+ for (i = 0; i < ARRAY_SIZE(debounce_time); i++) {
+ if (debounce <= debounce_time[i]) {
+ dbnc = i;
+ break;
+ }
+ }
+
+ if (!mtk_eint_get_mask(eint, eint_num)) {
+ mtk_eint_mask(d);
+ unmask = 1;
+ } else {
+ unmask = 0;
+ }
+
+ clr_bit = 0xff << eint_offset;
+ writel(clr_bit, eint->base + clr_offset);
+
+ bit = ((dbnc << MTK_EINT_DBNC_SET_DBNC_BITS) | MTK_EINT_DBNC_SET_EN) <<
+ eint_offset;
+ rst = MTK_EINT_DBNC_RST_BIT << eint_offset;
+ writel(rst | bit, eint->base + set_offset);
+
+ /*
+ * Delay a while (more than 2T) to wait for hw debounce counter reset
+ * work correctly.
+ */
+ udelay(1);
+ if (unmask == 1)
+ mtk_eint_unmask(d);
+
+ return 0;
+}
+
+int mtk_eint_find_irq(struct mtk_eint *eint, unsigned long eint_n)
+{
+ int irq;
+
+ irq = irq_find_mapping(eint->domain, eint_n);
+ if (!irq)
+ return -EINVAL;
+
+ return irq;
+}
+
+int mtk_eint_do_init(struct mtk_eint *eint)
+{
+ int i;
+
+ /* If clients don't assign a specific regs, let's use generic one */
+ if (!eint->regs)
+ eint->regs = &mtk_generic_eint_regs;
+
+ eint->wake_mask = devm_kcalloc(eint->dev, eint->hw->ports,
+ sizeof(*eint->wake_mask), GFP_KERNEL);
+ if (!eint->wake_mask)
+ return -ENOMEM;
+
+ eint->cur_mask = devm_kcalloc(eint->dev, eint->hw->ports,
+ sizeof(*eint->cur_mask), GFP_KERNEL);
+ if (!eint->cur_mask)
+ return -ENOMEM;
+
+ eint->dual_edge = devm_kcalloc(eint->dev, eint->hw->ap_num,
+ sizeof(int), GFP_KERNEL);
+ if (!eint->dual_edge)
+ return -ENOMEM;
+
+ eint->domain = irq_domain_add_linear(eint->dev->of_node,
+ eint->hw->ap_num,
+ &irq_domain_simple_ops, NULL);
+ if (!eint->domain)
+ return -ENOMEM;
+
+ mtk_eint_hw_init(eint);
+ for (i = 0; i < eint->hw->ap_num; i++) {
+ int virq = irq_create_mapping(eint->domain, i);
+
+ irq_set_chip_and_handler(virq, &mtk_eint_irq_chip,
+ handle_level_irq);
+ irq_set_chip_data(virq, eint);
+ }
+
+ irq_set_chained_handler_and_data(eint->irq, mtk_eint_irq_handler,
+ eint);
+
+ return 0;
+}
diff --git a/drivers/pinctrl/mediatek/mtk-eint.h b/drivers/pinctrl/mediatek/mtk-eint.h
new file mode 100644
index 0000000..55b4d5f
--- /dev/null
+++ b/drivers/pinctrl/mediatek/mtk-eint.h
@@ -0,0 +1,107 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2014-2018 MediaTek Inc.
+ *
+ * Author: Maoguang Meng <maoguang.meng@mediatek.com>
+ * Sean Wang <sean.wang@mediatek.com>
+ *
+ */
+#ifndef __MTK_EINT_H
+#define __MTK_EINT_H
+
+#include <linux/irqdomain.h>
+
+struct mtk_eint_regs {
+ unsigned int stat;
+ unsigned int ack;
+ unsigned int mask;
+ unsigned int mask_set;
+ unsigned int mask_clr;
+ unsigned int sens;
+ unsigned int sens_set;
+ unsigned int sens_clr;
+ unsigned int soft;
+ unsigned int soft_set;
+ unsigned int soft_clr;
+ unsigned int pol;
+ unsigned int pol_set;
+ unsigned int pol_clr;
+ unsigned int dom_en;
+ unsigned int dbnc_ctrl;
+ unsigned int dbnc_set;
+ unsigned int dbnc_clr;
+};
+
+struct mtk_eint_hw {
+ const char *name;
+ u8 port_mask;
+ u8 ports;
+ unsigned int ap_num;
+ unsigned int db_cnt;
+};
+
+struct mtk_eint;
+
+struct mtk_eint_xt {
+ int (*get_gpio_n)(void *data, unsigned long eint_n,
+ unsigned int *gpio_n,
+ struct gpio_chip **gpio_chip);
+ int (*get_gpio_state)(void *data, unsigned long eint_n);
+ int (*set_gpio_as_eint)(void *data, unsigned long eint_n);
+};
+
+struct mtk_eint {
+ struct device *dev;
+ void __iomem *base;
+ struct irq_domain *domain;
+ int irq;
+
+ int *dual_edge;
+ u32 *wake_mask;
+ u32 *cur_mask;
+
+ /* Used to fit into various EINT device */
+ const struct mtk_eint_hw *hw;
+ const struct mtk_eint_regs *regs;
+
+ /* Used to fit into various pinctrl device */
+ void *pctl;
+ const struct mtk_eint_xt *gpio_xlate;
+};
+
+#if IS_ENABLED(CONFIG_EINT_MTK)
+int mtk_eint_do_init(struct mtk_eint *eint);
+int mtk_eint_do_suspend(struct mtk_eint *eint);
+int mtk_eint_do_resume(struct mtk_eint *eint);
+int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_n,
+ unsigned int debounce);
+int mtk_eint_find_irq(struct mtk_eint *eint, unsigned long eint_n);
+
+#else
+static inline int mtk_eint_do_init(struct mtk_eint *eint)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int mtk_eint_do_suspend(struct mtk_eint *eint)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int mtk_eint_do_resume(struct mtk_eint *eint)
+{
+ return -EOPNOTSUPP;
+}
+
+int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_n,
+ unsigned int debounce)
+{
+ return -EOPNOTSUPP;
+}
+
+int mtk_eint_find_irq(struct mtk_eint *eint, unsigned long eint_n)
+{
+ return -EOPNOTSUPP;
+}
+#endif
+#endif /* __MTK_EINT_H */
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt2701.c b/drivers/pinctrl/mediatek/pinctrl-mt2701.c
index f86f3b3..e0963c6 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt2701.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt2701.c
@@ -531,8 +531,14 @@ static const struct mtk_pinctrl_devdata mt2701_pinctrl_data = {
.port_shf = 4,
.port_mask = 0x1f,
.port_align = 4,
- .eint_offsets = {
+ .eint_hw = {
.name = "mt2701_eint",
+ .port_mask = 6,
+ .ports = 6,
+ .ap_num = 169,
+ .db_cnt = 16,
+ },
+ .eint_regs = {
.stat = 0x000,
.ack = 0x040,
.mask = 0x080,
@@ -551,11 +557,7 @@ static const struct mtk_pinctrl_devdata mt2701_pinctrl_data = {
.dbnc_ctrl = 0x500,
.dbnc_set = 0x600,
.dbnc_clr = 0x700,
- .port_mask = 6,
- .ports = 6,
},
- .ap_num = 169,
- .db_cnt = 16,
};
static int mt2701_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt2712.c b/drivers/pinctrl/mediatek/pinctrl-mt2712.c
index 81e11f9..02aff28 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt2712.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt2712.c
@@ -576,8 +576,14 @@ static const struct mtk_pinctrl_devdata mt2712_pinctrl_data = {
.port_shf = 4,
.port_mask = 0xf,
.port_align = 4,
- .eint_offsets = {
+ .eint_hw = {
.name = "mt2712_eint",
+ .port_mask = 0xf,
+ .ports = 8,
+ .ap_num = 229,
+ .db_cnt = 40,
+ },
+ .eint_regs = {
.stat = 0x000,
.ack = 0x040,
.mask = 0x080,
@@ -596,11 +602,7 @@ static const struct mtk_pinctrl_devdata mt2712_pinctrl_data = {
.dbnc_ctrl = 0x500,
.dbnc_set = 0x600,
.dbnc_clr = 0x700,
- .port_mask = 0xf,
- .ports = 8,
},
- .ap_num = 229,
- .db_cnt = 40,
};
static int mt2712_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8127.c b/drivers/pinctrl/mediatek/pinctrl-mt8127.c
index d764915..71f6258 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt8127.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt8127.c
@@ -300,8 +300,14 @@ static const struct mtk_pinctrl_devdata mt8127_pinctrl_data = {
.port_shf = 4,
.port_mask = 0xf,
.port_align = 4,
- .eint_offsets = {
+ .eint_hw = {
.name = "mt8127_eint",
+ .port_mask = 7,
+ .ports = 6,
+ .ap_num = 143,
+ .db_cnt = 16,
+ },
+ .eint_regs = {
.stat = 0x000,
.ack = 0x040,
.mask = 0x080,
@@ -320,11 +326,7 @@ static const struct mtk_pinctrl_devdata mt8127_pinctrl_data = {
.dbnc_ctrl = 0x500,
.dbnc_set = 0x600,
.dbnc_clr = 0x700,
- .port_mask = 7,
- .ports = 6,
},
- .ap_num = 143,
- .db_cnt = 16,
};
static int mt8127_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8135.c b/drivers/pinctrl/mediatek/pinctrl-mt8135.c
index d8c645f..fdfa357 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt8135.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt8135.c
@@ -313,8 +313,14 @@ static const struct mtk_pinctrl_devdata mt8135_pinctrl_data = {
.port_shf = 4,
.port_mask = 0xf,
.port_align = 4,
- .eint_offsets = {
+ .eint_hw = {
.name = "mt8135_eint",
+ .port_mask = 7,
+ .ports = 6,
+ .ap_num = 192,
+ .db_cnt = 16,
+ },
+ .eint_regs = {
.stat = 0x000,
.ack = 0x040,
.mask = 0x080,
@@ -333,11 +339,7 @@ static const struct mtk_pinctrl_devdata mt8135_pinctrl_data = {
.dbnc_ctrl = 0x500,
.dbnc_set = 0x600,
.dbnc_clr = 0x700,
- .port_mask = 7,
- .ports = 6,
},
- .ap_num = 192,
- .db_cnt = 16,
};
static int mt8135_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8173.c b/drivers/pinctrl/mediatek/pinctrl-mt8173.c
index 8bfd427..1466c95 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt8173.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt8173.c
@@ -340,8 +340,14 @@ static const struct mtk_pinctrl_devdata mt8173_pinctrl_data = {
.port_shf = 4,
.port_mask = 0xf,
.port_align = 4,
- .eint_offsets = {
+ .eint_hw = {
.name = "mt8173_eint",
+ .port_mask = 7,
+ .ports = 6,
+ .ap_num = 224,
+ .db_cnt = 16,
+ },
+ .eint_regs = {
.stat = 0x000,
.ack = 0x040,
.mask = 0x080,
@@ -360,11 +366,7 @@ static const struct mtk_pinctrl_devdata mt8173_pinctrl_data = {
.dbnc_ctrl = 0x500,
.dbnc_set = 0x600,
.dbnc_clr = 0x700,
- .port_mask = 7,
- .ports = 6,
},
- .ap_num = 224,
- .db_cnt = 16,
};
static int mt8173_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
index c3975a0..11e0d0f 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
@@ -38,6 +38,7 @@
#include "../core.h"
#include "../pinconf.h"
#include "../pinctrl-utils.h"
+#include "mtk-eint.h"
#include "pinctrl-mtk-common.h"
#define MAX_GPIO_MODE_PER_REG 5
@@ -831,243 +832,38 @@ static int mtk_gpio_get(struct gpio_chip *chip, unsigned offset)
static int mtk_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
- const struct mtk_desc_pin *pin;
struct mtk_pinctrl *pctl = gpiochip_get_data(chip);
- int irq;
-
- pin = pctl->devdata->pins + offset;
- if (pin->eint.eintnum == NO_EINT_SUPPORT)
- return -EINVAL;
-
- irq = irq_find_mapping(pctl->domain, pin->eint.eintnum);
- if (!irq)
- return -EINVAL;
-
- return irq;
-}
-
-static int mtk_pinctrl_irq_request_resources(struct irq_data *d)
-{
- struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d);
- const struct mtk_desc_pin *pin;
- int ret;
-
- pin = mtk_find_pin_by_eint_num(pctl, d->hwirq);
-
- if (!pin) {
- dev_err(pctl->dev, "Can not find pin\n");
- return -EINVAL;
- }
-
- ret = gpiochip_lock_as_irq(pctl->chip, pin->pin.number);
- if (ret) {
- dev_err(pctl->dev, "unable to lock HW IRQ %lu for IRQ\n",
- irqd_to_hwirq(d));
- return ret;
- }
-
- /* set mux to INT mode */
- mtk_pmx_set_mode(pctl->pctl_dev, pin->pin.number, pin->eint.eintmux);
- /* set gpio direction to input */
- mtk_pmx_gpio_set_direction(pctl->pctl_dev, NULL, pin->pin.number, true);
- /* set input-enable */
- mtk_pconf_set_ies_smt(pctl, pin->pin.number, 1, PIN_CONFIG_INPUT_ENABLE);
-
- return 0;
-}
-
-static void mtk_pinctrl_irq_release_resources(struct irq_data *d)
-{
- struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d);
- const struct mtk_desc_pin *pin;
-
- pin = mtk_find_pin_by_eint_num(pctl, d->hwirq);
-
- if (!pin) {
- dev_err(pctl->dev, "Can not find pin\n");
- return;
- }
-
- gpiochip_unlock_as_irq(pctl->chip, pin->pin.number);
-}
-
-static void __iomem *mtk_eint_get_offset(struct mtk_pinctrl *pctl,
- unsigned int eint_num, unsigned int offset)
-{
- unsigned int eint_base = 0;
- void __iomem *reg;
-
- if (eint_num >= pctl->devdata->ap_num)
- eint_base = pctl->devdata->ap_num;
-
- reg = pctl->eint_reg_base + offset + ((eint_num - eint_base) / 32) * 4;
-
- return reg;
-}
-
-/*
- * mtk_can_en_debounce: Check the EINT number is able to enable debounce or not
- * @eint_num: the EINT number to setmtk_pinctrl
- */
-static unsigned int mtk_eint_can_en_debounce(struct mtk_pinctrl *pctl,
- unsigned int eint_num)
-{
- unsigned int sens;
- unsigned int bit = BIT(eint_num % 32);
- const struct mtk_eint_offsets *eint_offsets =
- &pctl->devdata->eint_offsets;
-
- void __iomem *reg = mtk_eint_get_offset(pctl, eint_num,
- eint_offsets->sens);
-
- if (readl(reg) & bit)
- sens = MT_LEVEL_SENSITIVE;
- else
- sens = MT_EDGE_SENSITIVE;
-
- if ((eint_num < pctl->devdata->db_cnt) && (sens != MT_EDGE_SENSITIVE))
- return 1;
- else
- return 0;
-}
-
-/*
- * mtk_eint_get_mask: To get the eint mask
- * @eint_num: the EINT number to get
- */
-static unsigned int mtk_eint_get_mask(struct mtk_pinctrl *pctl,
- unsigned int eint_num)
-{
- unsigned int bit = BIT(eint_num % 32);
- const struct mtk_eint_offsets *eint_offsets =
- &pctl->devdata->eint_offsets;
-
- void __iomem *reg = mtk_eint_get_offset(pctl, eint_num,
- eint_offsets->mask);
-
- return !!(readl(reg) & bit);
-}
-
-static int mtk_eint_flip_edge(struct mtk_pinctrl *pctl, int hwirq)
-{
- int start_level, curr_level;
- unsigned int reg_offset;
- const struct mtk_eint_offsets *eint_offsets = &(pctl->devdata->eint_offsets);
- u32 mask = BIT(hwirq & 0x1f);
- u32 port = (hwirq >> 5) & eint_offsets->port_mask;
- void __iomem *reg = pctl->eint_reg_base + (port << 2);
- const struct mtk_desc_pin *pin;
-
- pin = mtk_find_pin_by_eint_num(pctl, hwirq);
- curr_level = mtk_gpio_get(pctl->chip, pin->pin.number);
- do {
- start_level = curr_level;
- if (start_level)
- reg_offset = eint_offsets->pol_clr;
- else
- reg_offset = eint_offsets->pol_set;
- writel(mask, reg + reg_offset);
-
- curr_level = mtk_gpio_get(pctl->chip, pin->pin.number);
- } while (start_level != curr_level);
-
- return start_level;
-}
-
-static void mtk_eint_mask(struct irq_data *d)
-{
- struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d);
- const struct mtk_eint_offsets *eint_offsets =
- &pctl->devdata->eint_offsets;
- u32 mask = BIT(d->hwirq & 0x1f);
- void __iomem *reg = mtk_eint_get_offset(pctl, d->hwirq,
- eint_offsets->mask_set);
-
- writel(mask, reg);
-}
-
-static void mtk_eint_unmask(struct irq_data *d)
-{
- struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d);
- const struct mtk_eint_offsets *eint_offsets =
- &pctl->devdata->eint_offsets;
- u32 mask = BIT(d->hwirq & 0x1f);
- void __iomem *reg = mtk_eint_get_offset(pctl, d->hwirq,
- eint_offsets->mask_clr);
-
- writel(mask, reg);
-
- if (pctl->eint_dual_edges[d->hwirq])
- mtk_eint_flip_edge(pctl, d->hwirq);
-}
-
-static int mtk_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
- unsigned debounce)
-{
- struct mtk_pinctrl *pctl = dev_get_drvdata(chip->parent);
- int eint_num, virq, eint_offset;
- unsigned int set_offset, bit, clr_bit, clr_offset, rst, i, unmask, dbnc;
- static const unsigned int debounce_time[] = {500, 1000, 16000, 32000, 64000,
- 128000, 256000};
const struct mtk_desc_pin *pin;
- struct irq_data *d;
+ unsigned long eint_n;
pin = pctl->devdata->pins + offset;
if (pin->eint.eintnum == NO_EINT_SUPPORT)
return -EINVAL;
- eint_num = pin->eint.eintnum;
- virq = irq_find_mapping(pctl->domain, eint_num);
- eint_offset = (eint_num % 4) * 8;
- d = irq_get_irq_data(virq);
-
- set_offset = (eint_num / 4) * 4 + pctl->devdata->eint_offsets.dbnc_set;
- clr_offset = (eint_num / 4) * 4 + pctl->devdata->eint_offsets.dbnc_clr;
- if (!mtk_eint_can_en_debounce(pctl, eint_num))
- return -ENOSYS;
-
- dbnc = ARRAY_SIZE(debounce_time);
- for (i = 0; i < ARRAY_SIZE(debounce_time); i++) {
- if (debounce <= debounce_time[i]) {
- dbnc = i;
- break;
- }
- }
+ eint_n = pin->eint.eintnum;
- if (!mtk_eint_get_mask(pctl, eint_num)) {
- mtk_eint_mask(d);
- unmask = 1;
- } else {
- unmask = 0;
- }
-
- clr_bit = 0xff << eint_offset;
- writel(clr_bit, pctl->eint_reg_base + clr_offset);
-
- bit = ((dbnc << EINT_DBNC_SET_DBNC_BITS) | EINT_DBNC_SET_EN) <<
- eint_offset;
- rst = EINT_DBNC_RST_BIT << eint_offset;
- writel(rst | bit, pctl->eint_reg_base + set_offset);
-
- /* Delay a while (more than 2T) to wait for hw debounce counter reset
- work correctly */
- udelay(1);
- if (unmask == 1)
- mtk_eint_unmask(d);
-
- return 0;
+ return mtk_eint_find_irq(pctl->eint, eint_n);
}
static int mtk_gpio_set_config(struct gpio_chip *chip, unsigned offset,
unsigned long config)
{
+ struct mtk_pinctrl *pctl = gpiochip_get_data(chip);
+ const struct mtk_desc_pin *pin;
+ unsigned long eint_n;
u32 debounce;
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
return -ENOTSUPP;
+ pin = pctl->devdata->pins + offset;
+ if (pin->eint.eintnum == NO_EINT_SUPPORT)
+ return -EINVAL;
+
debounce = pinconf_to_config_argument(config);
- return mtk_gpio_set_debounce(chip, offset, debounce);
+ eint_n = pin->eint.eintnum;
+
+ return mtk_eint_set_debounce(pctl->eint, eint_n, debounce);
}
static const struct gpio_chip mtk_gpio_chip = {
@@ -1084,117 +880,18 @@ static const struct gpio_chip mtk_gpio_chip = {
.of_gpio_n_cells = 2,
};
-static int mtk_eint_set_type(struct irq_data *d,
- unsigned int type)
-{
- struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d);
- const struct mtk_eint_offsets *eint_offsets =
- &pctl->devdata->eint_offsets;
- u32 mask = BIT(d->hwirq & 0x1f);
- void __iomem *reg;
-
- if (((type & IRQ_TYPE_EDGE_BOTH) && (type & IRQ_TYPE_LEVEL_MASK)) ||
- ((type & IRQ_TYPE_LEVEL_MASK) == IRQ_TYPE_LEVEL_MASK)) {
- dev_err(pctl->dev, "Can't configure IRQ%d (EINT%lu) for type 0x%X\n",
- d->irq, d->hwirq, type);
- return -EINVAL;
- }
-
- if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
- pctl->eint_dual_edges[d->hwirq] = 1;
- else
- pctl->eint_dual_edges[d->hwirq] = 0;
-
- if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING)) {
- reg = mtk_eint_get_offset(pctl, d->hwirq,
- eint_offsets->pol_clr);
- writel(mask, reg);
- } else {
- reg = mtk_eint_get_offset(pctl, d->hwirq,
- eint_offsets->pol_set);
- writel(mask, reg);
- }
-
- if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
- reg = mtk_eint_get_offset(pctl, d->hwirq,
- eint_offsets->sens_clr);
- writel(mask, reg);
- } else {
- reg = mtk_eint_get_offset(pctl, d->hwirq,
- eint_offsets->sens_set);
- writel(mask, reg);
- }
-
- if (pctl->eint_dual_edges[d->hwirq])
- mtk_eint_flip_edge(pctl, d->hwirq);
-
- return 0;
-}
-
-static int mtk_eint_irq_set_wake(struct irq_data *d, unsigned int on)
-{
- struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d);
- int shift = d->hwirq & 0x1f;
- int reg = d->hwirq >> 5;
-
- if (on)
- pctl->wake_mask[reg] |= BIT(shift);
- else
- pctl->wake_mask[reg] &= ~BIT(shift);
-
- return 0;
-}
-
-static void mtk_eint_chip_write_mask(const struct mtk_eint_offsets *chip,
- void __iomem *eint_reg_base, u32 *buf)
-{
- int port;
- void __iomem *reg;
-
- for (port = 0; port < chip->ports; port++) {
- reg = eint_reg_base + (port << 2);
- writel_relaxed(~buf[port], reg + chip->mask_set);
- writel_relaxed(buf[port], reg + chip->mask_clr);
- }
-}
-
-static void mtk_eint_chip_read_mask(const struct mtk_eint_offsets *chip,
- void __iomem *eint_reg_base, u32 *buf)
-{
- int port;
- void __iomem *reg;
-
- for (port = 0; port < chip->ports; port++) {
- reg = eint_reg_base + chip->mask + (port << 2);
- buf[port] = ~readl_relaxed(reg);
- /* Mask is 0 when irq is enabled, and 1 when disabled. */
- }
-}
-
static int mtk_eint_suspend(struct device *device)
{
- void __iomem *reg;
struct mtk_pinctrl *pctl = dev_get_drvdata(device);
- const struct mtk_eint_offsets *eint_offsets =
- &pctl->devdata->eint_offsets;
- reg = pctl->eint_reg_base;
- mtk_eint_chip_read_mask(eint_offsets, reg, pctl->cur_mask);
- mtk_eint_chip_write_mask(eint_offsets, reg, pctl->wake_mask);
-
- return 0;
+ return mtk_eint_do_suspend(pctl->eint);
}
static int mtk_eint_resume(struct device *device)
{
struct mtk_pinctrl *pctl = dev_get_drvdata(device);
- const struct mtk_eint_offsets *eint_offsets =
- &pctl->devdata->eint_offsets;
- mtk_eint_chip_write_mask(eint_offsets,
- pctl->eint_reg_base, pctl->cur_mask);
-
- return 0;
+ return mtk_eint_do_resume(pctl->eint);
}
const struct dev_pm_ops mtk_eint_pm_ops = {
@@ -1202,117 +899,6 @@ const struct dev_pm_ops mtk_eint_pm_ops = {
.resume_noirq = mtk_eint_resume,
};
-static void mtk_eint_ack(struct irq_data *d)
-{
- struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d);
- const struct mtk_eint_offsets *eint_offsets =
- &pctl->devdata->eint_offsets;
- u32 mask = BIT(d->hwirq & 0x1f);
- void __iomem *reg = mtk_eint_get_offset(pctl, d->hwirq,
- eint_offsets->ack);
-
- writel(mask, reg);
-}
-
-static struct irq_chip mtk_pinctrl_irq_chip = {
- .name = "mt-eint",
- .irq_disable = mtk_eint_mask,
- .irq_mask = mtk_eint_mask,
- .irq_unmask = mtk_eint_unmask,
- .irq_ack = mtk_eint_ack,
- .irq_set_type = mtk_eint_set_type,
- .irq_set_wake = mtk_eint_irq_set_wake,
- .irq_request_resources = mtk_pinctrl_irq_request_resources,
- .irq_release_resources = mtk_pinctrl_irq_release_resources,
-};
-
-static unsigned int mtk_eint_init(struct mtk_pinctrl *pctl)
-{
- const struct mtk_eint_offsets *eint_offsets =
- &pctl->devdata->eint_offsets;
- void __iomem *reg = pctl->eint_reg_base + eint_offsets->dom_en;
- unsigned int i;
-
- for (i = 0; i < pctl->devdata->ap_num; i += 32) {
- writel(0xffffffff, reg);
- reg += 4;
- }
- return 0;
-}
-
-static inline void
-mtk_eint_debounce_process(struct mtk_pinctrl *pctl, int index)
-{
- unsigned int rst, ctrl_offset;
- unsigned int bit, dbnc;
- const struct mtk_eint_offsets *eint_offsets =
- &pctl->devdata->eint_offsets;
-
- ctrl_offset = (index / 4) * 4 + eint_offsets->dbnc_ctrl;
- dbnc = readl(pctl->eint_reg_base + ctrl_offset);
- bit = EINT_DBNC_SET_EN << ((index % 4) * 8);
- if ((bit & dbnc) > 0) {
- ctrl_offset = (index / 4) * 4 + eint_offsets->dbnc_set;
- rst = EINT_DBNC_RST_BIT << ((index % 4) * 8);
- writel(rst, pctl->eint_reg_base + ctrl_offset);
- }
-}
-
-static void mtk_eint_irq_handler(struct irq_desc *desc)
-{
- struct irq_chip *chip = irq_desc_get_chip(desc);
- struct mtk_pinctrl *pctl = irq_desc_get_handler_data(desc);
- unsigned int status, eint_num;
- int offset, index, virq;
- const struct mtk_eint_offsets *eint_offsets =
- &pctl->devdata->eint_offsets;
- void __iomem *reg = mtk_eint_get_offset(pctl, 0, eint_offsets->stat);
- int dual_edges, start_level, curr_level;
- const struct mtk_desc_pin *pin;
-
- chained_irq_enter(chip, desc);
- for (eint_num = 0;
- eint_num < pctl->devdata->ap_num;
- eint_num += 32, reg += 4) {
- status = readl(reg);
- while (status) {
- offset = __ffs(status);
- index = eint_num + offset;
- virq = irq_find_mapping(pctl->domain, index);
- status &= ~BIT(offset);
-
- dual_edges = pctl->eint_dual_edges[index];
- if (dual_edges) {
- /* Clear soft-irq in case we raised it
- last time */
- writel(BIT(offset), reg - eint_offsets->stat +
- eint_offsets->soft_clr);
-
- pin = mtk_find_pin_by_eint_num(pctl, index);
- start_level = mtk_gpio_get(pctl->chip,
- pin->pin.number);
- }
-
- generic_handle_irq(virq);
-
- if (dual_edges) {
- curr_level = mtk_eint_flip_edge(pctl, index);
-
- /* If level changed, we might lost one edge
- interrupt, raised it through soft-irq */
- if (start_level != curr_level)
- writel(BIT(offset), reg -
- eint_offsets->stat +
- eint_offsets->soft_set);
- }
-
- if (index < pctl->devdata->db_cnt)
- mtk_eint_debounce_process(pctl , index);
- }
- }
- chained_irq_exit(chip, desc);
-}
-
static int mtk_pctrl_build_state(struct platform_device *pdev)
{
struct mtk_pinctrl *pctl = platform_get_drvdata(pdev);
@@ -1345,6 +931,97 @@ static int mtk_pctrl_build_state(struct platform_device *pdev)
return 0;
}
+static int
+mtk_xt_get_gpio_n(void *data, unsigned long eint_n, unsigned int *gpio_n,
+ struct gpio_chip **gpio_chip)
+{
+ struct mtk_pinctrl *pctl = (struct mtk_pinctrl *)data;
+ const struct mtk_desc_pin *pin;
+
+ pin = mtk_find_pin_by_eint_num(pctl, eint_n);
+ if (!pin)
+ return -EINVAL;
+
+ *gpio_chip = pctl->chip;
+ *gpio_n = pin->pin.number;
+
+ return 0;
+}
+
+static int mtk_xt_get_gpio_state(void *data, unsigned long eint_n)
+{
+ struct mtk_pinctrl *pctl = (struct mtk_pinctrl *)data;
+ const struct mtk_desc_pin *pin;
+
+ pin = mtk_find_pin_by_eint_num(pctl, eint_n);
+ if (!pin)
+ return -EINVAL;
+
+ return mtk_gpio_get(pctl->chip, pin->pin.number);
+}
+
+static int mtk_xt_set_gpio_as_eint(void *data, unsigned long eint_n)
+{
+ struct mtk_pinctrl *pctl = (struct mtk_pinctrl *)data;
+ const struct mtk_desc_pin *pin;
+
+ pin = mtk_find_pin_by_eint_num(pctl, eint_n);
+ if (!pin)
+ return -EINVAL;
+
+ /* set mux to INT mode */
+ mtk_pmx_set_mode(pctl->pctl_dev, pin->pin.number, pin->eint.eintmux);
+ /* set gpio direction to input */
+ mtk_pmx_gpio_set_direction(pctl->pctl_dev, NULL, pin->pin.number,
+ true);
+ /* set input-enable */
+ mtk_pconf_set_ies_smt(pctl, pin->pin.number, 1,
+ PIN_CONFIG_INPUT_ENABLE);
+
+ return 0;
+}
+
+static const struct mtk_eint_xt mtk_eint_xt = {
+ .get_gpio_n = mtk_xt_get_gpio_n,
+ .get_gpio_state = mtk_xt_get_gpio_state,
+ .set_gpio_as_eint = mtk_xt_set_gpio_as_eint,
+};
+
+static int mtk_eint_init(struct mtk_pinctrl *pctl, struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct resource *res;
+
+ if (!of_property_read_bool(np, "interrupt-controller"))
+ return -ENODEV;
+
+ pctl->eint = devm_kzalloc(pctl->dev, sizeof(*pctl->eint), GFP_KERNEL);
+ if (!pctl->eint)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "Unable to get eint resource\n");
+ return -ENODEV;
+ }
+
+ pctl->eint->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(pctl->eint->base))
+ return PTR_ERR(pctl->eint->base);
+
+ pctl->eint->irq = irq_of_parse_and_map(np, 0);
+ if (!pctl->eint->irq)
+ return -EINVAL;
+
+ pctl->eint->dev = &pdev->dev;
+ pctl->eint->regs = &pctl->devdata->eint_regs;
+ pctl->eint->hw = &pctl->devdata->eint_hw;
+ pctl->eint->pctl = pctl;
+ pctl->eint->gpio_xlate = &mtk_eint_xt;
+
+ return mtk_eint_do_init(pctl->eint);
+}
+
int mtk_pctrl_init(struct platform_device *pdev,
const struct mtk_pinctrl_devdata *data,
struct regmap *regmap)
@@ -1353,8 +1030,7 @@ int mtk_pctrl_init(struct platform_device *pdev,
struct mtk_pinctrl *pctl;
struct device_node *np = pdev->dev.of_node, *node;
struct property *prop;
- struct resource *res;
- int i, ret, irq, ports_buf;
+ int ret, i;
pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
if (!pctl)
@@ -1441,70 +1117,10 @@ int mtk_pctrl_init(struct platform_device *pdev,
goto chip_error;
}
- if (!of_property_read_bool(np, "interrupt-controller"))
- return 0;
-
- /* Get EINT register base from dts. */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "Unable to get Pinctrl resource\n");
- ret = -EINVAL;
- goto chip_error;
- }
-
- pctl->eint_reg_base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(pctl->eint_reg_base)) {
- ret = -EINVAL;
- goto chip_error;
- }
-
- ports_buf = pctl->devdata->eint_offsets.ports;
- pctl->wake_mask = devm_kcalloc(&pdev->dev, ports_buf,
- sizeof(*pctl->wake_mask), GFP_KERNEL);
- if (!pctl->wake_mask) {
- ret = -ENOMEM;
- goto chip_error;
- }
-
- pctl->cur_mask = devm_kcalloc(&pdev->dev, ports_buf,
- sizeof(*pctl->cur_mask), GFP_KERNEL);
- if (!pctl->cur_mask) {
- ret = -ENOMEM;
- goto chip_error;
- }
-
- pctl->eint_dual_edges = devm_kcalloc(&pdev->dev, pctl->devdata->ap_num,
- sizeof(int), GFP_KERNEL);
- if (!pctl->eint_dual_edges) {
- ret = -ENOMEM;
- goto chip_error;
- }
-
- irq = irq_of_parse_and_map(np, 0);
- if (!irq) {
- dev_err(&pdev->dev, "couldn't parse and map irq\n");
- ret = -EINVAL;
- goto chip_error;
- }
-
- pctl->domain = irq_domain_add_linear(np,
- pctl->devdata->ap_num, &irq_domain_simple_ops, NULL);
- if (!pctl->domain) {
- dev_err(&pdev->dev, "Couldn't register IRQ domain\n");
- ret = -ENOMEM;
+ ret = mtk_eint_init(pctl, pdev);
+ if (ret)
goto chip_error;
- }
-
- mtk_eint_init(pctl);
- for (i = 0; i < pctl->devdata->ap_num; i++) {
- int virq = irq_create_mapping(pctl->domain, i);
-
- irq_set_chip_and_handler(virq, &mtk_pinctrl_irq_chip,
- handle_level_irq);
- irq_set_chip_data(virq, pctl);
- }
- irq_set_chained_handler_and_data(irq, mtk_eint_irq_handler, pctl);
return 0;
chip_error:
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
index 8543bc4..346e3db 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
@@ -19,6 +19,8 @@
#include <linux/regmap.h>
#include <linux/pinctrl/pinconf-generic.h>
+#include "mtk-eint.h"
+
#define NO_EINT_SUPPORT 255
#define MT_EDGE_SENSITIVE 0
#define MT_LEVEL_SENSITIVE 1
@@ -258,9 +260,8 @@ struct mtk_pinctrl_devdata {
unsigned char port_shf;
unsigned char port_mask;
unsigned char port_align;
- struct mtk_eint_offsets eint_offsets;
- unsigned int ap_num;
- unsigned int db_cnt;
+ struct mtk_eint_hw eint_hw;
+ struct mtk_eint_regs eint_regs;
};
struct mtk_pinctrl {
@@ -274,11 +275,7 @@ struct mtk_pinctrl {
const char **grp_names;
struct pinctrl_dev *pctl_dev;
const struct mtk_pinctrl_devdata *devdata;
- void __iomem *eint_reg_base;
- struct irq_domain *domain;
- int *eint_dual_edges;
- u32 *wake_mask;
- u32 *cur_mask;
+ struct mtk_eint *eint;
};
int mtk_pctrl_init(struct platform_device *pdev,
--
2.7.4
^ permalink raw reply related
* [PATCH v1 1/7] dt-bindings: pinctrl: add external interrupt support to MT7622 pinctrl
From: sean.wang at mediatek.com @ 2018-05-20 17:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1526835466.git.sean.wang@mediatek.com>
From: Sean Wang <sean.wang@mediatek.com>
Extend the capability of MT7622 pinctrl with adding EINT so that each
GPIO can be used to notify CPU when a signal state is changing on the
line as an external interrupt.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt
index f18ed99..743b32d 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt
@@ -9,6 +9,16 @@ Required properties for the root node:
- #gpio-cells: Should be two. The first cell is the pin number and the
second is the GPIO flags.
+Optional properties:
+- interrupt-controller : Marks the device node as an interrupt controller
+
+If the property interrupt-controller is defined, following property is required
+- reg-names: A string describing the "reg" entries. Must contain "eint".
+- interrupts : The interrupt output from the controller.
+- #interrupt-cells: Should be two.
+- interrupt-parent: Phandle of the interrupt parent to which the external
+ GPIO interrupts are forwarded to.
+
Please refer to pinctrl-bindings.txt in this directory for details of the
common pinctrl bindings used by client devices, including the meaning of the
phrase "pin configuration node".
--
2.7.4
^ permalink raw reply related
* [PATCH v1 0/7] add external interrupt support to MT7622 pinctrl
From: sean.wang at mediatek.com @ 2018-05-20 17:01 UTC (permalink / raw)
To: linux-arm-kernel
From: Sean Wang <sean.wang@mediatek.com>
The series is to add external interrupt support to MT7622 pinctrl.
Before we can freely do that in pinctrl-mt7622.c with patch 3, a refactor
work has to be done with patch 2 to split EINT-related code from a
specific driver and then allows pintrl-mt7622.c to reuse it.
patch 1, 3, 7: add EINT support to MT7622 pinctrl.
patch 2, 6: make EINT-related become a generic way for all MediaTek
pinctrl.
patch 4, 5: eliminate unnecessary code in existent EINT-related ones after
refactor work was done.
Sean Wang (7):
dt-bindings: pinctrl: add external interrupt support to MT7622 pinctrl
pinctrl: mediatek: refactor EINT related code for all MediaTek pinctrl
can fit
pinctrl: mediatek: add EINT support to MT7622 SoC
pinctrl: mediatek: use generic EINT register maps for each SoC
pinctrl: mediatek: remove unused fields in struct mtk_eint_hw
MAINTAINERS: update entry for PIN CONTROLLER - MEDIATEK
arm64: dts: mt7622: add EINT support to pinctrl
.../devicetree/bindings/pinctrl/pinctrl-mt7622.txt | 10 +
MAINTAINERS | 1 +
arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts | 2 +-
arch/arm64/boot/dts/mediatek/mt7622.dtsi | 8 +-
drivers/pinctrl/mediatek/Kconfig | 6 +
drivers/pinctrl/mediatek/Makefile | 1 +
drivers/pinctrl/mediatek/mtk-eint.c | 492 +++++++++++++++++
drivers/pinctrl/mediatek/mtk-eint.h | 106 ++++
drivers/pinctrl/mediatek/pinctrl-mt2701.c | 25 +-
drivers/pinctrl/mediatek/pinctrl-mt2712.c | 25 +-
drivers/pinctrl/mediatek/pinctrl-mt7622.c | 143 +++++
drivers/pinctrl/mediatek/pinctrl-mt8127.c | 25 +-
drivers/pinctrl/mediatek/pinctrl-mt8135.c | 25 +-
drivers/pinctrl/mediatek/pinctrl-mt8173.c | 25 +-
drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 608 ++++-----------------
drivers/pinctrl/mediatek/pinctrl-mtk-common.h | 13 +-
16 files changed, 901 insertions(+), 614 deletions(-)
create mode 100644 drivers/pinctrl/mediatek/mtk-eint.c
create mode 100644 drivers/pinctrl/mediatek/mtk-eint.h
--
2.7.4
^ permalink raw reply
* [PATCH 5/6] mtd: rawnand: ams-delta: use GPIO lookup table
From: Andy Shevchenko @ 2018-05-20 16:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <3505791.x6nWYTo8eb@z50>
On Sun, May 20, 2018 at 6:37 PM, Janusz Krzysztofik <jmkrzyszt@gmail.com> wrote:
> On Sunday, May 20, 2018 4:44:31 PM CEST Andy Shevchenko wrote:
>> Though, I completely dislike "rdy" name of GPIO. Where is it documented?
>
> No documentation files for Amstrad Delta nor for its NAND driver specifically
> exist under Documentation/. However, there exist some for generic GPIO NAND
> driver where the pin name "rdy" is used explicitly:
> Documentation/driver-api/gpio/drivers-on-gpio.rst
> Documentation/devicetree/bindings/mtd/gpio-control-nand.txt
> You can find that mnemonic used across drivers/mtd/nand/, standalone or as a
> suffix, including the Amstrad Delta NAND driver before the change discussed.
> To be honest, I don't like it much either, but I'm just using it instead of
> inventing something new.
OK, that's what I was looking for. Since it's already in use and
documented, then it's fine for me.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* [PATCH v6 9/9] iio: counter: Remove IIO counter subdirectory
From: Jonathan Cameron @ 2018-05-20 15:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4c335e0eebfbaf6e86f41e0f2864d76993d90b13.1526487615.git.vilhelm.gray@gmail.com>
On Wed, 16 May 2018 13:52:39 -0400
William Breathitt Gray <vilhelm.gray@gmail.com> wrote:
> This patch removes the IIO counter subdirectory which is now superceded
> by the Counter subsystem. Deprecation warnings are added to the
> documentation of the relevant IIO counter sysfs attributes.
>
> Signed-off-by: William Breathitt Gray <vilhelm.gray@gmail.com>
Please drop the directory when it becomes empty rather than in a later
patch. IIRC there are some issues with empty Makefiles that will
make building inbetween tricky.
For the deprecated markings.
Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> ---
> Documentation/ABI/testing/sysfs-bus-iio | 8 ++++++++
> .../ABI/testing/sysfs-bus-iio-counter-104-quad-8 | 16 ++++++++++++++++
> drivers/iio/Kconfig | 1 -
> drivers/iio/Makefile | 1 -
> drivers/iio/counter/Kconfig | 8 --------
> drivers/iio/counter/Makefile | 5 -----
> 6 files changed, 24 insertions(+), 15 deletions(-)
> delete mode 100644 drivers/iio/counter/Kconfig
> delete mode 100644 drivers/iio/counter/Makefile
>
> diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio
> index 731146c3b138..6115d97b075e 100644
> --- a/Documentation/ABI/testing/sysfs-bus-iio
> +++ b/Documentation/ABI/testing/sysfs-bus-iio
> @@ -1637,6 +1637,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_countY_raw
> KernelVersion: 4.10
> Contact: linux-iio at vger.kernel.org
> Description:
> + This interface is deprecated; please use the Counter subsystem.
> +
> Raw counter device counts from channel Y. For quadrature
> counters, multiplication by an available [Y]_scale results in
> the counts of a single quadrature signal phase from channel Y.
> @@ -1645,6 +1647,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_indexY_raw
> KernelVersion: 4.10
> Contact: linux-iio at vger.kernel.org
> Description:
> + This interface is deprecated; please use the Counter subsystem.
> +
> Raw counter device index value from channel Y. This attribute
> provides an absolute positional reference (e.g. a pulse once per
> revolution) which may be used to home positional systems as
> @@ -1654,6 +1658,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_count_count_direction_available
> KernelVersion: 4.12
> Contact: linux-iio at vger.kernel.org
> Description:
> + This interface is deprecated; please use the Counter subsystem.
> +
> A list of possible counting directions which are:
> - "up" : counter device is increasing.
> - "down": counter device is decreasing.
> @@ -1662,4 +1668,6 @@ What: /sys/bus/iio/devices/iio:deviceX/in_countY_count_direction
> KernelVersion: 4.12
> Contact: linux-iio at vger.kernel.org
> Description:
> + This interface is deprecated; please use the Counter subsystem.
> +
> Raw counter device counters direction for channel Y.
> diff --git a/Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8 b/Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8
> index 7fac2c268d9a..bac3d0d48b7b 100644
> --- a/Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8
> +++ b/Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8
> @@ -6,6 +6,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_index_synchronous_mode_available
> KernelVersion: 4.10
> Contact: linux-iio at vger.kernel.org
> Description:
> + This interface is deprecated; please use the Counter subsystem.
> +
> Discrete set of available values for the respective counter
> configuration are listed in this file.
>
> @@ -13,6 +15,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_countY_count_mode
> KernelVersion: 4.10
> Contact: linux-iio at vger.kernel.org
> Description:
> + This interface is deprecated; please use the Counter subsystem.
> +
> Count mode for channel Y. Four count modes are available:
> normal, range limit, non-recycle, and modulo-n. The preset value
> for channel Y is used by the count mode where required.
> @@ -47,6 +51,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_countY_noise_error
> KernelVersion: 4.10
> Contact: linux-iio at vger.kernel.org
> Description:
> + This interface is deprecated; please use the Counter subsystem.
> +
> Read-only attribute that indicates whether excessive noise is
> present at the channel Y count inputs in quadrature clock mode;
> irrelevant in non-quadrature clock mode.
> @@ -55,6 +61,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_countY_preset
> KernelVersion: 4.10
> Contact: linux-iio at vger.kernel.org
> Description:
> + This interface is deprecated; please use the Counter subsystem.
> +
> If the counter device supports preset registers, the preset
> count for channel Y is provided by this attribute.
>
> @@ -62,6 +70,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_countY_quadrature_mode
> KernelVersion: 4.10
> Contact: linux-iio at vger.kernel.org
> Description:
> + This interface is deprecated; please use the Counter subsystem.
> +
> Configure channel Y counter for non-quadrature or quadrature
> clock mode. Selecting non-quadrature clock mode will disable
> synchronous load mode. In quadrature clock mode, the channel Y
> @@ -83,6 +93,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_countY_set_to_preset_on_index
> KernelVersion: 4.10
> Contact: linux-iio at vger.kernel.org
> Description:
> + This interface is deprecated; please use the Counter subsystem.
> +
> Whether to set channel Y counter with channel Y preset value
> when channel Y index input is active, or continuously count.
> Valid attribute values are boolean.
> @@ -91,6 +103,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_indexY_index_polarity
> KernelVersion: 4.10
> Contact: linux-iio at vger.kernel.org
> Description:
> + This interface is deprecated; please use the Counter subsystem.
> +
> Active level of channel Y index input; irrelevant in
> non-synchronous load mode.
>
> @@ -98,6 +112,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_indexY_synchronous_mode
> KernelVersion: 4.10
> Contact: linux-iio at vger.kernel.org
> Description:
> + This interface is deprecated; please use the Counter subsystem.
> +
> Configure channel Y counter for non-synchronous or synchronous
> load mode. Synchronous load mode cannot be selected in
> non-quadrature clock mode.
> diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
> index d69e85a8bdc3..1152efad91a1 100644
> --- a/drivers/iio/Kconfig
> +++ b/drivers/iio/Kconfig
> @@ -74,7 +74,6 @@ source "drivers/iio/afe/Kconfig"
> source "drivers/iio/amplifiers/Kconfig"
> source "drivers/iio/chemical/Kconfig"
> source "drivers/iio/common/Kconfig"
> -source "drivers/iio/counter/Kconfig"
> source "drivers/iio/dac/Kconfig"
> source "drivers/iio/dummy/Kconfig"
> source "drivers/iio/frequency/Kconfig"
> diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
> index d8cba9c229c0..7bdd31f1b88f 100644
> --- a/drivers/iio/Makefile
> +++ b/drivers/iio/Makefile
> @@ -20,7 +20,6 @@ obj-y += amplifiers/
> obj-y += buffer/
> obj-y += chemical/
> obj-y += common/
> -obj-y += counter/
> obj-y += dac/
> obj-y += dummy/
> obj-y += gyro/
> diff --git a/drivers/iio/counter/Kconfig b/drivers/iio/counter/Kconfig
> deleted file mode 100644
> index 95a7a0df6cac..000000000000
> --- a/drivers/iio/counter/Kconfig
> +++ /dev/null
> @@ -1,8 +0,0 @@
> -#
> -# Counter devices
> -#
> -# When adding new entries keep the list in alphabetical order
> -
> -menu "Counters"
> -
> -endmenu
> diff --git a/drivers/iio/counter/Makefile b/drivers/iio/counter/Makefile
> deleted file mode 100644
> index 8fd3d954775a..000000000000
> --- a/drivers/iio/counter/Makefile
> +++ /dev/null
> @@ -1,5 +0,0 @@
> -#
> -# Makefile for IIO counter devices
> -#
> -
> -# When adding new entries keep the list in alphabetical order
^ permalink raw reply
* [PATCH v6 6/9] dt-bindings: counter: Document stm32 quadrature encoder
From: Jonathan Cameron @ 2018-05-20 15:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180518162815.GA24966@rob-hp-laptop>
On Fri, 18 May 2018 11:28:15 -0500
Rob Herring <robh@kernel.org> wrote:
> On Thu, May 17, 2018 at 08:59:40PM +0200, Benjamin Gaignard wrote:
> > 2018-05-17 18:23 GMT+02:00 Rob Herring <robh+dt@kernel.org>:
> > > On Wed, May 16, 2018 at 12:51 PM, William Breathitt Gray
> > > <vilhelm.gray@gmail.com> wrote:
> > >> From: Benjamin Gaignard <benjamin.gaignard@st.com>
> > >
> > > v6? Where's v1-v5?
> > >
> > >> Add bindings for STM32 Timer quadrature encoder.
> > >> It is a sub-node of STM32 Timer which implement the
> > >> counter part of the hardware.
> > >>
> > >> Cc: Rob Herring <robh+dt@kernel.org>
> > >> Cc: Mark Rutland <mark.rutland@arm.com>
> > >> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
> > >> Signed-off-by: William Breathitt Gray <vilhelm.gray@gmail.com>
> > >> ---
> > >> .../bindings/counter/stm32-timer-cnt.txt | 26 +++++++++++++++++++
> > >> .../devicetree/bindings/mfd/stm32-timers.txt | 7 +++++
> > >> 2 files changed, 33 insertions(+)
> > >> create mode 100644 Documentation/devicetree/bindings/counter/stm32-timer-cnt.txt
> > >>
> > >> diff --git a/Documentation/devicetree/bindings/counter/stm32-timer-cnt.txt b/Documentation/devicetree/bindings/counter/stm32-timer-cnt.txt
> > >> new file mode 100644
> > >> index 000000000000..377728128bef
> > >> --- /dev/null
> > >> +++ b/Documentation/devicetree/bindings/counter/stm32-timer-cnt.txt
> > >> @@ -0,0 +1,26 @@
> > >> +STMicroelectronics STM32 Timer quadrature encoder
> > >> +
> > >> +STM32 Timer provides quadrature encoder counter mode to detect
> > >
> > > 'mode' does not sound like a sub-block of the timers block.
> >
> > quadrature encoding is one of the counting modes of this hardware
> > block which is enable to count on other signals/triggers
>
> You don't need a child node and compatible to set a mode.
A pile of extra hardware becomes relevant and you only want
to be in this state if you have appropriate external device
wired up. In this case there is admittedly not a lot here
but some devices will look a bit more like a touchscreen controller.
They are often build on top of an ADC module, but have a load
of touch screen only signals and electrical elements that
warrant being represented as a separate node in the DT.
>
> > >> +angular position and direction of rotary elements,
> > >> +from IN1 and IN2 input signals.
> > >> +
> > >> +Must be a sub-node of an STM32 Timer device tree node.
> > >> +See ../mfd/stm32-timers.txt for details about the parent node.
> > >> +
> > >> +Required properties:
> > >> +- compatible: Must be "st,stm32-timer-counter".
> > >> +- pinctrl-names: Set to "default".
> > >> +- pinctrl-0: List of phandles pointing to pin configuration nodes,
> > >> + to set IN1/IN2 pins in mode of operation for Low-Power
> > >> + Timer input on external pin.
> > >> +
> > >> +Example:
> > >> + timers at 40010000 {
> > >> + compatible = "st,stm32-timers";
> > >> + ...
> > >> + counter {
> > >> + compatible = "st,stm32-timer-counter";
> > >
> > > Is there only 1? How is the counter addressed?
> >
> > Yes there is only one counter per hardware block.
> > Counter is addressed like the two others sub-nodes and the details
> > about parent mode are describe in stm32-timers.txt
> > Should I add them here too ? so example will be like that:
>
> No, you should drop the child node and add pinctrl to the parent.
>
> Any other functions this block has that you plan on adding? Please make
> bindings as complete as possible, not what you currently have drivers
> for.
>
> > timers at 40010000 {
> > #address-cells = <1>;
> > #size-cells = <0>;
> > compatible = "st,stm32-timers";
> > reg = <0x40010000 0x400>;
> > clocks = <&rcc 0 160>;
> > clock-names = "int";
> > counter {
> > compatible = "st,stm32-timer-counter";
> > pinctrl-names = "default";
> > pinctrl-0 = <&tim1_in_pins>;
> > };
> > };
> >
> > Benjamin
> > >
> > > _______________________________________________
> > > linux-arm-kernel mailing list
> > > linux-arm-kernel at lists.infradead.org
> > > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v6 4/9] counter: 104-quad-8: Add Generic Counter interface support
From: Jonathan Cameron @ 2018-05-20 15:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <881ede525a87ef68fad76cc757ce0ba72df03e5a.1526487615.git.vilhelm.gray@gmail.com>
On Wed, 16 May 2018 13:51:25 -0400
William Breathitt Gray <vilhelm.gray@gmail.com> wrote:
> This patch adds support for the Generic Counter interface to the
> 104-QUAD-8 driver. The existing 104-QUAD-8 device interface should not
> be affected by this patch; all changes are intended as supplemental
> additions as perceived by the user.
>
> Generic Counter Counts are created for the eight quadrature channel
> counts, as well as their respective quadrature A and B Signals (which
> are associated via respective Synapse structures) and respective index
> Signals.
>
> The new Generic Counter interface sysfs attributes are intended to
> expose the same functionality and data available via the existing
> 104-QUAD-8 IIO device interface; the Generic Counter interface serves
> to provide the respective functionality and data in a standard way
> expected of counter devices.
>
> Signed-off-by: William Breathitt Gray <vilhelm.gray@gmail.com>
A few general comments that applied just as well to the original driver
as they do to the modified version.
I wonder if this would be easier to review as two patches.
Move the driver then add the counter interfaces?
Right now people kind of have to review the old IIO driver and
all the new stuff which is a big job..
Jonathan
> ---
> MAINTAINERS | 4 +-
> drivers/counter/104-quad-8.c | 1335 ++++++++++++++++++++++++++++++
> drivers/counter/Kconfig | 21 +
> drivers/counter/Makefile | 2 +
> drivers/iio/counter/104-quad-8.c | 596 -------------
> drivers/iio/counter/Kconfig | 17 -
> drivers/iio/counter/Makefile | 1 -
> 7 files changed, 1360 insertions(+), 616 deletions(-)
> create mode 100644 drivers/counter/104-quad-8.c
> delete mode 100644 drivers/iio/counter/104-quad-8.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 7a01aa63fb33..f11bf7885aeb 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -266,12 +266,12 @@ L: linux-gpio at vger.kernel.org
> S: Maintained
> F: drivers/gpio/gpio-104-idio-16.c
>
> -ACCES 104-QUAD-8 IIO DRIVER
> +ACCES 104-QUAD-8 DRIVER
> M: William Breathitt Gray <vilhelm.gray@gmail.com>
> L: linux-iio at vger.kernel.org
> S: Maintained
> F: Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8
> -F: drivers/iio/counter/104-quad-8.c
> +F: drivers/counter/104-quad-8.c
>
> ACCES PCI-IDIO-16 GPIO DRIVER
> M: William Breathitt Gray <vilhelm.gray@gmail.com>
> diff --git a/drivers/counter/104-quad-8.c b/drivers/counter/104-quad-8.c
> new file mode 100644
> index 000000000000..7c72fb72d660
> --- /dev/null
> +++ b/drivers/counter/104-quad-8.c
> @@ -0,0 +1,1335 @@
> +// SPDX-License-Identifier: GPL-2.0-only
If you are happy with SPDX drop the GPL text below to keep things
short.
> +/*
> + * IIO driver for the ACCES 104-QUAD-8
> + * Copyright (C) 2016 William Breathitt Gray
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License, version 2, as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * This driver supports the ACCES 104-QUAD-8 and ACCES 104-QUAD-4.
> + */
> +#include <linux/bitops.h>
...
> +static int quad8_probe(struct device *dev, unsigned int id)
> +{
> + struct iio_dev *indio_dev;
> + struct quad8_iio *quad8iio;
> + int i, j;
> + unsigned int base_offset;
> + int err;
> +
> + if (!devm_request_region(dev, base[id], QUAD8_EXTENT, dev_name(dev))) {
> + dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
> + base[id], base[id] + QUAD8_EXTENT);
> + return -EBUSY;
> + }
> +
> + /* Allocate IIO device; this also allocates driver data structure */
> + indio_dev = devm_iio_device_alloc(dev, sizeof(*quad8iio));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + /* Initialize IIO device */
> + indio_dev->info = &quad8_info;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->num_channels = ARRAY_SIZE(quad8_channels);
> + indio_dev->channels = quad8_channels;
> + indio_dev->name = dev_name(dev);
> + indio_dev->dev.parent = dev;
> +
> + /* Initialize Counter device and driver data */
> + quad8iio = iio_priv(indio_dev);
> + quad8iio->counter.name = dev_name(dev);
> + quad8iio->counter.parent = dev;
> + quad8iio->counter.ops = &quad8_ops;
> + quad8iio->counter.counts = quad8_counts;
> + quad8iio->counter.num_counts = ARRAY_SIZE(quad8_counts);
> + quad8iio->counter.signals = quad8_signals;
> + quad8iio->counter.num_signals = ARRAY_SIZE(quad8_signals);
> + quad8iio->counter.priv = quad8iio;
> + quad8iio->base = base[id];
> +
> + /* Reset all counters and disable interrupt function */
> + outb(0x01, base[id] + 0x11);
> + /* Set initial configuration for all counters */
> + for (i = 0; i < QUAD8_NUM_COUNTERS; i++) {
> + base_offset = base[id] + 2 * i;
> + /* Reset Byte Pointer */
> + outb(0x01, base_offset + 1);
I'm going to be fussy. There are lots of values
in here that look like register bits and you could exchange much of
this documentation for a some good defines...
Taking base_offset + 1 bits 5 and 6 look to select the actual register
and the rest of them do the control.
Anyhow, not critical but the readability of this code could be improved
somewhat.
> + /* Reset Preset Register */
> + for (j = 0; j < 3; j++)
> + outb(0x00, base_offset);
> + /* Reset Borrow, Carry, Compare, and Sign flags */
> + outb(0x04, base_offset + 1);
> + /* Reset Error flag */
> + outb(0x06, base_offset + 1);
> + /* Binary encoding; Normal count; non-quadrature mode */
> + outb(0x20, base_offset + 1);
> + /* Disable A and B inputs; preset on index; FLG1 as Carry */
> + outb(0x40, base_offset + 1);
> + /* Disable index function; negative index polarity */
> + outb(0x60, base_offset + 1);
> + }
> + /* Enable all counters */
> + outb(0x00, base[id] + 0x11);
> +
> + /* Register IIO device */
> + err = devm_iio_device_register(dev, indio_dev);
> + if (err)
> + return err;
> +
> + /* Register Counter device */
> + return devm_counter_register(dev, &quad8iio->counter);
> +}
> +
> +static struct isa_driver quad8_driver = {
> + .probe = quad8_probe,
> + .driver = {
> + .name = "104-quad-8"
> + }
> +};
> +
> +module_isa_driver(quad8_driver, num_quad8);
> +
> +MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
> +MODULE_DESCRIPTION("ACCES 104-QUAD-8 IIO driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig
> index 65fa92abd5a4..73f03372484f 100644
> --- a/drivers/counter/Kconfig
> +++ b/drivers/counter/Kconfig
> @@ -16,3 +16,24 @@ menuconfig COUNTER
> consumption. The Generic Counter interface enables drivers to support
> and expose a common set of components and functionality present in
> counter devices.
> +
> +if COUNTER
> +
> +config 104_QUAD_8
> + tristate "ACCES 104-QUAD-8 driver"
> + depends on PC104 && X86 && IIO
> + select ISA_BUS_API
> + help
> + Say yes here to build support for the ACCES 104-QUAD-8 quadrature
> + encoder counter/interface device family (104-QUAD-8, 104-QUAD-4).
> +
> + Performing a write to a counter's IIO_CHAN_INFO_RAW sets the counter and
> + also clears the counter's respective error flag. Although the counters
> + have a 25-bit range, only the lower 24 bits may be set, either directly
> + or via a counter's preset attribute. Interrupts are not supported by
> + this driver.
This text probably wants to be updated to reflect the new counter subsystem support..
> +
> + The base port addresses for the devices may be configured via the base
> + array module parameter.
> +
> +endif # COUNTER
> diff --git a/drivers/counter/Makefile b/drivers/counter/Makefile
> index ad1ba7109cdc..23a4f6263e45 100644
> --- a/drivers/counter/Makefile
> +++ b/drivers/counter/Makefile
> @@ -6,3 +6,5 @@
>
> obj-$(CONFIG_COUNTER) += counter.o
> counter-y := generic-counter.o
> +
> +obj-$(CONFIG_104_QUAD_8) += 104-quad-8.o
> diff --git a/drivers/iio/counter/104-quad-8.c b/drivers/iio/counter/104-quad-8.c
...
^ permalink raw reply
* [PATCH 5/6] mtd: rawnand: ams-delta: use GPIO lookup table
From: Janusz Krzysztofik @ 2018-05-20 15:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAHp75Ved2nw1JKnXT2Jxnw4XLsby1eVJU6cfBjE2sp4LP4Kwmg@mail.gmail.com>
On Sunday, May 20, 2018 4:44:31 PM CEST Andy Shevchenko wrote:
> On Sun, May 20, 2018 at 12:55 AM, Janusz Krzysztofik
>
> <jmkrzyszt@gmail.com> wrote:
> > On Saturday, May 19, 2018 8:00:38 PM CEST Andy Shevchenko wrote:
> >> On Sat, May 19, 2018 at 2:15 AM, Janusz Krzysztofik <jmkrzyszt@gmail.com>
> >
> > wrote:
> >> NULL check in practice discards the _optional part of gpiod_get(). So,
> >> either you use non-optional variant and decide how to handle an
> >> errors, or user _optional w/o NULL check.
> >
> > OK, I'm going to use something like the below while submitting v2:
> >
> > - gpiod_rdy = devm_gpiod_get_optional(&pdev->dev, "rdy", GPIOD_IN);
> > - if (!IS_ERR_OR_NULL(gpiod_rdy)) {
> > - this->dev_ready = ams_delta_nand_ready;
> > - } else {
> > - this->dev_ready = NULL;
> > - pr_notice("Couldn't request gpio for Delta NAND
> > ready.\n");
> > + priv->gpiod_rdy = devm_gpiod_get_optional(&pdev->dev, "rdy",
> > + GPIOD_IN);
> > + if (IS_ERR(priv->gpiod_rdy)) {
> > + err = PTR_ERR(priv->gpiod_nwp);
> > + dev_warn(&pdev->dev, "RDY GPIO request failed (%d)\n",
> > err); + goto err_gpiod;
> >
> > }
> >
> > + if (priv->gpiod_rdy)
> > + this->dev_ready = ams_delta_nand_ready;
>
> This makes sense.
>
> Though, I completely dislike "rdy" name of GPIO. Where is it documented?
No documentation files for Amstrad Delta nor for its NAND driver specifically
exist under Documentation/. However, there exist some for generic GPIO NAND
driver where the pin name "rdy" is used explicitly:
Documentation/driver-api/gpio/drivers-on-gpio.rst
Documentation/devicetree/bindings/mtd/gpio-control-nand.txt
You can find that mnemonic used across drivers/mtd/nand/, standalone or as a
suffix, including the Amstrad Delta NAND driver before the change discussed.
To be honest, I don't like it much either, but I'm just using it instead of
inventing something new.
Thanks,
Janusz
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox