* [PATCH v3 0/2] Add stmpe mfd
@ 2012-09-04 9:58 Steffen Trumtrar
2012-09-04 9:58 ` [PATCH v3 1/2] mfd: add stmpe-i2c driver Steffen Trumtrar
2012-09-04 9:58 ` [PATCH v3 2/2] gpio: add driver for stmpe io-expander Steffen Trumtrar
0 siblings, 2 replies; 5+ messages in thread
From: Steffen Trumtrar @ 2012-09-04 9:58 UTC (permalink / raw)
To: barebox; +Cc: Steffen Trumtrar
Hi,
this fixes some issues with the v2 patches:
- remove unused variables
- allow multiple instances of stmpe-i2c
- remove unnecessary castings
Thanks to Sascha and Mark for reviewing.
Steffen Trumtrar (2):
mfd: add stmpe-i2c driver
gpio: add driver for stmpe io-expander
drivers/Kconfig | 1 +
drivers/gpio/Kconfig | 9 +++
drivers/gpio/Makefile | 2 +
drivers/gpio/gpio-stmpe.c | 162 +++++++++++++++++++++++++++++++++++++++++++++
drivers/mfd/Kconfig | 4 ++
drivers/mfd/Makefile | 1 +
drivers/mfd/stmpe-i2c.c | 153 ++++++++++++++++++++++++++++++++++++++++++
include/mfd/stmpe-i2c.h | 56 ++++++++++++++++
8 files changed, 388 insertions(+)
create mode 100644 drivers/gpio/Kconfig
create mode 100644 drivers/gpio/Makefile
create mode 100644 drivers/gpio/gpio-stmpe.c
create mode 100644 drivers/mfd/stmpe-i2c.c
create mode 100644 include/mfd/stmpe-i2c.h
--
1.7.10.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v3 1/2] mfd: add stmpe-i2c driver
2012-09-04 9:58 [PATCH v3 0/2] Add stmpe mfd Steffen Trumtrar
@ 2012-09-04 9:58 ` Steffen Trumtrar
2012-09-04 11:26 ` Marc Kleine-Budde
2012-09-05 6:32 ` Sascha Hauer
2012-09-04 9:58 ` [PATCH v3 2/2] gpio: add driver for stmpe io-expander Steffen Trumtrar
1 sibling, 2 replies; 5+ messages in thread
From: Steffen Trumtrar @ 2012-09-04 9:58 UTC (permalink / raw)
To: barebox; +Cc: Steffen Trumtrar
The stmpe mfds can be connected via i2c and spi. This driver provides the basic
infrastructure for the i2c kind. It can be added as a normal i2c-device in the
board code. To enable functions a platform_data struct has to be provided, that
describes what parts of the chip are to be used.
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
drivers/mfd/Kconfig | 4 ++
drivers/mfd/Makefile | 1 +
drivers/mfd/stmpe-i2c.c | 153 +++++++++++++++++++++++++++++++++++++++++++++++
include/mfd/stmpe-i2c.h | 56 +++++++++++++++++
4 files changed, 214 insertions(+)
create mode 100644 drivers/mfd/stmpe-i2c.c
create mode 100644 include/mfd/stmpe-i2c.h
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index af67935..20eef86 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -33,4 +33,8 @@ config I2C_TWL6030
select I2C_TWLCORE
bool "TWL6030 driver"
+config I2C_STMPE
+ depends on I2C
+ bool "STMPE-i2c driver"
+
endmenu
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index e11223b..792ae2d 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_I2C_LP3972) += lp3972.o
obj-$(CONFIG_I2C_TWLCORE) += twl-core.o
obj-$(CONFIG_I2C_TWL4030) += twl4030.o
obj-$(CONFIG_I2C_TWL6030) += twl6030.o
+obj-$(CONFIG_I2C_STMPE) += stmpe-i2c.o
diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c
new file mode 100644
index 0000000..53b3d06
--- /dev/null
+++ b/drivers/mfd/stmpe-i2c.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2012 Pengutronix
+ * Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <xfuncs.h>
+#include <errno.h>
+
+#include <i2c/i2c.h>
+#include <mfd/stmpe-i2c.h>
+
+#define DRIVERNAME "stmpe-i2c"
+
+#define to_stmpe(a) container_of(a, struct stmpe, cdev)
+
+int stmpe_reg_read(struct stmpe *stmpe, u32 reg, u8 *val)
+{
+ int ret;
+
+ ret = i2c_read_reg(stmpe->client, reg, val, 1);
+
+ return ret == 1 ? 0 : ret;
+}
+EXPORT_SYMBOL(stmpe_reg_read)
+
+int stmpe_reg_write(struct stmpe *stmpe, u32 reg, u8 val)
+{
+ int ret;
+
+ ret = i2c_write_reg(stmpe->client, reg, &val, 1);
+
+ return ret == 1 ? 0 : ret;
+}
+EXPORT_SYMBOL(stmpe_reg_write)
+
+int stmpe_set_bits(struct stmpe *stmpe, u32 reg, u8 mask, u8 val)
+{
+ u8 tmp;
+ int err;
+
+ err = stmpe_reg_read(stmpe, reg, &tmp);
+ tmp = (tmp & ~mask) | val;
+
+ if (!err)
+ err = stmpe_reg_write(stmpe, reg, tmp);
+
+ return err;
+}
+EXPORT_SYMBOL(stmpe_set_bits);
+
+static ssize_t stmpe_read(struct cdev *cdev, void *_buf, size_t count, loff_t offset, ulong flags)
+{
+ struct stmpe *stmpe = to_stmpe(cdev);
+ u8 *buf = _buf;
+ size_t i = count;
+ int err;
+
+ while (i) {
+ err = stmpe_reg_read(stmpe, offset, buf);
+ if (err)
+ return (ssize_t)err;
+ buf++;
+ i--;
+ offset++;
+ }
+
+ return count;
+}
+
+static ssize_t stmpe_write(struct cdev *cdev, const void *_buf, size_t count, loff_t offset, ulong flags)
+{
+ struct stmpe *stmpe = to_stmpe(cdev);
+ const u8 *buf = _buf;
+ size_t i = count;
+ int err;
+
+ while (i) {
+ err = stmpe_reg_write(stmpe, offset, *buf);
+ if (err)
+ return (ssize_t)err;
+ buf++;
+ i--;
+ offset++;
+ }
+
+ return count;
+}
+
+static struct file_operations stmpe_fops = {
+ .lseek = dev_lseek_default,
+ .read = stmpe_read,
+ .write = stmpe_write,
+};
+
+static struct stmpe_client_info i2c_ci = {
+ .read_reg = stmpe_reg_read,
+ .write_reg = stmpe_reg_write,
+};
+
+static int stmpe_probe(struct device_d *dev)
+{
+ struct stmpe_platform_data *pdata = dev->platform_data;
+ struct stmpe *stmpe_dev;
+
+ if (!pdata) {
+ dev_dbg(dev, "no platform data\n");
+ return -ENODEV;
+ }
+
+ stmpe_dev = xzalloc(sizeof(struct stmpe));
+ stmpe_dev->cdev.name = DRIVERNAME;
+ stmpe_dev->client = to_i2c_client(dev);
+ stmpe_dev->cdev.size = 191; /* 191 known registers */
+ stmpe_dev->cdev.dev = dev;
+ stmpe_dev->cdev.ops = &stmpe_fops;
+ stmpe_dev->pdata = pdata;
+ dev->priv = stmpe_dev;
+ i2c_ci.stmpe = stmpe_dev;
+
+ if (pdata->blocks &= STMPE_BLOCK_GPIO)
+ add_generic_device("stmpe-gpio", 0, NULL, pdata->base, 0x10, IORESOURCE_MEM, &i2c_ci);
+
+ devfs_create(&stmpe_dev->cdev);
+
+ return 0;
+}
+
+static struct driver_d stmpe_driver = {
+ .name = DRIVERNAME,
+ .probe = stmpe_probe,
+};
+
+static int stmpe_init(void)
+{
+ register_driver(&stmpe_driver);
+ return 0;
+}
+
+device_initcall(stmpe_init);
diff --git a/include/mfd/stmpe-i2c.h b/include/mfd/stmpe-i2c.h
new file mode 100644
index 0000000..c36aed9
--- /dev/null
+++ b/include/mfd/stmpe-i2c.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 Pengutronix
+ * Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * This file is released under the GPLv2
+ *
+ */
+
+#ifndef __ASM_ARCH_STMPE_H
+#define __ASM_ARCH_STMPE_H
+
+enum stmpe_revision {
+ STMPE610,
+ STMPE801,
+ STMPE811,
+ STMPE1601,
+ STMPE2401,
+ STMPE2403,
+ STMPE_NBR_PARTS
+};
+
+enum stmpe_blocks {
+ STMPE_BLOCK_GPIO = 1 << 0,
+ STMPE_BLOCK_KEYPAD = 1 << 1,
+ STMPE_BLOCK_TOUCHSCREEN = 1 << 2,
+ STMPE_BLOCK_ADC = 1 << 3,
+ STMPE_BLOCK_PWM = 1 << 4,
+ STMPE_BLOCK_ROTATOR = 1 << 5,
+};
+
+struct stmpe_platform_data {
+ enum stmpe_revision revision;
+ enum stmpe_blocks blocks;
+ void __iomem *base;
+ int gpio_base;
+};
+
+struct stmpe {
+ struct cdev cdev;
+ struct i2c_client *client;
+ struct stmpe_platform_data *pdata;
+};
+
+struct stmpe_client_info {
+ struct stmpe *stmpe;
+ int (*read_reg)(struct stmpe *stmpe, u32 reg, u8 *val);
+ int (*write_reg)(struct stmpe *stmpe, u32 reg, u8 val);
+};
+
+extern struct stmpe *stmpe_get(void);
+
+extern int stmpe_reg_read(struct stmpe *priv, u32 reg, u8 *val);
+extern int stmpe_reg_write(struct stmpe *priv, u32 reg, u8 val);
+extern int stmpe_set_bits(struct stmpe *priv, u32 reg, u8 mask, u8 val);
+
+#endif /* __ASM_ARCH_STMPE_H */
--
1.7.10.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v3 2/2] gpio: add driver for stmpe io-expander
2012-09-04 9:58 [PATCH v3 0/2] Add stmpe mfd Steffen Trumtrar
2012-09-04 9:58 ` [PATCH v3 1/2] mfd: add stmpe-i2c driver Steffen Trumtrar
@ 2012-09-04 9:58 ` Steffen Trumtrar
1 sibling, 0 replies; 5+ messages in thread
From: Steffen Trumtrar @ 2012-09-04 9:58 UTC (permalink / raw)
To: barebox; +Cc: Steffen Trumtrar
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
drivers/Kconfig | 1 +
drivers/gpio/Kconfig | 9 +++
drivers/gpio/Makefile | 2 +
drivers/gpio/gpio-stmpe.c | 162 +++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 174 insertions(+)
create mode 100644 drivers/gpio/Kconfig
create mode 100644 drivers/gpio/Makefile
create mode 100644 drivers/gpio/gpio-stmpe.c
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 883b0e7..adf8fcd 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -18,5 +18,6 @@ source "drivers/input/Kconfig"
source "drivers/watchdog/Kconfig"
source "drivers/pwm/Kconfig"
source "drivers/dma/Kconfig"
+source "drivers/gpio/Kconfig"
endmenu
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
new file mode 100644
index 0000000..acfd4ef
--- /dev/null
+++ b/drivers/gpio/Kconfig
@@ -0,0 +1,9 @@
+menu "GPIO "
+
+config STMPE_GPIO
+ depends on I2C
+ depends on GPIOLIB
+ select I2C_STMPE
+ bool "STMPE GPIO Expander"
+
+endmenu
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
new file mode 100644
index 0000000..da1bc21
--- /dev/null
+++ b/drivers/gpio/Makefile
@@ -0,0 +1,2 @@
+obj-y += gpio.o
+obj-$(CONFIG_STMPE_GPIO) += gpio-stmpe.o
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c
new file mode 100644
index 0000000..0746458
--- /dev/null
+++ b/drivers/gpio/gpio-stmpe.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2012 Pengutronix
+ * Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <io.h>
+#include <gpio.h>
+#include <init.h>
+#include <mfd/stmpe-i2c.h>
+
+#define GPIO_BASE 0x80
+#define GPIO_SET (GPIO_BASE + 0x02)
+#define GPIO_CLR (GPIO_BASE + 0x04)
+#define GPIO_MP (GPIO_BASE + 0x06)
+#define GPIO_SET_DIR (GPIO_BASE + 0x08)
+#define GPIO_ED (GPIO_BASE + 0x0a)
+#define GPIO_RE (GPIO_BASE + 0x0c)
+#define GPIO_FE (GPIO_BASE + 0x0e)
+#define GPIO_PULL_UP (GPIO_BASE + 0x10)
+#define GPIO_AF (GPIO_BASE + 0x12)
+#define GPIO_LT (GPIO_BASE + 0x16)
+
+#define OFFSET(gpio) (0xff & (1 << (gpio)) ? 1 : 0)
+
+struct stmpe_gpio_chip {
+ struct gpio_chip chip;
+ struct stmpe_client_info *ci;
+};
+
+static void stmpe_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value)
+{
+ struct stmpe_gpio_chip *stmpegpio = container_of(chip, struct stmpe_gpio_chip, chip);
+ struct stmpe_client_info *ci = (struct stmpe_client_info *)stmpegpio->ci;
+ int ret;
+ u8 val;
+
+ ci->read_reg(ci->stmpe, GPIO_MP + OFFSET(gpio), &val);
+
+ val |= 1 << (gpio % 8);
+
+ if (value)
+ ret = ci->write_reg(ci->stmpe, GPIO_SET + OFFSET(gpio), val);
+ else
+ ret = ci->write_reg(ci->stmpe, GPIO_CLR + OFFSET(gpio), val);
+
+ if (ret)
+ dev_err(chip->dev, "write failed!\n");
+}
+
+static int stmpe_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+ struct stmpe_gpio_chip *stmpegpio = container_of(chip, struct stmpe_gpio_chip, chip);
+ struct stmpe_client_info *ci = (struct stmpe_client_info *)stmpegpio->ci;
+ int ret;
+ u8 val;
+
+ ci->read_reg(ci->stmpe, GPIO_SET_DIR + OFFSET(gpio), &val);
+ val &= ~(1 << (gpio % 8));
+ ret = ci->write_reg(ci->stmpe, GPIO_SET_DIR + OFFSET(gpio), val);
+
+ if (ret)
+ dev_err(chip->dev, "couldn't change direction. Write failed!\n");
+
+ return ret;
+}
+
+static int stmpe_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value)
+{
+ struct stmpe_gpio_chip *stmpegpio = container_of(chip, struct stmpe_gpio_chip, chip);
+ struct stmpe_client_info *ci = (struct stmpe_client_info *)stmpegpio->ci;
+ int ret;
+ u8 val;
+
+ ci->read_reg(ci->stmpe, GPIO_SET_DIR + OFFSET(gpio), &val);
+ val |= 1 << (gpio % 8);
+ ret = ci->write_reg(ci->stmpe, GPIO_SET_DIR + OFFSET(gpio), val);
+
+ stmpe_gpio_set_value(chip, gpio, value);
+
+ if (ret)
+ dev_err(chip->dev, "couldn't change direction. Write failed!\n");
+
+ return ret;
+}
+
+static int stmpe_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
+{
+ struct stmpe_gpio_chip *stmpegpio = container_of(chip, struct stmpe_gpio_chip, chip);
+ struct stmpe_client_info *ci = (struct stmpe_client_info *)stmpegpio->ci;
+ u8 val;
+ int ret;
+
+ ret = ci->read_reg(ci->stmpe, GPIO_MP + OFFSET(gpio), &val);
+
+ if (ret)
+ dev_err(chip->dev, "read failed\n");
+
+ return val & (1 << (gpio % 8)) ? 1 : 0;
+}
+
+static struct gpio_ops stmpe_gpio_ops = {
+ .direction_input = stmpe_gpio_direction_input,
+ .direction_output = stmpe_gpio_direction_output,
+ .get = stmpe_gpio_get_value,
+ .set = stmpe_gpio_set_value,
+};
+
+static int stmpe_gpio_probe(struct device_d *dev)
+{
+ struct stmpe_gpio_chip *stmpegpio;
+ struct stmpe_client_info *ci;
+ int ret;
+
+ stmpegpio = xzalloc(sizeof(*stmpegpio));
+
+ stmpegpio->chip.ops = &stmpe_gpio_ops;
+ stmpegpio->ci = dev->platform_data;
+
+ ci = (struct stmpe_client_info *)stmpegpio->ci;
+
+ if (ci->stmpe->pdata->gpio_base)
+ stmpegpio->chip.base = ci->stmpe->pdata->gpio_base;
+ else
+ stmpegpio->chip.base = -1;
+
+ stmpegpio->chip.ngpio = 16;
+ stmpegpio->chip.dev = dev;
+
+ ret = gpiochip_add(&stmpegpio->chip);
+
+ if (ret) {
+ dev_err(dev, "couldn't add gpiochip\n");
+ return ret;
+ }
+
+ dev_info(dev, "probed stmpe gpiochip%d with base %d\n", dev->id, stmpegpio->chip.base);
+ return 0;
+}
+
+static struct driver_d stmpe_gpio_driver = {
+ .name = "stmpe-gpio",
+ .probe = stmpe_gpio_probe,
+};
+
+static int stmpe_gpio_add(void)
+{
+ return register_driver(&stmpe_gpio_driver);
+}
+coredevice_initcall(stmpe_gpio_add);
--
1.7.10.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v3 1/2] mfd: add stmpe-i2c driver
2012-09-04 9:58 ` [PATCH v3 1/2] mfd: add stmpe-i2c driver Steffen Trumtrar
@ 2012-09-04 11:26 ` Marc Kleine-Budde
2012-09-05 6:32 ` Sascha Hauer
1 sibling, 0 replies; 5+ messages in thread
From: Marc Kleine-Budde @ 2012-09-04 11:26 UTC (permalink / raw)
To: Steffen Trumtrar; +Cc: barebox
[-- Attachment #1.1: Type: text/plain, Size: 7554 bytes --]
On 09/04/2012 11:58 AM, Steffen Trumtrar wrote:
> The stmpe mfds can be connected via i2c and spi. This driver provides the basic
> infrastructure for the i2c kind. It can be added as a normal i2c-device in the
> board code. To enable functions a platform_data struct has to be provided, that
> describes what parts of the chip are to be used.
>
> Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
> ---
> drivers/mfd/Kconfig | 4 ++
> drivers/mfd/Makefile | 1 +
> drivers/mfd/stmpe-i2c.c | 153 +++++++++++++++++++++++++++++++++++++++++++++++
> include/mfd/stmpe-i2c.h | 56 +++++++++++++++++
> 4 files changed, 214 insertions(+)
> create mode 100644 drivers/mfd/stmpe-i2c.c
> create mode 100644 include/mfd/stmpe-i2c.h
>
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index af67935..20eef86 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -33,4 +33,8 @@ config I2C_TWL6030
> select I2C_TWLCORE
> bool "TWL6030 driver"
>
> +config I2C_STMPE
> + depends on I2C
> + bool "STMPE-i2c driver"
> +
> endmenu
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index e11223b..792ae2d 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -6,3 +6,4 @@ obj-$(CONFIG_I2C_LP3972) += lp3972.o
> obj-$(CONFIG_I2C_TWLCORE) += twl-core.o
> obj-$(CONFIG_I2C_TWL4030) += twl4030.o
> obj-$(CONFIG_I2C_TWL6030) += twl6030.o
> +obj-$(CONFIG_I2C_STMPE) += stmpe-i2c.o
> diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c
> new file mode 100644
> index 0000000..53b3d06
> --- /dev/null
> +++ b/drivers/mfd/stmpe-i2c.c
> @@ -0,0 +1,153 @@
> +/*
> + * Copyright (C) 2012 Pengutronix
> + * Steffen Trumtrar <s.trumtrar@pengutronix.de>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include <common.h>
> +#include <init.h>
> +#include <driver.h>
> +#include <xfuncs.h>
> +#include <errno.h>
> +
> +#include <i2c/i2c.h>
> +#include <mfd/stmpe-i2c.h>
> +
> +#define DRIVERNAME "stmpe-i2c"
> +
> +#define to_stmpe(a) container_of(a, struct stmpe, cdev)
> +
> +int stmpe_reg_read(struct stmpe *stmpe, u32 reg, u8 *val)
> +{
> + int ret;
> +
> + ret = i2c_read_reg(stmpe->client, reg, val, 1);
> +
> + return ret == 1 ? 0 : ret;
> +}
> +EXPORT_SYMBOL(stmpe_reg_read)
> +
> +int stmpe_reg_write(struct stmpe *stmpe, u32 reg, u8 val)
> +{
> + int ret;
> +
> + ret = i2c_write_reg(stmpe->client, reg, &val, 1);
> +
> + return ret == 1 ? 0 : ret;
> +}
> +EXPORT_SYMBOL(stmpe_reg_write)
> +
> +int stmpe_set_bits(struct stmpe *stmpe, u32 reg, u8 mask, u8 val)
> +{
> + u8 tmp;
> + int err;
> +
> + err = stmpe_reg_read(stmpe, reg, &tmp);
> + tmp = (tmp & ~mask) | val;
> +
> + if (!err)
> + err = stmpe_reg_write(stmpe, reg, tmp);
> +
> + return err;
> +}
> +EXPORT_SYMBOL(stmpe_set_bits);
> +
> +static ssize_t stmpe_read(struct cdev *cdev, void *_buf, size_t count, loff_t offset, ulong flags)
> +{
> + struct stmpe *stmpe = to_stmpe(cdev);
> + u8 *buf = _buf;
> + size_t i = count;
> + int err;
> +
> + while (i) {
> + err = stmpe_reg_read(stmpe, offset, buf);
> + if (err)
> + return (ssize_t)err;
> + buf++;
> + i--;
> + offset++;
> + }
> +
> + return count;
> +}
> +
> +static ssize_t stmpe_write(struct cdev *cdev, const void *_buf, size_t count, loff_t offset, ulong flags)
> +{
> + struct stmpe *stmpe = to_stmpe(cdev);
> + const u8 *buf = _buf;
> + size_t i = count;
> + int err;
> +
> + while (i) {
> + err = stmpe_reg_write(stmpe, offset, *buf);
> + if (err)
> + return (ssize_t)err;
> + buf++;
> + i--;
> + offset++;
> + }
> +
> + return count;
> +}
> +
> +static struct file_operations stmpe_fops = {
> + .lseek = dev_lseek_default,
> + .read = stmpe_read,
> + .write = stmpe_write,
> +};
> +
> +static struct stmpe_client_info i2c_ci = {
> + .read_reg = stmpe_reg_read,
> + .write_reg = stmpe_reg_write,
> +};
> +
> +static int stmpe_probe(struct device_d *dev)
> +{
> + struct stmpe_platform_data *pdata = dev->platform_data;
> + struct stmpe *stmpe_dev;
> +
> + if (!pdata) {
> + dev_dbg(dev, "no platform data\n");
> + return -ENODEV;
> + }
> +
> + stmpe_dev = xzalloc(sizeof(struct stmpe));
> + stmpe_dev->cdev.name = DRIVERNAME;
> + stmpe_dev->client = to_i2c_client(dev);
> + stmpe_dev->cdev.size = 191; /* 191 known registers */
> + stmpe_dev->cdev.dev = dev;
> + stmpe_dev->cdev.ops = &stmpe_fops;
> + stmpe_dev->pdata = pdata;
> + dev->priv = stmpe_dev;
> + i2c_ci.stmpe = stmpe_dev;
> +
> + if (pdata->blocks &= STMPE_BLOCK_GPIO)
> + add_generic_device("stmpe-gpio", 0, NULL, pdata->base, 0x10, IORESOURCE_MEM, &i2c_ci);
it doesn't have any iomem
> +
> + devfs_create(&stmpe_dev->cdev);
> +
> + return 0;
> +}
> +
> +static struct driver_d stmpe_driver = {
> + .name = DRIVERNAME,
> + .probe = stmpe_probe,
> +};
> +
> +static int stmpe_init(void)
> +{
> + register_driver(&stmpe_driver);
> + return 0;
> +}
> +
> +device_initcall(stmpe_init);
> diff --git a/include/mfd/stmpe-i2c.h b/include/mfd/stmpe-i2c.h
> new file mode 100644
> index 0000000..c36aed9
> --- /dev/null
> +++ b/include/mfd/stmpe-i2c.h
> @@ -0,0 +1,56 @@
> +/*
> + * Copyright (C) 2012 Pengutronix
> + * Steffen Trumtrar <s.trumtrar@pengutronix.de>
> + *
> + * This file is released under the GPLv2
> + *
> + */
> +
> +#ifndef __ASM_ARCH_STMPE_H
> +#define __ASM_ARCH_STMPE_H
> +
> +enum stmpe_revision {
> + STMPE610,
> + STMPE801,
> + STMPE811,
> + STMPE1601,
> + STMPE2401,
> + STMPE2403,
> + STMPE_NBR_PARTS
> +};
> +
> +enum stmpe_blocks {
> + STMPE_BLOCK_GPIO = 1 << 0,
> + STMPE_BLOCK_KEYPAD = 1 << 1,
> + STMPE_BLOCK_TOUCHSCREEN = 1 << 2,
> + STMPE_BLOCK_ADC = 1 << 3,
> + STMPE_BLOCK_PWM = 1 << 4,
> + STMPE_BLOCK_ROTATOR = 1 << 5,
> +};
> +
> +struct stmpe_platform_data {
> + enum stmpe_revision revision;
> + enum stmpe_blocks blocks;
> + void __iomem *base;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
unused?
> + int gpio_base;
> +};
> +
> +struct stmpe {
> + struct cdev cdev;
> + struct i2c_client *client;
> + struct stmpe_platform_data *pdata;
> +};
> +
> +struct stmpe_client_info {
> + struct stmpe *stmpe;
> + int (*read_reg)(struct stmpe *stmpe, u32 reg, u8 *val);
> + int (*write_reg)(struct stmpe *stmpe, u32 reg, u8 val);
> +};
> +
> +extern struct stmpe *stmpe_get(void);
> +
> +extern int stmpe_reg_read(struct stmpe *priv, u32 reg, u8 *val);
> +extern int stmpe_reg_write(struct stmpe *priv, u32 reg, u8 val);
> +extern int stmpe_set_bits(struct stmpe *priv, u32 reg, u8 mask, u8 val);
> +
> +#endif /* __ASM_ARCH_STMPE_H */
>
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]
[-- Attachment #2: Type: text/plain, Size: 149 bytes --]
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v3 1/2] mfd: add stmpe-i2c driver
2012-09-04 9:58 ` [PATCH v3 1/2] mfd: add stmpe-i2c driver Steffen Trumtrar
2012-09-04 11:26 ` Marc Kleine-Budde
@ 2012-09-05 6:32 ` Sascha Hauer
1 sibling, 0 replies; 5+ messages in thread
From: Sascha Hauer @ 2012-09-05 6:32 UTC (permalink / raw)
To: Steffen Trumtrar; +Cc: barebox
On Tue, Sep 04, 2012 at 11:58:45AM +0200, Steffen Trumtrar wrote:
> The stmpe mfds can be connected via i2c and spi. This driver provides the basic
> infrastructure for the i2c kind. It can be added as a normal i2c-device in the
> board code. To enable functions a platform_data struct has to be provided, that
> describes what parts of the chip are to be used.
>
> Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
> ---
> +static struct stmpe_client_info i2c_ci = {
> + .read_reg = stmpe_reg_read,
> + .write_reg = stmpe_reg_write,
> +};
> +
> +static int stmpe_probe(struct device_d *dev)
> +{
> + struct stmpe_platform_data *pdata = dev->platform_data;
> + struct stmpe *stmpe_dev;
> +
> + if (!pdata) {
> + dev_dbg(dev, "no platform data\n");
> + return -ENODEV;
> + }
> +
> + stmpe_dev = xzalloc(sizeof(struct stmpe));
> + stmpe_dev->cdev.name = DRIVERNAME;
> + stmpe_dev->client = to_i2c_client(dev);
> + stmpe_dev->cdev.size = 191; /* 191 known registers */
> + stmpe_dev->cdev.dev = dev;
> + stmpe_dev->cdev.ops = &stmpe_fops;
> + stmpe_dev->pdata = pdata;
> + dev->priv = stmpe_dev;
> + i2c_ci.stmpe = stmpe_dev;
This breaks for multiple instances of a stmpe device. You have to
allocate a static struct stmpe_client_info dynamically.
> +
> + if (pdata->blocks &= STMPE_BLOCK_GPIO)
> + add_generic_device("stmpe-gpio", 0, NULL, pdata->base, 0x10, IORESOURCE_MEM, &i2c_ci);
This issues:
drivers/mfd/stmpe-i2c.c: In function 'stmpe_probe':
drivers/mfd/stmpe-i2c.c:135:3: warning: passing argument 4 of 'add_generic_device' makes integer from pointer without a cast [enabled by default]
include/driver.h:197:18: note: expected 'resource_size_t' but argument is of type 'void *'
The base and size refer to the iomem space. As an i2c device we do not
have iomem here, so this is wrong.
Looking further at it it seems to be unused by the gpio driver anyway,
so you can just pass 0, 0 as iomem and size.
> +struct stmpe_platform_data {
> + enum stmpe_revision revision;
> + enum stmpe_blocks blocks;
> + void __iomem *base;
This is unused, please remove.
> + int gpio_base;
> +};
> +
> +
> +extern int stmpe_reg_read(struct stmpe *priv, u32 reg, u8 *val);
> +extern int stmpe_reg_write(struct stmpe *priv, u32 reg, u8 val);
> +extern int stmpe_set_bits(struct stmpe *priv, u32 reg, u8 mask, u8 val);
no 'extern' for function prototypes please.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2012-09-05 6:32 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-09-04 9:58 [PATCH v3 0/2] Add stmpe mfd Steffen Trumtrar
2012-09-04 9:58 ` [PATCH v3 1/2] mfd: add stmpe-i2c driver Steffen Trumtrar
2012-09-04 11:26 ` Marc Kleine-Budde
2012-09-05 6:32 ` Sascha Hauer
2012-09-04 9:58 ` [PATCH v3 2/2] gpio: add driver for stmpe io-expander Steffen Trumtrar
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox