}
EXPORT_SYMBOL(twl_i2c_read);
+/**
+ * twl_i2c_rmw_u8 - Reads a 8 bit register, modifies it and writes back
+ * @mod_no: module number
+ * @bits_to_clear
+ * @bits_to_set
+ * @reg: register address (just offset will do)
+ *
+ * Returns result of operation - 0 is success else failure.
+ */
+int twl_i2c_rmw_u8(u8 mod_no, u8 bits_to_clear, u8 bits_to_set, u8 reg)
+{
+ u8 value_w[2] = { 0 };
+ u8 value = 0;
+ int ret;
+ u8 val;
+ int sid;
+ struct twl_client *twl;
+ struct i2c_msg *msg;
+
+ if (unlikely(mod_no > TWL_MODULE_LAST)) {
+ pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
+ return -EPERM;
+ }
+ if (unlikely(!inuse)) {
+ pr_err("%s: not initialized\n", DRIVER_NAME);
+ return -EPERM;
+ }
+ sid = twl_map[mod_no].sid;
+ twl = &twl_modules[sid];
+
+ mutex_lock(&twl->xfer_lock);
+ /* [MSG1] fill the register address data */
+ msg = &twl->xfer_msg[0];
+ msg->addr = twl->address;
+ msg->len = 1;
+ msg->flags = 0; /* Read the register value */
+ val = twl_map[mod_no].base + reg;
+ msg->buf = &val;
+ /* [MSG2] fill the data rx buffer */
+ msg = &twl->xfer_msg[1];
+ msg->addr = twl->address;
+ msg->flags = I2C_M_RD; /* Read the register value */
+ msg->len = 1;
+ msg->buf = &value;
+ ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 2);
+ /* i2c_transfer returns number of messages transferred */
+ if (ret != 2) {
+ pr_err("%s: i2c_read failed to transfer all messages\n",
+ DRIVER_NAME);
+ if (ret >= 0)
+ ret = -EIO;
+ goto out;
+ }
+
+ value &= ~bits_to_clear;
+ value |= bits_to_set;
+
+ value_w[0] = twl_map[mod_no].base + reg;
+ value_w[1] = value;
+
+ msg = &twl->xfer_msg[0];
+ msg->addr = twl->address;
+ msg->len = 2;
+ msg->flags = 0;
+ msg->buf = value_w;
+ ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 1);
+ /* i2c_transfer returns number of messages transferred */
+ if (ret != 1) {
+ pr_err("%s: i2c_write failed to transfer all messages\n",
+ DRIVER_NAME);
+ if (ret >= 0)
+ ret = -EIO;
+ goto out;
+ }
+
+ ret = 0;
+out:
+ mutex_unlock(&twl->xfer_lock);
+ return ret;
+}
+EXPORT_SYMBOL(twl_i2c_rmw_u8);
+
/**
* twl_i2c_write_u8 - Writes a 8 bit register in TWL4030/TWL5030/TWL60X0
* @mod_no: module number
goto err;
}
- device_init_wakeup(&pdev->dev, can_wakeup);
pdev->dev.parent = &twl->client->dev;
if (pdata) {
}
status = platform_device_add(pdev);
+ if (status == 0)
+ device_init_wakeup(&pdev->dev, can_wakeup);
err:
if (status < 0) {
unsigned num_consumers, unsigned long features)
{
unsigned sub_chip_id;
+ struct twl_regulator_driver_data drv_data;
+
/* regulator framework demands init_data ... */
if (!pdata)
return NULL;
pdata->num_consumer_supplies = num_consumers;
}
- pdata->driver_data = (void *)features;
+ if (pdata->driver_data) {
+ /* If we have existing drv_data, just add the flags */
+ struct twl_regulator_driver_data *tmp;
+ tmp = pdata->driver_data;
+ tmp->features |= features;
+ } else {
+ /* add new driver data struct, used only during init */
+ drv_data.features = features;
+ drv_data.set_voltage = NULL;
+ drv_data.get_voltage = NULL;
+ drv_data.data = NULL;
+ pdata->driver_data = &drv_data;
+ }
/* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */
sub_chip_id = twl_map[TWL_MODULE_PM_MASTER].sid;
static struct regulator_consumer_supply usb1v8 = {
.supply = "usb1v8",
};
- static struct regulator_consumer_supply usb3v1 = {
- .supply = "usb3v1",
+ static struct regulator_consumer_supply usb3v1[] = {
+ { .supply = "usb3v1" },
+ { .supply = "bci3v1" },
};
/* First add the regulators so that they can be used by transceiver */
return PTR_ERR(child);
child = add_regulator_linked(TWL4030_REG_VUSB3V1,
- &usb_fixed, &usb3v1, 1,
+ &usb_fixed, usb3v1, 2,
features);
if (IS_ERR(child))
return PTR_ERR(child);
if (twl_has_regulator() && child) {
usb1v5.dev = child;
usb1v8.dev = child;
- usb3v1.dev = child;
+ usb3v1[0].dev = child;
}
}
if (twl_has_usb() && pdata->usb && twl_class_is_6030()) {
/* twl6030 regulators */
if (twl_has_regulator() && twl_class_is_6030() &&
!(features & TWL6025_SUBCLASS)) {
+ child = add_regulator(TWL6030_REG_VDD1, pdata->vdd1,
+ features);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator(TWL6030_REG_VDD2, pdata->vdd2,
+ features);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator(TWL6030_REG_VDD3, pdata->vdd3,
+ features);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc,
features);
if (IS_ERR(child))