MFD: ucb1x00-core: add handling for ucb1x00 reset
authorRussell King <rmk+kernel@arm.linux.org.uk>
Sun, 22 Jan 2012 19:02:25 +0000 (19:02 +0000)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Sat, 18 Feb 2012 23:15:32 +0000 (23:15 +0000)
Provide a way to handle the software controlled ucb1x00 reset signal
from the ucb1x00-core driver without having to code platform specifics
into these drivers.

Acked-by: Jochen Friedrich <jochen@scram.de>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
drivers/mfd/ucb1x00-core.c
include/linux/mfd/ucb1x00.h

index cc1c0dce7bd91b311f663a73e9935d1cbfcff4ed..42eee633b86407446372eda644eb143eac245d78 100644 (file)
@@ -530,13 +530,17 @@ static struct class ucb1x00_class = {
 
 static int ucb1x00_probe(struct mcp *mcp)
 {
-       struct ucb1x00 *ucb;
+       struct ucb1x00_plat_data *pdata = mcp->attached_device.platform_data;
        struct ucb1x00_driver *drv;
-       struct ucb1x00_plat_data *pdata;
+       struct ucb1x00 *ucb;
        unsigned int id;
        int ret = -ENODEV;
        int temp;
 
+       /* Tell the platform to deassert the UCB1x00 reset */
+       if (pdata && pdata->reset)
+               pdata->reset(UCB_RST_PROBE);
+
        mcp_enable(mcp);
        id = mcp_reg_read(mcp, UCB_ID);
 
@@ -550,7 +554,6 @@ static int ucb1x00_probe(struct mcp *mcp)
        if (!ucb)
                goto err_disable;
 
-       pdata = mcp->attached_device.platform_data;
        ucb->dev.class = &ucb1x00_class;
        ucb->dev.parent = &mcp->attached_device;
        dev_set_name(&ucb->dev, "ucb1x00");
@@ -606,7 +609,7 @@ static int ucb1x00_probe(struct mcp *mcp)
        }
        mutex_unlock(&ucb1x00_mutex);
 
-       goto out;
+       return ret;
 
  err_irq:
        free_irq(ucb->irq, ucb);
@@ -618,11 +621,14 @@ static int ucb1x00_probe(struct mcp *mcp)
  err_disable:
        mcp_disable(mcp);
  out:
+       if (pdata && pdata->reset)
+               pdata->reset(UCB_RST_PROBE_FAIL);
        return ret;
 }
 
 static void ucb1x00_remove(struct mcp *mcp)
 {
+       struct ucb1x00_plat_data *pdata = mcp->attached_device.platform_data;
        struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
        struct list_head *l, *n;
        int ret;
@@ -643,6 +649,9 @@ static void ucb1x00_remove(struct mcp *mcp)
 
        free_irq(ucb->irq, ucb);
        device_unregister(&ucb->dev);
+
+       if (pdata && pdata->reset)
+               pdata->reset(UCB_RST_REMOVE);
 }
 
 int ucb1x00_register_driver(struct ucb1x00_driver *drv)
index 731b23a656c026c8d0363137db069755a16ad571..fd088cc6a4ca9dcadd85628b995a398db67c710c 100644 (file)
 #define UCB_MODE_DYN_VFLAG_ENA (1 << 12)
 #define UCB_MODE_AUD_OFF_CAN   (1 << 13)
 
+enum ucb1x00_reset {
+       UCB_RST_PROBE,
+       UCB_RST_REMOVE,
+       UCB_RST_PROBE_FAIL,
+};
+
 struct ucb1x00_plat_data {
+       void                    (*reset)(enum ucb1x00_reset);
        int                     gpio_base;
 };