]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/mfd/wm8350-core.c
Merge branch 'drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
[linux-2.6-omap-h63xx.git] / drivers / mfd / wm8350-core.c
index e74829f298b9ea304a348e6c1c2ca81262319ece..0d47fb9e4b3bcec5248e510504d8c6b5f2b059ec 100644 (file)
@@ -183,6 +183,9 @@ static int wm8350_write(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *src)
                        (wm8350->reg_cache[i] & ~wm8350_reg_io_map[i].writable)
                        | src[i - reg];
 
+               /* Don't store volatile bits */
+               wm8350->reg_cache[i] &= ~wm8350_reg_io_map[i].vol;
+
                src[i - reg] = cpu_to_be16(src[i - reg]);
        }
 
@@ -1120,6 +1123,7 @@ static int wm8350_create_cache(struct wm8350 *wm8350, int mode)
                        }
                        value = be16_to_cpu(value);
                        value &= wm8350_reg_io_map[i].readable;
+                       value &= ~wm8350_reg_io_map[i].vol;
                        wm8350->reg_cache[i] = value;
                } else
                        wm8350->reg_cache[i] = reg_map[i];
@@ -1128,14 +1132,38 @@ static int wm8350_create_cache(struct wm8350 *wm8350, int mode)
 out:
        return ret;
 }
-EXPORT_SYMBOL_GPL(wm8350_create_cache);
+
+/*
+ * Register a client device.  This is non-fatal since there is no need to
+ * fail the entire device init due to a single platform device failing.
+ */
+static void wm8350_client_dev_register(struct wm8350 *wm8350,
+                                      const char *name,
+                                      struct platform_device **pdev)
+{
+       int ret;
+
+       *pdev = platform_device_alloc(name, -1);
+       if (pdev == NULL) {
+               dev_err(wm8350->dev, "Failed to allocate %s\n", name);
+               return;
+       }
+
+       (*pdev)->dev.parent = wm8350->dev;
+       platform_set_drvdata(*pdev, wm8350);
+       ret = platform_device_add(*pdev);
+       if (ret != 0) {
+               dev_err(wm8350->dev, "Failed to register %s: %d\n", name, ret);
+               platform_device_put(*pdev);
+               *pdev = NULL;
+       }
+}
 
 int wm8350_device_init(struct wm8350 *wm8350, int irq,
                       struct wm8350_platform_data *pdata)
 {
        int ret = -EINVAL;
        u16 id1, id2, mask, mode;
-       int i;
 
        /* get WM8350 revision and config mode */
        wm8350->read_dev(wm8350, WM8350_RESET_ID, sizeof(id1), &id1);
@@ -1192,7 +1220,7 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
 
        mutex_init(&wm8350->irq_mutex);
        INIT_WORK(&wm8350->irq_work, wm8350_irq_worker);
-       if (irq != NO_IRQ) {
+       if (irq) {
                ret = request_irq(irq, wm8350_irq, 0,
                                  "wm8350", wm8350);
                if (ret != 0) {
@@ -1208,6 +1236,15 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
 
        wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0x0);
 
+       wm8350_client_dev_register(wm8350, "wm8350-codec",
+                                  &(wm8350->codec.pdev));
+       wm8350_client_dev_register(wm8350, "wm8350-gpio",
+                                  &(wm8350->gpio.pdev));
+       wm8350_client_dev_register(wm8350, "wm8350-power",
+                                  &(wm8350->power.pdev));
+       wm8350_client_dev_register(wm8350, "wm8350-rtc", &(wm8350->rtc.pdev));
+       wm8350_client_dev_register(wm8350, "wm8350-wdt", &(wm8350->wdt.pdev));
+
        return 0;
 
 err:
@@ -1218,6 +1255,17 @@ EXPORT_SYMBOL_GPL(wm8350_device_init);
 
 void wm8350_device_exit(struct wm8350 *wm8350)
 {
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(wm8350->pmic.pdev); i++)
+               platform_device_unregister(wm8350->pmic.pdev[i]);
+
+       platform_device_unregister(wm8350->wdt.pdev);
+       platform_device_unregister(wm8350->rtc.pdev);
+       platform_device_unregister(wm8350->power.pdev);
+       platform_device_unregister(wm8350->gpio.pdev);
+       platform_device_unregister(wm8350->codec.pdev);
+
        free_irq(wm8350->chip_irq, wm8350);
        flush_work(&wm8350->irq_work);
        kfree(wm8350->reg_cache);