public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/4] tps65912: gpio: add gpio driver
@ 2011-05-10 20:25 Margarita Olaya
  2011-05-10 20:39 ` Mark Brown
  0 siblings, 1 reply; 2+ messages in thread
From: Margarita Olaya @ 2011-05-10 20:25 UTC (permalink / raw)
  To: linux-kernel; +Cc: Liam Girdwood, Mark Brown, grant.likely

TPS65912 has five GPIOs that can be configured for different
purposes.

Signed-off-by: Margarita Olaya Cabrera <magi@slimlogic.co.uk>
---
 drivers/mfd/Makefile         |    2 +-
 drivers/mfd/tps65912-gpio.c  |   94 ++++++++++++++++++++++++++++++++++++++++++
 drivers/mfd/tps65912.c       |   14 ++++++
 include/linux/mfd/tps65912.h |    3 +
 4 files changed, 112 insertions(+), 1 deletions(-)
 create mode 100644 drivers/mfd/tps65912-gpio.c

diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 9d60cfd..687bd2a 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -31,7 +31,7 @@ wm8350-objs			+= wm8350-irq.o
 obj-$(CONFIG_MFD_WM8350)	+= wm8350.o
 obj-$(CONFIG_MFD_WM8350_I2C)	+= wm8350-i2c.o
 obj-$(CONFIG_MFD_WM8994)	+= wm8994-core.o wm8994-irq.o
-obj-$(CONFIG_MFD_TPS65912)	+= tps65912.o
+obj-$(CONFIG_MFD_TPS65912)	+= tps65912.o tps65912-gpio.o

 obj-$(CONFIG_TPS6105X)		+= tps6105x.o
 obj-$(CONFIG_TPS65010)		+= tps65010.o
diff --git a/drivers/mfd/tps65912-gpio.c b/drivers/mfd/tps65912-gpio.c
new file mode 100644
index 0000000..fa94674
--- /dev/null
+++ b/drivers/mfd/tps65912-gpio.c
@@ -0,0 +1,94 @@
+/*
+ * tps65912-gpio.c  --	TI TPS6591x
+ *
+ * Copyright 2011 Texas Instruments Inc.
+ *
+ * Author: Margarita Olaya <magi@slimlogic.co.uk>
+ *
+ *  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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/mfd/tps65912.h>
+
+static int tps6591x_gpio_get(struct gpio_chip *gc, unsigned offset)
+{
+	struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio);
+	uint8_t val;
+
+	tps65912->read(tps65912, TPS65912_GPIO1 + offset, 1, &val);
+
+	if (val & GPIO_STS_MASK)
+		return 1;
+
+	return 0;
+}
+
+static void tps6591x_gpio_set(struct gpio_chip *gc, unsigned offset,
+			      int value)
+{
+	struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio);
+
+	if (value)
+		tps65912_set_bits(tps65912, TPS65912_GPIO1 + offset,
+							GPIO_SET_MASK);
+	else
+		tps65912_set_bits(tps65912, TPS65912_GPIO1 + offset,
+							~GPIO_SET_MASK);
+}
+
+static int tps6591x_gpio_output(struct gpio_chip *gc, unsigned offset,
+				int value)
+{
+	struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio);
+
+	/* Set the initial value */
+	tps6591x_gpio_set(gc, offset, value);
+
+	return tps65912_set_bits(tps65912, TPS65912_GPIO1 + offset,
+								GPIO_CFG_MASK);
+}
+
+static int tps6591x_gpio_input(struct gpio_chip *gc, unsigned offset)
+{
+	struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio);
+
+	return tps65912_clear_bits(tps65912, TPS65912_GPIO1 + offset,
+							~GPIO_CFG_MASK);
+
+}
+
+void tps65912_gpio_init(struct tps65912 *tps65912, int gpio_base)
+{
+	int ret;
+
+	if (!gpio_base)
+		return;
+
+	tps65912->gpio.owner		= THIS_MODULE;
+	/* FIXME: should we use compilation macro for SPI */
+	tps65912->gpio.label		= tps65912->i2c_client->name;
+	tps65912->gpio.dev		= tps65912->dev;
+	tps65912->gpio.base		= gpio_base;
+	tps65912->gpio.ngpio		= 5;
+	tps65912->gpio.can_sleep	= 1;
+
+	tps65912->gpio.direction_input	= tps6591x_gpio_input;
+	tps65912->gpio.direction_output	= tps6591x_gpio_output;
+	tps65912->gpio.set		= tps6591x_gpio_set;
+	tps65912->gpio.get		= tps6591x_gpio_get;
+
+	ret = gpiochip_add(&tps65912->gpio);
+
+	if (ret)
+		dev_warn(tps65912->dev, "GPIO registration failed: %d\n", ret);
+}
+
diff --git a/drivers/mfd/tps65912.c b/drivers/mfd/tps65912.c
index a6d5fce..83dbc3a 100644
--- a/drivers/mfd/tps65912.c
+++ b/drivers/mfd/tps65912.c
@@ -88,8 +88,13 @@ static int tps65912_i2c_probe(struct i2c_client *i2c,
 			    const struct i2c_device_id *id)
 {
 	struct tps65912 *tps65912;
+	struct tps65912_board *pmic_plat_data;
 	int ret = 0;

+	pmic_plat_data = dev_get_platdata(&i2c->dev);
+	if (!pmic_plat_data)
+		return -EINVAL;
+
 	tps65912 = kzalloc(sizeof(struct tps65912), GFP_KERNEL);
 	if (tps65912 == NULL)
 		return -ENOMEM;
@@ -107,6 +112,8 @@ static int tps65912_i2c_probe(struct i2c_client *i2c,
 	if (ret < 0)
 		goto err;

+	tps65912_gpio_init(tps65912, pmic_plat_data->gpio_base);
+
 	return ret;

 err:
@@ -207,9 +214,14 @@ static int tps65912_spi_read(struct tps65912
*tps65912, u8 addr,
 static int __devinit tps65912_spi_probe(struct spi_device *spi)
 {
 	struct tps65912 *tps65912;
+	struct tps65912_board *pmic_plat_data;
 	struct tps65912_platform_data *init_data;
 	int dcdc_avs, value, ret = 0;

+	pmic_plat_data = dev_get_platdata(&spi->dev);
+	if (!pmic_plat_data)
+		return -ENODEV;
+
 	init_data = kzalloc(sizeof(struct tps65912_platform_data),
 								GFP_KERNEL);
 	if (init_data == NULL)
@@ -241,6 +253,8 @@ static int __devinit tps65912_spi_probe(struct
spi_device *spi)
 	if (ret < 0)
 		goto err;

+	tps65912_gpio_init(tps65912, pmic_plat_data->gpio_base);
+
 	return ret;

 err:
diff --git a/include/linux/mfd/tps65912.h b/include/linux/mfd/tps65912.h
index 1d0aab8..bcfdc0d 100644
--- a/include/linux/mfd/tps65912.h
+++ b/include/linux/mfd/tps65912.h
@@ -405,6 +405,7 @@
  * Board platform dat may be used to initialize regulators.
  */
 struct tps65912_board {
+	int gpio_base;
 	struct regulator_init_data *tps65912_pmic_init_data;
 };

@@ -453,5 +454,7 @@ unsigned int tps_chip(void);

 int tps65912_set_bits(struct tps65912 *tps65912, u8 reg, u8 mask);
 int tps65912_clear_bits(struct tps65912 *tps65912, u8 reg, u8 mask);
+void tps65912_gpio_init(struct tps65912 *tps65912, int gpio_base);
+
 #endif /*  __LINUX_MFD_TPS65912_H */

-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH 2/4] tps65912: gpio: add gpio driver
  2011-05-10 20:25 [PATCH 2/4] tps65912: gpio: add gpio driver Margarita Olaya
@ 2011-05-10 20:39 ` Mark Brown
  0 siblings, 0 replies; 2+ messages in thread
