Re: [alsa-devel] [PATCH] ASoC: ams-delta: fix card initalization failure

2012-08-28 Thread Janusz Krzysztofik
On Mon, 27 Aug 2012 14:38:35 Mark Brown wrote:
> On Mon, Aug 27, 2012 at 11:28:30PM +0200, Janusz Krzysztofik wrote:
> 
> > -   platform_set_drvdata(ams_delta_audio_platform_device,
> > -   &ams_delta_audio_card);
> > -
> > -   ret = platform_device_add(ams_delta_audio_platform_device);
> > -   if (ret)
> > -   goto err;
> 
> The real fix here is that you should be using platform data here, not
> driver data.  Is there some reason not to do that?

Mark,

Do you think the change you propose is suitable for the rc cycle? I'm 
trying to fix a regression in the first place. Converting the ams-delta 
asoc to a platform driver is on my todo list and I'm going to take care 
of this as soon as I have enough spare time.

Thanks,
Janusz

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [alsa-devel] [PATCH] ASoC: ams-delta: fix card initalization failure

2012-08-28 Thread Janusz Krzysztofik
On Tue, 28 Aug 2012 11:13:39 Mark Brown wrote:
> On Tue, Aug 28, 2012 at 05:13:05PM +0200, Janusz Krzysztofik wrote:
> > On Mon, 27 Aug 2012 14:38:35 Mark Brown wrote:
> > > On Mon, Aug 27, 2012 at 11:28:30PM +0200, Janusz Krzysztofik wrote:
> 
> > > > -   platform_set_drvdata(ams_delta_audio_platform_device,
> > > > -   &ams_delta_audio_card);
> 
> > > The real fix here is that you should be using platform data here, 
not
> > > driver data.  Is there some reason not to do that?
> 
> > Do you think the change you propose is suitable for the rc cycle? 
I'm 
> > trying to fix a regression in the first place. Converting the ams-
delta 
> > asoc to a platform driver is on my todo list and I'm going to take 
care 
> > of this as soon as I have enough spare time.
> 
> The above looks like you already have a platform driver?  All I'm
> suggesting is changing the above to use platform rather than driver
> data.

The ams-delta asoc driver doesn't use snd_soc_register_card() so far, 
but relays solely on soc_probe() doing this for it, which in turn 
expects to find a snc_soc_card structure in drvdata. How is it supposed 
to find that structure if I pass it over platform data instead? Am I 
missing something?

Thanks,
Janusz
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [alsa-devel] [PATCH] ASoC: ams-delta: fix card initalization failure

2012-09-01 Thread Janusz Krzysztofik
Dnia piątek, 31 sierpnia 2012 14:31:04 Mark Brown pisze:
> On Wed, Aug 29, 2012 at 07:04:48AM +0200, Janusz Krzysztofik wrote:
> > On Tue, 28 Aug 2012 11:13:39 Mark Brown wrote:
> 
> > > The above looks like you already have a platform driver? 

Mark,
I should have rather answered: No, ams-delta.c is not a platform driver, 
only a module which registeres a soc-audio device and provides device 
specific data and callbacks to the soc-audio platform driver.

> > > All I'm
> > > suggesting is changing the above to use platform rather than 
driver
> > > data.
> ...
> s/drvdata/platdata/ in the code. 

Taking the above into account, I would have to apply this substitue to 
the soc-core.c, which is actually the platform driver for the ams-delta 
ASoC device, and this would break a lot of other cards.

> If you can't do this then just
> referencing the data directly in the code would be better than this
> bodge, it'd be much less fragile.

I see your point, however for now I can see no better way of referencing 
the data (of type struct snd_soc_card) then passing it to 
snd_soc_register_card(). But for this to work, I would have to register 
successfully an ams-delta specific platform device first, not the soc-
audio. This, even if still done from the sound/soc/omap/ams-delta.c, not 
from an arch board file, would require now not existing ams-delta ASoC 
platform driver probe/remove callbacks at least. I'm still not convinced 
if such modification would be acceptable in the middle of the rc cycle.

If there is a simpler, less intrusive way to do this, then sorry, I 
still can't see it.

Thanks,
Janusz
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] ASoC: ams-delta: fix card initalization failure

2012-08-27 Thread Janusz Krzysztofik
Since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d, 'device-core:
Ensure drvdata = NULL when no driver is bound', the Amstrad Delta sound
card no longer initializes correctly due to drvdata reset to NULL by an
upper layer before the codec device, required for successful card setup,
is registered. Fix this by moving the codec registration bits up, before
the card is probed for.

Created and tested against linux-3.6-rc3

Signed-off-by: Janusz Krzysztofik 
---
 sound/soc/omap/ams-delta.c |   18 ++
 1 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c
index 7d4fa8e..270de9c 100644
--- a/sound/soc/omap/ams-delta.c
+++ b/sound/soc/omap/ams-delta.c
@@ -590,20 +590,22 @@ static int __init ams_delta_module_init(void)
if (!ams_delta_audio_platform_device)
return -ENOMEM;
 
-   platform_set_drvdata(ams_delta_audio_platform_device,
-   &ams_delta_audio_card);
-
-   ret = platform_device_add(ams_delta_audio_platform_device);
-   if (ret)
-   goto err;
-
/*
 * Codec platform device could be registered from elsewhere (board?),
 * but I do it here as it makes sense only if used with the card.
+* Moreover, it must be registered before the card is probed for,
+* or the card setup fails due to drvdata reset by upper layers.
 */
cx20442_platform_device =
platform_device_register_simple("cx20442-codec", -1, NULL, 0);
-   return 0;
+
+   platform_set_drvdata(ams_delta_audio_platform_device,
+&ams_delta_audio_card);
+
+   ret = platform_device_add(ams_delta_audio_platform_device);
+   if (!ret)
+   return ret;
+
 err:
platform_device_put(ams_delta_audio_platform_device);
return ret;
-- 
1.7.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [alsa-devel] [PATCH v3 00/15] ASoC: OMAP: Convert to use dmaengine

2012-09-15 Thread Janusz Krzysztofik
Dnia piątek, 14 września 2012 15:05:43 Peter Ujfalusi pisze:
> Hello,
> 
> Changes since v2:
> - As it has been discussed the no_wakeup parameter has been replaced with 
> flags
>   for the dmaengine APIs
> 
> Changes since v1:
> - Support for pause/resume for OMAP audio via dmaengine
> - dmaengine: support for NO_PERIOD_WAKEUP in cyclic mode
>  - OMAP to keep supporting NO_PERIOD_WAKEUP for audio
>  - Other plaforms can also try to enable this mode since we have now generic
>interface to do so.
> 
> This series will switch the OMAP audio to use dmaengine.
> The final patch which does the switch was based on Russell King's earlier 
> patch.
> 
> The first 10 patch is to prepare the OMAP audio drivers for a smooth change to
> dmaengine:
> - sDMA FRAME sync mode is removed and replaced with PACKET mode
> - dai drivers no longer need to configure sDMA sync mode
> - dai drivers does not need to specify the DMA word length - with the 
> exception
>   of the omap-hdmi driver which requires 32bit word length regardless of the
>   audio format in use
> - the McPDM driver used (to my surprise) hackish way of getting the DMA 
> channel
>   and address - via defines from some header files
> 
> After the conversion OMAP audio support should have the same features as 
> before,
> no regressions expected.
> 
> I have tested the series on:
> - BeagleBoard (audio via McBSP): 
>  - aplay/arecord. In element mode and in threshold mode with different period
>sizes
>  - mplayer -ao alsa: for direct ALSA access
>  - mplayer -ao pulse: via PulseAudio to test NO_PERIOD_WAKEUP feature
> - OMAP4 Blaze (audio via McPDM and DMIC)
>  - aplay/arecord
>  - mplayer -ao alsa: for direct ALSA access
>  - mplayer -ao pulse: via PulseAudio to test NO_PERIOD_WAKEUP feature
> 
> The patches has been generated against:
> git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-3.7
> 
> Janusz: Can you retest this series on OMAP1 to be sure I have not broken it?

Hi Peter,
It looks like you haven't :-).

For OMAP1:
Tested-by: Janusz Krzysztofik 

Thanks,
Janusz
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RFC PATCH v2 04/12] mtd: rawnand: ams-delta: request data port GPIO resource

2018-08-06 Thread Janusz Krzysztofik
Data port used by the driver is actually an OMAP MPUIO device, already
under control of gpio-omap driver.  For that reason we used to not
request the memory region of the port as that would fail because the
region is already busy.  Despite that, we are still accessing the port
by just ioremapping it and performing read/write operations.  Moreover,
we are doing that without any proteciton from other users legally
manipulating the port pins over GPIO API.

The plan is to convert the driver to access the port over functions
exposed by the gpio-omap driver.  Before that happens, already prevent
from other users accessing the port pins by requesting an array of its
GPIO descriptors.

Signed-off-by: Janusz Krzysztofik 
---
 drivers/mtd/nand/raw/ams-delta.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index 48233d638d2a..09d6901fc94d 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -161,6 +161,7 @@ static int ams_delta_init(struct platform_device *pdev)
struct mtd_info *mtd;
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
void __iomem *io_base;
+   struct gpio_descs *data_gpiods;
int err = 0;
 
if (!res)
@@ -261,6 +262,13 @@ static int ams_delta_init(struct platform_device *pdev)
dev_err(&pdev->dev, "CLE GPIO request failed (%d)\n", err);
goto out_mtd;
}
+   /* Request array of data pins, initialize them as input */
+   data_gpiods = devm_gpiod_get_array(&pdev->dev, "data", GPIOD_IN);
+   if (IS_ERR(data_gpiods)) {
+   err = PTR_ERR(data_gpiods);
+   dev_err(&pdev->dev, "data GPIO request failed: %d\n", err);
+   goto out_mtd;
+   }
 
/* Scan to find existence of the device */
err = nand_scan(mtd, 1);
-- 
2.16.4



[PATCH v2 01/10] ARM: OMAP1: ams-delta: drop GPIO lookup table for serio device

2018-06-21 Thread Janusz Krzysztofik
GPIO lookup table for ams-delta-serio device was introduced by commit
0486738928bf ("ARM: OMAP1: ams-delta: add GPIO lookup tables").
Unfortunately, a follow up patch "Input: ams_delta_serio: use GPIO
lookup table" was not accepted by subystem maintainer who requested
conversion of the driver to a platform driver, replacepemnt of IRQ GPIO
pin with IRQ resource, replacement of GPIO pin providing keyboard power
with a regulator and removal of remaining GPIO pins from the driver as
not handled by it.

Let's start with removal of the no longer needed GPIO lookup table from
the board init file.

Signed-off-by: Janusz Krzysztofik 
---
Changelog:
v2: rebased on v4.18-rc1, no conflicts

 arch/arm/mach-omap1/board-ams-delta.c | 19 ---
 1 file changed, 19 deletions(-)

diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index 80f54cb54276..18e0ff437b27 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -504,20 +504,6 @@ static struct platform_device cx20442_codec_device = {
.id = -1,
 };
 
