2018-06-09 14:03:56

by Janusz Krzysztofik

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

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.

Signed-off-by: Janusz Krzysztofik <[email protected]>
---
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.1



2018-06-09 14:04:13

by Janusz Krzysztofik

[permalink] [raw]
Subject: [PATCH 03/10] Input: ams_delta_serio: use private structure

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 <[email protected]>

# Conflicts:
# drivers/input/serio/ams_delta_serio.c
---
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_open;
+ serio->close = ams_delta_serio_close;
+ strlcpy(serio->name, "AMS DELTA keyboard adapter", sizeof(serio->name));
+ strlcpy(serio->phys, dev_name(&pdev->dev), sizeof(serio->phys));
+ serio->dev.parent = &pdev->dev;
+ serio->port_data = priv;
+
+ serio_register_port(serio);
+
+ platform_set_drvdata(pdev, priv);
+
+ dev_info(&serio->dev, "%s\n", serio->name);

return 0;
+
+irq:
+ free_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), priv);
gpio:
gpio_free_array(ams_delta_gpios,
ARRAY_SIZE(ams_delta_gpios));
serio:
- kfree(ams_delta_serio);
return err;
}

static int ams_delta_serio_exit(struct platform_device *pdev)
{
- serio_unregister_port(ams_delta_serio);
+ struct ams_delta_serio *priv = platform_get_drvdata(pdev);
+
+ serio_unregister_port(priv->serio);
free_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 0);
gpio_free_array(ams_delta_gpios,
ARRAY_SIZE(ams_delta_gpios));
--
2.16.1


2018-06-09 14:04:20

by Janusz Krzysztofik

[permalink] [raw]
Subject: [PATCH 04/10] Input: ams_delta_serio: Replace power GPIO with regulator

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 <[email protected]>
---
arch/arm/mach-omap1/board-ams-delta.c | 63 +++++++++++++++++++++++++++++++++--
drivers/input/serio/ams_delta_serio.c | 27 ++++++++++-----
2 files changed, 79 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 = 5000000,
+ .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..d48beab1d00d 100644
--- a/drivers/input/serio/ams_delta_serio.c
+++ b/drivers/input/serio/ams_delta_serio.c
@@ -23,6 +23,7 @@
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
#include <linux/serio.h>
#include <linux/slab.h>
#include <linux/module.h>
@@ -39,6 +40,7 @@ MODULE_LICENSE("GPL");

struct ams_delta_serio {
struct serio *serio;
+ struct regulator *vcc;
};

static int check_data(struct serio *serio, int data)
@@ -94,16 +96,18 @@ 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);
+ struct ams_delta_serio *priv = serio->port_data;

- return 0;
+ /* enable keyboard */
+ return regulator_enable(priv->vcc);
}

static void ams_delta_serio_close(struct serio *serio)
{
+ struct ams_delta_serio *priv = serio->port_data;
+
/* disable keyboard */
- gpio_set_value(AMS_DELTA_GPIO_PIN_KEYBRD_PWR, 0);
+ regulator_disable(priv->vcc);
}

static const struct gpio ams_delta_gpios[] __initconst_or_module = {
@@ -117,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_PWR,
- .flags = GPIOF_OUT_INIT_LOW,
- .label = "serio-power",
- },
{
.gpio = AMS_DELTA_GPIO_PIN_KEYBRD_DATAOUT,
.flags = GPIOF_OUT_INIT_LOW,
@@ -146,6 +145,16 @@ static int ams_delta_serio_init(struct platform_device *pdev)
goto serio;
}

+ 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;
+ goto gpio;
+ }
+
err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
ams_delta_serio_interrupt, IRQ_TYPE_EDGE_RISING,
DRIVER_NAME, priv);
--
2.16.1


2018-06-09 14:04:33

by Janusz Krzysztofik

[permalink] [raw]
Subject: [PATCH 10/10] Input: ams_delta_serio: Get FIQ buffer from platform_data

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 <[email protected]>
---
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 e9d350117240..983638994bd4 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
* <linux/platform_data/ams-delta-fiq.h> 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;

return;

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 03640b171516..ee38c5140f43 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 FIQ_CIRC_BUFF 30 /*Start of circular buffer */

-#ifndef __ASSEMBLER__
-extern unsigned int fiq_buffer[];
-#endif
-
#endif
--
2.16.1


2018-06-09 14:04:51

by Janusz Krzysztofik

[permalink] [raw]
Subject: [PATCH 09/10] Input: ams_delta_serio: use IRQ resource

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 "keyboard_clk" GPIO pin from FIQ initialization routine.

As a benefit, the driver no longer needs to include
<mach/board-ams-delta.h>.

Signed-off-by: Janusz Krzysztofik <[email protected]>
---
arch/arm/mach-omap1/ams-delta-fiq.c | 8 +++++++-
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 | 28 ++++++++++------------------
4 files changed, 35 insertions(+), 21 deletions(-)

diff --git a/arch/arm/mach-omap1/ams-delta-fiq.c b/arch/arm/mach-omap1/ams-delta-fiq.c
index e72935034d42..e9d350117240 100644
--- a/arch/arm/mach-omap1/ams-delta-fiq.c
+++ b/arch/arm/mach-omap1/ams-delta-fiq.c
@@ -20,6 +20,7 @@
#include <linux/module.h>
#include <linux/io.h>
#include <linux/platform_data/ams-delta-fiq.h>
+#include <linux/platform_device.h>

#include <mach/board-ams-delta.h>

@@ -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,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 */
+ serio->resource[0].start = gpiod_to_irq(clk);
+ serio->resource[0].end = serio->resource[0].start;
+
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 5d0bd2005648..03640b171516 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 <linux/gpio.h>
#include <linux/irq.h>
#include <linux/platform_data/ams-delta-fiq.h>
#include <linux/platform_device.h>
@@ -29,8 +28,6 @@
#include <linux/slab.h>
#include <linux/module.h>

-#include <mach/board-ams-delta.h>
-
#define DRIVER_NAME "ams-delta-serio"

MODULE_AUTHOR("Matt Callow");
@@ -113,7 +110,7 @@ static int ams_delta_serio_init(struct platform_device *pdev)
{
struct ams_delta_serio *priv;
struct serio *serio;
- int err;
+ int irq, err;

priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -129,9 +126,12 @@ static int ams_delta_serio_init(struct platform_device *pdev)
return err;
}

- err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
- ams_delta_serio_interrupt, IRQ_TYPE_EDGE_RISING,
- DRIVER_NAME, priv);
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return -ENXIO;
+
+ err = devm_request_irq(&pdev->dev, irq, ams_delta_serio_interrupt,
+ IRQ_TYPE_EDGE_RISING, DRIVER_NAME, priv);
if (err < 0) {
dev_err(&pdev->dev, "IRQ request failed (%d)\n", err);
return err;
@@ -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);

serio = kzalloc(sizeof(*serio), GFP_KERNEL);
- if (!serio) {
- err = -ENOMEM;
- goto irq;
- }
+ if (!serio)
+ return -ENOMEM;

