#include <mach/sram.h>
+#define TWL60xx_IRQ_BASE (NR_GIC_IRQS + NR_GPIO_IRQS )
+#ifdef CONFIG_TWL4030_CORE
+#define TWL60xx_BASE_NR_IRQS 24
+#else
+#define TWL60xx_BASE_NR_IRQS 0
+#endif
+#define TWL60xx_IRQ_END (TWL60xx_IRQ_BASE + TWL60xx_BASE_NR_IRQS)
+
+
#ifdef CONFIG_TWL4030_CORE
#define VREG_VOLTAGE 3
#define VREG_VOLTAGE_DVS_SMPS 3
int tps80032_pre_init(void){
int ret;
u8 value;
- printk("--------------------\n");
printk("%s\n", __func__);
return 0;
{
struct regulator *dcdc;
struct regulator *ldo;
- printk("++++++++++++++++++++++++++++++++++++++\n");
printk("%s\n", __func__);
- ldo = regulator_get(NULL, "tps_ldo1"); //vcca_33
+ ldo = regulator_get(NULL, "ldo1"); //vcca_33
regulator_set_voltage(ldo, 3300000, 3300000);
regulator_enable(ldo);
- printk("%s set ldo1 vcca_33=%dmV end\n", __func__, regulator_get_voltage(ldo));
+// printk("%s set ldo1 vcca_33=%dmV end\n", __func__, regulator_get_voltage(ldo));
regulator_put(ldo);
udelay(100);
- ldo = regulator_get(NULL, "tps_ldo4"); // vdd_11
+ ldo = regulator_get(NULL, "ldo4"); // vdd_11
regulator_set_voltage(ldo, 1100000, 1100000);
regulator_enable(ldo);
- printk("%s set ldo4 vdd_11=%dmV end\n", __func__, regulator_get_voltage(ldo));
+// printk("%s set ldo4 vdd_11=%dmV end\n", __func__, regulator_get_voltage(ldo));
regulator_put(ldo);
udelay(100);
- dcdc = regulator_get(NULL, "tps_smps4");
+ dcdc = regulator_get(NULL, "smps4");
regulator_set_voltage(dcdc,3000000,3000000);
regulator_enable(dcdc);
- printk("%s set dcdc4 vcc_io=%dmV end\n", __func__, regulator_get_voltage(dcdc));
+// printk("%s set dcdc4 vcc_io=%dmV end\n", __func__, regulator_get_voltage(dcdc));
regulator_put(dcdc);
udelay(100);
- ldo = regulator_get(NULL, "tps_ldo2"); // vdd_usb11
+ ldo = regulator_get(NULL, "ldo2"); // vdd_usb11
regulator_set_voltage(ldo, 1100000, 1100000);
regulator_enable(ldo);
- printk("%s set ldo2 vdd_usb11=%dmV end\n", __func__, regulator_get_voltage(ldo));
+// printk("%s set ldo2 vdd_usb11=%dmV end\n", __func__, regulator_get_voltage(ldo));
regulator_put(ldo);
udelay(100);
- ldo = regulator_get(NULL, "tps_ldo5"); // vcc_25
+ ldo = regulator_get(NULL, "ldo5"); // vcc_25
regulator_set_voltage(ldo, 2500000, 2500000);
regulator_enable(ldo);
- printk("%s set ldo5 vcc_25=%dmV end\n", __func__, regulator_get_voltage(ldo));
+// printk("%s set ldo5 vcc_25=%dmV end\n", __func__, regulator_get_voltage(ldo));
regulator_put(ldo);
udelay(100);
- ldo = regulator_get(NULL, "tps_ldousb"); // vcc_usb33
+ ldo = regulator_get(NULL, "ldousb"); // vcc_usb33
regulator_set_voltage(ldo, 3300000, 3300000);
regulator_enable(ldo);
- printk("%s set ldousb vcc_usb33=%dmV end\n", __func__, regulator_get_voltage(ldo));
+// printk("%s set ldousb vcc_usb33=%dmV end\n", __func__, regulator_get_voltage(ldo));
regulator_put(ldo);
udelay(100);
- dcdc = regulator_get(NULL, "tps_smps1"); // vdd_arm
+ dcdc = regulator_get(NULL, "vdd_cpu"); // vdd_arm
regulator_set_voltage(dcdc,1100000,1100000);
regulator_enable(dcdc);
printk("%s set dcdc1 vdd_cpu=%dmV end\n", __func__, regulator_get_voltage(dcdc));
regulator_put(dcdc);
udelay(100);
- dcdc = regulator_get(NULL, "tps_smps2"); //vdd_log
+ dcdc = regulator_get(NULL, "vdd_core"); //vdd_log
regulator_set_voltage(dcdc,1100000,1100000);
regulator_enable(dcdc);
printk("%s set dcdc2 vdd_core=%dmV end\n", __func__, regulator_get_voltage(dcdc));
regulator_put(dcdc);
udelay(100);
- dcdc = regulator_get(NULL, "tps_smps3"); //vcc_ddr
- regulator_set_voltage(dcdc,1500000,1500000);
+ dcdc = regulator_get(NULL, "smps3"); //vcc_ddr
+ regulator_set_voltage(dcdc,1800000,1800000);
regulator_enable(dcdc);
- printk("%s set dcdc3 vcc_ddr=%dmV end\n", __func__, regulator_get_voltage(dcdc));
+// printk("%s set dcdc3 vcc_lpddr2_1v8=%dmV end\n", __func__, regulator_get_voltage(dcdc));
regulator_put(dcdc);
udelay(100);
-/*
- dcdc = regulator_get(NULL, "tps_smps5");
- regulator_set_voltage(dcdc,1800000,1800000);
-// regulator_set_suspend_voltage(dcdc, 1800000);
+
+ dcdc = regulator_get(NULL, "smps5");
+ regulator_set_voltage(dcdc,1200000,1200000);
regulator_enable(dcdc);
- printk("%s set dcdc5 vcc_lpddr2_1v8=%dmV end\n", __func__, regulator_get_voltage(dcdc));
+// printk("%s set dcdc5 vcc_lpddr2_1v2=%dmV end\n", __func__, regulator_get_voltage(dcdc));
regulator_put(dcdc);
udelay(100);
-*/
+
- ldo = regulator_get(NULL, "tps_ldo3"); //vcc_nandflash
+ ldo = regulator_get(NULL, "ldo3"); //vcc_nandflash
regulator_set_voltage(ldo, 3300000, 3300000);
regulator_enable(ldo);
- printk("%s set ldo3 vcc_nandflash=%dmV end\n", __func__, regulator_get_voltage(ldo));
+// printk("%s set ldo3 vcc_nandflash=%dmV end\n", __func__, regulator_get_voltage(ldo));
regulator_put(ldo);
udelay(100);
- ldo = regulator_get(NULL, "tps_ldo6"); //codecvdd_1v8
+ ldo = regulator_get(NULL, "ldo6"); //codecvdd_1v8
regulator_set_voltage(ldo, 1800000, 1800000);
regulator_enable(ldo);
- printk("%s set ldo6 codecvdd_1v8=%dmV end\n", __func__, regulator_get_voltage(ldo));
+// printk("%s set ldo6 codecvdd_1v8=%dmV end\n", __func__, regulator_get_voltage(ldo));
regulator_put(ldo);
udelay(100);
- ldo = regulator_get(NULL, "tps_ldo7"); //vcc_lcd
+ ldo = regulator_get(NULL, "ldo7"); //vcc_lcd
regulator_set_voltage(ldo, 3000000, 3000000);
regulator_enable(ldo);
- printk("%s set ldo7 vcc_lcd=%dmV end\n", __func__, regulator_get_voltage(ldo));
+// printk("%s set ldo7 vcc_lcd=%dmV end\n", __func__, regulator_get_voltage(ldo));
regulator_put(ldo);
udelay(100);
- ldo = regulator_get(NULL, "tps_ldoln"); //vcccodec_io
+ ldo = regulator_get(NULL, "ldoln"); //vcccodec_io
regulator_set_voltage(ldo, 3300000, 3300000);
regulator_enable(ldo);
- printk("%s set ldoln vcccodec_io=%dmV end\n", __func__, regulator_get_voltage(ldo));
+// printk("%s set ldoln vcccodec_io=%dmV end\n", __func__, regulator_get_voltage(ldo));
regulator_put(ldo);
udelay(100);
/*
- ldo = regulator_get(NULL, "tps_vana"); //vana_out
+ ldo = regulator_get(NULL, "vana"); //vana_out
regulator_set_voltage(ldo, 2500000, 2500000);
// regulator_set_suspend_voltage(ldo, 2500000);
regulator_enable(ldo);
regulator_put(ldo);
udelay(100);
*/
+
+ printk("tps80032_set_init end.\n");
return 0;
}
static struct regulator_consumer_supply tps80032_smps1_supply[] = {
{
- .supply = "tps_smps1",
+ .supply = "vdd_cpu",
},
};
static struct regulator_consumer_supply tps80032_smps2_supply[] = {
{
- .supply = "tps_smps2",
+ .supply = "vdd_core",
},
};
static struct regulator_consumer_supply tps80032_smps3_supply[] = {
{
- .supply = "tps_smps3",
+ .supply = "smps3",
},
};
static struct regulator_consumer_supply tps80032_smps4_supply[] = {
{
- .supply = "tps_smps4",
+ .supply = "smps4",
},
};
static struct regulator_consumer_supply tps80032_smps5_supply[] = {
{
- .supply = "tps_smps5",
+ .supply = "smps5",
},
};
static struct regulator_consumer_supply tps80032_ldo1_supply[] = {
{
- .supply = "tps_ldo1",
+ .supply = "ldo1",
},
};
static struct regulator_consumer_supply tps80032_ldo2_supply[] = {
{
- .supply = "tps_ldo2",
+ .supply = "ldo2",
},
};
static struct regulator_consumer_supply tps80032_ldo3_supply[] = {
{
- .supply = "tps_ldo3",
+ .supply = "ldo3",
},
};
static struct regulator_consumer_supply tps80032_ldo4_supply[] = {
{
- .supply = "tps_ldo4",
+ .supply = "ldo4",
},
};
static struct regulator_consumer_supply tps80032_ldo5_supply[] = {
{
- .supply = "tps_ldo5",
+ .supply = "ldo5",
},
};
static struct regulator_consumer_supply tps80032_ldo6_supply[] = {
{
- .supply = "tps_ldo6",
+ .supply = "ldo6",
},
};
static struct regulator_consumer_supply tps80032_ldo7_supply[] = {
{
- .supply = "tps_ldo7",
+ .supply = "ldo7",
},
};
static struct regulator_consumer_supply tps80032_ldoln_supply[] = {
{
- .supply = "tps_ldoln",
+ .supply = "ldoln",
},
};
static struct regulator_consumer_supply tps80032_ldousb_supply[] = {
{
- .supply = "tps_ldousb",
+ .supply = "ldousb",
},
};
static struct regulator_consumer_supply tps80032_ldovana_supply[] = {
{
- .supply = "tps_vana",
+ .supply = "vana",
},
};
/* */
static struct regulator_init_data tps80032_smps1 = {
.constraints = {
- .name = "TPS_SMPS1",
+ .name = "SMPS1",
.min_uV = 600000,
.max_uV = 2100000,
.apply_uV = 1,
/* */
static struct regulator_init_data tps80032_smps2 = {
.constraints = {
- .name = "TPS_SMPS2",
+ .name = "SMPS2",
.min_uV = 600000,
.max_uV = 2100000,
.apply_uV = 1,
/* */
static struct regulator_init_data tps80032_smps3 = {
.constraints = {
- .name = "TPS_SMPS3",
+ .name = "SMPS3",
.min_uV = 600000,
.max_uV = 2100000,
.apply_uV = 1,
/* */
static struct regulator_init_data tps80032_smps4 = {
.constraints = {
- .name = "TPS_SMPS4",
+ .name = "SMPS4",
.min_uV = 600000,
.max_uV = 2100000,
.apply_uV = 1,
/* */
static struct regulator_init_data tps80032_smps5 = {
.constraints = {
- .name = "TPS_SMPS5",
+ .name = "SMPS5",
.min_uV = 600000,
.max_uV = 2100000,
.apply_uV = 1,
};
static struct regulator_init_data tps80032_ldo1 = {
.constraints = {
- .name = "TPS_LDO1",
+ .name = "LDO1",
.min_uV = 1200000,
.max_uV = 3000000,
.apply_uV = 1,
/* */
static struct regulator_init_data tps80032_ldo2 = {
.constraints = {
- .name = "TPS_LDO2",
+ .name = "LDO2",
.min_uV = 1200000,
.max_uV = 3000000,
.apply_uV = 1,
/* */
static struct regulator_init_data tps80032_ldo3 = {
.constraints = {
- .name = "TPS_LDO3",
+ .name = "LDO3",
.min_uV = 1200000,
.max_uV = 3000000,
.apply_uV = 1,
/* */
static struct regulator_init_data tps80032_ldo4 = {
.constraints = {
- .name = "TPS_LDO4",
+ .name = "LDO4",
.min_uV = 1200000,
.max_uV = 3000000,
.apply_uV = 1,
/* */
static struct regulator_init_data tps80032_ldo5 = {
.constraints = {
- .name = "TPS_LDO5",
+ .name = "LDO5",
.min_uV = 1200000,
.max_uV = 3000000,
.apply_uV = 1,
/* */
static struct regulator_init_data tps80032_ldo6 = {
.constraints = {
- .name = "TPS_LDO6",
+ .name = "LDO6",
.min_uV = 1200000,
.max_uV = 3000000,
.apply_uV = 1,
/* */
static struct regulator_init_data tps80032_ldo7 = {
.constraints = {
- .name = "TPS_LDO7",
+ .name = "LDO7",
.min_uV = 1200000,
.max_uV = 3000000,
.apply_uV = 1,
/* */
static struct regulator_init_data tps80032_ldoln = {
.constraints = {
- .name = "TPS_LDOLN",
+ .name = "LDOLN",
.min_uV = 1200000,
.max_uV = 3000000,
.apply_uV = 1,
/* */
static struct regulator_init_data tps80032_ldousb = {
.constraints = {
- .name = "TPS_LDOUSB",
+ .name = "LDOUSB",
.min_uV = 3300000,
.max_uV = 3300000,
.apply_uV = 1,
/* */
static struct regulator_init_data tps80032_ldovana = {
.constraints = {
- .name = "TPS_LDOVANA",
+ .name = "LDOVANA",
.min_uV = 600000,
.max_uV = 2500000,
.apply_uV = 1,
.consumer_supplies = tps80032_ldovana_supply,
};
+
static struct twl4030_platform_data tps80032_data = {
- .irq_base = RK30_PIN0_PA1,
- .irq_end = RK30_PIN0_PA1,
+ .irq_base = TWL60xx_IRQ_BASE,
+ .irq_end = TWL60xx_IRQ_END,
//.irq = RK29_PIN0_PA1,
.pre_init = tps80032_pre_init,
.set_init = tps80032_set_init,
-
+
/* Regulators */
.ldo1 = &tps80032_ldo1,
.ldo2 = &tps80032_ldo2,
#include <linux/regulator/consumer.h>
#include <linux/err.h>
#include <linux/notifier.h>
+#include <linux/power_supply.h>
#include <linux/slab.h>
#include <linux/delay.h>
+#include <plat/usb.h>
+
/* usb register definitions */
#define USB_VENDOR_ID_LSB 0x00
#define USB_VENDOR_ID_MSB 0x01
#define USB_OTG_ADP_RISE 0x19
#define USB_OTG_REVISION 0x1A
-/* to be moved to LDO */
#define TWL6030_MISC2 0xE5
-#define TWL6030_CFG_LDO_PD2 0xF5
#define TWL6030_BACKUP_REG 0xFA
#define STS_HW_CONDITIONS 0x21
/* in module TWL6030_MODULE_MAIN_CHARGE */
#define CHARGERUSB_CTRL1 0x8
+#define SUSPEND_BOOT (1 << 7)
+#define OPA_MODE (1 << 6)
+#define HZ_MODE (1 << 5)
+#define TERM (1 << 4)
+
#define CONTROLLER_STAT1 0x03
#define VBUS_DET BIT(2)
struct regulator *usb3v3;
+ /* used to set vbus, in atomic path */
+ struct work_struct set_vbus_work;
+
int irq1;
int irq2;
+ unsigned int usb_cinlimit_mA;
u8 linkstat;
u8 asleep;
+ u8 prev_vbus;
bool irq_enabled;
+ bool vbus_enable;
+ bool is_phy_suspended;
unsigned long features;
};
struct device *dev = twl->dev;
struct twl4030_usb_data *pdata = dev->platform_data;
- pdata->phy_suspend(dev, suspend);
-
+ if (suspend && !twl->is_phy_suspended) {
+ pdata->phy_suspend(dev, 1);
+ twl->is_phy_suspended = true;
+ } else if (!suspend && twl->is_phy_suspended) {
+ pdata->phy_suspend(dev, 0);
+ twl->is_phy_suspended = false;
+ }
return 0;
}
static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
{
char *regulator_name;
+ u8 misc2_data = 0;
- if (twl->features & TWL6025_SUBCLASS)
+ if (twl->features & TWL6032_SUBCLASS)
regulator_name = "ldousb";
else
regulator_name = "vusb";
/* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */
twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG);
- /* Program CFG_LDO_PD2 register and set VUSB bit */
- twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_CFG_LDO_PD2);
-
- /* Program MISC2 register and set bit VUSB_IN_VBAT */
- twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2);
-
twl->usb3v3 = regulator_get(twl->dev, regulator_name);
if (IS_ERR(twl->usb3v3))
return -ENODEV;
*/
twl6030_writeb(twl, TWL_MODULE_USB, 0x14, USB_ID_CTRL_SET);
+ /* Program MISC2 register and clear bit VUSB_IN_VBAT */
+ misc2_data = twl6030_readb(twl, TWL6030_MODULE_ID0, TWL6030_MISC2);
+ misc2_data &= 0xEF;
+ twl6030_writeb(twl, TWL6030_MODULE_ID0, misc2_data, TWL6030_MISC2);
+
return 0;
}
switch (twl->linkstat) {
case USB_EVENT_VBUS:
- ret = snprintf(buf, PAGE_SIZE, "vbus\n");
- break;
+ ret = snprintf(buf, PAGE_SIZE, "vbus\n");
+ break;
case USB_EVENT_ID:
- ret = snprintf(buf, PAGE_SIZE, "id\n");
- break;
+ ret = snprintf(buf, PAGE_SIZE, "id\n");
+ break;
case USB_EVENT_NONE:
- ret = snprintf(buf, PAGE_SIZE, "none\n");
- break;
+ ret = snprintf(buf, PAGE_SIZE, "none\n");
+ break;
default:
- ret = snprintf(buf, PAGE_SIZE, "UNKNOWN\n");
+ ret = snprintf(buf, PAGE_SIZE, "UNKNOWN\n");
}
spin_unlock_irqrestore(&twl->lock, flags);
{
struct twl6030_usb *twl = _twl;
int status;
- u8 vbus_state, hw_state;
+ u8 vbus_state, hw_state, misc2_data;
+ unsigned charger_type;
hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
vbus_state = twl6030_readb(twl, TWL_MODULE_MAIN_CHARGE,
CONTROLLER_STAT1);
- if (!(hw_state & STS_USB_ID)) {
- if (vbus_state & VBUS_DET) {
- regulator_enable(twl->usb3v3);
- twl->asleep = 1;
+ vbus_state = vbus_state & VBUS_DET;
+
+ /* Ignore charger events other than VBUS */
+ if (vbus_state == twl->prev_vbus)
+ return IRQ_HANDLED;
+
+ if ((vbus_state) && !(hw_state & STS_USB_ID)) {
+ /* Program MISC2 register and set bit VUSB_IN_VBAT */
+ misc2_data = twl6030_readb(twl, TWL6030_MODULE_ID0,
+ TWL6030_MISC2);
+ misc2_data |= 0x10;
+ twl6030_writeb(twl, TWL6030_MODULE_ID0, misc2_data,
+ TWL6030_MISC2);
+
+ regulator_enable(twl->usb3v3);
+ twl6030_phy_suspend(&twl->otg, 0);
+ charger_type = omap4_charger_detect();
+ twl6030_phy_suspend(&twl->otg, 1);
+ if ((charger_type == POWER_SUPPLY_TYPE_USB_CDP)
+ || (charger_type == POWER_SUPPLY_TYPE_USB)) {
+
status = USB_EVENT_VBUS;
twl->otg.default_a = false;
+ twl->asleep = 1;
twl->otg.state = OTG_STATE_B_IDLE;
twl->linkstat = status;
twl->otg.last_event = status;
- atomic_notifier_call_chain(&twl->otg.notifier,
- status, twl->otg.gadget);
- } else {
- status = USB_EVENT_NONE;
+ } else if (charger_type == POWER_SUPPLY_TYPE_USB_DCP) {
+ regulator_disable(twl->usb3v3);
+ status = USB_EVENT_CHARGER;
+ twl->usb_cinlimit_mA = 1800;
+ twl->otg.state = OTG_STATE_B_IDLE;
twl->linkstat = status;
twl->otg.last_event = status;
- atomic_notifier_call_chain(&twl->otg.notifier,
- status, twl->otg.gadget);
- if (twl->asleep) {
- regulator_disable(twl->usb3v3);
- twl->asleep = 0;
- }
+ } else {
+ regulator_disable(twl->usb3v3);
+ goto vbus_notify;
+ }
+ atomic_notifier_call_chain(&twl->otg.notifier,
+ status, &charger_type);
+ }
+ if (!vbus_state) {
+ status = USB_EVENT_NONE;
+ twl->linkstat = status;
+ twl->otg.last_event = status;
+ atomic_notifier_call_chain(&twl->otg.notifier,
+ status, twl->otg.gadget);
+ if (twl->asleep) {
+ regulator_disable(twl->usb3v3);
+ twl->asleep = 0;
+ /* Program MISC2 register and clear bit VUSB_IN_VBAT */
+ misc2_data = twl6030_readb(twl, TWL6030_MODULE_ID0,
+ TWL6030_MISC2);
+ misc2_data &= 0xEF;
+ twl6030_writeb(twl, TWL6030_MODULE_ID0, misc2_data,
+ TWL6030_MISC2);
}
}
- sysfs_notify(&twl->dev->kobj, NULL, "vbus");
+vbus_notify:
+ sysfs_notify(&twl->dev->kobj, NULL, "vbus");
+ twl->prev_vbus = vbus_state;
return IRQ_HANDLED;
}
static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
{
+
+#ifndef CONFIG_USB_MUSB_PERIPHERAL
struct twl6030_usb *twl = _twl;
int status = USB_EVENT_NONE;
- u8 hw_state;
+ u8 hw_state, misc2_data;
hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
if (hw_state & STS_USB_ID) {
+ if (twl->otg.state == OTG_STATE_A_IDLE)
+ return IRQ_HANDLED;
+
+ /* Program MISC2 register and set bit VUSB_IN_VBAT */
+ misc2_data = twl6030_readb(twl, TWL6030_MODULE_ID0,
+ TWL6030_MISC2);
+ misc2_data |= 0x10;
+ twl6030_writeb(twl, TWL6030_MODULE_ID0, misc2_data,
+ TWL6030_MISC2);
regulator_enable(twl->usb3v3);
twl->asleep = 1;
- twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, 0x1);
- twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET,
- 0x10);
+ twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR);
+ twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET);
status = USB_EVENT_ID;
twl->otg.default_a = true;
twl->otg.state = OTG_STATE_A_IDLE;
atomic_notifier_call_chain(&twl->otg.notifier, status,
twl->otg.gadget);
} else {
- twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR,
- 0x10);
- twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET,
- 0x1);
+ twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR);
+ twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
}
- twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_LATCH_CLR, status);
+ twl6030_writeb(twl, TWL_MODULE_USB, status, USB_ID_INT_LATCH_CLR);
+#endif
return IRQ_HANDLED;
}
{
struct twl6030_usb *twl = xceiv_to_twl(x);
- twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, 0x1);
+ twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C);
twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C);
return 0;
}
-static int twl6030_set_vbus(struct otg_transceiver *x, bool enabled)
+unsigned int twl6030_get_usb_max_power(struct otg_transceiver *x)
{
struct twl6030_usb *twl = xceiv_to_twl(x);
+ return twl->usb_cinlimit_mA;
+}
+
+static void otg_set_vbus_work(struct work_struct *data)
+{
+ struct twl6030_usb *twl = container_of(data, struct twl6030_usb,
+ set_vbus_work);
/*
* Start driving VBUS. Set OPA_MODE bit in CHARGERUSB_CTRL1
* register. This enables boost mode.
*/
- if (enabled)
+ if (twl->vbus_enable)
twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x40,
CHARGERUSB_CTRL1);
- else
+ else
twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x00,
CHARGERUSB_CTRL1);
+}
+
+static int twl6030_set_hz_mode(struct otg_transceiver *x, bool enabled)
+{
+ u8 val;
+ struct twl6030_usb *twl;
+
+ if (!x)
+ return -ENODEV;
+
+ twl = xceiv_to_twl(x);
+
+ /* set/reset USB charger in High impedence mode on VBUS */
+ val = twl6030_readb(twl, TWL_MODULE_MAIN_CHARGE,
+ CHARGERUSB_CTRL1);
+
+ if (enabled)
+ val |= HZ_MODE;
+ else
+ val &= ~HZ_MODE;
+
+ twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , val,
+ CHARGERUSB_CTRL1);
+
+ return 0;
+}
+
+static int twl6030_set_vbus(struct otg_transceiver *x, bool enabled)
+{
+ struct twl6030_usb *twl = xceiv_to_twl(x);
+
+ twl->vbus_enable = enabled;
+ schedule_work(&twl->set_vbus_work);
return 0;
}
return 0;
}
+static int twl6030_set_power(struct otg_transceiver *x, unsigned int mA)
+{
+ struct twl6030_usb *twl = xceiv_to_twl(x);
+
+ twl->usb_cinlimit_mA = mA;
+ if (mA && (twl->otg.last_event != USB_EVENT_NONE))
+ atomic_notifier_call_chain(&twl->otg.notifier, USB_EVENT_ENUMERATED,
+ &twl->usb_cinlimit_mA);
+ return 0;
+}
+
static int __devinit twl6030_usb_probe(struct platform_device *pdev)
{
struct twl6030_usb *twl;
struct twl4030_usb_data *pdata;
struct device *dev = &pdev->dev;
pdata = dev->platform_data;
-
+printk("+++ twl6030_usb_probe+++\n");
+while(1);
twl = kzalloc(sizeof *twl, GFP_KERNEL);
if (!twl)
return -ENOMEM;
twl->otg.set_host = twl6030_set_host;
twl->otg.set_peripheral = twl6030_set_peripheral;
twl->otg.set_vbus = twl6030_set_vbus;
+ twl->otg.set_hz_mode = twl6030_set_hz_mode;
twl->otg.init = twl6030_phy_init;
+ twl->otg.set_power = twl6030_set_power;
twl->otg.shutdown = twl6030_phy_shutdown;
twl->otg.set_suspend = twl6030_phy_suspend;
twl->otg.start_srp = twl6030_start_srp;
+ twl->otg.state = OTG_STATE_UNDEFINED;
/* init spinlock for workqueue */
spin_lock_init(&twl->lock);
ATOMIC_INIT_NOTIFIER_HEAD(&twl->otg.notifier);
+ INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work);
+
+ twl->vbus_enable = false;
twl->irq_enabled = true;
status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq,
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
}
twl->asleep = 0;
+ twl->is_phy_suspended = true;
pdata->phy_init(dev);
twl6030_phy_suspend(&twl->otg, 0);
twl6030_enable_irq(&twl->otg);
regulator_put(twl->usb3v3);
pdata->phy_exit(twl->dev);
device_remove_file(twl->dev, &dev_attr_vbus);
+ cancel_work_sync(&twl->set_vbus_work);
kfree(twl);
return 0;