summaryrefslogtreecommitdiff
path: root/drivers/mfd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/tc6393xb.c130
1 files changed, 94 insertions, 36 deletions
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
index 3d5b14c60e20..0be5731685b4 100644
--- a/drivers/mfd/tc6393xb.c
+++ b/drivers/mfd/tc6393xb.c
@@ -22,6 +22,8 @@
#include <linux/mfd/tmio.h>
#include <linux/mfd/tc6393xb.h>
#include <linux/gpio/driver.h>
+#include <linux/gpio/machine.h>
+#include <linux/gpio/consumer.h>
#include <linux/slab.h>
#define SCR_REVID 0x08 /* b Revision ID */
@@ -87,8 +89,10 @@
struct tc6393xb {
void __iomem *scr;
+ struct device *dev;
struct gpio_chip gpio;
+ struct gpio_desc *vcc_on;
struct clk *clk; /* 3,6 Mhz */
@@ -497,17 +501,93 @@ static int tc6393xb_gpio_direction_output(struct gpio_chip *chip,
return 0;
}
-static int tc6393xb_register_gpio(struct tc6393xb *tc6393xb, int gpio_base)
+/*
+ * TC6393XB GPIOs as used on TOSA, are the only user of this chip.
+ * GPIOs 2, 5, 8 and 13 are not connected.
+ */
+#define TOSA_GPIO_TG_ON 0
+#define TOSA_GPIO_L_MUTE 1
+#define TOSA_GPIO_BL_C20MA 3
+#define TOSA_GPIO_CARD_VCC_ON 4
+#define TOSA_GPIO_CHARGE_OFF 6
+#define TOSA_GPIO_CHARGE_OFF_JC 7
+#define TOSA_GPIO_BAT0_V_ON 9
+#define TOSA_GPIO_BAT1_V_ON 10
+#define TOSA_GPIO_BU_CHRG_ON 11
+#define TOSA_GPIO_BAT_SW_ON 12
+#define TOSA_GPIO_BAT0_TH_ON 14
+#define TOSA_GPIO_BAT1_TH_ON 15
+
+
+GPIO_LOOKUP_SINGLE(tosa_lcd_gpio_lookup, "spi2.0", "tc6393xb",
+ TOSA_GPIO_TG_ON, "tg #pwr", GPIO_ACTIVE_HIGH);
+
+GPIO_LOOKUP_SINGLE(tosa_lcd_bl_gpio_lookup, "i2c-tos-bl", "tc6393xb",
+ TOSA_GPIO_BL_C20MA, "backlight", GPIO_ACTIVE_HIGH);
+
+GPIO_LOOKUP_SINGLE(tosa_audio_gpio_lookup, "tosa-audio", "tc6393xb",
+ TOSA_GPIO_L_MUTE, NULL, GPIO_ACTIVE_HIGH);
+
+static struct gpiod_lookup_table tosa_battery_gpio_lookup = {
+ .dev_id = "wm97xx-battery",
+ .table = {
+ GPIO_LOOKUP("tc6393xb", TOSA_GPIO_CHARGE_OFF,
+ "main charge off", GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP("tc6393xb", TOSA_GPIO_CHARGE_OFF_JC,
+ "jacket charge off", GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP("tc6393xb", TOSA_GPIO_BAT0_V_ON,
+ "main battery", GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP("tc6393xb", TOSA_GPIO_BAT1_V_ON,
+ "jacket battery", GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP("tc6393xb", TOSA_GPIO_BU_CHRG_ON,
+ "backup battery", GPIO_ACTIVE_HIGH),
+ /* BAT1 and BAT0 thermistors appear to be swapped */
+ GPIO_LOOKUP("tc6393xb", TOSA_GPIO_BAT1_TH_ON,
+ "main battery temp", GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP("tc6393xb", TOSA_GPIO_BAT0_TH_ON,
+ "jacket battery temp", GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP("tc6393xb", TOSA_GPIO_BAT_SW_ON,
+ "battery switch", GPIO_ACTIVE_HIGH),
+ { },
+ },
+};
+
+static struct gpiod_lookup_table *tc6393xb_gpio_lookups[] = {
+ &tosa_lcd_gpio_lookup,
+ &tosa_lcd_bl_gpio_lookup,
+ &tosa_audio_gpio_lookup,
+ &tosa_battery_gpio_lookup,
+};
+
+static int tc6393xb_register_gpio(struct tc6393xb *tc6393xb)
{
- tc6393xb->gpio.label = "tc6393xb";
- tc6393xb->gpio.base = gpio_base;
- tc6393xb->gpio.ngpio = 16;
- tc6393xb->gpio.set = tc6393xb_gpio_set;
- tc6393xb->gpio.get = tc6393xb_gpio_get;
- tc6393xb->gpio.direction_input = tc6393xb_gpio_direction_input;
- tc6393xb->gpio.direction_output = tc6393xb_gpio_direction_output;
-
- return gpiochip_add_data(&tc6393xb->gpio, tc6393xb);
+ struct gpio_chip *gc = &tc6393xb->gpio;
+ struct device *dev = tc6393xb->dev;
+ int ret;
+
+ gc->label = "tc6393xb";
+ gc->base = -1; /* Dynamic allocation */
+ gc->ngpio = 16;
+ gc->set = tc6393xb_gpio_set;
+ gc->get = tc6393xb_gpio_get;
+ gc->direction_input = tc6393xb_gpio_direction_input;
+ gc->direction_output = tc6393xb_gpio_direction_output;
+
+ ret = devm_gpiochip_add_data(dev, gc, tc6393xb);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to add GPIO chip\n");
+
+ /* Register descriptor look-ups for consumers */
+ gpiod_add_lookup_tables(tc6393xb_gpio_lookups, ARRAY_SIZE(tc6393xb_gpio_lookups));
+
+ /* Request some of our own GPIOs */
+ tc6393xb->vcc_on = gpiochip_request_own_desc(gc, TOSA_GPIO_CARD_VCC_ON, "VCC ON",
+ GPIO_ACTIVE_HIGH, GPIOD_OUT_HIGH);
+ if (IS_ERR(tc6393xb->vcc_on))
+ return dev_err_probe(dev, PTR_ERR(tc6393xb->vcc_on),
+ "failed to request VCC ON GPIO\n");
+
+ return 0;
}
/*--------------------------------------------------------------------------*/
@@ -617,6 +697,7 @@ static int tc6393xb_probe(struct platform_device *dev)
ret = -ENOMEM;
goto err_kzalloc;
}
+ tc6393xb->dev = &dev->dev;
raw_spin_lock_init(&tc6393xb->lock);
@@ -676,22 +757,12 @@ static int tc6393xb_probe(struct platform_device *dev)
tmio_ioread8(tc6393xb->scr + SCR_REVID),
(unsigned long) iomem->start, tc6393xb->irq);
- tc6393xb->gpio.base = -1;
-
- if (tcpd->gpio_base >= 0) {
- ret = tc6393xb_register_gpio(tc6393xb, tcpd->gpio_base);
- if (ret)
- goto err_gpio_add;
- }
+ ret = tc6393xb_register_gpio(tc6393xb);
+ if (ret)
+ goto err_gpio_add;
tc6393xb_attach_irq(dev);
- if (tcpd->setup) {
- ret = tcpd->setup(dev);
- if (ret)
- goto err_setup;
- }
-
tc6393xb_cells[TC6393XB_CELL_NAND].platform_data = tcpd->nand_data;
tc6393xb_cells[TC6393XB_CELL_NAND].pdata_size =
sizeof(*tcpd->nand_data);
@@ -705,15 +776,8 @@ static int tc6393xb_probe(struct platform_device *dev)
if (!ret)
return 0;
- if (tcpd->teardown)
- tcpd->teardown(dev);
-
-err_setup:
tc6393xb_detach_irq(dev);
-
err_gpio_add:
- if (tc6393xb->gpio.base != -1)
- gpiochip_remove(&tc6393xb->gpio);
tcpd->disable(dev);
err_enable:
clk_disable_unprepare(tc6393xb->clk);
@@ -738,14 +802,8 @@ static int tc6393xb_remove(struct platform_device *dev)
mfd_remove_devices(&dev->dev);
- if (tcpd->teardown)
- tcpd->teardown(dev);
-
tc6393xb_detach_irq(dev);
- if (tc6393xb->gpio.base != -1)
- gpiochip_remove(&tc6393xb->gpio);
-
ret = tcpd->disable(dev);
clk_disable_unprepare(tc6393xb->clk);
iounmap(tc6393xb->scr);