priv->serio = serio;

@@ -167,10 +164,6 @@ static int ams_delta_serio_init(struct platform_device *pdev)
dev_info(&serio->dev, "%s\n", serio->name);

return 0;
-
-irq:
- free_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), priv);
- return err;
}

static int ams_delta_serio_exit(struct platform_device *pdev)
@@ -178,7 +171,6 @@ static int ams_delta_serio_exit(struct platform_device *pdev)
struct ams_delta_serio *priv = platform_get_drvdata(pdev);

serio_unregister_port(priv->serio);
- free_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 0);

return 0;
}
--
2.16.1


2018-06-09 14:05:15

by Janusz Krzysztofik

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

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 <[email protected]>
---
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 0b4d5a952ecb..a83d8b3cd838 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 = "serio-data",
- },
- {
- .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_CLK,
- .flags = GPIOF_DIR_IN,
- .label = "serio-clock",
- },
-};
-
static int ams_delta_serio_init(struct platform_device *pdev)
{
struct ams_delta_serio *priv;
@@ -133,13 +120,6 @@ static int ams_delta_serio_init(struct platform_device *pdev)
if (!priv)
return -ENOMEM;

- err = gpio_request_array(ams_delta_gpios,
- ARRAY_SIZE(ams_delta_gpios));
- if (err) {
- dev_err(&pdev->dev, "Couldn't request gpio pins\n");
- goto serio;
- }
-
priv->vcc = devm_regulator_get(&pdev->dev, "vcc");
if (IS_ERR(priv->vcc)) {
err = PTR_ERR(priv->vcc);
@@ -147,7 +127,7 @@ static int ams_delta_serio_init(struct platform_device *pdev)
/* Fail softly if the regulator is not available yet */
if (err == -ENODEV)
err = -EPROBE_DEFER;
- goto gpio;
+ return err;
}

err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
@@ -155,7 +135,7 @@ static int ams_delta_serio_init(struct platform_device *pdev)
DRIVER_NAME, priv);
if (err < 0) {
dev_err(&pdev->dev, "IRQ request failed (%d)\n", err);
- goto gpio;
+ return err;
}
/*
* Since GPIO register handling for keyboard clock pin is performed
@@ -191,10 +171,6 @@ static int ams_delta_serio_init(struct platform_device *pdev)

irq:
free_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), priv);
-gpio:
- gpio_free_array(ams_delta_gpios,
- ARRAY_SIZE(ams_delta_gpios));
-serio:
return err;
}

@@ -204,8 +180,6 @@ static int ams_delta_serio_exit(struct platform_device *pdev)

serio_unregister_port(priv->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;
}
--
2.16.1


2018-06-09 14:05:26

by Janusz Krzysztofik

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

With introduction of GPIO lookup tables to Amstrad Delta board init
file, semantics of symbols representing OMAP GPIO pins defined in
<mach/board-ams-delta.h> 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 <[email protected]>
---
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 <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
@@ -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-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index 2821284aa0c9..f15c0793c34b 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -580,6 +580,44 @@ static struct gpiod_hog ams_delta_gpio_hogs[] = {
{},
};

+/*
+ * 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);
+}
+
+/*
+ * 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
+ * banks but their drivers don't use GPIO lookup tables or GPIO layer at all.
+ * The function may be called as soon as OMAP GPIO devices are probed.
+ * Since that happens at postcore_initcall, it can be called successfully
+ * from init_machine or later.
+ * Dependent devices may be registered from within this function or later.
+ */
+static void __init omap_gpio_deps_init(void)
+{
+ struct gpio_chip *chip;
+
+ chip = gpiochip_find(OMAP_GPIO_LABEL, gpiochip_match_by_label);
+ if (!chip) {
+ pr_err("%s: OMAP GPIO chip not found\n", __func__);
+ return;
+ }
+
+ ams_delta_init_fiq(chip);
+}
+
static void __init ams_delta_init(void)
{
/* mux pins for uarts */
@@ -600,6 +638,7 @@ static void __init ams_delta_init(void)
omap_cfg_reg(J19_1610_CAM_D6);
omap_cfg_reg(J18_1610_CAM_D7);

+ omap_gpio_deps_init();
gpiod_add_hogs(ams_delta_gpio_hogs);

omap_serial_init();
@@ -642,8 +681,6 @@ static void __init ams_delta_init(void)
gpiod_add_lookup_tables(ams_delta_gpio_tables,
ARRAY_SIZE(ams_delta_gpio_tables));

- ams_delta_init_fiq();
-
omap_writew(omap_readw(ARM_RSTCT1) | 0x0004, ARM_RSTCT1);

omapfb_set_lcd_config(&ams_delta_lcd_config);
diff --git a/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h b/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h
index 6dfc3e1210a3..a9769ff396bc 100644
--- a/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h
+++ b/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h
@@ -73,7 +73,7 @@
extern unsigned int fiq_buffer[];
extern unsigned char qwerty_fiqin_start, qwerty_fiqin_end;

-extern void __init ams_delta_init_fiq(void);
+extern void __init ams_delta_init_fiq(struct gpio_chip *chip);
#endif

#endif
--
2.16.1


2018-06-09 14:05:46

by Janusz Krzysztofik

[permalink] [raw]
Subject: [PATCH 08/10] ARM: OMAP1: Get rid of <mach/ams-delta-fiq.h>

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
<linux/platform_data/ams-delta-fiq.h>, to be used by ams-delta-serio
driver.

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 <[email protected]>
---
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 14fbc6e94774..c487348da38c 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 <[email protected]>
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 <linux/linkage.h>
-#include <asm/assembler.h>
+#include <linux/platform_data/ams-delta-fiq.h>

+#include <asm/assembler.h>
#include <mach/board-ams-delta.h>
-#include <mach/ams-delta-fiq.h>

+#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 <linux/irq.h>
#include <linux/module.h>
#include <linux/io.h>
+#include <linux/platform_data/ams-delta-fiq.h>

#include <mach/board-ams-delta.h>

#include <asm/fiq.h>

-#include <mach/ams-delta-fiq.h>
+#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
+ * <linux/platform_data/ams-delta-fiq.h> 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 000000000000..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 <mach/irqs.h>
+
+/*
+ * 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 <mach/mux.h>

#include <mach/hardware.h>
-#include <mach/ams-delta-fiq.h>
#include "camera.h"
#include <mach/usb.h>

+#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 a83d8b3cd838..5d0bd2005648 100644
--- a/drivers/input/serio/ams_delta_serio.c
+++ b/drivers/input/serio/ams_delta_serio.c
@@ -22,6 +22,7 @@
*/
#include <linux/gpio.h>
#include <linux/irq.h>
+#include <linux/platform_data/ams-delta-fiq.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/serio.h>
@@ -30,8 +31,6 @@

#include <mach/board-ams-delta.h>

-#include <mach/ams-delta-fiq.h>
-
#define DRIVER_NAME "ams-delta-serio"

MODULE_AUTHOR("Matt Callow");
diff --git a/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h b/include/linux/platform_data/ams-delta-fiq.h
similarity index 71%
rename from arch/arm/mach-omap1/include/mach/ams-delta-fiq.h
rename to include/linux/platform_data/ams-delta-fiq.h
index a9769ff396bc..dc0f835ea918 100644
--- a/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h
+++ b/include/linux/platform_data/ams-delta-fiq.h
@@ -1,5 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
/*
- * arch/arm/mach-omap1/include/ams-delta-fiq.h
+ * include/linux/platform_data/ams-delta-fiq.h
*
* Taken from the original Amstrad modifications to fiq.h
*
@@ -11,24 +13,8 @@
* 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 <mach/irqs.h>
-
-/*
- * 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 __LINUX_PLATFORM_DATA_AMS_DELTA_FIQ_H
+#define __LINUX_PLATFORM_DATA_AMS_DELTA_FIQ_H

/*
* These are the offsets from the beginning of the fiq_buffer. They are put here
@@ -71,9 +57,6 @@

#ifndef __ASSEMBLER__
extern unsigned int fiq_buffer[];
-extern unsigned char qwerty_fiqin_start, qwerty_fiqin_end;
-
-extern void __init ams_delta_init_fiq(struct gpio_chip *chip);
#endif

#endif
--
2.16.1


2018-06-09 14:05:57

by Janusz Krzysztofik

[permalink] [raw]
Subject: [PATCH 02/10] Input: ams_delta_serio: convert to platform driver

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 <[email protected]>
---
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 <linux/gpio.h>
#include <linux/irq.h>
+#include <linux/platform_device.h>
#include <linux/serio.h>
#include <linux/slab.h>
#include <linux/module.h>

-#include <asm/mach-types.h>
#include <mach/board-ams-delta.h>

#include <mach/ams-delta-fiq.h>

+#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.1


2018-06-09 14:06:38

by Janusz Krzysztofik

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

"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 <[email protected]>
---
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 d48beab1d00d..0b4d5a952ecb 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.1


2018-06-12 22:18:10

by Dmitry Torokhov

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

On Sat, Jun 09, 2018 at 04:02:18PM +0200, Janusz Krzysztofik wrote:
> 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 <[email protected]>
> ---
> arch/arm/mach-omap1/board-ams-delta.c | 63 +++++++++++++++++++++++++++++++++--
> drivers/input/serio/ams_delta_serio.c | 27 ++++++++++-----
> 2 files changed, 79 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 = 5000000,
> + .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..d48beab1d00d 100644
> --- a/drivers/input/serio/ams_delta_serio.c
> +++ b/drivers/input/serio/ams_delta_serio.c
> @@ -23,6 +23,7 @@
> #include <linux/gpio.h>
> #include <linux/irq.h>
> #include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> #include <linux/serio.h>
> #include <linux/slab.h>
> #include <linux/module.h>
> @@ -39,6 +40,7 @@ MODULE_LICENSE("GPL");
>
> struct ams_delta_serio {
> struct serio *serio;
> + struct regulator *vcc;
> };
>
> static int check_data(struct serio *serio, int data)
> @@ -94,16 +96,18 @@ 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);
> + struct ams_delta_serio *priv = serio->port_data;
>
> - return 0;
> + /* enable keyboard */
> + return regulator_enable(priv->vcc);
> }
>
> static void ams_delta_serio_close(struct serio *serio)
> {
> + struct ams_delta_serio *priv = serio->port_data;
> +
> /* disable keyboard */
> - gpio_set_value(AMS_DELTA_GPIO_PIN_KEYBRD_PWR, 0);
> + regulator_disable(priv->vcc);
> }
>
> static const struct gpio ams_delta_gpios[] __initconst_or_module = {
> @@ -117,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_PWR,
> - .flags = GPIOF_OUT_INIT_LOW,
> - .label = "serio-power",
> - },
> {
> .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_DATAOUT,
> .flags = GPIOF_OUT_INIT_LOW,
> @@ -146,6 +145,16 @@ static int ams_delta_serio_init(struct platform_device *pdev)
> goto serio;
> }
>
> + 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...

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