From: Mark Brown @ 2011-05-10 20:39 UTC (permalink / raw)
  To: Margarita Olaya; +Cc: linux-kernel, Liam Girdwood, grant.likely

On Tue, May 10, 2011 at 03:25:35PM -0500, Margarita Olaya wrote:

>  drivers/mfd/Makefile         |    2 +-
>  drivers/mfd/tps65912-gpio.c  |   94 ++++++++++++++++++++++++++++++++++++++++++

We're mostly moving GPIO drivers to drivers/gpio these days - there's a
push to move drivers into the appropriate subsystems (particularly
focused on arch/arm but still).

> +static void tps6591x_gpio_set(struct gpio_chip *gc, unsigned offset,
> +			      int value)
> +{
> +	struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio);
> +
> +	if (value)
> +		tps65912_set_bits(tps65912, TPS65912_GPIO1 + offset,
> +							GPIO_SET_MASK);
> +	else
> +		tps65912_set_bits(tps65912, TPS65912_GPIO1 + offset,
> +							~GPIO_SET_MASK);

Should one of those be clear_bits() given that there's such a function?

> +	tps65912->gpio.owner		= THIS_MODULE;
> +	/* FIXME: should we use compilation macro for SPI */
> +	tps65912->gpio.label		= tps65912->i2c_client->name;

I guess dev_name() would do a reasonable job?

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2011-05-10 20:39 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-05-10 20:25 [PATCH 2/4] tps65912: gpio: add gpio driver Margarita Olaya
2011-05-10 20:39 ` Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox