/*----------------------------------------------------------------------*/
-static int add_child(unsigned chip, const char *name,
- void *pdata, unsigned pdata_len,
- bool can_wakeup, int irq0, int irq1)
+/*
+ * NOTE: We know the first 8 IRQs after pdata->base_irq are
+ * for the PIH, and the next are for the PWR_INT SIH, since
+ * that's how twl_init_irq() sets things up.
+ */
+
+static int add_children(struct twl4030_platform_data *pdata)
{
- struct platform_device *pdev;
- struct twl4030_client *twl = &twl4030_modules[chip];
- int status;
-
- pdev = platform_device_alloc(name, -1);
- if (!pdev) {
- dev_dbg(&twl->client->dev, "can't alloc dev\n");
- status = -ENOMEM;
- goto err;
- }
+ struct platform_device *pdev = NULL;
+ struct twl4030_client *twl = NULL;
+ int status = 0;
- device_init_wakeup(&pdev->dev, can_wakeup);
- pdev->dev.parent = &twl->client->dev;
+ if (twl_has_bci() && pdata->bci) {
+ twl = &twl4030_modules[3];
- if (pdata) {
- status = platform_device_add_data(pdev, pdata, pdata_len);
- if (status < 0) {
- dev_dbg(&pdev->dev, "can't add platform_data\n");
+ pdev = platform_device_alloc("twl4030_bci", -1);
+ if (!pdev) {
+ pr_debug("%s: can't alloc bci dev\n", DRIVER_NAME);
+ status = -ENOMEM;
goto err;
}
- }
- if (irq0) {
- struct resource r[2] = {
- { .start = irq0, .flags = IORESOURCE_IRQ, },
- { .start = irq1, .flags = IORESOURCE_IRQ, },
- };
+ if (status == 0) {
+ pdev->dev.parent = &twl->client->dev;
+ status = platform_device_add_data(pdev, pdata->bci,
+ sizeof(*pdata->bci));
+ if (status < 0) {
+ dev_dbg(&twl->client->dev,
+ "can't add bci data, %d\n",
+ status);
+ goto err;
+ }
+ }
+
+ if (status == 0) {
+ struct resource r = {
+ .start = pdata->irq_base + 8 + 1,
+ .flags = IORESOURCE_IRQ,
+ };
+
+ status = platform_device_add_resources(pdev, &r, 1);
+ }
+
+ if (status == 0)
+ status = platform_device_add(pdev);
- status = platform_device_add_resources(pdev, r, irq1 ? 2 : 1);
if (status < 0) {
- dev_dbg(&pdev->dev, "can't add irqs\n");
+ platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't create bci dev, %d\n",
+ status);
goto err;
}
}
- status = platform_device_add(pdev);
+ if (twl_has_gpio() && pdata->gpio) {
+ twl = &twl4030_modules[1];
-err:
- if (status < 0) {
- platform_device_put(pdev);
- dev_err(&twl->client->dev, "can't add %s dev\n", name);
- }
- return status;
-}
+ pdev = platform_device_alloc("twl4030_gpio", -1);
+ if (!pdev) {
+ pr_debug("%s: can't alloc gpio dev\n", DRIVER_NAME);
+ status = -ENOMEM;
+ goto err;
+ }
-/*
- * NOTE: We know the first 8 IRQs after pdata->base_irq are
- * for the PIH, and the next are for the PWR_INT SIH, since
- * that's how twl_init_irq() sets things up.
- */
+ /* more driver model init */
+ if (status == 0) {
+ pdev->dev.parent = &twl->client->dev;
+ /* device_init_wakeup(&pdev->dev, 1); */
+
+ status = platform_device_add_data(pdev, pdata->gpio,
+ sizeof(*pdata->gpio));
+ if (status < 0) {
+ dev_dbg(&twl->client->dev,
+ "can't add gpio data, %d\n",
+ status);
+ goto err;
+ }
+ }
-static int add_children(struct twl4030_platform_data *pdata)
-{
- int status;
+ /* GPIO module IRQ */
+ if (status == 0) {
+ struct resource r = {
+ .start = pdata->irq_base + 0,
+ .flags = IORESOURCE_IRQ,
+ };
- if (twl_has_bci() && pdata->bci) {
- status = add_child(3, "twl4030_bci",
- pdata->bci, sizeof(*pdata->bci),
- false,
- /* irq0 = CHG_PRES, irq1 = BCI */
- pdata->irq_base + 8 + 1, pdata->irq_base + 2);
- if (status < 0)
- return status;
- }
+ status = platform_device_add_resources(pdev, &r, 1);
+ }
- if (twl_has_gpio() && pdata->gpio) {
- status = add_child(1, "twl4030_gpio",
- pdata->gpio, sizeof(*pdata->gpio),
- false, pdata->irq_base + 0, 0);
- if (status < 0)
- return status;
+ if (status == 0)
+ status = platform_device_add(pdev);
+
+ if (status < 0) {
+ platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't create gpio dev, %d\n",
+ status);
+ goto err;
+ }
}
if (twl_has_keypad() && pdata->keypad) {
- status = add_child(2, "twl4030_keypad",
- pdata->keypad, sizeof(*pdata->keypad),
- true, pdata->irq_base + 1, 0);
- if (status < 0)
- return status;
+ pdev = platform_device_alloc("twl4030_keypad", -1);
+ if (pdev) {
+ twl = &twl4030_modules[2];
+ pdev->dev.parent = &twl->client->dev;
+ device_init_wakeup(&pdev->dev, 1);
+ status = platform_device_add_data(pdev, pdata->keypad,
+ sizeof(*pdata->keypad));
+ if (status < 0) {
+ dev_dbg(&twl->client->dev,
+ "can't add keypad data, %d\n",
+ status);
+ platform_device_put(pdev);
+ goto err;
+ }
+ status = platform_device_add(pdev);
+ if (status < 0) {
+ platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't create keypad dev, %d\n",
+ status);
+ goto err;
+ }
+ } else {
+ pr_debug("%s: can't alloc keypad dev\n", DRIVER_NAME);
+ status = -ENOMEM;
+ goto err;
+ }
}
if (twl_has_madc() && pdata->madc) {
- status = add_child(2, "twl4030_madc",
- pdata->madc, sizeof(*pdata->madc),
- true, pdata->irq_base + 3, 0);
- if (status < 0)
- return status;
+ pdev = platform_device_alloc("twl4030_madc", -1);
+ if (pdev) {
+ twl = &twl4030_modules[2];
+ pdev->dev.parent = &twl->client->dev;
+ device_init_wakeup(&pdev->dev, 1);
+ status = platform_device_add_data(pdev, pdata->madc,
+ sizeof(*pdata->madc));
+ if (status < 0) {
+ platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't add madc data, %d\n",
+ status);
+ goto err;
+ }
+ status = platform_device_add(pdev);
+ if (status < 0) {
+ platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't create madc dev, %d\n",
+ status);
+ goto err;
+ }
+ } else {
+ pr_debug("%s: can't alloc madc dev\n", DRIVER_NAME);
+ status = -ENOMEM;
+ goto err;
+ }
}
if (twl_has_power() && pdata->power)
twl4030_power_init(pdata->power);
if (twl_has_rtc()) {
+ twl = &twl4030_modules[3];
+
+ pdev = platform_device_alloc("twl4030_rtc", -1);
+ if (!pdev) {
+ pr_debug("%s: can't alloc rtc dev\n", DRIVER_NAME);
+ status = -ENOMEM;
+ } else {
+ pdev->dev.parent = &twl->client->dev;
+ device_init_wakeup(&pdev->dev, 1);
+ }
+
/*
- * REVISIT platform_data here currently might expose the
+ * REVISIT platform_data here currently might use of
* "msecure" line ... but for now we just expect board
- * setup to tell the chip "it's always ok to SET_TIME".
+ * setup to tell the chip "we are secure" at all times.
* Eventually, Linux might become more aware of such
* HW security concerns, and "least privilege".
*/
- status = add_child(3, "twl4030_rtc",
- NULL, 0,
- true, pdata->irq_base + 8 + 3, 0);
- if (status < 0)
- return status;
+
+ /* RTC module IRQ */
+ if (status == 0) {
+ struct resource r = {
+ .start = pdata->irq_base + 8 + 3,
+ .flags = IORESOURCE_IRQ,
+ };
+
+ status = platform_device_add_resources(pdev, &r, 1);
+ }
+
+ if (status == 0)
+ status = platform_device_add(pdev);
+
+ if (status < 0) {
+ platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't create rtc dev, %d\n",
+ status);
+ goto err;
+ }
}
if (twl_has_usb() && pdata->usb) {
- status = add_child(0, "twl4030_usb",
- pdata->usb, sizeof(*pdata->usb),
- true,
- /* irq0 = USB_PRES, irq1 = USB */
- pdata->irq_base + 8 + 2, pdata->irq_base + 4);
- if (status < 0)
- return status;
+ twl = &twl4030_modules[0];
+
+ pdev = platform_device_alloc("twl4030_usb", -1);
+ if (!pdev) {
+ pr_debug("%s: can't alloc usb dev\n", DRIVER_NAME);
+ status = -ENOMEM;
+ goto err;
+ }
+
+ if (status == 0) {
+ pdev->dev.parent = &twl->client->dev;
+ device_init_wakeup(&pdev->dev, 1);
+ status = platform_device_add_data(pdev, pdata->usb,
+ sizeof(*pdata->usb));
+ if (status < 0) {
+ platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't add usb data, %d\n",
+ status);
+ goto err;
+ }
+ }
+
+ if (status == 0) {
+ struct resource r = {
+ .start = pdata->irq_base + 8 + 2,
+ .flags = IORESOURCE_IRQ,
+ };
+
+ status = platform_device_add_resources(pdev, &r, 1);
+ }
+
+ if (status == 0)
+ status = platform_device_add(pdev);
+
+ if (status < 0) {
+ platform_device_put(pdev);
+ dev_dbg(&twl->client->dev,
+ "can't create usb dev, %d\n",
+ status);
+ }
}
- return 0;
+err:
+ if (status)
+ pr_err("failed to add twl4030's children (status %d)\n", status);
+ return status;
}
/*----------------------------------------------------------------------*/