> + goto gpio;
> + }
> +
> err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
> ams_delta_serio_interrupt, IRQ_TYPE_EDGE_RISING,
> DRIVER_NAME, priv);
> --
> 2.16.1
>

Thanks.

--
Dmitry

2018-06-12 22:22:29

by Dmitry Torokhov

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

On Sat, Jun 09, 2018 at 04:02:23PM +0200, Janusz Krzysztofik wrote:
> 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 "keyboard_clk" GPIO pin from FIQ initialization routine.
>
> As a benefit, the driver no longer needs to include
> <mach/board-ams-delta.h>.
>
> Signed-off-by: Janusz Krzysztofik <[email protected]>
> ---
> arch/arm/mach-omap1/ams-delta-fiq.c | 8 +++++++-
> 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 | 28 ++++++++++------------------
> 4 files changed, 35 insertions(+), 21 deletions(-)
>
> diff --git a/arch/arm/mach-omap1/ams-delta-fiq.c b/arch/arm/mach-omap1/ams-delta-fiq.c
> index e72935034d42..e9d350117240 100644
> --- a/arch/arm/mach-omap1/ams-delta-fiq.c
> +++ b/arch/arm/mach-omap1/ams-delta-fiq.c
> @@ -20,6 +20,7 @@
> #include <linux/module.h>
> #include <linux/io.h>
> #include <linux/platform_data/ams-delta-fiq.h>
> +#include <linux/platform_device.h>
>
> #include <mach/board-ams-delta.h>
>
> @@ -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,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 */
> + serio->resource[0].start = gpiod_to_irq(clk);
> + serio->resource[0].end = serio->resource[0].start;
> +
> 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 5d0bd2005648..03640b171516 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 <linux/gpio.h>
> #include <linux/irq.h>
> #include <linux/platform_data/ams-delta-fiq.h>
> #include <linux/platform_device.h>
> @@ -29,8 +28,6 @@
> #include <linux/slab.h>
> #include <linux/module.h>
>
> -#include <mach/board-ams-delta.h>
> -
> #define DRIVER_NAME "ams-delta-serio"
>
> MODULE_AUTHOR("Matt Callow");
> @@ -113,7 +110,7 @@ static int ams_delta_serio_init(struct platform_device *pdev)
> {
> struct ams_delta_serio *priv;
> struct serio *serio;
> - int err;
> + int irq, err;
>
> priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> if (!priv)
> @@ -129,9 +126,12 @@ static int ams_delta_serio_init(struct platform_device *pdev)
> return err;
> }
>
> - err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
> - ams_delta_serio_interrupt, IRQ_TYPE_EDGE_RISING,
> - DRIVER_NAME, priv);
> + irq = platform_get_irq(pdev, 0);
> + if (irq < 0)
> + return -ENXIO;
> +
> + err = devm_request_irq(&pdev->dev, irq, ams_delta_serio_interrupt,
> + IRQ_TYPE_EDGE_RISING, DRIVER_NAME, priv);
> if (err < 0) {
> dev_err(&pdev->dev, "IRQ request failed (%d)\n", err);
> return err;
> @@ -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?

>
> serio = kzalloc(sizeof(*serio), GFP_KERNEL);
> - if (!serio) {
> - err = -ENOMEM;
> - goto irq;
> - }
> + if (!serio)
> + return -ENOMEM;
>
> priv->serio = serio;
>
> @@ -167,10 +164,6 @@ static int ams_delta_serio_init(struct platform_device *pdev)
> dev_info(&serio->dev, "%s\n", serio->name);
>
> return 0;
> -
> -irq:
> - free_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), priv);
> - return err;
> }
>
> static int ams_delta_serio_exit(struct platform_device *pdev)
> @@ -178,7 +171,6 @@ static int ams_delta_serio_exit(struct platform_device *pdev)
> struct ams_delta_serio *priv = platform_get_drvdata(pdev);
>
> serio_unregister_port(priv->serio);
> - free_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 0);
>
> return 0;
> }
> --
> 2.16.1
>