-static struct gpiod_lookup_table ams_delta_serio_gpio_table = {
-   .table = {
-   GPIO_LOOKUP(OMAP_GPIO_LABEL, AMS_DELTA_GPIO_PIN_KEYBRD_DATA,
-   "data", 0),
-   GPIO_LOOKUP(OMAP_GPIO_LABEL, AMS_DELTA_GPIO_PIN_KEYBRD_CLK,
-   "clock", 0),
-   GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_KEYBRD_PWR,
-   "power", 0),
-   GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_KEYBRD_DATAOUT,
-   "dataout", 0),
-   { },
-   },
-};
-
 static struct platform_device *ams_delta_devices[] __initdata = {
&latch1_gpio_device,
&latch2_gpio_device,
@@ -534,7 +520,6 @@ static struct platform_device *late_devices[] __initdata = {
 
 static struct gpiod_lookup_table *ams_delta_gpio_tables[] __initdata = {
&ams_delta_audio_gpio_table,
-   &ams_delta_serio_gpio_table,
 };
 
 static struct gpiod_lookup_table *late_gpio_tables[] __initdata = {
@@ -580,10 +565,6 @@ static void __init ams_delta_init(void)
 */
ams_delta_audio_gpio_table.dev_id =
dev_name(&ams_delta_audio_device.dev);
-   /*
-* No device name is assigned to GPIO lookup table for serio device
-* as long as serio driver is not converted to platform device driver.
-*/
 
gpiod_add_lookup_tables(ams_delta_gpio_tables,
ARRAY_SIZE(ams_delta_gpio_tables));
-- 
2.16.4



[PATCH v2 03/10] Input: ams_delta_serio: use private structure

2018-06-21 Thread Janusz Krzysztofik
Introduce a driver private structure and allocate it on device probe.
For now, use it instead of a static variable for storing a pointer to
serio structure.  Subsequent patches will populate it with more members
as needed.

Signed-off-by: Janusz Krzysztofik 
---
Changelog:
v2: rebased on v4.18-rc1, no conflicts

 drivers/input/serio/ams_delta_serio.c | 69 ++-
 1 file changed, 43 insertions(+), 26 deletions(-)

diff --git a/drivers/input/serio/ams_delta_serio.c 
b/drivers/input/serio/ams_delta_serio.c
index a2a7fa19bf49..551a4fa73fe4 100644
--- a/drivers/input/serio/ams_delta_serio.c
+++ b/drivers/input/serio/ams_delta_serio.c
@@ -37,17 +37,17 @@ MODULE_AUTHOR("Matt Callow");
 MODULE_DESCRIPTION("AMS Delta (E3) keyboard port driver");
 MODULE_LICENSE("GPL");
 
-static struct serio *ams_delta_serio;
+struct ams_delta_serio {
+   struct serio *serio;
+};
 
-static int check_data(int data)
+static int check_data(struct serio *serio, int data)
 {
int i, parity = 0;
 
/* check valid stop bit */
if (!(data & 0x400)) {
-   dev_warn(&ams_delta_serio->dev,
-   "invalid stop bit, data=0x%X\n",
-   data);
+   dev_warn(&serio->dev, "invalid stop bit, data=0x%X\n", data);
return SERIO_FRAME;
}
/* calculate the parity */
@@ -57,9 +57,9 @@ static int check_data(int data)
}
/* it should be odd */
if (!(parity & 0x01)) {
-   dev_warn(&ams_delta_serio->dev,
-   "parity check failed, data=0x%X parity=0x%X\n",
-   data, parity);
+   dev_warn(&serio->dev,
+"parity check failed, data=0x%X parity=0x%X\n", data,
+parity);
return SERIO_PARITY;
}
return 0;
@@ -67,6 +67,7 @@ static int check_data(int data)
 
 static irqreturn_t ams_delta_serio_interrupt(int irq, void *dev_id)
 {
+   struct ams_delta_serio *priv = dev_id;
int *circ_buff = &fiq_buffer[FIQ_CIRC_BUFF];
int data, dfl;
u8 scancode;
@@ -84,9 +85,9 @@ static irqreturn_t ams_delta_serio_interrupt(int irq, void 
*dev_id)
if (fiq_buffer[FIQ_HEAD_OFFSET] == fiq_buffer[FIQ_BUF_LEN])
fiq_buffer[FIQ_HEAD_OFFSET] = 0;
 
-   dfl = check_data(data);
+   dfl = check_data(priv->serio, data);
scancode = (u8) (data >> 1) & 0xFF;
-   serio_interrupt(ams_delta_serio, scancode, dfl);
+   serio_interrupt(priv->serio, scancode, dfl);
}
return IRQ_HANDLED;
 }
@@ -130,21 +131,14 @@ static const struct gpio ams_delta_gpios[] 
__initconst_or_module = {
 
 static int ams_delta_serio_init(struct platform_device *pdev)
 {
+   struct ams_delta_serio *priv;
+   struct serio *serio;
int err;
 
-   ams_delta_serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
-   if (!ams_delta_serio)
+   priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+   if (!priv)
return -ENOMEM;
 
-   ams_delta_serio->id.type = SERIO_8042;
-   ams_delta_serio->open = ams_delta_serio_open;
-   ams_delta_serio->close = ams_delta_serio_close;
-   strlcpy(ams_delta_serio->name, "AMS DELTA keyboard adapter",
-   sizeof(ams_delta_serio->name));
-   strlcpy(ams_delta_serio->phys, dev_name(&pdev->dev),
-   sizeof(ams_delta_serio->phys));
-   ams_delta_serio->dev.parent = &pdev->dev;
-
err = gpio_request_array(ams_delta_gpios,
ARRAY_SIZE(ams_delta_gpios));
if (err) {
@@ -154,7 +148,7 @@ static int ams_delta_serio_init(struct platform_device 
*pdev)
 
err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
ams_delta_serio_interrupt, IRQ_TYPE_EDGE_RISING,
-   DRIVER_NAME, 0);
+   DRIVER_NAME, priv);
if (err < 0) {
dev_err(&pdev->dev, "IRQ request failed (%d)\n", err);
goto gpio;
@@ -167,21 +161,44 @@ static int ams_delta_serio_init(struct platform_device 
*pdev)
irq_set_handler(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
handle_simple_irq);
 
-   serio_register_port(ams_delta_serio);
-   dev_info(&ams_delta_serio->dev, "%s\n", ams_delta_serio->name);
+   serio = kzalloc(sizeof(*serio), GFP_KERNEL);
+   if (!serio) {
+   err = -ENOMEM;
+   goto irq;
+   }
+
+   priv->serio = serio;
+
+   serio->id.type = SERIO_8042;
+   serio->open = ams_delta_serio_o

[PATCH v2 02/10] Input: ams_delta_serio: convert to platform driver

2018-06-21 Thread Janusz Krzysztofik
Convert the driver to an "ams-delta-serio" platform driver.  For it to
be used with Amstrad Delta, register an "ams-delta-serio" platform
device from the board init file.

Signed-off-by: Janusz Krzysztofik 
---
Changelog:
v2: rebased on v4.18-rc1, no conflicts

 arch/arm/mach-omap1/board-ams-delta.c |  6 ++
 drivers/input/serio/ams_delta_serio.c | 34 +-
 2 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index 18e0ff437b27..2119d2d3ba84 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -504,12 +504,18 @@ static struct platform_device cx20442_codec_device = {
.id = -1,
 };
 
+static struct platform_device ams_delta_serio_device = {
+   .name   = "ams-delta-serio",
+   .id = PLATFORM_DEVID_NONE,
+};
+
 static struct platform_device *ams_delta_devices[] __initdata = {
&latch1_gpio_device,
&latch2_gpio_device,
&ams_delta_kp_device,
&ams_delta_camera_device,
&ams_delta_audio_device,
+   &ams_delta_serio_device,
 };
 
 static struct platform_device *late_devices[] __initdata = {
diff --git a/drivers/input/serio/ams_delta_serio.c 
b/drivers/input/serio/ams_delta_serio.c
index 3df501c3421b..a2a7fa19bf49 100644
--- a/drivers/input/serio/ams_delta_serio.c
+++ b/drivers/input/serio/ams_delta_serio.c
@@ -22,15 +22,17 @@
  */
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 
-#include 
 #include 
 
 #include 
 
+#define DRIVER_NAME"ams-delta-serio"
+
 MODULE_AUTHOR("Matt Callow");
 MODULE_DESCRIPTION("AMS Delta (E3) keyboard port driver");
 MODULE_LICENSE("GPL");
@@ -126,13 +128,10 @@ static const struct gpio ams_delta_gpios[] 
__initconst_or_module = {
},
 };
 
-static int __init ams_delta_serio_init(void)
+static int ams_delta_serio_init(struct platform_device *pdev)
 {
int err;
 
-   if (!machine_is_ams_delta())
-   return -ENODEV;
-
ams_delta_serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (!ams_delta_serio)
return -ENOMEM;
@@ -142,22 +141,22 @@ static int __init ams_delta_serio_init(void)
ams_delta_serio->close = ams_delta_serio_close;
strlcpy(ams_delta_serio->name, "AMS DELTA keyboard adapter",
sizeof(ams_delta_serio->name));
-   strlcpy(ams_delta_serio->phys, "GPIO/serio0",
+   strlcpy(ams_delta_serio->phys, dev_name(&pdev->dev),
sizeof(ams_delta_serio->phys));
+   ams_delta_serio->dev.parent = &pdev->dev;
 
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");
+   dev_err(&pdev->dev, "Couldn't request gpio pins\n");
goto serio;
}
 
err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
ams_delta_serio_interrupt, IRQ_TYPE_EDGE_RISING,
-   "ams-delta-serio", 0);
+   DRIVER_NAME, 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));
+   dev_err(&pdev->dev, "IRQ request failed (%d)\n", err);
goto gpio;
}
/*
@@ -179,13 +178,22 @@ static int __init ams_delta_serio_init(void)
kfree(ams_delta_serio);
return err;
 }
-module_init(ams_delta_serio_init);
 
-static void __exit ams_delta_serio_exit(void)
+static int ams_delta_serio_exit(struct platform_device *pdev)
 {
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));
+
+   return 0;
 }
-module_exit(ams_delta_serio_exit);
+
+static struct platform_driver ams_delta_serio_driver = {
+   .probe  = ams_delta_serio_init,
+   .remove = ams_delta_serio_exit,
+   .driver = {
+   .name   = DRIVER_NAME
+   },
+};
+module_platform_driver(ams_delta_serio_driver);
-- 
2.16.4



[PATCH v2 08/10] ARM: OMAP1: Get rid of

2018-06-21 Thread Janusz Krzysztofik
Split the header file into two parts and move them to directories where
they belong.

Information on internal structure of FIQ buffer is moved to
 for ams-delta-serio driver use.

Other information used by ams-delta board init file and FIQ code is
made local to mach-omap1 root directory.

Signed-off-by: Janusz Krzysztofik 
---
Changelog:
v2: rebased on v4.18-rc1, no conflicts

 MAINTAINERS|  1 +
 arch/arm/mach-omap1/ams-delta-fiq-handler.S|  5 +--
 arch/arm/mach-omap1/ams-delta-fiq.c|  7 ++--
 arch/arm/mach-omap1/ams-delta-fiq.h| 41 ++
 arch/arm/mach-omap1/board-ams-delta.c  |  2 +-
 drivers/input/serio/ams_delta_serio.c  |  3 +-
 .../linux/platform_data}/ams-delta-fiq.h   | 27 +++---
 7 files changed, 56 insertions(+), 30 deletions(-)
 create mode 100644 arch/arm/mach-omap1/ams-delta-fiq.h
 rename {arch/arm/mach-omap1/include/mach => 
include/linux/platform_data}/ams-delta-fiq.h (71%)

diff --git a/MAINTAINERS b/MAINTAINERS
index 9d5eeff51b5f..c78b7dc42a81 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10391,6 +10391,7 @@ F:  arch/arm/plat-omap/
 F: arch/arm/configs/omap1_defconfig
 F: drivers/i2c/busses/i2c-omap.c
 F: include/linux/platform_data/i2c-omap.h
+F: include/linux/platform_data/ams-delta-fiq.h
 
 OMAP2+ SUPPORT
 M: Tony Lindgren 
diff --git a/arch/arm/mach-omap1/ams-delta-fiq-handler.S 
b/arch/arm/mach-omap1/ams-delta-fiq-handler.S
index bf608441b357..ddc27638ba2a 100644
--- a/arch/arm/mach-omap1/ams-delta-fiq-handler.S
+++ b/arch/arm/mach-omap1/ams-delta-fiq-handler.S
@@ -14,11 +14,12 @@
  */
 
 #include 
-#include 
+#include 
 
+#include 
 #include 
-#include 
 
+#include "ams-delta-fiq.h"
 #include "iomap.h"
 #include "soc.h"
 
diff --git a/arch/arm/mach-omap1/ams-delta-fiq.c 
b/arch/arm/mach-omap1/ams-delta-fiq.c
index 5a6c59ac9b5f..e72935034d42 100644
--- a/arch/arm/mach-omap1/ams-delta-fiq.c
+++ b/arch/arm/mach-omap1/ams-delta-fiq.c
@@ -19,12 +19,13 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
 #include 
 
-#include 
+#include "ams-delta-fiq.h"
 
 static struct fiq_handler fh = {
.name   = "ams-delta-fiq"
@@ -35,8 +36,8 @@ static struct fiq_handler fh = {
  * The FIQ and IRQ isrs can both read and write it.
  * It is structured as a header section several 32bit slots,
  * followed by the circular buffer where the FIQ isr stores
- * keystrokes received from the qwerty keyboard.
- * See ams-delta-fiq.h for details of offsets.
+ * keystrokes received from the qwerty keyboard.  See
+ *  for details of offsets.
  */
 unsigned int fiq_buffer[1024];
 EXPORT_SYMBOL(fiq_buffer);
diff --git a/arch/arm/mach-omap1/ams-delta-fiq.h 
b/arch/arm/mach-omap1/ams-delta-fiq.h
new file mode 100644
index ..3f691d68aa62
--- /dev/null
+++ b/arch/arm/mach-omap1/ams-delta-fiq.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * arch/arm/mach-omap1/ams-delta-fiq.h
+ *
+ * Taken from the original Amstrad modifications to fiq.h
+ *
+ * Copyright (c) 2004 Amstrad Plc
+ * Copyright (c) 2006 Matt Callow
+ * Copyright (c) 2010 Janusz Krzysztofik
+ *
+ * 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.
+ */
+#ifndef __AMS_DELTA_FIQ_H
+#define __AMS_DELTA_FIQ_H
+
+#include 
+
+/*
+ * Interrupt number used for passing control from FIQ to IRQ.
+ * IRQ12, described as reserved, has been selected.
+ */
+#define INT_DEFERRED_FIQ   INT_1510_RES12
+/*
+ * Base address of an interrupt handler that the INT_DEFERRED_FIQ belongs to.
+ */
+#if (INT_DEFERRED_FIQ < IH2_BASE)
+#define DEFERRED_FIQ_IH_BASE   OMAP_IH1_BASE
+#else
+#define DEFERRED_FIQ_IH_BASE   OMAP_IH2_BASE
+#endif
+
+#ifndef __ASSEMBLER__
+extern unsigned char qwerty_fiqin_start, qwerty_fiqin_end;
+
+extern void __init ams_delta_init_fiq(struct gpio_chip *chip);
+#endif
+
+#endif
diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index f15c0793c34b..fe9a3e7cbfeb 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -41,10 +41,10 @@
 #include 
 
 #include 
-#include 
 #include "camera.h"
 #include 
 
+#include "ams-delta-fiq.h"
 #include "iomap.h"
 #include "common.h"
 
diff --git a/drivers/input/serio/ams_delta_serio.c 
b/drivers/input/serio/ams_delta_serio.c
index 7952a29f9540..2602f7cff5ae 100644
--- a/drivers/input/serio/ams_delta_serio.c
+++ b/drivers/input/serio/ams_delta_serio.c
@@ -22,6 +22,7 @@
  */
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -30,8 +31,6 @@
 
 #include 
 
-#include 
-
 #define DRIVER_NAME"ams-delta-serio"
 
 MODULE_AUTHOR("Matt Callow");
diff --git a/arch/arm/mach-oma

[PATCH v2 09/10] Input: ams_delta_serio: use IRQ resource

2018-06-21 Thread Janusz Krzysztofik
The driver still obtains IRQ number from a hardcoded GPIO.  Use IRQ
resource instead.

For this to work on Amstrad Delta, add the IRQ resource to
ams-delta-serio platform device structure.  Obtain the IRQ number
assigned to "keybrd_clk" GPIO pin from FIQ initialization routine.

As a benefit, the driver no longer needs to include
.

Signed-off-by: Janusz Krzysztofik 
---
Changelog:
v2: - obsolete assignment of handle_simple_irq() removed from the driver
  and replaced with a comment in the FIQ init file,
- rebased on v4.18-rc1, no conflicts.

 arch/arm/mach-omap1/ams-delta-fiq.c   | 20 +++-
 arch/arm/mach-omap1/ams-delta-fiq.h   |  3 ++-
 arch/arm/mach-omap1/board-ams-delta.c | 17 -
 drivers/input/serio/ams_delta_serio.c | 32 +---
 4 files changed, 46 insertions(+), 26 deletions(-)

diff --git a/arch/arm/mach-omap1/ams-delta-fiq.c 
b/arch/arm/mach-omap1/ams-delta-fiq.c
index e72935034d42..82ca4246a5e4 100644
--- a/arch/arm/mach-omap1/ams-delta-fiq.c
+++ b/arch/arm/mach-omap1/ams-delta-fiq.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -84,7 +85,8 @@ static irqreturn_t deferred_fiq(int irq, void *dev_id)
return IRQ_HANDLED;
 }
 
-void __init ams_delta_init_fiq(struct gpio_chip *chip)
+void __init ams_delta_init_fiq(struct gpio_chip *chip,
+  struct platform_device *serio)
 {
struct gpio_desc *gpiod, *data = NULL, *clk = NULL;
void *fiqhandler_start;
@@ -201,6 +203,22 @@ void __init ams_delta_init_fiq(struct gpio_chip *chip)
val = omap_readl(OMAP_IH1_BASE + offset) | 1;
omap_writel(val, OMAP_IH1_BASE + offset);
 
+   /* Initialize serio device IRQ resource */
+   serio->resource[0].start = gpiod_to_irq(clk);
+   serio->resource[0].end = serio->resource[0].start;
+
+   /*
+* Since FIQ handler performs handling of GPIO registers for
+* "keybrd_clk" IRQ pin, ams_delta_serio driver used to set
+* handle_simple_irq() as active IRQ handler for that pin to avoid
+* bad interaction with gpio-omap driver.  This is no longer needed
+* as handle_simple_irq() is now the default handler for OMAP GPIO
+* edge interrupts.
+* This comment replaces the obsolete code which has been removed
+* from the ams_delta_serio driver and stands here only as a reminder
+* of that dependency on gpio-omap driver behavior.
+*/
+
return;
 
 out_gpio:
diff --git a/arch/arm/mach-omap1/ams-delta-fiq.h 
b/arch/arm/mach-omap1/ams-delta-fiq.h
index 3f691d68aa62..fd76df3cce37 100644
--- a/arch/arm/mach-omap1/ams-delta-fiq.h
+++ b/arch/arm/mach-omap1/ams-delta-fiq.h
@@ -35,7 +35,8 @@
 #ifndef __ASSEMBLER__
 extern unsigned char qwerty_fiqin_start, qwerty_fiqin_end;
 
-extern void __init ams_delta_init_fiq(struct gpio_chip *chip);
+extern void __init ams_delta_init_fiq(struct gpio_chip *chip,
+ struct platform_device *pdev);
 #endif
 
 #endif
diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index fe9a3e7cbfeb..84177ba3e39a 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -504,9 +504,24 @@ static struct platform_device cx20442_codec_device = {
.id = -1,
 };
 
+static struct resource ams_delta_serio_resources[] = {
+   {
+   .flags  = IORESOURCE_IRQ,
+   /*
+* Initialize IRQ resource with invalid IRQ number.
+* It will be replaced with dynamically allocated GPIO IRQ
+* obtained from GPIO chip as soon as the chip is available.
+*/
+   .start  = -EINVAL,
+   .end= -EINVAL,
+   },
+};
+
 static struct platform_device ams_delta_serio_device = {
.name   = "ams-delta-serio",
.id = PLATFORM_DEVID_NONE,
+   .num_resources  = ARRAY_SIZE(ams_delta_serio_resources),
+   .resource   = ams_delta_serio_resources,
 };
 
 static struct regulator_consumer_supply keybrd_pwr_consumers[] = {
@@ -615,7 +630,7 @@ static void __init omap_gpio_deps_init(void)
return;
}
 
-   ams_delta_init_fiq(chip);
+   ams_delta_init_fiq(chip, &ams_delta_serio_device);
 }
 
 static void __init ams_delta_init(void)
diff --git a/drivers/input/serio/ams_delta_serio.c 
b/drivers/input/serio/ams_delta_serio.c
index 2602f7cff5ae..c1f8226f172e 100644
--- a/drivers/input/serio/ams_delta_serio.c
+++ b/drivers/input/serio/ams_delta_serio.c
@@ -20,7 +20,6 @@
  * However, when used with the E3 mailboard that producecs non-standard
  * scancodes, a custom key table must be prepared and loaded from userspace.
  */
-#include 
 #include 
 #include 
 #include 
@@ -29,8 +28,6 @@
 #include 
 #include 
 
-#include 
-
 #define DRIVER_NAME"ams-delta-s

[PATCH v2 07/10] ARM: OMAP1: ams-delta FIQ: Keep serio input GPIOs requested

2018-06-21 Thread Janusz Krzysztofik
>From the very beginning, input GPIO pins of ams-delta serio port have
been used by FIQ handler, not serio driver.

Don't request those pins from the ams-delta-serio driver any longer,
instead keep them requested and initialized by the FIQ initialization
routine which already requests them and releases while identifying GPIO
IRQs.

Signed-off-by: Janusz Krzysztofik 
---
Changelog:
v2: rebased on v4.18-rc1, no conflicts

 arch/arm/mach-omap1/ams-delta-fiq.c   | 42 ++-
 drivers/input/serio/ams_delta_serio.c | 30 ++---
 2 files changed, 39 insertions(+), 33 deletions(-)

diff --git a/arch/arm/mach-omap1/ams-delta-fiq.c 
b/arch/arm/mach-omap1/ams-delta-fiq.c
index 1d54a6177f14..5a6c59ac9b5f 100644
--- a/arch/arm/mach-omap1/ams-delta-fiq.c
+++ b/arch/arm/mach-omap1/ams-delta-fiq.c
@@ -45,6 +45,11 @@ static struct irq_chip *irq_chip;
 static struct irq_data *irq_data[16];
 static unsigned int irq_counter[16];
 
+static const char *pin_name[16] __initconst = {
+   [AMS_DELTA_GPIO_PIN_KEYBRD_DATA]= "keybrd_data",
+   [AMS_DELTA_GPIO_PIN_KEYBRD_CLK] = "keybrd_clk",
+};
+
 static irqreturn_t deferred_fiq(int irq, void *dev_id)
 {
struct irq_data *d;
@@ -80,7 +85,7 @@ static irqreturn_t deferred_fiq(int irq, void *dev_id)
 
 void __init ams_delta_init_fiq(struct gpio_chip *chip)
 {
-   struct gpio_desc *gpiod;
+   struct gpio_desc *gpiod, *data = NULL, *clk = NULL;
void *fiqhandler_start;
unsigned int fiqhandler_length;
struct pt_regs FIQ_regs;
@@ -96,7 +101,7 @@ void __init ams_delta_init_fiq(struct gpio_chip *chip)
}
 
for (i = 0; i < ARRAY_SIZE(irq_data); i++) {
-   gpiod = gpiochip_request_own_desc(chip, i, NULL);
+   gpiod = gpiochip_request_own_desc(chip, i, pin_name[i]);
if (IS_ERR(gpiod)) {
pr_err("%s: failed to get GPIO pin %d (%ld)\n",
   __func__, i, PTR_ERR(gpiod));
@@ -105,8 +110,27 @@ void __init ams_delta_init_fiq(struct gpio_chip *chip)
/* Store irq_data location for IRQ handler use */
irq_data[i] = irq_get_irq_data(gpiod_to_irq(gpiod));
 
-   gpiochip_free_own_desc(gpiod);
+   /*
+* FIQ handler takes full control over serio data and clk GPIO
+* pins.  Initiaize them and keep requested so nobody can
+* interfere.  Fail if any of those two couldn't be requested.
+*/
+   switch (i) {
+   case AMS_DELTA_GPIO_PIN_KEYBRD_DATA:
+   data = gpiod;
+   gpiod_direction_input(data);
+   break;
+   case AMS_DELTA_GPIO_PIN_KEYBRD_CLK:
+   clk = gpiod;
+   gpiod_direction_input(clk);
+   break;
+   default:
+   gpiochip_free_own_desc(gpiod);
+   break;
+   }
}
+   if (!data || !clk)
+   goto out_gpio;
 
fiqhandler_start = &qwerty_fiqin_start;
fiqhandler_length = &qwerty_fiqin_end - &qwerty_fiqin_start;
@@ -117,7 +141,7 @@ void __init ams_delta_init_fiq(struct gpio_chip *chip)
if (retval) {
pr_err("ams_delta_init_fiq(): couldn't claim FIQ, ret=%d\n",
retval);
-   return;
+   goto out_gpio;
}
 
retval = request_irq(INT_DEFERRED_FIQ, deferred_fiq,
@@ -125,7 +149,7 @@ void __init ams_delta_init_fiq(struct gpio_chip *chip)
if (retval < 0) {
pr_err("Failed to get deferred_fiq IRQ, ret=%d\n", retval);
release_fiq(&fh);
-   return;
+   goto out_gpio;
}
/*
 * Since no set_type() method is provided by OMAP irq chip,
@@ -175,4 +199,12 @@ void __init ams_delta_init_fiq(struct gpio_chip *chip)
offset = IRQ_ILR0_REG_OFFSET + (INT_GPIO_BANK1 - NR_IRQS_LEGACY) * 0x4;
val = omap_readl(OMAP_IH1_BASE + offset) | 1;
omap_writel(val, OMAP_IH1_BASE + offset);
+
+   return;
+
+out_gpio:
+   if (data)
+   gpiochip_free_own_desc(data);
+   if (clk)
+   gpiochip_free_own_desc(clk);
 }
diff --git a/drivers/input/serio/ams_delta_serio.c 
b/drivers/input/serio/ams_delta_serio.c
index b955c6a72e99..7952a29f9540 100644
--- a/drivers/input/serio/ams_delta_serio.c
+++ b/drivers/input/serio/ams_delta_serio.c
@@ -110,19 +110,6 @@ static void ams_delta_serio_close(struct serio *serio)
regulator_disable(priv->vcc);
 }
 
-static const struct gpio ams_delta_gpios[] __initconst_or_module = {
-   {
-   .gpio   = AMS_DELTA_GPIO_PIN_KEYBRD_DATA,
-   .flags  = GPIOF_DIR_IN,
-   .label 

[PATCH v2 10/10] Input: ams_delta_serio: Get FIQ buffer from platform_data

2018-06-21 Thread Janusz Krzysztofik
Instead of exporting the FIQ buffer symbol to be used in
ams-delta-serio driver, pass it to the driver as platform_data.

Signed-off-by: Janusz Krzysztofik 
---
Changelog:
v2: rebased on v4.18-rc1, no conflicts

 arch/arm/mach-omap1/ams-delta-fiq.c |  6 +++---
 arch/arm/mach-omap1/board-ams-delta.c   |  8 
 drivers/input/serio/ams_delta_serio.c   | 20 +---
 include/linux/platform_data/ams-delta-fiq.h |  4 
 4 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/arch/arm/mach-omap1/ams-delta-fiq.c 
b/arch/arm/mach-omap1/ams-delta-fiq.c
index 82ca4246a5e4..b0dc7ddf5877 100644
--- a/arch/arm/mach-omap1/ams-delta-fiq.c
+++ b/arch/arm/mach-omap1/ams-delta-fiq.c
@@ -40,8 +40,7 @@ static struct fiq_handler fh = {
  * keystrokes received from the qwerty keyboard.  See
  *  for details of offsets.
  */
-unsigned int fiq_buffer[1024];
-EXPORT_SYMBOL(fiq_buffer);
+static unsigned int fiq_buffer[1024];
 
 static struct irq_chip *irq_chip;
 static struct irq_data *irq_data[16];
@@ -203,9 +202,10 @@ void __init ams_delta_init_fiq(struct gpio_chip *chip,
val = omap_readl(OMAP_IH1_BASE + offset) | 1;
omap_writel(val, OMAP_IH1_BASE + offset);
 
-   /* Initialize serio device IRQ resource */
+   /* Initialize serio device IRQ resource and platform_data */
serio->resource[0].start = gpiod_to_irq(clk);
serio->resource[0].end = serio->resource[0].start;
+   serio->dev.platform_data = fiq_buffer;
 
/*
 * Since FIQ handler performs handling of GPIO registers for
diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index 84177ba3e39a..772892487827 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -520,6 +520,14 @@ static struct resource ams_delta_serio_resources[] = {
 static struct platform_device ams_delta_serio_device = {
.name   = "ams-delta-serio",
.id = PLATFORM_DEVID_NONE,
+   .dev= {
+   /*
+* Initialize .platform_data explicitly with NULL to
+* indicate it is going to be used.  It will be replaced
+* with FIQ buffer address as soon as FIQ is initialized.
+*/
+   .platform_data = NULL,
+   },
.num_resources  = ARRAY_SIZE(ams_delta_serio_resources),
.resource   = ams_delta_serio_resources,
 };
diff --git a/drivers/input/serio/ams_delta_serio.c 
b/drivers/input/serio/ams_delta_serio.c
index c1f8226f172e..f8663d7891f2 100644
--- a/drivers/input/serio/ams_delta_serio.c
+++ b/drivers/input/serio/ams_delta_serio.c
@@ -37,6 +37,7 @@ MODULE_LICENSE("GPL");
 struct ams_delta_serio {
struct serio *serio;
struct regulator *vcc;
+   unsigned int *fiq_buffer;
 };
 
 static int check_data(struct serio *serio, int data)
@@ -66,22 +67,23 @@ static int check_data(struct serio *serio, int data)
 static irqreturn_t ams_delta_serio_interrupt(int irq, void *dev_id)
 {
struct ams_delta_serio *priv = dev_id;
-   int *circ_buff = &fiq_buffer[FIQ_CIRC_BUFF];
+   int *circ_buff = &priv->fiq_buffer[FIQ_CIRC_BUFF];
int data, dfl;
u8 scancode;
 
-   fiq_buffer[FIQ_IRQ_PEND] = 0;
+   priv->fiq_buffer[FIQ_IRQ_PEND] = 0;
 
/*
 * Read data from the circular buffer, check it
 * and then pass it on the serio
 */
-   while (fiq_buffer[FIQ_KEYS_CNT] > 0) {
+   while (priv->fiq_buffer[FIQ_KEYS_CNT] > 0) {
 
-   data = circ_buff[fiq_buffer[FIQ_HEAD_OFFSET]++];
-   fiq_buffer[FIQ_KEYS_CNT]--;
-   if (fiq_buffer[FIQ_HEAD_OFFSET] == fiq_buffer[FIQ_BUF_LEN])
-   fiq_buffer[FIQ_HEAD_OFFSET] = 0;
+   data = circ_buff[priv->fiq_buffer[FIQ_HEAD_OFFSET]++];
+   priv->fiq_buffer[FIQ_KEYS_CNT]--;
+   if (priv->fiq_buffer[FIQ_HEAD_OFFSET] ==
+   priv->fiq_buffer[FIQ_BUF_LEN])
+   priv->fiq_buffer[FIQ_HEAD_OFFSET] = 0;
 
dfl = check_data(priv->serio, data);
scancode = (u8) (data >> 1) & 0xFF;
@@ -116,6 +118,10 @@ static int ams_delta_serio_init(struct platform_device 
*pdev)
if (!priv)
return -ENOMEM;
 
+   priv->fiq_buffer = pdev->dev.platform_data;
+   if (!priv->fiq_buffer)
+   return -EINVAL;
+
priv->vcc = devm_regulator_get(&pdev->dev, "vcc");
if (IS_ERR(priv->vcc)) {
err = PTR_ERR(priv->vcc);
diff --git a/include/linux/platform_data/ams-delta-fiq.h 
b/include/linux/platform_data/ams-delta-fiq.h
index dc0f835ea918..cf4589ccb720 100644
--- a/include/linux/platform_data/ams-delta-fiq.h
+++ b/include/linux/platform_data/ams-delta-fiq.h
@@ -55,8 +55,4 @@
 
 #define

[PATCH v2 05/10] ARM: OMAP1: ams-delta: Hog "keybrd_dataout" GPIO pin

2018-06-21 Thread Janusz Krzysztofik
"keybrd_dataout" GPIO pin used to be initialized by ams-delta-serio
driver to a state safe for ams-delta-serio device function and not
changed thereafter.  As such, it may be assumed not under the driver
control and responsibility for its initialization handed over to board
init file.

Introduce a GPIO hog table and take over control of the
"keybrd_dataout" GPIO pin from the ams-delta-serio driver.

Signed-off-by: Janusz Krzysztofik 
---
Changelog:
v2: rebased on v4.18-rc1, no conflicts

 arch/arm/mach-omap1/board-ams-delta.c | 8 
 drivers/input/serio/ams_delta_serio.c | 5 -
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index 706eb2f9301d..2821284aa0c9 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -574,6 +574,12 @@ static struct gpiod_lookup_table *late_gpio_tables[] 
__initdata = {
&ams_delta_nand_gpio_table,
 };
 
+static struct gpiod_hog ams_delta_gpio_hogs[] = {
+   GPIO_HOG(LATCH2_LABEL, LATCH2_PIN_KEYBRD_DATAOUT, "keybrd_dataout",
+GPIO_ACTIVE_HIGH, GPIOD_OUT_LOW),
+   {},
+};
+
 static void __init ams_delta_init(void)
 {
/* mux pins for uarts */
@@ -594,6 +600,8 @@ static void __init ams_delta_init(void)
omap_cfg_reg(J19_1610_CAM_D6);
omap_cfg_reg(J18_1610_CAM_D7);
 
+   gpiod_add_hogs(ams_delta_gpio_hogs);
+
omap_serial_init();
omap_register_i2c_bus(1, 100, NULL, 0);
 
diff --git a/drivers/input/serio/ams_delta_serio.c 
b/drivers/input/serio/ams_delta_serio.c
index 854d0d3ada52..b955c6a72e99 100644
--- a/drivers/input/serio/ams_delta_serio.c
+++ b/drivers/input/serio/ams_delta_serio.c
@@ -121,11 +121,6 @@ static const struct gpio ams_delta_gpios[] 
__initconst_or_module = {
.flags  = GPIOF_DIR_IN,
.label  = "serio-clock",
},
-   {
-   .gpio   = AMS_DELTA_GPIO_PIN_KEYBRD_DATAOUT,
-   .flags  = GPIOF_OUT_INIT_LOW,
-   .label  = "serio-dataout",
-   },
 };
 
 static int ams_delta_serio_init(struct platform_device *pdev)
-- 
2.16.4



[PATCH v2 06/10] ARM: OMAP1: ams-delta FIQ: don't use static GPIO numbers

2018-06-21 Thread Janusz Krzysztofik
With introduction of GPIO lookup tables to Amstrad Delta board init
file, semantics of symbols representing OMAP GPIO pins defined in
 changed from statically assigned global GPIO
numbers to hardware pin numbers local to OMAP "gpio-0-15" chip.

This patch modifies deferred FIQ interrupt handler so it no longer uses
static GPIO numbers in favour of IRQ data descriptors obtained at FIQ
initialization time from descriptor of the GPIO chip with use of its
hardware pin numbers.  The chip descriptor is passed from the board
init file.

As a benefit, the deferred FIQ handler should work faster.

Signed-off-by: Janusz Krzysztofik 
Acked-by: Linus Walleij 
---
Changelog:
v2: rebased on v4.18-rc1, no conflicts

 arch/arm/mach-omap1/ams-delta-fiq.c  | 48 +---
 arch/arm/mach-omap1/board-ams-delta.c| 41 +++-
 arch/arm/mach-omap1/include/mach/ams-delta-fiq.h |  2 +-
 3 files changed, 74 insertions(+), 17 deletions(-)

diff --git a/arch/arm/mach-omap1/ams-delta-fiq.c 
b/arch/arm/mach-omap1/ams-delta-fiq.c
index d7ca9e2b40d2..1d54a6177f14 100644
--- a/arch/arm/mach-omap1/ams-delta-fiq.c
+++ b/arch/arm/mach-omap1/ams-delta-fiq.c
@@ -13,7 +13,8 @@
  * under the terms of the GNU General Public License version 2 as published by
  * the Free Software Foundation.
  */
-#include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -40,14 +41,14 @@ static struct fiq_handler fh = {
 unsigned int fiq_buffer[1024];
 EXPORT_SYMBOL(fiq_buffer);
 
+static struct irq_chip *irq_chip;
+static struct irq_data *irq_data[16];
 static unsigned int irq_counter[16];
 
 static irqreturn_t deferred_fiq(int irq, void *dev_id)
 {
+   struct irq_data *d;
int gpio, irq_num, fiq_count;
-   struct irq_chip *irq_chip;
-
-   irq_chip = irq_get_chip(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK));
 
/*
 * For each handled GPIO interrupt, keep calling its interrupt handler
@@ -55,24 +56,21 @@ static irqreturn_t deferred_fiq(int irq, void *dev_id)
 */
for (gpio = AMS_DELTA_GPIO_PIN_KEYBRD_CLK;
gpio <= AMS_DELTA_GPIO_PIN_HOOK_SWITCH; gpio++) {
-   irq_num = gpio_to_irq(gpio);
+   d = irq_data[gpio];
+   irq_num = d->irq;
fiq_count = fiq_buffer[FIQ_CNT_INT_00 + gpio];
 
if (irq_counter[gpio] < fiq_count &&
gpio != AMS_DELTA_GPIO_PIN_KEYBRD_CLK) {
-   struct irq_data *d = irq_get_irq_data(irq_num);
-
/*
 * handle_simple_irq() that OMAP GPIO edge
 * interrupts default to since commit 80ac93c27441
 * requires interrupt already acked and unmasked.
 */
-   if (irq_chip) {
-   if (irq_chip->irq_ack)
-   irq_chip->irq_ack(d);
-   if (irq_chip->irq_unmask)
-   irq_chip->irq_unmask(d);
-   }
+   if (irq_chip->irq_ack)
+   irq_chip->irq_ack(d);
+   if (irq_chip->irq_unmask)
+   irq_chip->irq_unmask(d);
}
for (; irq_counter[gpio] < fiq_count; irq_counter[gpio]++)
generic_handle_irq(irq_num);
@@ -80,14 +78,36 @@ static irqreturn_t deferred_fiq(int irq, void *dev_id)
return IRQ_HANDLED;
 }
 
-void __init ams_delta_init_fiq(void)
+void __init ams_delta_init_fiq(struct gpio_chip *chip)
 {
+   struct gpio_desc *gpiod;
void *fiqhandler_start;
unsigned int fiqhandler_length;
struct pt_regs FIQ_regs;
unsigned long val, offset;
int i, retval;
 
+   /* Store irq_chip location for IRQ handler use */
+   irq_chip = chip->irq.chip;
+   if (!irq_chip) {
+   pr_err("%s: GPIO chip %s is missing IRQ function\n", __func__,
+  chip->label);
+   return;
+   }
+
+   for (i = 0; i < ARRAY_SIZE(irq_data); i++) {
+   gpiod = gpiochip_request_own_desc(chip, i, NULL);
+   if (IS_ERR(gpiod)) {
+   pr_err("%s: failed to get GPIO pin %d (%ld)\n",
+  __func__, i, PTR_ERR(gpiod));
+   return;
+   }
+   /* Store irq_data location for IRQ handler use */
+   irq_data[i] = irq_get_irq_data(gpiod_to_irq(gpiod));
+
+   gpiochip_free_own_desc(gpiod);
+   }
+
fiqhandler_start = &qwerty_fiqin_start;
fiqhandler_length = &qwerty_fiqin_end - &qwerty_fiqin_start;
pr_info("Installing fiq handler from %p, length 0x%x\n",
diff --git a/arch/arm/mach

[PATCH v2 04/10] Input: ams_delta_serio: Replace power GPIO with regulator

2018-06-21 Thread Janusz Krzysztofik
Modify the driver so it no longer requests and manipulates the
"keybrd_pwr" GPIO pin but a "vcc" regulator supply instead.

For this to work with Amstrad Delta, define a regulator over the
"keybrd_pwr" GPIO pin with the "vcc" supply for ams-delta-serio device
and register it from the board file.  Both assign an absulute GPIO
number to the soon depreciated .gpio member of the regulator config
structure, and also build and register a GPIO lookup table so it is
ready for use by the regulator driver as soon as its upcoming update
is applied.

Signed-off-by: Janusz Krzysztofik 
---
Changelog:
v2: - extended comment above error code conversion, thanks Dmitry for 
  requesting that,
- rebased on v4.18-rc1, no conflicts.

 arch/arm/mach-omap1/board-ams-delta.c | 63 +--
 drivers/input/serio/ams_delta_serio.c | 37 +++-
 2 files changed, 89 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index 2119d2d3ba84..706eb2f9301d 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -509,6 +509,46 @@ static struct platform_device ams_delta_serio_device = {
.id = PLATFORM_DEVID_NONE,
 };
 
+static struct regulator_consumer_supply keybrd_pwr_consumers[] = {
+   /*
+* Initialize supply .dev_name with NULL.  It will be replaced
+* with serio dev_name() as soon as the serio device is registered.
+*/
+   REGULATOR_SUPPLY("vcc", NULL),
+};
+
+static struct regulator_init_data keybrd_pwr_initdata = {
+   .constraints= {
+   .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+   },
+   .num_consumer_supplies  = ARRAY_SIZE(keybrd_pwr_consumers),
+   .consumer_supplies  = keybrd_pwr_consumers,
+};
+
+static struct fixed_voltage_config keybrd_pwr_config = {
+   .supply_name= "keybrd_pwr",
+   .microvolts = 500,
+   .gpio   = AMS_DELTA_GPIO_PIN_KEYBRD_PWR,
+   .enable_high= 1,
+   .init_data  = &keybrd_pwr_initdata,
+};
+
+static struct platform_device keybrd_pwr_device = {
+   .name   = "reg-fixed-voltage",
+   .id = PLATFORM_DEVID_AUTO,
+   .dev= {
+   .platform_data  = &keybrd_pwr_config,
+   },
+};
+
+static struct gpiod_lookup_table keybrd_pwr_gpio_table = {
+   .table = {
+   GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_KEYBRD_PWR, NULL,
+   GPIO_ACTIVE_HIGH),
+   { },
+   },
+};
+
 static struct platform_device *ams_delta_devices[] __initdata = {
&latch1_gpio_device,
&latch2_gpio_device,
@@ -526,6 +566,7 @@ static struct platform_device *late_devices[] __initdata = {
 
 static struct gpiod_lookup_table *ams_delta_gpio_tables[] __initdata = {
&ams_delta_audio_gpio_table,
+   &keybrd_pwr_gpio_table,
 };
 
 static struct gpiod_lookup_table *late_gpio_tables[] __initdata = {
@@ -566,12 +607,30 @@ static void __init ams_delta_init(void)
platform_add_devices(ams_delta_devices, ARRAY_SIZE(ams_delta_devices));
 
/*
-* As soon as devices have been registered, assign their dev_names
-* to respective GPIO lookup tables before they are added.
+* As soon as regulator consumers have been registered, assign their
+* dev_names to consumer supply entries of respective regulators.
+*/
+   keybrd_pwr_consumers[0].dev_name =
+   dev_name(&ams_delta_serio_device.dev);
+
+   /*
+* Once consumer supply entries are populated with dev_names,
+* register regulator devices.  At this stage only the keyboard
+* power regulator has its consumer supply table fully populated.
+*/
+   platform_device_register(&keybrd_pwr_device);
+
+   /*
+* As soon as GPIO consumers have been registered, assign
+* their dev_names to respective GPIO lookup tables.
 */
ams_delta_audio_gpio_table.dev_id =
dev_name(&ams_delta_audio_device.dev);
+   keybrd_pwr_gpio_table.dev_id = dev_name(&keybrd_pwr_device.dev);
 
+   /*
+* Once GPIO lookup tables are populated with dev_names, register them.
+*/
gpiod_add_lookup_tables(ams_delta_gpio_tables,
ARRAY_SIZE(ams_delta_gpio_tables));
 
diff --git a/drivers/input/serio/ams_delta_serio.c 
b/drivers/input/serio/ams_delta_serio.c
index 551a4fa73fe4..854d0d3ada52 100644
--- a/drivers/input/serio/ams_delta_serio.c
+++ b/drivers/input/serio/ams_delta_serio.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -39,6 +40,7 @@ MODULE_LICENSE("GPL");
 
 struct ams_delta_serio 

[PATCH] ASoC: cx20442: Don't ignore regulator_get() errors.

2018-06-24 Thread Janusz Krzysztofik
In its current shape, the driver just ignores errors returned by
regulator_get() at component_probe().  This doesn't hurt on Amstrad
Delta board as long as it registers the codec device at late_initcall,
when the regulator which depends on basic-mmio-gpio device (probed as
late as at dev_initcall) is already available.  Otherwise the driver
may end up trying to control a codec which is not powered up.

Remove that dependency on initialization order by handling the error.
If the regulator is not yet available and -ENODEV is returned, convert
it to -EPROBE_DEFER to get another chance.

Signed-off-by: Janusz Krzysztofik 
---
Created and tested on linux-4.18-rc1

 sound/soc/codecs/cx20442.c | 23 +--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c
index 07dd33b09596..ab174b5114dc 100644
--- a/sound/soc/codecs/cx20442.c
+++ b/sound/soc/codecs/cx20442.c
@@ -362,8 +362,27 @@ static int cx20442_component_probe(struct 
snd_soc_component *component)
return -ENOMEM;
 
cx20442->por = regulator_get(component->dev, "POR");
-   if (IS_ERR(cx20442->por))
-   dev_warn(component->dev, "failed to get the regulator");
+   if (IS_ERR(cx20442->por)) {
+   int err = PTR_ERR(cx20442->por);
+
+   dev_warn(component->dev, "failed to get POR supply (%d)", err);
+   /*
+* When running on a non-dt platform and requested regulator
+* is not available, regulator_get() never returns
+* -EPROBE_DEFER as it is not able to justify if the regulator
+* may still appear later.  On the other hand, the board can
+* still set full constraints flag at late_initcall in order
+* to instruct regulator_get() to return a dummy one if
+* sufficient.  Hence, if we get -ENODEV here, let's convert
+* it to -EPROBE_DEFER and wait for the board to decide or
+* let Deferred Probe infrastructure handle this error.
+*/
+   if (err == -ENODEV)
+   err = -EPROBE_DEFER;
+   kfree(cx20442);
+   return err;
+   }
+
cx20442->tty = NULL;
 
snd_soc_component_set_drvdata(component, cx20442);
-- 
2.16.4



[PATCH v3 0/7] mtd: rawnand: ams-delta: Use GPIO API for data I/O

2018-08-13 Thread Janusz Krzysztofik


Implement the idea suggested by Artem Bityutskiy and Tony Lindgren,
described in commit b027274d2e3a ("mtd: ams-delta: fix
request_mem_region() failure"). Use pure GPIO API as suggested by
Boris Brezillon.


Janusz Krzysztofik (7):
  mtd: rawnand: ams-delta: show parent device in sysfs
  mtd: rawnand: ams-delta: Use private structure
  ARM: OMAP1: ams-delta: Provide GPIO lookup table for NAND data port
  mtd: rawnand: ams-delta: request data port GPIO resource
  mtd: rawnand: ams-delta: Set port direction when needed
  mtd: rawnand: ams-delta: Simplify pointer resolution on read/write
  mtd: rawnand: ams-delta: use GPIO API for data I/O


Changelog:
v3:
[PATCH v3 1/7] mtd: rawnand: ams-delta: show parent device in sysfs
- renamed and an explanation added based on other similar patches on
 Marek Vasut request, thanks.
[PATCH v3 2/7] mtd: rawnand: ams-delta: Use private structure
- no changes.
[PATCH v3 3/7] ARM: OMAP1: ams-delta: Provide GPIO lookup table for NAND
 data port
- no changes.
[PATCH v3 4/7] mtd: rawnand: ams-delta: request data port GPIO resource
- no changes.
[PATCH v3 5/7] mtd: rawnand: ams-delta: Set port direction when needed
- modified to set port direction only when needed instead of on each
 transfer as suggested by Boris, thanks, though I kept separate 
 *_next_byte() functions to maximize performance as much as possible,
- moved back in front of "mtd: rawnand: ams-delta: use GPIO API for data
 I/O" with a comment added referring to the planned switch to GPIO API.
[PATCH v3 6/7] mtd: rawnand: ams-delta: Simplify pointer resolution
- moved back in front of "mtd: rawnand: ams-delta: use GPIO API for data 
 I/O" on Boris request, thanks.
[RFC PATCH v3 7/7] mtd: rawnand: ams-delta: use GPIO API for data I/O
- rebased back on top of the two mentioned above,
- not intended to apply it yet due to performance issues on Amstrad Delta.
Removed from the series:
[RFC PATCH v2 09/12] gpiolib: Identify GPIO descriptor arrays with direct
 mapping
[RFC PATCH v2 10/12] gpiolib: Introduce bitmap get/set array API extension
[RFC PATCH v2 11/12] mtd: rawnand: ams-delta: Use GPIO API bitmap extension
[RFC PATCH v2 12/12] gpiolib: Add fast processing path to bitmap API functions
- intended to be still iterated in a follow up series until performance
 issues are resolved.
[RFC PATCH v2 06/12] ARM: OMAP1: ams-delta: drop obsolete NAND resources
- postponed until acceptable performance on Amstrad Delta is achieved.

v2:
[RFC PATCH v2 00/12] mtd: rawnand: ams-delta: Use GPIO API for data I/O
- renamed from former [RFC PATCH 0/8] mtd: rawnand: ams-delta: Use
  gpio-omap accessors for data I/O
[RFC PATCH v2 01/12] mtd: rawnand: ams-delta: Assign mtd->dev.parent,
not mtd->owner
- split out from former [RFC PATCH 1/8] on Boris request, thanks.
[RFC PATCH v2 02/12] mtd: rawnand: ams-delta: Use private structure
- remaining part of the former [RFC PATCH 1/8].
[RFC PATCH v2 03/12] ARM: OMAP1: ams-delta: Provide GPIO lookup table
for NAND data port
- split out from former [RFC PATCH 5/8] on Boris requesst, thanks,
[RFC PATCH v2 04/12] mtd: rawnand: ams-delta: request data port GPIO resource
- remaining part of the former [RFC PATCH 5/8],
[RFC PATCH v2 05/12] mtd: rawnand: ams-delta: use GPIO API for data read/write
- reworked from former [RFC PATCH 8/8] on Boris requesst to use pure
  GPIO API, thanks,
- moved up in front of former [RFC PATCH 3/8] on Boris request, thanks.
[RFC PATCH v2 06/12] ARM: OMAP1: ams-delta: drop obsolete NAND resources
- split out from former [RFC PATCH 8/8].
[RFC PATCH v2 07/12] mtd: rawnand: ams-delta: Set port direction once per
transfer
- reworked from former [RFC PATCH 3/8] on top of [RFC PATCH v2 05/12].
[RFC PATCH v2 08/12] mtd: rawnand: ams-delta: Simplify pointer resolution
on read/write
- reworked from former [RFC PATCH 4/8] on top of [RFC PATCH v2 08/12],
- renamed from 'Optimize' to 'Simplify' on Boris request, thanks.
[RFC PATCH v2 09/12] gpiolib: Identify GPIO descriptor arrays with direct
mapping
- new patch.
[RFC PATCH v2 10/12] gpiolib: Introduce bitmap get/set array API extension
- new patch.
[RFC PATCH v2 11/12] mtd: rawnand: ams-delta: Use GPIO API bitmap extension
- new patch.
[RFC PATCH v2 12/12] gpiolib: Add fast processing path to bitmap API functions
- new patch.
Removed from the series:
[RFC PATCH 2/8] mtd: rawnand: ams-delta: Write protect device during probe
- postponed on Boris request, thanks.
[RFC PATCH 6/8] gpio: omap: Add get/set_multiple() callbacks
- already applied by Linux in linux-gpio tree, thanks.
[RFC PATCH 7/8] mtd: rawnand: ams-delta: Check sanity of data GPIO resource
- most controversial one, no longer needed after switching to GPIO API.


diffstat
 arch/arm/mach-omap1/board-ams-delta.c |   11 -
 drivers/mtd/nand/raw/ams-delta.c  |  351 

[PATCH v3 5/7] mtd: rawnand: ams-delta: Set port direction when needed

2018-08-13 Thread Janusz Krzysztofik
In its current shape, the driver sets data port direction before each
byte read/write operation, even during multi-byte transfers.  Improve
performance of the driver by setting the port direction only when
needed.

This optimisation will become particularly important as soon as
planned conversion of the driver to GPIO API for data I/O will be
implemented.

Signed-off-by: Janusz Krzysztofik 
---
 drivers/mtd/nand/raw/ams-delta.c | 59 
 1 file changed, 47 insertions(+), 12 deletions(-)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index 09d6901fc94d..5f9180fe4f8b 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -45,6 +45,7 @@ struct ams_delta_nand {
struct gpio_desc*gpiod_ale;
struct gpio_desc*gpiod_cle;
void __iomem*io_base;
+   booldata_in;
 };
 
 /*
@@ -72,50 +73,83 @@ static const struct mtd_partition partition_info[] = {
  .size =  3 * SZ_256K },
 };
 
-static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
+static void ams_delta_write_next_byte(struct mtd_info *mtd, u_char byte)
 {
struct nand_chip *this = mtd_to_nand(mtd);
struct ams_delta_nand *priv = nand_get_controller_data(this);
-   void __iomem *io_base = priv->io_base;
 
-   writew(0, io_base + OMAP_MPUIO_IO_CNTL);
writew(byte, this->IO_ADDR_W);
+
gpiod_set_value(priv->gpiod_nwe, 0);
ndelay(40);
gpiod_set_value(priv->gpiod_nwe, 1);
 }
 
-static u_char ams_delta_read_byte(struct mtd_info *mtd)
+static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
 {
-   u_char res;
struct nand_chip *this = mtd_to_nand(mtd);
struct ams_delta_nand *priv = nand_get_controller_data(this);
void __iomem *io_base = priv->io_base;
 
+   if (priv->data_in) {
+   writew(0, io_base + OMAP_MPUIO_IO_CNTL);
+   priv->data_in = false;
+   }
+
+   ams_delta_write_next_byte(mtd, byte);
+}
+
+static u_char ams_delta_read_next_byte(struct mtd_info *mtd)
+{
+   struct nand_chip *this = mtd_to_nand(mtd);
+   struct ams_delta_nand *priv = nand_get_controller_data(this);
+   u_char res;
+
gpiod_set_value(priv->gpiod_nre, 0);
ndelay(40);
-   writew(~0, io_base + OMAP_MPUIO_IO_CNTL);
+
res = readw(this->IO_ADDR_R);
+
gpiod_set_value(priv->gpiod_nre, 1);
 
return res;
 }
 
+static u_char ams_delta_read_byte(struct mtd_info *mtd)
+{
+   struct nand_chip *this = mtd_to_nand(mtd);
+   struct ams_delta_nand *priv = nand_get_controller_data(this);
+   void __iomem *io_base = priv->io_base;
+
+   if (!priv->data_in) {
+   writew(~0, io_base + OMAP_MPUIO_IO_CNTL);
+   priv->data_in = true;
+   }
+
+   return ams_delta_read_next_byte(mtd);
+}
+
 static void ams_delta_write_buf(struct mtd_info *mtd, const u_char *buf,
int len)
 {
-   int i;
+   int i = 0;
+
+   if (len > 0)
+   ams_delta_write_byte(mtd, buf[i++]);
 
-   for (i=0; i 0)
+   buf[i++] = ams_delta_read_byte(mtd);
 
-   for (i=0; idev, "data GPIO request failed: %d\n", err);
goto out_mtd;
}
+   priv->data_in = true;
 
/* Scan to find existence of the device */
err = nand_scan(mtd, 1);
-- 
2.16.4



[PATCH v3 1/7] mtd: rawnand: ams-delta: show parent device in sysfs

2018-08-13 Thread Janusz Krzysztofik
Fix a bug where parent device symlinks aren't shown in sysfs.

While at it, make use of the default owner set by mtdcore.

Signed-off-by: Janusz Krzysztofik 
Reviewed-by: Boris Brezillon 
---
 drivers/mtd/nand/raw/ams-delta.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index 2a8872ebd14a..af313c620264 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -162,7 +162,7 @@ static int ams_delta_init(struct platform_device *pdev)
}
 
ams_delta_mtd = nand_to_mtd(this);
-   ams_delta_mtd->owner = THIS_MODULE;
+   ams_delta_mtd->dev.parent = &pdev->dev;
 
/*
 * Don't try to request the memory region from here,
-- 
2.16.4



[PATCH v3 6/7] mtd: rawnand: ams-delta: Simplify pointer resolution on read/write

2018-08-13 Thread Janusz Krzysztofik
Simplify data read/write sub-functions by making them accept private
structure pointer instead of resolving it again from mtd_info.

Signed-off-by: Janusz Krzysztofik 
Reviewed-by: Boris Brezillon 
---
 drivers/mtd/nand/raw/ams-delta.c | 30 +++---
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index 5f9180fe4f8b..59fc417e8fa9 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -73,10 +73,9 @@ static const struct mtd_partition partition_info[] = {
  .size =  3 * SZ_256K },
 };
 
-static void ams_delta_write_next_byte(struct mtd_info *mtd, u_char byte)
+static void ams_delta_write_next_byte(struct ams_delta_nand *priv, u_char byte)
 {
-   struct nand_chip *this = mtd_to_nand(mtd);
-   struct ams_delta_nand *priv = nand_get_controller_data(this);
+   struct nand_chip *this = &priv->nand_chip;
 
writew(byte, this->IO_ADDR_W);
 
@@ -85,10 +84,8 @@ static void ams_delta_write_next_byte(struct mtd_info *mtd, 
u_char byte)
gpiod_set_value(priv->gpiod_nwe, 1);
 }
 
-static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
+static void ams_delta_write_byte(struct ams_delta_nand *priv, u_char byte)
 {
-   struct nand_chip *this = mtd_to_nand(mtd);
-   struct ams_delta_nand *priv = nand_get_controller_data(this);
void __iomem *io_base = priv->io_base;
 
if (priv->data_in) {
@@ -96,13 +93,12 @@ static void ams_delta_write_byte(struct mtd_info *mtd, 
u_char byte)
priv->data_in = false;
}
 
-   ams_delta_write_next_byte(mtd, byte);
+   ams_delta_write_next_byte(priv, byte);
 }
 
-static u_char ams_delta_read_next_byte(struct mtd_info *mtd)
+static u_char ams_delta_read_next_byte(struct ams_delta_nand *priv)
 {
-   struct nand_chip *this = mtd_to_nand(mtd);
-   struct ams_delta_nand *priv = nand_get_controller_data(this);
+   struct nand_chip *this = &priv->nand_chip;
u_char res;
 
gpiod_set_value(priv->gpiod_nre, 0);
@@ -126,30 +122,34 @@ static u_char ams_delta_read_byte(struct mtd_info *mtd)
priv->data_in = true;
}
 
-   return ams_delta_read_next_byte(mtd);
+   return ams_delta_read_next_byte(priv);
 }
 
 static void ams_delta_write_buf(struct mtd_info *mtd, const u_char *buf,
int len)
 {
+   struct nand_chip *this = mtd_to_nand(mtd);
+   struct ams_delta_nand *priv = nand_get_controller_data(this);
int i = 0;
 
if (len > 0)
-   ams_delta_write_byte(mtd, buf[i++]);
+   ams_delta_write_byte(priv, buf[i++]);
 
while (i < len)
-   ams_delta_write_next_byte(mtd, buf[i++]);
+   ams_delta_write_next_byte(priv, buf[i++]);
 }
 
 static void ams_delta_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
+   struct nand_chip *this = mtd_to_nand(mtd);
+   struct ams_delta_nand *priv = nand_get_controller_data(this);
int i = 0;
 
if (len > 0)
buf[i++] = ams_delta_read_byte(mtd);
 
while (i < len)
-   buf[i++] = ams_delta_read_next_byte(mtd);
+   buf[i++] = ams_delta_read_next_byte(priv);
 }
 
 /*
@@ -173,7 +173,7 @@ static void ams_delta_hwcontrol(struct mtd_info *mtd, int 
cmd,
}
 
if (cmd != NAND_CMD_NONE)
-   ams_delta_write_byte(mtd, cmd);
+   ams_delta_write_byte(priv, cmd);
 }
 
 static int ams_delta_nand_ready(struct mtd_info *mtd)
-- 
2.16.4



[PATCH v3 3/7] ARM: OMAP1: ams-delta: Provide GPIO lookup table for NAND data port

2018-08-13 Thread Janusz Krzysztofik
Data port used by Amstrad Delta NAND driver is actually an OMAP MPUIO
device, already under control of gpio-omap driver.  The NAND driver
gets access to the port by ioremapping it and performs read/write
operations.  That is done without any proteciton from other users
legally manipulating the port pins over GPIO API.

The plan is to convert the driver to access the port over GPIO consumer
API.  Before that is implemented, the driver can already obtain
exclusive access to the port by requesting an array of its GPIO
descriptors.

Add respective entries to the NAND GPIO lookup table.

Signed-off-by: Janusz Krzysztofik 
Reviewed-by: Boris Brezillon 
Reviewed-by: Linus Walleij 
---
 arch/arm/mach-omap1/board-ams-delta.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index eedacdfe9725..16f7bbe47607 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -337,7 +337,8 @@ static struct platform_device ams_delta_nand_device = {
.resource   = ams_delta_nand_resources,
 };
 
-#define OMAP_GPIO_LABEL"gpio-0-15"
+#define OMAP_GPIO_LABEL"gpio-0-15"
+#define OMAP_MPUIO_LABEL   "mpuio"
 
 static struct gpiod_lookup_table ams_delta_nand_gpio_table = {
.table = {
@@ -349,6 +350,14 @@ static struct gpiod_lookup_table ams_delta_nand_gpio_table 
= {
GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NWE, "nwe", 0),
GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_ALE, "ale", 0),
GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_CLE, "cle", 0),
+   GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 0, "data", 0, 0),
+   GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 1, "data", 1, 0),
+   GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 2, "data", 2, 0),
+   GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 3, "data", 3, 0),
+   GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 4, "data", 4, 0),
+   GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 5, "data", 5, 0),
+   GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 6, "data", 6, 0),
+   GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 7, "data", 7, 0),
{ },
},
 };
-- 
2.16.4



[PATCH v3 4/7] mtd: rawnand: ams-delta: request data port GPIO resource

2018-08-13 Thread Janusz Krzysztofik
Data port used by the driver is actually an OMAP MPUIO device, already
under control of gpio-omap driver.  For that reason we used to not
request the memory region of the port as that would fail because the
region is already busy.  Despite that, we are still accessing the port
by just ioremapping it and performing read/write operations.  Moreover,
we are doing that without any proteciton from other users legally
manipulating the port pins over GPIO API.

The plan is to convert the driver to access the port over functions
exposed by the gpio-omap driver.  Before that happens, already prevent
from other users accessing the port pins by requesting an array of its
GPIO descriptors.

Signed-off-by: Janusz Krzysztofik 
Reviewed-by: Boris Brezillon 
Reviewed-by: Linus Walleij 
---
 drivers/mtd/nand/raw/ams-delta.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index 48233d638d2a..09d6901fc94d 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -161,6 +161,7 @@ static int ams_delta_init(struct platform_device *pdev)
struct mtd_info *mtd;
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
void __iomem *io_base;
+   struct gpio_descs *data_gpiods;
int err = 0;
 
if (!res)
@@ -261,6 +262,13 @@ static int ams_delta_init(struct platform_device *pdev)
dev_err(&pdev->dev, "CLE GPIO request failed (%d)\n", err);
goto out_mtd;
}
+   /* Request array of data pins, initialize them as input */
+   data_gpiods = devm_gpiod_get_array(&pdev->dev, "data", GPIOD_IN);
+   if (IS_ERR(data_gpiods)) {
+   err = PTR_ERR(data_gpiods);
+   dev_err(&pdev->dev, "data GPIO request failed: %d\n", err);
+   goto out_mtd;
+   }
 
/* Scan to find existence of the device */
err = nand_scan(mtd, 1);
-- 
2.16.4



[PATCH v3 7/7] mtd: rawnand: ams-delta: use GPIO API for data I/O

2018-08-13 Thread Janusz Krzysztofik
Don't readw()/writew() data directly from/to GPIO port which is under
control of gpio-omap driver, use GPIO API instead.

Degrade of performance on Amstrad Delta is significant, can be
recognized as a regression, that's why I'm still submitting this patch
as RFC.

The driver should work with any 8+-bit bidirectional GPIO port, not
only OMAP.

Signed-off-by: Janusz Krzysztofik 
Reviewed-by: Linus Walleij 
---
Exceprts fro timestamped boot logs showing performance degrade.
Before the change:
[5.469426] Creating 6 MTD partitions on "ams-delta-nand":
[5.480909] 0x-0x0038 : "Kernel"
[5.502659] 0x0038-0x003c : "u-boot"
[5.523055] 0x003c-0x0040 : "u-boot params"
[5.543612] 0x0040-0x0044 : "Amstrad LDR"
[5.564607] 0x0044-0x01f4 : "File system"
[5.601760] 0x01f4-0x0200 : "PBL reserved"
[5.624369] usbcore: registered new interface driver dm9601
[5.636233] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[5.649191] ohci-omap: OHCI OMAP driver
[5.660713] ohci ohci: OMAP OHCI
[5.671299] ohci ohci: new USB bus registered, assigned bus number 1
[5.686862] ohci ohci: irq 54, io mem 0xfffba000
[5.785897] hub 1-0:1.0: USB hub found
[5.797856] hub 1-0:1.0: 3 ports detected
[5.817576] usbcore: registered new interface driver usb-storage
[5.832551] ams-delta-serio ams-delta-serio: incomplete constraints, dummy 
supplies not allowed
[5.858588] ams-delta-serio ams-delta-serio: regulator request failed (-19)
[5.879312] input: omap-keypad as /devices/platform/omap-keypad/input/input0
[5.902490] omap_rtc omap_rtc: already running
[5.922929] omap_rtc omap_rtc: registered as rtc0
[5.945570] softdog: initialized. soft_noboot=0 soft_margin=60 sec 
soft_panic=0 (nowayout=0)
[5.976712] usbcore: registered new interface driver btusb
[6.007348] cx20442-codec cx20442-codec: incomplete constraints, dummy 
supplies not allowed
[6.040575] cx20442-codec cx20442-codec: failed to get POR supply (-19)
[6.060916] cx20442-codec cx20442-codec: ASoC: failed to probe component -517
[6.083486] ams-delta-audio ams-delta-audio: ASoC: failed to instantiate 
card -517
[6.121850] ams-delta-audio ams-delta-audio: snd_soc_register_card failed 
(-517)
[6.163047] NET: Registered protocol family 17
[6.182770] Bluetooth: BNEP (Ethernet Emulation) ver 1.3
[6.203517] Bluetooth: BNEP socket layer initialized
[6.283017] serial8250 serial8250.1: Linked as a consumer to regulator.1
[6.306113] usb 1-1: new full-speed USB device number 2 using ohci
[6.328825] clock: disabling unused clocks to save power
[6.350426] Skipping reset check for DSP domain clock "dsptim_ck"
[6.372272] Skipping reset check for DSP domain clock "dspxor_ck"
[6.393712] Skipping reset check for DSP domain clock "dspper_ck"
[6.428311] ams-delta-serio ams-delta-serio: Linked as a consumer to 
regulator.2
[6.467801] serio serio0: AMS DELTA keyboard adapter
[6.492511] cx20442-codec cx20442-codec: Linked as a consumer to regulator.1
[6.527382] ams-delta-audio ams-delta-audio: cx20442-voice <-> omap-mcbsp.1 
mapping ok
[6.577387] input: AMS_DELTA hook_switch as 
/devices/platform/ams-delta-audio/sound/card0/input1
[6.627497] input: AT Raw Set 2 keyboard as 
/devices/platform/ams-delta-serio/serio0/input/input2
[6.673663] omap_rtc omap_rtc: setting system clock to 2013-02-09 07:22:13 
UTC (1360394533)
[6.715895] modem_nreset: incomplete constraints, leaving on
[6.738677] ALSA device list:
[6.758398]   #0: AMS_DELTA
[7.036234] dm9601 1-1:1.0 eth0: register 'dm9601' at usb-ohci-1, Davicom 
DM96xx USB 10/100 Ethernet, 00:60:6e:00:00:11
[  133.860599] random: crng init done
[  138.275853] VFS: Mounted root (jffs2 filesystem) on device 31:4.

After the change:
[6.261107] Creating 6 MTD partitions on "ams-delta-nand":
[6.272046] 0x-0x0038 : "Kernel"
[6.294436] 0x0038-0x003c : "u-boot"
[6.314454] 0x003c-0x0040 : "u-boot params"
[6.335353] 0x0040-0x0044 : "Amstrad LDR"
[6.356669] 0x0044-0x01f4 : "File system"
[6.393713] 0x01f4-0x0200 : "PBL reserved"
[6.416771] usbcore: registered new interface driver dm9601
[6.428631] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[6.441533] ohci-omap: OHCI OMAP driver
[6.452758] ohci ohci: OMAP OHCI
[6.463300] ohci ohci: new USB bus registered, assigned bus number 1
[6.478817] ohci ohci: irq 54, io mem 0xfffba000
[6.580520] hub 1-0:1.0: USB hub found
[6.592424] hub 1-0:1.0: 3 ports detected
[6.61236

[PATCH v3 2/7] mtd: rawnand: ams-delta: Use private structure

2018-08-13 Thread Janusz Krzysztofik
Introduce a driver private structure and allocate it on device probe.
Use it for storing nand_chip structure, GPIO descriptors prevoiusly
stored in static variables as well as io_base pointer previously passed
as nand controller data or platform driver data.  Subsequent patches
may populate the structure with more members as needed.

Signed-off-by: Janusz Krzysztofik 
Reviewed-by: Boris Brezillon 
---
 drivers/mtd/nand/raw/ams-delta.c | 126 +--
 1 file changed, 69 insertions(+), 57 deletions(-)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index af313c620264..48233d638d2a 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -34,14 +34,18 @@
 /*
  * MTD structure for E3 (Delta)
  */
-static struct mtd_info *ams_delta_mtd = NULL;
-static struct gpio_desc *gpiod_rdy;
-static struct gpio_desc *gpiod_nce;
-static struct gpio_desc *gpiod_nre;
-static struct gpio_desc *gpiod_nwp;
-static struct gpio_desc *gpiod_nwe;
-static struct gpio_desc *gpiod_ale;
-static struct gpio_desc *gpiod_cle;
+
+struct ams_delta_nand {
+   struct nand_chipnand_chip;
+   struct gpio_desc*gpiod_rdy;
+   struct gpio_desc*gpiod_nce;
+   struct gpio_desc*gpiod_nre;
+   struct gpio_desc*gpiod_nwp;
+   struct gpio_desc*gpiod_nwe;
+   struct gpio_desc*gpiod_ale;
+   struct gpio_desc*gpiod_cle;
+   void __iomem*io_base;
+};
 
 /*
  * Define partitions for flash devices
@@ -71,26 +75,28 @@ static const struct mtd_partition partition_info[] = {
 static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
 {
struct nand_chip *this = mtd_to_nand(mtd);
-   void __iomem *io_base = (void __iomem *)nand_get_controller_data(this);
+   struct ams_delta_nand *priv = nand_get_controller_data(this);
+   void __iomem *io_base = priv->io_base;
 
writew(0, io_base + OMAP_MPUIO_IO_CNTL);
writew(byte, this->IO_ADDR_W);
-   gpiod_set_value(gpiod_nwe, 0);
+   gpiod_set_value(priv->gpiod_nwe, 0);
ndelay(40);
-   gpiod_set_value(gpiod_nwe, 1);
+   gpiod_set_value(priv->gpiod_nwe, 1);
 }
 
 static u_char ams_delta_read_byte(struct mtd_info *mtd)
 {
u_char res;
struct nand_chip *this = mtd_to_nand(mtd);
-   void __iomem *io_base = (void __iomem *)nand_get_controller_data(this);
+   struct ams_delta_nand *priv = nand_get_controller_data(this);
+   void __iomem *io_base = priv->io_base;
 
-   gpiod_set_value(gpiod_nre, 0);
+   gpiod_set_value(priv->gpiod_nre, 0);
ndelay(40);
writew(~0, io_base + OMAP_MPUIO_IO_CNTL);
res = readw(this->IO_ADDR_R);
-   gpiod_set_value(gpiod_nre, 1);
+   gpiod_set_value(priv->gpiod_nre, 1);
 
return res;
 }
@@ -123,11 +129,13 @@ static void ams_delta_read_buf(struct mtd_info *mtd, 
u_char *buf, int len)
 static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
 {
+   struct nand_chip *this = mtd_to_nand(mtd);
+   struct ams_delta_nand *priv = nand_get_controller_data(this);
 
if (ctrl & NAND_CTRL_CHANGE) {
-   gpiod_set_value(gpiod_nce, !(ctrl & NAND_NCE));
-   gpiod_set_value(gpiod_cle, !!(ctrl & NAND_CLE));
-   gpiod_set_value(gpiod_ale, !!(ctrl & NAND_ALE));
+   gpiod_set_value(priv->gpiod_nce, !(ctrl & NAND_NCE));
+   gpiod_set_value(priv->gpiod_cle, !!(ctrl & NAND_CLE));
+   gpiod_set_value(priv->gpiod_ale, !!(ctrl & NAND_ALE));
}
 
if (cmd != NAND_CMD_NONE)
@@ -136,7 +144,10 @@ static void ams_delta_hwcontrol(struct mtd_info *mtd, int 
cmd,
 
 static int ams_delta_nand_ready(struct mtd_info *mtd)
 {
-   return gpiod_get_value(gpiod_rdy);
+   struct nand_chip *this = mtd_to_nand(mtd);
+   struct ams_delta_nand *priv = nand_get_controller_data(this);
+
+   return gpiod_get_value(priv->gpiod_rdy);
 }
 
 
@@ -145,7 +156,9 @@ static int ams_delta_nand_ready(struct mtd_info *mtd)
  */
 static int ams_delta_init(struct platform_device *pdev)
 {
+   struct ams_delta_nand *priv;
struct nand_chip *this;
+   struct mtd_info *mtd;
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
void __iomem *io_base;
int err = 0;
@@ -154,15 +167,16 @@ static int ams_delta_init(struct platform_device *pdev)
return -ENXIO;
 
/* Allocate memory for MTD device structure and private data */
-   this = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
-   if (!this) {
+   priv = devm_kzalloc(&pdev->dev, sizeof(struct ams_delta_nand),
+   GFP_KERNEL);
+   if (!priv) {
pr_warn("Unable to allocate E3 NAND MTD de

[RFC PATCH 0/8] mtd: rawnand: ams-delta: Use gpio-omap accessors for data I/O

2018-07-18 Thread Janusz Krzysztofik


Implement the idea suggested by Artem Bityutskiy and Tony Lindgren
described in commit b027274d2e3a ("mtd: ams-delta: fix
request_mem_region() failure").

 arch/arm/mach-omap1/board-ams-delta.c |   22 -
 drivers/gpio/gpio-omap.c  |   88 ++
 drivers/mtd/nand/raw/ams-delta.c  |  436 +-
 3 files changed, 376 insertions(+), 170 deletions(-)



[RFC PATCH 1/8] mtd: rawnand: ams-delta: Use private structure

2018-07-18 Thread Janusz Krzysztofik
Introduce a driver private structure and allocate it on device probe.
Use it for storing nand_chip structure, GPIO descriptors prevoiusly
stored in static variables as well as io_base pointer previously passed
as nand controller data or platform driver data.  Subsequent patches
may populate the structure with more members as needed.

While at it, fix missing mtd->dev.parent and drop useless mtd->owner.

Signed-off-by: Janusz Krzysztofik 
---
 drivers/mtd/nand/raw/ams-delta.c | 126 +--
 1 file changed, 69 insertions(+), 57 deletions(-)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index 2a8872ebd14a..48233d638d2a 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -34,14 +34,18 @@
 /*
  * MTD structure for E3 (Delta)
  */
-static struct mtd_info *ams_delta_mtd = NULL;
-static struct gpio_desc *gpiod_rdy;
-static struct gpio_desc *gpiod_nce;
-static struct gpio_desc *gpiod_nre;
-static struct gpio_desc *gpiod_nwp;
-static struct gpio_desc *gpiod_nwe;
-static struct gpio_desc *gpiod_ale;
-static struct gpio_desc *gpiod_cle;
+
+struct ams_delta_nand {
+   struct nand_chipnand_chip;
+   struct gpio_desc*gpiod_rdy;
+   struct gpio_desc*gpiod_nce;
+   struct gpio_desc*gpiod_nre;
+   struct gpio_desc*gpiod_nwp;
+   struct gpio_desc*gpiod_nwe;
+   struct gpio_desc*gpiod_ale;
+   struct gpio_desc*gpiod_cle;
+   void __iomem*io_base;
+};
 
 /*
  * Define partitions for flash devices
@@ -71,26 +75,28 @@ static const struct mtd_partition partition_info[] = {
 static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
 {
struct nand_chip *this = mtd_to_nand(mtd);
-   void __iomem *io_base = (void __iomem *)nand_get_controller_data(this);
+   struct ams_delta_nand *priv = nand_get_controller_data(this);
+   void __iomem *io_base = priv->io_base;
 
writew(0, io_base + OMAP_MPUIO_IO_CNTL);
writew(byte, this->IO_ADDR_W);
-   gpiod_set_value(gpiod_nwe, 0);
+   gpiod_set_value(priv->gpiod_nwe, 0);
ndelay(40);
-   gpiod_set_value(gpiod_nwe, 1);
+   gpiod_set_value(priv->gpiod_nwe, 1);
 }
 
 static u_char ams_delta_read_byte(struct mtd_info *mtd)
 {
u_char res;
struct nand_chip *this = mtd_to_nand(mtd);
-   void __iomem *io_base = (void __iomem *)nand_get_controller_data(this);
+   struct ams_delta_nand *priv = nand_get_controller_data(this);
+   void __iomem *io_base = priv->io_base;
 
-   gpiod_set_value(gpiod_nre, 0);
+   gpiod_set_value(priv->gpiod_nre, 0);
ndelay(40);
writew(~0, io_base + OMAP_MPUIO_IO_CNTL);
res = readw(this->IO_ADDR_R);
-   gpiod_set_value(gpiod_nre, 1);
+   gpiod_set_value(priv->gpiod_nre, 1);
 
return res;
 }
@@ -123,11 +129,13 @@ static void ams_delta_read_buf(struct mtd_info *mtd, 
u_char *buf, int len)
 static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
 {
+   struct nand_chip *this = mtd_to_nand(mtd);
+   struct ams_delta_nand *priv = nand_get_controller_data(this);
 
if (ctrl & NAND_CTRL_CHANGE) {
-   gpiod_set_value(gpiod_nce, !(ctrl & NAND_NCE));
-   gpiod_set_value(gpiod_cle, !!(ctrl & NAND_CLE));
-   gpiod_set_value(gpiod_ale, !!(ctrl & NAND_ALE));
+   gpiod_set_value(priv->gpiod_nce, !(ctrl & NAND_NCE));
+   gpiod_set_value(priv->gpiod_cle, !!(ctrl & NAND_CLE));
+   gpiod_set_value(priv->gpiod_ale, !!(ctrl & NAND_ALE));
}
 
if (cmd != NAND_CMD_NONE)
@@ -136,7 +144,10 @@ static void ams_delta_hwcontrol(struct mtd_info *mtd, int 
cmd,
 
 static int ams_delta_nand_ready(struct mtd_info *mtd)
 {
-   return gpiod_get_value(gpiod_rdy);
+   struct nand_chip *this = mtd_to_nand(mtd);
+   struct ams_delta_nand *priv = nand_get_controller_data(this);
+
+   return gpiod_get_value(priv->gpiod_rdy);
 }
 
 
@@ -145,7 +156,9 @@ static int ams_delta_nand_ready(struct mtd_info *mtd)
  */
 static int ams_delta_init(struct platform_device *pdev)
 {
+   struct ams_delta_nand *priv;
struct nand_chip *this;
+   struct mtd_info *mtd;
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
void __iomem *io_base;
int err = 0;
@@ -154,15 +167,16 @@ static int ams_delta_init(struct platform_device *pdev)
return -ENXIO;
 
/* Allocate memory for MTD device structure and private data */
-   this = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
-   if (!this) {
+   priv = devm_kzalloc(&pdev->dev, sizeof(struct ams_delta_nand),
+   GFP_KERNEL);
+   if (!priv) {
pr_warn("U

[RFC PATCH 5/8] mtd: rawnand: ams-delta: Request data port GPIO resource

2018-07-18 Thread Janusz Krzysztofik
Data port used by the driver is actually an OMAP MPUIO device, already
under control of gpio-omap driver.  For that reason we used to not
request the memory region of the port as that would fail because the
region is already busy.  Despite that, we are still accessing the port
by just ioremapping it and performing read/write operations.  Moreover,
we are doing that without any proteciton from other users legally
manipulating the port pins over GPIO API.

The plan is to convert the driver to access the port over functions
exposed by the gpio-omap driver.  Before that happens, we can already
obtain exclusive access to the port by requesting an array of its GPIO
descriptors.  For that to work on Amstrad Delta, respective GPIO lookup
table entries are added to the board init file.

Signed-off-by: Janusz Krzysztofik 
---
 arch/arm/mach-omap1/board-ams-delta.c | 11 ++-
 drivers/mtd/nand/raw/ams-delta.c  |  8 
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index eedacdfe9725..16f7bbe47607 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -337,7 +337,8 @@ static struct platform_device ams_delta_nand_device = {
.resource   = ams_delta_nand_resources,
 };
 
-#define OMAP_GPIO_LABEL"gpio-0-15"
+#define OMAP_GPIO_LABEL"gpio-0-15"
+#define OMAP_MPUIO_LABEL   "mpuio"
 
 static struct gpiod_lookup_table ams_delta_nand_gpio_table = {
.table = {
@@ -349,6 +350,14 @@ static struct gpiod_lookup_table ams_delta_nand_gpio_table 
= {
GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NWE, "nwe", 0),
GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_ALE, "ale", 0),
GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_CLE, "cle", 0),
+   GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 0, "data", 0, 0),
+   GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 1, "data", 1, 0),
+   GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 2, "data", 2, 0),
+   GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 3, "data", 3, 0),
+   GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 4, "data", 4, 0),
+   GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 5, "data", 5, 0),
+   GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 6, "data", 6, 0),
+   GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 7, "data", 7, 0),
{ },
},
 };
diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index d7e4c9dbef67..ad62c0245458 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -189,6 +189,7 @@ static int ams_delta_init(struct platform_device *pdev)
struct mtd_info *mtd;
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
void __iomem *io_base;
+   struct gpio_descs *data_gpiods;
int err = 0;
 
if (!res)
@@ -289,6 +290,13 @@ static int ams_delta_init(struct platform_device *pdev)
dev_err(&pdev->dev, "CLE GPIO request failed (%d)\n", err);
goto out_mtd;
}
+   /* Request array of data pins, initialize them as output and set low */
+   data_gpiods = devm_gpiod_get_array(&pdev->dev, "data", GPIOD_OUT_LOW);
+   if (IS_ERR(data_gpiods)) {
+   err = PTR_ERR(data_gpiods);
+   dev_err(&pdev->dev, "data GPIO request failed: %d\n", err);
+   goto out_mtd;
+   }
 
/* Scan to find existence of the device */
err = nand_scan(mtd, 1);
-- 
2.16.4



[RFC PATCH 7/8] mtd: rawnand: ams-delta: Check sanity of data GPIO resource

2018-07-18 Thread Janusz Krzysztofik
The plan is to replace data port readw()/writew() operations with GPIO
callbacks provided by gpio-omap driver.  For acceptable performance the
GPIO chip must support get/set_multiple() GPIO callbacks.

In order to avoid data corruption, we require the array of data GPIO
descriptors obtained with gpiod_get_array() to meet some strict
requirements:
- all pins must belong to the same single GPIO chip,
- array index of each pin descriptor must match its hardware number,
- pin polarity must not be inverted,
- pin hardware configuration must not be open drain nor open source.

Let's implement the above described sanity checks before replacing the
readw()/writew() operations witn GPIO callbacks.  If a check fails,
return -EINVAL to indicate the board provided GPIO setup is invalid.

Signed-off-by: Janusz Krzysztofik 
---
 drivers/mtd/nand/raw/ams-delta.c | 87 +++-
 1 file changed, 86 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index ad62c0245458..bd501f385e78 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -190,7 +191,9 @@ static int ams_delta_init(struct platform_device *pdev)
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
void __iomem *io_base;
struct gpio_descs *data_gpiods;
-   int err = 0;
+   struct gpio_chip *data_gpioc;
+   unsigned long mask, bits;
+   int i, err = 0;
 
if (!res)
return -ENXIO;
@@ -298,6 +301,88 @@ static int ams_delta_init(struct platform_device *pdev)
goto out_mtd;
}
 
+   /* Use GPIO chip of first data GPIO pin descriptor */
+   data_gpioc = gpiod_to_chip(data_gpiods->desc[0]);
+
+   /*
+* For acceptable performance require the data GPIO
+* chip to support get/set_multiple() callbacks.
+*/
+   if (!data_gpioc->get_multiple || !data_gpioc->set_multiple) {
+   err = -EINVAL;
+   dev_err(&pdev->dev,
+   "data GPIO chip does not support get/set_multiple()\n");
+   goto out_mtd;
+   }
+
+   /* Verify if get_multiple() returns all pins low as initialized above */
+   mask = (1 << data_gpiods->ndescs) - 1;
+   err = data_gpioc->get_multiple(data_gpioc, &mask, &bits);
+   if (err) {
+   dev_err(&pdev->dev,
+   "data GPIO chip get_multiple() failed: %d\n", err);
+   goto out_mtd;
+   }
+   if (bits) {
+   err = -EINVAL;
+   dev_err(&pdev->dev,
+   "mismmatch of data GPIO initial value: %lu\n", bits);
+   goto out_mtd;
+   }
+
+   /* Verify each data GPIO pin */
+   for (i = 0; i < data_gpiods->ndescs; i++) {
+   /* Require all pins belong to the same GPIO chip */
+   if (gpiod_to_chip(data_gpiods->desc[i]) != data_gpioc) {
+   err = -EINVAL;
+   dev_err(&pdev->dev, "GPIO chip mismatch of data bit 
%d\n",
+   i);
+   goto out_mtd;
+   }
+
+   /* Require all pins active high (not inverted) */
+   if (gpiod_is_active_low(data_gpiods->desc[i])) {
+   err = -EINVAL;
+   dev_err(&pdev->dev,
+   "unsupported polarity of data GPIO bit %d\n",
+   i);
+   goto out_mtd;
+   }
+
+   /*
+* Require pin gpiod array index to match hardware pin number.
+* Verified by setting the pin high with gpiod_set_raw_value()
+* then reading it back with gpiochip->get() for comparison.
+*/
+   gpiod_set_raw_value(data_gpiods->desc[i], 1);
+   err = data_gpioc->get(data_gpioc, i);
+   if (err < 0) {
+   dev_err(&pdev->dev,
+   "data bit %d GPIO chip get() failed: %d\n", i,
+   err);
+   goto out_mtd;
+   }
+   if (!err) {
+   err = -EINVAL;
+   dev_err(&pdev->dev, "mismatch of data GPIO bit %d 
value\n",
+   i);
+   goto out_mtd;
+   }
+
+   /*
+* Check for unsupported pin hardware configuration.  Use
+* just verified gpiod array index as hardware pin number.
+*/
+   if (gpiochip_line_is_

[RFC PATCH 3/8] mtd: rawnand: ams-delta: Set port direction once per transfer

2018-07-18 Thread Janusz Krzysztofik
In its current shape, the driver sets data port direction before each
byte read/write operation, even during multi-byte transfers.  Optimize
that by setting the port direction only on first byte of each transfer.

Signed-off-by: Janusz Krzysztofik 
---
 drivers/mtd/nand/raw/ams-delta.c | 42 ++--
 1 file changed, 32 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index 6ac38e9cfa1a..dfefcd79b420 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -72,50 +72,72 @@ static const struct mtd_partition partition_info[] = {
  .size =  3 * SZ_256K },
 };
 
-static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
+static void ams_delta_write_next_byte(struct mtd_info *mtd, u_char byte)
 {
struct nand_chip *this = mtd_to_nand(mtd);
struct ams_delta_nand *priv = nand_get_controller_data(this);
-   void __iomem *io_base = priv->io_base;
 
-   writew(0, io_base + OMAP_MPUIO_IO_CNTL);
writew(byte, this->IO_ADDR_W);
gpiod_set_value(priv->gpiod_nwe, 0);
ndelay(40);
gpiod_set_value(priv->gpiod_nwe, 1);
 }
 
-static u_char ams_delta_read_byte(struct mtd_info *mtd)
+static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
 {
-   u_char res;
struct nand_chip *this = mtd_to_nand(mtd);
struct ams_delta_nand *priv = nand_get_controller_data(this);
void __iomem *io_base = priv->io_base;
 
+   writew(0, io_base + OMAP_MPUIO_IO_CNTL);
+
+   ams_delta_write_next_byte(mtd, byte);
+}
+
+static u_char ams_delta_read_next_byte(struct mtd_info *mtd)
+{
+   struct nand_chip *this = mtd_to_nand(mtd);
+   struct ams_delta_nand *priv = nand_get_controller_data(this);
+   u_char res;
+
gpiod_set_value(priv->gpiod_nre, 0);
ndelay(40);
-   writew(~0, io_base + OMAP_MPUIO_IO_CNTL);
res = readw(this->IO_ADDR_R);
gpiod_set_value(priv->gpiod_nre, 1);
 
return res;
 }
 
+static u_char ams_delta_read_byte(struct mtd_info *mtd)
+{
+   struct nand_chip *this = mtd_to_nand(mtd);
+   struct ams_delta_nand *priv = nand_get_controller_data(this);
+   void __iomem *io_base = priv->io_base;
+
+   writew(~0, io_base + OMAP_MPUIO_IO_CNTL);
+
+   return ams_delta_read_next_byte(mtd);
+}
+
 static void ams_delta_write_buf(struct mtd_info *mtd, const u_char *buf,
int len)
 {
int i;
 
-   for (i=0; i 0)
+   ams_delta_write_byte(mtd, buf[0]);
+   for (i = 1; i < len; i++)
+   ams_delta_write_next_byte(mtd, buf[i]);
 }
 
 static void ams_delta_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
int i;
 
-   for (i=0; i 0)
+   buf[0] = ams_delta_read_byte(mtd);
+   for (i = 1; i < len; i++)
+   buf[i] = ams_delta_read_next_byte(mtd);
 }
 
 /*
-- 
2.16.4



[RFC PATCH 6/8] gpio: omap: Add get/set_multiple() callbacks

2018-07-18 Thread Janusz Krzysztofik
This should make applications utilizing whole banks work faster.

Signed-off-by: Janusz Krzysztofik 
---
 drivers/gpio/gpio-omap.c | 88 ++--
 1 file changed, 86 insertions(+), 2 deletions(-)

diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index d1afedf4dcbf..e81008678a38 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -77,6 +77,8 @@ struct gpio_bank {
bool workaround_enabled;
 
void (*set_dataout)(struct gpio_bank *bank, unsigned gpio, int enable);
+   void (*set_dataout_multiple)(struct gpio_bank *bank,
+unsigned long *mask, unsigned long *bits);
int (*get_context_loss_count)(struct device *dev);
 
struct omap_gpio_reg_offs *regs;
@@ -161,6 +163,51 @@ static int omap_get_gpio_dataout(struct gpio_bank *bank, 
int offset)
return (readl_relaxed(reg) & (BIT(offset))) != 0;
 }
 
+/* set multiple data out values using dedicate set/clear register */
+static void omap_set_gpio_dataout_reg_multiple(struct gpio_bank *bank,
+  unsigned long *mask,
+  unsigned long *bits)
+{
+   void __iomem *reg = bank->base;
+   u32 l;
+
+   l = *bits & *mask;
+   writel_relaxed(l, reg + bank->regs->set_dataout);
+   bank->context.dataout |= l;
+
+   l = ~*bits & *mask;
+   writel_relaxed(l, reg + bank->regs->clr_dataout);
+   bank->context.dataout &= ~l;
+}
+
+/* set multiple data out values using mask register */
+static void omap_set_gpio_dataout_mask_multiple(struct gpio_bank *bank,
+   unsigned long *mask,
+   unsigned long *bits)
+{
+   void __iomem *reg = bank->base + bank->regs->dataout;
+   u32 l = (readl_relaxed(reg) & ~*mask) | (*bits & *mask);
+
+   writel_relaxed(l, reg);
+   bank->context.dataout = l;
+}
+
+static unsigned long omap_get_gpio_datain_multiple(struct gpio_bank *bank,
+ unsigned long *mask)
+{
+   void __iomem *reg = bank->base + bank->regs->datain;
+
+   return readl_relaxed(reg) & *mask;
+}
+
+static unsigned long omap_get_gpio_dataout_multiple(struct gpio_bank *bank,
+  unsigned long *mask)
+{
+   void __iomem *reg = bank->base + bank->regs->dataout;
+
+   return readl_relaxed(reg) & *mask;
+}
+
 static inline void omap_gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool 
set)
 {
int l = readl_relaxed(base + reg);
@@ -968,6 +1015,26 @@ static int omap_gpio_output(struct gpio_chip *chip, 
unsigned offset, int value)
return 0;
 }
 
+static int omap_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
+ unsigned long *bits)
+{
+   struct gpio_bank *bank = gpiochip_get_data(chip);
+   void __iomem *reg = bank->base + bank->regs->direction;
+   unsigned long in = readl_relaxed(reg), l;
+
+   *bits = 0;
+
+   l = in & *mask;
+   if (l)
+   *bits |= omap_get_gpio_datain_multiple(bank, &l);
+
+   l = ~in & *mask;
+   if (l)
+   *bits |= omap_get_gpio_dataout_multiple(bank, &l);
+
+   return 0;
+}
+
 static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset,
  unsigned debounce)
 {
@@ -1012,6 +1079,17 @@ static void omap_gpio_set(struct gpio_chip *chip, 
unsigned offset, int value)
raw_spin_unlock_irqrestore(&bank->lock, flags);
 }
 
+static void omap_gpio_set_multiple(struct gpio_chip *chip, unsigned long *mask,
+  unsigned long *bits)
+{
+   struct gpio_bank *bank = gpiochip_get_data(chip);
+   unsigned long flags;
+
+   raw_spin_lock_irqsave(&bank->lock, flags);
+   bank->set_dataout_multiple(bank, mask, bits);
+   raw_spin_unlock_irqrestore(&bank->lock, flags);
+}
+
 /*-*/
 
 static void omap_gpio_show_rev(struct gpio_bank *bank)
@@ -1073,9 +1151,11 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, 
struct irq_chip *irqc)
bank->chip.get_direction = omap_gpio_get_direction;
bank->chip.direction_input = omap_gpio_input;
bank->chip.get = omap_gpio_get;
+   bank->chip.get_multiple = omap_gpio_get_multiple;
bank->chip.direction_output = omap_gpio_output;
bank->chip.set_config = omap_gpio_set_config;
bank->chip.set = omap_gpio_set;
+   bank->chip.set_multiple = omap_gpio_set_multiple;
if (bank->is_mpuio) {
bank->chip.label = "mpuio";
if (bank->regs->wkup_en)

[RFC PATCH 2/8] mtd: rawnand: ams-delta: Write protect device during probe

2018-07-18 Thread Janusz Krzysztofik
Initialize NWP GPIO pin low to protect the device from hazard during
probe.  Release write protection as soon as the device is under
control.

Signed-off-by: Janusz Krzysztofik 
---
 drivers/mtd/nand/raw/ams-delta.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index 48233d638d2a..6ac38e9cfa1a 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -219,8 +219,8 @@ static int ams_delta_init(struct platform_device *pdev)
 
platform_set_drvdata(pdev, priv);
 
-   /* Set chip enabled, but  */
-   priv->gpiod_nwp = devm_gpiod_get(&pdev->dev, "nwp", GPIOD_OUT_HIGH);
+   /* Set chip enabled but write protected */
+   priv->gpiod_nwp = devm_gpiod_get(&pdev->dev, "nwp", GPIOD_OUT_LOW);
if (IS_ERR(priv->gpiod_nwp)) {
err = PTR_ERR(priv->gpiod_nwp);
dev_err(&pdev->dev, "NWP GPIO request failed (%d)\n", err);
@@ -267,6 +267,9 @@ static int ams_delta_init(struct platform_device *pdev)
if (err)
goto out_mtd;
 
+   /* As soon as the device is found, release write protection */
+   gpiod_set_value(priv->gpiod_nwp, 1);
+
/* Register the partitions */
mtd_device_register(mtd, partition_info, ARRAY_SIZE(partition_info));
 
@@ -288,6 +291,9 @@ static int ams_delta_cleanup(struct platform_device *pdev)
struct mtd_info *mtd = nand_to_mtd(&priv->nand_chip);
void __iomem *io_base = priv->io_base;
 
+   /* Apply write protection */
+   gpiod_set_value(priv->gpiod_nwp, 0);
+
/* Release resources, unregister device */
nand_release(mtd);
 
-- 
2.16.4



[RFC PATCH 8/8] mtd: rawnand: ams-delta: Use GPIO callbacks for data I/O

2018-07-18 Thread Janusz Krzysztofik
Don't readw()/writew() data directly from/to GPIO port which is under
control of gpio-omap driver, use GPIO chip callbacks instead.

Thanks to utilization of get/set_multiple() callbacks, performance
degrade is minor for typical data transfers.

The driver should now work with any 8+-bit bidirectional GPIO port,
not only OMAP.

Signed-off-by: Janusz Krzysztofik 

# Conflicts:
#   drivers/mtd/nand/raw/ams-delta.c
---
 arch/arm/mach-omap1/board-ams-delta.c |  11 
 drivers/mtd/nand/raw/ams-delta.c  | 119 +++---
 2 files changed, 52 insertions(+), 78 deletions(-)

diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index 16f7bbe47607..08e732bc1cd2 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -321,20 +321,9 @@ struct modem_private_data {
 
 static struct modem_private_data modem_priv;
 
-static struct resource ams_delta_nand_resources[] = {
-   [0] = {
-   .start  = OMAP1_MPUIO_BASE,
-   .end= OMAP1_MPUIO_BASE +
-   OMAP_MPUIO_IO_CNTL + sizeof(u32) - 1,
-   .flags  = IORESOURCE_MEM,
-   },
-};
-
 static struct platform_device ams_delta_nand_device = {
.name   = "ams-delta-nand",
.id = -1,
-   .num_resources  = ARRAY_SIZE(ams_delta_nand_resources),
-   .resource   = ams_delta_nand_resources,
 };
 
 #define OMAP_GPIO_LABEL"gpio-0-15"
diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index bd501f385e78..8fac8d2a444a 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -25,13 +25,11 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 
 #include 
 #include 
 
-#include 
-
 /*
  * MTD structure for E3 (Delta)
  */
@@ -45,7 +43,9 @@ struct ams_delta_nand {
struct gpio_desc*gpiod_nwe;
struct gpio_desc*gpiod_ale;
struct gpio_desc*gpiod_cle;
-   void __iomem*io_base;
+   struct gpio_chip*data_gpioc;
+   unsigned long   data_mask;
+   int data_width;
 };
 
 /*
@@ -73,43 +73,55 @@ static const struct mtd_partition partition_info[] = {
  .size =  3 * SZ_256K },
 };
 
-static void ams_delta_write_next_byte(struct ams_delta_nand *priv, u_char byte)
+static void ams_delta_write_commit(struct ams_delta_nand *priv)
 {
-   struct nand_chip *this = &priv->nand_chip;
-
-   writew(byte, this->IO_ADDR_W);
gpiod_set_value(priv->gpiod_nwe, 0);
ndelay(40);
gpiod_set_value(priv->gpiod_nwe, 1);
 }
 
+static void ams_delta_write_next_byte(struct ams_delta_nand *priv, u_char byte)
+{
+   struct gpio_chip *data_gpioc = priv->data_gpioc;
+   unsigned long bits = byte;
+
+   data_gpioc->set_multiple(data_gpioc, &priv->data_mask, &bits);
+
+   ams_delta_write_commit(priv);
+}
+
 static void ams_delta_write_first_byte(struct ams_delta_nand *priv, u_char 
byte)
 {
-   void __iomem *io_base = priv->io_base;
+   struct gpio_chip *data_gpioc = priv->data_gpioc;
+   unsigned long bits = byte;
+   int i;
 
-   writew(0, io_base + OMAP_MPUIO_IO_CNTL);
+   for (i = 0; i < priv->data_width; i++)
+   data_gpioc->direction_output(data_gpioc, i, test_bit(i, &bits));
 
-   ams_delta_write_next_byte(priv, byte);
+   ams_delta_write_commit(priv);
 }
 
 static u_char ams_delta_read_next_byte(struct ams_delta_nand *priv)
 {
-   struct nand_chip *this = &priv->nand_chip;
-   u_char res;
+   struct gpio_chip *data_gpioc = priv->data_gpioc;
+   unsigned long bits;
 
gpiod_set_value(priv->gpiod_nre, 0);
ndelay(40);
-   res = readw(this->IO_ADDR_R);
+   data_gpioc->get_multiple(data_gpioc, &priv->data_mask, &bits);
gpiod_set_value(priv->gpiod_nre, 1);
 
-   return res;
+   return bits;
 }
 
 static u_char ams_delta_read_first_byte(struct ams_delta_nand *priv)
 {
-   void __iomem *io_base = priv->io_base;
+   struct gpio_chip *data_gpioc = priv->data_gpioc;
+   int i;
 
-   writew(~0, io_base + OMAP_MPUIO_IO_CNTL);
+   for (i = 0; i < priv->data_width; i++)
+   data_gpioc->direction_input(data_gpioc, i);
 
return ams_delta_read_next_byte(priv);
 }
@@ -188,16 +200,11 @@ static int ams_delta_init(struct platform_device *pdev)
struct ams_delta_nand *priv;
struct nand_chip *this;
struct mtd_info *mtd;
-   struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-   void __iomem *io_base;
struct gpio_descs *data_gpiods;
struct gpio_chip *data_gpioc;
unsigned long mask, bits;
int i, err = 0;
 
-   if (!res)
-   return -EN

[RFC PATCH 4/8] mtd: rawnand: ams-delta: Optimize pointer resolution on read/write

2018-07-18 Thread Janusz Krzysztofik
Further optimize processing speed of read/write callback functions by
resolving private structure pointer only once per callback and passing
it to all subfunctions instead of mtd_info.

Signed-off-by: Janusz Krzysztofik 
---
 drivers/mtd/nand/raw/ams-delta.c | 44 +++-
 1 file changed, 25 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index dfefcd79b420..d7e4c9dbef67 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -72,10 +72,9 @@ static const struct mtd_partition partition_info[] = {
  .size =  3 * SZ_256K },
 };
 
-static void ams_delta_write_next_byte(struct mtd_info *mtd, u_char byte)
+static void ams_delta_write_next_byte(struct ams_delta_nand *priv, u_char byte)
 {
-   struct nand_chip *this = mtd_to_nand(mtd);
-   struct ams_delta_nand *priv = nand_get_controller_data(this);
+   struct nand_chip *this = &priv->nand_chip;
 
writew(byte, this->IO_ADDR_W);
gpiod_set_value(priv->gpiod_nwe, 0);
@@ -83,21 +82,18 @@ static void ams_delta_write_next_byte(struct mtd_info *mtd, 
u_char byte)
gpiod_set_value(priv->gpiod_nwe, 1);
 }
 
-static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
+static void ams_delta_write_first_byte(struct ams_delta_nand *priv, u_char 
byte)
 {
-   struct nand_chip *this = mtd_to_nand(mtd);
-   struct ams_delta_nand *priv = nand_get_controller_data(this);
void __iomem *io_base = priv->io_base;
 
writew(0, io_base + OMAP_MPUIO_IO_CNTL);
 
-   ams_delta_write_next_byte(mtd, byte);
+   ams_delta_write_next_byte(priv, byte);
 }
 
-static u_char ams_delta_read_next_byte(struct mtd_info *mtd)
+static u_char ams_delta_read_next_byte(struct ams_delta_nand *priv)
 {
-   struct nand_chip *this = mtd_to_nand(mtd);
-   struct ams_delta_nand *priv = nand_get_controller_data(this);
+   struct nand_chip *this = &priv->nand_chip;
u_char res;
 
gpiod_set_value(priv->gpiod_nre, 0);
@@ -108,36 +104,46 @@ static u_char ams_delta_read_next_byte(struct mtd_info 
*mtd)
return res;
 }
 
-static u_char ams_delta_read_byte(struct mtd_info *mtd)
+static u_char ams_delta_read_first_byte(struct ams_delta_nand *priv)
 {
-   struct nand_chip *this = mtd_to_nand(mtd);
-   struct ams_delta_nand *priv = nand_get_controller_data(this);
void __iomem *io_base = priv->io_base;
 
writew(~0, io_base + OMAP_MPUIO_IO_CNTL);
 
-   return ams_delta_read_next_byte(mtd);
+   return ams_delta_read_next_byte(priv);
+}
+
+static u_char ams_delta_read_byte(struct mtd_info *mtd)
+{
+   struct nand_chip *this = mtd_to_nand(mtd);
+   struct ams_delta_nand *priv = nand_get_controller_data(this);
+
+   return ams_delta_read_first_byte(priv);
 }
 
 static void ams_delta_write_buf(struct mtd_info *mtd, const u_char *buf,
int len)
 {
+   struct nand_chip *this = mtd_to_nand(mtd);
+   struct ams_delta_nand *priv = nand_get_controller_data(this);
int i;
 
if (len > 0)
-   ams_delta_write_byte(mtd, buf[0]);
+   ams_delta_write_first_byte(priv, buf[0]);
for (i = 1; i < len; i++)
-   ams_delta_write_next_byte(mtd, buf[i]);
+   ams_delta_write_next_byte(priv, buf[i]);
 }
 
 static void ams_delta_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
+   struct nand_chip *this = mtd_to_nand(mtd);
+   struct ams_delta_nand *priv = nand_get_controller_data(this);
int i;
 
if (len > 0)
-   buf[0] = ams_delta_read_byte(mtd);
+   buf[0] = ams_delta_read_first_byte(priv);
for (i = 1; i < len; i++)
-   buf[i] = ams_delta_read_next_byte(mtd);
+   buf[i] = ams_delta_read_next_byte(priv);
 }
 
 /*
@@ -161,7 +167,7 @@ static void ams_delta_hwcontrol(struct mtd_info *mtd, int 
cmd,
}
 
if (cmd != NAND_CMD_NONE)
-   ams_delta_write_byte(mtd, cmd);
+   ams_delta_write_first_byte(priv, cmd);
 }
 
 static int ams_delta_nand_ready(struct mtd_info *mtd)
-- 
2.16.4



[RFC PATCH] ARM: OMAP1: Make OMAP15xx MPUIO based GPIO device optional

2018-07-20 Thread Janusz Krzysztofik
At least one OMAP15xx based board - Amstrad Delta - makes other use
than simple GPIO of OMAP1 MPUIO port.  Since the port is registered
unconditionally at postcore_initcall as "omap_gpio" platform device,
hence occupied by gpio-omap driver, other device driver has no chance
to request its I/O memory resources successfully and may either fail or
proceed without having those resources reserved.
See commit b027274d2e3a ("mtd: ams-delta: fix request_mem_region()
failure") for details.

Even if it's theoretically possible to perform data I/O on the MPUIO
port with help of gpiod_*_array_*() functions, that additional layer
adds too much overhead for a relatively low powerful OMAP15xx machine.
One possible workaround providing acceptable performance would be to
use GPIO chip callbacks directly but that approach hasn't been
accepted.

Instead of inventing a widely acceptable new API for affected driver to
get efficient access to the port over the gpio-omap driver, make
registration of gpio-omap platform device optional for that port.
Boards are then free to decide if they need it as a GPIO device and can
call its initialization, or can assign the port resources to another
device.

Signed-off-by: Janusz Krzysztofik 
---
 arch/arm/mach-omap1/board-generic.c   | 2 ++
 arch/arm/mach-omap1/board-innovator.c | 7 ++-
 arch/arm/mach-omap1/board-palmte.c| 2 ++
 arch/arm/mach-omap1/board-palmtt.c| 2 ++
 arch/arm/mach-omap1/board-palmz71.c   | 2 ++
 arch/arm/mach-omap1/board-sx1.c   | 2 ++
 arch/arm/mach-omap1/common.h  | 3 +++
 arch/arm/mach-omap1/gpio15xx.c| 6 +-
 8 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap1/board-generic.c 
b/arch/arm/mach-omap1/board-generic.c
index 9708629f8c5f..3f812061095e 100644
--- a/arch/arm/mach-omap1/board-generic.c
+++ b/arch/arm/mach-omap1/board-generic.c
@@ -55,6 +55,8 @@ static void __init omap_generic_init(void)
 {
 #ifdef CONFIG_ARCH_OMAP15XX
if (cpu_is_omap15xx()) {
+   omap15xx_mpuio_init();
+
/* mux pins for uarts */
omap_cfg_reg(UART1_TX);
omap_cfg_reg(UART1_RTS);
diff --git a/arch/arm/mach-omap1/board-innovator.c 
b/arch/arm/mach-omap1/board-innovator.c
index 8c286a29f24b..33b74efe3352 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -373,8 +373,13 @@ static inline void innovator_mmc_init(void)
 
 static void __init innovator_init(void)
 {
-   if (cpu_is_omap1510())
+#ifdef CONFIG_ARCH_OMAP15XX
+   if (cpu_is_omap1510()) {
+   omap15xx_mpuio_init();
+
omap1510_fpga_init_irq();
+   }
+#endif
innovator_init_smc91x();
 
 #ifdef CONFIG_ARCH_OMAP15XX
diff --git a/arch/arm/mach-omap1/board-palmte.c 
b/arch/arm/mach-omap1/board-palmte.c
index 2dc5deb19803..b8620e4a2958 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -210,6 +210,8 @@ static void __init palmte_misc_gpio_setup(void)
 
 static void __init omap_palmte_init(void)
 {
+   omap15xx_mpuio_init();
+
/* mux pins for uarts */
omap_cfg_reg(UART1_TX);
omap_cfg_reg(UART1_RTS);
diff --git a/arch/arm/mach-omap1/board-palmtt.c 
b/arch/arm/mach-omap1/board-palmtt.c
index a23327682df0..20ab494f20c5 100644
--- a/arch/arm/mach-omap1/board-palmtt.c
+++ b/arch/arm/mach-omap1/board-palmtt.c
@@ -256,6 +256,8 @@ static void __init omap_mpu_wdt_mode(int mode) {
 
 static void __init omap_palmtt_init(void)
 {
+   omap15xx_mpuio_init();
+
/* mux pins for uarts */
omap_cfg_reg(UART1_TX);
omap_cfg_reg(UART1_RTS);
diff --git a/arch/arm/mach-omap1/board-palmz71.c 
b/arch/arm/mach-omap1/board-palmz71.c
index 30b07096197b..5d468111f681 100644
--- a/arch/arm/mach-omap1/board-palmz71.c
+++ b/arch/arm/mach-omap1/board-palmz71.c
@@ -268,6 +268,8 @@ palmz71_gpio_setup(int early)
 static void __init
 omap_palmz71_init(void)
 {
+   omap15xx_mpuio_init();
+
/* mux pins for uarts */
omap_cfg_reg(UART1_TX);
omap_cfg_reg(UART1_RTS);
diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c
index ec27bb3e370f..bbea85943b3b 100644
--- a/arch/arm/mach-omap1/board-sx1.c
+++ b/arch/arm/mach-omap1/board-sx1.c
@@ -311,6 +311,8 @@ static struct platform_device *sx1_devices[] __initdata = {
 
 static void __init omap_sx1_init(void)
 {
+   omap15xx_mpuio_init();
+
/* mux pins for uarts */
omap_cfg_reg(UART1_TX);
omap_cfg_reg(UART1_RTS);
diff --git a/arch/arm/mach-omap1/common.h b/arch/arm/mach-omap1/common.h
index c6537d2c2859..72551c850197 100644
--- a/arch/arm/mach-omap1/common.h
+++ b/arch/arm/mach-omap1/common.h
@@ -95,6 +95,9 @@ static inline int __init omap_32k_timer_init(void)
 }
 #endif
 
+#ifdef CONFIG_ARCH_OMAP15XX
+extern void omap15xx_init_mpuio(void);
+#endif
 #ifdef CONFIG_ARCH_OMAP16XX
 extern int ocpi_enable(void);
 #else
di

Re: [RFC PATCH 0/8] mtd: rawnand: ams-delta: Use gpio-omap accessors for data I/O

2018-07-20 Thread Janusz Krzysztofik
Hi Boris,

On Thursday, July 19, 2018 8:15:08 AM CEST Boris Brezillon wrote:
> Hi Janusz,
> 
> On Thu, 19 Jul 2018 01:57:02 +0200
> Janusz Krzysztofik  wrote:
> 
> > Implement the idea suggested by Artem Bityutskiy and Tony Lindgren
> > described in commit b027274d2e3a ("mtd: ams-delta: fix
> > request_mem_region() failure").
> 
> Thanks for doing that. I'll review the patches, but I already have a
> extra request: can you convert this driver to ->exec_op()? It does not
> necessarily have to be done in this patchset, but, that'd be great to
> have one more driver converted to the new interface.

OK, I'll have a look as my free time permits.

> BTW, there seems to be a nand_gpio driver, maybe we should merge
> ams-delta code into nand_gpio after it's been patched to use the GPIO
> consumer API.

nand_gpio uses a form of read()/write() on a single bidirectional register for 
data transfer, not GPIO, and it does not make use of NRE / NWE signals.  Maybe 
the two drivers could be merged to some extent but not entirely, I think.

Thanks,
Janusz




Re: [RFC PATCH 1/8] mtd: rawnand: ams-delta: Use private structure

2018-07-20 Thread Janusz Krzysztofik
On Thursday, July 19, 2018 8:17:28 AM CEST Boris Brezillon wrote:
> On Thu, 19 Jul 2018 01:57:03 +0200
> Janusz Krzysztofik  wrote:
> 
> > Introduce a driver private structure and allocate it on device probe.
> > Use it for storing nand_chip structure, GPIO descriptors prevoiusly
> > stored in static variables as well as io_base pointer previously passed
> > as nand controller data or platform driver data.
> 
> That's a good thing. Thanks for doing that.
> 
> > Subsequent patches
> > may populate the structure with more members as needed.
> > 
> > While at it, fix missing mtd->dev.parent and drop useless mtd->owner.
> 
> I'd prefer to have it done in a separate patch if you don't mind.

No problem, I'll split it.

Thanks,
Janusz







Re: [RFC PATCH 2/8] mtd: rawnand: ams-delta: Write protect device during probe

2018-07-20 Thread Janusz Krzysztofik
On Thursday, July 19, 2018 8:22:00 AM CEST Boris Brezillon wrote:
> On Thu, 19 Jul 2018 01:57:04 +0200
> Janusz Krzysztofik  wrote:
> 
> > Initialize NWP GPIO pin low to protect the device from hazard during
> > probe.  Release write protection as soon as the device is under
> > control.
> > 
> > Signed-off-by: Janusz Krzysztofik 
> > ---
> >  drivers/mtd/nand/raw/ams-delta.c | 10 --
> >  1 file changed, 8 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/mtd/nand/raw/ams-delta.c 
> > b/drivers/mtd/nand/raw/ams-delta.c
> > index 48233d638d2a..6ac38e9cfa1a 100644
> > --- a/drivers/mtd/nand/raw/ams-delta.c
> > +++ b/drivers/mtd/nand/raw/ams-delta.c
> > @@ -219,8 +219,8 @@ static int ams_delta_init(struct platform_device *pdev)
> >  
> > platform_set_drvdata(pdev, priv);
> >  
> > -   /* Set chip enabled, but  */
> > -   priv->gpiod_nwp = devm_gpiod_get(&pdev->dev, "nwp", GPIOD_OUT_HIGH);
> > +   /* Set chip enabled but write protected */
> > +   priv->gpiod_nwp = devm_gpiod_get(&pdev->dev, "nwp", GPIOD_OUT_LOW);
> > if (IS_ERR(priv->gpiod_nwp)) {
> > err = PTR_ERR(priv->gpiod_nwp);
> > dev_err(&pdev->dev, "NWP GPIO request failed (%d)\n", err);
> > @@ -267,6 +267,9 @@ static int ams_delta_init(struct platform_device *pdev)
> > if (err)
> > goto out_mtd;
> >  
> > +   /* As soon as the device is found, release write protection */
> > +   gpiod_set_value(priv->gpiod_nwp, 1);
> 
> Please don't do that until we have a generic way to assert/deassert WP
> from the core. I agree that we shouldn't write things in the
> nand_scan() path, but I'd be more comfortable if the core had control
> on this pin just in case we ever need to disable write-protection
> during chip detection/initialization.

OK, I can drop this patch for now if that's what you suggest.
 
Thanks,
Janusz




Re: [RFC PATCH 3/8] mtd: rawnand: ams-delta: Set port direction once per transfer

2018-07-20 Thread Janusz Krzysztofik
On Thursday, July 19, 2018 8:23:18 AM CEST Boris Brezillon wrote:
> On Thu, 19 Jul 2018 01:57:05 +0200
> Janusz Krzysztofik  wrote:
> 
> > In its current shape, the driver sets data port direction before each
> > byte read/write operation, even during multi-byte transfers.  Optimize
> > that by setting the port direction only on first byte of each transfer.
> 
> Sounds like premature optimization for something you'll rework when
> fully switching to the GPIO consumer API to control the DATA bus.

Indeed, this optimization was crucial for getting acceptable performance of 
data transfers over GPIO.  I'm only not sure if there is any action in 
response to your comment expected on my side, e.g., did you want to say I 
should modify the patch description, or change the order of patches?

Thanks,
Janusz





Re: [RFC PATCH 4/8] mtd: rawnand: ams-delta: Optimize pointer resolution on read/write

2018-07-20 Thread Janusz Krzysztofik
On Thursday, July 19, 2018 8:25:38 AM CEST Boris Brezillon wrote:
> On Thu, 19 Jul 2018 01:57:06 +0200
> Janusz Krzysztofik  wrote:
> 
> > Further optimize processing speed of read/write callback functions by
> > resolving private structure pointer only once per callback and passing
> > it to all subfunctions instead of mtd_info.

OK, I'll call it simplification (the code looks more simple after that, doesn't 
it), not optimization if you agree.

Thanks,
Janusz





Re: [RFC PATCH 8/8] mtd: rawnand: ams-delta: Use GPIO callbacks for data I/O

2018-07-20 Thread Janusz Krzysztofik
On Thursday, July 19, 2018 8:47:49 AM CEST Boris Brezillon wrote:
> On Thu, 19 Jul 2018 01:57:10 +0200
> Janusz Krzysztofik  wrote:
> 
> > Don't readw()/writew() data directly from/to GPIO port which is under
> > control of gpio-omap driver, use GPIO chip callbacks instead.
> > 
> > Thanks to utilization of get/set_multiple() callbacks, performance
> > degrade is minor for typical data transfers.
> 
> Same comment here, don't use the gpio_chip hooks directly, use the
> consumer API instead.

I tired but performance was not acceptable.

I see your point but please understand, what I'm trying to do here is not to 
develop a shiny general purpose fully GPIO based NAND driver, I'm trying to 
resolve issues with NAND driver for Amstrad Delta I like to play with, without 
loosing much performance.

I'm going to reconsider all possible options, not only doing data I/O over 
GPIO inside the driver, to have the task completed.  Once done,  I can get 
back to the GPIO based code I developed so far and create a new generic driver 
as my free time permits, or anyone can do that if needed, the code is open 
source after all. 

Thanks,
Janusz




Re: [PATCH v4] regulator: fixed: Convert to use GPIO descriptor only

2018-07-13 Thread Janusz Krzysztofik
Hi Linus,

On Friday, July 13, 2018 9:35:06 AM CEST Linus Walleij wrote:
> On Tue, Jul 10, 2018 at 7:56 PM Janusz Krzysztofik  
wrote:
> > > - .gpio   = AMS_DELTA_GPIO_PIN_MODEM_NRESET,
> > 
> > This is OK but not enough for clean build of board-ams-delta.c when merged
> > into current linux-next as one more struct fixed_voltage_config introduced
> > there recently - keybrd_pwr_config - needs removal of .gpio member
> > (respective lookup table with NULL function name is already there).
> > 
> > > @@ -538,6 +546,7 @@ static struct gpiod_lookup_table
> > > *ams_delta_gpio_tables[] __initdata = {> > 
> > >  };
> > >  
> > >  static struct gpiod_lookup_table *late_gpio_tables[] __initdata = {
> > > 
> > > + &ams_delta_nreset_gpiod_table,
> > 
> > That is also OK but may raise a conflict when merged into current
> > linux-next where late_gpio_tables[] has been removed from
> > board-ams-delta.c  and its content integrated into
> > ams_delta_gpio_tables[].
> > 
> > >   &ams_delta_lcd_gpio_table,
> > >   &ams_delta_nand_gpio_table,
> > >  
> > >  };
> > 
> > If that makes your life easier, I can prepare a fix for board-ams-delta.c
> > on top of your patch.  In that case you can add my:
> > Reviewed-by: Janusz Krzysztofik 
> 
> Hm it's a bit of cross-tree conflict going on here I guess.
> 
> Do you have some idea about how serious the conflicts will be?
> Is it just one patch to the ARM SoC OMAP tree or several?

Just one patch, so ...

> It's a bit of Mark's pick, there are several ways to go about it:
> 
> 1. Simply defer this to the next kernel cycle when your change is upstream
>   and avoid all fuzz (totally OK as long as one is not impatient).
>   I'm definately not in a hurry.
> 
> 2. Mark applies this, conflicts appear in linux-next, you help Stephen
>   to solve it and later on Torvalds has to solve it. Then we need to
>   know how serious the conflicts are.
> 
> 3. Apply this patch with fixes to the ARM SoC tree. Which makes it hard to
>   pull out so I'm not so sure about that.
> 
> 4. An immutable branch with the ARM SoC change for Mark to pull
>   before applying this so I can rebase this patch on that.
> 
> 5. Pick some patch from ARM SoC and apply it *also* to the regulator
>   tree and then this on top so I can rebase the changes and avoid
>   all conflicts. (We do this sometimes as some last resort.)
> 
> 6. ...?

6. The conflict can be easily avoided (or made resolvable automatically) if you 
put the '&ams_delta_nreset_gpiod_table,' entry either at the end of 
late_gpio_tables[] or at the beginning of ams_delta_gpio_tables[]. Then the 
only thing left to do will be a fix removing obsolete .gpio member from the 
board-ams-delta's new "keybrd_pwr" regulator setup.

> BTW I like your OMAP1 cleanups a lot!

Thank you :-),
Janusz





[PATCH] ARM: OMAP1: ams-delta: Fix audio permanently muted

2018-11-23 Thread Janusz Krzysztofik
Since commit 1137ceee76ba ("ARM: OMAP1: ams-delta: Don't request unused
GPIOs"), on-board audio has appeared muted.  Believed to be unused GPIO
pin "hookflash1", apparently set high regardless of the corresponding
bit of "latch2" port attempted to be set low during .init_machine(),
has been identified as the reason.

According to Amstrad E3 wiki, the purpose of the pin hasn't been
clearly identified.  Original Amstrad software used to produce a high
pulse on it when the phone was taken off hook or recall was pressed.
With the current finding, we can assume the pin provides a kind of
audio mute function.

Proper resolution of the issue should be done in two steps:
- resolution of an issue with the pin state not reflecting the value
  the corresponding bit of the port was attempted to be initialized
  with,
- extension of on-board audio driver with a new control.

For now, rename the pin to "audio_mute" to reflect its function and,
as a quick fix, hogg it as output low so on-board audio can produce
audible sound again.

Fixes: 1137ceee76ba ("ARM: OMAP1: ams-delta: Don't request unused GPIOs")
Signed-off-by: Janusz Krzysztofik 
---
 arch/arm/mach-omap1/board-ams-delta.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index 3d191fd52910..1d801f5e8308 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -247,8 +247,8 @@ static struct platform_device latch2_gpio_device = {
 #define LATCH2_PIN_SCARD_CMDVCC11
 #define LATCH2_PIN_MODEM_NRESET12
 #define LATCH2_PIN_MODEM_CODEC 13
-#define LATCH2_PIN_HOOKFLASH1  14
-#define LATCH2_PIN_HOOKFLASH2  15
+#define LATCH2_PIN_AUDIO_MUTE  14
+#define LATCH2_PIN_HOOKFLASH   15
 
 static struct regulator_consumer_supply modem_nreset_consumers[] = {
REGULATOR_SUPPLY("RESET#", "serial8250.1"),
@@ -588,6 +588,8 @@ static int gpiochip_match_by_label(struct gpio_chip *chip, 
void *data)
 static struct gpiod_hog ams_delta_gpio_hogs[] = {
GPIO_HOG(LATCH2_LABEL, LATCH2_PIN_KEYBRD_DATAOUT, "keybrd_dataout",
 GPIO_ACTIVE_HIGH, GPIOD_OUT_LOW),
+   GPIO_HOG(LATCH2_LABEL, LATCH2_PIN_AUDIO_MUTE, "audio_mute",
+GPIO_ACTIVE_HIGH, GPIOD_OUT_LOW),
{},
 };
 
-- 
2.18.1



[PATCH v4 4/4] ARM: OMAP1: ams-delta: Drop obsolete NAND resources

2018-11-21 Thread Janusz Krzysztofik
Amstrad Delta NAND driver now uses GPIO API for data I/O so there is no
need to assign memory I/O resource to the device any longer.  Drop it.

Signed-off-by: Janusz Krzysztofik 
---
 arch/arm/mach-omap1/board-ams-delta.c | 11 ---
 1 file changed, 11 deletions(-)

diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index 30c0d18f372e..d594f60c3224 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -296,20 +296,9 @@ struct modem_private_data {
 
 static struct modem_private_data modem_priv;
 
-static struct resource ams_delta_nand_resources[] = {
-   [0] = {
-   .start  = OMAP1_MPUIO_BASE,
-   .end= OMAP1_MPUIO_BASE +
-   OMAP_MPUIO_IO_CNTL + sizeof(u32) - 1,
-   .flags  = IORESOURCE_MEM,
-   },
-};
-
 static struct platform_device ams_delta_nand_device = {
.name   = "ams-delta-nand",
.id = -1,
-   .num_resources  = ARRAY_SIZE(ams_delta_nand_resources),
-   .resource   = ams_delta_nand_resources,
 };
 
 #define OMAP_GPIO_LABEL"gpio-0-15"
-- 
2.18.1



[PATCH v4 3/4] mtd: rawnand: ams-delta: Use GPIO API for data I/O

2018-11-21 Thread Janusz Krzysztofik
Don't readw()/writew() data directly from/to GPIO port which is under
control of gpio-omap driver, use GPIO consumer API instead.

The driver should now work with any 8-bit bidirectional GPIO port, not
only OMAP.

Signed-off-by: Janusz Krzysztofik 
Reviewed-by: Linus Walleij 
---
 drivers/mtd/nand/raw/ams-delta.c | 109 +--
 1 file changed, 61 insertions(+), 48 deletions(-)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index bb50dda05654..8312182088c1 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -18,11 +18,10 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 
 /*
@@ -38,7 +37,7 @@ struct ams_delta_nand {
struct gpio_desc*gpiod_nwe;
struct gpio_desc*gpiod_ale;
struct gpio_desc*gpiod_cle;
-   void __iomem*io_base;
+   struct gpio_descs   *data_gpiods;
booldata_in;
 };
 
@@ -67,42 +66,78 @@ static const struct mtd_partition partition_info[] = {
  .size =  3 * SZ_256K },
 };
 
-static void ams_delta_io_write(struct ams_delta_nand *priv, u8 byte)
+static void ams_delta_write_commit(struct ams_delta_nand *priv)
 {
-   writew(byte, priv->io_base + OMAP_MPUIO_OUTPUT);
gpiod_set_value(priv->gpiod_nwe, 0);
ndelay(40);
gpiod_set_value(priv->gpiod_nwe, 1);
 }
 
+static void ams_delta_io_write(struct ams_delta_nand *priv, u8 byte)
+{
+   struct gpio_descs *data_gpiods = priv->data_gpiods;
+   DECLARE_BITMAP(values, BITS_PER_TYPE(byte)) = { byte, };
+
+   gpiod_set_raw_array_value(data_gpiods->ndescs, data_gpiods->desc,
+ data_gpiods->info, values);
+
+   ams_delta_write_commit(priv);
+}
+
+static void ams_delta_dir_output(struct ams_delta_nand *priv, u8 byte)
+{
+   struct gpio_descs *data_gpiods = priv->data_gpiods;
+   DECLARE_BITMAP(values, BITS_PER_TYPE(byte)) = { byte, };
+   int i;
+
+   for (i = 0; i < data_gpiods->ndescs; i++)
+   gpiod_direction_output_raw(data_gpiods->desc[i],
+  test_bit(i, values));
+
+   ams_delta_write_commit(priv);
+
+   priv->data_in = false;
+}
+
 static u8 ams_delta_io_read(struct ams_delta_nand *priv)
 {
u8 res;
+   struct gpio_descs *data_gpiods = priv->data_gpiods;
+   DECLARE_BITMAP(values, BITS_PER_TYPE(res)) = { 0, };
 
gpiod_set_value(priv->gpiod_nre, 0);
ndelay(40);
-   res = readw(priv->io_base + OMAP_MPUIO_INPUT_LATCH);
+
+   gpiod_get_raw_array_value(data_gpiods->ndescs, data_gpiods->desc,
+ data_gpiods->info, values);
+
gpiod_set_value(priv->gpiod_nre, 1);
 
+   res = values[0];
return res;
 }
 
-static void ams_delta_dir_input(struct ams_delta_nand *priv, bool in)
+static void ams_delta_dir_input(struct ams_delta_nand *priv)
 {
-   writew(in ? ~0 : 0, priv->io_base + OMAP_MPUIO_IO_CNTL);
-   priv->data_in = in;
+   struct gpio_descs *data_gpiods = priv->data_gpiods;
+   int i;
+
+   for (i = 0; i < data_gpiods->ndescs; i++)
+   gpiod_direction_input(data_gpiods->desc[i]);
+
+   priv->data_in = true;
 }
 
 static void ams_delta_write_buf(struct ams_delta_nand *priv, const u8 *buf,
int len)
 {
-   int i;
+   int i = 0;
 
-   if (priv->data_in)
-   ams_delta_dir_input(priv, false);
+   if (len > 0 && priv->data_in)
+   ams_delta_dir_output(priv, buf[i++]);
 
-   for (i = 0; i < len; i++)
-   ams_delta_io_write(priv, buf[i]);
+   while (i < len)
+   ams_delta_io_write(priv, buf[i++]);
 }
 
 static void ams_delta_read_buf(struct ams_delta_nand *priv, u8 *buf, int len)
@@ -110,7 +145,7 @@ static void ams_delta_read_buf(struct ams_delta_nand *priv, 
u8 *buf, int len)
int i;
 
if (!priv->data_in)
-   ams_delta_dir_input(priv, true);
+   ams_delta_dir_input(priv);
 
for (i = 0; i < len; i++)
buf[i] = ams_delta_io_read(priv);
@@ -188,14 +223,9 @@ static int ams_delta_init(struct platform_device *pdev)
struct ams_delta_nand *priv;
struct nand_chip *this;
struct mtd_info *mtd;
-   struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-   void __iomem *io_base;
struct gpio_descs *data_gpiods;
int err = 0;
 
-   if (!res)
-   return -ENXIO;
-
/* Allocate memory for MTD device structure and private data */
priv = devm_kzalloc(&pdev->dev, sizeof(struct ams_delta_nand),
GFP_KERNEL);
@@ -207,25 +237,13 @@ static

[PATCH v4 2/4] mtd: rawnand: ams-delta: Request data port GPIO resource

2018-11-21 Thread Janusz Krzysztofik
Data port used by the driver is actually an OMAP MPUIO device, already
under control of gpio-omap driver.  For that reason we used to not
request the memory region of the port as that would fail because the
region is already busy.  Despite that, we are still accessing the port
by just ioremapping it and performing read/write operations.  Moreover,
we are doing that without any proteciton from other users legally
manipulating the port pins over GPIO API.

The plan is to convert the driver to access the port over GPIO consumer
API.  Before that happens, already prevent from other users accessing
the port pins by requesting an array of its GPIO descriptors.

Signed-off-by: Janusz Krzysztofik 
Reviewed-by: Boris Brezillon 
Reviewed-by: Linus Walleij 
---
 drivers/mtd/nand/raw/ams-delta.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index f8eb4a419e77..bb50dda05654 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -190,6 +190,7 @@ static int ams_delta_init(struct platform_device *pdev)
struct mtd_info *mtd;
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
void __iomem *io_base;
+   struct gpio_descs *data_gpiods;
int err = 0;
 
if (!res)
@@ -275,8 +276,14 @@ static int ams_delta_init(struct platform_device *pdev)
goto err_unmap;
}
 
-   /* Initialize data port direction to a known state */
-   ams_delta_dir_input(priv, true);
+   /* Request array of data pins, initialize them as input */
+   data_gpiods = devm_gpiod_get_array(&pdev->dev, "data", GPIOD_IN);
+   if (IS_ERR(data_gpiods)) {
+   err = PTR_ERR(data_gpiods);
+   dev_err(&pdev->dev, "data GPIO request failed: %d\n", err);
+   goto err_unmap;
+   }
+   priv->data_in = true;
 
/* Initialize the NAND controller object embedded in ams_delta_nand. */
priv->base.ops = &ams_delta_ops;
-- 
2.18.1



Subject: [PATCH v4 0/4] mtd: rawnand: ams-delta: Use GPIO API for data I/O

2018-11-21 Thread Janusz Krzysztofik


Finalize implementation of the idea suggested by Artem Bityutskiy and
Tony Lindgren, described in commit b027274d2e3a ("mtd: ams-delta: fix
request_mem_region() failure"). Use pure GPIO consumer API, as reqested
by Boris Brezillon.

Janusz Krzysztofik (4):
  ARM: OMAP1: ams-delta: Provide GPIO lookup table for NAND data port
  mtd: rawnand: ams-delta: Request data port GPIO resource
  mtd: rawnand: ams-delta: Use GPIO API for data I/O
  ARM: OMAP1: ams-delta: Drop obsolete NAND resources

 arch/arm/mach-omap1/board-ams-delta.c |   22 ++
 drivers/mtd/nand/raw/ams-delta.c  |  120 +++---
 2 files changed, 80 insertions(+), 62 deletions(-)

Performance on Amstrad Delta is now acceptable after recent extensions
to GPIO API and rawnanad enhancements.

Series intented to be merged via mtd tree, should not conflict with
other OMAP1 patches submitted for 4.21.

Changelog:
v4:   
- drop patches 1/7, 2/7, 5/7 6/7 - changes already merged,
- reintroduce postponed PATCH v2 06/12 as 4/4,
- rebase on nand-next for 4.21.

v3:
[PATCH v3 1/7] mtd: rawnand: ams-delta: show parent device in sysfs
- renamed and an explanation added based on other similar patches on
 Marek Vasut request, thanks.
[PATCH v3 2/7] mtd: rawnand: ams-delta: Use private structure
- no changes.
[PATCH v3 3/7] ARM: OMAP1: ams-delta: Provide GPIO lookup table for NAND
 data port
- no changes.
[PATCH v3 4/7] mtd: rawnand: ams-delta: request data port GPIO resource
- no changes.
[PATCH v3 5/7] mtd: rawnand: ams-delta: Set port direction when needed
- modified to set port direction only when needed instead of on each
 transfer as suggested by Boris, thanks, though I kept separate 
 *_next_byte() functions to maximize performance as much as possible,
- moved back in front of "mtd: rawnand: ams-delta: use GPIO API for data
 I/O" with a comment added referring to the planned switch to GPIO API.
[PATCH v3 6/7] mtd: rawnand: ams-delta: Simplify pointer resolution
- moved back in front of "mtd: rawnand: ams-delta: use GPIO API for data 
 I/O" on Boris request, thanks.
[RFC PATCH v3 7/7] mtd: rawnand: ams-delta: use GPIO API for data I/O
- rebased back on top of the two mentioned above,
- not intended to apply it yet due to performance issues on Amstrad Delta.
Removed from the series:
[RFC PATCH v2 09/12] gpiolib: Identify GPIO descriptor arrays with direct
 mapping
[RFC PATCH v2 10/12] gpiolib: Introduce bitmap get/set array API extension
[RFC PATCH v2 11/12] mtd: rawnand: ams-delta: Use GPIO API bitmap extension
[RFC PATCH v2 12/12] gpiolib: Add fast processing path to bitmap API functions
- intended to be still iterated in a follow up series until performance
 issues are resolved.
[RFC PATCH v2 06/12] ARM: OMAP1: ams-delta: drop obsolete NAND resources
- postponed until acceptable performance on Amstrad Delta is achieved.

v2:
[RFC PATCH v2 00/12] mtd: rawnand: ams-delta: Use GPIO API for data I/O
- renamed from former [RFC PATCH 0/8] mtd: rawnand: ams-delta: Use
  gpio-omap accessors for data I/O
[RFC PATCH v2 01/12] mtd: rawnand: ams-delta: Assign mtd->dev.parent,
not mtd->owner
- split out from former [RFC PATCH 1/8] on Boris request, thanks.
[RFC PATCH v2 02/12] mtd: rawnand: ams-delta: Use private structure
- remaining part of the former [RFC PATCH 1/8].
[RFC PATCH v2 03/12] ARM: OMAP1: ams-delta: Provide GPIO lookup table
for NAND data port
- split out from former [RFC PATCH 5/8] on Boris requesst, thanks,
[RFC PATCH v2 04/12] mtd: rawnand: ams-delta: request data port GPIO resource
- remaining part of the former [RFC PATCH 5/8],
[RFC PATCH v2 05/12] mtd: rawnand: ams-delta: use GPIO API for data read/write
- reworked from former [RFC PATCH 8/8] on Boris requesst to use pure
  GPIO API, thanks,
- moved up in front of former [RFC PATCH 3/8] on Boris request, thanks.
[RFC PATCH v2 06/12] ARM: OMAP1: ams-delta: drop obsolete NAND resources
- split out from former [RFC PATCH 8/8].
[RFC PATCH v2 07/12] mtd: rawnand: ams-delta: Set port direction once per
transfer
- reworked from former [RFC PATCH 3/8] on top of [RFC PATCH v2 05/12].
[RFC PATCH v2 08/12] mtd: rawnand: ams-delta: Simplify pointer resolution
on read/write
- reworked from former [RFC PATCH 4/8] on top of [RFC PATCH v2 08/12],
- renamed from 'Optimize' to 'Simplify' on Boris request, thanks.
[RFC PATCH v2 09/12] gpiolib: Identify GPIO descriptor arrays with direct
mapping
- new patch.
[RFC PATCH v2 10/12] gpiolib: Introduce bitmap get/set array API extension
- new patch.
[RFC PATCH v2 11/12] mtd: rawnand: ams-delta: Use GPIO API bitmap extension
- new patch.
[RFC PATCH v2 12/12] gpiolib: Add fast processing path to bitmap API functions
- new patch.
Removed from the series:
[RFC PATCH 2/8] mtd: rawnand: ams-delta: Write protect device during probe
- postponed on Bo

[PATCH v4 1/4] ARM: OMAP1: ams-delta: Provide GPIO lookup table for NAND data port

2018-11-21 Thread Janusz Krzysztofik
Data port used by Amstrad Delta NAND driver is actually an OMAP MPUIO
device, already under control of gpio-omap driver.  The NAND driver
gets access to the port by ioremapping it and performs read/write
operations.  That is done without any proteciton from other users
legally manipulating the port pins over GPIO API.

The plan is to convert the driver to access the port over GPIO consumer
API.  Before that is implemented, the driver can already obtain
exclusive access to the port by requesting an array of its GPIO
descriptors.

Add respective entries to the NAND GPIO lookup table.

Signed-off-by: Janusz Krzysztofik 
Reviewed-by: Boris Brezillon 
Reviewed-by: Linus Walleij 
---
 arch/arm/mach-omap1/board-ams-delta.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index 3d191fd52910..30c0d18f372e 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -312,7 +312,8 @@ static struct platform_device ams_delta_nand_device = {
.resource   = ams_delta_nand_resources,
 };
 
-#define OMAP_GPIO_LABEL"gpio-0-15"
+#define OMAP_GPIO_LABEL"gpio-0-15"
+#define OMAP_MPUIO_LABEL   "mpuio"
 
 static struct gpiod_lookup_table ams_delta_nand_gpio_table = {
.table = {
@@ -324,6 +325,14 @@ static struct gpiod_lookup_table ams_delta_nand_gpio_table 
= {
GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NWE, "nwe", 0),
GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_ALE, "ale", 0),
GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_CLE, "cle", 0),
+   GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 0, "data", 0, 0),
+   GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 1, "data", 1, 0),
+   GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 2, "data", 2, 0),
+   GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 3, "data", 3, 0),
+   GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 4, "data", 4, 0),
+   GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 5, "data", 5, 0),
+   GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 6, "data", 6, 0),
+   GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 7, "data", 7, 0),
{ },
},
 };
-- 
2.18.1



Re: [PATCH 2/5 v7] regulator: fixed/gpio: Pull inversion/OD into gpiolib

2018-11-29 Thread Janusz Krzysztofik
Hi Linus,

On Monday, November 19, 2018 8:11:23 AM CET Linus Walleij wrote:
> This pushes the handling of inversion semantics and open drain
> settings to the GPIO descriptor and gpiolib. All affected board
> files are also augmented.
> 
> This is especially nice since we don't have to have any
> confusing flags passed around to the left and right littering
> the fixed and GPIO regulator drivers and the regulator core.
> It is all just very straight-forward: the core asks the GPIO
> line to be asserted or deasserted and gpiolib deals with the
> rest depending on how the platform is configured: if the line
> is active low, it deals with that, if the line is open drain,
> it deals with that too.
> 
> Cc: Janusz Krzysztofik  # OMAP1

Tested-by: Janusz Krzysztofik  #OMAP1 Amstrad Delta

Thanks,
Janusz




[PATCH] ARM: OMAP1: ams-delta: move late devices back to init_machine

2018-07-02 Thread Janusz Krzysztofik
Initialization of several Amstrad Delta devices was once moved to
late_initcall by commit f7519d8c8290 ("ARM: OMAP1: ams-delta: register
latch dependent devices later").  The purpose of that move was to allow
smooth conversion of Amstrad Delta latches to GPIO.

After successful conversion only ams_delta_serio driver was moved back
to device_initcall by commit 8d09a1bb3147 ("input: serio: ams-delta:
toggle keyboard power over GPIO").  Registration of ams-delta-nand and
lcd_ams_delta devices was kept in late_initcall in order to avoid
corrupt data reported by the serio driver on boot.  Registration of
cx20442-codec device was kept there for it to be probed after a
regulator on which it depended was ready.

The issue of "keybrd_dataout" GPIO pin not initilized to GPIO_OUT_LOW
before other latch2 pins causing the corruption have been apparently
fixed by commit 5322c19b117a ("ARM: OMAP1: ams-delta: Hog
"keybrd_dataout" GPIO pin").  In turn, the issue of missing regulator
has been fixed by commit 50c678772a0b ("ASoC: cx20442: Don't ignore
regulator_get() errors.").

Simplify the board init code by moving registration of those devices
back to init_machine.

Signed-off-by: Janusz Krzysztofik 
---
Created and testet on top of recent commits 3e14de3bfb3a ("ARM: OMAP1:
ams-delta: refactor late_init()") and 5322c19b117a ("ARM: OMAP1:
ams-delta: Hog "keybrd_dataout" GPIO pin") found in branch
omap-for-v4.19/omap1 of linux-omap tree as well as on commit
50c678772a0b ("ASoC: cx20442: Don't ignore regulator_get() errors.")
already found in linux-next tree.

 arch/arm/mach-omap1/board-ams-delta.c | 24 ++--
 1 file changed, 2 insertions(+), 22 deletions(-)

diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index 22f9be297c2a..dd28d2614d7f 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -596,9 +596,6 @@ static struct platform_device *ams_delta_devices[] 
__initdata = {
&ams_delta_camera_device,
&ams_delta_audio_device,
&ams_delta_serio_device,
-};
-
-static struct platform_device *late_devices[] __initdata = {
&ams_delta_nand_device,
&ams_delta_lcd_device,
&cx20442_codec_device,
@@ -607,9 +604,6 @@ static struct platform_device *late_devices[] __initdata = {
 static struct gpiod_lookup_table *ams_delta_gpio_tables[] __initdata = {
&ams_delta_audio_gpio_table,
&keybrd_pwr_gpio_table,
-};
-
-static struct gpiod_lookup_table *late_gpio_tables[] __initdata = {
&ams_delta_lcd_gpio_table,
&ams_delta_nand_gpio_table,
 };
@@ -713,6 +707,8 @@ static void __init ams_delta_init(void)
ams_delta_audio_gpio_table.dev_id =
dev_name(&ams_delta_audio_device.dev);
keybrd_pwr_gpio_table.dev_id = dev_name(&keybrd_pwr_device.dev);
+   ams_delta_nand_gpio_table.dev_id = dev_name(&ams_delta_nand_device.dev);
+   ams_delta_lcd_gpio_table.dev_id = dev_name(&ams_delta_lcd_device.dev);
 
/*
 * Once GPIO lookup tables are populated with dev_names, register them.
@@ -836,20 +832,6 @@ static int __init ams_delta_gpio_init(void)
 }
 device_initcall_sync(ams_delta_gpio_init);
 
-static void __init ams_delta_late_devices(void)
-{
-   platform_add_devices(late_devices, ARRAY_SIZE(late_devices));
-
-   /*
-* As soon as devices have been registered, assign their dev_names
-* to respective GPIO lookup tables before they are added.
-*/
-   ams_delta_lcd_gpio_table.dev_id = dev_name(&ams_delta_lcd_device.dev);
-   ams_delta_nand_gpio_table.dev_id = dev_name(&ams_delta_nand_device.dev);
-
-   gpiod_add_lookup_tables(late_gpio_tables, ARRAY_SIZE(late_gpio_tables));
-}
-
 static int __init modem_nreset_init(void)
 {
int err;
@@ -894,8 +876,6 @@ static int __init late_init(void)
 {
int err;
 
-   ams_delta_late_devices();
-
err = modem_nreset_init();
if (err)
return err;
-- 
2.16.4



[PATCH v3] mtd: rawnand: ams-delta: use GPIO lookup table

2018-07-09 Thread Janusz Krzysztofik
Now as Amstrad Delta board - the only user of this driver - 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_ function calls 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.

Signed-off-by: Janusz Krzysztofik 
---
Changlog:
v1: Fix handling of devm_gpiod_get_optional() return values - thanks to
Andy Shevchenko.
v2: Remove problematic error code conversion, no longer needed if used
on top of commit d08605a64e67 ("ARM: OMAP1: ams-delta: move late
devices back to init_machine") already in linux-next and commit
8853daf3b4ac ("gpiolib: Defer on non-DT find_chip_by_name()
failure") just applied to linux-gpio/devel.

 drivers/mtd/nand/raw/ams-delta.c | 121 ---
 1 file changed, 62 insertions(+), 59 deletions(-)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index 37a3cc21c7bc..09b2f9fda5b9 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -20,23 +20,28 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
-#include 
 #include 
 
 #include 
 #include 
 
-#include 
-
 #include 
 
 /*
  * MTD structure for E3 (Delta)
  */
 static struct mtd_info *ams_delta_mtd = NULL;
+static struct gpio_desc *gpiod_rdy;
+static struct gpio_desc *gpiod_nce;
+static struct gpio_desc *gpiod_nre;
+static struct gpio_desc *gpiod_nwp;
+static struct gpio_desc *gpiod_nwe;
+static struct gpio_desc *gpiod_ale;
+static struct gpio_desc *gpiod_cle;
 
 /*
  * Define partitions for flash devices
@@ -70,9 +75,9 @@ static void ams_delta_write_byte(struct mtd_info *mtd, u_char 
byte)
 
writew(0, io_base + OMAP_MPUIO_IO_CNTL);
writew(byte, this->IO_ADDR_W);
-   gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 0);
+   gpiod_set_value(gpiod_nwe, 0);
ndelay(40);
-   gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 1);
+   gpiod_set_value(gpiod_nwe, 1);
 }
 
 static u_char ams_delta_read_byte(struct mtd_info *mtd)
@@ -81,11 +86,11 @@ static u_char ams_delta_read_byte(struct mtd_info *mtd)
struct nand_chip *this = mtd_to_nand(mtd);
void __iomem *io_base = (void __iomem *)nand_get_controller_data(this);
 
-   gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 0);
+   gpiod_set_value(gpiod_nre, 0);
ndelay(40);
writew(~0, io_base + OMAP_MPUIO_IO_CNTL);
res = readw(this->IO_ADDR_R);
-   gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 1);
+   gpiod_set_value(gpiod_nre, 1);
 
return res;
 }
@@ -120,12 +125,9 @@ static void ams_delta_hwcontrol(struct mtd_info *mtd, int 
cmd,
 {
 
if (ctrl & NAND_CTRL_CHANGE) {
-   gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NCE,
-   (ctrl & NAND_NCE) == 0);
-   gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_CLE,
-   (ctrl & NAND_CLE) != 0);
-   gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_ALE,
-   (ctrl & NAND_ALE) != 0);
+   gpiod_set_value(gpiod_nce, !(ctrl & NAND_NCE));
+   gpiod_set_value(gpiod_cle, !!(ctrl & NAND_CLE));
+   gpiod_set_value(gpiod_ale, !!(ctrl & NAND_ALE));
}
 
if (cmd != NAND_CMD_NONE)
@@ -134,41 +136,9 @@ static void ams_delta_hwcontrol(struct mtd_info *mtd, int 
cmd,
 
 static int ams_delta_nand_ready(struct mtd_info *mtd)
 {
-   return gpio_get_value(AMS_DELTA_GPIO_PIN_NAND_RB);
+   return gpiod_get_value(gpiod_rdy);
 }
 
-static const struct gpio _mandatory_gpio[] = {
-   {
-   .gpio   = AMS_DELTA_GPIO_PIN_NAND_NCE,
-   .flags  = GPIOF_OUT_INIT_HIGH,
-   .label  = "nand_nce",
-   },
-   {
-   .gpio   = AMS_DELTA_GPIO_PIN_NAND_NRE,
-   .flags  = GPIOF_OUT_INIT_HIGH,
-   .label  = "nand_nre",
-   },
-   {
-   .gpio   = AMS_DELTA_GPIO_PIN_NAND_NWP,
-   .flags  = GPIOF_OUT_INIT_HIGH,
-   .label  = "nand_nwp",
-   },
-   {
-   .gpio   = AMS_DELTA_GPIO_PIN_NAND_NWE,
-   .flags  = GPIOF_OUT_INIT_HIGH,
-   .label  = "nand_nwe",
-   },
-   {
-   .gpio   = AMS_DELTA_GPIO_PIN_NAND_ALE,
-   .flags  = GPIOF_OUT_INIT_LOW,
-   .label  = "nand_ale",
-   },
-   {
-   .gpio   = AMS_DELTA_GPIO_PIN_NAND_CLE,
-   .flags  = GPIOF_OUT_INIT_LOW,
-   .label  = "nand_cle",
-   },
-};
 
 /*
  * Main initialization routine
@@ -216,12 +186,17 @@ static int ams_delta_init(struct platform_device *pdev)

Re: [PATCH v4] regulator: fixed: Convert to use GPIO descriptor only

2018-07-10 Thread Janusz Krzysztofik
Hi Linus,

Regarding OMAP1 part (limited to board-ams-delta.c):

On Tuesday, July 10, 2018 8:11:12 AM CEST Linus Walleij wrote:
> ...
> ChangeLog v3->v4:
> - Rebase and adapt the OMAP1 changes for the GPIO descriptor
>   look-up tables deployed by Janusz.
> ...
> - Go over all patches to board files and make sure we pass
>   a NULL descriptor instead of an "enable" descriptor. The code
>   is looking for unnamed GPIOs as the device tree also just pass
>   gpio[s] = <&foo> so board files also need to use anonymous
>   GPIOs.
> ...
> diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
> b/arch/arm/mach-omap1/board-ams-delta.c
> index 80f54cb54276..2d24cab22134 100644
> --- a/arch/arm/mach-omap1/board-ams-delta.c
> +++ b/arch/arm/mach-omap1/board-ams-delta.c
> @@ -288,7 +288,6 @@ static struct regulator_init_data modem_nreset_data = {
>  static struct fixed_voltage_config modem_nreset_config = {
>   .supply_name= "modem_nreset",
>   .microvolts = 330,
> - .gpio   = AMS_DELTA_GPIO_PIN_MODEM_NRESET,

This is OK but not enough for clean build of board-ams-delta.c when merged 
into current linux-next as one more struct fixed_voltage_config introduced 
there 
recently - keybrd_pwr_config - needs removal of .gpio member (respective lookup 
table with NULL function name is already there).

>   .startup_delay  = 25000,
>   .enable_high= 1,
>   .enabled_at_boot= 1,
> @@ -303,6 +302,15 @@ static struct platform_device modem_nreset_device = {
>   },
>  };
> 
> +static struct gpiod_lookup_table ams_delta_nreset_gpiod_table = {
> + .dev_id = "reg-fixed-voltage",
> + .table = {
> + GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_MODEM_NRESET,
> + NULL, GPIO_ACTIVE_HIGH),
> + { },
> + },
> +};
> +
>  struct modem_private_data {
>   struct regulator *regulator;
>  };
> @@ -538,6 +546,7 @@ static struct gpiod_lookup_table *ams_delta_gpio_tables[] 
> __initdata = {
>  };
> 
>  static struct gpiod_lookup_table *late_gpio_tables[] __initdata = {
> + &ams_delta_nreset_gpiod_table,

That is also OK but may raise a conflict when merged into current linux-next 
where late_gpio_tables[] has been removed from board-ams-delta.c  and its 
content integrated into ams_delta_gpio_tables[].

>   &ams_delta_lcd_gpio_table,
>   &ams_delta_nand_gpio_table,
>  };

If that makes your life easier, I can prepare a fix for board-ams-delta.c on 
top of your patch.  In that case you can add my:
Reviewed-by: Janusz Krzysztofik 

Thanks,
Janusz





Re: [PATCH 3/6] ASoC: ams_delta: use GPIO lookup table

2018-05-24 Thread Janusz Krzysztofik
On Wednesday, May 23, 2018 8:52:44 PM CEST Tony Lindgren wrote:
> * Mark Brown  [180521 10:07]:
> > On Fri, May 18, 2018 at 11:09:51PM +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.
> > 
> > Acked-by: Mark Brown 
> 

Hi Tony,

> Thanks applying patches 1 and 3 of this series into omap-for-v4.18/soc.
> It's kind of getting late for v4.18, but let's see if we can still make
> it.

Thank you.

> Seems the others can be applied to the driver trees after no more
> comments, then once all that is done we can apply the last patch
> in this series.

I'll be submitting v2 of 5/6 (nand) very soon. 4/6 (lcd) is still waiting for 
Tomi to respond. I hope there will be no issues with it. Howevver, regarding 
2/6 - serio - I have to work more on that to satisfy Dmitry's comments. So 
let's forget about 6/6 for now and I'll resubmit it again when we are ready 
for that. Meanwhile, I'm going to submit a few more patches against the board 
init file to complete migration to GPIO descriptors so dynamic allocation of 
GPIO numbers to ams-delta latches will be possible.

Thanks,
Janusz





[PATCH 5/6 v2] mtd: rawnand: ams-delta: use GPIO lookup table

2018-05-25 Thread Janusz Krzysztofik
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. Return -EPROBE_DEFER
if the GPIO pins are not yet available so device initialization is
postponed instead of aborted.

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" (already applied to
omap-for-v4.18/soc tree).

Changes since v1:
- fix handling of devm_gpiod_get_optional() return values - thanks to
  Andy Shevchenko.

Signed-off-by: Janusz Krzysztofik 
---
 drivers/mtd/nand/raw/ams-delta.c | 120 +--
 1 file changed, 64 insertions(+), 56 deletions(-)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index 37a3cc21c7bc..524ceaf12de0 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -20,23 +20,28 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
-#include 
 #include 
 
 #include 
 #include 
 
-#include 
-
 #include 
 
 /*
  * MTD structure for E3 (Delta)
  */
 static struct mtd_info *ams_delta_mtd = NULL;
+static struct gpio_desc *gpiod_rdy;
+static struct gpio_desc *gpiod_nce;
+static struct gpio_desc *gpiod_nre;
+static struct gpio_desc *gpiod_nwp;
+static struct gpio_desc *gpiod_nwe;
+static struct gpio_desc *gpiod_ale;
+static struct gpio_desc *gpiod_cle;
 
 /*
  * Define partitions for flash devices
@@ -70,9 +75,9 @@ static void ams_delta_write_byte(struct mtd_info *mtd, u_char 
byte)
 
writew(0, io_base + OMAP_MPUIO_IO_CNTL);
writew(byte, this->IO_ADDR_W);
-   gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 0);
+   gpiod_set_value(gpiod_nwe, 0);
ndelay(40);
-   gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 1);
+   gpiod_set_value(gpiod_nwe, 1);
 }
 
 static u_char ams_delta_read_byte(struct mtd_info *mtd)
@@ -81,11 +86,11 @@ static u_char ams_delta_read_byte(struct mtd_info *mtd)
struct nand_chip *this = mtd_to_nand(mtd);
void __iomem *io_base = (void __iomem *)nand_get_controller_data(this);
 
-   gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 0);
+   gpiod_set_value(gpiod_nre, 0);
ndelay(40);
writew(~0, io_base + OMAP_MPUIO_IO_CNTL);
res = readw(this->IO_ADDR_R);
-   gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 1);
+   gpiod_set_value(gpiod_nre, 1);
 
return res;
 }
@@ -120,12 +125,9 @@ static void ams_delta_hwcontrol(struct mtd_info *mtd, int 
cmd,
 {
 
if (ctrl & NAND_CTRL_CHANGE) {
-   gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NCE,
-   (ctrl & NAND_NCE) == 0);
-   gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_CLE,
-   (ctrl & NAND_CLE) != 0);
-   gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_ALE,
-   (ctrl & NAND_ALE) != 0);
+   gpiod_set_value(gpiod_nce, !(ctrl & NAND_NCE));
+   gpiod_set_value(gpiod_cle, !!(ctrl & NAND_CLE));
+   gpiod_set_value(gpiod_ale, !!(ctrl & NAND_ALE));
}
 
if (cmd != NAND_CMD_NONE)
@@ -134,41 +136,9 @@ static void ams_delta_hwcontrol(struct mtd_info *mtd, int 
cmd,
 
 static int ams_delta_nand_ready(struct mtd_info *mtd)
 {
-   return gpio_get_value(AMS_DELTA_GPIO_PIN_NAND_RB);
+   return gpiod_get_value(gpiod_rdy);
 }
 
-static const struct gpio _mandatory_gpio[] = {
-   {
-   .gpio   = AMS_DELTA_GPIO_PIN_NAND_NCE,
-   .flags  = GPIOF_OUT_INIT_HIGH,
-   .label  = "nand_nce",
-   },
-   {
-   .gpio   = AMS_DELTA_GPIO_PIN_NAND_NRE,
-   .flags  = GPIOF_OUT_INIT_HIGH,
-   .label  = "nand_nre",
-   },
-   {
-   .gpio   = AMS_DELTA_GPIO_PIN_NAND_NWP,
-   .flags  = GPIOF_OUT_INIT_HIGH,
-   .label  = "nand_nwp",
-   },
-   {
-   .gpio   = AMS_DELTA_GPIO_PIN_NAND_NWE,
-   .flags  = GPIOF_OUT_INIT_HIGH,
-   .label  = "nand_nwe",
-   },
-   {
-   .gpio   = AMS_DELTA_GPIO_PIN_NAND_ALE,
-   .flags  = GPIOF_OUT_INIT_LOW,
-   .label  = "nand_ale",
-   },
-   {
-   .gpio   = AMS_DELTA_GPIO_PIN_NAND_CLE,
-   .flags  = GPIOF_OUT_INIT_LOW,
-   .label  = "nand_cle",
-   },
-};
 
 /*
  * Main initialization routine
@@ -216,12 +186,17 @@ static int ams_delta_init(struct platform_device *pdev)
this->write_buf = ams_delta_write_buf;
this->read_buf = ams_delta_read_buf

[Resend] [PATCH 4/6] fbdev: omapfb: lcd_ams_delta: use GPIO lookup table

2018-05-25 Thread Janusz Krzysztofik
On Friday, May 18, 2018 11:09:52 PM CEST 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. Move GPIO lookup
> to the driver probe function so device initialization can be postponed
> instead of aborted if the GPIO pin is not yet available.
> 
> 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 
> ---
>  drivers/video/fbdev/omap/lcd_ams_delta.c | 59
> ++-- 1 file changed, 26 insertions(+), 33
> deletions(-)
> 
> diff --git a/drivers/video/fbdev/omap/lcd_ams_delta.c
> b/drivers/video/fbdev/omap/lcd_ams_delta.c index a4ee947006c7..19b6425b54be
> 100644
> --- a/drivers/video/fbdev/omap/lcd_ams_delta.c
> +++ b/drivers/video/fbdev/omap/lcd_ams_delta.c
> @@ -24,11 +24,10 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
> -#include 
> 
>  #include 
> -#include 
> 
>  #include "omapfb.h"
> 
> @@ -41,6 +40,8 @@
>  /* LCD class device section */
> 
>  static int ams_delta_lcd;
> +static struct gpio_desc *gpiod_vblen;
> +static struct gpio_desc *gpiod_ndisp;
> 
>  static int ams_delta_lcd_set_power(struct lcd_device *dev, int power)
>  {
> @@ -99,41 +100,17 @@ static struct lcd_ops ams_delta_lcd_ops = {
> 
>  /* omapfb panel section */
> 
> -static const struct gpio _gpios[] = {
> - {
> - .gpio   = AMS_DELTA_GPIO_PIN_LCD_VBLEN,
> - .flags  = GPIOF_OUT_INIT_LOW,
> - .label  = "lcd_vblen",
> - },
> - {
> - .gpio   = AMS_DELTA_GPIO_PIN_LCD_NDISP,
> - .flags  = GPIOF_OUT_INIT_LOW,
> - .label  = "lcd_ndisp",
> - },
> -};
> -
> -static int ams_delta_panel_init(struct lcd_panel *panel,
> - struct omapfb_device *fbdev)
> -{
> - return gpio_request_array(_gpios, ARRAY_SIZE(_gpios));
> -}
> -
> -static void ams_delta_panel_cleanup(struct lcd_panel *panel)
> -{
> - gpio_free_array(_gpios, ARRAY_SIZE(_gpios));
> -}
> -
>  static int ams_delta_panel_enable(struct lcd_panel *panel)
>  {
> - gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_NDISP, 1);
> - gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_VBLEN, 1);
> + gpiod_set_value(gpiod_ndisp, 1);
> + gpiod_set_value(gpiod_vblen, 1);
>   return 0;
>  }
> 
>  static void ams_delta_panel_disable(struct lcd_panel *panel)
>  {
> - gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_VBLEN, 0);
> - gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_NDISP, 0);
> + gpiod_set_value(gpiod_vblen, 0);
> + gpiod_set_value(gpiod_ndisp, 0);
>  }
> 
>  static struct lcd_panel ams_delta_panel = {
> @@ -154,8 +131,6 @@ static struct lcd_panel ams_delta_panel = {
>   .pcd= 0,
>   .acb= 37,
> 
> - .init   = ams_delta_panel_init,
> - .cleanup= ams_delta_panel_cleanup,
>   .enable = ams_delta_panel_enable,
>   .disable= ams_delta_panel_disable,
>  };
> @@ -166,9 +141,27 @@ static struct lcd_panel ams_delta_panel = {
>  static int ams_delta_panel_probe(struct platform_device *pdev)
>  {
>   struct lcd_device *lcd_device = NULL;
> -#ifdef CONFIG_LCD_CLASS_DEVICE
>   int ret;
> 
> + gpiod_vblen = devm_gpiod_get(&pdev->dev, "vblen", GPIOD_OUT_LOW);
> + if (IS_ERR(gpiod_vblen)) {
> + ret = PTR_ERR(gpiod_vblen);
> + dev_err(&pdev->dev, "VBLEN GPIO request failed (%d)\n", ret);
> + if (ret == -ENODEV || ret == -ENOENT)
> + ret = -EPROBE_DEFER;
> + return ret;
> + }
> +
> + gpiod_ndisp = devm_gpiod_get(&pdev->dev, "ndisp", GPIOD_OUT_LOW);
> + if (IS_ERR(gpiod_ndisp)) {
> + ret = PTR_ERR(gpiod_ndisp);
> + dev_err(&pdev->dev, "NDISP GPIO request failed (%d)\n", ret);
> + if (ret == -ENODEV || ret == -ENOENT)
> + ret = -EPROBE_DEFER;
> + return ret;
> + }
> +
> +#ifdef CONFIG_LCD_CLASS_DEVICE
>   lcd_device = lcd_device_register("omapfb", &pdev->dev, NULL,
>   &ams_delta_lcd_ops);






[PATCH 2/2] ARM: OMAP1: ams-delta: assign LED GPIO numbers from descriptors

2018-05-27 Thread Janusz Krzysztofik
Assign a label to latch1 GPIO device the LEDs hang off, enumerate its
pins for the purpose of indexing gpio_led table, remove hardcoded GPIO
numbers from that table replacing them with invalid GPIO numbers and
remove initialization of incompletely described LED device from
machine_init.

As soon as the latch1 GPIO device is registered, use its label to find
respective GPIO chip, identify each LED's GPIO descriptor by its pin
number and assign its gobal GPIO number to the gpio_led table.  Once
completed, register the LED device.

Created and tested against linux-v4.17-rc3.

Signed-off-by: Janusz Krzysztofik 
---
 arch/arm/mach-omap1/board-ams-delta.c | 116 --
 1 file changed, 98 insertions(+), 18 deletions(-)

diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index cdba8decc532..d4b26352ddde 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -179,7 +179,10 @@ static struct resource latch1_resources[] = {
},
 };
 
+#define LATCH1_LABEL   "latch1"
+
 static struct bgpio_pdata latch1_pdata = {
+   .label  = LATCH1_LABEL,
.base   = LATCH1_GPIO_BASE,
.ngpio  = LATCH1_NGPIO,
 };
@@ -194,6 +197,15 @@ static struct platform_device latch1_gpio_device = {
},
 };
 
+#define LATCH1_PIN_LED_CAMERA  0
+#define LATCH1_PIN_LED_ADVERT  1
+#define LATCH1_PIN_LED_MAIL2
+#define LATCH1_PIN_LED_HANDSFREE   3
+#define LATCH1_PIN_LED_VOICEMAIL   4
+#define LATCH1_PIN_LED_VOICE   5
+#define LATCH1_PIN_DOCKIT1 6
+#define LATCH1_PIN_DOCKIT2 7
+
 static struct resource latch2_resources[] = {
[0] = {
.name   = "dat",
@@ -398,38 +410,43 @@ static struct gpiod_lookup_table ams_delta_lcd_gpio_table 
= {
},
 };
 
-static const struct gpio_led gpio_leds[] __initconst = {
-   {
+/*
+ * Dynamically allocated GPIO numbers must be obtained fromm GPIO device
+ * before they can be put in the gpio_led table.  Before that happens,
+ * initialize the table with invalid GPIO numbers, not 0.
+ */
+static struct gpio_led gpio_leds[] __initdata = {
+   [LATCH1_PIN_LED_CAMERA] = {
.name= "camera",
-   .gpio= LATCH1_GPIO_BASE + 0,
+   .gpio= -EINVAL,
.default_state   = LEDS_GPIO_DEFSTATE_OFF,
 #ifdef CONFIG_LEDS_TRIGGERS
.default_trigger = "ams_delta_camera",
 #endif
},
-   {
+   [LATCH1_PIN_LED_ADVERT] = {
.name= "advert",
-   .gpio= LATCH1_GPIO_BASE + 1,
+   .gpio= -EINVAL,
.default_state   = LEDS_GPIO_DEFSTATE_OFF,
},
-   {
+   [LATCH1_PIN_LED_MAIL] = {
.name= "email",
-   .gpio= LATCH1_GPIO_BASE + 2,
+   .gpio= -EINVAL,
.default_state   = LEDS_GPIO_DEFSTATE_OFF,
},
-   {
+   [LATCH1_PIN_LED_HANDSFREE] = {
.name= "handsfree",
-   .gpio= LATCH1_GPIO_BASE + 3,
+   .gpio= -EINVAL,
.default_state   = LEDS_GPIO_DEFSTATE_OFF,
},
-   {
+   [LATCH1_PIN_LED_VOICEMAIL] = {
.name= "voicemail",
-   .gpio= LATCH1_GPIO_BASE + 4,
+   .gpio= -EINVAL,
.default_state   = LEDS_GPIO_DEFSTATE_OFF,
},
-   {
+   [LATCH1_PIN_LED_VOICE] = {
.name= "voice",
-   .gpio= LATCH1_GPIO_BASE + 5,
+   .gpio= -EINVAL,
.default_state   = LEDS_GPIO_DEFSTATE_OFF,
},
 };
@@ -542,6 +559,22 @@ static struct gpiod_lookup_table *late_gpio_tables[] 
__initdata = {
&ams_delta_nand_gpio_table,
 };
 
+/*
+ * Some drivers may not use GPIO lookup tables but need to be provided
+ * with GPIO numbers.  The same applies to GPIO based IRQ lines - some
+ * drivers may even not use GPIO layer but expect just IRQ numbers.
+ * We could either define GPIO lookup tables then use them on behalf
+ * of those devices, or we can use GPIO driver level methods for
+ * identification of GPIO and IRQ numbers. For the purpose of the latter,
+ * defina a helper function which identifies GPIO chips by their labels.
+ */
+static int gpiochip_match_by_label(struct gpio_chip *chip, void *data)
+{
+   char *label = data;
+
+   return !strcmp(label, chip->label);
+}
+
 static void __init ams_delta_init(void)
 {
/* mux pins for uarts */
@@ -571,7 +604,6 @@ static void __init ams_delta_init(void)
led_trigger_register_simple("ams_delta_camera",
&am

[PATCH 1/2] ARM: OMAP1: ams-delta: refactor late_init()

2018-05-27 Thread Janusz Krzysztofik
Before the board level GPIO handling is converted from GPIO numbers to
GPIO descriptors, split late_init() into functional blocks and move
them to separate functions.

While being at it, drop machine type check from late_init() - the
function is now called from the board init_late callback so there is
no need for yet another applicability check.

Signed-off-by: Janusz Krzysztofik 
---
 arch/arm/mach-omap1/board-ams-delta.c | 55 +++
 1 file changed, 43 insertions(+), 12 deletions(-)

diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index 80f54cb54276..cdba8decc532 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -643,19 +643,19 @@ static struct platform_device ams_delta_modem_device = {
},
 };
 
-static int __init late_init(void)
+static int __init ams_delta_gpio_init(void)
 {
int err;
 
-   if (!machine_is_ams_delta())
-   return -ENODEV;
-
err = gpio_request_array(latch_gpios, ARRAY_SIZE(latch_gpios));
-   if (err) {
+   if (err)
pr_err("Couldn't take over latch1/latch2 GPIO pins\n");
-   return err;
-   }
 
+   return err;
+}
+
+static void __init ams_delta_late_devices(void)
+{
platform_add_devices(late_devices, ARRAY_SIZE(late_devices));
 
/*
@@ -666,12 +666,23 @@ static int __init late_init(void)
ams_delta_nand_gpio_table.dev_id = dev_name(&ams_delta_nand_device.dev);
 
gpiod_add_lookup_tables(late_gpio_tables, ARRAY_SIZE(late_gpio_tables));
+}
+
+static int __init modem_nreset_init(void)
+{
+   int err;
 
err = platform_device_register(&modem_nreset_device);
-   if (err) {
+   if (err)
pr_err("Couldn't register the modem regulator device\n");
-   return err;
-   }
+
+   return err;
+}
+
+
+static int __init ams_delta_modem_init(void)
+{
+   int err;
 
omap_cfg_reg(M14_1510_GPIO2);
ams_delta_modem_ports[0].irq =
@@ -692,7 +703,28 @@ static int __init late_init(void)
 
err = platform_device_register(&ams_delta_modem_device);
if (err)
-   goto gpio_free;
+   gpio_free(AMS_DELTA_GPIO_PIN_MODEM_IRQ);
+
+   return err;
+}
+
+static int __init late_init(void)
+{
+   int err;
+
+   err = ams_delta_gpio_init();
+   if (err)
+   return err;
+
+   ams_delta_late_devices();
+
+   err = modem_nreset_init();
+   if (err)
+   return err;
+
+   err = ams_delta_modem_init();
+   if (err)
+   return err;
 
/*
 * Once the modem device is registered, the modem_nreset
@@ -708,7 +740,6 @@ static int __init late_init(void)
 
 unregister:
platform_device_unregister(&ams_delta_modem_device);
-gpio_free:
gpio_free(AMS_DELTA_GPIO_PIN_MODEM_IRQ);
return err;
 }
-- 
2.16.1



Re: [PATCH 5/6 v2] mtd: rawnand: ams-delta: use GPIO lookup table

2018-05-30 Thread Janusz Krzysztofik
On Wednesday, May 30, 2018 11:05:00 AM CEST Boris Brezillon wrote:
> Hi Janusz,

Hi Boris,

> On Sat, 26 May 2018 00:20:45 +0200
> Janusz Krzysztofik  wrote:
> > ...
> > Changes since v1:
> > - fix handling of devm_gpiod_get_optional() return values - thanks to
> >   Andy Shevchenko.
> 
> Can you put the changelog after the "---" separator so that it does not
> appear in the final commit message?

Yes, sure, sorry for that.

> > +err_gpiod:
> > +   if (err == -ENODEV || err == -ENOENT)
> > +   err = -EPROBE_DEFER;
> 
> Hm, isn't it better to make gpiod_find() return ERR_PTR(-EPROBE_DEFER)
> here [1]? At least, ENOENT should not be turned into EPROBE_DEFER,
> because it's returned when there's no entry matching the requested gpio
> in the lookup table, and deferring the probe won't solve this problem.

ENOENT is also returned when no matching lookup table is found. That may 
happen if consumer dev_name stored in the table differs from dev_name assigned 
to the consumer by its bus, the platform bus in this case. For that reason I 
think the consumer dev_name should be initialized in the table after the 
device is registered, when its actual dev_name can be obtained. If that device 
registration happens after the driver is already registered, e.g., at 
late_initcall, the device is probed before its lookup table is ready. For that 
reason returning EPROBE_DEFER seems better to me even in the ENOENT case.

Thanks,
Janusz





Re: [PATCH 5/6 v2] mtd: rawnand: ams-delta: use GPIO lookup table

2018-05-30 Thread Janusz Krzysztofik
On Wednesday, May 30, 2018 7:52:20 PM CEST Boris Brezillon wrote:
> On Wed, 30 May 2018 19:43:09 +0200
> 
> Janusz Krzysztofik  wrote:
> > On Wednesday, May 30, 2018 11:05:00 AM CEST Boris Brezillon wrote:
> > > Hi Janusz,
> > 
> > Hi Boris,
> > 
> > > On Sat, 26 May 2018 00:20:45 +0200
> > > 
> > > Janusz Krzysztofik  wrote:
> > > > ...
> > > > Changes since v1:
> > > > - fix handling of devm_gpiod_get_optional() return values - thanks to
> > > > 
> > > >   Andy Shevchenko.
> > > 
> > > Can you put the changelog after the "---" separator so that it does not
> > > appear in the final commit message?
> > 
> > Yes, sure, sorry for that.
> > 
> > > > +err_gpiod:
> > > > +   if (err == -ENODEV || err == -ENOENT)
> > > > +   err = -EPROBE_DEFER;
> > > 
> > > Hm, isn't it better to make gpiod_find() return ERR_PTR(-EPROBE_DEFER)
> > > here [1]? At least, ENOENT should not be turned into EPROBE_DEFER,
> > > because it's returned when there's no entry matching the requested gpio
> > > in the lookup table, and deferring the probe won't solve this problem.
> > 
> > ENOENT is also returned when no matching lookup table is found. That may
> > happen if consumer dev_name stored in the table differs from dev_name
> > assigned to the consumer by its bus, the platform bus in this case. For
> > that reason I think the consumer dev_name should be initialized in the
> > table after the device is registered, when its actual dev_name can be
> > obtained. If that device registration happens after the driver is already
> > registered, e.g., at late_initcall, the device is probed before its
> > lookup table is ready. For that reason returning EPROBE_DEFER seems
> > better to me even in the ENOENT case.
> Sorry, I don't get it. Aren't GPIO lookup tables supposed to be declared
> in board files, especially if the GPIO is used by a platform device?
> When would you have a lookup table registered later in the init/boot
> process?

When e.g. I'd like to register my GPIO consumer platform device at 
late_initcall for some reason, and I'm not sure what exact dev_name my 
consomer will be registered with by the platform bus. In that case I think I 
should assign dev_name to the lookup table after the consumer device is 
registered and its exact dev_name can be obtained, then register the table,

Am I missing something?

Thanks,
Janusz





Re: linux-next: manual merge of the regulator tree with the arm-soc tree

2018-05-30 Thread Janusz Krzysztofik
On Wednesday, May 30, 2018 7:07:11 AM CEST Stephen Rothwell wrote:
> Hi all,
> 
> Today's linux-next merge of the regulator tree got a conflict in:
> 
>   arch/arm/mach-omap1/board-ams-delta.c
> 
> between commit:
> 
>   0486738928bf ("ARM: OMAP1: ams-delta: add GPIO lookup tables")
> 
> from the arm-soc tree and commit:
> 
>   6059577cb28d ("regulator: fixed: Convert to use GPIO descriptor only")
> 
> from the regulator tree.
> 
> I fixed it up (see below - it may be better done) and can carry the fix
> as necessary. 

Hi Stephen,

Your fix looks pretty good to me, but anyway, I will test it and confirm in a 
day or two, as soon as I have access to the device.

Thanks,
Janusz





Re: linux-next: manual merge of the regulator tree with the arm-soc tree

2018-06-01 Thread Janusz Krzysztofik
On Wednesday, May 30, 2018 9:29:24 AM CEST Linus Walleij wrote:
> On Wed, May 30, 2018 at 7:07 AM, Stephen Rothwell  
wrote:
> > Hi all,
> > 
> > Today's linux-next merge of the regulator tree got a conflict in:
> >   arch/arm/mach-omap1/board-ams-delta.c
> > 
> > between commit:
> >   0486738928bf ("ARM: OMAP1: ams-delta: add GPIO lookup tables")
> > 
> > from the arm-soc tree and commit:
> >   6059577cb28d ("regulator: fixed: Convert to use GPIO descriptor only")
> > 
> > from the regulator tree.
> > 
> > I fixed it up (see below - it may be better done) and can carry the fix
> > as necessary.
> 
> OMG that patch on a patch makes my head spin.
>
> I think I just have to look at the eventual result in linux-next and see if
> it makes proper sense, and rely on Janusz to test the result and help
> to fix it up.

Hi,

I confirm the fix by Stephen works for me, however, the conflicting patch by 
Linus breaks things a bit.

Lookup tables added to board files use function name "enable" while the 
regulator uses NULL. As a result, GPIO descriptor is not matched and not 
assigned to the regulator which ends up running with no control over GPIO pin.

Either the regulator driver should use the function name "enable" or that name 
should be removed from lookup tables.

Thanks,
Janusz





[PATCH] DMA: OMAP: fix OMAP1510 incorrect residue_granularity

2018-06-02 Thread Janusz Krzysztofik
Commit 0198d7bb8a0c ("ASoC: omap-mcbsp: Convert to use the sdma-pcm
instead of omap-pcm") resulted in broken audio playback on OMAP1510
(discovered on Amstrad Delta).

When running on OMAP1510, omap-pcm used to obtain DMA offset from
snd_dmaengine_pcm_pointer_no_residue() based on DMA interrupt triggered
software calculations instead of snd_dmaengine_pcm_pointer() which
depended on residue value calculated from omap_dma_get_src_pos().
Similar code path is still available in now used
sound/soc/soc-generic-dmaengine-pcm.c but it is not triggered.

It was verified already before that omap_get_dma_src_pos() from
arch/arm/plat-omap/dma.c didn't work correctly for OMAP1510 - see
commit 1bdd7419910c ("ASoC: OMAP: fix OMAP1510 broken PCM pointer
callback") for details.  Apparently the same applies to its successor,
omap_dma_get_src_pos() from drivers/dma/omap-dma.c.

On the other hand, snd_dmaengine_pcm_pointer_no_residue() is described
as depreciated and discouraged for use in new drivers because of its
unreliable accuracy.  However, it seems the only working option for
OPAM1510 now, as long as a software calculated residue is not
implemented as OMAP1510 fallback in omap-dma.

Using snd_dmaengine_pcm_pointer_no_residue() code path instead of
snd_dmaengine_pcm_pointer() in sound/soc/soc-generic-dmaengine-pcm.c
can be triggered in two ways:
- by passing pcm->flags |= SND_DMAENGINE_PCM_FLAG_NO_RESIDUE from
  sound/soc/omap/sdma-pcm.c,
- by passing dma_caps.residue_granularity =
  DMA_RESIDUE_GRANULARITY_DESCRIPTOR from drivers/dma/omap-dma.c.

Let's do the latter.

Created and tested against next-20180531 tag from linux-next tree.

Signed-off-by: Janusz Krzysztofik 
---
 drivers/dma/omap-dma.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index d21c19822feb..56399bd45179 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -1485,7 +1485,11 @@ static int omap_dma_probe(struct platform_device *pdev)
od->ddev.src_addr_widths = OMAP_DMA_BUSWIDTHS;
od->ddev.dst_addr_widths = OMAP_DMA_BUSWIDTHS;
od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
-   od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
+   if (__dma_omap15xx(od->plat->dma_attr))
+   od->ddev.residue_granularity =
+   DMA_RESIDUE_GRANULARITY_DESCRIPTOR;
+   else
+   od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
od->ddev.max_burst = SZ_16M - 1; /* CCEN: 24bit unsigned */
od->ddev.dev = &pdev->dev;
INIT_LIST_HEAD(&od->ddev.channels);
-- 
2.16.1



Re: [PATCH] DMA: OMAP: fix OMAP1510 incorrect residue_granularity

2018-06-02 Thread Janusz Krzysztofik
On Saturday, June 2, 2018 4:22:04 PM CEST Janusz Krzysztofik wrote:
> - by passing dma_caps.residue_granularity =
>   DMA_RESIDUE_GRANULARITY_DESCRIPTOR from drivers/dma/omap-dma.c.
> 
> Let's do the latter.
> 
> Created and tested against next-20180531 tag from linux-next tree.

I'm sorry, I missed 'git bisect reset' before testing the patch, it seems 
drivers/dma/omap-dma.c disappeared from next-20180531. I'll rework it and send 
again.

Thanks,
Janusz





[PATCH v2] DMA: OMAP: fix OMAP1510 incorrect residue_granularity

2018-06-02 Thread Janusz Krzysztofik
Commit 0198d7bb8a0c ("ASoC: omap-mcbsp: Convert to use the sdma-pcm
instead of omap-pcm") resulted in broken audio playback on OMAP1510
(discovered on Amstrad Delta).

When running on OMAP1510, omap-pcm used to obtain DMA offset from
snd_dmaengine_pcm_pointer_no_residue() based on DMA interrupt triggered
software calculations instead of snd_dmaengine_pcm_pointer() which
depended on residue value calculated from omap_dma_get_src_pos().
Similar code path is still available in now used
sound/soc/soc-generic-dmaengine-pcm.c but it is not triggered.

It was verified already before that omap_get_dma_src_pos() from
arch/arm/plat-omap/dma.c didn't work correctly for OMAP1510 - see
commit 1bdd7419910c ("ASoC: OMAP: fix OMAP1510 broken PCM pointer
callback") for details.  Apparently the same applies to its successor,
omap_dma_get_src_pos() from drivers/dma/ti/omap-dma.c.

On the other hand, snd_dmaengine_pcm_pointer_no_residue() is described
as depreciated and discouraged for use in new drivers because of its
unreliable accuracy.  However, it seems the only working option for
OPAM1510 now, as long as a software calculated residue is not
implemented as OMAP1510 fallback in omap-dma.

Using snd_dmaengine_pcm_pointer_no_residue() code path instead of
snd_dmaengine_pcm_pointer() in sound/soc/soc-generic-dmaengine-pcm.c
can be triggered in two ways:
- by passing pcm->flags |= SND_DMAENGINE_PCM_FLAG_NO_RESIDUE from
  sound/soc/omap/sdma-pcm.c,
- by passing dma_caps.residue_granularity =
  DMA_RESIDUE_GRANULARITY_DESCRIPTOR from DMA engine.

Let's do the latter.

Created and tested against next-20180531 tag from linux-next tree.

Signed-off-by: Janusz Krzysztofik 
---
Changelog:
v2: apply the patch against omap-dma.c moved to drivers/dma/ti/

 drivers/dma/ti/omap-dma.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/ti/omap-dma.c b/drivers/dma/ti/omap-dma.c
index b73fb51fbc81..96b5096c26dd 100644
--- a/drivers/dma/ti/omap-dma.c
+++ b/drivers/dma/ti/omap-dma.c
@@ -1485,7 +1485,11 @@ static int omap_dma_probe(struct platform_device *pdev)
od->ddev.src_addr_widths = OMAP_DMA_BUSWIDTHS;
od->ddev.dst_addr_widths = OMAP_DMA_BUSWIDTHS;
od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
-   od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
+   if (__dma_omap15xx(od->plat->dma_attr))
+   od->ddev.residue_granularity =
+   DMA_RESIDUE_GRANULARITY_DESCRIPTOR;
+   else
+   od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
od->ddev.max_burst = SZ_16M - 1; /* CCEN: 24bit unsigned */
od->ddev.dev = &pdev->dev;
INIT_LIST_HEAD(&od->ddev.channels);
-- 
2.16.1



[PATCH] gpiolib: Defer on non-DT find_chip_by_name() failure

2018-07-03 Thread Janusz Krzysztofik
Avoid replication of error code conversion in non-DT GPIO consumers'
code by returning -EPROBE_DEFER from gpiod_find() in case a chip
identified by its label in a registered lookup table is not ready.

See https://lkml.org/lkml/2018/5/30/176 for example case.

Signed-off-by: Janusz Krzysztofik 
---
If accepted, please add
Suggested-by: Boris Brezillon 
if Boris doesn't mind.

Thanks,
Janusz

 drivers/gpio/gpiolib.c | 13 ++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index e11a3bb03820..15dc77c80328 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -3639,9 +3639,16 @@ static struct gpio_desc *gpiod_find(struct device *dev, 
const char *con_id,
chip = find_chip_by_name(p->chip_label);
 
if (!chip) {
-   dev_err(dev, "cannot find GPIO chip %s\n",
-   p->chip_label);
-   return ERR_PTR(-ENODEV);
+   /*
+* As the lookup table indicates a chip with
+* p->chip_label should exist, assume it may
+* still appear latar and let the interested
+* consumer be probed again or let the Deferred
+* Probe infrastructure handle the error.
+*/
+   dev_warn(dev, "cannot find GPIO chip %s, deferring\n",
+p->chip_label);
+   return ERR_PTR(-EPROBE_DEFER);
}
 
if (chip->ngpio <= p->chip_hwnum) {
-- 
2.16.4



[PATCH v2] gpiolib: Defer on non-DT find_chip_by_name() failure

2018-07-03 Thread Janusz Krzysztofik
Avoid replication of error code conversion in non-DT GPIO consumers'
code by returning -EPROBE_DEFER from gpiod_find() in case a chip
identified by its label in a registered lookup table is not ready.

See https://lkml.org/lkml/2018/5/30/176 for example case.

Suggested-by: Boris Brezillon 
Signed-off-by: Janusz Krzysztofik 
Reviewed-by: Boris Brezillon 
---
Changelog
v2: fix typo (latar -> later) - thanks Boris and Andy for catching this

I'm not sure if adding both Suggested-by: and Reviewed-by: heades both
with the same person name is in line with good practices, please remove
one if not.

Thanks,
Janusz

 drivers/gpio/gpiolib.c | 13 ++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index e11a3bb03820..01295c03b315 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -3639,9 +3639,16 @@ static struct gpio_desc *gpiod_find(struct device *dev, 
const char *con_id,
chip = find_chip_by_name(p->chip_label);
 
if (!chip) {
-   dev_err(dev, "cannot find GPIO chip %s\n",
-   p->chip_label);
-   return ERR_PTR(-ENODEV);
+   /*
+* As the lookup table indicates a chip with
+* p->chip_label should exist, assume it may
+* still appear later and let the interested
+* consumer be probed again or let the Deferred
+* Probe infrastructure handle the error.
+*/
+   dev_warn(dev, "cannot find GPIO chip %s, deferring\n",
+p->chip_label);
+   return ERR_PTR(-EPROBE_DEFER);
}
 
if (chip->ngpio <= p->chip_hwnum) {
-- 
2.16.4



Re: [PATCH] gpiolib: Defer on non-DT find_chip_by_name() failure

2018-07-04 Thread Janusz Krzysztofik
On Tuesday, July 3, 2018 7:31:41 PM CEST Boris Brezillon wrote:
> Hi Janusz,
> 
> On Tue,  3 Jul 2018 19:26:35 +0200
> 
> Janusz Krzysztofik  wrote:
> > Avoid replication of error code conversion in non-DT GPIO consumers'
> > code by returning -EPROBE_DEFER from gpiod_find() in case a chip
> > identified by its label in a registered lookup table is not ready.
> > 
> > See https://lkml.org/lkml/2018/5/30/176 for example case.
> > 
> > Signed-off-by: Janusz Krzysztofik 
> > ---
> > If accepted, please add
> > 
> > Suggested-by: Boris Brezillon 
> > 
> > if Boris doesn't mind.
> > 
> > Thanks,
> > Janusz
> > 
> >  drivers/gpio/gpiolib.c | 13 ++---
> >  1 file changed, 10 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
> > index e11a3bb03820..15dc77c80328 100644
> > --- a/drivers/gpio/gpiolib.c
> > +++ b/drivers/gpio/gpiolib.c
> > @@ -3639,9 +3639,16 @@ static struct gpio_desc *gpiod_find(struct device
> > *dev, const char *con_id,> 
> > chip = find_chip_by_name(p->chip_label);
> > 
> > if (!chip) {
> > 
> > -   dev_err(dev, "cannot find GPIO chip %s\n",
> > -   p->chip_label);
> > -   return ERR_PTR(-ENODEV);
> > +   /*
> > +* As the lookup table indicates a chip with
> > +* p->chip_label should exist, assume it may
> > +* still appear latar and let the interested
> 
>   ^ later
> 
> > +* consumer be probed again or let the Deferred
> > +* Probe infrastructure handle the error.
> > +*/
> > +   dev_warn(dev, "cannot find GPIO chip %s, deferring\n",
> > +p->chip_label);
> > +   return ERR_PTR(-EPROBE_DEFER);
> > 
> > }
> > 
> > if (chip->ngpio <= p->chip_hwnum) {
> 
> Looks good otherwise. Let's hope we're not breaking implementations
> testing for -ENODEV...

I've reviewed them all and found two which I think may be affected:
- drivers/mfd/arizona-core.c,
- drivers/i2c/busses/i2c-imx.c.
As far as I can understand the code, both depend on error != -EPROBE_DEFER in 
order to continue in degraded mode. I'm adding their maintainers to the loop.

Thanks,
Janusz





Re: [PATCH] gpiolib: Defer on non-DT find_chip_by_name() failure

2018-07-05 Thread Janusz Krzysztofik
On Thursday, July 5, 2018 7:50:37 AM CEST Lee Jones wrote:
> On Wed, 04 Jul 2018, Janusz Krzysztofik wrote:
> > On Tuesday, July 3, 2018 7:31:41 PM CEST Boris Brezillon wrote:
> > > Hi Janusz,
> > > 
> > > On Tue,  3 Jul 2018 19:26:35 +0200
> > > 
> > > Janusz Krzysztofik  wrote:
> > > > Avoid replication of error code conversion in non-DT GPIO consumers'
> > > > code by returning -EPROBE_DEFER from gpiod_find() in case a chip
> > > > identified by its label in a registered lookup table is not ready.
> > > > 
> > > > See https://lkml.org/lkml/2018/5/30/176 for example case.
> > > > 
> > > > Signed-off-by: Janusz Krzysztofik 
> > > > ---
> > > > If accepted, please add
> > > > 
> > > > Suggested-by: Boris Brezillon 
> > > > 
> > > > if Boris doesn't mind.
> > > > 
> > > > Thanks,
> > > > Janusz
> > > > 
> > > >  drivers/gpio/gpiolib.c | 13 ++---
> > > >  1 file changed, 10 insertions(+), 3 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
> > > > index e11a3bb03820..15dc77c80328 100644
> > > > --- a/drivers/gpio/gpiolib.c
> > > > +++ b/drivers/gpio/gpiolib.c
> > > > @@ -3639,9 +3639,16 @@ static struct gpio_desc *gpiod_find(struct
> > > > device
> > > > *dev, const char *con_id,>
> > > > 
> > > > chip = find_chip_by_name(p->chip_label);
> > > > 
> > > > if (!chip) {
> > > > 
> > > > -   dev_err(dev, "cannot find GPIO chip %s\n",
> > > > -   p->chip_label);
> > > > -   return ERR_PTR(-ENODEV);
> > > > +   /*
> > > > +* As the lookup table indicates a chip with
> > > > +* p->chip_label should exist, assume it may
> > > > +* still appear latar and let the interested
> > > > 
> > >   ^ later
> > > > 
> > > > +* consumer be probed again or let the Deferred
> > > > +* Probe infrastructure handle the error.
> > > > +*/
> > > > +   dev_warn(dev, "cannot find GPIO chip %s, 
> > > > deferring\n",
> > > > +p->chip_label);
> > > > +   return ERR_PTR(-EPROBE_DEFER);
> > > > 
> > > > }
> > > > 
> > > > if (chip->ngpio <= p->chip_hwnum) {
> > > 
> > > Looks good otherwise. Let's hope we're not breaking implementations
> > > testing for -ENODEV...
> > 
> > I've reviewed them all and found two which I think may be affected:
> > - drivers/mfd/arizona-core.c,
> > - drivers/i2c/busses/i2c-imx.c.
> > As far as I can understand the code, both depend on error != -EPROBE_DEFER
> > in order to continue in degraded mode. I'm adding their maintainers to
> > the loop.
> From a quick glance, the -EPROBE_DEFER handing in Arizona Core appears
> to be correct.  Would you mind explaining what your concerns are in
> more detail please?

Hi

That's more about handling -ENODEV rather than -EPROBE_DEFER.

Before the change, if GPIO chip supposed to provide "reset" pin was not ready 
during  arizona_dev_init(), devm_gpiod_get() returned -ENODEV and device was 
initialized in degraded mode, i.e., with no control over the "reset" pin.
After the change, gpiod_get() will return -EPROBE_DEFER in such case and 
arizona_dev_init() won't succeed in case the GPIO chip doesn't appear later 
for some reason.

Thanks,
Januszz





Re: [PATCH] gpiolib: Defer on non-DT find_chip_by_name() failure

2018-07-06 Thread Janusz Krzysztofik
> >> On Wed, 04 Jul 2018, Janusz Krzysztofik wrote:
> >>> On Tuesday, July 3, 2018 7:31:41 PM CEST Boris Brezillon wrote:
> >>>> On Tue,  3 Jul 2018 19:26:35 +0200 Janusz Krzysztofik wrote:
> >>>>> chip = find_chip_by_name(p->chip_label);
> >>>>> if (!chip) {
> >>>>> -   dev_err(dev, "cannot find GPIO chip %s\n",
> >>>>> -   p->chip_label);
> >>>>> -   return ERR_PTR(-ENODEV);
> >>>>> +   /*
> >>>>> +* As the lookup table indicates a chip with
> >>>>> +* p->chip_label should exist, assume it may
> >>>>> +* still appear latar and let the interested
> >>>>> +* consumer be probed again or let the Deferred
> >>>>> +* Probe infrastructure handle the error.
> >>>>> +*/
> >>>>> +   dev_warn(dev, "cannot find GPIO chip %s, 
> >>>>> deferring\n",
> >>>>> +p->chip_label);
> >>>>> +   return ERR_PTR(-EPROBE_DEFER);
> >>>>> }
> >>>> 
> >>>> Looks good otherwise. Let's hope we're not breaking implementations
> >>>> testing for -ENODEV...
> >>> 
> >>> I've reviewed them all and found two which I think may be affected:
> >>> - drivers/mfd/arizona-core.c,
> >>> - drivers/i2c/busses/i2c-imx.c.

On Thursday, July 5, 2018 7:23:46 AM CEST Uwe Kleine-König wrote:
> TL;DR: Either I don't understand the implication for
> drivers/i2c/busses/i2c-imx.c or everything is fine.
> ...
> So if a patch changes devm_gpiod_get() to return -EPROBE_DEFER in more
> cases that doesn't seem to hurt. Moreover TTBOMK this driver should only
> be used by dt-machines today such that changing gpio* for non-DT users
> shouldn't affect it.

On Friday, July 6, 2018 11:03:53 AM CEST Richard Fitzgerald wrote:
> The intention is that if the DT node is missing, the Arizona driver can run
> using only soft reset, though there are limitations in that mode.
> This should return -ENOENT so that the Arizona driver will continue without
> a GPIO.
> 
> If the DT defines a GPIO it is effectively saying that this GPIO is required
> so it is valid for the Arizona driver never to come up if the GPIO it is
> defined to depend on doesn't come up.

Uwe, Richard, thanks for clarifications.

I think we can assume the change is safe for all current implementations.

Thanks,
Janusz





Re: [PATCH 04/10] Input: ams_delta_serio: Replace power GPIO with regulator

2018-06-12 Thread Janusz Krzysztofik
On Wednesday, June 13, 2018 12:17:24 AM CEST Dmitry Torokhov wrote:
> On Sat, Jun 09, 2018 at 04:02:18PM +0200, Janusz Krzysztofik wrote:
> > ...
> > +   priv->vcc = devm_regulator_get(&pdev->dev, "vcc");
> > +   if (IS_ERR(priv->vcc)) {
> > +   err = PTR_ERR(priv->vcc);
> > +   dev_err(&pdev->dev, "regulator request failed (%d)\n", err);
> > +   /* Fail softly if the regulator is not available yet */
> > +   if (err == -ENODEV)
> > +   err = -EPROBE_DEFER;
> 
> Hmm, if regulator is not ready yet, devm_regulator_get() should be
> returning -EPROBE_DEFER already, we should not have to convert -ENODEV
> to -EPROBE_DEFER...

Regulator is not ready because its initialization at subsys_initcall is 
deferred by not ready GPIO pin, that in turn is caused by gpio-mmio driver, 
unlike many other GPIO drivers, registered as late as at device_initcall.

I agree devm_regulator_get() could return -EPROBE_DEFER in this case, but I 
can see it does that only when of_get_regulator() indicates the regulator 
should exist. In non-dt case there is apparently no way to justify if it 
should unless its consumer supply table was already in place. For that,  
registration of that table would have to be independent of successful 
registration of the regulator itself while it's not. Maybe it should, but 
that's a separate topic for a separate discussion, I think.

> Is it because we have_full_constraints() returns false? You might need
> to add call to regulator_has_full_constraints() to your board file.

If have_full_constraints() returned true before the regulator or its consumer 
supply table is ready, devm_regulator_get() would happily return a dummy 
regulator and our keyboard would never get its power.

I'm afraid we have to live with that return code conversion as long as the 
only user of this driver is not migrated to dt.

Thanks,
Janusz





Re: [PATCH 09/10] Input: ams_delta_serio: use IRQ resource

2018-06-12 Thread Janusz Krzysztofik
On Wednesday, June 13, 2018 12:21:04 AM CEST Dmitry Torokhov wrote:
> On Sat, Jun 09, 2018 at 04:02:23PM +0200, Janusz Krzysztofik wrote:
> > ...
> > @@ -141,14 +141,11 @@ static int ams_delta_serio_init(struct
> > platform_device *pdev)> 
> >  * 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(irq, handle_simple_irq);
> 
> Do we still need to do this here, or it can be moved into board file?

You're right, it should be possible to move it. I'll check possible options 
and submit a follow up patch.

Thanks,
Janusz





Re: [PATCH 01/10] ARM: OMAP1: ams-delta: drop GPIO lookup table for serio device

2018-06-12 Thread Janusz Krzysztofik
On Wednesday, June 13, 2018 12:23:56 AM CEST Dmitry Torokhov wrote:
> Hi Janusz,
> 
> On Sat, Jun 09, 2018 at 04:02:15PM +0200, Janusz Krzysztofik wrote:
> > GPIO lookup table for ams-delta-serio device was introduced by commit
> > 0486738928bf ("ARM: OMAP1: ams-delta: add GPIO lookup tables").
> > Unfortunately, a follow up patch "Input: ams_delta_serio: use GPIO
> > lookup table" was not accepted by subystem maintainer who requested
> > conversion of the driver to a platform driver, replacepemnt of IRQ GPIO
> > pin with IRQ resource, replacement of GPIO pin providing keyboard power
> > with a regulator and removal of remaining GPIO pins from the driver as
> > not handled by it.
> > 
> > Let's start with removal of no the longer needed GPIO lookup table from
> > the board init file.
> > 
> > Series created and tested on top of next-20180608 tag from linux-next
> > tree.
> 
> This all is really nice (modulo a couple of questions), thank you for
> implementing this. How do you want to merge this? Through OMAP tree or
> input?

Hi Dmitry,

If Tony doesn't mind, I would prefer it merged through OMAP tree as I still 
have a few board patches built on top of it in my queue.

Thanks,
Janusz





[PATCH 4/10 v2] Input: ams_delta_serio: Replace power GPIO with regulator

2018-06-14 Thread Janusz Krzysztofik
Modify the driver so it no longer requests and manipulates the
"keybrd_pwr" GPIO pin but a "vcc" regulator supply instead.

For this to work with Amstrad Delta, define a regulator over the
"keybrd_pwr" GPIO pin with the "vcc" supply for ams-delta-serio device
and register it from the board file.  Both assign an absulute GPIO
number to the soon depreciated .gpio member of the regulator config
structure, and also build and register a GPIO lookup table so it is
ready for use by the regulator driver as soon as its upcoming update
is applied.

Signed-off-by: Janusz Krzysztofik 
---
Changelog:
v2: Extend the comment above error code conversion, thanks Dmitry for 
requesting that.

If you prefer me to resubmit the whole series as v2, please let me know.
In that case, I'll also add the patch which moves substitution of IRQ
handler out of the driver and submit complete v2 as soon as I get access
to the device (next weekend) and can test that extra change, otherwise
I'll submit it as a separate patch.

Thanks,
Janusz


 arch/arm/mach-omap1/board-ams-delta.c | 63 +--
 drivers/input/serio/ams_delta_serio.c | 37 +++-
 2 files changed, 89 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index 2119d2d3ba84..706eb2f9301d 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -509,6 +509,46 @@ static struct platform_device ams_delta_serio_device = {
.id = PLATFORM_DEVID_NONE,
 };
 
+static struct regulator_consumer_supply keybrd_pwr_consumers[] = {
+   /*
+* Initialize supply .dev_name with NULL.  It will be replaced
+* with serio dev_name() as soon as the serio device is registered.
+*/
+   REGULATOR_SUPPLY("vcc", NULL),
+};
+
+static struct regulator_init_data keybrd_pwr_initdata = {
+   .constraints= {
+   .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+   },
+   .num_consumer_supplies  = ARRAY_SIZE(keybrd_pwr_consumers),
+   .consumer_supplies  = keybrd_pwr_consumers,
+};
+
+static struct fixed_voltage_config keybrd_pwr_config = {
+   .supply_name= "keybrd_pwr",
+   .microvolts = 500,
+   .gpio   = AMS_DELTA_GPIO_PIN_KEYBRD_PWR,
+   .enable_high= 1,
+   .init_data  = &keybrd_pwr_initdata,
+};
+
+static struct platform_device keybrd_pwr_device = {
+   .name   = "reg-fixed-voltage",
+   .id = PLATFORM_DEVID_AUTO,
+   .dev= {
+   .platform_data  = &keybrd_pwr_config,
+   },
+};
+
+static struct gpiod_lookup_table keybrd_pwr_gpio_table = {
+   .table = {
+   GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_KEYBRD_PWR, NULL,
+   GPIO_ACTIVE_HIGH),
+   { },
+   },
+};
+
 static struct platform_device *ams_delta_devices[] __initdata = {
&latch1_gpio_device,
&latch2_gpio_device,
@@ -526,6 +566,7 @@ static struct platform_device *late_devices[] __initdata = {
 
 static struct gpiod_lookup_table *ams_delta_gpio_tables[] __initdata = {
&ams_delta_audio_gpio_table,
+   &keybrd_pwr_gpio_table,
 };
 
 static struct gpiod_lookup_table *late_gpio_tables[] __initdata = {
@@ -566,12 +607,30 @@ static void __init ams_delta_init(void)
platform_add_devices(ams_delta_devices, ARRAY_SIZE(ams_delta_devices));
 
/*
-* As soon as devices have been registered, assign their dev_names
-* to respective GPIO lookup tables before they are added.
+* As soon as regulator consumers have been registered, assign their
+* dev_names to consumer supply entries of respective regulators.
+*/
+   keybrd_pwr_consumers[0].dev_name =
+   dev_name(&ams_delta_serio_device.dev);
+
+   /*
+* Once consumer supply entries are populated with dev_names,
+* register regulator devices.  At this stage only the keyboard
+* power regulator has its consumer supply table fully populated.
+*/
+   platform_device_register(&keybrd_pwr_device);
+
+   /*
+* As soon as GPIO consumers have been registered, assign
+* their dev_names to respective GPIO lookup tables.
 */
ams_delta_audio_gpio_table.dev_id =
dev_name(&ams_delta_audio_device.dev);
+   keybrd_pwr_gpio_table.dev_id = dev_name(&keybrd_pwr_device.dev);
 
+   /*
+* Once GPIO lookup tables are populated with dev_names, register them.
+*/
gpiod_add_lookup_tables(ams_delta_gpio_tables,
ARRAY_SIZE(ams_delta_gpio_tables));
 
diff --git a/drivers/input/serio/ams_delta_serio.c 
b/drivers/input/serio/ams_del

[PATCH 1/6] ARM: OMAP1: ams-delta: add GPIO lookup tables

2018-05-18 Thread Janusz Krzysztofik
Scope of the change is limited to GPIO pins used by board specific
device drivers which will be updated by follow-up patches of the
series. Those are some OMAP GPIO (gpio-0-15) and most of Amstrad Delta
latch2 GPIO bank pins. Remaining pins of those banks, as well as
Amstrad Delta latch1 pins, will be addressed later.

Assign a label ("latch2") to the bank, enumerate its pins and put that
information, together with OMAP GPIO bank pins, in GPIO lookup tables.
Assign lookup tables to devices as soon as those devices are registered
and their names can be obtained.

A step froward in:
- removal of hard-coded GPIO numbers from drivers,
- removal of board mach includes from drivers,
- switching to dynamically assigned GPIO numbers.

Created and compile tested agains linux-4.17-rc3

Signed-off-by: Janusz Krzysztofik 
---
 arch/arm/mach-omap1/board-ams-delta.c | 102 ++
 1 file changed, 102 insertions(+)

diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index 52e8e53ca154..4b78e73f8bf7 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -12,6 +12,7 @@
  * published by the Free Software Foundation.
  */
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -202,7 +203,10 @@ static struct resource latch2_resources[] = {
},
 };
 
+#define LATCH2_LABEL   "latch2"
+
 static struct bgpio_pdata latch2_pdata = {
+   .label  = LATCH2_LABEL,
.base   = AMS_DELTA_LATCH2_GPIO_BASE,
.ngpio  = AMS_DELTA_LATCH2_NGPIO,
 };
@@ -217,6 +221,23 @@ static struct platform_device latch2_gpio_device = {
},
 };
 
+#define LATCH2_PIN_LCD_VBLEN   0
+#define LATCH2_PIN_LCD_NDISP   1
+#define LATCH2_PIN_NAND_NCE2
+#define LATCH2_PIN_NAND_NRE3
+#define LATCH2_PIN_NAND_NWP4
+#define LATCH2_PIN_NAND_NWE5
+#define LATCH2_PIN_NAND_ALE6
+#define LATCH2_PIN_NAND_CLE7
+#define LATCH2_PIN_KEYBRD_PWR  8
+#define LATCH2_PIN_KEYBRD_DATAOUT  9
+#define LATCH2_PIN_SCARD_RSTIN 10
+#define LATCH2_PIN_SCARD_CMDVCC11
+#define LATCH2_PIN_MODEM_NRESET12
+#define LATCH2_PIN_MODEM_CODEC 13
+#define LATCH2_PIN_HOOKFLASH1  14
+#define LATCH2_PIN_HOOKFLASH2  15
+
 static const struct gpio latch_gpios[] __initconst = {
{
.gpio   = LATCH1_GPIO_BASE + 6,
@@ -323,6 +344,22 @@ static struct platform_device ams_delta_nand_device = {
.resource   = ams_delta_nand_resources,
 };
 
+#define OMAP_GPIO_LABEL"gpio-0-15"
+
+static struct gpiod_lookup_table ams_delta_nand_gpio_table = {
+   .table = {
+   GPIO_LOOKUP(OMAP_GPIO_LABEL, AMS_DELTA_GPIO_PIN_NAND_RB, "rdy",
+   0),
+   GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NCE, "nce", 0),
+   GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NRE, "nre", 0),
+   GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NWP, "nwp", 0),
+   GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NWE, "nwe", 0),
+   GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_ALE, "ale", 0),
+   GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_CLE, "cle", 0),
+   { },
+   },
+};
+
 static struct resource ams_delta_kp_resources[] = {
[0] = {
.start  = INT_KEYBOARD,
@@ -358,6 +395,14 @@ static struct platform_device ams_delta_lcd_device = {
.id = -1,
 };
 
+static struct gpiod_lookup_table ams_delta_lcd_gpio_table = {
+   .table = {
+   GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_LCD_VBLEN, "vblen", 0),
+   GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_LCD_NDISP, "ndisp", 0),
+   { },
+   },
+};
+
 static const struct gpio_led gpio_leds[] __initconst = {
{
.name= "camera",
@@ -449,11 +494,35 @@ static struct platform_device ams_delta_audio_device = {
.id = -1,
 };
 
+static struct gpiod_lookup_table ams_delta_audio_gpio_table = {
+   .table = {
+   GPIO_LOOKUP(OMAP_GPIO_LABEL, AMS_DELTA_GPIO_PIN_HOOK_SWITCH,
+   "hook_switch", 0),
+   GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_MODEM_CODEC,
+   "modem_codec", 0),
+   { },
+   },
+};
+
 static struct platform_device cx20442_codec_device = {
.name   = "cx20442-codec",
.id = -1,
 };
 
+static struct gpiod_lookup_table ams_delta_serio_gpio_table = {
+   .table = {
+   GPIO_LOOKUP(OMAP_GPIO_LABEL, AMS_DELTA_GPIO_PIN_KEYBRD_DATA,
+   "data", 0),
+   GPIO_LOOKUP(OMAP_GPIO_LABEL, AMS_DELTA_GPIO_PIN_KEYBRD_CLK,
+

[PATCH 6/6] ARM: OMAP1: ams-delta: make board header file local to mach-omap1

2018-05-18 Thread Janusz Krzysztofik
Now as the AMS Delta board header file is no longer included by
drivers, move it to the root directory of mach-omap1.

Signed-off-by: Janusz Krzysztofik 
---
 arch/arm/mach-omap1/ams-delta-fiq-handler.S  | 2 +-
 arch/arm/mach-omap1/ams-delta-fiq.c  | 3 +--
 arch/arm/mach-omap1/board-ams-delta.c| 2 +-
 arch/arm/mach-omap1/{include/mach => }/board-ams-delta.h | 0
 4 files changed, 3 insertions(+), 4 deletions(-)
 rename arch/arm/mach-omap1/{include/mach => }/board-ams-delta.h (100%)

diff --git a/arch/arm/mach-omap1/ams-delta-fiq-handler.S 
b/arch/arm/mach-omap1/ams-delta-fiq-handler.S
index bf608441b357..9005c00db948 100644
--- a/arch/arm/mach-omap1/ams-delta-fiq-handler.S
+++ b/arch/arm/mach-omap1/ams-delta-fiq-handler.S
@@ -16,9 +16,9 @@
 #include 
 #include 
 
-#include 
 #include 
 
+#include "board-ams-delta.h"
 #include "iomap.h"
 #include "soc.h"
 
diff --git a/arch/arm/mach-omap1/ams-delta-fiq.c 
b/arch/arm/mach-omap1/ams-delta-fiq.c
index d7ca9e2b40d2..30aedcc3f2b3 100644
--- a/arch/arm/mach-omap1/ams-delta-fiq.c
+++ b/arch/arm/mach-omap1/ams-delta-fiq.c
@@ -19,11 +19,10 @@
 #include 
 #include 
 
-#include 
-
 #include 
 
 #include 
+#include "board-ams-delta.h"
 
 static struct fiq_handler fh = {
.name   = "ams-delta-fiq"
diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index 80f54cb54276..17d69eb64df3 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -36,7 +36,6 @@
 #include 
 #include 
 
-#include 
 #include 
 #include 
 
@@ -45,6 +44,7 @@
 #include "camera.h"
 #include 
 
+#include "board-ams-delta.h"
 #include "iomap.h"
 #include "common.h"
 
diff --git a/arch/arm/mach-omap1/include/mach/board-ams-delta.h 
b/arch/arm/mach-omap1/board-ams-delta.h
similarity index 100%
rename from arch/arm/mach-omap1/include/mach/board-ams-delta.h
rename to arch/arm/mach-omap1/board-ams-delta.h
-- 
2.16.1



[PATCH 3/6] ASoC: ams_delta: use GPIO lookup table

2018-05-18 Thread Janusz Krzysztofik
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.

The card uses two pins, one for jack and the other for voice modem
codec DAI control.

For jack pin, remove hardcoded GPIO number and use GPIO descriptor
based variant of jack GPIO initialization.

For modem_codec pin, declare static variable for storing its GPIO
descriptor, obtain it on card initialization and replace obsolete
ams_delta_latch2_write() with gpiod_set_value().  For that to work,
don't request the modem_codec pin from the board init code anymore.

If the modem_codec GPIO lookup fails, skip initialization of
functionality of the card which depends on its availability.

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 
---
 arch/arm/mach-omap1/board-ams-delta.c |  5 -
 sound/soc/omap/ams-delta.c| 38 +++
 2 files changed, 21 insertions(+), 22 deletions(-)

diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index 4b78e73f8bf7..80f54cb54276 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -259,11 +259,6 @@ static const struct gpio latch_gpios[] __initconst = {
.flags  = GPIOF_OUT_INIT_LOW,
.label  = "scard_cmdvcc",
},
-   {
-   .gpio   = AMS_DELTA_GPIO_PIN_MODEM_CODEC,
-   .flags  = GPIOF_OUT_INIT_LOW,
-   .label  = "modem_codec",
-   },
{
.gpio   = AMS_DELTA_LATCH2_GPIO_BASE + 14,
.flags  = GPIOF_OUT_INIT_LOW,
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c
index 77a30f0f0c96..4dce494dfbd3 100644
--- a/sound/soc/omap/ams-delta.c
+++ b/sound/soc/omap/ams-delta.c
@@ -22,7 +22,7 @@
  *
  */
 
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -32,7 +32,6 @@
 
 #include 
 
-#include 
 #include 
 
 #include "omap-mcbsp.h"
@@ -213,7 +212,6 @@ static const struct snd_kcontrol_new 
ams_delta_audio_controls[] = {
 static struct snd_soc_jack ams_delta_hook_switch;
 static struct snd_soc_jack_gpio ams_delta_hook_switch_gpios[] = {
{
-   .gpio = 4,
.name = "hook_switch",
.report = SND_JACK_HEADSET,
.invert = 1,
@@ -259,6 +257,7 @@ static struct timer_list cx81801_timer;
 static bool cx81801_cmd_pending;
 static bool ams_delta_muted;
 static DEFINE_SPINLOCK(ams_delta_lock);
+static struct gpio_desc *gpiod_modem_codec;
 
 static void cx81801_timeout(struct timer_list *unused)
 {
@@ -272,7 +271,7 @@ static void cx81801_timeout(struct timer_list *unused)
/* Reconnect the codec DAI back from the modem to the CPU DAI
 * only if digital mute still off */
if (!muted)
-   ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, 0);
+   gpiod_set_value(gpiod_modem_codec, 0);
 }
 
 /* Line discipline .open() */
@@ -381,8 +380,7 @@ static void cx81801_receive(struct tty_struct *tty,
/* Apply config pulse by connecting the codec to the modem
 * if not already done */
if (apply)
-   ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC,
-   AMS_DELTA_LATCH2_MODEM_CODEC);
+   gpiod_set_value(gpiod_modem_codec, 1);
break;
}
 }
@@ -432,8 +430,7 @@ static int ams_delta_digital_mute(struct snd_soc_dai *dai, 
int mute)
spin_unlock_bh(&ams_delta_lock);
 
if (apply)
-   ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC,
-   mute ? AMS_DELTA_LATCH2_MODEM_CODEC : 0);
+   gpiod_set_value(gpiod_modem_codec, !!mute);
return 0;
 }
 
@@ -469,14 +466,6 @@ static int ams_delta_cx20442_init(struct 
snd_soc_pcm_runtime *rtd)
/* Store a pointer to the codec structure for tty ldisc use */
cx20442_codec = rtd->codec_dai->component;
 
-   /* Set up digital mute if not provided by the codec */
-   if (!codec_dai->driver->ops) {
-   codec_dai->driver->ops = &ams_delta_dai_ops;
-   } else {
-   ams_delta_ops.startup = ams_delta_startup;
-   ams_delta_ops.shutdown = ams_delta_shutdown;
-   }
-
/* Add hook switch - can be used to control the codec from userspace
 * even if line discipline fails */
ret = snd_soc_card_jack_new(card, "hook_switch", SND_JACK_HEADSET,
@@ -486,7 +475,7 @@ static int ams_delta_cx20442_init(struct 
snd_soc_pcm_runtime *rtd)
   

[PATCH 2/6] Input: ams_delta_serio: use GPIO lookup table

2018-05-18 Thread Janusz Krzysztofik
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 
---
 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 
+#include 
 #include 
 #include 
 #include 
 #include 
 
 #include 
-#include 
 
 #include 
 
@@ -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;
 
 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

[PATCH 5/6] mtd: rawnand: ams-delta: use GPIO lookup table

2018-05-18 Thread Janusz Krzysztofik
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. Return -EPROBE_DEFER
if the GPIO pins are not yet available so device initialization is
postponed instead of aborted.

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 
---
 drivers/mtd/nand/raw/ams-delta.c | 110 +--
 1 file changed, 58 insertions(+), 52 deletions(-)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index 37a3cc21c7bc..c44be2f5a65c 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -20,23 +20,28 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
-#include 
 #include 
 
 #include 
 #include 
 
-#include 
-
 #include 
 
 /*
  * MTD structure for E3 (Delta)
  */
 static struct mtd_info *ams_delta_mtd = NULL;
+static struct gpio_desc *gpiod_rdy;
+static struct gpio_desc *gpiod_nce;
+static struct gpio_desc *gpiod_nre;
+static struct gpio_desc *gpiod_nwp;
+static struct gpio_desc *gpiod_nwe;
+static struct gpio_desc *gpiod_ale;
+static struct gpio_desc *gpiod_cle;
 
 /*
  * Define partitions for flash devices
@@ -70,9 +75,9 @@ static void ams_delta_write_byte(struct mtd_info *mtd, u_char 
byte)
 
writew(0, io_base + OMAP_MPUIO_IO_CNTL);
writew(byte, this->IO_ADDR_W);
-   gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 0);
+   gpiod_set_value(gpiod_nwe, 0);
ndelay(40);
-   gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 1);
+   gpiod_set_value(gpiod_nwe, 1);
 }
 
 static u_char ams_delta_read_byte(struct mtd_info *mtd)
@@ -81,11 +86,11 @@ static u_char ams_delta_read_byte(struct mtd_info *mtd)
struct nand_chip *this = mtd_to_nand(mtd);
void __iomem *io_base = (void __iomem *)nand_get_controller_data(this);
 
-   gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 0);
+   gpiod_set_value(gpiod_nre, 0);
ndelay(40);
writew(~0, io_base + OMAP_MPUIO_IO_CNTL);
res = readw(this->IO_ADDR_R);
-   gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 1);
+   gpiod_set_value(gpiod_nre, 1);
 
return res;
 }
@@ -120,12 +125,9 @@ static void ams_delta_hwcontrol(struct mtd_info *mtd, int 
cmd,
 {
 
if (ctrl & NAND_CTRL_CHANGE) {
-   gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NCE,
-   (ctrl & NAND_NCE) == 0);
-   gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_CLE,
-   (ctrl & NAND_CLE) != 0);
-   gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_ALE,
-   (ctrl & NAND_ALE) != 0);
+   gpiod_set_value(gpiod_nce, !(ctrl & NAND_NCE));
+   gpiod_set_value(gpiod_cle, !!(ctrl & NAND_CLE));
+   gpiod_set_value(gpiod_ale, !!(ctrl & NAND_ALE));
}
 
if (cmd != NAND_CMD_NONE)
@@ -134,41 +136,9 @@ static void ams_delta_hwcontrol(struct mtd_info *mtd, int 
cmd,
 
 static int ams_delta_nand_ready(struct mtd_info *mtd)
 {
-   return gpio_get_value(AMS_DELTA_GPIO_PIN_NAND_RB);
+   return gpiod_get_value(gpiod_rdy);
 }
 
-static const struct gpio _mandatory_gpio[] = {
-   {
-   .gpio   = AMS_DELTA_GPIO_PIN_NAND_NCE,
-   .flags  = GPIOF_OUT_INIT_HIGH,
-   .label  = "nand_nce",
-   },
-   {
-   .gpio   = AMS_DELTA_GPIO_PIN_NAND_NRE,
-   .flags  = GPIOF_OUT_INIT_HIGH,
-   .label  = "nand_nre",
-   },
-   {
-   .gpio   = AMS_DELTA_GPIO_PIN_NAND_NWP,
-   .flags  = GPIOF_OUT_INIT_HIGH,
-   .label  = "nand_nwp",
-   },
-   {
-   .gpio   = AMS_DELTA_GPIO_PIN_NAND_NWE,
-   .flags  = GPIOF_OUT_INIT_HIGH,
-   .label  = "nand_nwe",
-   },
-   {
-   .gpio   = AMS_DELTA_GPIO_PIN_NAND_ALE,
-   .flags  = GPIOF_OUT_INIT_LOW,
-   .label  = "nand_ale",
-   },
-   {
-   .gpio   = AMS_DELTA_GPIO_PIN_NAND_CLE,
-   .flags  = GPIOF_OUT_INIT_LOW,
-   .label  = "nand_cle",
-   },
-};
 
 /*
  * Main initialization routine
@@ -216,12 +186,15 @@ static int ams_delta_init(struct platform_device *pdev)
this->write_buf = ams_delta_write_buf;
this->read_buf = ams_delta_read_buf;
this->cmd_ctrl = ams_delta_hwcontrol;
-   if (gpio_request(AMS_DELTA_GPIO_PIN_NAND_RB, "nand_rdy") == 0) {
+
+   gpiod

[PATCH 4/6] fbdev: omapfb: lcd_ams_delta: use GPIO lookup table

2018-05-18 Thread Janusz Krzysztofik
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. Move GPIO lookup
to the driver probe function so device initialization can be postponed
instead of aborted if the GPIO pin is not yet available.

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 
---
 drivers/video/fbdev/omap/lcd_ams_delta.c | 59 ++--
 1 file changed, 26 insertions(+), 33 deletions(-)

diff --git a/drivers/video/fbdev/omap/lcd_ams_delta.c 
b/drivers/video/fbdev/omap/lcd_ams_delta.c
index a4ee947006c7..19b6425b54be 100644
--- a/drivers/video/fbdev/omap/lcd_ams_delta.c
+++ b/drivers/video/fbdev/omap/lcd_ams_delta.c
@@ -24,11 +24,10 @@
 #include 
 #include 
 #include 
+#include 
 #include 
-#include 
 
 #include 
-#include 
 
 #include "omapfb.h"
 
@@ -41,6 +40,8 @@
 /* LCD class device section */
 
 static int ams_delta_lcd;
+static struct gpio_desc *gpiod_vblen;
+static struct gpio_desc *gpiod_ndisp;
 
 static int ams_delta_lcd_set_power(struct lcd_device *dev, int power)
 {
@@ -99,41 +100,17 @@ static struct lcd_ops ams_delta_lcd_ops = {
 
 /* omapfb panel section */
 
-static const struct gpio _gpios[] = {
-   {
-   .gpio   = AMS_DELTA_GPIO_PIN_LCD_VBLEN,
-   .flags  = GPIOF_OUT_INIT_LOW,
-   .label  = "lcd_vblen",
-   },
-   {
-   .gpio   = AMS_DELTA_GPIO_PIN_LCD_NDISP,
-   .flags  = GPIOF_OUT_INIT_LOW,
-   .label  = "lcd_ndisp",
-   },
-};
-
-static int ams_delta_panel_init(struct lcd_panel *panel,
-   struct omapfb_device *fbdev)
-{
-   return gpio_request_array(_gpios, ARRAY_SIZE(_gpios));
-}
-
-static void ams_delta_panel_cleanup(struct lcd_panel *panel)
-{
-   gpio_free_array(_gpios, ARRAY_SIZE(_gpios));
-}
-
 static int ams_delta_panel_enable(struct lcd_panel *panel)
 {
-   gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_NDISP, 1);
-   gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_VBLEN, 1);
+   gpiod_set_value(gpiod_ndisp, 1);
+   gpiod_set_value(gpiod_vblen, 1);
return 0;
 }
 
 static void ams_delta_panel_disable(struct lcd_panel *panel)
 {
-   gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_VBLEN, 0);
-   gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_NDISP, 0);
+   gpiod_set_value(gpiod_vblen, 0);
+   gpiod_set_value(gpiod_ndisp, 0);
 }
 
 static struct lcd_panel ams_delta_panel = {
@@ -154,8 +131,6 @@ static struct lcd_panel ams_delta_panel = {
.pcd= 0,
.acb= 37,
 
-   .init   = ams_delta_panel_init,
-   .cleanup= ams_delta_panel_cleanup,
.enable = ams_delta_panel_enable,
.disable= ams_delta_panel_disable,
 };
@@ -166,9 +141,27 @@ static struct lcd_panel ams_delta_panel = {
 static int ams_delta_panel_probe(struct platform_device *pdev)
 {
struct lcd_device *lcd_device = NULL;
-#ifdef CONFIG_LCD_CLASS_DEVICE
int ret;
 
+   gpiod_vblen = devm_gpiod_get(&pdev->dev, "vblen", GPIOD_OUT_LOW);
+   if (IS_ERR(gpiod_vblen)) {
+   ret = PTR_ERR(gpiod_vblen);
+   dev_err(&pdev->dev, "VBLEN GPIO request failed (%d)\n", ret);
+   if (ret == -ENODEV || ret == -ENOENT)
+   ret = -EPROBE_DEFER;
+   return ret;
+   }
+
+   gpiod_ndisp = devm_gpiod_get(&pdev->dev, "ndisp", GPIOD_OUT_LOW);
+   if (IS_ERR(gpiod_ndisp)) {
+   ret = PTR_ERR(gpiod_ndisp);
+   dev_err(&pdev->dev, "NDISP GPIO request failed (%d)\n", ret);
+   if (ret == -ENODEV || ret == -ENOENT)
+   ret = -EPROBE_DEFER;
+   return ret;
+   }
+
+#ifdef CONFIG_LCD_CLASS_DEVICE
lcd_device = lcd_device_register("omapfb", &pdev->dev, NULL,
&ams_delta_lcd_ops);
 
-- 
2.16.1



Re: [PATCH 5/6] mtd: rawnand: ams-delta: use GPIO lookup table

2018-05-18 Thread Janusz Krzysztofik
On Friday, May 18, 2018 11:21:14 PM CEST Andy Shevchenko wrote:
> On Sat, May 19, 2018 at 12:09 AM, Janusz Krzysztofik
> 
>  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.

> > this->dev_ready = ams_delta_nand_ready;
> > 
> > } else {
> > 
> > this->dev_ready = NULL;
> > pr_notice("Couldn't request gpio for Delta NAND
> > ready.\n");
> 
> dev_notice() ?

Sure, but maybe in a separate patch? That's not a new code just being added 
but an existing one, not the merit of the change.

> > }
> > 
> > +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?

Thanks,
Janusz





[PATCH 3/3] ARM: OMAP1: ams-delta: register MODEM device earlier

2018-08-20 Thread Janusz Krzysztofik
Amstrad Delta MODEM device used to be initialized at arch_initcall
before it was once moved to late_initcall by commit f7519d8c8290 ("ARM:
OMAP1: ams-delta: register latch dependent devices later"). The purpose
of that change was to postpone initialization of devices which depended
on latch2 pins until latch2 converted to GPIO device was ready.

After recent fixes to GPIO handling, it was possible to moove
registration of most of those device back to where they were before.
The same can be safely done with the MODEM device as initialization
of GPIO pins it depends on was moved to machine_init by preceding
patch.

Move registration of the MODEM device to arch_initcall_sync, not to
arch_initcall, so it is never exposed to potential conflictinh
registration order hazard against OMAP serial ports.

Signed-off-by: Janusz Krzysztofik 
---
 arch/arm/mach-omap1/board-ams-delta.c | 22 ++
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index c865c6921af8..a98783f98f3a 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -896,11 +896,28 @@ static int __init modem_nreset_init(void)
 /*
  * This function expects MODEM IRQ number already assigned to the port
  * and fails if it's not.
+ * The MODEM device requires its RESET# pin kept high during probe.
+ * That requirement can be fulfilled in several ways:
+ * - with a descriptor of already functional modem_nreset regulator
+ *   assigned to the MODEM private data,
+ * - with the regulator not yet controlled by modem_pm function but
+ *   already enabled by default on probe,
+ * - before the modem_nreset regulator is probed, with the pin already
+ *   set high explicitly.
+ * The last one is already guaranteed by ams_delta_latch2_init() called
+ * from machine_init.
+ * In order to avoid taking over ttyS0 device slot, the MODEM device
+ * should be registered after OMAP serial ports.  Since those ports
+ * are registered at arch_initcall, this function can be called safely
+ * at arch_initcall_sync earliest.
  */
 static int __init ams_delta_modem_init(void)
 {
int err;
 
+   if (!machine_is_ams_delta())
+   return -ENODEV;
+
if (ams_delta_modem_ports[0].irq < 0)
return ams_delta_modem_ports[0].irq;
 
@@ -913,6 +930,7 @@ static int __init ams_delta_modem_init(void)
 
return err;
 }
+arch_initcall_sync(ams_delta_modem_init);
 
 static int __init late_init(void)
 {
@@ -922,10 +940,6 @@ static int __init late_init(void)
if (err)
return err;
 
-   err = ams_delta_modem_init();
-   if (err)
-   return err;
-
/*
 * Once the modem device is registered, the modem_nreset
 * regulator can be requested on behalf of that device.
-- 
2.16.4



[PATCH 2/3] ARM: OMAP1: ams-delta: initialize latch2 pins to safe values

2018-08-20 Thread Janusz Krzysztofik
Latch2 pins control a number of on-board devices, namely LCD, NAND,
MODEM and CODEC.  Those pins used to be initialized with safe values
from init_machine before that operation was:
1) moved to late_initcall in preparation for conversion of latch2 to
GPIO device - see commit f7519d8c8290 ("ARM: OMAP1: ams-delta: register
latch dependent devices later"),
2) replaced with non-atomic initialization performed by means of
gpio_request_array() - see commit 937eb4bb0058 ("ARM: OMAP1: ams-delta:
convert latches to basic_mmio_gpio"),
3) made completely asynchronous by delegation of GPIO request
operations performed on subsets of pins to respective device drivers in
subsequent commits.

One visible negative result of that disintegration was corrupt keyboard
data reported by serio driver, recently fixed by commit 41f8fee385a0
("ARM: OMAP1: ams-delta: Hog "keybrd_dataout" GPIO pin").

Moreover, initialization of LATCH2_PIN_MODEM_CODEC still performed with
ams_delta_latch2_write() wrapper from late_init() is now done on not
requested GPIO pin.

Reintroduce atomic initialization of latch2 pins at machine_init to
prevent from random values potentially corrupting NAND data or maybe
even destroing other hardware.  Also take care of MODEM/CODEC related
pins so MODEM device probe succeeds even if latch2 GPIO device or
dependent regulator is not ready and CODEC can be reached over the
MODEM even if audio driver doesn't take control over
LATCH2_PIN_MODEM_CODEC.

Once done, remove the no longer needed GPIO based implementation of
ams_delta_latch_write() and its frontend macro.

Signed-off-by: Janusz Krzysztofik 
---
 arch/arm/mach-omap1/board-ams-delta.c | 52 +++
 arch/arm/mach-omap1/board-ams-delta.h |  7 -
 2 files changed, 35 insertions(+), 24 deletions(-)

diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index b3fe515b6f49..c865c6921af8 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -321,20 +321,6 @@ struct modem_private_data {
 
 static struct modem_private_data modem_priv;
 
-void ams_delta_latch_write(int base, int ngpio, u16 mask, u16 value)
-{
-   int bit = 0;
-   u16 bitpos = 1 << bit;
-
-   for (; bit < ngpio; bit++, bitpos = bitpos << 1) {
-   if (!(mask & bitpos))
-   continue;
-   else
-   gpio_set_value(base + bit, (value & bitpos) != 0);
-   }
-}
-EXPORT_SYMBOL(ams_delta_latch_write);
-
 static struct resource ams_delta_nand_resources[] = {
[0] = {
.start  = OMAP1_MPUIO_BASE,
@@ -680,6 +666,40 @@ static void __init omap_gpio_deps_init(void)
modem_assign_irq(chip);
 }
 
+/*
+ * Initialize latch2 pins with values which are safe for dependent on-board
+ * devices or useful for their successull initialization even before GPIO
+ * driver takes control over the latch pins:
+ * - LATCH2_PIN_LCD_VBLEN  = 0
+ * - LATCH2_PIN_LCD_NDISP  = 0 Keep LCD device powered off before its
+ * driver takes control over it.
+ * - LATCH2_PIN_NAND_NCE   = 0
+ * - LATCH2_PIN_NAND_NWP   = 0 Keep NAND device down and write-
+ * protected before its driver takes
+ * control over it.
+ * - LATCH2_PIN_KEYBRD_PWR = 0 Keep keyboard powered off before serio
+ * driver takes control over it.
+ * - LATCH2_PIN_KEYBRD_DATAOUT = 0 Keep low to avoid corruption of first
+ * byte of data received from attached
+ * keyboard when serio device is probed;
+ * the pin is also hogged low by the latch2
+ * GPIO driver as soon as it is ready.
+ * - LATCH2_PIN_MODEM_NRESET   = 1 Enable voice MODEM device, allowing for
+ * its successful probe even before a
+ * regulator it depends on, which in turn
+ * takes control over the pin, is set up.
+ * - LATCH2_PIN_MODEM_CODEC= 1 Attach voice MODEM CODEC data port
+ * to the MODEM so the CODEC is under
+ * control even if audio driver doesn't
+ * take it over.
+ */
+static void __init ams_delta_latch2_init(void)
+{
+   u16 latch2 = 1 << LATCH2_PIN_MODEM_NRESET | 1 << LATCH2_PIN_MODEM_CODEC;
+
+   __raw_writew(latch2, LATCH2_VIRT);
+}
+
 static void __init ams_delta_init(void)
 {
/* mux pins for uarts */
@@ -701,6 +721,7 @@ static void __init ams_delta_init(void)
omap_cfg_reg(J18_1610_CAM_D7);
 
omap_gpio_dep

[PATCH 0/3] ARM: OMAP1: ams-delta: Clean up GPIO setup for MODEM

2018-08-20 Thread Janusz Krzysztofik


Convert modem related GPIO setup from integer space to GPIO descriptors.
Also, restore original initialization order of the MODEM device and its
related GPIO pins.

Cleanup of MODEM relaated regulator setup is postponed while waiting for
upcoming conversion of fixed regulator API to GPIO descriptors.


Janusz Krzysztofik (3):
  ARM: OMAP1: ams-delta: assign MODEM IRQ from GPIO descriptor
  ARM: OMAP1: ams-delta: initialize latch2 pins to safe values
  ARM: OMAP1: ams-delta: register MODEM device earlier


diffstat:
 board-ams-delta.c |  120 +++---
 board-ams-delta.h |7 ---
 2 files changed, 88 insertions(+), 39 deletions(-)



[PATCH 1/3] ARM: OMAP1: ams-delta: assign MODEM IRQ from GPIO descriptor

2018-08-20 Thread Janusz Krzysztofik
Don't request MODEM IRQ GPIO by its global number in
ams_delta_modem_init().  Instead, obtain its GPIO descriptor
and assign related IRQ to the MODEM.  Do that from
omap_gpio_deps_init(), where the chip is already looked up.  Then, in
ams_delta_modem_init(), just check for the IRQ number having been
already assigned.

Signed-off-by: Janusz Krzysztofik 
---
 arch/arm/mach-omap1/board-ams-delta.c | 46 ++-
 1 file changed, 35 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index 34cb63ff45b3..b3fe515b6f49 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -630,6 +630,28 @@ static struct gpiod_hog ams_delta_gpio_hogs[] = {
{},
 };
 
+static struct plat_serial8250_port ams_delta_modem_ports[];
+
+/*
+ * Obtain MODEM IRQ GPIO descriptor using its hardware pin
+ * number and assign related IRQ number to the MODEM port.
+ * Keep the GPIO descriptor open so nobody steps in.
+ */
+static void __init modem_assign_irq(struct gpio_chip *chip)
+{
+   struct gpio_desc *gpiod;
+
+   gpiod = gpiochip_request_own_desc(chip, AMS_DELTA_GPIO_PIN_MODEM_IRQ,
+ "modem_irq");
+   if (IS_ERR(gpiod)) {
+   pr_err("%s: modem IRQ GPIO request failed (%ld)\n", __func__,
+  PTR_ERR(gpiod));
+   } else {
+   gpiod_direction_input(gpiod);
+   ams_delta_modem_ports[0].irq = gpiod_to_irq(gpiod);
+   }
+}
+
 /*
  * The purpose of this function is to take care of proper initialization of
  * devices and data structures which depend on GPIO lines provided by OMAP GPIO
@@ -649,7 +671,13 @@ static void __init omap_gpio_deps_init(void)
return;
}
 
+   /*
+* Start with FIQ initialization as it may have to request
+* and release successfully each OMAP GPIO pin in turn.
+*/
ams_delta_init_fiq(chip, &ams_delta_serio_device);
+
+   modem_assign_irq(chip);
 }
 
 static void __init ams_delta_init(void)
@@ -844,20 +872,18 @@ static int __init modem_nreset_init(void)
 }
 
 
+/*
+ * This function expects MODEM IRQ number already assigned to the port
+ * and fails if it's not.
+ */
 static int __init ams_delta_modem_init(void)
 {
int err;
 
-   omap_cfg_reg(M14_1510_GPIO2);
-   ams_delta_modem_ports[0].irq =
-   gpio_to_irq(AMS_DELTA_GPIO_PIN_MODEM_IRQ);
+   if (ams_delta_modem_ports[0].irq < 0)
+   return ams_delta_modem_ports[0].irq;
 
-   err = gpio_request(AMS_DELTA_GPIO_PIN_MODEM_IRQ, "modem");
-   if (err) {
-   pr_err("Couldn't request gpio pin for modem\n");
-   return err;
-   }
-   gpio_direction_input(AMS_DELTA_GPIO_PIN_MODEM_IRQ);
+   omap_cfg_reg(M14_1510_GPIO2);
 
/* Initialize the modem_nreset regulator consumer before use */
modem_priv.regulator = ERR_PTR(-ENODEV);
@@ -866,8 +892,6 @@ static int __init ams_delta_modem_init(void)
AMS_DELTA_LATCH2_MODEM_CODEC);
 
err = platform_device_register(&ams_delta_modem_device);
-   if (err)
-   gpio_free(AMS_DELTA_GPIO_PIN_MODEM_IRQ);
 
return err;
 }
-- 
2.16.4



[PATCH v4 1/3] mtd: rawnand: ams-delta: show parent device in sysfs

2018-08-20 Thread Janusz Krzysztofik
Fix a bug where parent device symlinks aren't shown in sysfs.

While at it, make use of the default owner set by mtdcore.

Signed-off-by: Janusz Krzysztofik 
Reviewed-by: Boris Brezillon 
---
 drivers/mtd/nand/raw/ams-delta.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index 2a8872ebd14a..af313c620264 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -162,7 +162,7 @@ static int ams_delta_init(struct platform_device *pdev)
}
 
ams_delta_mtd = nand_to_mtd(this);
-   ams_delta_mtd->owner = THIS_MODULE;
+   ams_delta_mtd->dev.parent = &pdev->dev;
 
/*
 * Don't try to request the memory region from here,
-- 
2.16.4



[PATCH v4 0/3] mtd: rawnand: ams-delta: Cleanups and optimizations

2018-08-20 Thread Janusz Krzysztofik


This series consist of possibly ready to apply patches extracted from
a former one titled "mtd: rawnand:  ams-delta: Use GPIO API for data I/O".
Remaining patches implementing conversion of data I/O to GPIO have been
postponed until gpiolib is optimized to ensure sufficient performance.


Janusz Krzysztofik (3):
  mtd: rawnand: ams-delta: show parent device in sysfs
  mtd: rawnand: ams-delta: Use private structure
  mtd: rawnand: ams-delta: Set port direction when needed


Changelog:
v4:
[PATCH v4 1/3] mtd: rawnand: ams-delta: show parent device in sysfs
- no changes.
[PATCH v4 2/3] mtd: rawnand: ams-delta: Use private structure
- no changes.
[PATCH v4 3/3] mtd: rawnand: ams-delta: Set port direction when
- formerly submitted as [PATCH v3 5/7], now rebased on top of 2/3 from
  the top of the postponed "[PATCH v3 4/7] mtd: rawnand: ams-delta:
  request data port GPIO resource",
- refactored as requested by Boris Brezillon, thanks.
Rrmoved from this series:
[PATCH v3 3/7] ARM: OMAP1: ams-delta: Provide GPIO lookup table for NAND
 data port
- postponed, will be resubmitted when gpiolib optimizations are ready.
[PATCH v3 4/7] mtd: rawnand: ams-delta: request data port GPIO resource
- postponed, will be resubmitted when gpiolib optimizations are ready.
[PATCH v3 6/7] mtd: rawnand: ams-delta: Simplify pointer resolution
- no longer needed, the idea has been implemented in the refactored 3/3.
[RFC PATCH v3 7/7] mtd: rawnand: ams-delta: use GPIO API for data I/O
- postponed, will be resubmitted when gpiolib optimizations are ready.

v3:
[PATCH v3 1/7] mtd: rawnand: ams-delta: show parent device in sysfs
- renamed and an explanation added based on other similar patches on
 Marek Vasut request, thanks.
[PATCH v3 2/7] mtd: rawnand: ams-delta: Use private structure
- no changes.
[PATCH v3 3/7] ARM: OMAP1: ams-delta: Provide GPIO lookup table for NAND
 data port
- no changes.
[PATCH v3 4/7] mtd: rawnand: ams-delta: request data port GPIO resource
- no changes.
[PATCH v3 5/7] mtd: rawnand: ams-delta: Set port direction when needed
- modified to set port direction only when needed instead of on each
 transfer as suggested by Boris, thanks, though I kept separate 
 *_next_byte() functions to maximize performance as much as possible,
- moved back in front of "mtd: rawnand: ams-delta: use GPIO API for data
 I/O" with a comment added referring to the planned switch to GPIO API.
[PATCH v3 6/7] mtd: rawnand: ams-delta: Simplify pointer resolution
- moved back in front of "mtd: rawnand: ams-delta: use GPIO API for data 
 I/O" on Boris request, thanks.
[RFC PATCH v3 7/7] mtd: rawnand: ams-delta: use GPIO API for data I/O
- rebased back on top of the two mentioned above,
- not intended to apply it yet due to performance issues on Amstrad Delta.
Removed from the series:
[RFC PATCH v2 09/12] gpiolib: Identify GPIO descriptor arrays with direct
 mapping
[RFC PATCH v2 10/12] gpiolib: Introduce bitmap get/set array API extension
[RFC PATCH v2 11/12] mtd: rawnand: ams-delta: Use GPIO API bitmap extension
[RFC PATCH v2 12/12] gpiolib: Add fast processing path to bitmap API functions
- intended to be still iterated in a follow up series until performance
 issues are resolved.
[RFC PATCH v2 06/12] ARM: OMAP1: ams-delta: drop obsolete NAND resources
- postponed until acceptable performance on Amstrad Delta is achieved.

v2:
[RFC PATCH v2 00/12] mtd: rawnand: ams-delta: Use GPIO API for data I/O
- renamed from former [RFC PATCH 0/8] mtd: rawnand: ams-delta: Use
  gpio-omap accessors for data I/O
[RFC PATCH v2 01/12] mtd: rawnand: ams-delta: Assign mtd->dev.parent,
not mtd->owner
- split out from former [RFC PATCH 1/8] on Boris request, thanks.
[RFC PATCH v2 02/12] mtd: rawnand: ams-delta: Use private structure
- remaining part of the former [RFC PATCH 1/8].
[RFC PATCH v2 03/12] ARM: OMAP1: ams-delta: Provide GPIO lookup table
for NAND data port
- split out from former [RFC PATCH 5/8] on Boris requesst, thanks,
[RFC PATCH v2 04/12] mtd: rawnand: ams-delta: request data port GPIO resource
- remaining part of the former [RFC PATCH 5/8],
[RFC PATCH v2 05/12] mtd: rawnand: ams-delta: use GPIO API for data read/write
- reworked from former [RFC PATCH 8/8] on Boris requesst to use pure
  GPIO API, thanks,
- moved up in front of former [RFC PATCH 3/8] on Boris request, thanks.
[RFC PATCH v2 06/12] ARM: OMAP1: ams-delta: drop obsolete NAND resources
- split out from former [RFC PATCH 8/8].
[RFC PATCH v2 07/12] mtd: rawnand: ams-delta: Set port direction once per
transfer
- reworked from former [RFC PATCH 3/8] on top of [RFC PATCH v2 05/12].
[RFC PATCH v2 08/12] mtd: rawnand: ams-delta: Simplify pointer resolution
on read/write
- reworked from former [RFC PATCH 4/8] on top of [RFC PATCH v2 08/12],
- renamed from 'Optimize' to 'Simplify' on Boris request, thanks.
[RFC PA

[PATCH v4 3/3] mtd: rawnand: ams-delta: Set port direction when needed

2018-08-20 Thread Janusz Krzysztofik
In its current shape, the driver sets data port direction before each
byte read/write operation, even during multi-byte transfers.  Improve
performance of the driver by setting the port direction only when
needed.

This optimisation will become particularly important as soon as
planned conversion of the driver to GPIO API for data I/O will be
implemented.

Signed-off-by: Janusz Krzysztofik 
---
 drivers/mtd/nand/raw/ams-delta.c | 68 ++--
 1 file changed, 45 insertions(+), 23 deletions(-)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index 48233d638d2a..4d5e5790f18e 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -45,6 +45,7 @@ struct ams_delta_nand {
struct gpio_desc*gpiod_ale;
struct gpio_desc*gpiod_cle;
void __iomem*io_base;
+   booldata_in;
 };
 
 /*
@@ -72,50 +73,65 @@ static const struct mtd_partition partition_info[] = {
  .size =  3 * SZ_256K },
 };
 
-static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
+static void ams_delta_io_write(struct ams_delta_nand *priv, u8 byte)
 {
-   struct nand_chip *this = mtd_to_nand(mtd);
-   struct ams_delta_nand *priv = nand_get_controller_data(this);
-   void __iomem *io_base = priv->io_base;
-
-   writew(0, io_base + OMAP_MPUIO_IO_CNTL);
-   writew(byte, this->IO_ADDR_W);
+   writew(byte, priv->nand_chip.IO_ADDR_W);
gpiod_set_value(priv->gpiod_nwe, 0);
ndelay(40);
gpiod_set_value(priv->gpiod_nwe, 1);
 }
 
-static u_char ams_delta_read_byte(struct mtd_info *mtd)
+static u8 ams_delta_io_read(struct ams_delta_nand *priv)
 {
-   u_char res;
-   struct nand_chip *this = mtd_to_nand(mtd);
-   struct ams_delta_nand *priv = nand_get_controller_data(this);
-   void __iomem *io_base = priv->io_base;
+   u8 res;
 
gpiod_set_value(priv->gpiod_nre, 0);
ndelay(40);
-   writew(~0, io_base + OMAP_MPUIO_IO_CNTL);
-   res = readw(this->IO_ADDR_R);
+   res = readw(priv->nand_chip.IO_ADDR_R);
gpiod_set_value(priv->gpiod_nre, 1);
 
return res;
 }
 
-static void ams_delta_write_buf(struct mtd_info *mtd, const u_char *buf,
-   int len)
+static void ams_delta_dir_input(struct ams_delta_nand *priv, bool in)
 {
+   writew(in ? ~0 : 0, priv->io_base + OMAP_MPUIO_IO_CNTL);
+   priv->data_in = in;
+}
+
+static void ams_delta_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
+{
+   struct nand_chip *this = mtd_to_nand(mtd);
+   struct ams_delta_nand *priv = nand_get_controller_data(this);
int i;
 
-   for (i=0; idata_in)
+   ams_delta_dir_input(priv, false);
+
+   for (i = 0; i < len; i++)
+   ams_delta_io_write(priv, buf[i]);
 }
 
-static void ams_delta_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+static void ams_delta_read_buf(struct mtd_info *mtd, u8 *buf, int len)
 {
+   struct nand_chip *this = mtd_to_nand(mtd);
+   struct ams_delta_nand *priv = nand_get_controller_data(this);
int i;
 
-   for (i=0; idata_in)
+   ams_delta_dir_input(priv, true);
+
+   for (i = 0; i < len; i++)
+   buf[i] = ams_delta_io_read(priv);
+}
+
+static u8 ams_delta_read_byte(struct mtd_info *mtd)
+{
+   u8 res;
+
+   ams_delta_read_buf(mtd, &res, 1);
+
+   return res;
 }
 
 /*
@@ -138,8 +154,11 @@ static void ams_delta_hwcontrol(struct mtd_info *mtd, int 
cmd,
gpiod_set_value(priv->gpiod_ale, !!(ctrl & NAND_ALE));
}
 
-   if (cmd != NAND_CMD_NONE)
-   ams_delta_write_byte(mtd, cmd);
+   if (cmd != NAND_CMD_NONE) {
+   u8 byte = cmd;
+
+   ams_delta_write_buf(mtd, &byte, 1);
+   }
 }
 
 static int ams_delta_nand_ready(struct mtd_info *mtd)
@@ -262,6 +281,9 @@ static int ams_delta_init(struct platform_device *pdev)
goto out_mtd;
}
 
+   /* Initialize data port direction to a known state */
+   ams_delta_dir_input(priv, true);
+
/* Scan to find existence of the device */
err = nand_scan(mtd, 1);
if (err)
-- 
2.16.4



[PATCH v4 2/3] mtd: rawnand: ams-delta: Use private structure

2018-08-20 Thread Janusz Krzysztofik
Introduce a driver private structure and allocate it on device probe.
Use it for storing nand_chip structure, GPIO descriptors prevoiusly
stored in static variables as well as io_base pointer previously passed
as nand controller data or platform driver data.  Subsequent patches
may populate the structure with more members as needed.

Signed-off-by: Janusz Krzysztofik 
Reviewed-by: Boris Brezillon 
---
 drivers/mtd/nand/raw/ams-delta.c | 126 +--
 1 file changed, 69 insertions(+), 57 deletions(-)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index af313c620264..48233d638d2a 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -34,14 +34,18 @@
 /*
  * MTD structure for E3 (Delta)
  */
-static struct mtd_info *ams_delta_mtd = NULL;
-static struct gpio_desc *gpiod_rdy;
-static struct gpio_desc *gpiod_nce;
-static struct gpio_desc *gpiod_nre;
-static struct gpio_desc *gpiod_nwp;
-static struct gpio_desc *gpiod_nwe;
-static struct gpio_desc *gpiod_ale;
-static struct gpio_desc *gpiod_cle;
+
+struct ams_delta_nand {
+   struct nand_chipnand_chip;
+   struct gpio_desc*gpiod_rdy;
+   struct gpio_desc*gpiod_nce;
+   struct gpio_desc*gpiod_nre;
+   struct gpio_desc*gpiod_nwp;
+   struct gpio_desc*gpiod_nwe;
+   struct gpio_desc*gpiod_ale;
+   struct gpio_desc*gpiod_cle;
+   void __iomem*io_base;
+};
 
 /*
  * Define partitions for flash devices
@@ -71,26 +75,28 @@ static const struct mtd_partition partition_info[] = {
 static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
 {
struct nand_chip *this = mtd_to_nand(mtd);
-   void __iomem *io_base = (void __iomem *)nand_get_controller_data(this);
+   struct ams_delta_nand *priv = nand_get_controller_data(this);
+   void __iomem *io_base = priv->io_base;
 
writew(0, io_base + OMAP_MPUIO_IO_CNTL);
writew(byte, this->IO_ADDR_W);
-   gpiod_set_value(gpiod_nwe, 0);
+   gpiod_set_value(priv->gpiod_nwe, 0);
ndelay(40);
-   gpiod_set_value(gpiod_nwe, 1);
+   gpiod_set_value(priv->gpiod_nwe, 1);
 }
 
 static u_char ams_delta_read_byte(struct mtd_info *mtd)
 {
u_char res;
struct nand_chip *this = mtd_to_nand(mtd);
-   void __iomem *io_base = (void __iomem *)nand_get_controller_data(this);
+   struct ams_delta_nand *priv = nand_get_controller_data(this);
+   void __iomem *io_base = priv->io_base;
 
-   gpiod_set_value(gpiod_nre, 0);
+   gpiod_set_value(priv->gpiod_nre, 0);
ndelay(40);
writew(~0, io_base + OMAP_MPUIO_IO_CNTL);
res = readw(this->IO_ADDR_R);
-   gpiod_set_value(gpiod_nre, 1);
+   gpiod_set_value(priv->gpiod_nre, 1);
 
return res;
 }
@@ -123,11 +129,13 @@ static void ams_delta_read_buf(struct mtd_info *mtd, 
u_char *buf, int len)
 static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
 {
+   struct nand_chip *this = mtd_to_nand(mtd);
+   struct ams_delta_nand *priv = nand_get_controller_data(this);
 
if (ctrl & NAND_CTRL_CHANGE) {
-   gpiod_set_value(gpiod_nce, !(ctrl & NAND_NCE));
-   gpiod_set_value(gpiod_cle, !!(ctrl & NAND_CLE));
-   gpiod_set_value(gpiod_ale, !!(ctrl & NAND_ALE));
+   gpiod_set_value(priv->gpiod_nce, !(ctrl & NAND_NCE));
+   gpiod_set_value(priv->gpiod_cle, !!(ctrl & NAND_CLE));
+   gpiod_set_value(priv->gpiod_ale, !!(ctrl & NAND_ALE));
}
 
if (cmd != NAND_CMD_NONE)
@@ -136,7 +144,10 @@ static void ams_delta_hwcontrol(struct mtd_info *mtd, int 
cmd,
 
 static int ams_delta_nand_ready(struct mtd_info *mtd)
 {
-   return gpiod_get_value(gpiod_rdy);
+   struct nand_chip *this = mtd_to_nand(mtd);
+   struct ams_delta_nand *priv = nand_get_controller_data(this);
+
+   return gpiod_get_value(priv->gpiod_rdy);
 }
 
 
@@ -145,7 +156,9 @@ static int ams_delta_nand_ready(struct mtd_info *mtd)
  */
 static int ams_delta_init(struct platform_device *pdev)
 {
+   struct ams_delta_nand *priv;
struct nand_chip *this;
+   struct mtd_info *mtd;
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
void __iomem *io_base;
int err = 0;
@@ -154,15 +167,16 @@ static int ams_delta_init(struct platform_device *pdev)
return -ENXIO;
 
/* Allocate memory for MTD device structure and private data */
-   this = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
-   if (!this) {
+   priv = devm_kzalloc(&pdev->dev, sizeof(struct ams_delta_nand),
+   GFP_KERNEL);
+   if (!priv) {
pr_warn("Unable to allocate E3 NAND MTD de

[PATCH v3 1/3] mtd: rawnand: Provide helper for polling GPIO R/B pin

2018-10-15 Thread Janusz Krzysztofik
Each controller driver having access to NAND R/B pin over GPIO would
have to reimplement the polling loop otherwise.

Suggested-by: Boris Brezillon 
Signed-off-by: Janusz Krzysztofik 
Reviewed-by: Boris Brezillon 
---
Changelog:
v3:
- don't surround added code with #ifdef CONFIG_GPIOLIB - sugeested by
  Boris Brezillon - thanks,
- drop inadequate comment on calling ->exec_op() recursively - catched
  by Boris Brezillon, thanks,
- drop redundant commend from header file - suggensted by Boris
  Brezillon - thanks,
- update comment on waiting for R/B pin rather than command completion
v2:
New patch - v1 consisted of only one patch reusing legacy helper

 drivers/mtd/nand/raw/nand_base.c | 31 +++
 include/linux/mtd/rawnand.h  |  4 
 2 files changed, 35 insertions(+)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 05bd0779fe9b..0d5a2dc59b8d 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -45,6 +45,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "internals.h"
 
@@ -531,6 +532,36 @@ int nand_soft_waitrdy(struct nand_chip *chip, unsigned 
long timeout_ms)
 };
 EXPORT_SYMBOL_GPL(nand_soft_waitrdy);
 
+/**
+ * nand_gpio_waitrdy - Poll R/B GPIO pin until ready
+ * @chip: NAND chip structure
+ * @gpiod: GPIO descriptor of R/B pin
+ * @timeout_ms: Timeout in ms
+ *
+ * Poll the R/B GPIO pin until it becomes ready. If that does not happen
+ * whitin the specified timeout, -ETIMEDOUT is returned.
+ *
+ * This helper is intended to be used when the controller has access to the
+ * NAND R/B pin over GPIO.
+ *
+ * Return 0 if the R/B pin indicates chip is ready, a negative error otherwise.
+ */
+int nand_gpio_waitrdy(struct nand_chip *chip, struct gpio_desc *gpiod,
+ unsigned long timeout_ms)
+{
+   /* Wait until R/B pin indicates chip is ready or timeout occurs */
+   timeout_ms = jiffies + msecs_to_jiffies(timeout_ms);
+   do {
+   if (gpiod_get_value_cansleep(gpiod))
+   return 0;
+
+   cond_resched();
+   } while (time_before(jiffies, timeout_ms));
+
+   return gpiod_get_value_cansleep(gpiod) ? 0 : -ETIMEDOUT;
+};
+EXPORT_SYMBOL_GPL(nand_gpio_waitrdy);
+
 /**
  * panic_nand_get_device - [GENERIC] Get chip for selected access
  * @chip: the nand chip descriptor
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index e10b126e148f..4e91a70ede10 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1346,4 +1346,8 @@ void nand_release(struct nand_chip *chip);
  */
 int nand_soft_waitrdy(struct nand_chip *chip, unsigned long timeout_ms);
 
+struct gpio_desc;
+int nand_gpio_waitrdy(struct nand_chip *chip, struct gpio_desc *gpiod,
+ unsigned long timeout_ms);
+
 #endif /* __LINUX_MTD_RAWNAND_H */
-- 
2.16.4



[PATCH v3 3/3] mtd: rawnand: ams-delta: Convert the driver to ->exec_op()

2018-10-15 Thread Janusz Krzysztofik
Replace legacy callbacks with ->select_chip() and ->exec_op().

Suggested-by: Boris Brezillon 
Signed-off-by: Janusz Krzysztofik 
Reviewed-by: Boris Brezillon 
---
Changelog:
v3:
- former PATCH 2/2 from which PATCH v3 2/3 has been split out,
- added missing return on check_only - requested by Boris Brezillon,
  thanks
v2:
- replace references to legacy structure .IO_ADDR_R/W members with 
  runtime calculated values - requested by Boris Brezillon, thanks!
- modify ams_delta_read/write_buf() functions, no longer exposed as 
  callbacks, to accept driver private structure instead of struct 
  nand_chip,
- use newly introduced nand_gpio_waitrdy() helper instead of legacy 
  nand_wait_ready() - suggested by Boris Brezillon, thanks!
- remove no longer needed ams_delta_dev_ready() legacy callback and
  legacy structure member .chip_delay.

 drivers/mtd/nand/raw/ams-delta.c | 100 ++-
 1 file changed, 56 insertions(+), 44 deletions(-)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index 46193db6d368..9ca70aab199d 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -99,10 +99,9 @@ static void ams_delta_dir_input(struct ams_delta_nand *priv, 
bool in)
priv->data_in = in;
 }
 
-static void ams_delta_write_buf(struct nand_chip *this, const u_char *buf,
+static void ams_delta_write_buf(struct ams_delta_nand *priv, const u_char *buf,
int len)
 {
-   struct ams_delta_nand *priv = nand_get_controller_data(this);
int i;
 
if (priv->data_in)
@@ -112,9 +111,9 @@ static void ams_delta_write_buf(struct nand_chip *this, 
const u_char *buf,
ams_delta_io_write(priv, buf[i]);
 }
 
-static void ams_delta_read_buf(struct nand_chip *this, u_char *buf, int len)
+static void ams_delta_read_buf(struct ams_delta_nand *priv, u_char *buf,
+  int len)
 {
-   struct ams_delta_nand *priv = nand_get_controller_data(this);
int i;
 
if (!priv->data_in)
@@ -124,46 +123,66 @@ static void ams_delta_read_buf(struct nand_chip *this, 
u_char *buf, int len)
buf[i] = ams_delta_io_read(priv);
 }
 
-static u_char ams_delta_read_byte(struct nand_chip *this)
-{
-   u_char res;
-
-   ams_delta_read_buf(this, &res, 1);
-
-   return res;
-}
-
-/*
- * Command control function
- *
- * ctrl:
- * NAND_NCE: bit 0 -> bit 2
- * NAND_CLE: bit 1 -> bit 7
- * NAND_ALE: bit 2 -> bit 6
- */
-static void ams_delta_hwcontrol(struct nand_chip *this, int cmd,
-   unsigned int ctrl)
+static void ams_delta_select_chip(struct nand_chip *this, int n)
 {
struct ams_delta_nand *priv = nand_get_controller_data(this);
 
-   if (ctrl & NAND_CTRL_CHANGE) {
-   gpiod_set_value(priv->gpiod_nce, !(ctrl & NAND_NCE));
-   gpiod_set_value(priv->gpiod_cle, !!(ctrl & NAND_CLE));
-   gpiod_set_value(priv->gpiod_ale, !!(ctrl & NAND_ALE));
-   }
-
-   if (cmd != NAND_CMD_NONE) {
-   u_char byte = cmd;
+   if (n > 0)
+   return;
 
-   ams_delta_write_buf(this, &byte, 1);
-   }
+   gpiod_set_value(priv->gpiod_nce, n < 0);
 }
 
-static int ams_delta_nand_ready(struct nand_chip *this)
+static int ams_delta_exec_op(struct nand_chip *this,
+const struct nand_operation *op, bool check_only)
 {
struct ams_delta_nand *priv = nand_get_controller_data(this);
+   const struct nand_op_instr *instr;
+   int ret = 0;
+
+   if (check_only)
+   return 0;
+
+   for (instr = op->instrs; instr < op->instrs + op->ninstrs; instr++) {
+
+   switch (instr->type) {
+   case NAND_OP_CMD_INSTR:
+   gpiod_set_value(priv->gpiod_cle, 1);
+   ams_delta_write_buf(priv, &instr->ctx.cmd.opcode, 1);
+   gpiod_set_value(priv->gpiod_cle, 0);
+   break;
+
+   case NAND_OP_ADDR_INSTR:
+   gpiod_set_value(priv->gpiod_ale, 1);
+   ams_delta_write_buf(priv, instr->ctx.addr.addrs,
+   instr->ctx.addr.naddrs);
+   gpiod_set_value(priv->gpiod_ale, 0);
+   break;
+
+   case NAND_OP_DATA_IN_INSTR:
+   ams_delta_read_buf(priv, instr->ctx.data.buf.in,
+  instr->ctx.data.len);
+   break;
+
+   case NAND_OP_DATA_OUT_INSTR:
+   ams_delta_write_buf(priv, instr->ctx.data.buf.out,
+   instr->ctx.data.len);
+   break;
+
+   case NAND_OP_WAITRDY_INSTR:

[PATCH v3 2/3] mtd: rawnand: ams-delta: Stop using legacy .IOADDR_R/W

2018-10-15 Thread Janusz Krzysztofik
Replace use of legacy .IOADDR_R/W with runtime calculations based on
priv->io_base.

Suggested-by: Boris Brezillon 
Signed-off-by: Janusz Krzysztofik 
Reviewed-by: Boris Brezillon 
---
Changelog:
v3:
New patch, split out from former PATCH 2/2 on Boris request - thanks

 drivers/mtd/nand/raw/ams-delta.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index 5ba180a291eb..46193db6d368 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -75,7 +75,7 @@ static const struct mtd_partition partition_info[] = {
 
 static void ams_delta_io_write(struct ams_delta_nand *priv, u_char byte)
 {
-   writew(byte, priv->nand_chip.legacy.IO_ADDR_W);
+   writew(byte, priv->io_base + OMAP_MPUIO_OUTPUT);
gpiod_set_value(priv->gpiod_nwe, 0);
ndelay(40);
gpiod_set_value(priv->gpiod_nwe, 1);
@@ -87,7 +87,7 @@ static u_char ams_delta_io_read(struct ams_delta_nand *priv)
 
gpiod_set_value(priv->gpiod_nre, 0);
ndelay(40);
-   res = readw(priv->nand_chip.legacy.IO_ADDR_R);
+   res = readw(priv->io_base + OMAP_MPUIO_INPUT_LATCH);
gpiod_set_value(priv->gpiod_nre, 1);
 
return res;
@@ -211,8 +211,6 @@ static int ams_delta_init(struct platform_device *pdev)
nand_set_controller_data(this, priv);
 
/* Set address of NAND IO lines */
-   this->legacy.IO_ADDR_R = io_base + OMAP_MPUIO_INPUT_LATCH;
-   this->legacy.IO_ADDR_W = io_base + OMAP_MPUIO_OUTPUT;
this->legacy.read_byte = ams_delta_read_byte;
this->legacy.write_buf = ams_delta_write_buf;
this->legacy.read_buf = ams_delta_read_buf;
-- 
2.16.4



[PATCH] ARM: OMAP1: ams-delta: make board header file local to mach-omap1

2018-11-05 Thread Janusz Krzysztofik
Now as the board header file is no longer included by drivers, move it
to the root directory of mach-omap1.

Signed-off-by: Janusz Krzysztofik 
---
Changelog:
v4:
- rebased on top of v4.20-rc1
- resubmitted as a standalone patch, other patches of the series it
  depended on have been already applied

v3:
- rebased on top of v4.19-rc1
- submitted as PATCH v3 3/3

v2:
- resent as PATCH v2 3/3

Initially submitted in series as PATCH 6/6


 arch/arm/mach-omap1/ams-delta-fiq-handler.S  | 2 +-
 arch/arm/mach-omap1/ams-delta-fiq.c  | 3 +--
 arch/arm/mach-omap1/board-ams-delta.c| 2 +-
 arch/arm/mach-omap1/{include/mach => }/board-ams-delta.h | 2 +-
 4 files changed, 4 insertions(+), 5 deletions(-)
 rename arch/arm/mach-omap1/{include/mach => }/board-ams-delta.h (97%)

diff --git a/arch/arm/mach-omap1/ams-delta-fiq-handler.S 
b/arch/arm/mach-omap1/ams-delta-fiq-handler.S
index e3faa0274b56..7c9fb7fe0070 100644
--- a/arch/arm/mach-omap1/ams-delta-fiq-handler.S
+++ b/arch/arm/mach-omap1/ams-delta-fiq-handler.S
@@ -18,9 +18,9 @@
 #include 
 
 #include 
-#include 
 
 #include "ams-delta-fiq.h"
+#include "board-ams-delta.h"
 #include "iomap.h"
 #include "soc.h"
 
diff --git a/arch/arm/mach-omap1/ams-delta-fiq.c 
b/arch/arm/mach-omap1/ams-delta-fiq.c
index b0dc7ddf5877..14c3d3f5255e 100644
--- a/arch/arm/mach-omap1/ams-delta-fiq.c
+++ b/arch/arm/mach-omap1/ams-delta-fiq.c
@@ -22,11 +22,10 @@
 #include 
 #include 
 
-#include 
-
 #include 
 
 #include "ams-delta-fiq.h"
+#include "board-ams-delta.h"
 
 static struct fiq_handler fh = {
.name   = "ams-delta-fiq"
diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index 3d191fd52910..b8acc9912a58 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -36,7 +36,6 @@
 #include 
 #include 
 
-#include 
 #include 
 #include 
 
@@ -45,6 +44,7 @@
 #include 
 
 #include "ams-delta-fiq.h"
+#include "board-ams-delta.h"
 #include "iomap.h"
 #include "common.h"
 
diff --git a/arch/arm/mach-omap1/include/mach/board-ams-delta.h 
b/arch/arm/mach-omap1/board-ams-delta.h
similarity index 97%
rename from arch/arm/mach-omap1/include/mach/board-ams-delta.h
rename to arch/arm/mach-omap1/board-ams-delta.h
index 3b2d8019238a..a74a306d7e77 100644
--- a/arch/arm/mach-omap1/include/mach/board-ams-delta.h
+++ b/arch/arm/mach-omap1/board-ams-delta.h
@@ -1,5 +1,5 @@
 /*
- * arch/arm/plat-omap/include/mach/board-ams-delta.h
+ * arch/arm/mach-omap1/board-ams-delta.h
  *
  * Copyright (C) 2006 Jonathan McDowell 
  *
-- 
2.16.4



[PATCH] ARM: OMAP1: ams-delta: Provide GPIO lookup table for LED device

2018-11-05 Thread Janusz Krzysztofik
Global GPIO numbers no longer have to be passed to leds-gpio driver,
replace their assignment with a lookup table.

Signed-off-by: Janusz Krzysztofik 
---
 arch/arm/mach-omap1/board-ams-delta.c | 95 ++-
 1 file changed, 26 insertions(+), 69 deletions(-)

diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index b8acc9912a58..19e0c071d675 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -371,15 +371,9 @@ static struct gpiod_lookup_table ams_delta_lcd_gpio_table 
= {
},
 };
 
-/*
- * Dynamically allocated GPIO numbers must be obtained fromm GPIO device
- * before they can be put in the gpio_led table.  Before that happens,
- * initialize the table with invalid GPIO numbers, not 0.
- */
 static struct gpio_led gpio_leds[] __initdata = {
[LATCH1_PIN_LED_CAMERA] = {
.name= "camera",
-   .gpio= -EINVAL,
.default_state   = LEDS_GPIO_DEFSTATE_OFF,
 #ifdef CONFIG_LEDS_TRIGGERS
.default_trigger = "ams_delta_camera",
@@ -387,27 +381,22 @@ static struct gpio_led gpio_leds[] __initdata = {
},
[LATCH1_PIN_LED_ADVERT] = {
.name= "advert",
-   .gpio= -EINVAL,
.default_state   = LEDS_GPIO_DEFSTATE_OFF,
},
[LATCH1_PIN_LED_MAIL] = {
.name= "email",
-   .gpio= -EINVAL,
.default_state   = LEDS_GPIO_DEFSTATE_OFF,
},
[LATCH1_PIN_LED_HANDSFREE] = {
.name= "handsfree",
-   .gpio= -EINVAL,
.default_state   = LEDS_GPIO_DEFSTATE_OFF,
},
[LATCH1_PIN_LED_VOICEMAIL] = {
.name= "voicemail",
-   .gpio= -EINVAL,
.default_state   = LEDS_GPIO_DEFSTATE_OFF,
},
[LATCH1_PIN_LED_VOICE] = {
.name= "voice",
-   .gpio= -EINVAL,
.default_state   = LEDS_GPIO_DEFSTATE_OFF,
},
 };
@@ -417,6 +406,24 @@ static const struct gpio_led_platform_data leds_pdata 
__initconst = {
.num_leds   = ARRAY_SIZE(gpio_leds),
 };
 
+static struct gpiod_lookup_table leds_gpio_table = {
+   .table = {
+   GPIO_LOOKUP_IDX(LATCH1_LABEL, LATCH1_PIN_LED_CAMERA, NULL,
+   LATCH1_PIN_LED_CAMERA, 0),
+   GPIO_LOOKUP_IDX(LATCH1_LABEL, LATCH1_PIN_LED_ADVERT, NULL,
+   LATCH1_PIN_LED_ADVERT, 0),
+   GPIO_LOOKUP_IDX(LATCH1_LABEL, LATCH1_PIN_LED_MAIL, NULL,
+   LATCH1_PIN_LED_MAIL, 0),
+   GPIO_LOOKUP_IDX(LATCH1_LABEL, LATCH1_PIN_LED_HANDSFREE, NULL,
+   LATCH1_PIN_LED_HANDSFREE, 0),
+   GPIO_LOOKUP_IDX(LATCH1_LABEL, LATCH1_PIN_LED_VOICEMAIL, NULL,
+   LATCH1_PIN_LED_VOICEMAIL, 0),
+   GPIO_LOOKUP_IDX(LATCH1_LABEL, LATCH1_PIN_LED_VOICE, NULL,
+   LATCH1_PIN_LED_VOICE, 0),
+   { },
+   },
+};
+
 static struct i2c_board_info ams_delta_camera_board_info[] = {
{
I2C_BOARD_INFO("ov6650", 0x60),
@@ -677,6 +684,8 @@ static void __init ams_delta_latch2_init(void)
 
 static void __init ams_delta_init(void)
 {
+   struct platform_device *leds_pdev;
+
/* mux pins for uarts */
omap_cfg_reg(UART1_TX);
omap_cfg_reg(UART1_RTS);
@@ -740,6 +749,12 @@ static void __init ams_delta_init(void)
gpiod_add_lookup_tables(ams_delta_gpio_tables,
ARRAY_SIZE(ams_delta_gpio_tables));
 
+   leds_pdev = gpio_led_register_device(PLATFORM_DEVID_NONE, &leds_pdata);
+   if (!IS_ERR(leds_pdev)) {
+   leds_gpio_table.dev_id = dev_name(&leds_pdev->dev);
+   gpiod_add_lookup_table(&leds_gpio_table);
+   }
+
omap_writew(omap_readw(ARM_RSTCT1) | 0x0004, ARM_RSTCT1);
 
omapfb_set_lcd_config(&ams_delta_lcd_config);
@@ -793,64 +808,6 @@ static struct platform_device ams_delta_modem_device = {
},
 };
 
-/*
- * leds-gpio driver doesn't make use of GPIO lookup tables,
- * it has to be provided with GPIO numbers over platform data
- * if GPIO descriptor info can't be obtained from device tree.
- * We could either define GPIO lookup tables and use them on behalf
- * of the leds-gpio device, or we can use GPIO driver level methods
- * for identification of GPIO numbers as long as we don't support
- * device tree.  Let's do the latter.
- */
-static void __init ams_delta_led_init(struct gpio_chip *chip)
-{
-   struct gpio_desc *gpiod;
-   int i;
-
-   f

[PATCH 1/3] ARM: OMAP1: ams-delta: Drop board specific global GPIO numbers

2018-11-07 Thread Janusz Krzysztofik
As all users of the board specific GPIO pins have been converted from
legacy integer-based to descriptor-based interface, there is no longer
a need to maintain statically assigned GPIO pin numbers.  Drop support
for that.

Signed-off-by: Janusz Krzysztofik 
---
 arch/arm/mach-omap1/board-ams-delta.c |  3 ---
 arch/arm/mach-omap1/board-ams-delta.h | 16 
 2 files changed, 19 deletions(-)

diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index 19e0c071d675..a6986a83a916 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -167,7 +167,6 @@ static struct omap_usb_config ams_delta_usb_config 
__initdata = {
.pins[0]= 2,
 };
 
-#define LATCH1_GPIO_BASE   232
 #define LATCH1_NGPIO   8
 
 static struct resource latch1_resources[] = {
@@ -183,7 +182,6 @@ static struct resource latch1_resources[] = {
 
 static struct bgpio_pdata latch1_pdata = {
.label  = LATCH1_LABEL,
-   .base   = LATCH1_GPIO_BASE,
.ngpio  = LATCH1_NGPIO,
 };
 
@@ -219,7 +217,6 @@ static struct resource latch2_resources[] = {
 
 static struct bgpio_pdata latch2_pdata = {
.label  = LATCH2_LABEL,
-   .base   = AMS_DELTA_LATCH2_GPIO_BASE,
.ngpio  = AMS_DELTA_LATCH2_NGPIO,
 };
 
diff --git a/arch/arm/mach-omap1/board-ams-delta.h 
b/arch/arm/mach-omap1/board-ams-delta.h
index a74a306d7e77..06e4c64a47f8 100644
--- a/arch/arm/mach-omap1/board-ams-delta.h
+++ b/arch/arm/mach-omap1/board-ams-delta.h
@@ -41,22 +41,6 @@
 #define AMS_DELTA_GPIO_PIN_CONFIG  11
 #define AMS_DELTA_GPIO_PIN_NAND_RB 12
 
-#define AMS_DELTA_GPIO_PIN_LCD_VBLEN   240
-#define AMS_DELTA_GPIO_PIN_LCD_NDISP   241
-#define AMS_DELTA_GPIO_PIN_NAND_NCE242
-#define AMS_DELTA_GPIO_PIN_NAND_NRE243
-#define AMS_DELTA_GPIO_PIN_NAND_NWP244
-#define AMS_DELTA_GPIO_PIN_NAND_NWE245
-#define AMS_DELTA_GPIO_PIN_NAND_ALE246
-#define AMS_DELTA_GPIO_PIN_NAND_CLE247
-#define AMS_DELTA_GPIO_PIN_KEYBRD_PWR  248
-#define AMS_DELTA_GPIO_PIN_KEYBRD_DATAOUT  249
-#define AMS_DELTA_GPIO_PIN_SCARD_RSTIN 250
-#define AMS_DELTA_GPIO_PIN_SCARD_CMDVCC251
-#define AMS_DELTA_GPIO_PIN_MODEM_NRESET252
-#define AMS_DELTA_GPIO_PIN_MODEM_CODEC 253
-
-#define AMS_DELTA_LATCH2_GPIO_BASE AMS_DELTA_GPIO_PIN_LCD_VBLEN
 #define AMS_DELTA_LATCH2_NGPIO 16
 
 #endif /* CONFIG_MACH_AMS_DELTA */
-- 
2.16.4



[PATCH 0/3] ARN: OMAP1: ams-delta: Post-GPIO-refresh cleanups

2018-11-07 Thread Janusz Krzysztofik


Janusz Krzysztofik (3):
  ARM: OMAP1: ams-delta: Drop board specific global GPIO numbers
  ARM: OMAP1: ams-delta: Drop unused symbols from the board header
  ARM: OMAP1: ams-delta: Move AMS_DELTA_LATCH2_NGPIO to the board file

 board-ams-delta.c |9 -
 board-ams-delta.h |   22 --
 2 files changed, 4 insertions(+), 27 deletions(-)



[PATCH 3/3] ARM: OMAP1: ams-delta: Move AMS_DELTA_LATCH2_NGPIO to the board file

2018-11-07 Thread Janusz Krzysztofik
That symbol is not used outside the board file, there is no need to
keep it in the board header.

Signed-off-by: Janusz Krzysztofik 
---
 arch/arm/mach-omap1/board-ams-delta.c | 6 --
 arch/arm/mach-omap1/board-ams-delta.h | 2 --
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index a6986a83a916..1947bc63074e 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -204,11 +204,13 @@ static struct platform_device latch1_gpio_device = {
 #define LATCH1_PIN_DOCKIT1 6
 #define LATCH1_PIN_DOCKIT2 7
 
+#define LATCH2_NGPIO   16
+
 static struct resource latch2_resources[] = {
[0] = {
.name   = "dat",
.start  = LATCH2_PHYS,
-   .end= LATCH2_PHYS + (AMS_DELTA_LATCH2_NGPIO - 1) / 8,
+   .end= LATCH2_PHYS + (LATCH2_NGPIO - 1) / 8,
.flags  = IORESOURCE_MEM,
},
 };
@@ -217,7 +219,7 @@ static struct resource latch2_resources[] = {
 
 static struct bgpio_pdata latch2_pdata = {
.label  = LATCH2_LABEL,
-   .ngpio  = AMS_DELTA_LATCH2_NGPIO,
+   .ngpio  = LATCH2_NGPIO,
 };
 
 static struct platform_device latch2_gpio_device = {
diff --git a/arch/arm/mach-omap1/board-ams-delta.h 
b/arch/arm/mach-omap1/board-ams-delta.h
index 2c3aff824cf0..b5c4a373b905 100644
--- a/arch/arm/mach-omap1/board-ams-delta.h
+++ b/arch/arm/mach-omap1/board-ams-delta.h
@@ -37,8 +37,6 @@
 #define AMS_DELTA_GPIO_PIN_CONFIG  11
 #define AMS_DELTA_GPIO_PIN_NAND_RB 12
 
-#define AMS_DELTA_LATCH2_NGPIO 16
-
 #endif /* CONFIG_MACH_AMS_DELTA */
 
 #endif /* __ASM_ARCH_OMAP_AMS_DELTA_H */
-- 
2.16.4



[PATCH 2/3] ARM: OMAP1: ams-delta: Drop unused symbols from the board header

2018-11-07 Thread Janusz Krzysztofik
Those bitmap symbols defining pins of latch2 register, used with
read()/write() calls before the latch was converted to a GPIO device,
have been obsoleted by integer symbols defined inside the board file.

Signed-off-by: Janusz Krzysztofik 
---
 arch/arm/mach-omap1/board-ams-delta.h | 4 
 1 file changed, 4 deletions(-)

diff --git a/arch/arm/mach-omap1/board-ams-delta.h 
b/arch/arm/mach-omap1/board-ams-delta.h
index 06e4c64a47f8..2c3aff824cf0 100644
--- a/arch/arm/mach-omap1/board-ams-delta.h
+++ b/arch/arm/mach-omap1/board-ams-delta.h
@@ -28,10 +28,6 @@
 
 #if defined (CONFIG_MACH_AMS_DELTA)
 
-#define AMD_DELTA_LATCH2_SCARD_RSTIN   0x0400
-#define AMD_DELTA_LATCH2_SCARD_CMDVCC  0x0800
-#define AMS_DELTA_LATCH2_MODEM_CODEC   0x2000
-
 #define AMS_DELTA_GPIO_PIN_KEYBRD_DATA 0
 #define AMS_DELTA_GPIO_PIN_KEYBRD_CLK  1
 #define AMS_DELTA_GPIO_PIN_MODEM_IRQ   2
-- 
2.16.4



[PATCH] ARM: OMAP1: ams-delta: Fix possible use of uninitialized field

2018-11-07 Thread Janusz Krzysztofik
While playing with initialization order of modem device, it has been
discovered that under some circumstances (early console init, I
believe) its .pm() callback may be called before the
uart_port->private_data pointer is initialized from
plat_serial8250_port->private_data, resulting in NULL pointer
dereference.  Fix it by checking for uninitialized pointer before using
it in modem_pm().

Fixes: aabf31737a6a ("ARM: OMAP1: ams-delta: update the modem to use regulator 
API")
Signed-off-by: Janusz Krzysztofik 
---
 arch/arm/mach-omap1/board-ams-delta.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/mach-omap1/board-ams-delta.c 
b/arch/arm/mach-omap1/board-ams-delta.c
index 1947bc63074e..17e0b386e1b2 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -764,6 +764,9 @@ static void modem_pm(struct uart_port *port, unsigned int 
state, unsigned old)
struct modem_private_data *priv = port->private_data;
int ret;
 
+   if (!priv)
+   return;
+
if (IS_ERR(priv->regulator))
return;
 
-- 
2.16.4



[RFT PATCH] mmc: pwrseq_simple: Fix incorrect handling of GPIO bitmap

2018-10-12 Thread Janusz Krzysztofik
Commit b9762bebc633 ("gpiolib: Pass bitmaps, not integer arrays, to
get/set array") changed the way GPIO values are passed to
gpiod_get/set_array_value() and friends.  The new code introduced into
mmc_pwrseq_simple_set_gpios_value() incorrectly interpretes the 'value'
argument as a bitmap of GPIO values and assigns it directly to the
'values' bitmap variable passed to gpiod_set_array_value_cansleep()
instead of filling that bitmap with bits equal to the 'value' argument.
As a result, only member 0 of the array is handled correctly.

Moreover, wrong assumption is taken about the 'values' bitmap size not
exceding the number of bits of the 'value' argument type.

Fix it.

Signed-off-by: Janusz Krzysztofik 
---
Hi,

I think that patch has been missed while we were resolving issues 
related to GPIO fast bitmap processing.  Since all issues other than the 
one addreessed by this patch have been been hopefully identified and 
fixed, GPIO tree seems now to be in good shape in regard to that. 
However, I believe pwrseq_simple is still broken.  Hence, I'm 
resubmitting this patch to Ulf for inclusion in MMC tree, Cc: many other 
people who are kindly requested to test it if possible.

I've identified the following DT files representing devices which may be 
affected (have more than one GPIO assigned to pwrseq_simple):
- arch/arm/boot/dts/imx6qdl-sr-som-brcm.dtsi
- arch/arm/boot/dts/exynos5250-snow-common.dtsi
- arch/arm/boot/dts/imx6sl-warp.dts
- arch/arm/boot/dts/omap3-igep0030.dts
- arch/arm/boot/dts/omap3-igep0020.dts
- arch/arm/boot/dts/rk3036-kylin.dts
- arch/arm64/boot/dts/rockchip/rk3368-r88.dts
- arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi

Please start with checking if pwrseq_simple from linux-next works for 
you and if not, please test if this patch fixes the issue.

Thanks,
Janusz


 drivers/mmc/core/pwrseq_simple.c | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c
index 7f882a2bb872..ece34c734693 100644
--- a/drivers/mmc/core/pwrseq_simple.c
+++ b/drivers/mmc/core/pwrseq_simple.c
@@ -40,13 +40,22 @@ static void mmc_pwrseq_simple_set_gpios_value(struct 
mmc_pwrseq_simple *pwrseq,
struct gpio_descs *reset_gpios = pwrseq->reset_gpios;
 
if (!IS_ERR(reset_gpios)) {
-   DECLARE_BITMAP(values, BITS_PER_TYPE(value));
+   unsigned long *values;
int nvalues = reset_gpios->ndescs;
 
-   values[0] = value;
+   values = bitmap_alloc(nvalues, GFP_KERNEL);
+   if (!values)
+   return;
+
+   if (value)
+   bitmap_fill(values, nvalues);
+   else
+   bitmap_zero(values, nvalues);
 
gpiod_set_array_value_cansleep(nvalues, reset_gpios->desc,
   reset_gpios->info, values);
+
+   kfree(values);
}
 }
 
-- 
2.16.4



[PATCH v2 2/2] mtd: rawnand: ams-delta: Use ->exec_op()

2018-10-12 Thread Janusz Krzysztofik
Replace legacy callbacks with ->select_chip() and ->exec_op().

In order to remove any references to legacy structure members, use of 
.IO_ADDR_R/W has been replaced wit runtime calculations based on 
priv->io_base.

Suggested-by: Boris Brezillon 
Signed-off-by: Janusz Krzysztofik 
---
Changelog:
v2:
- replace references to legacy structure .IO_ADDR_R/W members with 
  runtime calculated values - requested by Boris Brezillon, thanks!
- modify ams_delta_read/write_buf() functions, no longer exposed as 
  callbacks, to accept driver private structure instead of struct 
  nand_chip,
- use newly introduced nand_gpio_waitrdy() helper instead of legacy 
  nand_wait_ready() - suggested by Boris Brezillon, thanks!
- remove no longer needed ams_delta_dev_ready() legacy callback and
  legacy structure member .chip_delay.

 drivers/mtd/nand/raw/ams-delta.c | 103 +--
 1 file changed, 55 insertions(+), 48 deletions(-)

diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index 5ba180a291eb..f0745aeecb1c 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -75,7 +75,7 @@ static const struct mtd_partition partition_info[] = {
 
 static void ams_delta_io_write(struct ams_delta_nand *priv, u_char byte)
 {
-   writew(byte, priv->nand_chip.legacy.IO_ADDR_W);
+   writew(byte, priv->io_base + OMAP_MPUIO_OUTPUT);
gpiod_set_value(priv->gpiod_nwe, 0);
ndelay(40);
gpiod_set_value(priv->gpiod_nwe, 1);
@@ -87,7 +87,7 @@ static u_char ams_delta_io_read(struct ams_delta_nand *priv)
 
gpiod_set_value(priv->gpiod_nre, 0);
ndelay(40);
-   res = readw(priv->nand_chip.legacy.IO_ADDR_R);
+   res = readw(priv->io_base + OMAP_MPUIO_INPUT_LATCH);
gpiod_set_value(priv->gpiod_nre, 1);
 
return res;
@@ -99,10 +99,9 @@ static void ams_delta_dir_input(struct ams_delta_nand *priv, 
bool in)
priv->data_in = in;
 }
 
-static void ams_delta_write_buf(struct nand_chip *this, const u_char *buf,
+static void ams_delta_write_buf(struct ams_delta_nand *priv, const u_char *buf,
int len)
 {
-   struct ams_delta_nand *priv = nand_get_controller_data(this);
int i;
 
if (priv->data_in)
@@ -112,9 +111,9 @@ static void ams_delta_write_buf(struct nand_chip *this, 
const u_char *buf,
ams_delta_io_write(priv, buf[i]);
 }
 
-static void ams_delta_read_buf(struct nand_chip *this, u_char *buf, int len)
+static void ams_delta_read_buf(struct ams_delta_nand *priv, u_char *buf,
+  int len)
 {
-   struct ams_delta_nand *priv = nand_get_controller_data(this);
int i;
 
if (!priv->data_in)
@@ -124,46 +123,63 @@ static void ams_delta_read_buf(struct nand_chip *this, 
u_char *buf, int len)
buf[i] = ams_delta_io_read(priv);
 }
 
-static u_char ams_delta_read_byte(struct nand_chip *this)
-{
-   u_char res;
-
-   ams_delta_read_buf(this, &res, 1);
-
-   return res;
-}
-
-/*
- * Command control function
- *
- * ctrl:
- * NAND_NCE: bit 0 -> bit 2
- * NAND_CLE: bit 1 -> bit 7
- * NAND_ALE: bit 2 -> bit 6
- */
-static void ams_delta_hwcontrol(struct nand_chip *this, int cmd,
-   unsigned int ctrl)
+static void ams_delta_select_chip(struct nand_chip *this, int n)
 {
struct ams_delta_nand *priv = nand_get_controller_data(this);
 
-   if (ctrl & NAND_CTRL_CHANGE) {
-   gpiod_set_value(priv->gpiod_nce, !(ctrl & NAND_NCE));
-   gpiod_set_value(priv->gpiod_cle, !!(ctrl & NAND_CLE));
-   gpiod_set_value(priv->gpiod_ale, !!(ctrl & NAND_ALE));
-   }
-
-   if (cmd != NAND_CMD_NONE) {
-   u_char byte = cmd;
+   if (n > 0)
+   return;
 
-   ams_delta_write_buf(this, &byte, 1);
-   }
+   gpiod_set_value(priv->gpiod_nce, n < 0);
 }
 
-static int ams_delta_nand_ready(struct nand_chip *this)
+static int ams_delta_exec_op(struct nand_chip *this,
+const struct nand_operation *op, bool check_only)
 {
struct ams_delta_nand *priv = nand_get_controller_data(this);
+   const struct nand_op_instr *instr;
+   int ret = 0;
+
+   for (instr = op->instrs; instr < op->instrs + op->ninstrs; instr++) {
+
+   switch (instr->type) {
+   case NAND_OP_CMD_INSTR:
+   gpiod_set_value(priv->gpiod_cle, 1);
+   ams_delta_write_buf(priv, &instr->ctx.cmd.opcode, 1);
+   gpiod_set_value(priv->gpiod_cle, 0);
+   break;
+
+   case NAND_OP_ADDR_INSTR:
+   gpiod_set_value(priv->gpiod_ale, 1);
+   ams_delta_write_buf(priv, instr->ctx.addr.addrs,

  1   2   3   >