From 0692923d2a60c5766c0154b4f90f2f6f8e85cd97 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E5=BC=A0=E6=99=B4?= Date: Wed, 9 May 2012 15:01:06 +0800 Subject: [PATCH] rk30:phone:add sleep,battery charger,powerbutton ,gpadc and poweroff for TI pmu 80032 --- arch/arm/configs/rk30_phone_loquat_defconfig | 5 + arch/arm/mach-rk30/board-rk30-phone-twl60xx.c | 302 +++++++++++++++++- drivers/input/misc/Kconfig | 10 + drivers/input/misc/Makefile | 1 + drivers/input/misc/twl6030-pwrbutton.c | 200 ++++++++++++ drivers/mfd/twl-core.c | 26 +- drivers/power/twl6030_bci_battery.c | 10 +- drivers/regulator/twl-regulator.c | 2 +- include/linux/i2c/twl.h | 2 + 9 files changed, 535 insertions(+), 23 deletions(-) create mode 100644 drivers/input/misc/twl6030-pwrbutton.c mode change 100644 => 100755 drivers/power/twl6030_bci_battery.c diff --git a/arch/arm/configs/rk30_phone_loquat_defconfig b/arch/arm/configs/rk30_phone_loquat_defconfig index 0d993635ceba..3fe52d93fc15 100755 --- a/arch/arm/configs/rk30_phone_loquat_defconfig +++ b/arch/arm/configs/rk30_phone_loquat_defconfig @@ -229,6 +229,7 @@ CONFIG_TOUCHSCREEN_FT5306=y CONFIG_INPUT_MISC=y CONFIG_INPUT_LPSENSOR_AL3006=y CONFIG_INPUT_KEYCHORD=y +CONFIG_INPUT_TWL6030_PWRBUTTON=y CONFIG_INPUT_UINPUT=y CONFIG_MAG_SENSORS=y CONFIG_COMPASS_AK8975=y @@ -263,8 +264,12 @@ CONFIG_SPI_FPGA_GPIO_NUM=0 CONFIG_SPI_FPGA_GPIO_IRQ_NUM=0 CONFIG_POWER_SUPPLY=y CONFIG_TEST_POWER=y +CONFIG_TWL6030_BCI_BATTERY=y # CONFIG_HWMON is not set CONFIG_TWL4030_CORE=y +CONFIG_TWL6030_POWEROFF=y +CONFIG_TWL6030_MADC=y +CONFIG_TWL6030_GPADC=y CONFIG_AIC3262_CODEC=y CONFIG_REGULATOR=y CONFIG_REGULATOR_TWL4030=y diff --git a/arch/arm/mach-rk30/board-rk30-phone-twl60xx.c b/arch/arm/mach-rk30/board-rk30-phone-twl60xx.c index 05064a5193c2..c5583711a2e0 100755 --- a/arch/arm/mach-rk30/board-rk30-phone-twl60xx.c +++ b/arch/arm/mach-rk30/board-rk30-phone-twl60xx.c @@ -3,6 +3,19 @@ #include +#define grf_readl(offset) readl_relaxed(RK30_GRF_BASE + offset) +#define grf_writel(v, offset) do { writel_relaxed(v, RK30_GRF_BASE + offset); dsb(); } while (0) + +#define CRU_CLKGATE5_CON_ADDR 0x00e4 +#define GRF_GPIO6L_DIR_ADDR 0x0030 +#define GRF_GPIO6L_DO_ADDR 0x0068 +#define GRF_GPIO6L_EN_ADDR 0x00a0 +#define GPIO6_PB3_DIR_OUT 0x08000800 +#define GPIO6_PB3_DO_LOW 0x08000000 +#define GPIO6_PB3_DO_HIGH 0x08000800 +#define GPIO6_PB3_EN_MASK 0x08000800 +#define GPIO6_PB3_UNEN_MASK 0x08000000 + #define TWL60xx_IRQ_BASE (NR_GIC_IRQS + NR_GPIO_IRQS ) #ifdef CONFIG_TWL4030_CORE #define TWL60xx_BASE_NR_IRQS 24 @@ -11,29 +24,98 @@ #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 -static inline int twl_reg_read(unsigned base, unsigned slave_subgp, unsigned offset) +#define PREQ1_RES_ASS_A 0x2a +#define PREQ1_RES_ASS_B 0x2b +#define PREQ1_RES_ASS_C 0x2c +#define PREQ2_RES_ASS_A 0x2d +#define PREQ3_RES_ASS_A 0x30 +#define PHOENIX_MSK_TRANSITION 0x01 +#define PHOENIX_SENS_TRANSITION 0x0b +#define SMPS4_CFG_TRANS 0x11 +#define SMPS4_CFG_STATE 0x12 +#define SMPS4_CFG_VOLTAGE 0x13 +#define SMPS5_CFG_TRANS 0x17 +#define SMPS5_CFG_STATE 0x18 +#define SMPS5_CFG_FORCE 0x19 +#define SMPS5_CFG_VOLTAGE 0x1A +#define SMPS5_CFG_STEP 0x1B +#define SMPS1_CFG_TRANS 0x23 +#define SMPS1_CFG_STATE 0x24 +#define SMPS1_CFG_FORCE 0x25 +#define SMPS1_CFG_VOLTAGE 0x26 +#define SMPS1_CFG_STEP 0x27 +#define SMPS2_CFG_TRANS 0x29 +#define SMPS2_CFG_STATE 0x2a +#define SMPS2_CFG_FORCE 0x2b +#define SMPS2_CFG_VOLTAGE 0x2c +#define SMPS2_CFG_STEP 0x2d +#define VANA_CFG_TRANS 0x51 +#define VANA_CFG_STATE 0x52 +#define VANA_CFG_VOLTAGE 0x53 +#define LDO2_CFG_TRANS 0x55 +#define LDO2_CFG_STATE 0x56 +#define LDO2_CFG_VOLTAGE 0x57 +#define LDO4_CFG_TRANS 0x59 +#define LDO4_CFG_STATE 0x5a +#define LDO4_CFG_VOLTAGE 0x5b +#define LDO3_CFG_TRANS 0x5d +#define LDO3_CFG_STATE 0x5e +#define LDO3_CFG_VOLTAGE 0x5f +#define LDO6_CFG_TRANS 0x61 +#define LDO6_CFG_STATE 0x62 +#define LDO6_CFG_VOLTAGE 0x63 +#define LDOLN_CFG_TRANS 0x65 +#define LDOLN_CFG_STATE 0x66 +#define LDOLN_CFG_VOLTAGE 0x67 +#define LDO5_CFG_TRANS 0x69 +#define LDO5_CFG_STATE 0x6A +#define LDO5_CFG_VOLTAGE 0x6B +#define LDO1_CFG_TRANS 0x6D +#define LDO1_CFG_STATE 0x6E +#define LDO1_CFG_VOLTAGE 0x6F +#define LDOUSB_CFG_TRANS 0x71 +#define LDOUSB_CFG_STATE 0x72 +#define LDOUSB_CFG_VOLTAGE 0x73 +#define LDO7_CFG_TRANS 0x75 +#define LDO7_CFG_STATE 0x76 +#define LDO7_CFG_VOLTAGE 0x77 +static inline int twl_reg_read(unsigned base, unsigned slave_subgp) { u8 value; int status; - status = twl_i2c_read_u8(slave_subgp,&value, base + offset); + status = twl_i2c_read_u8(slave_subgp,&value, base); return (status < 0) ? status : value; } -static inline int twl_reg_write(unsigned base, unsigned slave_subgp, unsigned offset, +static inline int twl_reg_write(unsigned base, unsigned slave_subgp, u8 value) { - return twl_i2c_write_u8(slave_subgp,value, base + offset); + return twl_i2c_write_u8(slave_subgp,value, base); } +#define PMU_POWER_SLEEP RK30_PIN6_PB3 + int tps80032_pre_init(void){ int ret; u8 value; - printk("%s\n", __func__); + printk("%s\n", __func__); + + gpio_request(PMU_POWER_SLEEP, "NULL"); + gpio_direction_output(PMU_POWER_SLEEP, GPIO_LOW); + + twl_reg_write(PREQ1_RES_ASS_A,TWL_MODULE_PM_SLAVE_RES,0x0b); + twl_reg_write(PREQ1_RES_ASS_B,TWL_MODULE_PM_SLAVE_RES,0x10); + twl_reg_write(PREQ1_RES_ASS_C,TWL_MODULE_PM_SLAVE_RES,0x2f); + twl_reg_write(PHOENIX_SENS_TRANSITION,TWL_MODULE_PM_MASTER,0xc0); //set pmu enter sleep on a preq1 rising edge + + twl_reg_write(SMPS1_CFG_STATE,TWL_MODULE_PM_RECEIVER,0x01); //set state + twl_reg_write(SMPS2_CFG_STATE,TWL_MODULE_PM_RECEIVER,0x01); + twl_reg_write(LDO7_CFG_STATE,TWL_MODULE_PM_RECEIVER,0x01); + +// twl_reg_write(LDO5_CFG_TRANS,TWL_MODULE_PM_RECEIVER,0x03); //set ldo5 is disabled when in sleep mode +// twl_reg_write(LDO7_CFG_TRANS,TWL_MODULE_PM_RECEIVER,0x03); //set ldo7 is disabled when in sleep mode return 0; @@ -136,12 +218,14 @@ int tps80032_set_init(void) regulator_put(ldo); udelay(100); + 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)); regulator_put(ldo); udelay(100); + /* ldo = regulator_get(NULL, "vana"); //vana_out regulator_set_voltage(ldo, 2500000, 2500000); @@ -489,14 +573,212 @@ static struct regulator_init_data tps80032_ldovana = { .consumer_supplies = tps80032_ldovana_supply, }; +static struct twl4030_madc_platform_data tps80032_madc_data = { + .irq_line = 1, +}; +static int tps_batt_table[] = { +/* 0 C*/ + 3400,3420,3440,3475,3505,3525, + 3540,3557,3570,3580,3610, + 3630,3640,3652,3662,3672, + 3680,3687,3693,3699,3705, + 3710,3714,3718,3722,3726, + 3730,3734,3738,3742,3746, + 3750,3756,3764,3774,3786, + 3800,3808,3817,3827,3845, + 3950,3964,3982,4002,4026, + 4030,4034,4055,4070,4085,4120 +}; +static struct twl4030_bci_platform_data tps80032_bci_data = { + .battery_tmp_tbl = tps_batt_table, + .tblsize = ARRAY_SIZE(tps_batt_table), +}; +static struct twl4030_usb_data tps80032_usb_data = { + .usb_mode = T2_USB_MODE_ULPI, +}; +static struct twl4030_ins sleep_on_seq[] __initdata = { +/* + * Turn off everything + */ + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, 1, 0, RES_STATE_SLEEP), 2}, +}; + +static struct twl4030_script sleep_on_script __initdata = { + .script = sleep_on_seq, + .size = ARRAY_SIZE(sleep_on_seq), + .flags = TWL4030_SLEEP_SCRIPT, +}; + +static struct twl4030_ins wakeup_seq[] __initdata = { +/* + * Reenable everything + */ + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, 1, 0, RES_STATE_ACTIVE), 2}, +}; + +static struct twl4030_script wakeup_script __initdata = { + .script = wakeup_seq, + .size = ARRAY_SIZE(wakeup_seq), + .flags = TWL4030_WAKEUP12_SCRIPT, +}; + +static struct twl4030_ins wakeup_p3_seq[] __initdata = { +/* + * Reenable everything + */ + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, 1, 0, RES_STATE_ACTIVE), 2}, +}; + +static struct twl4030_script wakeup_p3_script __initdata = { + .script = wakeup_p3_seq, + .size = ARRAY_SIZE(wakeup_p3_seq), + .flags = TWL4030_WAKEUP3_SCRIPT, +}; +static struct twl4030_ins wrst_seq[] __initdata = { +/* + * Reset twl4030. + * Reset VDD1 regulator. + * Reset VDD2 regulator. + * Reset VPLL1 regulator. + * Enable sysclk output. + * Reenable twl4030. + */ + {MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_OFF), 2}, + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, 0, 1, RES_STATE_ACTIVE), + 0x13}, + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_PP, 0, 3, RES_STATE_OFF), 0x13}, + {MSG_SINGULAR(DEV_GRP_NULL, RES_VDD1, RES_STATE_WRST), 0x13}, + {MSG_SINGULAR(DEV_GRP_NULL, RES_VDD2, RES_STATE_WRST), 0x13}, + {MSG_SINGULAR(DEV_GRP_NULL, RES_VPLL1, RES_STATE_WRST), 0x35}, + {MSG_SINGULAR(DEV_GRP_P3, RES_HFCLKOUT, RES_STATE_ACTIVE), 2}, + {MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_ACTIVE), 2}, +}; +static struct twl4030_script wrst_script __initdata = { + .script = wrst_seq, + .size = ARRAY_SIZE(wrst_seq), + .flags = TWL4030_WRST_SCRIPT, +}; + +static struct twl4030_script *twl4030_scripts[] __initdata = { + /* wakeup12 script should be loaded before sleep script, otherwise a + board might hit retention before loading of wakeup script is + completed. This can cause boot failures depending on timing issues. + */ + &wakeup_script, + &sleep_on_script, + &wakeup_p3_script, + &wrst_script, +}; +static struct twl4030_resconfig twl4030_rconfig[] __initdata = { + { .resource = RES_VDD1, .devgroup = -1, + .type = 1, .type2 = -1, .remap_off = RES_STATE_OFF, + .remap_sleep = RES_STATE_OFF + }, + { .resource = RES_VDD2, .devgroup = -1, + .type = 1, .type2 = -1, .remap_off = RES_STATE_OFF, + .remap_sleep = RES_STATE_OFF + }, + { .resource = RES_VPLL1, .devgroup = -1, + .type = 1, .type2 = -1, .remap_off = RES_STATE_OFF, + .remap_sleep = RES_STATE_OFF + }, + { .resource = RES_VPLL2, .devgroup = -1, + .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_VAUX1, .devgroup = -1, + .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_VAUX2, .devgroup = -1, + .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_VAUX3, .devgroup = -1, + .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_VAUX4, .devgroup = -1, + .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_VMMC1, .devgroup = -1, + .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_VMMC2, .devgroup = -1, + .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_VDAC, .devgroup = -1, + .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_VSIM, .devgroup = -1, + .type = -1, .type2 = 3, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_VINTANA1, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, + .type = -1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_VINTANA2, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, + .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_VINTDIG, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, + .type = -1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_VIO, .devgroup = DEV_GRP_P3, + .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_CLKEN, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, + .type = 1, .type2 = -1 , .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_REGEN, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, + .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_NRES_PWRON, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, + .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_SYSEN, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, + .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_HFCLKOUT, .devgroup = DEV_GRP_P3, + .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_32KCLKOUT, .devgroup = -1, + .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_RESET, .devgroup = -1, + .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 + }, + { .resource = RES_MAIN_REF, .devgroup = -1, + .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 + }, + { 0, 0}, +}; +static struct twl4030_power_data tps80032_scripts_data __initdata = { + .scripts = twl4030_scripts, + .num = ARRAY_SIZE(twl4030_scripts), + .resource_config = twl4030_rconfig, +}; + + +void __sramfunc board_pmu_suspend(void) +{ + grf_writel(GPIO6_PB3_DIR_OUT, GRF_GPIO6L_DIR_ADDR); + grf_writel(GPIO6_PB3_DO_HIGH, GRF_GPIO6L_DO_ADDR); //set gpio6_b3 output low + grf_writel(GPIO6_PB3_EN_MASK, GRF_GPIO6L_EN_ADDR); +} +void __sramfunc board_pmu_resume(void) +{ + grf_writel(GPIO6_PB3_DIR_OUT, GRF_GPIO6L_DIR_ADDR); + grf_writel(GPIO6_PB3_DO_LOW, GRF_GPIO6L_DO_ADDR); //set gpio6_b3 output high + grf_writel(GPIO6_PB3_EN_MASK, GRF_GPIO6L_EN_ADDR); + sram_udelay(2000); +} static struct twl4030_platform_data tps80032_data = { .irq_base = TWL60xx_IRQ_BASE, .irq_end = TWL60xx_IRQ_END, //.irq = RK29_PIN0_PA1, -// .pre_init = tps80032_pre_init, + .pre_init = tps80032_pre_init, .set_init = tps80032_set_init, - + + .madc = &tps80032_madc_data, + .bci = &tps80032_bci_data, + .usb = &tps80032_usb_data, +// .power = &tps80032_scripts_data, /* Regulators */ .ldo1 = &tps80032_ldo1, .ldo2 = &tps80032_ldo2, diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 1a362c11bf68..cc7ab5426d26 100755 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -284,6 +284,16 @@ config INPUT_TWL4030_PWRBUTTON To compile this driver as a module, choose M here. The module will be called twl4030_pwrbutton. +config INPUT_TWL6030_PWRBUTTON + tristate "TWL6030 Power button Driver" + depends on TWL4030_CORE + help + Say Y here if you want to enable power key reporting via the + TWL6030 family of chips. + + To compile this driver as a module, choose M here. The module will + be called twl6030_pwrbutton. + config INPUT_TWL4030_VIBRA tristate "Support for TWL4030 Vibrator" depends on TWL4030_CORE diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 3b6e7b0e262b..eaab936a0ada 100755 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o +obj-$(CONFIG_INPUT_TWL6030_PWRBUTTON) += twl6030-pwrbutton.o obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o obj-$(CONFIG_INPUT_UINPUT) += uinput.o obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o diff --git a/drivers/input/misc/twl6030-pwrbutton.c b/drivers/input/misc/twl6030-pwrbutton.c new file mode 100644 index 000000000000..3b5b76191a7c --- /dev/null +++ b/drivers/input/misc/twl6030-pwrbutton.c @@ -0,0 +1,200 @@ +/** + * twl6030-pwrbutton.c - TWL6030 Power Button Input Driver + * + * Copyright (C) 2011 + * + * Written by Dan Murphy + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file "COPYING" in the main directory of this + * archive for more details. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Derived Work from: twl4030-pwrbutton.c from + * Peter De Schrijver + * Felipe Balbi + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PWR_PWRON_IRQ (1 << 0) +#define STS_HW_CONDITIONS 0x21 + +struct twl6030_pwr_button { + struct input_dev *input_dev; + struct device *dev; + int report_key; +}; + +static inline int twl6030_readb(struct twl6030_pwr_button *twl, + u8 module, u8 address) +{ + u8 data = 0; + int ret = 0; + + ret = twl_i2c_read_u8(module, &data, address); + if (ret >= 0) + ret = data; + else + dev_dbg(twl->dev, + "TWL6030:readb[0x%x,0x%x] Error %d\n", + module, address, ret); + + return ret; +} + +static inline int twl6030_writeb(struct twl6030_pwr_button *twl, u8 module, + u8 data, u8 address) +{ + int ret = 0; + + ret = twl_i2c_write_u8(module, data, address); + if (ret < 0) + dev_dbg(twl->dev, + "TWL6030:Write[0x%x] Error %d\n", address, ret); + return ret; +} + +static irqreturn_t powerbutton_irq(int irq, void *_pwr) +{ + struct twl6030_pwr_button *pwr = _pwr; + int hw_state; + int pwr_val; + static int prev_hw_state = 0xFFFF; + static int push_release_flag; + + hw_state = twl6030_readb(pwr, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); + pwr_val = !(hw_state & PWR_PWRON_IRQ); + if ((prev_hw_state != pwr_val) && (prev_hw_state != 0xFFFF)) { + push_release_flag = 0; + input_report_key(pwr->input_dev, pwr->report_key, pwr_val); + input_sync(pwr->input_dev); + } else if (!push_release_flag) { + push_release_flag = 1; + input_report_key(pwr->input_dev, pwr->report_key, !pwr_val); + input_sync(pwr->input_dev); + + msleep(20); + + input_report_key(pwr->input_dev, pwr->report_key, pwr_val); + input_sync(pwr->input_dev); + } else + push_release_flag = 0; + + prev_hw_state = pwr_val; + + return IRQ_HANDLED; +} + +static int __devinit twl6030_pwrbutton_probe(struct platform_device *pdev) +{ + struct twl6030_pwr_button *pwr_button; + int irq = platform_get_irq(pdev, 0); + int err = -ENODEV; + + pr_info("%s: Enter\n", __func__); + pwr_button = kzalloc(sizeof(struct twl6030_pwr_button), GFP_KERNEL); + if (!pwr_button) + return -ENOMEM; + + pwr_button->input_dev = input_allocate_device(); + if (!pwr_button->input_dev) { + dev_dbg(&pdev->dev, "Can't allocate power button\n"); + goto input_error; + } + + __set_bit(EV_KEY, pwr_button->input_dev->evbit); + + pwr_button->report_key = KEY_END; + pwr_button->dev = &pdev->dev; + pwr_button->input_dev->evbit[0] = BIT_MASK(EV_KEY); + pwr_button->input_dev->keybit[BIT_WORD(pwr_button->report_key)] = + BIT_MASK(pwr_button->report_key); + pwr_button->input_dev->name = "twl6030_pwrbutton"; + pwr_button->input_dev->phys = "twl6030_pwrbutton/input0"; + pwr_button->input_dev->dev.parent = &pdev->dev; + + err = request_threaded_irq(irq, NULL, powerbutton_irq, + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, + "twl6030_pwrbutton", pwr_button); + if (err < 0) { + dev_dbg(&pdev->dev, "Can't get IRQ for pwrbutton: %d\n", err); + goto free_input_dev; + } + + err = input_register_device(pwr_button->input_dev); + if (err) { + dev_dbg(&pdev->dev, "Can't register power button: %d\n", err); + goto free_irq; + } + + twl6030_interrupt_unmask(0x01, REG_INT_MSK_LINE_A); + twl6030_interrupt_unmask(0x01, REG_INT_MSK_STS_A); + + platform_set_drvdata(pdev, pwr_button); + + return 0; + +free_irq: + free_irq(irq, NULL); +free_input_dev: + input_free_device(pwr_button->input_dev); +input_error: + kfree(pwr_button); + return err; +} + +static int __devexit twl6030_pwrbutton_remove(struct platform_device *pdev) +{ + struct input_dev *pwr = platform_get_drvdata(pdev); + int irq = platform_get_irq(pdev, 0); + + free_irq(irq, pwr); + input_unregister_device(pwr); + + return 0; +} + +struct platform_driver twl6030_pwrbutton_driver = { + .probe = twl6030_pwrbutton_probe, + .remove = __devexit_p(twl6030_pwrbutton_remove), + .driver = { + .name = "twl6030_pwrbutton", + .owner = THIS_MODULE, + }, +}; + +static int __init twl6030_pwrbutton_init(void) +{ + return platform_driver_register(&twl6030_pwrbutton_driver); +} +module_init(twl6030_pwrbutton_init); + +static void __exit twl6030_pwrbutton_exit(void) +{ + platform_driver_unregister(&twl6030_pwrbutton_driver); +} +module_exit(twl6030_pwrbutton_exit); + +MODULE_ALIAS("platform:twl6030_pwrbutton"); +MODULE_DESCRIPTION("Triton2 Power Button"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Dan Murphy "); diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 26b4db7a23c7..be9c6ac119e0 100755 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -406,12 +406,12 @@ int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) * fill the data Tx buffer */ msg = &twl->xfer_msg[0]; - #if 1 //add - if((reg == 0x26)||(reg == 0x2C)||(reg == 0x2A)) + #if 1 + //add + if(mod_no== TWL_MODULE_PM_DVS) { msg->addr = 0x12; - reg--; - } + } else { msg->addr = twl->address; @@ -475,7 +475,19 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) mutex_lock(&twl->xfer_lock); /* [MSG1] fill the register address data */ msg = &twl->xfer_msg[0]; + #if 1 + if(mod_no== 0x1a) + { + msg->addr = 0x12; + } + else + { msg->addr = twl->address; + + } + #else + msg->addr = twl->address; + #endif msg->len = 1; msg->flags = 0; /* Read the register value */ val = twl_map[mod_no].base + reg; @@ -519,8 +531,8 @@ int twl_i2c_write_u8(u8 mod_no, u8 value, u8 reg) /* 2 bytes offset 1 contains the data offset 0 is used by i2c_write */ u8 temp_buffer[2] = { 0 }; - #if 1 //add - if(reg == 0x26) + #if 0 //add + if(mod_no == 0x1a) { temp_buffer[1] = 0x43; twl_i2c_write(mod_no, temp_buffer, 0x25, 1); @@ -1317,7 +1329,7 @@ static void clocks_init(struct device *dev, #ifdef CONFIG_PM static int twl_suspend(struct i2c_client *client, pm_message_t mesg) -{ +{ return irq_set_irq_wake(client->irq, 1); } diff --git a/drivers/power/twl6030_bci_battery.c b/drivers/power/twl6030_bci_battery.c old mode 100644 new mode 100755 index cbfd2f0c7522..fc35f8ba2a20 --- a/drivers/power/twl6030_bci_battery.c +++ b/drivers/power/twl6030_bci_battery.c @@ -2419,7 +2419,7 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev) u8 chargerusb_ctrl1 = 0; u8 hw_state = 0; u8 reg = 0; - + printk("%s\n", __func__); if (!pdata) { dev_dbg(&pdev->dev, "platform_data not available\n"); return -EINVAL; @@ -2828,10 +2828,10 @@ static int twl6030_bci_battery_suspend(struct device *dev) /* We cannot tolarate a sleep longer than 30 seconds * while on ac charging we have to reset the BQ watchdog timer. */ - if ((di->charger_source == POWER_SUPPLY_TYPE_MAINS) && - ((wakeup_timer_seconds > 25) || !wakeup_timer_seconds)) { - wakeup_timer_seconds = 25; - } +// if ((di->charger_source == POWER_SUPPLY_TYPE_MAINS) && +// ((wakeup_timer_seconds > 25) || !wakeup_timer_seconds)) { +// wakeup_timer_seconds = 25; +// } /*reset the BQ watch dog*/ events = BQ2415x_RESET_TIMER; diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 3d18ea4ce8a9..b8c8a55bcfa0 100755 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -1253,7 +1253,7 @@ static struct twlreg_info twl_regs[] = { TWL6032_ADJUSTABLE_DVSSMPS(SMPS1, 0x22), TWL6032_ADJUSTABLE_DVSSMPS(SMPS2, 0x28), - TWL6032_ADJUSTABLE_DVSSMPS(SMPS5, 0x26), + TWL6032_ADJUSTABLE_DVSSMPS(SMPS5, 0x16), TWL6030_EXTERNAL_CONTROL_PIN(SYSEN, 0x83, 0), TWL6030_EXTERNAL_CONTROL_PIN(REGEN1, 0x7d, 0), diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index accbd9a4c478..ea9ba0035fe1 100755 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h @@ -203,6 +203,8 @@ int twl_i2c_read_u8(u8 mod_no, u8 *val, u8 reg); int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); +void twl6030_poweroff(void); + int twl_get_type(void); int twl_get_version(void); -- 2.34.1