--
Dmitry

2018-06-12 22:32:30

by Dmitry Torokhov

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

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?

>
> Signed-off-by: Janusz Krzysztofik <[email protected]>
> ---
> 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.1
>

--
Dmitry

2018-06-13 01:01:24

by Janusz Krzysztofik

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

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




2018-06-13 01:12:01

by Janusz Krzysztofik

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

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




2018-06-13 01:17:36

by Janusz Krzysztofik

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

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




2018-06-13 04:44:00

by Tony Lindgren

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

* Janusz Krzysztofik <[email protected]> [180613 01:18]:
> 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.

Works for me once Dmitry is happy with the patches.

Regards,

Tony

2018-06-13 20:52:36

by Dmitry Torokhov

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

On Wed, Jun 13, 2018 at 03:01:05AM +0200, Janusz Krzysztofik wrote:
> 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.

OK, fair enough. Can you please add a comment to that effect?

Thanks.

--
Dmitry

2018-06-14 08:46:43

by Linus Walleij

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

On Sat, Jun 9, 2018 at 4:02 PM, Janusz Krzysztofik <[email protected]> wrote:

> With introduction of GPIO lookup tables to Amstrad Delta board init
> file, semantics of symbols representing OMAP GPIO pins defined in
> <mach/board-ams-delta.h> 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 <[email protected]>

Making the kernel a better place, so:
Acked-by: Linus Walleij <[email protected]>

> +/*
> + * 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);
> +}
> +
> +/*
> + * 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
> + * banks but their drivers don't use GPIO lookup tables or GPIO layer at all.
> + * The function may be called as soon as OMAP GPIO devices are probed.
> + * Since that happens at postcore_initcall, it can be called successfully
> + * from init_machine or later.
> + * Dependent devices may be registered from within this function or later.
> + */
> +static void __init omap_gpio_deps_init(void)
> +{
> + struct gpio_chip *chip;
> +
> + chip = gpiochip_find(OMAP_GPIO_LABEL, gpiochip_match_by_label);
> + if (!chip) {
> + pr_err("%s: OMAP GPIO chip not found\n", __func__);
> + return;
> + }
> +
> + ams_delta_init_fiq(chip);
> +}

This is some real stunt work isn't it.

We should really think about ways to get gpiolib more helpful for board
setups like this, but it seems complex.

Yours,
Linus Walleij

2018-06-14 22:17:49

by Janusz Krzysztofik

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

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 <[email protected]>
---
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 = 5000000,
+ .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 <linux/gpio.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
#include <linux/serio.h>
#include <linux/slab.h>
#include <linux/module.h>
@@ -39,6 +40,7 @@ MODULE_LICENSE("GPL");

struct ams_delta_serio {
struct serio *serio;
+ struct regulator *vcc;
};

static int check_data(struct serio *serio, int data)
@@ -94,16 +96,18 @@ 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);
+ struct ams_delta_serio *priv = serio->port_data;

- return 0;
+ /* enable keyboard */
+ return regulator_enable(priv->vcc);
}

static void ams_delta_serio_close(struct serio *serio)
{
+ struct ams_delta_serio *priv = serio->port_data;
+
/* disable keyboard */
- gpio_set_value(AMS_DELTA_GPIO_PIN_KEYBRD_PWR, 0);
+ regulator_disable(priv->vcc);
}

static const struct gpio ams_delta_gpios[] __initconst_or_module = {
@@ -117,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_PWR,
- .flags = GPIOF_OUT_INIT_LOW,
- .label = "serio-power",
- },
{
.gpio = AMS_DELTA_GPIO_PIN_KEYBRD_DATAOUT,
.flags = GPIOF_OUT_INIT_LOW,
@@ -146,6 +145,26 @@ static int ams_delta_serio_init(struct platform_device *pdev)
goto serio;
}

+ 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);
+ /*
+ * When running on a non-dt platform and requested regulator
+ * is not available, devm_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 constriants flag at late_initcall in order
+ * to instruct devm_regulator_get() to returnn 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;
+ goto gpio;
+ }
+
err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
ams_delta_serio_interrupt, IRQ_TYPE_EDGE_RISING,
DRIVER_NAME, priv);
--
2.16.1


2018-06-19 06:53:20

by Tony Lindgren

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

* Tony Lindgren <[email protected]> [180613 04:44]:
> * Janusz Krzysztofik <[email protected]> [180613 01:18]:
> > 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.
>
> Works for me once Dmitry is happy with the patches.

And please repost the whole series with acks collected so
I know what I need to apply :)

Regards,

Tony


2018-06-21 22:42:49

by Janusz Krzysztofik

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

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 <[email protected]>
---
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


2018-06-21 22:43:34

by Janusz Krzysztofik

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

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 <[email protected]>
---
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 <linux/gpio.h>
#include <linux/irq.h>
+#include <linux/platform_device.h>
#include <linux/serio.h>
#include <linux/slab.h>
#include <linux/module.h>

-#include <asm/mach-types.h>
#include <mach/board-ams-delta.h>

#include <mach/ams-delta-fiq.h>

+#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


2018-06-21 22:43:51

by Janusz Krzysztofik

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

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 <[email protected]>
---
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 = "serio-data",
- },
- {
- .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_CLK,
- .flags = GPIOF_DIR_IN,
- .label = "serio-clock",
- },
-};
-
static int ams_delta_serio_init(struct platform_device *pdev)
{
struct ams_delta_serio *priv;
@@ -133,13 +120,6 @@ static int ams_delta_serio_init(struct platform_device *pdev)
if (!priv)
return -ENOMEM;

- err = gpio_request_array(ams_delta_gpios,
- ARRAY_SIZE(ams_delta_gpios));
- if (err) {
- dev_err(&pdev->dev, "Couldn't request gpio pins\n");
- goto serio;
- }
-
priv->vcc = devm_regulator_get(&pdev->dev, "vcc");
if (IS_ERR(priv->vcc)) {
err = PTR_ERR(priv->vcc);
@@ -157,7 +137,7 @@ static int ams_delta_serio_init(struct platform_device *pdev)
*/
if (err == -ENODEV)
err = -EPROBE_DEFER;
- goto gpio;
+ return err;
}

