From: 张晴 Date: Sun, 6 May 2012 11:19:28 +0000 (+0800) Subject: rk30:phone loquat:add the function of the PMU and opened by default X-Git-Tag: firefly_0821_release~9253 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=04c1047f22e1413bcc0806aac7c1e1f49a0c9ccd;p=firefly-linux-kernel-4.4.55.git rk30:phone loquat:add the function of the PMU and opened by default --- diff --git a/arch/arm/configs/rk30_phone_loquat_defconfig b/arch/arm/configs/rk30_phone_loquat_defconfig index dbab407d0f00..328a35324adf 100755 --- a/arch/arm/configs/rk30_phone_loquat_defconfig +++ b/arch/arm/configs/rk30_phone_loquat_defconfig @@ -262,8 +262,10 @@ CONFIG_SPI_FPGA_GPIO_IRQ_NUM=0 CONFIG_POWER_SUPPLY=y CONFIG_TEST_POWER=y # CONFIG_HWMON is not set +CONFIG_TWL4030_CORE=y CONFIG_AIC3262_CODEC=y CONFIG_REGULATOR=y +CONFIG_REGULATOR_TWL4030=y CONFIG_MEDIA_SUPPORT=y CONFIG_VIDEO_DEV=y CONFIG_SOC_CAMERA=y @@ -374,6 +376,7 @@ CONFIG_LEDS_GPIO=y CONFIG_SWITCH=y CONFIG_SWITCH_GPIO=y CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_TWL4030=y CONFIG_STAGING=y CONFIG_ANDROID=y CONFIG_ANDROID_BINDER_IPC=y diff --git a/arch/arm/mach-rk30/board-rk30-phone-loquat.c b/arch/arm/mach-rk30/board-rk30-phone-loquat.c index 2991beed0a29..6d419666ca6f 100755 --- a/arch/arm/mach-rk30/board-rk30-phone-loquat.c +++ b/arch/arm/mach-rk30/board-rk30-phone-loquat.c @@ -1543,18 +1543,9 @@ static struct i2c_board_info __initdata i2c0_info[] = { #endif #ifdef CONFIG_I2C1_RK30 -#include "board-rk30-sdk-wm8326.c" #include "board-rk30-sdk-twl80032.c" static struct i2c_board_info __initdata i2c1_info[] = { -#if defined (CONFIG_MFD_WM831X_I2C) - { - .type = "wm8326", - .addr = 0x34, - .flags = 0, - .irq = RK30_PIN6_PA4, - .platform_data = &wm831x_platdata, - }, -#endif + #if defined (CONFIG_TWL4030_CORE) { .type = "twl6032", diff --git a/arch/arm/mach-rk30/board-rk30-sdk-twl80032.c b/arch/arm/mach-rk30/board-rk30-sdk-twl80032.c index e0c99894abce..9961dd0a51ce 100755 --- a/arch/arm/mach-rk30/board-rk30-sdk-twl80032.c +++ b/arch/arm/mach-rk30/board-rk30-sdk-twl80032.c @@ -3,6 +3,15 @@ #include +#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 @@ -24,7 +33,6 @@ static inline int twl_reg_write(unsigned base, unsigned slave_subgp, unsigned of int tps80032_pre_init(void){ int ret; u8 value; - printk("--------------------\n"); printk("%s\n", __func__); return 0; @@ -34,110 +42,108 @@ int tps80032_set_init(void) { 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); @@ -145,91 +151,93 @@ int tps80032_set_init(void) 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, @@ -245,7 +253,7 @@ static struct regulator_init_data tps80032_smps1 = { /* */ static struct regulator_init_data tps80032_smps2 = { .constraints = { - .name = "TPS_SMPS2", + .name = "SMPS2", .min_uV = 600000, .max_uV = 2100000, .apply_uV = 1, @@ -263,7 +271,7 @@ static struct regulator_init_data tps80032_smps2 = { /* */ static struct regulator_init_data tps80032_smps3 = { .constraints = { - .name = "TPS_SMPS3", + .name = "SMPS3", .min_uV = 600000, .max_uV = 2100000, .apply_uV = 1, @@ -280,7 +288,7 @@ static struct regulator_init_data tps80032_smps3 = { /* */ static struct regulator_init_data tps80032_smps4 = { .constraints = { - .name = "TPS_SMPS4", + .name = "SMPS4", .min_uV = 600000, .max_uV = 2100000, .apply_uV = 1, @@ -295,7 +303,7 @@ static struct regulator_init_data tps80032_smps4 = { /* */ static struct regulator_init_data tps80032_smps5 = { .constraints = { - .name = "TPS_SMPS5", + .name = "SMPS5", .min_uV = 600000, .max_uV = 2100000, .apply_uV = 1, @@ -309,7 +317,7 @@ static struct regulator_init_data tps80032_smps5 = { }; static struct regulator_init_data tps80032_ldo1 = { .constraints = { - .name = "TPS_LDO1", + .name = "LDO1", .min_uV = 1200000, .max_uV = 3000000, .apply_uV = 1, @@ -325,7 +333,7 @@ static struct regulator_init_data tps80032_ldo1 = { /* */ static struct regulator_init_data tps80032_ldo2 = { .constraints = { - .name = "TPS_LDO2", + .name = "LDO2", .min_uV = 1200000, .max_uV = 3000000, .apply_uV = 1, @@ -341,7 +349,7 @@ static struct regulator_init_data tps80032_ldo2 = { /* */ static struct regulator_init_data tps80032_ldo3 = { .constraints = { - .name = "TPS_LDO3", + .name = "LDO3", .min_uV = 1200000, .max_uV = 3000000, .apply_uV = 1, @@ -357,7 +365,7 @@ static struct regulator_init_data tps80032_ldo3 = { /* */ static struct regulator_init_data tps80032_ldo4 = { .constraints = { - .name = "TPS_LDO4", + .name = "LDO4", .min_uV = 1200000, .max_uV = 3000000, .apply_uV = 1, @@ -373,7 +381,7 @@ static struct regulator_init_data tps80032_ldo4 = { /* */ static struct regulator_init_data tps80032_ldo5 = { .constraints = { - .name = "TPS_LDO5", + .name = "LDO5", .min_uV = 1200000, .max_uV = 3000000, .apply_uV = 1, @@ -389,7 +397,7 @@ static struct regulator_init_data tps80032_ldo5 = { /* */ static struct regulator_init_data tps80032_ldo6 = { .constraints = { - .name = "TPS_LDO6", + .name = "LDO6", .min_uV = 1200000, .max_uV = 3000000, .apply_uV = 1, @@ -405,7 +413,7 @@ static struct regulator_init_data tps80032_ldo6 = { /* */ static struct regulator_init_data tps80032_ldo7 = { .constraints = { - .name = "TPS_LDO7", + .name = "LDO7", .min_uV = 1200000, .max_uV = 3000000, .apply_uV = 1, @@ -421,7 +429,7 @@ static struct regulator_init_data tps80032_ldo7 = { /* */ static struct regulator_init_data tps80032_ldoln = { .constraints = { - .name = "TPS_LDOLN", + .name = "LDOLN", .min_uV = 1200000, .max_uV = 3000000, .apply_uV = 1, @@ -437,7 +445,7 @@ static struct regulator_init_data tps80032_ldoln = { /* */ static struct regulator_init_data tps80032_ldousb = { .constraints = { - .name = "TPS_LDOUSB", + .name = "LDOUSB", .min_uV = 3300000, .max_uV = 3300000, .apply_uV = 1, @@ -453,7 +461,7 @@ static struct regulator_init_data tps80032_ldousb = { /* */ static struct regulator_init_data tps80032_ldovana = { .constraints = { - .name = "TPS_LDOVANA", + .name = "LDOVANA", .min_uV = 600000, .max_uV = 2500000, .apply_uV = 1, @@ -466,13 +474,14 @@ static struct regulator_init_data tps80032_ldovana = { .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, diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 2f102d7632f3..35ff8fe22183 100755 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -195,6 +195,18 @@ config TWL4030_CORE high speed USB OTG transceiver, an audio codec (on most versions) and many other features. +config TWL6030_POWER + bool "Support power resources on TWL6030 family chips" + depends on TWL4030_CORE + help + Say yes here if you want to use the power resources on the + TWL6030 family chips. Most of these resources are regulators, + which have a separate driver; some are control signals, such + as clock request handshaking. + + This driver defaults to assuming only APPs processor uses + the resource, it can however be overridden by board file + config TWL4030_MADC tristate "Texas Instruments TWL4030 MADC" depends on TWL4030_CORE @@ -233,6 +245,28 @@ config TWL6030_PWM Say yes here if you want support for TWL6030 PWM. This is used to control charging LED brightness. +config TWL6030_POWEROFF + bool "TWL6030 device poweroff" + depends on TWL4030_CORE + +config TWL6030_MADC + tristate "Texas Instruments TWL6030 MADC" + depends on TWL4030_CORE + help + This driver provides support for TWL6030-MADC. The + driver supports both RT and SW conversion methods. + + This driver can be built as a module. If so it will be + named twl6030-madc + +config TWL6030_GPADC + tristate "TWL6030 GPADC (General Purpose A/D Convertor) Support" + depends on TWL4030_CORE + default n + help + Say yes here if you want support for the TWL6030 General Purpose + A/D Convertor. + config AIC3262_CODEC bool "Support TI Codec Aic3262" select MFD_CORE diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 829bbf1b42fa..b7638f47a784 100755 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -39,10 +39,15 @@ obj-$(CONFIG_TPS6507X) += tps6507x.o obj-$(CONFIG_MENELAUS) += menelaus.o obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o -obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o +#obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o +obj-$(CONFIG_TWL4030_MADC) += twl6030-madc.o obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o +obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o +obj-$(CONFIG_TWL6030_POWEROFF) += twl6030-poweroff.o +obj-$(CONFIG_TWL6030_POWER) += twl6030-power.o + obj-$(CONFIG_AIC3262_CODEC) += tlv320aic3262-core.o tlv320aic3262-irq.o obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o @@ -97,4 +102,4 @@ obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o obj-$(CONFIG_MFD_TPS65910) += tps65910.o tps65910-irq.o obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o -obj-$(CONFIG_MFD_RK610) += rk610-core.o \ No newline at end of file +obj-$(CONFIG_MFD_RK610) += rk610-core.o diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c old mode 100644 new mode 100755 index 7226a2db300d..7c766c2e03da --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c @@ -423,7 +423,7 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev) int ret = -EINVAL; int irq = platform_get_irq(pdev, 0); u8 rd_reg; - + printk("+++ twl_rtc_probe +++\n"); if (irq <= 0) goto out1; diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c old mode 100644 new mode 100755 index cfb5aa72b196..7a72841503d0 --- a/drivers/usb/otg/twl6030-usb.c +++ b/drivers/usb/otg/twl6030-usb.c @@ -30,9 +30,12 @@ #include #include #include +#include #include #include +#include + /* usb register definitions */ #define USB_VENDOR_ID_LSB 0x00 #define USB_VENDOR_ID_MSB 0x01 @@ -63,9 +66,7 @@ #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 @@ -82,6 +83,11 @@ /* 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) @@ -95,11 +101,18 @@ struct twl6030_usb { 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; }; @@ -185,8 +198,13 @@ static int twl6030_phy_suspend(struct otg_transceiver *x, int suspend) 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; } @@ -206,8 +224,9 @@ static int twl6030_start_srp(struct otg_transceiver *x) 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"; @@ -215,12 +234,6 @@ static int twl6030_usb_ldo_init(struct twl6030_usb *twl) /* 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; @@ -234,6 +247,11 @@ static int twl6030_usb_ldo_init(struct twl6030_usb *twl) */ 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; } @@ -248,16 +266,16 @@ static ssize_t twl6030_usb_vbus_show(struct device *dev, 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); @@ -269,55 +287,103 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl) { 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; @@ -326,12 +392,11 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) 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; } @@ -356,7 +421,7 @@ static int twl6030_enable_irq(struct otg_transceiver *x) { 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); @@ -370,20 +435,60 @@ static int twl6030_enable_irq(struct otg_transceiver *x) 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; } @@ -401,6 +506,17 @@ static int twl6030_set_host(struct otg_transceiver *x, struct usb_bus *host) 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; @@ -408,7 +524,8 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) 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; @@ -422,10 +539,13 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) 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); @@ -444,6 +564,9 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) 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, @@ -469,6 +592,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) } twl->asleep = 0; + twl->is_phy_suspended = true; pdata->phy_init(dev); twl6030_phy_suspend(&twl->otg, 0); twl6030_enable_irq(&twl->otg); @@ -494,6 +618,7 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev) 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;