static int add_children(struct twl4030_platform_data *pdata, unsigned long features) { struct device *child; unsigned sub_chip_id;
if (twl_has_gpio() && pdata->gpio) { child = add_child(SUB_CHIP_ID1, "twl4030_gpio", pdata->gpio, sizeof(*pdata->gpio), false, pdata->irq_base + GPIO_INTR_OFFSET, 0); if (IS_ERR(child)) return PTR_ERR(child); }
if (twl_has_keypad() && pdata->keypad) { child = add_child(SUB_CHIP_ID2, "twl4030_keypad", pdata->keypad, sizeof(*pdata->keypad), true, pdata->irq_base + KEYPAD_INTR_OFFSET, 0); if (IS_ERR(child)) return PTR_ERR(child); } if (twl_has_bci() && pdata->bci && !(features & (TPS_SUBSET | TWL5031))) { child = add_child(3, "twl4030_bci", pdata->bci, sizeof(*pdata->bci), false, /* irq0 = CHG_PRES, irq1 = BCI */ pdata->irq_base + BCI_PRES_INTR_OFFSET, pdata->irq_base + BCI_INTR_OFFSET); if (IS_ERR(child)) return PTR_ERR(child); } if (twl_has_bci() && pdata->bci && (features & TWL6030_CLASS)) { child = add_child(1, "twl6030_bci", pdata->bci, sizeof(*pdata->bci), false, pdata->irq_base + CHARGER_INTR_OFFSET, pdata->irq_base + CHARGERFAULT_INTR_OFFSET); }
if (twl_has_madc() && pdata->madc && twl_class_is_4030()) { child = add_child(2, "twl4030_madc", pdata->madc, sizeof(*pdata->madc), true, pdata->irq_base + MADC_INTR_OFFSET, 0); if (IS_ERR(child)) return PTR_ERR(child); }
if (twl_has_madc() && pdata->madc && twl_class_is_6030()) { child = add_child(1, "twl6030_gpadc", pdata->madc, sizeof(*pdata->madc), true, pdata->irq_base + MADC_INTR_OFFSET, pdata->irq_base + GPADCSW_INTR_OFFSET); if (IS_ERR(child)) return PTR_ERR(child); }
if (twl_has_rtc()) { /* * REVISIT platform_data here currently might expose the * "msecure" line ... but for now we just expect board * setup to tell the chip "it's always ok to SET_TIME". * Eventually, Linux might become more aware of such * HW security concerns, and "least privilege". */ sub_chip_id = twl_map[TWL_MODULE_RTC].sid; child = add_child(sub_chip_id, "twl_rtc", NULL, 0, true, pdata->irq_base + RTC_INTR_OFFSET, 0); if (IS_ERR(child)) return PTR_ERR(child); }
if (twl_has_usb() && pdata->usb && twl_class_is_4030()) {
static struct regulator_consumer_supply usb1v5 = { .supply = "usb1v5", }; static struct regulator_consumer_supply usb1v8 = { .supply = "usb1v8", }; static struct regulator_consumer_supply usb3v1 = { .supply = "usb3v1", };
/* First add the regulators so that they can be used by transceiver */ if (twl_has_regulator()) { /* this is a template that gets copied */ struct regulator_init_data usb_fixed = { .constraints.valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .constraints.valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, };
child = add_regulator_linked(TWL4030_REG_VUSB1V5, &usb_fixed, &usb1v5, 1); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator_linked(TWL4030_REG_VUSB1V8, &usb_fixed, &usb1v8, 1); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator_linked(TWL4030_REG_VUSB3V1, &usb_fixed, &usb3v1, 1); if (IS_ERR(child)) return PTR_ERR(child);
}
child = add_child(0, "twl4030_usb", pdata->usb, sizeof(*pdata->usb), true, /* irq0 = USB_PRES, irq1 = USB */ pdata->irq_base + USB_PRES_INTR_OFFSET, pdata->irq_base + USB_INTR_OFFSET);
if (IS_ERR(child)) return PTR_ERR(child);
/* we need to connect regulators to this transceiver */ if (twl_has_regulator() && child) { usb1v5.dev = child; usb1v8.dev = child; usb3v1.dev = child; } } if (twl_has_usb() && pdata->usb && twl_class_is_6030()) {
static struct regulator_consumer_supply usb3v3 = { .supply = "vusb", };
if (twl_has_regulator()) { /* this is a template that gets copied */ struct regulator_init_data usb_fixed = { .constraints.valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .constraints.valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, };
child = add_regulator_linked(TWL6030_REG_VUSB, &usb_fixed, &usb3v3, 1); if (IS_ERR(child)) return PTR_ERR(child); }
child = add_child(0, "twl6030_usb", pdata->usb, sizeof(*pdata->usb), true, /* irq1 = VBUS_PRES, irq0 = USB ID */ pdata->irq_base + USBOTG_INTR_OFFSET, pdata->irq_base + USB_PRES_INTR_OFFSET);
if (IS_ERR(child)) return PTR_ERR(child); /* we need to connect regulators to this transceiver */ if (twl_has_regulator() && child) usb3v3.dev = child;
}
if (twl_has_watchdog()) { child = add_child(0, "twl4030_wdt", NULL, 0, false, 0, 0); if (IS_ERR(child)) return PTR_ERR(child); }
if (twl4030_has_pwrbutton()) { child = add_child(1, "twl4030_pwrbutton", NULL, 0, true, pdata->irq_base + 8 + 0, 0); if (IS_ERR(child)) return PTR_ERR(child); }
if (twl6030_has_pwrbutton()) { child = add_child(1, "twl6030_pwrbutton", NULL, 0, true, pdata->irq_base, 0); if (IS_ERR(child)) return PTR_ERR(child); }
if (twl_has_codec() && pdata->codec && twl_class_is_4030()) { sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid; child = add_child(sub_chip_id, "twl4030-audio", pdata->codec, sizeof(*pdata->codec), false, 0, 0); if (IS_ERR(child)) return PTR_ERR(child); }
/* Phoenix codec driver is probed directly atm */ if (twl_has_codec() && pdata->codec && twl_class_is_6030()) { sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid; child = add_child(sub_chip_id, "twl6040_audio", pdata->codec, sizeof(*pdata->codec), false, 0, 0); if (IS_ERR(child)) return PTR_ERR(child); }
/* twl4030 regulators */ if (twl_has_regulator() && twl_class_is_4030()) { child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VIO, pdata->vio); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VDD1, pdata->vdd1); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VDD2, pdata->vdd2); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VDAC, pdata->vdac); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator((features & TWL4030_VAUX2) ? TWL4030_REG_VAUX2_4030 : TWL4030_REG_VAUX2, pdata->vaux2); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VINTANA1, pdata->vintana1); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VINTANA2, pdata->vintana2); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VINTDIG, pdata->vintdig); if (IS_ERR(child)) return PTR_ERR(child); }
/* maybe add LDOs that are omitted on cost-reduced parts */ if (twl_has_regulator() && !(features & TPS_SUBSET) && twl_class_is_4030()) { child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VSIM, pdata->vsim); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator(TWL6030_REG_CLK32KG, pdata->clk32kg); if (IS_ERR(child)) return PTR_ERR(child); }
/* twl6030 regulators */ if (twl_has_regulator() && twl_class_is_6030()) { child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VPP, pdata->vpp); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VUSIM, pdata->vusim); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VANA, pdata->vana); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VCXIO, pdata->vcxio); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VDAC, pdata->vdac); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VAUX1_6030, pdata->vaux1); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VAUX2_6030, pdata->vaux2); if (IS_ERR(child)) return PTR_ERR(child);
child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3); if (IS_ERR(child)) return PTR_ERR(child); }
return 0; }
|