err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
@@ -165,7 +145,7 @@ static int ams_delta_serio_init(struct platform_device *pdev)
DRIVER_NAME, priv);
if (err < 0) {
dev_err(&pdev->dev, "IRQ request failed (%d)\n", err);
- goto gpio;
+ return err;
}
/*
* Since GPIO register handling for keyboard clock pin is performed
@@ -201,10 +181,6 @@ static int ams_delta_serio_init(struct platform_device *pdev)

irq:
free_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), priv);
-gpio:
- gpio_free_array(ams_delta_gpios,
- ARRAY_SIZE(ams_delta_gpios));
-serio:
return err;
}

@@ -214,8 +190,6 @@ static int ams_delta_serio_exit(struct platform_device *pdev)

serio_unregister_port(priv->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;
}
--
2.16.4


2018-06-21 22:43:58

by Janusz Krzysztofik

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

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
<mach/board-ams-delta.h>.

Signed-off-by: Janusz Krzysztofik <[email protected]>
---
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 <linux/module.h>
#include <linux/io.h>
#include <linux/platform_data/ams-delta-fiq.h>
+#include <linux/platform_device.h>

#include <mach/board-ams-delta.h>

@@ -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 <linux/gpio.h>
#include <linux/irq.h>
#include <linux/platform_data/ams-delta-fiq.h>
#include <linux/platform_device.h>
@@ -29,8 +28,6 @@
#include <linux/slab.h>
#include <linux/module.h>

-#include <mach/board-ams-delta.h>
-
#define DRIVER_NAME "ams-delta-serio"

MODULE_AUTHOR("Matt Callow");
@@ -113,7 +110,7 @@ static int ams_delta_serio_init(struct platform_device *pdev)
{
struct ams_delta_serio *priv;
struct serio *serio;
- int err;
+ int irq, err;

priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -139,26 +136,20 @@ static int ams_delta_serio_init(struct platform_device *pdev)
return err;
}

- err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
- ams_delta_serio_interrupt, IRQ_TYPE_EDGE_RISING,
- DRIVER_NAME, priv);
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return -ENXIO;
+
+ err = devm_request_irq(&pdev->dev, irq, ams_delta_serio_interrupt,
+ IRQ_TYPE_EDGE_RISING, DRIVER_NAME, priv);
if (err < 0) {
dev_err(&pdev->dev, "IRQ request failed (%d)\n", err);
return err;
}
- /*
- * Since GPIO register handling for keyboard clock pin is performed
- * at FIQ level, switch back from edge to simple interrupt handler
- * to avoid bad interaction.
- */
- irq_set_handler(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
- handle_simple_irq);

serio = kzalloc(sizeof(*serio), GFP_KERNEL);
- if (!serio) {
- err = -ENOMEM;
- goto irq;
- }
+ if (!serio)
+ return -ENOMEM;

priv->serio = serio;

@@ -177,10 +168,6 @@ static int ams_delta_serio_init(struct platform_device *pdev)
dev_info(&serio->dev, "%s\n", serio->name);

return 0;
-
-irq:
- free_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), priv);
- return err;
}

static int ams_delta_serio_exit(struct platform_device *pdev)
@@ -188,7 +175,6 @@ static int ams_delta_serio_exit(struct platform_device *pdev)
struct ams_delta_serio *priv = platform_get_drvdata(pdev);

serio_unregister_port(priv->serio);
- free_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 0);

return 0;
}
--
2.16.4


2018-06-21 22:44:02

by Janusz Krzysztofik

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

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 <[email protected]>
---
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
* <linux/platform_data/ams-delta-fiq.h> 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 FIQ_CIRC_BUFF 30 /*Start of circular buffer */

-#ifndef __ASSEMBLER__
-extern unsigned int fiq_buffer[];
-#endif
-
#endif
--
2.16.4


2018-06-21 22:44:28

by Janusz Krzysztofik

[permalink] [raw]
Subject: [PATCH v2 08/10] ARM: OMAP1: Get rid of <mach/ams-delta-fiq.h>

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
<linux/platform_data/ams-delta-fiq.h> 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 <[email protected]>
---
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 <[email protected]>
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 <linux/linkage.h>
-#include <asm/assembler.h>
+#include <linux/platform_data/ams-delta-fiq.h>

+#include <asm/assembler.h>
#include <mach/board-ams-delta.h>
-#include <mach/ams-delta-fiq.h>

+#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 <linux/irq.h>
#include <linux/module.h>
#include <linux/io.h>
+#include <linux/platform_data/ams-delta-fiq.h>

#include <mach/board-ams-delta.h>

#include <asm/fiq.h>

