summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2019-06-01 00:37:56 +0200
committerWolfram Sang <wsa@the-dreams.de>2019-06-12 13:20:23 +0200
commitfdb7e884ad617f8aa69abdd7f39e3fdac85e081e (patch)
tree8040de47cccdb9797aa15272df7d0afde3431307 /drivers
parented7357c9f9b6a560992446c37260be25e514c4ab (diff)
i2c: iop: Use GPIO descriptors
The IOP3xx has some elaborate code to directly slam the GPIO lines multiplexed with I2C down low before enablement, apparently a workaround for a hardware bug found in the early chips. After consulting the developer documentation for IOP80321 and IOP80331 I can clearly see that this may be useful for IOP80321 family (mach-iop32x) but it is highly dubious for any 80331 series or later chip: in these chips the lines are not multiplexed for UARTs. We convert the code to pass optional GPIO descriptors and register these only on the 80321-based boards where it makes sense, optionally obtain them in the driver and use the gpiod_set_raw_value() to ascertain the line gets driven low when needed. The GPIO driver does not give the GPIO chip a reasonable label so the patch also adds that so that these machine descriptor tables can be used. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpio/gpio-iop.c1
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.c32
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.h2
3 files changed, 24 insertions, 11 deletions
diff --git a/drivers/gpio/gpio-iop.c b/drivers/gpio/gpio-iop.c
index 11b77d868c89..e9546d6c7451 100644
--- a/drivers/gpio/gpio-iop.c
+++ b/drivers/gpio/gpio-iop.c
@@ -40,6 +40,7 @@ static int iop3xx_gpio_probe(struct platform_device *pdev)
gc->base = 0;
gc->owner = THIS_MODULE;
+ gc->label = "gpio-iop";
return devm_gpiochip_add_data(&pdev->dev, gc, NULL);
}
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index a34cb3848280..eafc1a4d8656 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -38,7 +38,7 @@
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/io.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include "i2c-iop3xx.h"
@@ -71,17 +71,16 @@ iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
/*
* Every time unit enable is asserted, GPOD needs to be cleared
- * on IOP3XX to avoid data corruption on the bus.
+ * on IOP3XX to avoid data corruption on the bus. We use the
+ * gpiod_set_raw_value() to make sure the 0 hits the hardware
+ * GPOD register. These descriptors are only passed along to
+ * the device if this is necessary.
*/
-#if defined(CONFIG_ARCH_IOP32X) || defined(CONFIG_ARCH_IOP33X)
- if (iop3xx_adap->id == 0) {
- gpio_set_value(7, 0);
- gpio_set_value(6, 0);
- } else {
- gpio_set_value(5, 0);
- gpio_set_value(4, 0);
- }
-#endif
+ if (iop3xx_adap->gpio_scl)
+ gpiod_set_raw_value(iop3xx_adap->gpio_scl, 0);
+ if (iop3xx_adap->gpio_sda)
+ gpiod_set_raw_value(iop3xx_adap->gpio_sda, 0);
+
/* NB SR bits not same position as CR IE bits :-( */
iop3xx_adap->SR_enabled =
IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD |
@@ -434,6 +433,17 @@ iop3xx_i2c_probe(struct platform_device *pdev)
goto free_adapter;
}
+ adapter_data->gpio_scl = devm_gpiod_get_optional(&pdev->dev,
+ "scl",
+ GPIOD_ASIS);
+ if (IS_ERR(adapter_data->gpio_scl))
+ return PTR_ERR(adapter_data->gpio_scl);
+ adapter_data->gpio_sda = devm_gpiod_get_optional(&pdev->dev,
+ "sda",
+ GPIOD_ASIS);
+ if (IS_ERR(adapter_data->gpio_sda))
+ return PTR_ERR(adapter_data->gpio_sda);
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
ret = -ENODEV;
diff --git a/drivers/i2c/busses/i2c-iop3xx.h b/drivers/i2c/busses/i2c-iop3xx.h
index 2d6929c2bd92..231897838386 100644
--- a/drivers/i2c/busses/i2c-iop3xx.h
+++ b/drivers/i2c/busses/i2c-iop3xx.h
@@ -98,6 +98,8 @@ struct i2c_algo_iop3xx_data {
spinlock_t lock;
u32 SR_enabled, SR_received;
int id;
+ struct gpio_desc *gpio_scl;
+ struct gpio_desc *gpio_sda;
};
#endif /* I2C_IOP3XX_H */