-#include <mach/ams-delta-fiq.h>
+#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
+ * <linux/platform_data/ams-delta-fiq.h> 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 000000000000..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 <mach/irqs.h>
+
+/*
+ * 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 <mach/mux.h>

#include <mach/hardware.h>
-#include <mach/ams-delta-fiq.h>
#include "camera.h"
#include <mach/usb.h>

+#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 <linux/gpio.h>
#include <linux/irq.h>
+#include <linux/platform_data/ams-delta-fiq.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/serio.h>
@@ -30,8 +31,6 @@

#include <mach/board-ams-delta.h>

-#include <mach/ams-delta-fiq.h>
-
#define DRIVER_NAME "ams-delta-serio"

MODULE_AUTHOR("Matt Callow");
diff --git a/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h b/include/linux/platform_data/ams-delta-fiq.h
similarity index 71%
rename from arch/arm/mach-omap1/include/mach/ams-delta-fiq.h
rename to include/linux/platform_data/ams-delta-fiq.h
index a9769ff396bc..dc0f835ea918 100644
--- a/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h
+++ b/include/linux/platform_data/ams-delta-fiq.h
@@ -1,5 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
/*
- * arch/arm/mach-omap1/include/ams-delta-fiq.h
+ * include/linux/platform_data/ams-delta-fiq.h
*
* Taken from the original Amstrad modifications to fiq.h
*
@@ -11,24 +13,8 @@
* 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 <mach/irqs.h>
-
-/*
- * 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 __LINUX_PLATFORM_DATA_AMS_DELTA_FIQ_H
+#define __LINUX_PLATFORM_DATA_AMS_DELTA_FIQ_H

/*
* These are the offsets from the beginning of the fiq_buffer. They are put here
@@ -71,9 +57,6 @@

#ifndef __ASSEMBLER__
extern unsigned int fiq_buffer[];
-extern unsigned char qwerty_fiqin_start, qwerty_fiqin_end;
-
-extern void __init ams_delta_init_fiq(struct gpio_chip *chip);
#endif

#endif
--
2.16.4


2018-06-21 22:45:11

by Janusz Krzysztofik

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

"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 <[email protected]>
---
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


2018-06-21 22:45:22

by Janusz Krzysztofik

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

With introduction of GPIO lookup tables to Amstrad Delta board init
file, semantics of symbols representing OMAP GPIO pins defined in
<mach/board-ams-delta.h> 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 <[email protected]>
Acked-by: Linus Walleij <[email protected]>
---
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 <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
@@ -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-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index 2821284aa0c9..f15c0793c34b 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -580,6 +580,44 @@ static struct gpiod_hog ams_delta_gpio_hogs[] = {
{},
};

+/*
+ * 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);
+}
+
+/*
+ * 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
+ * banks but their drivers don't use GPIO lookup tables or GPIO layer at all.
+ * The function may be called as soon as OMAP GPIO devices are probed.
+ * Since that happens at postcore_initcall, it can be called successfully
+ * from init_machine or later.
+ * Dependent devices may be registered from within this function or later.
+ */
+static void __init omap_gpio_deps_init(void)
+{
+ struct gpio_chip *chip;
+
+ chip = gpiochip_find(OMAP_GPIO_LABEL, gpiochip_match_by_label);
+ if (!chip) {
+ pr_err("%s: OMAP GPIO chip not found\n", __func__);
+ return;
+ }
+
+ ams_delta_init_fiq(chip);
+}
+
static void __init ams_delta_init(void)
{
/* mux pins for uarts */
@@ -600,6 +638,7 @@ static void __init ams_delta_init(void)
omap_cfg_reg(J19_1610_CAM_D6);
omap_cfg_reg(J18_1610_CAM_D7);

+ omap_gpio_deps_init();
gpiod_add_hogs(ams_delta_gpio_hogs);

omap_serial_init();
@@ -642,8 +681,6 @@ static void __init ams_delta_init(void)
gpiod_add_lookup_tables(ams_delta_gpio_tables,
ARRAY_SIZE(ams_delta_gpio_tables));

- ams_delta_init_fiq();
-
omap_writew(omap_readw(ARM_RSTCT1) | 0x0004, ARM_RSTCT1);

omapfb_set_lcd_config(&ams_delta_lcd_config);
diff --git a/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h b/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h
index 6dfc3e1210a3..a9769ff396bc 100644
--- a/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h
+++ b/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h
@@ -73,7 +73,7 @@
extern unsigned int fiq_buffer[];
extern unsigned char qwerty_fiqin_start, qwerty_fiqin_end;

-extern void __init ams_delta_init_fiq(void);
+extern void __init ams_delta_init_fiq(struct gpio_chip *chip);
#endif

#endif
--
2.16.4


2018-06-21 22:45:36

by Janusz Krzysztofik

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

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 <[email protected]>
---
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 = 5000000,
+ .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 <linux/gpio.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
#include <linux/serio.h>
#include <linux/slab.h>
#include <linux/module.h>
@@ -39,6 +40,7 @@ MODULE_LICENSE("GPL");

struct ams_delta_serio {
struct serio *serio;
+ struct regulator *vcc;
};

static int check_data(struct serio *serio, int data)
@@ -94,16 +96,18 @@ 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);
+ struct ams_delta_serio *priv = serio->port_data;

- return 0;
+ /* enable keyboard */
+ return regulator_enable(priv->vcc);
}

static void ams_delta_serio_close(struct serio *serio)
{
+ struct ams_delta_serio *priv = serio->port_data;
+
/* disable keyboard */
- gpio_set_value(AMS_DELTA_GPIO_PIN_KEYBRD_PWR, 0);
+ regulator_disable(priv->vcc);
}

static const struct gpio ams_delta_gpios[] __initconst_or_module = {
@@ -117,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_PWR,
- .flags = GPIOF_OUT_INIT_LOW,
- .label = "serio-power",
- },
{
.gpio = AMS_DELTA_GPIO_PIN_KEYBRD_DATAOUT,
.flags = GPIOF_OUT_INIT_LOW,
@@ -146,6 +145,26 @@ static int ams_delta_serio_init(struct platform_device *pdev)
goto serio;
}

+ 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);
+ /*
+ * When running on a non-dt platform and requested regulator
+ * is not available, devm_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 constriants flag at late_initcall in order
+ * to instruct devm_regulator_get() to returnn 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;
+ goto gpio;
+ }
+
err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
ams_delta_serio_interrupt, IRQ_TYPE_EDGE_RISING,
DRIVER_NAME, priv);
--
2.16.4


2018-06-21 22:46:38

by Janusz Krzysztofik

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

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 <[email protected]>
---
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_open;
+ serio->close = ams_delta_serio_close;
+ strlcpy(serio->name, "AMS DELTA keyboard adapter", sizeof(serio->name));
+ strlcpy(serio->phys, dev_name(&pdev->dev), sizeof(serio->phys));
+ serio->dev.parent = &pdev->dev;
+ serio->port_data = priv;
+
+ serio_register_port(serio);
+
+ platform_set_drvdata(pdev, priv);
+
+ dev_info(&serio->dev, "%s\n", serio->name);

return 0;
+
+irq:
+ free_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), priv);
gpio:
gpio_free_array(ams_delta_gpios,
ARRAY_SIZE(ams_delta_gpios));
serio:
- kfree(ams_delta_serio);
return err;
}

static int ams_delta_serio_exit(struct platform_device *pdev)
{
- serio_unregister_port(ams_delta_serio);
+ struct ams_delta_serio *priv = platform_get_drvdata(pdev);
+
+ serio_unregister_port(priv->serio);
free_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 0);
gpio_free_array(ams_delta_gpios,
ARRAY_SIZE(ams_delta_gpios));
--
2.16.4


2018-06-22 00:06:01

by Dmitry Torokhov

[permalink] [raw]
Subject: Re: [PATCH v2 02/10] Input: ams_delta_serio: convert to platform driver

On Fri, Jun 22, 2018 at 12:41:20AM +0200, Janusz Krzysztofik wrote:
> 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 <[email protected]>
> ---
> Changelog:
> v2: rebased on v4.18-rc1, no conflicts

Input bits look good to me.

Acked-by: Dmitry Torokhov <[email protected]>

>
> 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 <linux/gpio.h>
> #include <linux/irq.h>
> +#include <linux/platform_device.h>
> #include <linux/serio.h>
> #include <linux/slab.h>
> #include <linux/module.h>
>
> -#include <asm/mach-types.h>
> #include <mach/board-ams-delta.h>
>
> #include <mach/ams-delta-fiq.h>
>
> +#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
>

--
Dmitry

2018-06-22 00:08:41

by Dmitry Torokhov

[permalink] [raw]
Subject: Re: [PATCH v2 03/10] Input: ams_delta_serio: use private structure

On Fri, Jun 22, 2018 at 12:41:21AM +0200, Janusz Krzysztofik wrote:
> 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 <[email protected]>

Acked-by: Dmitry Torokhov <[email protected]>

> ---
> 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_open;
> + serio->close = ams_delta_serio_close;
> + strlcpy(serio->name, "AMS DELTA keyboard adapter", sizeof(serio->name));
> + strlcpy(serio->phys, dev_name(&pdev->dev), sizeof(serio->phys));
> + serio->dev.parent = &pdev->dev;
> + serio->port_data = priv;
> +
> + serio_register_port(serio);
> +
> + platform_set_drvdata(pdev, priv);
> +
> + dev_info(&serio->dev, "%s\n", serio->name);
>
> return 0;
> +
> +irq:
> + free_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), priv);
> gpio:
> gpio_free_array(ams_delta_gpios,
> ARRAY_SIZE(ams_delta_gpios));
> serio:
> - kfree(ams_delta_serio);
> return err;
> }
>
> static int ams_delta_serio_exit(struct platform_device *pdev)
> {
> - serio_unregister_port(ams_delta_serio);
> + struct ams_delta_serio *priv = platform_get_drvdata(pdev);
> +
> + serio_unregister_port(priv->serio);
> free_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 0);
> gpio_free_array(ams_delta_gpios,
> ARRAY_SIZE(ams_delta_gpios));
> --
> 2.16.4
>

--
Dmitry

2018-06-22 00:10:03

by Dmitry Torokhov

[permalink] [raw]
Subject: Re: [PATCH v2 04/10] Input: ams_delta_serio: Replace power GPIO with regulator

On Fri, Jun 22, 2018 at 12:41:22AM +0200, Janusz Krzysztofik wrote:
> 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 <[email protected]>

Input bits look good.

Acked-by: Dmitry Torokhov <[email protected]>

> ---
> 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 = 5000000,
> + .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 <linux/gpio.h>
> #include <linux/irq.h>
> #include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> #include <linux/serio.h>
> #include <linux/slab.h>
> #include <linux/module.h>
> @@ -39,6 +40,7 @@ MODULE_LICENSE("GPL");
>
> struct ams_delta_serio {
> struct serio *serio;
> + struct regulator *vcc;
> };
>
> static int check_data(struct serio *serio, int data)
> @@ -94,16 +96,18 @@ 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);
> + struct ams_delta_serio *priv = serio->port_data;
>
> - return 0;
> + /* enable keyboard */
> + return regulator_enable(priv->vcc);
> }
>
> static void ams_delta_serio_close(struct serio *serio)
> {
> + struct ams_delta_serio *priv = serio->port_data;
> +
> /* disable keyboard */
> - gpio_set_value(AMS_DELTA_GPIO_PIN_KEYBRD_PWR, 0);
> + regulator_disable(priv->vcc);
> }
>
> static const struct gpio ams_delta_gpios[] __initconst_or_module = {
> @@ -117,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_PWR,
> - .flags = GPIOF_OUT_INIT_LOW,
> - .label = "serio-power",
> - },
> {
> .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_DATAOUT,
> .flags = GPIOF_OUT_INIT_LOW,
> @@ -146,6 +145,26 @@ static int ams_delta_serio_init(struct platform_device *pdev)
> goto serio;
> }
>
> + 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);
> + /*
> + * When running on a non-dt platform and requested regulator
> + * is not available, devm_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 constriants flag at late_initcall in order
> + * to instruct devm_regulator_get() to returnn 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;
> + goto gpio;
> + }
> +
> err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
> ams_delta_serio_interrupt, IRQ_TYPE_EDGE_RISING,
> DRIVER_NAME, priv);
> --
> 2.16.4
>

--
Dmitry

2018-06-22 00:11:08

by Dmitry Torokhov

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

On Fri, Jun 22, 2018 at 12:41:25AM +0200, Janusz Krzysztofik wrote:
> 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 <[email protected]>

Input bits look good.

Acked-by: Dmitry Torokhov <[email protected]>

> ---
> 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 = "serio-data",
> - },
> - {
> - .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_CLK,
> - .flags = GPIOF_DIR_IN,
> - .label = "serio-clock",
> - },
> -};
> -
> static int ams_delta_serio_init(struct platform_device *pdev)
> {
> struct ams_delta_serio *priv;
> @@ -133,13 +120,6 @@ static int ams_delta_serio_init(struct platform_device *pdev)
> if (!priv)
> return -ENOMEM;
>
> - err = gpio_request_array(ams_delta_gpios,
> - ARRAY_SIZE(ams_delta_gpios));
> - if (err) {
> - dev_err(&pdev->dev, "Couldn't request gpio pins\n");
> - goto serio;
> - }
> -
> priv->vcc = devm_regulator_get(&pdev->dev, "vcc");
> if (IS_ERR(priv->vcc)) {
> err = PTR_ERR(priv->vcc);
> @@ -157,7 +137,7 @@ static int ams_delta_serio_init(struct platform_device *pdev)
> */
> if (err == -ENODEV)
> err = -EPROBE_DEFER;
> - goto gpio;
> + return err;
> }
>
> err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
> @@ -165,7 +145,7 @@ static int ams_delta_serio_init(struct platform_device *pdev)
> DRIVER_NAME, priv);
> if (err < 0) {
> dev_err(&pdev->dev, "IRQ request failed (%d)\n", err);
> - goto gpio;
> + return err;
> }
> /*
> * Since GPIO register handling for keyboard clock pin is performed
> @@ -201,10 +181,6 @@ static int ams_delta_serio_init(struct platform_device *pdev)
>
> irq:
> free_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), priv);
> -gpio:
> - gpio_free_array(ams_delta_gpios,
> - ARRAY_SIZE(ams_delta_gpios));
> -serio:
> return err;
> }
>
> @@ -214,8 +190,6 @@ static int ams_delta_serio_exit(struct platform_device *pdev)
>
> serio_unregister_port(priv->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;
> }
> --
> 2.16.4
>

--
Dmitry

2018-06-22 00:12:22

by Dmitry Torokhov

[permalink] [raw]
Subject: Re: [PATCH v2 08/10] ARM: OMAP1: Get rid of <mach/ams-delta-fiq.h>

On Fri, Jun 22, 2018 at 12:41:26AM +0200, Janusz Krzysztofik wrote:
> 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
> <linux/platform_data/ams-delta-fiq.h> 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 <[email protected]>

Input bits look good.

Acked-by: Dmitry Torokhov <[email protected]>

> ---
> 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 <[email protected]>
> 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 <linux/linkage.h>
> -#include <asm/assembler.h>
> +#include <linux/platform_data/ams-delta-fiq.h>
>
> +#include <asm/assembler.h>
> #include <mach/board-ams-delta.h>
> -#include <mach/ams-delta-fiq.h>
>
> +#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 <linux/irq.h>
> #include <linux/module.h>
> #include <linux/io.h>
> +#include <linux/platform_data/ams-delta-fiq.h>
>
> #include <mach/board-ams-delta.h>
>
> #include <asm/fiq.h>
>
> -#include <mach/ams-delta-fiq.h>
> +#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
> + * <linux/platform_data/ams-delta-fiq.h> 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 000000000000..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 <mach/irqs.h>
> +
> +/*
> + * 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 <mach/mux.h>
>
> #include <mach/hardware.h>
> -#include <mach/ams-delta-fiq.h>
> #include "camera.h"
> #include <mach/usb.h>
>
> +#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 <linux/gpio.h>
> #include <linux/irq.h>
> +#include <linux/platform_data/ams-delta-fiq.h>
> #include <linux/platform_device.h>
> #include <linux/regulator/consumer.h>
> #include <linux/serio.h>
> @@ -30,8 +31,6 @@
>
> #include <mach/board-ams-delta.h>
>
> -#include <mach/ams-delta-fiq.h>
> -
> #define DRIVER_NAME "ams-delta-serio"
>
> MODULE_AUTHOR("Matt Callow");
> diff --git a/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h b/include/linux/platform_data/ams-delta-fiq.h
> similarity index 71%
> rename from arch/arm/mach-omap1/include/mach/ams-delta-fiq.h
> rename to include/linux/platform_data/ams-delta-fiq.h
> index a9769ff396bc..dc0f835ea918 100644
> --- a/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h
> +++ b/include/linux/platform_data/ams-delta-fiq.h
> @@ -1,5 +1,7 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> /*
> - * arch/arm/mach-omap1/include/ams-delta-fiq.h
> + * include/linux/platform_data/ams-delta-fiq.h
> *
> * Taken from the original Amstrad modifications to fiq.h
> *
> @@ -11,24 +13,8 @@
> * 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 <mach/irqs.h>
> -
> -/*
> - * 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 __LINUX_PLATFORM_DATA_AMS_DELTA_FIQ_H
> +#define __LINUX_PLATFORM_DATA_AMS_DELTA_FIQ_H
>
> /*
> * These are the offsets from the beginning of the fiq_buffer. They are put here
> @@ -71,9 +57,6 @@
>
> #ifndef __ASSEMBLER__
> extern unsigned int fiq_buffer[];
> -extern unsigned char qwerty_fiqin_start, qwerty_fiqin_end;
> -
> -extern void __init ams_delta_init_fiq(struct gpio_chip *chip);
> #endif
>
> #endif
> --
> 2.16.4
>

--
Dmitry

2018-06-22 00:13:01

by Dmitry Torokhov

[permalink] [raw]
Subject: Re: [PATCH v2 09/10] Input: ams_delta_serio: use IRQ resource

On Fri, Jun 22, 2018 at 12:41:27AM +0200, Janusz Krzysztofik wrote:
> 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
> <mach/board-ams-delta.h>.
>
> Signed-off-by: Janusz Krzysztofik <[email protected]>

Input bits look good.

Acked-by: Dmitry Torokhov <[email protected]>

> ---
> 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 <linux/module.h>
> #include <linux/io.h>
> #include <linux/platform_data/ams-delta-fiq.h>
> +#include <linux/platform_device.h>
>
> #include <mach/board-ams-delta.h>
>
> @@ -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 <linux/gpio.h>
> #include <linux/irq.h>
> #include <linux/platform_data/ams-delta-fiq.h>
> #include <linux/platform_device.h>
> @@ -29,8 +28,6 @@
> #include <linux/slab.h>
> #include <linux/module.h>
>
> -#include <mach/board-ams-delta.h>
> -
> #define DRIVER_NAME "ams-delta-serio"
>
> MODULE_AUTHOR("Matt Callow");
> @@ -113,7 +110,7 @@ static int ams_delta_serio_init(struct platform_device *pdev)
> {
> struct ams_delta_serio *priv;
> struct serio *serio;
> - int err;
> + int irq, err;
>
> priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> if (!priv)
> @@ -139,26 +136,20 @@ static int ams_delta_serio_init(struct platform_device *pdev)
> return err;
> }
>
> - err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
> - ams_delta_serio_interrupt, IRQ_TYPE_EDGE_RISING,
> - DRIVER_NAME, priv);
> + irq = platform_get_irq(pdev, 0);
> + if (irq < 0)
> + return -ENXIO;
> +
> + err = devm_request_irq(&pdev->dev, irq, ams_delta_serio_interrupt,
> + IRQ_TYPE_EDGE_RISING, DRIVER_NAME, priv);
> if (err < 0) {
> dev_err(&pdev->dev, "IRQ request failed (%d)\n", err);
> return err;
> }
> - /*
> - * Since GPIO register handling for keyboard clock pin is performed
> - * at FIQ level, switch back from edge to simple interrupt handler
> - * to avoid bad interaction.
> - */
> - irq_set_handler(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
> - handle_simple_irq);
>
> serio = kzalloc(sizeof(*serio), GFP_KERNEL);
> - if (!serio) {
> - err = -ENOMEM;
> - goto irq;
> - }
> + if (!serio)
> + return -ENOMEM;
>
> priv->serio = serio;
>
> @@ -177,10 +168,6 @@ static int ams_delta_serio_init(struct platform_device *pdev)
> dev_info(&serio->dev, "%s\n", serio->name);
>
> return 0;
> -
> -irq:
> - free_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), priv);
> - return err;
> }
>
> static int ams_delta_serio_exit(struct platform_device *pdev)
> @@ -188,7 +175,6 @@ static int ams_delta_serio_exit(struct platform_device *pdev)
> struct ams_delta_serio *priv = platform_get_drvdata(pdev);
>
> serio_unregister_port(priv->serio);
> - free_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 0);
>
> return 0;
> }
> --
> 2.16.4
>

--
Dmitry

2018-06-22 00:13:06

by Dmitry Torokhov

[permalink] [raw]
Subject: Re: [PATCH v2 10/10] Input: ams_delta_serio: Get FIQ buffer from platform_data

On Fri, Jun 22, 2018 at 12:41:28AM +0200, Janusz Krzysztofik wrote:
> 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 <[email protected]>

Input bits look good.

Acked-by: Dmitry Torokhov <[email protected]>

> ---
> 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
> * <linux/platform_data/ams-delta-fiq.h> 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 FIQ_CIRC_BUFF 30 /*Start of circular buffer */
>
> -#ifndef __ASSEMBLER__
> -extern unsigned int fiq_buffer[];
> -#endif
> -
> #endif
> --
> 2.16.4
>

--
Dmitry

2018-07-02 12:57:37

by Tony Lindgren

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

* Janusz Krzysztofik <[email protected]> [180621 22:45]:
> --- a/arch/arm/mach-omap1/board-ams-delta.c
> +++ b/arch/arm/mach-omap1/board-ams-delta.c
> @@ -580,6 +580,44 @@ static struct gpiod_hog ams_delta_gpio_hogs[] = {
> {},
> };
>
> +/*
> + * 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);
> +}

I left out the duplicate gpiochip_match_by_label() above as it's already
there from an earlier "ARM: OMAP1: ams-delta: assign LED GPIO numbers
from descriptors". The whole series is now pushed out to
omap-for-v4.19/omap1 and I'll merge it into my for-next soon.

Thanks,

Tony