From d69f6b8301349b0100c07c65157bfd35e17f20f7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E5=BC=A0=E6=99=B4?= Date: Mon, 14 Apr 2014 14:39:17 +0800 Subject: [PATCH] rk3288:ricoh619&syb827:support pmic ricoh619 and dcdc syb827 --- arch/arm/boot/dts/ricoh619.dtsi | 169 +++ arch/arm/boot/dts/rk3288-tb.dts | 238 +++- arch/arm/configs/rockchip_defconfig | 6 + drivers/input/misc/Kconfig | 9 + drivers/input/misc/Makefile | 1 + drivers/input/misc/ricoh619-pwrkey.c | 706 +++++----- drivers/mfd/Kconfig | 12 + drivers/mfd/Makefile | 1 + drivers/mfd/ricoh619-irq.c | 173 ++- drivers/mfd/ricoh619.c | 260 ++-- drivers/power/Kconfig | 7 + drivers/power/Makefile | 1 + drivers/power/ricoh619-battery.c | 1377 +++++++++++++------ drivers/regulator/Kconfig | 12 + drivers/regulator/Makefile | 2 + drivers/regulator/ricoh619-regulator.c | 170 ++- drivers/regulator/syb827.c | 584 ++++++++ drivers/rtc/Kconfig | 10 + drivers/rtc/Makefile | 2 + drivers/rtc/rtc-ricoh619.c | 160 ++- include/linux/mfd/ricoh619.h | 14 +- include/linux/power/ricoh619_battery.h | 36 +- include/linux/power/ricoh61x_battery_init.h | 12 +- 23 files changed, 2928 insertions(+), 1034 deletions(-) create mode 100644 arch/arm/boot/dts/ricoh619.dtsi mode change 100755 => 100644 arch/arm/boot/dts/rk3288-tb.dts mode change 100644 => 100755 drivers/input/misc/Kconfig mode change 100644 => 100755 drivers/input/misc/Makefile mode change 100644 => 100755 drivers/input/misc/ricoh619-pwrkey.c mode change 100644 => 100755 drivers/mfd/ricoh619-irq.c mode change 100644 => 100755 drivers/power/Kconfig mode change 100644 => 100755 drivers/power/Makefile mode change 100644 => 100755 drivers/power/ricoh619-battery.c mode change 100644 => 100755 drivers/regulator/Kconfig mode change 100644 => 100755 drivers/regulator/Makefile create mode 100755 drivers/regulator/syb827.c mode change 100644 => 100755 drivers/rtc/Kconfig mode change 100644 => 100755 drivers/rtc/Makefile mode change 100644 => 100755 include/linux/mfd/ricoh619.h mode change 100644 => 100755 include/linux/power/ricoh619_battery.h diff --git a/arch/arm/boot/dts/ricoh619.dtsi b/arch/arm/boot/dts/ricoh619.dtsi new file mode 100644 index 000000000000..99af2fa695df --- /dev/null +++ b/arch/arm/boot/dts/ricoh619.dtsi @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2014 Ricoh Electronic Devices Co., Ltd. - http://www.rioch.com/LSI + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * Integrated Power Management Chip + * http://www.ricoh.com/LSI/product_pmic/multiple-pmu/rc5t619/ + */ + +&ricoh619 +{ + compatible = "ricoh,ricoh619"; + interrupt-controller; + #interrupt-cells = <0>; + + pwrkey: pwrkey@0 { + compatible = "ricoh,ricoh619-pwrkey"; + ricoh,pwrkey-delay-ms = <20>; + }; + + rtc { + compatible = "ricoh,ricoh619-rtc"; + ricoh,rtc-tm-year = <2014>; + ricoh,rtc-tm-month = <1>; + ricoh,rtc-tm-mday = <1>; + ricoh,rtc-tm-hour = <8>; + ricoh,rtc-tm-min = <0>; + ricoh,rtc-tm-sec = <0>; + }; + + battery { + compatible = "ricoh,ricoh619-battery"; + ricoh,alarm-vol-mv = <3300>; + ricoh,multiple = <100>; + ricoh,monitor-time = <1>; + + ricoh,ch-vfchg = <0xff>;/* VFCHG = 0 - 4 (4.05v, 4.10v, 4.15v, 4.20v, 4.35v) */ + ricoh,ch-vrchg = <0xff>;/* VRCHG = 0 - 4 (3.85v, 3.90v, 3.95v, 4.00v, 4.10v) */ + ricoh,ch-vbatovset = <0xff>;/* VBATOVSET = 0 or 1 (0 : 4.38v(up)/3.95v(down) 1: 4.53v(up)/4.10v(down)) */ + ricoh,ch-ichg = <0xff>;/* ICHG = 0 - 0x1D (100mA - 3000mA) */ + ricoh,ch-ilim-adp = <0xff>;/* ILIM_ADP = 0 - 0x1D (100mA - 3000mA) */ + ricoh,ch-ilim-usb = <0xff>;/* ILIM_USB = 0 - 0x1D (100mA - 3000mA) */ + ricoh,ch-icchg = <0x03>;/* ICCHG = 0 - 3 (50mA 100mA 150mA 200mA) */ + ricoh,fg-target-vsys = <3000>;/* This value is the target one to DSOC=0% */ + ricoh,fg-target-ibat = <1000>;/* This value is the target one to DSOC=0% */ + ricoh,fg-poff-vbat = <0>;/* setting value of 0 per Vbat */ + ricoh,jt-en = <0>;/* JEITA Enable = 0 or 1 (1:enable, 0:disable) */ + ricoh,jt-hw-sw = <1>;/* JEITA HW or SW = 0 or 1 (1:HardWare, 0:SoftWare) */ + ricoh,jt-temp-h = <50>;/* degree C */ + ricoh,jt-temp-l = <12>;/* degree C */ + ricoh,jt-vfchg-h = <0x03>;/* VFCHG High = 0 - 4 (4.05v, 4.10v, 4.15v, 4.20v, 4.35v) */ + ricoh,jt-vfchg-l = <0>;/* VFCHG High = 0 - 4 (4.05v, 4.10v, 4.15v, 4.20v, 4.35v) */ + ricoh,jt-ichg-h = <0x0D>;/* VFCHG Low = 0 - 4 (4.05v, 4.10v, 4.15v, 4.20v, 4.35v) */ + ricoh,jt-ichg-l = <0x09>;/* ICHG Low = 0 - 0x1D (100mA - 3000mA) */ + }; + + regulators { + #address-cells = <1>; + #size-cells = <0>; + + ricoh619_dcdc1_reg: regulator@0 { + reg = <0>; + regulator-compatible = "ricoh619_dc1"; + regulator-always-on; + regulator-boot-on; + }; + ricoh619_dcdc2_reg: regulator@1 { + reg = <1>; + regulator-compatible = "ricoh619_dc2"; + regulator-always-on; + regulator-boot-on; + }; + ricoh619_dcdc3_reg: regulator@2 { + reg = <2>; + regulator-compatible = "ricoh619_dc3"; + regulator-always-on; + regulator-boot-on; + }; + ricoh619_dcdc4_reg: regulator@3 { + reg = <3>; + regulator-compatible = "ricoh619_dc4"; + regulator-always-on; + regulator-boot-on; + }; + ricoh619_dcdc5_reg: regulator@4 { + reg = <4>; + regulator-compatible = "ricoh619_dc5"; + regulator-always-on; + regulator-boot-on; + }; + ricoh619_ldo1_reg: regulator@5 { + reg = <5>; + regulator-compatible = "ricoh619_ldo1"; + regulator-always-on; + regulator-boot-on; + }; + ricoh619_ldo2_reg: regulator@6 { + reg = <6>; + regulator-compatible = "ricoh619_ldo2"; + regulator-always-on; + regulator-boot-on; + }; + ricoh619_ldo3_reg: regulator@7 { + reg = <7>; + regulator-compatible = "ricoh619_ldo3"; + regulator-always-on; + regulator-boot-on; + }; + ricoh619_ldo4_reg: regulator@8 { + reg = <8>; + regulator-compatible = "ricoh619_ldo4"; + regulator-always-on; + regulator-boot-on; + }; + ricoh619_ldo5_reg: regulator@9 { + reg = <9>; + regulator-compatible = "ricoh619_ldo5"; + regulator-always-on; + regulator-boot-on; + }; + ricoh619_ldo6_reg: regulator@10 { + reg = <10>; + regulator-compatible = "ricoh619_ldo6"; + regulator-always-on; + regulator-boot-on; + }; + ricoh619_ldo7_reg: regulator@11 { + reg = <11>; + regulator-compatible = "ricoh619_ldo7"; + regulator-always-on; + regulator-boot-on; + }; + ricoh619_ldo8_reg: regulator@12 { + reg = <12>; + regulator-compatible = "ricoh619_ldo8"; + regulator-always-on; + regulator-boot-on; + }; + ricoh619_ldo9_reg: regulator@13 { + reg = <13>; + regulator-compatible = "ricoh619_ldo9"; + regulator-always-on; + regulator-boot-on; + }; + ricoh619_ldo10_reg: regulator@14 { + reg = <14>; + regulator-compatible = "ricoh619_ldo10"; + regulator-always-on; + regulator-boot-on; + }; + ricoh619_ldortc1_reg: regulator@15 { + reg = <15>; + regulator-compatible = "ricoh619_ldortc1"; + regulator-always-on; + regulator-boot-on; + }; + ricoh619_ldortc2_reg: regulator@16 { + reg = <16>; + regulator-compatible = "ricoh619_ldortc2"; + regulator-always-on; + regulator-boot-on; + }; + }; +}; + diff --git a/arch/arm/boot/dts/rk3288-tb.dts b/arch/arm/boot/dts/rk3288-tb.dts old mode 100755 new mode 100644 index b885f6049a28..9ff8b3037ec6 --- a/arch/arm/boot/dts/rk3288-tb.dts +++ b/arch/arm/boot/dts/rk3288-tb.dts @@ -308,7 +308,61 @@ reg = <0x1b>; status = "okay"; }; - + syb827b: syb827b@40 { + compatible = "silergy,syb827"; + reg = <0x40>; + status = "okay"; + regulators { + #address-cells = <1>; + #size-cells = <0>; + syb827b_dc1: regulator@0 { + reg = <0>; + regulator-compatible = "syb827_dcdc1"; + regulator-name = "vdd_arm"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + regulator-boot-on; + regulator-initial-mode = <0x2>; + regulator-initial-state = <3>; + regulator-state-mem { + regulator-state-mode = <0x2>; + regulator-state-disabled; + regulator-state-uv = <900000>; + }; + }; + }; + }; + syb827c: syb827c@41 { + compatible = "silergy,syb827"; + reg = <0x41>; + status = "okay"; + regulators { + #address-cells = <1>; + #size-cells = <0>; + syb827c_dc1: regulator@0 { + reg = <0>; + regulator-compatible = "syb827_dcdc1"; + regulator-name = "vdd_gpu"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + regulator-boot-on; + regulator-initial-mode = <0x2>; + regulator-initial-state = <3>; + regulator-state-mem { + regulator-state-mode = <0x2>; + regulator-state-enabled; + regulator-state-uv = <900000>; + }; + }; + }; + }; + + ricoh619: ricoh619@32 { + reg = <0x32>; + status = "okay"; + }; bq24296: bq24296@6b { compatible = "ti,bq24296"; reg = <0x6b>; @@ -316,6 +370,7 @@ bq24296,chg_current = <1000 2000 3000>; status = "okay"; }; + bq27320: bq27320@55 { compatible = "ti,bq27320"; reg = <0x55>; @@ -527,7 +582,7 @@ rockchip,power_type = ; label = "volume down"; rockchip,adc_value = <170>; }; - + power-key { gpios = <&gpio0 GPIO_A5 GPIO_ACTIVE_LOW>; linux,code = <116>; @@ -732,6 +787,185 @@ rockchip,power_type = ; }; }; +/include/ "ricoh619.dtsi" +&ricoh619 { + gpios =<&gpio0 GPIO_A4 GPIO_ACTIVE_HIGH>,<&gpio0 GPIO_B3 GPIO_ACTIVE_LOW>; + ricoh619,system-power-controller; + + regulators { + ricoh619_dcdc1_reg: regulator@0 { + regulator-name = "vdd_logic"; + regulator-min-microvolt = < 700000>; + regulator-max-microvolt = <1500000>; + regulator-initial-mode = <0x2>; + regulator-initial-state = <3>; + regulator-state-mem { + regulator-state-mode = <0x2>; + regulator-state-enabled; + regulator-state-uv = <900000>; + }; + }; + ricoh619_dcdc2_reg: regulator@1 { + regulator-name = "ricoh619_dcdc2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = <0x2>; + regulator-initial-state = <3>; + regulator-state-mem { + regulator-state-mode = <0x2>; + regulator-state-enabled; + regulator-state-uv = <1200000>; + }; + }; + ricoh619_dcdc3_reg: regulator@2 { + regulator-name = "ricoh619_dcdc3"; + regulator-min-microvolt = < 1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = <0x2>; + regulator-initial-state = <3>; + regulator-state-mem { + regulator-state-mode = <0x2>; + regulator-state-enabled; + regulator-state-uv = <1200000>; + }; + }; + ricoh619_dcdc4_reg: regulator@3 { + regulator-name = "ricoh619_dcdc4"; + regulator-min-microvolt = < 3300000>; + regulator-max-microvolt = <3300000>; + regulator-initial-mode = <0x2>; + regulator-initial-state = <3>; + regulator-state-mem { + regulator-state-mode = <0x2>; + regulator-state-enabled; + regulator-state-uv = <2800000>; + }; + }; + ricoh619_dcdc5_reg: regulator@4 { + regulator-name = "ricoh619_dcdc5"; + regulator-min-microvolt = < 2000000>; + regulator-max-microvolt = <2000000>; + regulator-initial-mode = <0x2>; + regulator-initial-state = <3>; + regulator-state-mem { + regulator-state-mode = <0x2>; + regulator-state-enabled; + regulator-state-uv = <2000000>; + }; + }; + ricoh619_ldo1_reg: regulator@5 { + regulator-name = "ricoh619_ldo1"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-initial-state = <3>; + regulator-state-mem { + regulator-state-enabled; + regulator-state-uv = <3300000>; + }; + }; + ricoh619_ldo2_reg: regulator@6 { + regulator-name = "ricoh619_ldo2"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-initial-state = <3>; + regulator-state-mem { + regulator-state-enabled; + regulator-state-uv = <3300000>; + }; + }; + ricoh619_ldo3_reg: regulator@7 { + regulator-name = "ricoh619_ldo3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-initial-state = <3>; + regulator-state-mem { + regulator-state-enabled; + regulator-state-uv = <3300000>; + }; + }; + ricoh619_ldo4_reg: regulator@8 { + regulator-name = "vcc_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-initial-state = <3>; + regulator-state-mem { + regulator-state-enabled; + regulator-state-uv = <3300000>; + }; + }; + ricoh619_ldo5_reg: regulator@9 { + regulator-name = "ricoh619_ldo5"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-initial-state = <3>; + regulator-state-mem { + regulator-state-enabled; + regulator-state-uv = <3300000>; + }; + }; + ricoh619_ldo6_reg: regulator@10 { + regulator-name = "ricoh619_ldo6"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-state = <3>; + regulator-state-mem { + regulator-state-enabled; + regulator-state-uv = <1800000>; + }; + }; + ricoh619_ldo7_reg: regulator@11 { + regulator-name = "ricoh619_ldo7"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-initial-state = <3>; + regulator-state-mem { + regulator-state-enabled; + regulator-state-uv = <3300000>; + }; + }; + ricoh619_ldo8_reg: regulator@12 { + regulator-name = "ricoh619_ldo8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-state = <3>; + regulator-state-mem { + regulator-state-enabled; + regulator-state-uv = <3300000>; + }; + }; + ricoh619_ldo9_reg: regulator@13 { + regulator-name = "ricoh619_ldo9"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-initial-state = <3>; + regulator-state-mem { + regulator-state-enabled; + regulator-state-uv = <3300000>; + }; + }; + ricoh619_ldo10_reg: regulator@14 { + regulator-name = "ricoh619_ldo10"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-state = <3>; + regulator-state-mem { + regulator-state-enabled; + regulator-state-uv = <3300000>; + }; + }; + ricoh619_ldortc1_reg: regulator@15 { + regulator-name = "ricoh619_ldortc1"; + regulator-min-microvolt = < 3300000>; + regulator-max-microvolt = <3300000>; + }; + ricoh619_ldortc2_reg: regulator@16 { + regulator-name = "ricoh619_ldortc2"; + regulator-min-microvolt = < 3300000>; + regulator-max-microvolt = <3300000>; + }; + }; +}; + &lcdc_vdd_domain { regulator-name = "vcc30_lcd"; }; diff --git a/arch/arm/configs/rockchip_defconfig b/arch/arm/configs/rockchip_defconfig index fd5aaa74f5a0..2c67100fc12e 100755 --- a/arch/arm/configs/rockchip_defconfig +++ b/arch/arm/configs/rockchip_defconfig @@ -295,6 +295,7 @@ CONFIG_TOUCHSCREEN_GT8XX=y CONFIG_CT36X_TS=y CONFIG_INPUT_MISC=y CONFIG_INPUT_KEYCHORD=y +CONFIG_INPUT_RICOH619_PWRKEY=y CONFIG_INPUT_UINPUT=y CONFIG_INPUT_GPIO=y # CONFIG_GS_LIS3DH is not set @@ -319,16 +320,20 @@ CONFIG_SPI_ROCKCHIP_DMA=y CONFIG_SPI_ROCKCHIP_TEST=y CONFIG_DEBUG_GPIO=y CONFIG_GPIO_SYSFS=y +CONFIG_BATTERY_RICOH619=y CONFIG_BATTERY_BQ24296=y CONFIG_BATTERY_BQ27320=y CONFIG_CW2015_BATTERY=y CONFIG_SENSORS_ROCKCHIP_TSADC=y CONFIG_THERMAL=y CONFIG_MFD_RK808=y +CONFIG_MFD_RICOH619=y CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_ACT8846=y CONFIG_ROCKCHIP_PWM_REGULATOR=y +CONFIG_REGULATOR_SYB827=y +CONFIG_REGULATOR_RICOH619=y CONFIG_MEDIA_SUPPORT=y CONFIG_MEDIA_CAMERA_SUPPORT=y CONFIG_MEDIA_RC_SUPPORT=y @@ -482,6 +487,7 @@ CONFIG_SWITCH=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_PCF8563=y CONFIG_RK808_RTC=y +CONFIG_RTC_DRV_RC5T619=y CONFIG_STAGING=y CONFIG_ANDROID=y CONFIG_ANDROID_BINDER_IPC=y diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig old mode 100644 new mode 100755 index 4abf046e30b1..c74bfdd50e70 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -405,6 +405,15 @@ config INPUT_TWL4030_PWRBUTTON To compile this driver as a module, choose M here. The module will be called twl4030_pwrbutton. +config INPUT_RICOH619_PWRKEY + tristate "RICOH RC5T619 PMU PWRKEY driver" + depends on MFD_RICOH619 + default n + help + If you say yes here you get support for the RICOH RC5T619 PWRKEY module. + + This driver can also be built as a module. If so, the module + will be called rc5t619-pwrkey. 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 old mode 100644 new mode 100755 index 6b0e8a677725..3a961326fddc --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -62,3 +62,4 @@ obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o obj-$(CONFIG_INPUT_YEALINK) += yealink.o +obj-$(CONFIG_INPUT_RICOH619_PWRKEY) += ricoh619-pwrkey.o diff --git a/drivers/input/misc/ricoh619-pwrkey.c b/drivers/input/misc/ricoh619-pwrkey.c old mode 100644 new mode 100755 index 95018d288aaf..db624e765ff0 --- a/drivers/input/misc/ricoh619-pwrkey.c +++ b/drivers/input/misc/ricoh619-pwrkey.c @@ -1,330 +1,376 @@ -/* -* driver/input/misc/ricoh619-pwrkey.c -* -* Power Key driver for RICOH RC5T619 power management chip. -* -* Copyright (C) 2012-2013 RICOH COMPANY,LTD -* -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* 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, see . -* -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define RICOH619_ONKEY_TRIGGER_LEVEL 0 -#define RICOH619_ONKEY_OFF_IRQ 0 - -struct ricoh619_pwrkey { - struct device *dev; - struct input_dev *pwr; - #if RICOH619_ONKEY_TRIGGER_LEVEL - struct timer_list timer; - #endif - struct workqueue_struct *workqueue; - struct work_struct work; - unsigned long delay; - int key_irq; - bool pressed_first; - struct ricoh619_pwrkey_platform_data *pdata; - spinlock_t lock; -}; - -struct ricoh619_pwrkey *g_pwrkey; - -#if RICOH619_ONKEY_TRIGGER_LEVEL -void ricoh619_pwrkey_timer(unsigned long t) -{ - queue_work(g_pwrkey->workqueue, &g_pwrkey->work); -} -#endif - -static void ricoh619_irq_work(struct work_struct *work) -{ - /* unsigned long flags; */ - uint8_t val; - -// printk("PMU: %s: \n",__func__); - //spin_lock_irqsave(&g_pwrkey->lock, flags); - - if(pwrkey_wakeup){ -// printk("PMU: %s: pwrkey_wakeup\n",__func__); - pwrkey_wakeup = 0; - input_event(g_pwrkey->pwr, EV_KEY, KEY_POWER, 1); - input_event(g_pwrkey->pwr, EV_SYN, 0, 0); - input_event(g_pwrkey->pwr, EV_KEY, KEY_POWER, 0); - input_event(g_pwrkey->pwr, EV_SYN, 0, 0); - - return; - } - ricoh619_read(g_pwrkey->dev->parent, RICOH619_INT_MON_SYS, &val); - dev_dbg(g_pwrkey->dev, "pwrkey is pressed?(0x%x): 0x%x\n", - RICOH619_INT_MON_SYS, val); -// printk(KERN_INFO "PMU: %s: val=0x%x\n", __func__, val); - val &= 0x1; - if(val){ - #if (RICOH619_ONKEY_TRIGGER_LEVEL) - g_pwrkey->timer.expires = jiffies + g_pwrkey->delay; - dd_timer(&g_pwrkey->timer); - #endif - if (!g_pwrkey->pressed_first){ - g_pwrkey->pressed_first = true; -// printk("PMU1: %s: Power Key!!!\n",__func__); - //input_report_key(g_pwrkey->pwr, KEY_POWER, 1); - //input_sync(g_pwrkey->pwr); - input_event(g_pwrkey->pwr, EV_KEY, KEY_POWER, 1); - input_event(g_pwrkey->pwr, EV_SYN, 0, 0); - } - } else { - if (g_pwrkey->pressed_first) { -// printk(KERN_INFO "PMU2: %s: Power Key!!!\n", __func__); - /* input_report_key(g_pwrkey->pwr, KEY_POWER, 0); */ - /* input_sync(g_pwrkey->pwr); */ - input_event(g_pwrkey->pwr, EV_KEY, KEY_POWER, 0); - input_event(g_pwrkey->pwr, EV_SYN, 0, 0); - } - g_pwrkey->pressed_first = false; - } - - /* spin_unlock_irqrestore(&g_pwrkey->lock, flags); */ -} - -static irqreturn_t pwrkey_irq(int irq, void *_pwrkey) -{ -// printk(KERN_INFO "PMU: %s:\n", __func__); - - #if (RICOH619_ONKEY_TRIGGER_LEVEL) - g_pwrkey->timer.expires = jiffies + g_pwrkey->delay; - add_timer(&g_pwrkey->timer); - #else - queue_work(g_pwrkey->workqueue, &g_pwrkey->work); - #endif - return IRQ_HANDLED; -} - -#if RICOH619_ONKEY_OFF_IRQ -static irqreturn_t pwrkey_irq_off(int irq, void *_pwrkey) -{ - dev_warn(g_pwrkey->dev, "ONKEY is pressed long time!\n"); - return IRQ_HANDLED; -} -#endif - -static int __devinit ricoh619_pwrkey_probe(struct platform_device *pdev) -{ - struct input_dev *pwr; - int key_irq; - int err; - struct ricoh619_pwrkey *pwrkey; - struct ricoh619_pwrkey_platform_data *pdata = pdev->dev.platform_data; - uint8_t val; - -// printk("PMU: %s: \n",__func__); - - if (!pdata) { - dev_err(&pdev->dev, "power key platform data not supplied\n"); - return -EINVAL; - } - key_irq = (pdata->irq + RICOH619_IRQ_POWER_ON); - printk(KERN_INFO "PMU1: %s: key_irq=%d\n", __func__, key_irq); - pwrkey = kzalloc(sizeof(*pwrkey), GFP_KERNEL); - if (!pwrkey) - return -ENOMEM; - - pwrkey->dev = &pdev->dev; - pwrkey->pdata = pdata; - pwrkey->pressed_first = false; - pwrkey->delay = HZ / 1000 * pdata->delay_ms; - g_pwrkey = pwrkey; - pwr = input_allocate_device(); - if (!pwr) { - dev_dbg(&pdev->dev, "Can't allocate power button\n"); - err = -ENOMEM; - goto free_pwrkey; - } - input_set_capability(pwr, EV_KEY, KEY_POWER); - pwr->name = "ricoh619_pwrkey"; - pwr->phys = "ricoh619_pwrkey/input0"; - pwr->dev.parent = &pdev->dev; - - #if RICOH619_ONKEY_TRIGGER_LEVEL - init_timer(&pwrkey->timer); - pwrkey->timer.function = ricoh619_pwrkey_timer; - #endif - - spin_lock_init(&pwrkey->lock); - err = input_register_device(pwr); - if (err) { - dev_dbg(&pdev->dev, "Can't register power key: %d\n", err); - goto free_input_dev; - } - pwrkey->key_irq = key_irq; - pwrkey->pwr = pwr; - platform_set_drvdata(pdev, pwrkey); - - /* Check if power-key is pressed at boot up */ - err = ricoh619_read(pwrkey->dev->parent, RICOH619_INT_MON_SYS, &val); - if (err < 0) { - dev_err(&pdev->dev, "Key-press status at boot failed rc=%d\n", - err); - goto unreg_input_dev; - } - val &= 0x1; - if (val) { - input_report_key(pwrkey->pwr, KEY_POWER, 1); -// printk(KERN_INFO "******KEY_POWER:1\n"); - input_sync(pwrkey->pwr); - pwrkey->pressed_first = true; - } - - #if !(RICOH619_ONKEY_TRIGGER_LEVEL) - /* trigger both edge */ - ricoh619_set_bits(pwrkey->dev->parent, RICOH619_PWR_IRSEL, 0x1); - #endif - - err = request_threaded_irq(key_irq, NULL, pwrkey_irq, - IRQF_ONESHOT, "ricoh619_pwrkey", pwrkey); - if (err < 0) { - dev_err(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", - key_irq, err); - goto unreg_input_dev; - } - - #if RICOH619_ONKEY_OFF_IRQ - err = request_threaded_irq(key_irq + RICOH619_IRQ_ONKEY_OFF, NULL, - pwrkey_irq_off, IRQF_ONESHOT, - "ricoh619_pwrkey_off", pwrkey); - if (err < 0) { - dev_err(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", - key_irq + RICOH619_IRQ_ONKEY_OFF, err); - free_irq(key_irq, pwrkey); - goto unreg_input_dev; - } - #endif - - pwrkey->workqueue = create_singlethread_workqueue("ricoh619_pwrkey"); - INIT_WORK(&pwrkey->work, ricoh619_irq_work); - - /* Enable power key IRQ */ - /* trigger both edge */ - ricoh619_set_bits(pwrkey->dev->parent, RICOH619_PWR_IRSEL, 0x1); - /* Enable system interrupt */ - ricoh619_set_bits(pwrkey->dev->parent, RICOH619_INTC_INTEN, 0x1); - /* Enable power-on interrupt */ - ricoh619_set_bits(pwrkey->dev->parent, RICOH619_INT_EN_SYS, 0x1); -// printk(KERN_INFO "PMU: %s is OK!\n", __func__); - return 0; - -unreg_input_dev: - input_unregister_device(pwr); - pwr = NULL; - -free_input_dev: - input_free_device(pwr); - free_pwrkey: - kfree(pwrkey); - - return err; -} - -static int __devexit ricoh619_pwrkey_remove(struct platform_device *pdev) -{ - struct ricoh619_pwrkey *pwrkey = platform_get_drvdata(pdev); - - flush_workqueue(pwrkey->workqueue); - destroy_workqueue(pwrkey->workqueue); - free_irq(pwrkey->key_irq, pwrkey); - input_unregister_device(pwrkey->pwr); - kfree(pwrkey); - - return 0; -} - -#ifdef CONFIG_PM -static int ricoh619_pwrkey_suspend(struct device *dev) -{ - struct ricoh619_pwrkey *info = dev_get_drvdata(dev); - -// printk(KERN_INFO "PMU: %s\n", __func__); - - if (info->key_irq) - disable_irq(info->key_irq); - cancel_work_sync(&info->work); - flush_workqueue(info->workqueue); - - return 0; -} - -static int ricoh619_pwrkey_resume(struct device *dev) -{ - struct ricoh619_pwrkey *info = dev_get_drvdata(dev); - -// printk(KERN_INFO "PMU: %s\n", __func__); - queue_work(info->workqueue, &info->work); - if (info->key_irq) - enable_irq(info->key_irq); - - return 0; -} - -static const struct dev_pm_ops ricoh619_pwrkey_pm_ops = { - .suspend = ricoh619_pwrkey_suspend, - .resume = ricoh619_pwrkey_resume, -}; -#endif - -static struct platform_driver ricoh619_pwrkey_driver = { - .probe = ricoh619_pwrkey_probe, - .remove = __devexit_p(ricoh619_pwrkey_remove), - .driver = { - .name = "ricoh619-pwrkey", - .owner = THIS_MODULE, -#ifdef CONFIG_PM - .pm = &ricoh619_pwrkey_pm_ops, -#endif - }, -}; - -static int __init ricoh619_pwrkey_init(void) -{ - return platform_driver_register(&ricoh619_pwrkey_driver); -} -subsys_initcall_sync(ricoh619_pwrkey_init); - -static void __exit ricoh619_pwrkey_exit(void) -{ - platform_driver_unregister(&ricoh619_pwrkey_driver); -} -module_exit(ricoh619_pwrkey_exit); - - -MODULE_ALIAS("platform:ricoh619-pwrkey"); -MODULE_AUTHOR("zhangqing "); -MODULE_DESCRIPTION("ricoh619 Power Key"); -MODULE_LICENSE("GPL v2"); \ No newline at end of file +/* +* driver/input/misc/ricoh619-pwrkey.c +* +* Power Key driver for RICOH RC5T619 power management chip. +* +* Copyright (C) 2012-2013 RICOH COMPANY,LTD +* +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* 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, see . +* +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define RICOH619_ONKEY_TRIGGER_LEVEL 0 +#define RICOH619_ONKEY_OFF_IRQ 0 + +struct ricoh619_pwrkey { + struct device *dev; + struct input_dev *pwr; + #if RICOH619_ONKEY_TRIGGER_LEVEL + struct timer_list timer; + #endif + struct workqueue_struct *workqueue; + struct work_struct work; + unsigned long delay; + int key_irq; + bool pressed_first; + struct ricoh619_pwrkey_platform_data *pdata; + spinlock_t lock; +}; + +struct ricoh619_pwrkey *g_pwrkey; + +#if RICOH619_ONKEY_TRIGGER_LEVEL +void ricoh619_pwrkey_timer(unsigned long t) +{ + queue_work(g_pwrkey->workqueue, &g_pwrkey->work); +} +#endif + +static void ricoh619_irq_work(struct work_struct *work) +{ + /* unsigned long flags; */ + uint8_t val; + +// printk("PMU: %s: \n",__func__); + //spin_lock_irqsave(&g_pwrkey->lock, flags); + + if(pwrkey_wakeup){ +// printk("PMU: %s: pwrkey_wakeup\n",__func__); + pwrkey_wakeup = 0; + input_event(g_pwrkey->pwr, EV_KEY, KEY_POWER, 1); + input_event(g_pwrkey->pwr, EV_SYN, 0, 0); + input_event(g_pwrkey->pwr, EV_KEY, KEY_POWER, 0); + input_event(g_pwrkey->pwr, EV_SYN, 0, 0); + + return; + } + ricoh619_read(g_pwrkey->dev->parent, RICOH619_INT_MON_SYS, &val); + dev_dbg(g_pwrkey->dev, "pwrkey is pressed?(0x%x): 0x%x\n", + RICOH619_INT_MON_SYS, val); +// printk(KERN_INFO "PMU: %s: val=0x%x\n", __func__, val); + val &= 0x1; + if(val){ + #if (RICOH619_ONKEY_TRIGGER_LEVEL) + g_pwrkey->timer.expires = jiffies + g_pwrkey->delay; + dd_timer(&g_pwrkey->timer); + #endif + if (!g_pwrkey->pressed_first){ + g_pwrkey->pressed_first = true; +// printk("PMU1: %s: Power Key!!!\n",__func__); + //input_report_key(g_pwrkey->pwr, KEY_POWER, 1); + //input_sync(g_pwrkey->pwr); + input_event(g_pwrkey->pwr, EV_KEY, KEY_POWER, 1); + input_event(g_pwrkey->pwr, EV_SYN, 0, 0); + } + } else { + if (g_pwrkey->pressed_first) { +// printk(KERN_INFO "PMU2: %s: Power Key!!!\n", __func__); + /* input_report_key(g_pwrkey->pwr, KEY_POWER, 0); */ + /* input_sync(g_pwrkey->pwr); */ + input_event(g_pwrkey->pwr, EV_KEY, KEY_POWER, 0); + input_event(g_pwrkey->pwr, EV_SYN, 0, 0); + } + g_pwrkey->pressed_first = false; + } + + /* spin_unlock_irqrestore(&g_pwrkey->lock, flags); */ +} +extern void rk_send_wakeup_key(void); +static irqreturn_t pwrkey_irq(int irq, void *_pwrkey) +{ +// printk(KERN_INFO "PMU: %s:\n", __func__); +// rk_send_wakeup_key(); + #if (RICOH619_ONKEY_TRIGGER_LEVEL) + g_pwrkey->timer.expires = jiffies + g_pwrkey->delay; + add_timer(&g_pwrkey->timer); + #else + queue_work(g_pwrkey->workqueue, &g_pwrkey->work); + #endif + return IRQ_HANDLED; +} + +#if RICOH619_ONKEY_OFF_IRQ +static irqreturn_t pwrkey_irq_off(int irq, void *_pwrkey) +{ + dev_warn(g_pwrkey->dev, "ONKEY is pressed long time!\n"); + return IRQ_HANDLED; +} +#endif + +#ifdef CONFIG_OF +static struct ricoh619_pwrkey_platform_data * +ricoh619_pwrkey_dt_init(struct platform_device *pdev) +{ + struct device_node *nproot = pdev->dev.parent->of_node; + struct device_node *np; + struct ricoh619_pwrkey_platform_data *pdata; + + if (!nproot) + return pdev->dev.platform_data; + + np = of_find_node_by_name(nproot, "pwrkey"); + if (!np) { + dev_err(&pdev->dev, "failed to find pwrkey node\n"); + return NULL; + } + + pdata = devm_kzalloc(&pdev->dev, + sizeof(struct ricoh619_pwrkey_platform_data), + GFP_KERNEL); + + of_property_read_u32(np, "ricoh,pwrkey-delay-ms", &pdata->delay_ms); + of_node_put(np); + + return pdata; +} +#else +static struct ricoh619_pwrkey_platform_data * +ricoh619_pwrkey_dt_init(struct platform_device *pdev) +{ + return pdev->dev.platform_data; +} +#endif + +static int ricoh619_pwrkey_probe(struct platform_device *pdev) +{ + struct input_dev *pwr; + int key_irq; + int err; + struct ricoh619_pwrkey *pwrkey; + struct ricoh619_pwrkey_platform_data *pdata; + struct ricoh619 *ricoh619 = dev_get_drvdata(pdev->dev.parent); + uint8_t val; + +// printk("PMU: %s: \n",__func__); + + pdata = ricoh619_pwrkey_dt_init(pdev); + if (!pdata) { + dev_err(&pdev->dev, "platform data isn't assigned to " + "power key\n"); + return -EINVAL; + } + key_irq = irq_create_mapping(ricoh619->irq_domain, RICOH619_IRQ_POWER_ON); + printk(KERN_INFO "PMU1: %s: key_irq=%d\n", __func__, key_irq); + pwrkey = kzalloc(sizeof(*pwrkey), GFP_KERNEL); + if (!pwrkey) + return -ENOMEM; + + pwrkey->dev = &pdev->dev; + pwrkey->pdata = pdata; + pwrkey->pressed_first = false; + pwrkey->delay = HZ / 1000 * pdata->delay_ms; + g_pwrkey = pwrkey; + pwr = input_allocate_device(); + if (!pwr) { + dev_dbg(&pdev->dev, "Can't allocate power button\n"); + err = -ENOMEM; + goto free_pwrkey; + } + input_set_capability(pwr, EV_KEY, KEY_POWER); + pwr->name = "ricoh619_pwrkey"; + pwr->phys = "ricoh619_pwrkey/input0"; + pwr->dev.parent = &pdev->dev; + + #if RICOH619_ONKEY_TRIGGER_LEVEL + init_timer(&pwrkey->timer); + pwrkey->timer.function = ricoh619_pwrkey_timer; + #endif + + spin_lock_init(&pwrkey->lock); + err = input_register_device(pwr); + if (err) { + dev_dbg(&pdev->dev, "Can't register power key: %d\n", err); + goto free_input_dev; + } + pwrkey->key_irq = key_irq; + pwrkey->pwr = pwr; + platform_set_drvdata(pdev, pwrkey); + + /* Check if power-key is pressed at boot up */ + err = ricoh619_read(pwrkey->dev->parent, RICOH619_INT_MON_SYS, &val); + if (err < 0) { + dev_err(&pdev->dev, "Key-press status at boot failed rc=%d\n", + err); + goto unreg_input_dev; + } + val &= 0x1; + if (val) { + input_report_key(pwrkey->pwr, KEY_POWER, 1); +// printk(KERN_INFO "******KEY_POWER:1\n"); + input_sync(pwrkey->pwr); + pwrkey->pressed_first = true; + } + + #if !(RICOH619_ONKEY_TRIGGER_LEVEL) + /* trigger both edge */ + ricoh619_set_bits(pwrkey->dev->parent, RICOH619_PWR_IRSEL, 0x1); + #endif + err = request_threaded_irq(key_irq, NULL, pwrkey_irq,IRQF_ONESHOT, "ricoh619_pwrkey", pwrkey); + if (err < 0) { + dev_err(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", + key_irq, err); + goto unreg_input_dev; + } + /* + #if RICOH619_ONKEY_OFF_IRQ + err = request_threaded_irq( key_irq +RICOH619_ONKEY_OFF_IRQ, NULL,pwrkey_irq_off, IRQF_ONESHOT, + "ricoh619_pwrkey_off", pwrkey); + if (err < 0) { + dev_err(&pdev->dev, "Can't get %d IRQ for ricoh619_pwrkey_off: %d\n", + key_irq + RICOH619_ONKEY_OFF_IRQ, err); + free_irq(key_irq, pwrkey); + goto unreg_input_dev; + } + #endif +*/ + pwrkey->workqueue = create_singlethread_workqueue("ricoh619_pwrkey"); + INIT_WORK(&pwrkey->work, ricoh619_irq_work); + + /* Enable power key IRQ */ + /* trigger both edge */ + ricoh619_set_bits(pwrkey->dev->parent, RICOH619_PWR_IRSEL, 0x1); + /* Enable system interrupt */ + ricoh619_set_bits(pwrkey->dev->parent, RICOH619_INTC_INTEN, 0x1); + /* Enable power-on interrupt */ + ricoh619_set_bits(pwrkey->dev->parent, RICOH619_INT_EN_SYS, 0x1); +// printk(KERN_INFO "PMU: %s is OK!\n", __func__); + return 0; + +unreg_input_dev: + input_unregister_device(pwr); + pwr = NULL; + +free_input_dev: + input_free_device(pwr); + free_pwrkey: + kfree(pwrkey); + + return err; +} + +static int ricoh619_pwrkey_remove(struct platform_device *pdev) +{ + struct ricoh619_pwrkey *pwrkey = platform_get_drvdata(pdev); + + flush_workqueue(pwrkey->workqueue); + destroy_workqueue(pwrkey->workqueue); + free_irq(pwrkey->key_irq, pwrkey); + input_unregister_device(pwrkey->pwr); + kfree(pwrkey); + + return 0; +} + +#ifdef CONFIG_PM +static int ricoh619_pwrkey_suspend(struct device *dev) +{ + struct ricoh619_pwrkey *info = dev_get_drvdata(dev); + +// printk(KERN_INFO "PMU: %s\n", __func__); + +// if (info->key_irq) +// disable_irq(info->key_irq); + cancel_work_sync(&info->work); + flush_workqueue(info->workqueue); + + return 0; +} + +static int ricoh619_pwrkey_resume(struct device *dev) +{ + struct ricoh619_pwrkey *info = dev_get_drvdata(dev); + +// printk(KERN_INFO "PMU: %s\n", __func__); + queue_work(info->workqueue, &info->work); +// if (info->key_irq) +// enable_irq(info->key_irq); + + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id ricoh619_pwrkey_dt_match[] = { + { .compatible = "ricoh,ricoh619-pwrkey", }, + {}, +}; +MODULE_DEVICE_TABLE(of, ricoh619_pwrkey_dt_match); +#endif + +static const struct dev_pm_ops ricoh619_pwrkey_pm_ops = { + .suspend = ricoh619_pwrkey_suspend, + .resume = ricoh619_pwrkey_resume, +}; +#endif + +static struct platform_driver ricoh619_pwrkey_driver = { + .probe = ricoh619_pwrkey_probe, + .remove = ricoh619_pwrkey_remove, + .driver = { + .name = "ricoh619-pwrkey", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(ricoh619_pwrkey_dt_match), +#ifdef CONFIG_PM + .pm = &ricoh619_pwrkey_pm_ops, +#endif + }, +}; + +static int __init ricoh619_pwrkey_init(void) +{ + return platform_driver_register(&ricoh619_pwrkey_driver); +} +subsys_initcall_sync(ricoh619_pwrkey_init); + +static void __exit ricoh619_pwrkey_exit(void) +{ + platform_driver_unregister(&ricoh619_pwrkey_driver); +} +module_exit(ricoh619_pwrkey_exit); + + +MODULE_ALIAS("platform:ricoh619-pwrkey"); +MODULE_AUTHOR("zhangqing "); +MODULE_DESCRIPTION("ricoh619 Power Key"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 50f1c09957a5..2301511ec409 100755 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -922,6 +922,18 @@ config TWL6040_CORE This driver provides common support for accessing the device, additional drivers must be enabled in order to use the functionality of the device (audio, vibra). + +config MFD_RICOH619 + bool "Ricoh RC5T619 Power Management system device" + depends on I2C && GPIOLIB && GENERIC_HARDIRQS + select MFD_CORE + default n + help + If you say yes here you get support for the RICOH619 Power + Management system device. + This driver provides common support for accessing the device, + additional drivers must be enabled in order to use the + functionality of the device. config MENELAUS bool "TI TWL92330/Menelaus PM chip" diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 4eb11e7690ae..94150e881d86 100755 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -145,6 +145,7 @@ obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o obj-$(CONFIG_MFD_TPS65090) += tps65090.o obj-$(CONFIG_MFD_RK808) += rk808.o rk808-irq.o +obj-$(CONFIG_MFD_RICOH619) += ricoh619.o ricoh619-irq.o obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o obj-$(CONFIG_MFD_PALMAS) += palmas.o diff --git a/drivers/mfd/ricoh619-irq.c b/drivers/mfd/ricoh619-irq.c old mode 100644 new mode 100755 index 5bf56f136ffd..e35604e58043 --- a/drivers/mfd/ricoh619-irq.c +++ b/drivers/mfd/ricoh619-irq.c @@ -29,6 +29,7 @@ #include #include #include +#include enum int_type { @@ -209,7 +210,11 @@ static const struct ricoh619_irq_data ricoh619_irqs[RICOH619_NR_IRQS] = { [RICOH619_IRQ_FWARN_ADP] = RICOH619_IRQ(CHG_INT, 6, 32, 3, 12), }; - +static const inline struct ricoh619_irq_data * irq_to_ricoh619_irq(struct ricoh619 *ricoh619, int irq) +{ + struct irq_data *data = irq_get_irq_data(irq); + return &ricoh619_irqs[data->hwirq]; +} static void ricoh619_irq_lock(struct irq_data *irq_data) { struct ricoh619 *ricoh619 = irq_data_get_irq_chip_data(irq_data); @@ -220,8 +225,7 @@ static void ricoh619_irq_lock(struct irq_data *irq_data) static void ricoh619_irq_unmask(struct irq_data *irq_data) { struct ricoh619 *ricoh619 = irq_data_get_irq_chip_data(irq_data); - unsigned int __irq = irq_data->irq - ricoh619->irq_base; - const struct ricoh619_irq_data *data = &ricoh619_irqs[__irq]; + const struct ricoh619_irq_data *data= irq_to_ricoh619_irq(ricoh619,irq_data->irq); ricoh619->group_irq_en[data->master_bit] |= (1 << data->grp_index); if (ricoh619->group_irq_en[data->master_bit]) @@ -238,8 +242,7 @@ static void ricoh619_irq_unmask(struct irq_data *irq_data) static void ricoh619_irq_mask(struct irq_data *irq_data) { struct ricoh619 *ricoh619 = irq_data_get_irq_chip_data(irq_data); - unsigned int __irq = irq_data->irq - ricoh619->irq_base; - const struct ricoh619_irq_data *data = &ricoh619_irqs[__irq]; + const struct ricoh619_irq_data *data= irq_to_ricoh619_irq(ricoh619,irq_data->irq); ricoh619->group_irq_en[data->master_bit] &= ~(1 << data->grp_index); if (!ricoh619->group_irq_en[data->master_bit]) @@ -260,27 +263,20 @@ static void ricoh619_irq_sync_unlock(struct irq_data *irq_data) for (i = 0; i < ARRAY_SIZE(ricoh619->gpedge_reg); i++) { if (ricoh619->gpedge_reg[i] != ricoh619->gpedge_cache[i]) { - if (!WARN_ON(ricoh619_write(ricoh619->dev, - gpedge_add[i], - ricoh619->gpedge_reg[i]))) - ricoh619->gpedge_cache[i] = - ricoh619->gpedge_reg[i]; + if (!WARN_ON(ricoh619_write(ricoh619->dev, gpedge_add[i],ricoh619->gpedge_reg[i]))) + ricoh619->gpedge_cache[i] =ricoh619->gpedge_reg[i]; } } for (i = 0; i < ARRAY_SIZE(ricoh619->irq_en_reg); i++) { if (ricoh619->irq_en_reg[i] != ricoh619->irq_en_cache[i]) { - if (!WARN_ON(ricoh619_write(ricoh619->dev, - irq_en_add[i], - ricoh619->irq_en_reg[i]))) - ricoh619->irq_en_cache[i] = - ricoh619->irq_en_reg[i]; + if (!WARN_ON(ricoh619_write(ricoh619->dev, irq_en_add[i],ricoh619->irq_en_reg[i]))) + ricoh619->irq_en_cache[i] =ricoh619->irq_en_reg[i]; } } if (ricoh619->intc_inten_reg != ricoh619->intc_inten_cache) { - if (!WARN_ON(ricoh619_write(ricoh619->dev, - RICOH619_INTC_INTEN, ricoh619->intc_inten_reg))) + if (!WARN_ON(ricoh619_write(ricoh619->dev,RICOH619_INTC_INTEN, ricoh619->intc_inten_reg))) ricoh619->intc_inten_cache = ricoh619->intc_inten_reg; } @@ -290,8 +286,7 @@ static void ricoh619_irq_sync_unlock(struct irq_data *irq_data) static int ricoh619_irq_set_type(struct irq_data *irq_data, unsigned int type) { struct ricoh619 *ricoh619 = irq_data_get_irq_chip_data(irq_data); - unsigned int __irq = irq_data->irq - ricoh619->irq_base; - const struct ricoh619_irq_data *data = &ricoh619_irqs[__irq]; + const struct ricoh619_irq_data *data= irq_to_ricoh619_irq(ricoh619,irq_data->irq); int val = 0; int gpedge_index; int gpedge_bit_pos; @@ -331,7 +326,8 @@ static irqreturn_t ricoh619_irq(int irq, void *data) int i; int ret; unsigned int rtc_int_sts = 0; - + int cur_irq; + /* Clear the status */ for (i = 0; i < MAX_INTERRUPT_MASKS; i++) int_sts[i] = 0; @@ -349,8 +345,8 @@ static irqreturn_t ricoh619_irq(int irq, void *data) /* Even if INTC_INTMON register = 1, INT signal might not output because INTC_INTMON register indicates only interrupt facter level. So remove the following procedure */ -// if (!(master_int & main_int_type[i])) -// continue; + if (!(master_int & main_int_type[i])) + continue; ret = ricoh619_read(ricoh619->dev, irq_mon_add[i], &int_sts[i]); @@ -361,7 +357,9 @@ static irqreturn_t ricoh619_irq(int irq, void *data) int_sts[i] = 0; continue; } - + if (!int_sts[i]) + continue; + if (main_int_type[i] & RTC_INT) { // Changes status bit position from RTCCNT2 to RTCCNT1 rtc_int_sts = 0; @@ -370,21 +368,28 @@ static irqreturn_t ricoh619_irq(int irq, void *data) if (int_sts[i] & 0x4) rtc_int_sts |= BIT(0); } - if (i != 2) { + + if(irq_clr_add[i] == RICOH619_INT_IR_RTC) + { + int_sts[i] &= ~0x85; ret = ricoh619_write(ricoh619->dev, - irq_clr_add[i], ~int_sts[i]); - if (ret < 0) { + irq_clr_add[i], int_sts[i]); + if (ret < 0) dev_err(ricoh619->dev, "Error in writing reg 0x%02x " "error: %d\n", irq_clr_add[i], ret); - } } - - if (main_int_type[i] & RTC_INT) - int_sts[i] = rtc_int_sts; + else + { + ret = ricoh619_write(ricoh619->dev, + irq_clr_add[i], ~int_sts[i]); + if (ret < 0) + dev_err(ricoh619->dev, "Error in reading reg 0x%02x " + "error: %d\n", irq_clr_add[i], ret); + } /* Mask Charger Interrupt */ if (main_int_type[i] & CHG_INT) { - if (int_sts[i]) + if (int_sts[i]) { ret = ricoh619_write(ricoh619->dev, irq_en_add[i], 0xff); if (ret < 0) { @@ -392,10 +397,11 @@ static irqreturn_t ricoh619_irq(int irq, void *data) "Error in write reg 0x%02x error: %d\n", irq_en_add[i], ret); } + } } /* Mask ADC Interrupt */ if (main_int_type[i] & ADC_INT) { - if (int_sts[i]) + if (int_sts[i]) { ret = ricoh619_write(ricoh619->dev, irq_en_add[i], 0); if (ret < 0) { @@ -403,8 +409,11 @@ static irqreturn_t ricoh619_irq(int irq, void *data) "Error in write reg 0x%02x error: %d\n", irq_en_add[i], ret); } + } } - + + if (main_int_type[i] & RTC_INT) + int_sts[i] = rtc_int_sts; } @@ -412,12 +421,13 @@ static irqreturn_t ricoh619_irq(int irq, void *data) int_sts[6] |= int_sts[7]; /* Call interrupt handler if enabled */ - for (i = 0; i < RICOH619_NR_IRQS; ++i) { + + for (i = 0; i mask_reg_index] & (1 << data->int_en_bit)) && - (ricoh619->group_irq_en[data->master_bit] & - (1 << data->grp_index))) - handle_nested_irq(ricoh619->irq_base + i); + if ((int_sts[data->mask_reg_index] & (1 << data->int_en_bit)) &&(ricoh619->group_irq_en[data->master_bit] & (1 << data->grp_index))) + cur_irq = irq_find_mapping(ricoh619->irq_domain, i); + if (cur_irq) + handle_nested_irq(cur_irq); } // printk(KERN_INFO "PMU: %s: out\n", __func__); @@ -434,17 +444,39 @@ static struct irq_chip ricoh619_irq_chip = { .irq_set_wake = ricoh619_irq_set_wake, }; +static int ricoh619_irq_domain_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hw) +{ + struct ricoh619 *ricoh619 = d->host_data; + + irq_set_chip_data(irq, ricoh619); + irq_set_chip_and_handler(irq, &ricoh619_irq_chip, handle_edge_irq); + irq_set_nested_thread(irq, 1); +#ifdef CONFIG_ARM + set_irq_flags(irq, IRQF_VALID); +#else + irq_set_noprobe(irq); +#endif + return 0; +} + +static struct irq_domain_ops ricoh619_irq_domain_ops = { + .map = ricoh619_irq_domain_map, +}; + int ricoh619_irq_init(struct ricoh619 *ricoh619, int irq, - int irq_base) + struct ricoh619_platform_data *pdata) { - int i, ret; + int i, ret,val; u8 reg_data = 0; - - if (!irq_base) { - dev_warn(ricoh619->dev, "No interrupt support on IRQ base\n"); - return -EINVAL; + struct irq_domain *domain; + + // printk("%s,line=%d\n", __func__,__LINE__); + if (!irq) { + dev_warn(ricoh619->dev, "No interrupt support, no core IRQ\n"); + return 0; } - + mutex_init(&ricoh619->irq_lock); /* Initialize all locals to 0 */ @@ -527,40 +559,41 @@ int ricoh619_irq_init(struct ricoh619 *ricoh619, int irq, } } - ricoh619->irq_base = irq_base; - ricoh619->chip_irq = irq; + if (pdata->irq_gpio && !ricoh619->chip_irq) { + ricoh619->chip_irq = gpio_to_irq(pdata->irq_gpio); - for (i = 0; i < RICOH619_NR_IRQS; i++) { - int __irq = i + ricoh619->irq_base; - irq_set_chip_data(__irq, ricoh619); - irq_set_chip_and_handler(__irq, &ricoh619_irq_chip, - handle_simple_irq); - irq_set_nested_thread(__irq, 1); -#ifdef CONFIG_ARM - set_irq_flags(__irq, IRQF_VALID); -#endif + if (pdata->irq_gpio) { + ret = gpio_request(pdata->irq_gpio, "ricoh619_pmic_irq"); + if (ret < 0) { + dev_err(ricoh619->dev, + "Failed to request gpio %d with ret:" + "%d\n", pdata->irq_gpio, ret); + return IRQ_NONE; + } + gpio_direction_input(pdata->irq_gpio); + val = gpio_get_value(pdata->irq_gpio); + gpio_free(pdata->irq_gpio); + pr_info("%s: ricoh619_pmic_irq=%x\n", __func__, val); + } } - - ret = request_threaded_irq(irq, NULL, ricoh619_irq, - IRQ_TYPE_LEVEL_LOW|IRQF_DISABLED|IRQF_ONESHOT, - "ricoh619", ricoh619); - if (ret < 0) - dev_err(ricoh619->dev, "Error in registering interrupt " - "error: %d\n", ret); -/* - if (!ret) { - device_init_wakeup(ricoh619->dev, 1); - enable_irq_wake(irq); + + domain = irq_domain_add_linear(NULL, RICOH619_NR_IRQS, + &ricoh619_irq_domain_ops, ricoh619); + if (!domain) { + dev_err(ricoh619->dev, "could not create irq domain\n"); + return -ENODEV; } -*/ + ricoh619->irq_domain = domain; + ret = devm_request_threaded_irq(ricoh619->dev,ricoh619->chip_irq, NULL, ricoh619_irq, IRQF_TRIGGER_FALLING |IRQF_ONESHOT, "ricoh619", ricoh619); +// ret = devm_request_threaded_irq(ricoh619->dev,ricoh619->chip_irq, NULL, ricoh619_irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT , "ricoh619", ricoh619); + irq_set_irq_type(ricoh619->chip_irq, IRQ_TYPE_LEVEL_LOW); + enable_irq_wake(ricoh619->chip_irq); return ret; } int ricoh619_irq_exit(struct ricoh619 *ricoh619) { - if (ricoh619->chip_irq) - free_irq(ricoh619->chip_irq, ricoh619); return 0; } diff --git a/drivers/mfd/ricoh619.c b/drivers/mfd/ricoh619.c index bdceb2ccd1c4..4b5f98e74091 100755 --- a/drivers/mfd/ricoh619.c +++ b/drivers/mfd/ricoh619.c @@ -35,12 +35,35 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include struct ricoh619 *g_ricoh619; struct sleep_control_data { u8 reg_add; }; +static struct mfd_cell ricoh619s[] = { + { + .name = "ricoh619-regulator", + }, + { + .name = "ricoh619-battery", + }, + { + .name = "ricoh619-rtc", + }, + { + .name = "ricoh619-pwrkey", + }, +}; + #define SLEEP_INIT(_id, _reg) \ [RICOH619_DS_##_id] = {.reg_add = _reg} @@ -68,12 +91,10 @@ static struct sleep_control_data sleep_data[] = { SLEEP_INIT(PSO4, 0x29), SLEEP_INIT(LDORTC1, 0x2A), }; - static inline int __ricoh619_read(struct i2c_client *client, u8 reg, uint8_t *val) { - int ret; - + int ret =0; ret = i2c_smbus_read_byte_data(client, reg); if (ret < 0) { dev_err(&client->dev, "failed reading at 0x%02x\n", reg); @@ -107,7 +128,7 @@ static inline int __ricoh619_bulk_reads(struct i2c_client *client, u8 reg, static inline int __ricoh619_write(struct i2c_client *client, u8 reg, uint8_t val) { - int ret; + int ret=0; dev_dbg(&client->dev, "ricoh619: reg write reg=%x, val=%x\n", reg, val); @@ -117,14 +138,13 @@ static inline int __ricoh619_write(struct i2c_client *client, val, reg); return ret; } - return 0; } static inline int __ricoh619_bulk_writes(struct i2c_client *client, u8 reg, int len, uint8_t *val) { - int ret; + int ret=0; int i; for (i = 0; i < len; ++i) { @@ -137,7 +157,6 @@ static inline int __ricoh619_bulk_writes(struct i2c_client *client, u8 reg, dev_err(&client->dev, "failed writings to 0x%02x\n", reg); return ret; } - return 0; } @@ -162,11 +181,11 @@ int ricoh619_write(struct device *dev, u8 reg, uint8_t val) struct ricoh619 *ricoh619 = dev_get_drvdata(dev); int ret = 0; - mutex_lock(&ricoh619->io_lock); +// mutex_lock(&ricoh619->io_lock); ret = set_bank_ricoh619(dev, 0); if( !ret ) ret = __ricoh619_write(to_i2c_client(dev), reg, val); - mutex_unlock(&ricoh619->io_lock); +// mutex_unlock(&ricoh619->io_lock); return ret; } @@ -288,7 +307,7 @@ int ricoh619_set_bits(struct device *dev, u8 reg, uint8_t bit_mask) ret = set_bank_ricoh619(dev, 0); if (!ret) { ret = __ricoh619_read(to_i2c_client(dev), reg, ®_val); - if (ret) + if (ret<0) goto out; if ((reg_val & bit_mask) != bit_mask) { @@ -313,7 +332,7 @@ int ricoh619_clr_bits(struct device *dev, u8 reg, uint8_t bit_mask) ret = set_bank_ricoh619(dev, 0); if( !ret ){ ret = __ricoh619_read(to_i2c_client(dev), reg, ®_val); - if (ret) + if (ret<0) goto out; if (reg_val & bit_mask) { @@ -338,7 +357,7 @@ int ricoh619_update(struct device *dev, u8 reg, uint8_t val, uint8_t mask) ret = set_bank_ricoh619(dev, 0); if( !ret ){ ret = __ricoh619_read(ricoh619->client, reg, ®_val); - if (ret) + if (ret<0) goto out; if ((reg_val & mask) != val) { @@ -362,7 +381,7 @@ int ricoh619_update_bank1(struct device *dev, u8 reg, uint8_t val, uint8_t mask) ret = set_bank_ricoh619(dev, 1); if( !ret ){ ret = __ricoh619_read(ricoh619->client, reg, ®_val); - if (ret) + if (ret<0) goto out; if ((reg_val & mask) != val) { @@ -376,14 +395,14 @@ out: } static struct i2c_client *ricoh619_i2c_client; -int ricoh619_power_off(void) +static int ricoh619_power_off(void) { int ret; uint8_t val; int err = -1; int status, charge_state; struct ricoh619 *ricoh619 = g_ricoh619; - +#ifdef CONFIG_BATTERY_RICOH619 val = g_soc; val &= 0x7f; ricoh619_read(ricoh619->dev, 0xBD, &status); @@ -405,13 +424,9 @@ int ricoh619_power_off(void) err = ricoh619_set_bits(ricoh619->dev, TIMSET_REG, 0x03); if (err < 0) dev_err(ricoh619->dev, "Error in writing the TIMSET_Reg\n"); - - ret = ricoh619_write(ricoh619->dev, RICOH619_INTC_INTEN, 0); - - if (!ricoh619_i2c_client) - return -EINVAL; -//__ricoh618_write(ricoh618_i2c_client, RICOH618_PWR_REP_CNT, 0x0); //Not repeat power ON after power off(Power Off/N_OE) -// __ricoh618_write(ricoh618_i2c_client, RICOH618_PWR_SLP_CNT, 0x1); //Power OFF +#endif + ret = ricoh619_clr_bits(ricoh619->dev, 0xae, (0x1 <<6)); //disable alam_d + ret = ricoh619_write(ricoh619->dev, RICOH619_INTC_INTEN, 0); ret = ricoh619_clr_bits(ricoh619->dev,RICOH619_PWR_REP_CNT,(0x1<<0));//Not repeat power ON after power off(Power Off/N_OE) if(( charge_state == CHG_STATE_CHG_TRICKLE)||( charge_state == CHG_STATE_CHG_RAPID)) @@ -479,7 +494,7 @@ static int ricoh619_gpio_to_irq(struct gpio_chip *gc, unsigned off) } -static void __devinit ricoh619_gpio_init(struct ricoh619 *ricoh619, +static void ricoh619_gpio_init(struct ricoh619 *ricoh619, struct ricoh619_platform_data *pdata) { int ret; @@ -564,7 +579,7 @@ static int ricoh619_remove_subdevs(struct ricoh619 *ricoh619) ricoh619_remove_subdev); } -static int __devinit ricoh619_add_subdevs(struct ricoh619 *ricoh619, +static int ricoh619_add_subdevs(struct ricoh619 *ricoh619, struct ricoh619_platform_data *pdata) { struct ricoh619_subdev_info *subdev; @@ -687,119 +702,165 @@ static void __init ricoh619_debuginit(struct ricoh619 *ricoh) } #endif -static void __devinit ricoh619_noe_init(struct ricoh619 *ricoh) +#ifdef CONFIG_OF +static struct ricoh619_platform_data *ricoh619_parse_dt(struct ricoh619 *ricoh619) { - struct i2c_client *client = ricoh->client; + struct ricoh619_platform_data *pdata; + struct device_node *regs,*ricoh619_pmic_np; + int i, count; + + ricoh619_pmic_np = of_node_get(ricoh619->dev->of_node); + if (!ricoh619_pmic_np) { + printk("could not find pmic sub-node\n"); + return NULL; + } + pdata = devm_kzalloc(ricoh619->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return NULL; + + pdata->irq_gpio = of_get_named_gpio(ricoh619_pmic_np,"gpios",0); + if (!gpio_is_valid(pdata->irq_gpio)) { + printk("invalid gpio: %d\n", pdata->irq_gpio); + return NULL; + } + + pdata->pmic_sleep_gpio = of_get_named_gpio(ricoh619_pmic_np,"gpios",1); + if (!gpio_is_valid(pdata->pmic_sleep_gpio)) { + printk("invalid gpio: %d\n", pdata->pmic_sleep_gpio); + } + pdata->pmic_sleep = true; + + pdata->pm_off = of_property_read_bool(ricoh619_pmic_np,"ricoh619,system-power-controller"); + + return pdata; +} + +#else +static struct ricoh619_platform_data *ricoh619_parse_dt(struct ricoh619 *ricoh619) +{ + return NULL; +} +#endif + +static void ricoh619_noe_init(struct ricoh619 *ricoh) +{ + int ret; + + /***************set noe time 128ms**************/ + ret = ricoh619_set_bits(ricoh->dev,0x11,(0x1 <<3)); + ret = ricoh619_clr_bits(ricoh->dev,0x11,(0x7 <<0)); + ret = ricoh619_clr_bits(ricoh->dev,0x11,(0x1 <<3));//N_OE timer setting to 128mS + /**********************************************/ + ret = ricoh619_clr_bits(ricoh->dev,RICOH619_PWR_REP_CNT,(1 << 0)); //Repeat power ON after reset (Power Off/N_OE) :1:reset 0:power off +} + +static int ricoh619_pre_init(struct ricoh619 *ricoh619) +{ + int ret=0; + u8 val; + printk("%s,line=%d\n", __func__,__LINE__); + /* + ret = ricoh619_read(ricoh619->dev,0x09,&val); + printk("%s,line=%d ricoh619 power on his %08x\n", __func__,__LINE__,val); + ret = ricoh619_read(ricoh619->dev,0x0a,&val); + printk("%s,line=%d ricoh619 power off his %08x\n", __func__,__LINE__,val); + */ + ricoh619_set_bits(ricoh619->dev, 0xae, (0x1 <<6));//enable alam_d - __ricoh619_write(client, RICOH619_PWR_NOE_TIMSET, 0x0); //N_OE timer setting to 128mS - __ricoh619_write(client, RICOH619_PWR_REP_CNT, 0x1); //Repeat power ON after reset (Power Off/N_OE) + ricoh619_noe_init(ricoh619); + /***************set PKEY long press time 0sec*******/ + ret = ricoh619_set_bits(ricoh619->dev,0x10,(0x1 <<7)); + ret = ricoh619_clr_bits(ricoh619->dev,0x10,(0x1 <<3)); + ret = ricoh619_clr_bits(ricoh619->dev,0x10,(0x1 <<7)); + /**********************************************/ + ret = ricoh619_set_bits(ricoh619->dev,BATSET2_REG,(3 << 0)); + ret = ricoh619_clr_bits(ricoh619->dev,BATSET2_REG,(1 << 2)); //set vrchg 4v + return ret; } static int ricoh619_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct ricoh619 *ricoh619; - struct ricoh619_platform_data *pdata = client->dev.platform_data; + struct ricoh619_platform_data *pdata; int ret; uint8_t control; - printk(KERN_INFO "PMU: %s:\n", __func__); + printk("%s,line=%d\n", __func__,__LINE__); - ricoh619 = kzalloc(sizeof(struct ricoh619), GFP_KERNEL); + ricoh619 = devm_kzalloc(&client->dev,sizeof(struct ricoh619), GFP_KERNEL); if (ricoh619 == NULL) return -ENOMEM; ricoh619->client = client; ricoh619->dev = &client->dev; i2c_set_clientdata(client, ricoh619); - mutex_init(&ricoh619->io_lock); ret = ricoh619_read(ricoh619->dev, 0x36, &control); - if ((control < 0) || (control == 0xff) || (control == 0)) { - printk(KERN_INFO "The device is not ricoh619\n"); - return 0; + if ((ret <0) || (control < 0) || (control == 0xff) || (control == 0) ){ + printk(KERN_INFO "The device is not ricoh619 %08x %d\n",control,ret); + goto err; } - /***************set noe time 128ms**************/ - ret = ricoh619_set_bits(ricoh619->dev,0x11,(0x1 <<3)); - ret = ricoh619_clr_bits(ricoh619->dev,0x11,(0x7 <<0)); - ret = ricoh619_clr_bits(ricoh619->dev,0x11,(0x1 <<3)); - /**********************************************/ - /***************set PKEY long press time 0sec*******/ - ret = ricoh619_set_bits(ricoh619->dev,0x10,(0x1 <<7)); - ret = ricoh619_clr_bits(ricoh619->dev,0x10,(0x1 <<3)); - ret = ricoh619_clr_bits(ricoh619->dev,0x10,(0x1 <<7)); - /**********************************************/ + ret = ricoh619_pre_init(ricoh619); + if (ret < 0){ + printk("The ricoh619_pre_init failed %d\n",ret); + goto err; + } ricoh619->bank_num = 0; - -// ret = pdata->init_port(client->irq); // For init PMIC_IRQ port - if (client->irq) { - ret = ricoh619_irq_init(ricoh619, client->irq, pdata->irq_base); - if (ret) { - dev_err(&client->dev, "IRQ init failed: %d\n", ret); - goto err_irq_init; - } - } - ret = ricoh619_add_subdevs(ricoh619, pdata); - if (ret) { - dev_err(&client->dev, "add devices failed: %d\n", ret); - goto err_add_devs; - } - ricoh619_noe_init(ricoh619); + if (ricoh619->dev->of_node) + pdata = ricoh619_parse_dt(ricoh619); + + /******************************set sleep vol & dcdc mode******************/ + #ifdef CONFIG_OF + if (pdata->pmic_sleep_gpio) { + ret = gpio_request(pdata->pmic_sleep_gpio, "ricoh619_pmic_sleep"); + if (ret < 0) { + dev_err(ricoh619->dev,"Failed to request gpio %d with ret:""%d\n", pdata->pmic_sleep_gpio, ret); + return IRQ_NONE; + } + gpio_direction_output(pdata->pmic_sleep_gpio,0); + ret = gpio_get_value(pdata->pmic_sleep_gpio); + gpio_free(pdata->pmic_sleep_gpio); + pr_info("%s: ricoh619_pmic_sleep=%x\n", __func__, ret); + } + #endif + /**********************************************************/ + ret = ricoh619_irq_init(ricoh619, pdata->irq_gpio, pdata); + if (ret < 0) + goto err; + ret = mfd_add_devices(ricoh619->dev, -1, + ricoh619s, ARRAY_SIZE(ricoh619s), + NULL, 0,NULL); g_ricoh619 = ricoh619; - if (pdata && pdata->pre_init) { - ret = pdata->pre_init(ricoh619); - if (ret != 0) { - dev_err(ricoh619->dev, "pre_init() failed: %d\n", ret); - goto err; - } + if (pdata->pm_off && !pm_power_off) { + pm_power_off = ricoh619_power_off; } - - //ricoh619_gpio_init(ricoh619, pdata); - ricoh619_debuginit(ricoh619); - if (pdata && pdata->post_init) { - ret = pdata->post_init(ricoh619); - if (ret != 0) { - dev_err(ricoh619->dev, "post_init() failed: %d\n", ret); - goto err; - } - } - ricoh619_i2c_client = client; return 0; err: mfd_remove_devices(ricoh619->dev); - kfree(ricoh619); -err_add_devs: - if (client->irq) - ricoh619_irq_exit(ricoh619); -err_irq_init: - kfree(ricoh619); return ret; } -static int __devexit ricoh619_i2c_remove(struct i2c_client *client) +static int ricoh619_i2c_remove(struct i2c_client *client) { struct ricoh619 *ricoh619 = i2c_get_clientdata(client); - - if (client->irq) - ricoh619_irq_exit(ricoh619); - ricoh619_remove_subdevs(ricoh619); - kfree(ricoh619); return 0; } #ifdef CONFIG_PM static int ricoh619_i2c_suspend(struct i2c_client *client, pm_message_t state) { - if (client->irq) - disable_irq(client->irq); +// if (g_ricoh619->chip_irq) +// disable_irq(g_ricoh619->chip_irq); +// printk("PMU: %s: \n",__func__); return 0; } @@ -808,15 +869,13 @@ static int ricoh619_i2c_resume(struct i2c_client *client) { uint8_t reg_val; int ret; - ret = __ricoh619_read(client, RICOH619_INT_IR_SYS, ®_val); if(reg_val & 0x01) { //If PWR_KEY wakeup // printk("PMU: %s: PWR_KEY Wakeup\n",__func__); pwrkey_wakeup = 1; __ricoh619_write(client, RICOH619_INT_IR_SYS, 0x0); //Clear PWR_KEY IRQ } - - enable_irq(client->irq); +// enable_irq(g_ricoh619->chip_irq); return 0; } @@ -826,16 +885,25 @@ static const struct i2c_device_id ricoh619_i2c_id[] = { {"ricoh619", 0}, {} }; - MODULE_DEVICE_TABLE(i2c, ricoh619_i2c_id); +#ifdef CONFIG_OF +static const struct of_device_id ricoh619_dt_match[] = { + { .compatible = "ricoh,ricoh619", }, + {}, +}; +MODULE_DEVICE_TABLE(of, ricoh619_dt_match); +#endif + + static struct i2c_driver ricoh619_i2c_driver = { .driver = { .name = "ricoh619", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(ricoh619_dt_match), }, .probe = ricoh619_i2c_probe, - .remove = __devexit_p(ricoh619_i2c_remove), + .remove = ricoh619_i2c_remove, #ifdef CONFIG_PM .suspend = ricoh619_i2c_suspend, .resume = ricoh619_i2c_resume, diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig old mode 100644 new mode 100755 index e9e85f5e6587..a59488ab56be --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -64,6 +64,13 @@ config WM8350_POWER Say Y here to enable support for the power management unit provided by the Wolfson Microelectronics WM8350 PMIC. +config BATTERY_RICOH619 + tristate "Ricoh RC5T619 PMIC battery driver" + depends on MFD_RICOH619 && I2C && GENERIC_HARDIRQS + help + Say Y to enable support for the battery control of the Ricoh RC5T619 + Power Management device. + config TEST_POWER tristate "Test power driver" help diff --git a/drivers/power/Makefile b/drivers/power/Makefile old mode 100644 new mode 100755 index dfe34f627885..4dc7f07376bc --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -56,5 +56,6 @@ obj-$(CONFIG_POWER_AVS) += avs/ obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o obj-$(CONFIG_CW2015_BATTERY) += cw2015_battery.o +obj-$(CONFIG_BATTERY_RICOH619) += ricoh619-battery.o obj-$(CONFIG_CHARGER_DISPLAY) += rk29_charger_display.o obj-$(CONFIG_POWER_RESET) += reset/ diff --git a/drivers/power/ricoh619-battery.c b/drivers/power/ricoh619-battery.c old mode 100644 new mode 100755 index ecab67ffe238..8bfc7d679c11 --- a/drivers/power/ricoh619-battery.c +++ b/drivers/power/ricoh619-battery.c @@ -19,6 +19,9 @@ * along with this program. If not, see . * */ +#define RICOH619_BATTERY_VERSION "RICOH619_BATTERY_VERSION: 2014.03.28" + + #include #include #include @@ -31,12 +34,12 @@ #include #include #include -#include -#include +#include #include #include +#include /* define for function */ @@ -45,7 +48,7 @@ #define ENABLE_FACTORY_MODE #define DISABLE_CHARGER_TIMER /* #define ENABLE_FG_KEEP_ON_MODE */ -#define ENABLE_OCV_TABLE_CALIB +/* #define ENABLE_OCV_TABLE_CALIB */ @@ -78,12 +81,17 @@ enum int_type { #define RICOH619_GET_CHARGE_NUM 10 #define RICOH619_UPDATE_COUNT_DISP 4 #define RICOH619_UPDATE_COUNT_FULL 4 +#define RICOH619_UPDATE_COUNT_FULL_RESET 7 #define RICOH619_CHARGE_UPDATE_TIME 3 -#define RICOH619_FULL_WAIT_TIME 2 +#define RICOH619_FULL_WAIT_TIME 4 #define RE_CAP_GO_DOWN 10 /* 40 */ #define RICOH619_ENTER_LOW_VOL 70 -#define RICOH619_TAH_SEL2 5 -#define RICOH619_TAL_SEL2 6 +#define RICOH619_TAH_SEL2 5 +#define RICOH619_TAL_SEL2 6 + +#define RICOH619_OCV_OFFSET_BOUND 3 +#define RICOH619_OCV_OFFSET_RATIO 2 + /* define for FG status */ enum { RICOH619_SOCA_START, @@ -106,6 +114,7 @@ struct ricoh619_soca_info { int n_cap; int ocv_table_def[11]; int ocv_table[11]; + int ocv_table_low[11]; int soc; /* Latest FG SOC value */ int displayed_soc; int suspend_soc; @@ -114,26 +123,29 @@ struct ricoh619_soca_info { int chg_status; /* chg_status */ int soc_delta; /* soc delta for status3(DISP) */ int cc_delta; + int cc_cap_offset; int last_soc; + int last_displayed_soc; int ready_fg; int reset_count; int reset_soc[3]; - int reset_flg_90; - int reset_flg_95; - int f_chg_margin; int chg_cmp_times; int dischg_state; int Vbat[RICOH619_GET_CHARGE_NUM]; int Vsys[RICOH619_GET_CHARGE_NUM]; int Ibat[RICOH619_GET_CHARGE_NUM]; int Vbat_ave; + int Vbat_old; int Vsys_ave; int Ibat_ave; int chg_count; - int update_count; + int full_reset_count; + int soc_full; + int fc_cap; /* for LOW VOL state */ int target_use_cap; int hurry_up_flg; + int zero_flg; int re_cap_old; int cutoff_ocv; int Rsys; @@ -142,6 +154,10 @@ struct ricoh619_soca_info { int jt_limit; int OCV100_min; int OCV100_max; + int R_low; + int rsoc_ready_flag; + int init_pswr; + int last_cc_sum; }; struct ricoh619_battery_info { @@ -199,6 +215,7 @@ struct ricoh619_battery_info { int ch_icchg; int fg_target_vsys; int fg_target_ibat; + int fg_poff_vbat; int jt_en; int jt_hw_sw; int jt_temp_h; @@ -211,16 +228,19 @@ struct ricoh619_battery_info { int num; }; +struct power_supply powerac; +struct power_supply powerusb; + +int g_full_flag; int charger_irq; /* this value is for mfd fucntion */ int g_soc; int g_fg_on_mode; -extern int dwc_vbus_status(void); +int type_n; +extern int dwc_otg_check_dpdm(bool wait); /*This is for full state*/ -int g_full_flag; static int BatteryTableFlagDef=0; static int BatteryTypeDef=0; -static void ricoh619_scaling_OCV_table(struct ricoh619_battery_info *info, int cutoff_vol, int full_vol, int *start_per, int *end_per); static int Battery_Type(void) { return BatteryTypeDef; @@ -253,14 +273,17 @@ static int get_check_fuel_gauge_reg(struct ricoh619_battery_info *info, int Reg_h, int Reg_l, int enable_bit); static int calc_capacity_in_period(struct ricoh619_battery_info *info, int *cc_cap, bool *is_charging, bool cc_rst); -static int get_charge_priority(struct ricoh619_battery_info *info, bool *data); -static int set_charge_priority(struct ricoh619_battery_info *info, bool *data); +//static int get_charge_priority(struct ricoh619_battery_info *info, bool *data); +//static int set_charge_priority(struct ricoh619_battery_info *info, bool *data); static int get_power_supply_status(struct ricoh619_battery_info *info); +static int get_power_supply_Android_status(struct ricoh619_battery_info *info); static int measure_vsys_ADC(struct ricoh619_battery_info *info, int *data); static int Calc_Linear_Interpolation(int x0, int y0, int x1, int y1, int y); static int get_battery_temp(struct ricoh619_battery_info *info); static int get_battery_temp_2(struct ricoh619_battery_info *info); static int check_jeita_status(struct ricoh619_battery_info *info, bool *is_jeita_updated); +static void ricoh619_scaling_OCV_table(struct ricoh619_battery_info *info, int cutoff_vol, int full_vol, int *start_per, int *end_per); +static int ricoh619_Check_OCV_Offset(struct ricoh619_battery_info *info); static int calc_ocv(struct ricoh619_battery_info *info) { @@ -277,18 +300,213 @@ static int calc_ocv(struct ricoh619_battery_info *info) return ocv; } + +static int set_Rlow(struct ricoh619_battery_info *info) +{ + int err; + int Rbat_low_max; + uint8_t val; + int Vocv; + int temp; + + if (info->soca->Rbat == 0) + info->soca->Rbat = get_OCV_init_Data(info, 12) * 1000 / 512 + * 5000 / 4095; + + Vocv = calc_ocv(info); + Rbat_low_max = info->soca->Rbat * 1.5; + + if (Vocv < get_OCV_voltage(info,3)) + { + info->soca->R_low = Calc_Linear_Interpolation(info->soca->Rbat,get_OCV_voltage(info,3), + Rbat_low_max, get_OCV_voltage(info,0), Vocv); + RICOH_FG_DBG("PMU: Modify RBAT from %d to %d ", info->soca->Rbat, info->soca->R_low); + temp = info->soca->R_low *4095/5000*512/1000; + + val = info->soca->R_low>>8; + err = ricoh619_write_bank1(info->dev->parent, 0xD4, val); + if (err < 0) { + dev_err(info->dev, "batterry initialize error\n"); + return err; + } + + val = info->soca->R_low & 0xff; + err = ricoh619_write_bank1(info->dev->parent, 0xD5, val); + if (err < 0) { + dev_err(info->dev, "batterry initialize error\n"); + return err; + } + } + else info->soca->R_low = 0; + + + return err; +} + +static int Set_back_ocv_table(struct ricoh619_battery_info *info) +{ + int err; + uint8_t val; + int temp; + int i; + uint8_t debug_disp[22]; + + /* Modify back ocv table */ + + if (0 != info->soca->ocv_table_low[0]) + { + for (i = 0 ; i < 11; i++){ + battery_init_para[info->num][i*2 + 1] = info->soca->ocv_table_low[i]; + battery_init_para[info->num][i*2] = info->soca->ocv_table_low[i] >> 8; + } + err = ricoh619_clr_bits(info->dev->parent, FG_CTRL_REG, 0x01); + + err = ricoh619_bulk_writes_bank1(info->dev->parent, + BAT_INIT_TOP_REG, 22, battery_init_para[info->num]); + + err = ricoh619_set_bits(info->dev->parent, FG_CTRL_REG, 0x01); + + /* debug comment start*/ + err = ricoh619_bulk_reads_bank1(info->dev->parent, + BAT_INIT_TOP_REG, 22, debug_disp); + for (i = 0; i < 11; i++){ + RICOH_FG_DBG("PMU : %s : after OCV table %d 0x%x\n",__func__, i * 10, (debug_disp[i*2] << 8 | debug_disp[i*2+1])); + } + /* end */ + /* clear table*/ + for(i = 0; i < 11; i++) + { + info->soca->ocv_table_low[i] = 0; + } + } + + /* Modify back Rbat */ + if (0!=info->soca->R_low) + { + RICOH_FG_DBG("PMU: Modify back RBAT from %d to %d ", info->soca->R_low,info->soca->Rbat); + temp = info->soca->Rbat*4095/5000*512/1000; + + val = info->soca->R_low>>8; + err = ricoh619_write_bank1(info->dev->parent, 0xD4, val); + if (err < 0) { + dev_err(info->dev, "batterry initialize error\n"); + return err; + } + + val = info->soca->R_low & 0xff; + err = ricoh619_write_bank1(info->dev->parent, 0xD5, val); + if (err < 0) { + dev_err(info->dev, "batterry initialize error\n"); + return err; + } + + info->soca->R_low = 0; + } + return 0; +} + +/** +**/ +static int ricoh619_Check_OCV_Offset(struct ricoh619_battery_info *info) +{ + int ocv_table[11]; // HEX value + int i; + int temp; + int ret; + uint8_t debug_disp[22]; + uint8_t val = 0; + + RICOH_FG_DBG("PMU : %s : calc ocv %d get OCV %d\n",__func__,calc_ocv(info),get_OCV_voltage(info, RICOH619_OCV_OFFSET_BOUND)); + + /* check adp/usb status */ + ret = ricoh619_read(info->dev->parent, CHGSTATE_REG, &val); + if (ret < 0) { + dev_err(info->dev, "Error in reading the control register\n"); + return ret; + } + + val = (val & 0xC0) >> 6; + + if (val != 0){ /* connect adp or usb */ + if (calc_ocv(info) < get_OCV_voltage(info, RICOH619_OCV_OFFSET_BOUND) ) + { + if(0 == info->soca->ocv_table_low[0]){ + for (i = 0 ; i < 11; i++){ + ocv_table[i] = (battery_init_para[info->num][i*2]<<8) | (battery_init_para[info->num][i*2+1]); + RICOH_FG_DBG("PMU : %s : OCV table %d 0x%x\n",__func__,i * 10, ocv_table[i]); + info->soca->ocv_table_low[i] = ocv_table[i]; + } + + for (i = 0 ; i < 11; i++){ + temp = ocv_table[i] * (100 + RICOH619_OCV_OFFSET_RATIO) / 100; + + battery_init_para[info->num][i*2 + 1] = temp; + battery_init_para[info->num][i*2] = temp >> 8; + } + ret = ricoh619_clr_bits(info->dev->parent, FG_CTRL_REG, 0x01); + + ret = ricoh619_bulk_writes_bank1(info->dev->parent, + BAT_INIT_TOP_REG, 22, battery_init_para[info->num]); + + ret = ricoh619_set_bits(info->dev->parent, FG_CTRL_REG, 0x01); + + /* debug comment start*/ + ret = ricoh619_bulk_reads_bank1(info->dev->parent, + BAT_INIT_TOP_REG, 22, debug_disp); + for (i = 0; i < 11; i++){ + RICOH_FG_DBG("PMU : %s : after OCV table %d 0x%x\n",__func__, i * 10, (debug_disp[i*2] << 8 | debug_disp[i*2+1])); + } + /* end */ + } + } + } + + return 0; +} + +static int reset_FG_process(struct ricoh619_battery_info *info) +{ + int err; + + //err = set_Rlow(info); + //err = ricoh619_Check_OCV_Offset(info); + err = ricoh619_write(info->dev->parent, + FG_CTRL_REG, 0x51); + info->soca->ready_fg = 0; + return err; +} + + static int check_charge_status_2(struct ricoh619_battery_info *info, int displayed_soc_temp) { if (displayed_soc_temp < 0) displayed_soc_temp = 0; get_power_supply_status(info); - /* for issue 5 */ + info->soca->soc = calc_capacity(info) * 100; + if (POWER_SUPPLY_STATUS_FULL == info->soca->chg_status) { - g_full_flag = 1; - info->soca->displayed_soc = 100*100; + if ((info->first_pwon == 1) + && (RICOH619_SOCA_START == info->soca->status)) { + g_full_flag = 1; + info->soca->soc_full = info->soca->soc; + info->soca->displayed_soc = 100*100; + info->soca->full_reset_count = 0; + } else { + if ( (displayed_soc_temp > 97*100) + && (calc_ocv(info) > (get_OCV_voltage(info, 9) + (get_OCV_voltage(info, 10) - get_OCV_voltage(info, 9))*7/10) )){ + g_full_flag = 1; + info->soca->soc_full = info->soca->soc; + info->soca->displayed_soc = 100*100; + info->soca->full_reset_count = 0; + } else { + g_full_flag = 0; + info->soca->displayed_soc = displayed_soc_temp; + } + + } } - if (info->soca->Ibat_ave >= 0) { /* for issue 3 */ + if (info->soca->Ibat_ave >= 0) { if (g_full_flag == 1) { info->soca->displayed_soc = 100*100; } else { @@ -301,10 +519,10 @@ static int check_charge_status_2(struct ricoh619_battery_info *info, int display } if (info->soca->Ibat_ave < 0) { if (g_full_flag == 1) { - if ((calc_ocv(info) < (get_OCV_voltage(info, 9) + (get_OCV_voltage(info, 10) - get_OCV_voltage(info, 9))*3/10) ) - && (info->soca->soc/100 <= 98) ) { + if (calc_ocv(info) < (get_OCV_voltage(info, 9) + (get_OCV_voltage(info, 10) - get_OCV_voltage(info, 9))*7/10) ) { g_full_flag = 0; - info->soca->displayed_soc = 100*100; + //info->soca->displayed_soc = 100*100; + info->soca->displayed_soc = displayed_soc_temp; } else { info->soca->displayed_soc = 100*100; } @@ -333,15 +551,18 @@ static int calc_capacity_in_period(struct ricoh619_battery_info *info, int *cc_cap, bool *is_charging, bool cc_rst) { int err; - uint8_t cc_sum_reg[4]; - uint8_t cc_clr[4] = {0, 0, 0, 0}; - uint8_t fa_cap_reg[2]; - uint16_t fa_cap; - uint32_t cc_sum; - int cc_stop_flag; - uint8_t status; - uint8_t charge_state; - int Ocv; + uint8_t cc_sum_reg[4]; + uint8_t cc_clr[4] = {0, 0, 0, 0}; + uint8_t fa_cap_reg[2]; + uint16_t fa_cap; + uint32_t cc_sum; + int cc_stop_flag; + uint8_t status; + uint8_t charge_state; + int Ocv; + uint32_t cc_cap_temp; + uint32_t cc_cap_min; + int cc_cap_res; *is_charging = true; /* currrent state initialize -> charging */ @@ -448,9 +669,34 @@ static int calc_capacity_in_period(struct ricoh619_battery_info *info, cc_sum = (cc_sum^0xffffffff)+0x01; *is_charging = false; /* discharge */ } + /* (CC_SUM x 10000)/3600/FA_CAP */ + *cc_cap = cc_sum*25/9/fa_cap; /* unit is 0.01% */ - *cc_cap = cc_sum*25/9/fa_cap; /* CC_SUM/3600/FA_CAP */ - + ////////////////////////////////////////////////////////////////// + cc_cap_min = fa_cap*3600/100/100/100; /* Unit is 0.0001% */ + cc_cap_temp = cc_sum / cc_cap_min; + + cc_cap_res = cc_cap_temp % 100; + + RICOH_FG_DBG("PMU: cc_sum = %d: cc_cap_res= %d: \n", cc_sum, cc_cap_res); + + + if(*is_charging) { + info->soca->cc_cap_offset += cc_cap_res; + if (info->soca->cc_cap_offset >= 100) { + *cc_cap += 1; + info->soca->cc_cap_offset %= 100; + } + } else { + info->soca->cc_cap_offset -= cc_cap_res; + if (info->soca->cc_cap_offset <= -100) { + *cc_cap += 1; + info->soca->cc_cap_offset %= 100; + } + } + RICOH_FG_DBG("PMU: cc_cap_offset= %d: \n", info->soca->cc_cap_offset); + + ////////////////////////////////////////////////////////////////// return 0; out: dev_err(info->dev, "Error !!-----\n"); @@ -461,10 +707,10 @@ out: **/ static int get_target_use_cap(struct ricoh619_battery_info *info) { - int i; + int i,j; int ocv_table[11]; int temp; - int Target_Cutoff_Vol; + int Target_Cutoff_Vol = 0; int Ocv_ZeroPer_now; int Ibat_now; int fa_cap,use_cap; @@ -474,6 +720,12 @@ static int get_target_use_cap(struct ricoh619_battery_info *info) int CC_OnePer_step; int Ibat_min; + int Ocv_now; + int Ocv_now_table; + int soc_per; + int use_cap_now; + int Rsys_now; + /* get const value */ Ibat_min = -1 * info->soca->target_ibat; if (info->soca->Ibat_ave > Ibat_min) /* I bat is minus */ @@ -485,22 +737,37 @@ static int get_target_use_cap(struct ricoh619_battery_info *info) fa_cap = get_check_fuel_gauge_reg(info, FA_CAP_H_REG, FA_CAP_L_REG, 0x7fff); use_cap = fa_cap - info->soca->re_cap_old; - - Ocv_ZeroPer_now = info->soca->target_vsys * 1000 - Ibat_now * info->soca->Rsys; - - RICOH_FG_DBG("PMU: ------- Rsys= %d: cutoff_ocv= %d: Ocv_ZeroPer_now= %d =======\n", - info->soca->Rsys, info->soca->cutoff_ocv, Ocv_ZeroPer_now); - /* get FA_CAP_now */ - /* Check Start % */ + /* get OCV table % */ for (i = 0; i <= 10; i = i+1) { temp = (battery_init_para[info->num][i*2]<<8) | (battery_init_para[info->num][i*2+1]); /* conversion unit 1 Unit is 1.22mv (5000/4095 mv) */ temp = ((temp * 50000 * 10 / 4095) + 5) / 10; ocv_table[i] = temp; + RICOH_FG_DBG("PMU : %s : ocv_table %d is %d v\n",__func__, i, ocv_table[i]); } + + /* Find out Current OCV */ + i = info->soca->soc/1000; + j = info->soca->soc - info->soca->soc/1000*1000; + Ocv_now_table = ocv_table[i]*100+(ocv_table[i+1]-ocv_table[i])*j/10; + + Rsys_now = (info->soca->Vsys_ave - Ocv_now_table) / info->soca->Ibat_ave; + + Ocv_ZeroPer_now = info->soca->target_vsys * 1000 - Ibat_now * Rsys_now; + + RICOH_FG_DBG("PMU: ------- Ocv_now_table= %d: Rsys_now= %d =======\n", + Ocv_now_table, Rsys_now); + + RICOH_FG_DBG("PMU: ------- Rsys= %d: cutoff_ocv= %d: Ocv_ZeroPer_now= %d =======\n", + info->soca->Rsys, info->soca->cutoff_ocv, Ocv_ZeroPer_now); + + /* get FA_CAP_now */ + + for (i = 1; i < 11; i++) { + RICOH_FG_DBG("PMU : %s : ocv_table %d is %d v Ocv_ZerPernow is %d\n",__func__, i, ocv_table[i],(Ocv_ZeroPer_now / 100)); if (ocv_table[i] >= Ocv_ZeroPer_now / 100) { /* unit is 0.001% */ start_per = Calc_Linear_Interpolation( @@ -510,6 +777,8 @@ static int get_target_use_cap(struct ricoh619_battery_info *info) } } + start_per = max(0, start_per); + FA_CAP_now = fa_cap * ((10000 - start_per) / 100 ) / 100; RICOH_FG_DBG("PMU: ------- Target_Cutoff_Vol= %d: Ocv_ZeroPer_now= %d: start_per= %d =======\n", @@ -518,22 +787,31 @@ static int get_target_use_cap(struct ricoh619_battery_info *info) /* get RE_CAP_now */ RE_CAP_now = FA_CAP_now - use_cap; - if (RE_CAP_now < RE_CAP_GO_DOWN || info->soca->Vsys_ave < info->soca->target_vsys*1000) { + if (RE_CAP_now < RE_CAP_GO_DOWN) { info->soca->hurry_up_flg = 1; - } else { - info->soca->hurry_up_flg = 0; - /* get CC_OnePer_step */ - if (info->soca->displayed_soc > 0) { /* avoid divide-by-0 */ - CC_OnePer_step = RE_CAP_now / (info->soca->displayed_soc / 100); + } else if (info->soca->Vsys_ave < info->soca->target_vsys*1000) { + info->soca->hurry_up_flg = 1; + } else if (info->fg_poff_vbat != 0) { + if (info->soca->Vbat_ave < info->fg_poff_vbat*1000) { + info->soca->hurry_up_flg = 1; } else { - CC_OnePer_step = 0; + info->soca->hurry_up_flg = 0; } - /* get info->soca->target_use_cap */ - info->soca->target_use_cap = use_cap + CC_OnePer_step; + } else { + info->soca->hurry_up_flg = 0; + } + + /* get CC_OnePer_step */ + if (info->soca->displayed_soc > 0) { /* avoid divide-by-0 */ + CC_OnePer_step = RE_CAP_now / (info->soca->displayed_soc / 100 + 1); + } else { + CC_OnePer_step = 0; } + /* get info->soca->target_use_cap */ + info->soca->target_use_cap = use_cap + CC_OnePer_step; - RICOH_FG_DBG("PMU: ------- FA_CAP_now= %d: RE_CAP_now= %d: target_use_cap= %d: hurry_up_flg= %d -------\n", - FA_CAP_now, RE_CAP_now, info->soca->target_use_cap, info->soca->hurry_up_flg); + RICOH_FG_DBG("PMU: ------- FA_CAP_now= %d: RE_CAP_now= %d: CC_OnePer_step= %d: target_use_cap= %d: hurry_up_flg= %d -------\n", + FA_CAP_now, RE_CAP_now, CC_OnePer_step, info->soca->target_use_cap, info->soca->hurry_up_flg); return 0; } @@ -550,7 +828,8 @@ static int calib_ocvTable(struct ricoh619_battery_info *info, int vbat_ocv) int cutoff_ocv; int i; int ocv100_new; - int start_per,end_per; + int start_per = 0; + int end_per = 0; RICOH_FG_DBG("PMU: %s\n", __func__); @@ -577,7 +856,6 @@ static int calib_ocvTable(struct ricoh619_battery_info *info, int vbat_ocv) goto err; } - info->soca->ready_fg = 0; //cutoff_ocv = (battery_init_para[info->num][0]<<8) | (battery_init_para[info->num][1]); cutoff_ocv = get_OCV_voltage(info, 0); @@ -600,14 +878,14 @@ static int calib_ocvTable(struct ricoh619_battery_info *info, int vbat_ocv) } /* FG_En on & Reset*/ - ret = ricoh619_write(info->dev->parent, FG_CTRL_REG, 0x51); + ret = reset_FG_process(info); if (ret < 0) { dev_err("PMU: %s Error in FG_En On & Reset\n", __func__); goto err; } RICOH_FG_DBG("PMU: %s Exit \n", __func__); - return 0; + return 0; err: return ret; @@ -626,16 +904,15 @@ static void ricoh619_displayed_work(struct work_struct *work) int disp_dec; int cc_cap = 0; bool is_charging = true; - int i; int re_cap,fa_cap,use_cap; bool is_jeita_updated; uint8_t reg_val; int delay_flag = 0; int Vbat = 0; int Ibat = 0; - int ret; - int ocv; + int Vsys = 0; int temp_ocv; + int fc_delta = 0; struct ricoh619_battery_info *info = container_of(work, struct ricoh619_battery_info, displayed_work.work); @@ -656,7 +933,7 @@ static void ricoh619_displayed_work(struct work_struct *work) || (RICOH619_SOCA_FULL == info->soca->status)) info->soca->ready_fg = 1; - /* judege Full state or Moni Vsys state */ + /* judge Full state or Moni Vsys state */ if ((RICOH619_SOCA_DISP == info->soca->status) || (RICOH619_SOCA_STABLE == info->soca->status)) { @@ -664,31 +941,26 @@ static void ricoh619_displayed_work(struct work_struct *work) temp_ocv = get_OCV_voltage(info, 10) - (get_OCV_voltage(info, 10) - get_OCV_voltage(info, 9))/2; - if ((POWER_SUPPLY_STATUS_FULL == info->soca->chg_status) - && (calc_ocv(info) > temp_ocv)) { + if(g_full_flag == 1){ /* for issue 1 solution start*/ info->soca->status = RICOH619_SOCA_FULL; - info->soca->update_count = 0; - } - /* for issue 1 solution start*/ - if(g_full_flag == 1){ + }else if ((POWER_SUPPLY_STATUS_FULL == info->soca->chg_status) + && (calc_ocv(info) > temp_ocv)) { info->soca->status = RICOH619_SOCA_FULL; - info->soca->update_count = 0; - } - /* for issue1 solution end */ - /* check Full state or not*/ - if (info->soca->Ibat_ave >= -20) { + g_full_flag = 0; + } else if (info->soca->Ibat_ave >= -20) { + /* for issue1 solution end */ + /* check Full state or not*/ if ((calc_ocv(info) > (get_OCV_voltage(info, 9) + (get_OCV_voltage(info, 10) - get_OCV_voltage(info, 9))*7/10)) - || (info->soca->displayed_soc/100 >= 99)) + || (POWER_SUPPLY_STATUS_FULL == info->soca->chg_status) + || (info->soca->displayed_soc > 9850)) { - g_full_flag = 0; info->soca->status = RICOH619_SOCA_FULL; - info->soca->update_count = 0; + g_full_flag = 0; } else if ((calc_ocv(info) > (get_OCV_voltage(info, 9))) && (info->soca->Ibat_ave < 300)) { - g_full_flag = 0; info->soca->status = RICOH619_SOCA_FULL; - info->soca->update_count = 0; + g_full_flag = 0; } } else { /* dis-charging */ if (info->soca->displayed_soc/100 < RICOH619_ENTER_LOW_VOL) { @@ -700,68 +972,8 @@ static void ricoh619_displayed_work(struct work_struct *work) if (RICOH619_SOCA_STABLE == info->soca->status) { info->soca->soc = calc_capacity_2(info); - soc_round = info->soca->soc / 100; - last_soc_round = info->soca->last_soc / 100; - info->soca->soc_delta = info->soca->soc - info->soca->last_soc; - //get charge status - if (info->soca->chg_status == POWER_SUPPLY_STATUS_CHARGING) { - if (soc_round >= 90) { - if(soc_round < 95) { - if (info->soca->reset_flg_90 == 0) { - err = ricoh619_write(info->dev->parent, - FG_CTRL_REG, 0x51); - if (err< 0) - dev_err(info->dev, "Error in writing the control register\n"); - - info->soca->ready_fg = 0; - - for (i = 0; i < 3; i = i+1) { - info->soca->reset_soc[i] = 0; - } - info->soca->stable_count = 0; - - info->soca->status = RICOH619_SOCA_FG_RESET; - /* Delay for addition Reset Time (6s) */ - info->soca->stable_count = 1; - queue_delayed_work(info->monitor_wqueue, - &info->charge_stable_work, - RICOH619_FG_RESET_TIME*HZ); - - info->soca->reset_flg_90 = 1; - goto end_flow; - } - } else if (soc_round < 100) { - if (info->soca->reset_flg_95 == 0) { - err = ricoh619_write(info->dev->parent, - FG_CTRL_REG, 0x51); - if (err < 0) - dev_err(info->dev, "Error in writing the control register\n"); - - info->soca->ready_fg = 0; - - for (i = 0; i < 3; i = i+1) { - info->soca->reset_soc[i] = 0; - } - - info->soca->stable_count = 0; - info->soca->status = RICOH619_SOCA_FG_RESET; - info->soca->stable_count = 1; - queue_delayed_work(info->monitor_wqueue, - &info->charge_stable_work, - RICOH619_FG_RESET_TIME*HZ); - - info->soca->reset_flg_95 = 1; - goto end_flow; - } - } - } else { - info->soca->reset_flg_90 = 0; - info->soca->reset_flg_95 = 0; - } - } - if (info->soca->soc_delta >= -100 && info->soca->soc_delta <= 100) { info->soca->displayed_soc = info->soca->soc; } else { @@ -781,34 +993,55 @@ static void ricoh619_displayed_work(struct work_struct *work) if (info->soca->Ibat_ave >= -20) { /* charging */ if (0 == info->soca->jt_limit) { if (g_full_flag == 1) { - /* caluc 95% ocv */ - //temp_ocv = get_OCV_voltage(info, 10) - - // (get_OCV_voltage(info, 10) - get_OCV_voltage(info, 9))/2; - temp_ocv = get_OCV_voltage(info, 9); - info->soca->update_count++; - info->soca->chg_cmp_times = 0; - if (info->soca->update_count >= RICOH619_UPDATE_COUNT_FULL) { - if (calc_ocv(info) < temp_ocv) { - if(info->soca->displayed_soc > info->soca->soc) { - info->soca->displayed_soc = info->soca->displayed_soc - 1; - } else { - info->soca->displayed_soc = info->soca->soc; - } - } else { - info->soca->displayed_soc = 100*100; + + if (POWER_SUPPLY_STATUS_FULL == info->soca->chg_status) { + if(info->soca->full_reset_count < RICOH619_UPDATE_COUNT_FULL_RESET) { + info->soca->full_reset_count++; + } else if (info->soca->full_reset_count < (RICOH619_UPDATE_COUNT_FULL_RESET + 1)) { + err = reset_FG_process(info); + if (err < 0) + dev_err(info->dev, "Error in writing the control register\n"); + info->soca->full_reset_count++; + goto end_flow; + } else if(info->soca->full_reset_count < (RICOH619_UPDATE_COUNT_FULL_RESET + 2)) { + info->soca->full_reset_count++; + info->soca->fc_cap = 0; + info->soca->soc_full = info->soca->soc; + } + } else { + if(info->soca->fc_cap < -1 * 200) { + g_full_flag = 0; + info->soca->displayed_soc = 99 * 100; } - info->soca->update_count = 0; + info->soca->full_reset_count = 0; + } + + + info->soca->chg_cmp_times = 0; + err = calc_capacity_in_period(info, &cc_cap, &is_charging, true); + if (err < 0) + dev_err(info->dev, "Read cc_sum Error !!-----\n"); + + fc_delta = (is_charging == true) ? cc_cap : -cc_cap; + + info->soca->fc_cap = info->soca->fc_cap + fc_delta; + + if (g_full_flag == 1){ + info->soca->displayed_soc = 100*100; } } else { if (calc_ocv(info) < (get_OCV_voltage(info, 8))) { /* fail safe*/ g_full_flag = 0; info->soca->status = RICOH619_SOCA_DISP; info->soca->soc_delta = 0; - } else if (POWER_SUPPLY_STATUS_FULL == info->soca->chg_status) { - if(info->soca->chg_cmp_times >= RICOH619_FULL_WAIT_TIME) { + } else if ((POWER_SUPPLY_STATUS_FULL == info->soca->chg_status) + && (info->soca->displayed_soc >= 9890)){ + if(info->soca->chg_cmp_times > RICOH619_FULL_WAIT_TIME) { info->soca->displayed_soc = 100*100; - info->soca->update_count = 0; g_full_flag = 1; + info->soca->full_reset_count = 0; + info->soca->soc_full = info->soca->soc; + info->soca->fc_cap = 0; #ifdef ENABLE_OCV_TABLE_CALIB err = calib_ocvTable(info,calc_ocv(info)); if (err < 0) @@ -818,31 +1051,56 @@ static void ricoh619_displayed_work(struct work_struct *work) info->soca->chg_cmp_times++; } } else { - info->soca->chg_cmp_times = 0; - if (info->soca->displayed_soc/100 < 99) { - info->soca->update_count++; - if (info->soca->update_count - >= RICOH619_UPDATE_COUNT_FULL) { - info->soca->displayed_soc = info->soca->displayed_soc + 100; - info->soca->update_count = 0; + fa_cap = get_check_fuel_gauge_reg(info, FA_CAP_H_REG, FA_CAP_L_REG, + 0x7fff); + + if (info->soca->displayed_soc >= 9950) { + if((info->soca->soc_full - info->soca->soc) < 200) { + goto end_flow; } - } else { + } + info->soca->chg_cmp_times = 0; + + err = calc_capacity_in_period(info, &cc_cap, &is_charging, true); + if (err < 0) + dev_err(info->dev, "Read cc_sum Error !!-----\n"); + info->soca->cc_delta + = (is_charging == true) ? cc_cap : -cc_cap; + + if((POWER_SUPPLY_STATUS_FULL == info->soca->chg_status) + // || (info->soca->Ibat_ave > 200)) + || (info->soca->Ibat_ave < info->ch_icchg*50 + 100) || (info->soca->displayed_soc<9700)) + { + info->soca->displayed_soc += 13 * 3000 / fa_cap; + } + else { + info->soca->displayed_soc + = info->soca->displayed_soc + info->soca->cc_delta*8/10; + } + + info->soca->displayed_soc + = min(10000, info->soca->displayed_soc); + info->soca->displayed_soc = max(0, info->soca->displayed_soc); + + if (info->soca->displayed_soc >= 9890) { info->soca->displayed_soc = 99 * 100; - info->soca->update_count = 0; } } } } else { - info->soca->update_count = 0; + info->soca->full_reset_count = 0; } } else { /* discharging */ - if (g_full_flag == 1) { + if (info->soca->displayed_soc >= 9950) { if (info->soca->Ibat_ave <= -1 * RICOH619_REL1_SEL_VALUE) { if ((calc_ocv(info) < (get_OCV_voltage(info, 9) + (get_OCV_voltage(info, 10) - get_OCV_voltage(info, 9))*3/10)) - && (info->soca->soc/100 <= 98)) { + || ((info->soca->soc_full - info->soca->soc) > 200)) { + g_full_flag = 0; + info->soca->full_reset_count = 0; info->soca->displayed_soc = 100 * 100; info->soca->status = RICOH619_SOCA_DISP; + info->soca->last_soc = info->soca->soc; info->soca->soc_delta = 0; } else { info->soca->displayed_soc = 100 * 100; @@ -853,8 +1111,10 @@ static void ricoh619_displayed_work(struct work_struct *work) info->soca->displayed_soc = 100 * 100; } else { g_full_flag = 0; + info->soca->full_reset_count = 0; info->soca->displayed_soc = 100 * 100; info->soca->status = RICOH619_SOCA_DISP; + info->soca->last_soc = info->soca->soc; info->soca->soc_delta = 0; } } @@ -862,6 +1122,8 @@ static void ricoh619_displayed_work(struct work_struct *work) g_full_flag = 0; info->soca->status = RICOH619_SOCA_DISP; info->soca->soc_delta = 0; + info->soca->full_reset_count = 0; + info->soca->last_soc = info->soca->soc; } } } else if (RICOH619_SOCA_LOW_VOL == info->soca->status) { @@ -899,8 +1161,8 @@ static void ricoh619_displayed_work(struct work_struct *work) info->soca->soc = calc_capacity_2(info); - soc_round = info->soca->soc / 100; - last_soc_round = info->soca->last_soc / 100; + soc_round = (info->soca->soc + 50) / 100; + last_soc_round = (info->soca->last_soc + 50) / 100; last_disp_round = (info->soca->displayed_soc + 50) / 100; info->soca->soc_delta = @@ -931,7 +1193,7 @@ static void ricoh619_displayed_work(struct work_struct *work) if ((50 <= disp_dec) && (disp_dec <= 74)) info->soca->soc_delta = 0; } - if (info->soca->displayed_soc/100 + if ((info->soca->displayed_soc + 50)/100 >= soc_round) { info->soca->displayed_soc = info->soca->soc ; @@ -945,7 +1207,7 @@ static void ricoh619_displayed_work(struct work_struct *work) info->soca->displayed_soc += 100; info->soca->soc_delta -= 300; } - if (info->soca->displayed_soc/100 + if ((info->soca->displayed_soc + 50)/100 <= soc_round) { info->soca->displayed_soc = info->soca->soc ; @@ -973,7 +1235,7 @@ static void ricoh619_displayed_work(struct work_struct *work) if ((25 <= disp_dec) && (disp_dec <= 49)) info->soca->soc_delta = 0; } - if (info->soca->displayed_soc/100 + if ((info->soca->displayed_soc + 50)/100 <= soc_round) { info->soca->displayed_soc = info->soca->soc ; @@ -987,7 +1249,7 @@ static void ricoh619_displayed_work(struct work_struct *work) info->soca->displayed_soc -= 100; info->soca->soc_delta += 300; } - if (info->soca->displayed_soc/100 + if ((info->soca->displayed_soc + 50)/100 >= soc_round) { info->soca->displayed_soc = info->soca->soc ; @@ -998,6 +1260,50 @@ static void ricoh619_displayed_work(struct work_struct *work) } } } else if (RICOH619_SOCA_UNSTABLE == info->soca->status) { + /* caluc 95% ocv */ + temp_ocv = get_OCV_voltage(info, 10) - + (get_OCV_voltage(info, 10) - get_OCV_voltage(info, 9))/2; + + if(g_full_flag == 1){ /* for issue 1 solution start*/ + info->soca->status = RICOH619_SOCA_FULL; + err = reset_FG_process(info); + if (err < 0) + dev_err(info->dev, "Error in writing the control register\n"); + + goto end_flow; + }else if ((POWER_SUPPLY_STATUS_FULL == info->soca->chg_status) + && (calc_ocv(info) > temp_ocv)) { + info->soca->status = RICOH619_SOCA_FULL; + g_full_flag = 0; + err = reset_FG_process(info); + if (err < 0) + dev_err(info->dev, "Error in writing the control register\n"); + goto end_flow; + } else if (info->soca->Ibat_ave >= -20) { + /* for issue1 solution end */ + /* check Full state or not*/ + if ((calc_ocv(info) > (get_OCV_voltage(info, 9) + (get_OCV_voltage(info, 10) - get_OCV_voltage(info, 9))*7/10)) + || (POWER_SUPPLY_STATUS_FULL == info->soca->chg_status) + || (info->soca->displayed_soc > 9850)) + { + info->soca->status = RICOH619_SOCA_FULL; + g_full_flag = 0; + err = reset_FG_process(info); + if (err < 0) + dev_err(info->dev, "Error in writing the control register\n"); + goto end_flow; + } else if ((calc_ocv(info) > (get_OCV_voltage(info, 9))) + && (info->soca->Ibat_ave < 300)) + { + info->soca->status = RICOH619_SOCA_FULL; + g_full_flag = 0; + err = reset_FG_process(info); + if (err < 0) + dev_err(info->dev, "Error in writing the control register\n"); + goto end_flow; + } + } + err = ricoh619_read(info->dev->parent, PSWR_REG, &val); val &= 0x7f; info->soca->soc = val * 100; @@ -1021,17 +1327,23 @@ static void ricoh619_displayed_work(struct work_struct *work) if (displayed_soc_temp < 0) displayed_soc_temp = 0; displayed_soc_temp - = min(10000, displayed_soc_temp); + = min(9850, displayed_soc_temp); displayed_soc_temp = max(0, displayed_soc_temp); - if (0 == info->soca->jt_limit) { - check_charge_status_2(info, displayed_soc_temp); - } else { - info->soca->displayed_soc = displayed_soc_temp; - } + info->soca->displayed_soc = displayed_soc_temp; + } else if (RICOH619_SOCA_FG_RESET == info->soca->status) { /* No update */ } else if (RICOH619_SOCA_START == info->soca->status) { + + err = measure_Ibatt_FG(info, &Ibat); + err = measure_vbatt_FG(info, &Vbat); + err = measure_vsys_ADC(info, &Vsys); + + info->soca->Ibat_ave = Ibat; + info->soca->Vbat_ave = Vbat; + info->soca->Vsys_ave = Vsys; + err = check_jeita_status(info, &is_jeita_updated); is_jeita_updated = false; if (err < 0) { @@ -1039,15 +1351,6 @@ static void ricoh619_displayed_work(struct work_struct *work) } err = ricoh619_read(info->dev->parent, PSWR_REG, &val); val &= 0x7f; - ////debug for Zero state/// - ret = measure_vbatt_FG(info, &Vbat); - ret = measure_Ibatt_FG(info, &Ibat); - ocv = Vbat - Ibat * info->soca->Rbat; - RICOH_FG_DBG("Check ZERO state : Vbat %d, Ibat %d, ocv %d Rbat %d %d\n",Vbat,Ibat,ocv,info->soca->Rbat); - info->soca->soc = calc_capacity(info) * 100; - RICOH_FG_DBG("Check ZERO state : first_pwon %d, RSOC is %d OCV is %d\n",info->first_pwon,info->soca->soc/100,calc_ocv(info)); - RICOH_FG_DBG("Check ZERO state : g_fg_on_mode %d, get ocv voltage %d\n",g_fg_on_mode,get_OCV_voltage(info, 0)); - /////////////////////////// if (info->first_pwon) { info->soca->soc = calc_capacity(info) * 100; val = (info->soca->soc + 50)/100; @@ -1067,7 +1370,22 @@ static void ricoh619_displayed_work(struct work_struct *work) } else { info->soca->displayed_soc = info->soca->soc; } - info->soca->status = RICOH619_SOCA_UNSTABLE; + if (Ibat < 0) { + if (info->soca->displayed_soc < 300) { + info->soca->target_use_cap = 0; + info->soca->status = RICOH619_SOCA_LOW_VOL; + } else { + if ((info->fg_poff_vbat != 0) + && (Vbat < info->fg_poff_vbat * 1000) ){ + info->soca->target_use_cap = 0; + info->soca->status = RICOH619_SOCA_LOW_VOL; + } else { + info->soca->status = RICOH619_SOCA_UNSTABLE; + } + } + } else { + info->soca->status = RICOH619_SOCA_UNSTABLE; + } } } else if (g_fg_on_mode && (val == 0x7f)) { info->soca->soc = calc_capacity(info) * 100; @@ -1117,30 +1435,67 @@ static void ricoh619_displayed_work(struct work_struct *work) info->soca->displayed_soc = displayed_soc_temp; } info->soca->last_soc = calc_capacity(info) * 100; - info->soca->status = RICOH619_SOCA_UNSTABLE; + if (Ibat < 0) { + if (info->soca->displayed_soc < 300) { + info->soca->target_use_cap = 0; + info->soca->status = RICOH619_SOCA_LOW_VOL; + } else { + if ((info->fg_poff_vbat != 0) + && (Vbat < info->fg_poff_vbat * 1000)){ + info->soca->target_use_cap = 0; + info->soca->status = RICOH619_SOCA_LOW_VOL; + } else { + info->soca->status = RICOH619_SOCA_UNSTABLE; + } + } + } else { + info->soca->status = RICOH619_SOCA_UNSTABLE; + } } } } else if (RICOH619_SOCA_ZERO == info->soca->status) { if (calc_ocv(info) > get_OCV_voltage(info, 0)) { - err = ricoh619_write(info->dev->parent, - FG_CTRL_REG, 0x51); + err = reset_FG_process(info); if (err < 0) dev_err(info->dev, "Error in writing the control register\n"); info->soca->last_soc = calc_capacity_2(info); info->soca->status = RICOH619_SOCA_STABLE; - info->soca->ready_fg = 0; } info->soca->displayed_soc = 0; } end_flow: + /* keep DSOC = 1 when Vbat is over 3.4V*/ + if( info->fg_poff_vbat != 0) { + if (info->soca->zero_flg == 1) { + if(info->soca->Ibat_ave >= 0) { + info->soca->zero_flg = 0; + } + info->soca->displayed_soc = 0; + } else if (info->soca->displayed_soc < 50) { + if (info->soca->Vbat_ave < 2000*1000) { /* error value */ + info->soca->displayed_soc = 100; + } else if (info->soca->Vbat_ave < info->fg_poff_vbat*1000) { + info->soca->displayed_soc = 0; + info->soca->zero_flg = 1; + } else { + info->soca->displayed_soc = 100; + } + } + } + if (g_fg_on_mode && (info->soca->status == RICOH619_SOCA_STABLE)) { err = ricoh619_write(info->dev->parent, PSWR_REG, 0x7f); if (err < 0) dev_err(info->dev, "Error in writing PSWR_REG\n"); g_soc = 0x7F; + err = calc_capacity_in_period(info, &cc_cap, + &is_charging, true); + if (err < 0) + dev_err(info->dev, "Read cc_sum Error !!-----\n"); + } else if (RICOH619_SOCA_UNSTABLE != info->soca->status) { - if (info->soca->displayed_soc <= 0) { + if ((info->soca->displayed_soc + 50) / 100 <= 1) { val = 1; } else { val = (info->soca->displayed_soc + 50)/100; @@ -1206,10 +1561,13 @@ end_flow: RICOH619_DISPLAY_UPDATE_TIME * HZ); mutex_unlock(&info->lock); - - if(true == is_jeita_updated) + + if((true == is_jeita_updated) + || (info->soca->last_displayed_soc/100 != (info->soca->displayed_soc+50)/100)) power_supply_changed(&info->battery); + info->soca->last_displayed_soc = info->soca->displayed_soc+50; + return; } @@ -1232,11 +1590,9 @@ static void ricoh619_stable_charge_countdown_work(struct work_struct *work) if (2 <= info->soca->stable_count) { if (3 == info->soca->stable_count && RICOH619_SOCA_FG_RESET == info->soca->status) { - ret = ricoh619_write(info->dev->parent, - FG_CTRL_REG, 0x51); + ret = reset_FG_process(info); if (ret < 0) dev_err(info->dev, "Error in writing the control register\n"); - info->soca->ready_fg = 0; } info->soca->stable_count = info->soca->stable_count - 1; queue_delayed_work(info->monitor_wqueue, @@ -1256,12 +1612,10 @@ static void ricoh619_stable_charge_countdown_work(struct work_struct *work) return; } /* Do reset setting */ - ret = ricoh619_write(info->dev->parent, - FG_CTRL_REG, 0x51); + ret = reset_FG_process(info); if (ret < 0) dev_err(info->dev, "Error in writing the control register\n"); - info->soca->ready_fg = 0; info->soca->status = RICOH619_SOCA_FG_RESET; /* Delay for addition Reset Time (6s) */ @@ -1296,13 +1650,10 @@ static void ricoh619_stable_charge_countdown_work(struct work_struct *work) goto adjust; } else { /* Do reset setting */ - ret = ricoh619_write(info->dev->parent, - FG_CTRL_REG, 0x51); + ret = reset_FG_process(info); if (ret < 0) dev_err(info->dev, "Error in writing the control register\n"); - info->soca->ready_fg = 0; - /* Delay for addition Reset Time (6s) */ queue_delayed_work(info->monitor_wqueue, &info->charge_stable_work, @@ -1463,6 +1814,8 @@ static int ricoh619_init_fgsoca(struct ricoh619_battery_info *info) int i; int err; uint8_t val; + int cc_cap = 0; + bool is_charging = true; for (i = 0; i <= 10; i = i+1) { info->soca->ocv_table[i] = get_OCV_voltage(info, i); @@ -1494,6 +1847,8 @@ static int ricoh619_init_fgsoca(struct ricoh619_battery_info *info) dev_err(info->dev, "Error in writing the control register\n"); } + err = calc_capacity_in_period(info, &cc_cap, &is_charging, true); + msleep(6000); err = ricoh619_write(info->dev->parent, CHGISET_REG, val); @@ -1507,20 +1862,22 @@ static int ricoh619_init_fgsoca(struct ricoh619_battery_info *info) * 5000 / 4095; info->soca->n_cap = get_OCV_init_Data(info, 11); - info->soca->f_chg_margin = (get_OCV_voltage(info, 10) - - get_OCV_voltage(info, 9)) / 10; info->soca->displayed_soc = 0; + info->soca->last_displayed_soc = 0; info->soca->suspend_soc = 0; info->soca->ready_fg = 0; info->soca->soc_delta = 0; - info->soca->update_count = 0; + info->soca->full_reset_count = 0; + info->soca->soc_full = 0; + info->soca->fc_cap = 0; info->soca->status = RICOH619_SOCA_START; /* stable count down 11->2, 1: reset; 0: Finished; */ info->soca->stable_count = 11; info->soca->chg_cmp_times = 0; info->soca->dischg_state = 0; info->soca->Vbat_ave = 0; + info->soca->Vbat_old = 0; info->soca->Vsys_ave = 0; info->soca->Ibat_ave = 0; info->soca->chg_count = 0; @@ -1528,13 +1885,19 @@ static int ricoh619_init_fgsoca(struct ricoh619_battery_info *info) info->soca->hurry_up_flg = 0; info->soca->re_cap_old = 0; info->soca->jt_limit = 0; + info->soca->zero_flg = 0; + info->soca->cc_cap_offset = 0; + + for (i = 0; i < 11; i++) { + info->soca->ocv_table_low[i] = 0; + } for (i = 0; i < RICOH619_GET_CHARGE_NUM; i++) { info->soca->Vbat[i] = 0; info->soca->Vsys[i] = 0; info->soca->Ibat[i] = 0; } - + g_full_flag = 0; #ifdef ENABLE_FG_KEEP_ON_MODE @@ -1617,7 +1980,6 @@ static int check_jeita_status(struct ricoh619_battery_info *info, bool *is_jeita { int temp; int err = 0; - uint8_t val; int vfchg; uint8_t chgiset_org; uint8_t batset2_org; @@ -1727,6 +2089,7 @@ static int check_jeita_status(struct ricoh619_battery_info *info, bool *is_jeita goto out; } info->soca->jt_limit = 0; + *is_jeita_updated = true; } else RICOH_FG_DBG(KERN_INFO "PMU: %s *** 12jt_vfchg_h); @@ -1914,7 +2277,6 @@ static int Calc_Linear_Interpolation(int x0, int y0, int x1, int y1, int y) static void ricoh619_scaling_OCV_table(struct ricoh619_battery_info *info, int cutoff_vol, int full_vol, int *start_per, int *end_per) { - int ret = 0; int i, j; int temp; int percent_step; @@ -1930,13 +2292,18 @@ static void ricoh619_scaling_OCV_table(struct ricoh619_battery_info *info, int c // __func__, cutoff_vol,full_vol); /* Check Start % */ - for (i = 1; i < 11; i++) { - if (info->soca->ocv_table_def[i] >= cutoff_vol * 1000) { - /* unit is 0.001% */ - *start_per = Calc_Linear_Interpolation( - (i-1)*1000, info->soca->ocv_table_def[i-1], i*1000, - info->soca->ocv_table_def[i], (cutoff_vol * 1000)); - i = 11; + if (info->soca->ocv_table_def[0] > cutoff_vol * 1000) { + *start_per = 0; + RICOH_FG_DBG("PMU : %s : setting value of cuttoff_vol(%d) is out of range(%d) \n",__func__, cutoff_vol, info->soca->ocv_table_def[0]); + } else { + for (i = 1; i < 11; i++) { + if (info->soca->ocv_table_def[i] >= cutoff_vol * 1000) { + /* unit is 0.001% */ + *start_per = Calc_Linear_Interpolation( + (i-1)*1000, info->soca->ocv_table_def[i-1], i*1000, + info->soca->ocv_table_def[i], (cutoff_vol * 1000)); + break; + } } } @@ -1947,7 +2314,7 @@ static void ricoh619_scaling_OCV_table(struct ricoh619_battery_info *info, int c *end_per = Calc_Linear_Interpolation( (i-1)*1000, info->soca->ocv_table_def[i-1], i*1000, info->soca->ocv_table_def[i], (full_vol * 1000)); - i = 11; + break; } } @@ -1974,7 +2341,7 @@ static void ricoh619_scaling_OCV_table(struct ricoh619_battery_info *info, int c battery_init_para[info->num][i*2 + 1] = temp; battery_init_para[info->num][i*2] = temp >> 8; - j = 11; + break; } } } @@ -1992,20 +2359,14 @@ static void ricoh619_scaling_OCV_table(struct ricoh619_battery_info *info, int c static int ricoh619_set_OCV_table(struct ricoh619_battery_info *info) { int ret = 0; - int OCV_set_table[11]; - int i, j; + int i; int full_ocv; int available_cap; int available_cap_ori; - int OCV_100_def; - int OCV_0_def; - int OCV_100_diff; - int OCV_0_diff; int temp; - int start_per; - int end_per; - int percent_step; - int OCV_percent_new[11]; + int temp1; + int start_per = 0; + int end_per = 0; int Rbat; int Ibat_min; uint8_t val; @@ -2020,19 +2381,42 @@ static int ricoh619_set_OCV_table(struct ricoh619_battery_info *info) __func__, i, info->soca->ocv_table_def[i]); } - info->soca->target_vsys = info->fg_target_vsys; - info->soca->target_ibat = info->fg_target_ibat; + temp = (battery_init_para[info->num][24]<<8) | (battery_init_para[info->num][25]); + Rbat = temp * 1000 / 512 * 5000 / 4095; + info->soca->Rsys = Rbat + 55; + + if ((info->fg_target_ibat == 0) || (info->fg_target_vsys == 0)) { /* normal version */ + + temp = (battery_init_para[info->num][22]<<8) | (battery_init_para[info->num][23]); + //fa_cap = get_check_fuel_gauge_reg(info, FA_CAP_H_REG, FA_CAP_L_REG, + // 0x7fff); + + info->soca->target_ibat = temp*2/10; /* calc 0.2C*/ + temp1 = (battery_init_para[info->num][0]<<8) | (battery_init_para[info->num][1]); + + info->soca->target_vsys = temp1 + ( info->soca->target_ibat * info->soca->Rsys ) / 1000; + + + } else { + info->soca->target_ibat = info->fg_target_ibat; + /* calc min vsys value */ + temp1 = (battery_init_para[info->num][0]<<8) | (battery_init_para[info->num][1]); + temp = temp1 + ( info->soca->target_ibat * info->soca->Rsys ) / 1000; + if( temp < info->fg_target_vsys) { + info->soca->target_vsys = info->fg_target_vsys; + } else { + info->soca->target_vsys = temp; + RICOH_FG_DBG("PMU : %s : setting value of target vsys(%d) is out of range(%d)\n",__func__, info->fg_target_vsys, temp); + } + } //for debug RICOH_FG_DBG("PMU : %s : target_vsys is %d target_ibat is %d\n",__func__,info->soca->target_vsys,info->soca->target_ibat); if ((info->soca->target_ibat == 0) || (info->soca->target_vsys == 0)) { /* normal version */ } else { /*Slice cutoff voltage version. */ - temp = (battery_init_para[info->num][24]<<8) | (battery_init_para[info->num][25]); - Rbat = temp * 1000 / 512 * 5000 / 4095; Ibat_min = -1 * info->soca->target_ibat; - info->soca->Rsys = Rbat + 55; info->soca->cutoff_ocv = info->soca->target_vsys - Ibat_min * info->soca->Rsys / 1000; full_ocv = (battery_init_para[info->num][20]<<8) | (battery_init_para[info->num][21]); @@ -2059,58 +2443,6 @@ static int ricoh619_set_OCV_table(struct ricoh619_battery_info *info) dev_err(info->dev, "error in FG_En off\n"); goto err; } - //////////////////////////////// - //////////////////////////////// - //check OCV calibration or not - /* get ocv table from setting */ - for (i = 0; i < 11; i++){ - ret = ricoh619_read_bank1(info->dev->parent, (0xBC + i*2), &val); - if (ret < 0) { - dev_err(info->dev, "batterry initialize error\n"); - return ret; - } - ret = ricoh619_read_bank1(info->dev->parent, (0xBD + i*2), &val2); - if (ret < 0) { - dev_err(info->dev, "batterry initialize error\n"); - return ret; - } - val &= 0x0F; - OCV_set_table[i] = val2 + (val << 8); - RICOH_FG_DBG("PMU : %s : no %d OCV_set_table %x\n", __func__, i, OCV_set_table[i]); - - } - - OCV_100_def = (battery_init_para[info->num][20]<<8) - | (battery_init_para[info->num][21]); - - OCV_0_def = (battery_init_para[info->num][0]<<8) - | (battery_init_para[info->num][1]); - - if(OCV_100_def < OCV_set_table[10]) { - OCV_100_diff = OCV_set_table[10] - OCV_100_def; - } else { - OCV_100_diff = OCV_100_def - OCV_set_table[10]; - } - - if(OCV_0_def < OCV_set_table[0]) { - OCV_0_diff = OCV_set_table[0] - OCV_0_def; - } else { - OCV_0_diff = OCV_0_def - OCV_set_table[0]; - } - RICOH_FG_DBG("PMU : %s : def OCV 100 %x OCV 0 %x \n", __func__, OCV_100_def, OCV_0_def); - RICOH_FG_DBG("PMU : %s : OCV 100 %x OCV 0 %x \n", __func__, OCV_set_table[10], OCV_set_table[0]); - RICOH_FG_DBG("PMU : %s : diff OCV 100 %x OCV 0 %x \n", __func__, OCV_100_diff, OCV_0_diff); - - if ( (OCV_100_diff > 5) - &&(OCV_0_diff < 5)) - {/* keep setting OCV table */ - for (i = 0; i < 11; i++) { - RICOH_FG_DBG("PMU : 1\n"); - battery_init_para[info->num][i*2+1] = OCV_set_table[i]; - battery_init_para[info->num][i*2] = OCV_set_table[i] >> 8; - } - } - ///////////////////////////////// ret = ricoh619_read_bank1(info->dev->parent, 0xDC, &val); if (ret < 0) { @@ -2175,7 +2507,7 @@ static int ricoh619_set_OCV_table(struct ricoh619_battery_info *info) } for (i = 0; i < 6; i++) { - ret = ricoh619_write_bank1(info->dev->parent, 0xD4+i, battery_init_para[info->num][23+i]); + ret = ricoh619_write_bank1(info->dev->parent, 0xD4+i, battery_init_para[info->num][24+i]); if (ret < 0) { dev_err(info->dev, "batterry initialize error\n"); return ret; @@ -2208,13 +2540,13 @@ static int ricoh619_init_battery(struct ricoh619_battery_info *info) /* -------------------------- */ #ifdef ENABLE_FUEL_GAUGE_FUNCTION - /* set kanwa state */ + /* set relaxation state */ if (RICOH619_REL1_SEL_VALUE > 240) val = 0x0F; else val = RICOH619_REL1_SEL_VALUE / 16 ; - /* set kanwa state */ + /* set relaxation state */ if (RICOH619_REL2_SEL_VALUE > 120) val2 = 0x0F; else @@ -2286,7 +2618,6 @@ static int ricoh619_init_battery(struct ricoh619_battery_info *info) static int ricoh619_init_charger(struct ricoh619_battery_info *info) { int err; - int i; uint8_t val; uint8_t val2; uint8_t val3; @@ -2394,7 +2725,7 @@ static int ricoh619_init_charger(struct ricoh619_battery_info *info) if ((info->ch_icchg != 0xFF) || (info->ch_icchg <= 0x03)) { val3 = info->ch_icchg << 6; } else { /* Keep OTP value */ - val3 = (val & 0xC); + val3 = (val & 0xC0); } val = val2 + val3; @@ -2700,6 +3031,47 @@ static int get_power_supply_status(struct ricoh619_battery_info *info) return info->soca->chg_status; } +static int get_power_supply_Android_status(struct ricoh619_battery_info *info) +{ + + get_power_supply_status(info); + + /* get power supply status */ + if (info->entry_factory_mode) + return POWER_SUPPLY_STATUS_NOT_CHARGING; + + switch (info->soca->chg_status) { + case POWER_SUPPLY_STATUS_UNKNOWN: + return POWER_SUPPLY_STATUS_UNKNOWN; + break; + + case POWER_SUPPLY_STATUS_NOT_CHARGING: + return POWER_SUPPLY_STATUS_NOT_CHARGING; + break; + + case POWER_SUPPLY_STATUS_DISCHARGING: + return POWER_SUPPLY_STATUS_DISCHARGING; + break; + + case POWER_SUPPLY_STATUS_CHARGING: + return POWER_SUPPLY_STATUS_CHARGING; + break; + + case POWER_SUPPLY_STATUS_FULL: + if(info->soca->displayed_soc == 100 * 100) { + return POWER_SUPPLY_STATUS_FULL; + } else { + return POWER_SUPPLY_STATUS_CHARGING; + } + break; + default: + return POWER_SUPPLY_STATUS_UNKNOWN; + break; + } + + return POWER_SUPPLY_STATUS_UNKNOWN; +} + static void charger_irq_work(struct work_struct *work) { struct ricoh619_battery_info *info @@ -2709,8 +3081,10 @@ static void charger_irq_work(struct work_struct *work) RICOH_FG_DBG("PMU:%s In\n", __func__); power_supply_changed(&info->battery); + power_supply_changed(&powerac); + power_supply_changed(&powerusb); - mutex_lock(&info->lock); +// mutex_lock(&info->lock); if (info->chg_stat1 & 0x01) { ricoh619_read(info->dev->parent, CHGSTATE_REG, ®_val); @@ -2741,7 +3115,7 @@ static void charger_irq_work(struct work_struct *work) "%s(): Error in enable charger mask INT %d\n", __func__, ret); - mutex_unlock(&info->lock); +// mutex_unlock(&info->lock); RICOH_FG_DBG("PMU:%s Out\n", __func__); } @@ -2771,14 +3145,16 @@ static void ricoh619_usb_charge_det(void) { struct ricoh619 *ricoh619 = g_ricoh619; ricoh619_set_bits(ricoh619->dev,REGISET2_REG,(1 << 7)); //set usb limit current when SDP or other mode - if(2 == dwc_vbus_status()){ + if(2 == dwc_otg_check_dpdm(0)){ ricoh619_write(ricoh619->dev,REGISET2_REG,0x13); //set usb limit current 2A ricoh619_write(ricoh619->dev,CHGISET_REG,0xD3); //set charge current 2A } - else if(1 == dwc_vbus_status()){ + else { ricoh619_write(ricoh619->dev,REGISET2_REG,0x04); //set usb limit current 500ma ricoh619_write(ricoh619->dev,CHGISET_REG,0xC4); //set charge current 500ma } + power_supply_changed(&powerac); + power_supply_changed(&powerusb); } static void usb_det_irq_work(struct work_struct *work) @@ -2787,11 +3163,12 @@ static void usb_det_irq_work(struct work_struct *work) struct ricoh619_battery_info, usb_irq_work); int ret = 0; uint8_t sts; - int time =0; RICOH_FG_DBG("PMU:%s In\n", __func__); power_supply_changed(&info->battery); + power_supply_changed(&powerac); + power_supply_changed(&powerusb); mutex_lock(&info->lock); @@ -2810,13 +3187,7 @@ static void usb_det_irq_work(struct work_struct *work) sts &= 0x02; if (sts) { - //time = 60; - //do { - //ricoh619_usb_charge_det(); - //time --; - //mdelay(1000); - //}while(time >0); - + ricoh619_usb_charge_det(); } else { /*********************/ /* No process ?? */ @@ -2826,18 +3197,16 @@ static void usb_det_irq_work(struct work_struct *work) RICOH_FG_DBG("PMU:%s Out\n", __func__); } -extern void rk28_send_wakeup_key(void); +extern void rk_send_wakeup_key(void); static irqreturn_t charger_in_isr(int irq, void *battery_info) { struct ricoh619_battery_info *info = battery_info; - struct ricoh619 *ricoh619 = g_ricoh619; - RICOH_FG_DBG("PMU:%s\n", __func__); info->chg_stat1 |= 0x01; queue_work(info->workqueue, &info->irq_work); -// rk28_send_wakeup_key(); +// rk_send_wakeup_key(); return IRQ_HANDLED; } @@ -2849,7 +3218,7 @@ static irqreturn_t charger_complete_isr(int irq, void *battery_info) info->chg_stat1 |= 0x02; queue_work(info->workqueue, &info->irq_work); - rk28_send_wakeup_key(); +// rk_send_wakeup_key(); return IRQ_HANDLED; } @@ -2867,7 +3236,7 @@ static irqreturn_t charger_usb_isr(int irq, void *battery_info) info->soca->chg_count = 0; // queue_work(info->usb_workqueue, &info->usb_irq_work); -// rk28_send_wakeup_key(); + rk_send_wakeup_key(); if (RICOH619_SOCA_UNSTABLE == info->soca->status || RICOH619_SOCA_FG_RESET == info->soca->status) @@ -2879,12 +3248,11 @@ static irqreturn_t charger_usb_isr(int irq, void *battery_info) static irqreturn_t charger_adp_isr(int irq, void *battery_info) { struct ricoh619_battery_info *info = battery_info; - struct ricoh619 *ricoh619 = g_ricoh619; RICOH_FG_DBG("PMU:%s\n", __func__); info->chg_ctr |= 0x01; queue_work(info->workqueue, &info->irq_work); - rk28_send_wakeup_key(); + rk_send_wakeup_key(); info->soca->dischg_state = 0; info->soca->chg_count = 0; @@ -2916,7 +3284,7 @@ static irqreturn_t adc_vsysl_isr(int irq, void *battery_info) RICOH_FG_DBG("PMU:%s\n", __func__); // ricoh619_write(info->dev->parent, RICOH619_INT_EN_ADC1, 0x10); -// rk28_send_wakeup_key(); + rk_send_wakeup_key(); return IRQ_HANDLED; } @@ -2929,6 +3297,7 @@ static irqreturn_t adc_vsysl_isr(int irq, void *battery_info) * true : VUSB * false: VADP */ + /* static int get_charge_priority(struct ricoh619_battery_info *info, bool *data) { int ret = 0; @@ -2940,6 +3309,7 @@ static int get_charge_priority(struct ricoh619_battery_info *info, bool *data) return ret; } +*/ /* * Set Charger Priority @@ -2948,18 +3318,20 @@ static int get_charge_priority(struct ricoh619_battery_info *info, bool *data) * true : VUSB * false: VADP */ + /* static int set_charge_priority(struct ricoh619_battery_info *info, bool *data) { int ret = 0; - uint8_t val = 0; + uint8_t val = 0x80; - val = *data << 7; - val &= 0x80; + if (*data == 1) + ret = ricoh619_set_bits(info->dev->parent, CHGCTL1_REG, val); + else + ret = ricoh619_clr_bits(info->dev->parent, CHGCTL1_REG, val); - ret = ricoh619_set_bits(info->dev->parent, CHGCTL1_REG, val); return ret; } - +*/ #ifdef ENABLE_FUEL_GAUGE_FUNCTION static int get_check_fuel_gauge_reg(struct ricoh619_battery_info *info, int Reg_h, int Reg_l, int enable_bit) @@ -3023,6 +3395,9 @@ static int calc_capacity(struct ricoh619_battery_info *info) temp = capacity * 100 * 100 / (10000 - nt); + temp = min(100, temp); + temp = max(0, temp); + return temp; /* Unit is 1% */ } @@ -3052,9 +3427,9 @@ static int calc_capacity_2(struct ricoh619_battery_info *info) 0x7fff); if (fa_cap != 0) { - capacity = ((long)re_cap * 100 * 100 / fa_cap) + 50; - capacity = min(10000, capacity); - capacity = max(0, capacity); + capacity = ((long)re_cap * 100 * 100 / fa_cap); + capacity = (long)(min(10000, (int)capacity)); + capacity = (long)(max(0, (int)capacity)); } else { ret = ricoh619_read(info->dev->parent, SOC_REG, &val); if (ret < 0) { @@ -3067,6 +3442,9 @@ static int calc_capacity_2(struct ricoh619_battery_info *info) temp = (int)(capacity * 100 * 100 / (10000 - nt)); + temp = min(10000, temp); + temp = max(0, temp); + return temp; /* Unit is 0.01% */ } @@ -3274,18 +3652,23 @@ static int measure_vbatt_FG(struct ricoh619_battery_info *info, int *data) { int ret = 0; - ret = get_check_fuel_gauge_reg(info, VOLTAGE_1_REG, VOLTAGE_2_REG, - 0x0fff); - if (ret < 0) { - dev_err(info->dev, "Error in reading the fuel gauge control register\n"); - return ret; - } + if(info->soca->ready_fg == 1) { + ret = get_check_fuel_gauge_reg(info, VOLTAGE_1_REG, VOLTAGE_2_REG, + 0x0fff); + if (ret < 0) { + dev_err(info->dev, "Error in reading the fuel gauge control register\n"); + return ret; + } - *data = ret; - /* conversion unit 1 Unit is 1.22mv (5000/4095 mv) */ - *data = *data * 50000 / 4095; - /* return unit should be 1uV */ - *data = *data * 100; + *data = ret; + /* conversion unit 1 Unit is 1.22mv (5000/4095 mv) */ + *data = *data * 50000 / 4095; + /* return unit should be 1uV */ + *data = *data * 100; + info->soca->Vbat_old = *data; + } else { + *data = info->soca->Vbat_old; + } return ret; } @@ -3441,7 +3824,7 @@ static int ricoh619_batt_get_prop(struct power_supply *psy, mutex_lock(&info->lock); switch (psp) { -#if 0 + case POWER_SUPPLY_PROP_ONLINE: ret = ricoh619_read(info->dev->parent, CHGSTATE_REG, &status); if (ret < 0) { @@ -3454,10 +3837,9 @@ static int ricoh619_batt_get_prop(struct power_supply *psy, else if (psy->type == POWER_SUPPLY_TYPE_USB) val->intval = (status & 0x80 ? 1 : 0); break; -#endif /* this setting is same as battery driver of 584 */ case POWER_SUPPLY_PROP_STATUS: - ret = get_power_supply_status(info); + ret = get_power_supply_Android_status(info); val->intval = ret; info->status = ret; /* RICOH_FG_DBG("Power Supply Status is %d\n", @@ -3478,7 +3860,7 @@ static int ricoh619_batt_get_prop(struct power_supply *psy, else { //val->intval = -EINVAL; data = info->cur_voltage * 1000; - /* RICOH_FG_DBG( "battery voltage is not ready\n"); */ + RICOH_FG_DBG( "battery voltage is not ready\n"); } #else ret = measure_vbatt_ADC(info, &data); @@ -3498,14 +3880,14 @@ static int ricoh619_batt_get_prop(struct power_supply *psy, val->intval = 100; info->capacity = 100; } else if (info->soca->displayed_soc <= 0) { - val->intval = 0; - info->capacity = 0; + val->intval = 10; + info->capacity = 10; } else { val->intval = (info->soca->displayed_soc + 50)/100; info->capacity = (info->soca->displayed_soc + 50)/100; } - /* RICOH_FG_DBG("battery capacity is %d%%\n", - info->capacity); */ + RICOH_FG_DBG("battery capacity is %d%%\n", + info->capacity); break; /* current temperature of battery */ @@ -3608,58 +3990,152 @@ struct power_supply powerusb = { .get_property = ricoh619_batt_get_prop, }; -static __devinit int ricoh619_battery_probe(struct platform_device *pdev) +#ifdef CONFIG_OF +static struct ricoh619_battery_platform_data * +ricoh619_battery_dt_init(struct platform_device *pdev) +{ + struct device_node *nproot = pdev->dev.parent->of_node; + struct device_node *np; + struct ricoh619_battery_platform_data *pdata; + int temp; + + if (!nproot) + return pdev->dev.platform_data; + + np = of_find_node_by_name(nproot, "battery"); + if (!np) { + dev_err(&pdev->dev, "failed to find battery node\n"); + return NULL; + } + + pdata = devm_kzalloc(&pdev->dev, + sizeof(struct ricoh619_battery_platform_data), + GFP_KERNEL); + + of_property_read_u32(np, "ricoh,monitor-time", &pdata->monitor_time); + of_property_read_u32(np, "ricoh,alarm-vol-mv", &pdata->alarm_vol_mv); + + /* check rage of b,.attery type */ + type_n = Battery_Type(); + RICOH_FG_DBG("%s type_n=%d,temp is %d\n", __func__, type_n,temp); + + switch (type_n) { + case (0): + of_property_read_u32(np, "ricoh,ch-vfchg", &pdata->type[0].ch_vfchg); + of_property_read_u32(np, "ricoh,ch-vrchg", &pdata->type[0].ch_vrchg); + of_property_read_u32(np, "ricoh,ch-vbatovset", &pdata->type[0].ch_vbatovset); + of_property_read_u32(np, "ricoh,ch-ichg", &pdata->type[0].ch_ichg); + of_property_read_u32(np, "ricoh,ch-ilim-adp", &pdata->type[0].ch_ilim_adp); + of_property_read_u32(np, "ricoh,ch-ilim-usb", &pdata->type[0].ch_ilim_usb); + of_property_read_u32(np, "ricoh,ch-icchg", &pdata->type[0].ch_icchg); + of_property_read_u32(np, "ricoh,fg-target-vsys", &pdata->type[0].fg_target_vsys); + of_property_read_u32(np, "ricoh,fg-target-ibat", &pdata->type[0].fg_target_ibat); + of_property_read_u32(np, "ricoh,fg-poff-vbat", &pdata->type[0].fg_poff_vbat); + of_property_read_u32(np, "ricoh,jt-en", &pdata->type[0].jt_en); + of_property_read_u32(np, "ricoh,jt-hw-sw", &pdata->type[0].jt_hw_sw); + of_property_read_u32(np, "ricoh,jt-temp-h", &pdata->type[0].jt_temp_h); + of_property_read_u32(np, "ricoh,jt-temp-l", &pdata->type[0].jt_temp_l); + of_property_read_u32(np, "ricoh,jt-vfchg-h", &pdata->type[0].jt_vfchg_h); + of_property_read_u32(np, "ricoh,jt-vfchg-l", &pdata->type[0].jt_vfchg_l); + of_property_read_u32(np, "ricoh,jt-ichg-h", &pdata->type[0].jt_ichg_h); + of_property_read_u32(np, "ricoh,jt-ichg-l", &pdata->type[0].jt_ichg_l); + break; +#if 0 + case (1): + of_property_read_u32(np, "ricoh,ch-vfchg-1", &pdata->type[1].ch_vfchg); + of_property_read_u32(np, "ricoh,ch-vrchg-1", &pdata->type[1].ch_vrchg); + of_property_read_u32(np, "ricoh,ch-vbatovset-1", &pdata->type[1].ch_vbatovset); + of_property_read_u32(np, "ricoh,ch-ichg-1", &pdata->type[1].ch_ichg); + of_property_read_u32(np, "ricoh,ch-ilim-adp-1", &pdata->type[1].ch_ilim_adp); + of_property_read_u32(np, "ricoh,ch-ilim-usb-1", &pdata->type[1].ch_ilim_usb); + of_property_read_u32(np, "ricoh,ch-icchg-1", &pdata->type[1].ch_icchg); + of_property_read_u32(np, "ricoh,fg-target-vsys-1", &pdata->type[1].fg_target_vsys); + of_property_read_u32(np, "ricoh,fg-target-ibat-1", &pdata->type[1].fg_target_ibat); + of_property_read_u32(np, "ricoh,fg-poff-vbat-1", &pdata->type[1].fg_poff_vbat); + of_property_read_u32(np, "ricoh,jt-en-1", &pdata->type[1].jt_en); + of_property_read_u32(np, "ricoh,jt-hw-sw-1", &pdata->type[1].jt_hw_sw); + of_property_read_u32(np, "ricoh,jt-temp-h-1", &pdata->type[1].jt_temp_h); + of_property_read_u32(np, "ricoh,jt-temp-l-1", &pdata->type[1].jt_temp_l); + of_property_read_u32(np, "ricoh,jt-vfchg-h-1", &pdata->type[1].jt_vfchg_h); + of_property_read_u32(np, "ricoh,jt-vfchg-l-1", &pdata->type[1].jt_vfchg_l); + of_property_read_u32(np, "ricoh,jt-ichg-h-1", &pdata->type[1].jt_ichg_h); + of_property_read_u32(np, "ricoh,jt-ichg-l-1", &pdata->type[1].jt_ichg_l); + break; +#endif + default: + of_node_put(np); + return 0; + } + + of_node_put(np); + + return pdata; +} +#else +static struct ricoh619_battery_platform_data * +ricoh619_battery_dt_init(struct platform_device *pdev) +{ + return pdev->dev.platform_data; +} +#endif + +static int ricoh619_battery_probe(struct platform_device *pdev) { struct ricoh619_battery_info *info; struct ricoh619_battery_platform_data *pdata; - int type_n; + struct ricoh619 *ricoh619 = dev_get_drvdata(pdev->dev.parent); int ret, temp; - RICOH_FG_DBG("PMU:2013.8.3 %s\n", __func__); - - info = kzalloc(sizeof(struct ricoh619_battery_info), GFP_KERNEL); + RICOH_FG_DBG(KERN_INFO "PMU: %s : version is %s\n", __func__,RICOH619_BATTERY_VERSION); + + pdata = ricoh619_battery_dt_init(pdev); + if (!pdata) { + dev_err(&pdev->dev, "platform data isn't assigned to " + "power supply\n"); + return -EINVAL; + } + info = devm_kzalloc(ricoh619->dev,sizeof(struct ricoh619_battery_info), GFP_KERNEL); if (!info) return -ENOMEM; - info->soca = kzalloc(sizeof(struct ricoh619_soca_info), GFP_KERNEL); + info->soca = devm_kzalloc(ricoh619->dev,sizeof(struct ricoh619_soca_info), GFP_KERNEL); if (!info->soca) return -ENOMEM; info->dev = &pdev->dev; info->status = POWER_SUPPLY_STATUS_CHARGING; - pdata = pdev->dev.platform_data; info->monitor_time = pdata->monitor_time * HZ; info->alarm_vol_mv = pdata->alarm_vol_mv; - type_n = Battery_Type(); + /* check rage of battery num */ info->num = Battery_Table(); temp = sizeof(battery_init_para)/(sizeof(uint8_t)*32); - RICOH_FG_DBG("%s temp=%d\n", __func__, temp); if(info->num >= (sizeof(battery_init_para)/(sizeof(uint8_t)*32))) - info->num = 0; - RICOH_FG_DBG("%s type_n=%d\n", __func__, type_n); - RICOH_FG_DBG("%s info->num=%d\n", __func__, info->num); - /* these valuse are set in platform */ - if (type_n == 0) { - info->ch_vfchg = pdata->ch_vfchg; - info->ch_vrchg = pdata->ch_vrchg; - info->ch_vbatovset = pdata->ch_vbatovset; - info->ch_ichg = pdata->ch_ichg; - info->ch_ilim_adp = pdata->ch_ilim_adp; - info->ch_ilim_usb = pdata->ch_ilim_usb; - info->ch_icchg = pdata->ch_icchg; - info->fg_target_vsys = pdata->fg_target_vsys; - info->fg_target_ibat = pdata->fg_target_ibat; - info->jt_en = pdata->jt_en; - info->jt_hw_sw = pdata->jt_hw_sw; - info->jt_temp_h = pdata->jt_temp_h; - info->jt_temp_l = pdata->jt_temp_l; - info->jt_vfchg_h = pdata->jt_vfchg_h; - info->jt_vfchg_l = pdata->jt_vfchg_l; - info->jt_ichg_h = pdata->jt_ichg_h; - info->jt_ichg_l = pdata->jt_ichg_l; - } else { + RICOH_FG_DBG("%s : Battery num is out of range\n", __func__); + info->num = 0; } + RICOH_FG_DBG("%s info->num=%d,temp is %d\n", __func__, info->num,temp); + + /* these valuse are set in platform */ + info->ch_vfchg = pdata->type[type_n].ch_vfchg; + info->ch_vrchg = pdata->type[type_n].ch_vrchg; + info->ch_vbatovset = pdata->type[type_n].ch_vbatovset; + info->ch_ichg = pdata->type[type_n].ch_ichg; + info->ch_ilim_adp = pdata->type[type_n].ch_ilim_adp; + info->ch_ilim_usb = pdata->type[type_n].ch_ilim_usb; + info->ch_icchg = pdata->type[type_n].ch_icchg; + info->fg_target_vsys = pdata->type[type_n].fg_target_vsys; + info->fg_target_ibat = pdata->type[type_n].fg_target_ibat; + info->fg_poff_vbat = pdata->type[type_n].fg_poff_vbat; + info->jt_en = pdata->type[type_n].jt_en; + info->jt_hw_sw = pdata->type[type_n].jt_hw_sw; + info->jt_temp_h = pdata->type[type_n].jt_temp_h; + info->jt_temp_l = pdata->type[type_n].jt_temp_l; + info->jt_vfchg_h = pdata->type[type_n].jt_vfchg_h; + info->jt_vfchg_l = pdata->type[type_n].jt_vfchg_l; + info->jt_ichg_h = pdata->type[type_n].jt_ichg_h; + info->jt_ichg_l = pdata->type[type_n].jt_ichg_l; + info->adc_vdd_mv = ADC_VDD_MV; /* 2800; */ info->min_voltage = MIN_VOLTAGE; /* 3100; */ info->max_voltage = MAX_VOLTAGE; /* 4200; */ @@ -3681,28 +4157,28 @@ static __devinit int ricoh619_battery_probe(struct platform_device *pdev) /* Disable Charger/ADC interrupt */ ret = ricoh619_clr_bits(info->dev->parent, RICOH619_INTC_INTEN, CHG_INT | ADC_INT); - if (ret) + if (ret<0) goto out; ret = ricoh619_init_battery(info); - if (ret) + if (ret<0) goto out; - +/* #ifdef ENABLE_FACTORY_MODE info->factory_mode_wqueue = create_singlethread_workqueue("ricoh619_factory_mode"); - INIT_DELAYED_WORK_DEFERRABLE(&info->factory_mode_work, + INIT_DEFERRABLE_WORK(&info->factory_mode_work, check_charging_state_work); ret = ricoh619_factory_mode(info); - if (ret) + if (ret<0) goto out; #endif - +*/ ret = power_supply_register(&pdev->dev, &info->battery); - if (ret) + if (ret<0) info->battery.dev->parent = &pdev->dev; ret = power_supply_register(&pdev->dev, &powerac); @@ -3718,52 +4194,43 @@ static __devinit int ricoh619_battery_probe(struct platform_device *pdev) = create_singlethread_workqueue("rc5t619_usb_det"); INIT_WORK(&info->usb_irq_work, usb_det_irq_work); - INIT_DELAYED_WORK_DEFERRABLE(&info->monitor_work, + INIT_DEFERRABLE_WORK(&info->monitor_work, ricoh619_battery_work); - INIT_DELAYED_WORK_DEFERRABLE(&info->displayed_work, + INIT_DEFERRABLE_WORK(&info->displayed_work, ricoh619_displayed_work); - INIT_DELAYED_WORK_DEFERRABLE(&info->charge_stable_work, + INIT_DEFERRABLE_WORK(&info->charge_stable_work, ricoh619_stable_charge_countdown_work); - INIT_DELAYED_WORK_DEFERRABLE(&info->charge_monitor_work, + INIT_DEFERRABLE_WORK(&info->charge_monitor_work, ricoh619_charge_monitor_work); - INIT_DELAYED_WORK_DEFERRABLE(&info->get_charge_work, + INIT_DEFERRABLE_WORK(&info->get_charge_work, ricoh619_get_charge_work); - INIT_DELAYED_WORK_DEFERRABLE(&info->jeita_work, ricoh619_jeita_work); + INIT_DEFERRABLE_WORK(&info->jeita_work, ricoh619_jeita_work); INIT_DELAYED_WORK(&info->changed_work, ricoh619_changed_work); /* Charger IRQ workqueue settings */ - charger_irq = pdata->irq; - ret = request_threaded_irq(charger_irq + RICOH619_IRQ_FONCHGINT, - NULL, charger_in_isr, IRQF_ONESHOT, + ret = request_threaded_irq( irq_create_mapping(ricoh619->irq_domain, RICOH619_IRQ_FONCHGINT),NULL, charger_in_isr, IRQF_ONESHOT, "rc5t619_charger_in", info); if (ret < 0) { - dev_err(&pdev->dev, "Can't get CHG_INT IRQ for chrager: %d\n", - ret); + dev_err(&pdev->dev, "Can't get CHG_INT IRQ for chrager: %d\n",ret); goto out; } - ret = request_threaded_irq(charger_irq + RICOH619_IRQ_FCHGCMPINT, - NULL, charger_complete_isr, - IRQF_ONESHOT, "rc5t619_charger_comp", - info); + ret = request_threaded_irq(irq_create_mapping(ricoh619->irq_domain, RICOH619_IRQ_FCHGCMPINT),NULL, charger_complete_isr, + IRQF_ONESHOT, "rc5t619_charger_comp",info); if (ret < 0) { - dev_err(&pdev->dev, "Can't get CHG_COMP IRQ for chrager: %d\n", - ret); + dev_err(&pdev->dev, "Can't get CHG_COMP IRQ for chrager: %d\n",ret); goto out; } - ret = request_threaded_irq(charger_irq + RICOH619_IRQ_FVUSBDETSINT, - NULL, charger_usb_isr, IRQF_ONESHOT, + ret = request_threaded_irq(irq_create_mapping(ricoh619->irq_domain, RICOH619_IRQ_FVUSBDETSINT) ,NULL, charger_usb_isr, IRQF_ONESHOT, "rc5t619_usb_det", info); if (ret < 0) { - dev_err(&pdev->dev, "Can't get USB_DET IRQ for chrager: %d\n", - ret); + dev_err(&pdev->dev, "Can't get USB_DET IRQ for chrager: %d\n",ret); goto out; } - ret = request_threaded_irq(charger_irq + RICOH619_IRQ_FVADPDETSINT, - NULL, charger_adp_isr, IRQF_ONESHOT, + ret = request_threaded_irq(irq_create_mapping(ricoh619->irq_domain, RICOH619_IRQ_FVADPDETSINT),NULL, charger_adp_isr, IRQF_ONESHOT, "rc5t619_adp_det", info); if (ret < 0) { dev_err(&pdev->dev, @@ -3772,21 +4239,20 @@ static __devinit int ricoh619_battery_probe(struct platform_device *pdev) } #ifdef ENABLE_LOW_BATTERY_DETECTION - ret = request_threaded_irq(charger_irq + RICOH619_IRQ_VSYSLIR, - NULL, adc_vsysl_isr, IRQF_ONESHOT, + ret = request_threaded_irq(irq_create_mapping(ricoh619->irq_domain, RICOH619_IRQ_VSYSLIR) ,NULL, adc_vsysl_isr, IRQF_ONESHOT, "rc5t619_adc_vsysl", info); if (ret < 0) { dev_err(&pdev->dev, "Can't get ADC_VSYSL IRQ for chrager: %d\n", ret); goto out; } - INIT_DELAYED_WORK_DEFERRABLE(&info->low_battery_work, + INIT_DEFERRABLE_WORK(&info->low_battery_work, low_battery_irq_work); #endif /* Charger init and IRQ setting */ ret = ricoh619_init_charger(info); - if (ret) + if (ret<0) goto out; #ifdef ENABLE_FUEL_GAUGE_FUNCTION @@ -3795,8 +4261,8 @@ static __devinit int ricoh619_battery_probe(struct platform_device *pdev) queue_delayed_work(info->monitor_wqueue, &info->monitor_work, RICOH619_MONITOR_START_TIME*HZ); - /* Enable Charger interrupt */ - ricoh619_set_bits(info->dev->parent, RICOH619_INTC_INTEN, CHG_INT); + /* Enable Charger/ADC interrupt */ + ricoh619_set_bits(info->dev->parent, RICOH619_INTC_INTEN, CHG_INT | ADC_INT); return 0; @@ -3805,9 +4271,10 @@ out: return ret; } -static int __devexit ricoh619_battery_remove(struct platform_device *pdev) +static int ricoh619_battery_remove(struct platform_device *pdev) { struct ricoh619_battery_info *info = platform_get_drvdata(pdev); + struct ricoh619 *ricoh619 = dev_get_drvdata(pdev->dev.parent); uint8_t val; int ret; int err; @@ -3853,12 +4320,12 @@ static int __devexit ricoh619_battery_remove(struct platform_device *pdev) dev_err(info->dev, "Error in writing the control register\n"); } - free_irq(charger_irq + RICOH619_IRQ_FONCHGINT, &info); - free_irq(charger_irq + RICOH619_IRQ_FCHGCMPINT, &info); - free_irq(charger_irq + RICOH619_IRQ_FVUSBDETSINT, &info); - free_irq(charger_irq + RICOH619_IRQ_FVADPDETSINT, &info); + free_irq(irq_create_mapping(ricoh619->irq_domain, RICOH619_IRQ_FONCHGINT), &info); + free_irq(irq_create_mapping(ricoh619->irq_domain, RICOH619_IRQ_FCHGCMPINT), &info); + free_irq(irq_create_mapping(ricoh619->irq_domain, RICOH619_IRQ_FVUSBDETSINT), &info); + free_irq(irq_create_mapping(ricoh619->irq_domain, RICOH619_IRQ_FVADPDETSINT) , &info); #ifdef ENABLE_LOW_BATTERY_DETECTION - free_irq(charger_irq + RICOH619_IRQ_VSYSLIR, &info); + free_irq(irq_create_mapping(ricoh619->irq_domain, RICOH619_IRQ_VSYSLIR), &info); #endif cancel_delayed_work(&info->monitor_work); @@ -3902,6 +4369,7 @@ static int ricoh619_battery_suspend(struct device *dev) int err; int cc_cap = 0; bool is_charging = true; + int displayed_soc_temp; if (g_fg_on_mode && (info->soca->status == RICOH619_SOCA_STABLE)) { @@ -3910,6 +4378,11 @@ static int ricoh619_battery_suspend(struct device *dev) dev_err(info->dev, "Error in writing PSWR_REG\n"); g_soc = 0x7F; info->soca->suspend_soc = info->soca->displayed_soc; + ret = calc_capacity_in_period(info, &cc_cap, + &is_charging, true); + if (ret < 0) + dev_err(info->dev, "Read cc_sum Error !!-----\n"); + } else if (info->soca->status != RICOH619_SOCA_START && info->soca->status != RICOH619_SOCA_UNSTABLE) { if (info->soca->displayed_soc <= 0) { @@ -3924,12 +4397,23 @@ static int ricoh619_battery_suspend(struct device *dev) g_soc = val; - info->soca->suspend_soc = info->soca->displayed_soc; - ret = calc_capacity_in_period(info, &cc_cap, &is_charging, true); if (ret < 0) dev_err(info->dev, "Read cc_sum Error !!-----\n"); + + if (info->soca->status != RICOH619_SOCA_STABLE) { + info->soca->cc_delta + = (is_charging == true) ? cc_cap : -cc_cap; + + displayed_soc_temp + = info->soca->displayed_soc + info->soca->cc_delta; + displayed_soc_temp = min(10000, displayed_soc_temp); + displayed_soc_temp = max(0, displayed_soc_temp); + info->soca->displayed_soc = displayed_soc_temp; + } + info->soca->suspend_soc = info->soca->displayed_soc; + } else if (info->soca->status == RICOH619_SOCA_START || info->soca->status == RICOH619_SOCA_UNSTABLE) { @@ -3968,7 +4452,7 @@ static int ricoh619_battery_suspend(struct device *dev) #ifdef ENABLE_LOW_BATTERY_DETECTION // disable_irq(charger_irq + RICOH619_IRQ_VSYSLIR); #endif - +#if 0 flush_delayed_work(&info->monitor_work); flush_delayed_work(&info->displayed_work); flush_delayed_work(&info->charge_stable_work); @@ -3983,7 +4467,22 @@ static int ricoh619_battery_suspend(struct device *dev) // flush_work(&info->irq_work); // flush_work(&info->usb_irq_work); +#else + cancel_delayed_work(&info->monitor_work); + cancel_delayed_work(&info->displayed_work); + cancel_delayed_work(&info->charge_stable_work); + cancel_delayed_work(&info->charge_monitor_work); + cancel_delayed_work(&info->get_charge_work); + cancel_delayed_work(&info->changed_work); +#ifdef ENABLE_LOW_BATTERY_DETECTION + cancel_delayed_work(&info->low_battery_work); +#endif + cancel_delayed_work(&info->factory_mode_work); + cancel_delayed_work(&info->jeita_work); +// flush_work(&info->irq_work); +// flush_work(&info->usb_irq_work); +#endif return 0; } @@ -4036,11 +4535,10 @@ static int ricoh619_battery_resume(struct device *dev) displayed_soc_temp = max(0, displayed_soc_temp); info->soca->displayed_soc = displayed_soc_temp; - ret = ricoh619_write(info->dev->parent, - FG_CTRL_REG, 0x51); + ret = reset_FG_process(info); + if (ret < 0) dev_err(info->dev, "Error in writing the control register\n"); - info->soca->ready_fg = 0; info->soca->status = RICOH619_SOCA_FG_RESET; } else @@ -4063,8 +4561,26 @@ static int ricoh619_battery_resume(struct device *dev) info->soca->cc_delta = (is_charging == true) ? cc_cap : -cc_cap; displayed_soc_temp = info->soca->soc + info->soca->cc_delta; - if (displayed_soc_temp < 0) + if (info->soca->zero_flg == 1) { + if((info->soca->Ibat_ave >= 0) + || (displayed_soc_temp >= 100)){ + info->soca->zero_flg = 0; + } else { displayed_soc_temp = 0; + } + } else if (displayed_soc_temp < 100) { + /* keep DSOC = 1 when Vbat is over 3.4V*/ + if( info->fg_poff_vbat != 0) { + if (info->soca->Vbat_ave < 2000*1000) { /* error value */ + displayed_soc_temp = 100; + } else if (info->soca->Vbat_ave < info->fg_poff_vbat*1000) { + displayed_soc_temp = 0; + info->soca->zero_flg = 1; + } else { + displayed_soc_temp = 100; + } + } + } displayed_soc_temp = min(10000, displayed_soc_temp); displayed_soc_temp = max(0, displayed_soc_temp); @@ -4078,7 +4594,6 @@ static int ricoh619_battery_resume(struct device *dev) info->soca->last_soc = calc_capacity_2(info); } } - info->soca->update_count = 0; ret = measure_vbatt_FG(info, &info->soca->Vbat_ave); ret = measure_vsys_ADC(info, &info->soca->Vsys_ave); @@ -4131,6 +4646,15 @@ static int ricoh619_battery_resume(struct device *dev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id ricoh619_battery_dt_match[] = { + { .compatible = "ricoh,ricoh619-battery", }, + {}, +}; +MODULE_DEVICE_TABLE(of, ricoh619_battery_dt_match); +#endif + + static const struct dev_pm_ops ricoh619_battery_pm_ops = { .suspend = ricoh619_battery_suspend, .resume = ricoh619_battery_resume, @@ -4141,12 +4665,13 @@ static struct platform_driver ricoh619_battery_driver = { .driver = { .name = "ricoh619-battery", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(ricoh619_battery_dt_match), #ifdef CONFIG_PM .pm = &ricoh619_battery_pm_ops, #endif }, .probe = ricoh619_battery_probe, - .remove = __devexit_p(ricoh619_battery_remove), + .remove = ricoh619_battery_remove, }; static int __init ricoh619_battery_init(void) @@ -4154,7 +4679,7 @@ static int __init ricoh619_battery_init(void) RICOH_FG_DBG("PMU: %s\n", __func__); return platform_driver_register(&ricoh619_battery_driver); } -subsys_initcall_sync(ricoh619_battery_init); +fs_initcall_sync(ricoh619_battery_init); static void __exit ricoh619_battery_exit(void) { diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig old mode 100644 new mode 100755 index 3afbb5d2adea..fdfde54afa41 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -267,6 +267,12 @@ config ROCKCHIP_PWM_REGULATOR help Say Y to enable support for the voltage regulators control on the ROCKCHIP. +config REGULATOR_SYB827 + tristate "SYB827 DCDC SUPPORT REGULATOR" + depends on I2C + help + Support the voltage and current regulators of the SYB827 series of DCDC devices. + config REGULATOR_PCAP tristate "Motorola PCAP2 regulator driver" depends on EZX_PCAP @@ -524,6 +530,12 @@ config REGULATOR_WM8994 This driver provides support for the voltage regulators on the WM8994 CODEC. +config REGULATOR_RICOH619 + tristate "RICOH 619 Power regulators" + depends on MFD_RICOH619 + default n + help + This driver supports regulator driver for RICOH619 PMIC. config REGULATOR_AS3711 tristate "AS3711 PMIC" depends on MFD_AS3711 diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile old mode 100644 new mode 100755 index 6ed37407f0a8..d38b4658e8a0 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -74,6 +74,8 @@ obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o obj-$(CONFIG_REGULATOR_ACT8846) += act8846.o +obj-$(CONFIG_REGULATOR_SYB827) += syb827.o +obj-$(CONFIG_REGULATOR_RICOH619) += ricoh619-regulator.o obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip_io_vol_domain.o diff --git a/drivers/regulator/ricoh619-regulator.c b/drivers/regulator/ricoh619-regulator.c index 900f25ef9eee..b840ce9ae19c 100644 --- a/drivers/regulator/ricoh619-regulator.c +++ b/drivers/regulator/ricoh619-regulator.c @@ -35,6 +35,8 @@ #include #include #include +#include +#include struct ricoh619_regulator { int id; @@ -203,10 +205,12 @@ static int ricoh619_set_suspend_voltage(struct regulator_dev *rdev, static int ricoh619_get_voltage(struct regulator_dev *rdev) { struct ricoh619_regulator *ri = rdev_get_drvdata(rdev); + struct device *parent = to_ricoh619_dev(rdev); uint8_t vsel; + int ret; - vsel = ri->vout_reg_cache & ri->vout_mask; - return ri->min_uV + vsel * ri->step_uV; + ret = ricoh619_read(parent, ri->vout_reg, &vsel); + return ricoh619_list_voltage(rdev,vsel); } int ricoh619_regulator_enable_eco_mode(struct regulator_dev *rdev) @@ -331,7 +335,55 @@ static int ricoh619_dcdc_set_voltage_time_sel(struct regulator_dev *rdev, unsi return DIV_ROUND_UP(abs(old_volt - new_volt)*2, 14000); } +static int ricoh619_dcdc_set_suspend_mode(struct regulator_dev *rdev, unsigned int mode) +{ + struct ricoh619_regulator *ri = rdev_get_drvdata(rdev); + struct device *parent = to_ricoh619_dev(rdev); + int ret; + uint8_t control; + + ret = ricoh619_read(parent, ri->reg_en_reg,&control); + switch(mode) + { + case REGULATOR_MODE_FAST: + return ricoh619_write(parent, ri->reg_en_reg, ((control & 0x3f) | 0x40)); + case REGULATOR_MODE_NORMAL: + return ricoh619_write(parent, ri->reg_en_reg, (control & 0x3f)); + case REGULATOR_MODE_STANDBY: + return ricoh619_write(parent, ri->reg_en_reg, ((control & 0x3f) | 0x80)); + default: + printk("error:pmu_619 only powersave pwm psm mode\n"); + return -EINVAL; + } + + +} +static int ricoh619_reg_suspend_enable(struct regulator_dev *rdev) +{ + struct ricoh619_regulator *ri = rdev_get_drvdata(rdev); + struct device *parent = to_ricoh619_dev(rdev); + int ret; + u8 vout_val; + ret = ricoh619_set_bits(parent, (0x16 + ri->id), (0xf << 0)); + if (ret < 0) { + dev_err(&rdev->dev, "Error in updating the STATE register\n"); + return ret; + } + udelay(ri->delay); + return ret; +} + +static int ricoh619_reg_suspend_disable(struct regulator_dev *rdev) +{ + struct ricoh619_regulator *ri = rdev_get_drvdata(rdev); + struct device *parent = to_ricoh619_dev(rdev); + int ret; + ret = ricoh619_clr_bits(parent, (0x16 + ri->id), (0xf <<0)); + if (ret < 0) + dev_err(&rdev->dev, "Error in updating the STATE register\n"); + return ret; +} static struct regulator_ops ricoh619_ops = { .list_voltage = ricoh619_list_voltage, @@ -343,6 +395,9 @@ static struct regulator_ops ricoh619_ops = { .set_mode = ricoh619_dcdc_set_mode, .enable = ricoh619_reg_enable, .disable = ricoh619_reg_disable, + .set_suspend_mode = ricoh619_dcdc_set_suspend_mode, + .set_suspend_enable = ricoh619_reg_suspend_enable, + .set_suspend_disable = ricoh619_reg_suspend_disable, .is_enabled = ricoh619_reg_is_enabled, }; @@ -378,7 +433,7 @@ static struct regulator_ops ricoh619_ops = { }, \ } -static struct ricoh619_regulator ricoh619_regulator[] = { +static struct ricoh619_regulator ricoh619_regulator_data[] = { RICOH619_REG(DC1, 0x2C, 0, 0x2C, 1, 0x36, 0xFF, 0x3B, 600000, 3500000, 12500, 0xE8, ricoh619_ops, 500, 0x00, 0, 0x00, 0), @@ -447,13 +502,14 @@ static struct ricoh619_regulator ricoh619_regulator[] = { 900000, 3500000, 25000, 0x68, ricoh619_ops, 500, 0x00, 0, 0x00, 0), }; + static inline struct ricoh619_regulator *find_regulator_info(int id) { struct ricoh619_regulator *ri; int i; - for (i = 0; i < ARRAY_SIZE(ricoh619_regulator); i++) { - ri = &ricoh619_regulator[i]; + for (i = 0; i < ARRAY_SIZE(ricoh619_regulator_data); i++) { + ri = &ricoh619_regulator_data[i]; if (ri->desc.id == id) return ri; } @@ -502,47 +558,105 @@ static inline int ricoh619_cache_regulator_register(struct device *parent, return ricoh619_read(parent, ri->vout_reg, &ri->vout_reg_cache); } -static int __devinit ricoh619_regulator_probe(struct platform_device *pdev) +#ifdef CONFIG_OF +static struct of_regulator_match ricoh619_regulator_matches[] = { + { .name = "ricoh619_dc1",}, + { .name = "ricoh619_dc2",}, + { .name = "ricoh619_dc3",}, + { .name = "ricoh619_dc4",}, + { .name = "ricoh619_dc5",}, + { .name = "ricoh619_ldo1",}, + { .name = "ricoh619_ldo2",}, + { .name = "ricoh619_ldo3",}, + { .name = "ricoh619_ldo4",}, + { .name = "ricoh619_ldo5",}, + { .name = "ricoh619_ldo6",}, + { .name = "ricoh619_ldo7",}, + { .name = "ricoh619_ldo8",}, + { .name = "ricoh619_ldo9",}, + { .name = "ricoh619_ldo10",}, + { .name = "ricoh619_ldortc1",}, + { .name = "ricoh619_ldortc2",}, +}; +#endif + +#ifdef CONFIG_OF +static int ricoh619_regulator_dt_init(struct platform_device *pdev, + struct regulator_config *config, + int regidx) +{ + struct device_node *nproot, *np; + int rcount; + nproot = of_node_get(pdev->dev.parent->of_node); + if (!nproot) + return -ENODEV; + np = of_find_node_by_name(nproot, "regulators"); + if (!np) { + dev_err(&pdev->dev, "failed to find regulators node\n"); + return -ENODEV; + } + + rcount = of_regulator_match(&pdev->dev, np, + &ricoh619_regulator_matches[regidx], 1); + of_node_put(np); + if (rcount < 0) + return -ENODEV; + config->init_data = ricoh619_regulator_matches[regidx].init_data; + config->of_node = ricoh619_regulator_matches[regidx].of_node; + + return 0; +} +#else +#define ricoh619_regulator_dt_init(x, y, z) (-1) +#endif + +static int ricoh619_regulator_probe(struct platform_device *pdev) { struct ricoh619_regulator *ri = NULL; struct regulator_dev *rdev; - struct ricoh619_regulator_platform_data *tps_pdata; - int id = pdev->id; - int err; + struct regulator_config config = { }; + struct regulator_init_data *pdata_regulator = dev_get_platdata(&pdev->dev); + int err,id=0; + + rdev = devm_kzalloc(&pdev->dev, RICOH619_NUM_REGULATOR * + sizeof(*rdev), GFP_KERNEL); + if (!rdev) { + dev_err(&pdev->dev, "Mmemory alloc failed\n"); + return -ENOMEM; + } + + for (id = 0; id < RICOH619_NUM_REGULATOR; ++id) { ri = find_regulator_info(id); - if (ri == NULL) { + if (!ri) { dev_err(&pdev->dev, "invalid regulator ID specified\n"); - return -EINVAL; + err = -EINVAL; } - tps_pdata = pdev->dev.platform_data; + ri->dev = &pdev->dev; -/* - err = ricoh619_cache_regulator_register(pdev->dev.parent, ri); - if (err) { - dev_err(&pdev->dev, "Fail in caching register\n"); - return err; - } + config.dev = &pdev->dev; + config.driver_data = ri; - err = ricoh619_regulator_preinit(pdev->dev.parent, ri, tps_pdata); - if (err) { - dev_err(&pdev->dev, "Fail in pre-initialisation\n"); - return err; - } - */ - rdev = regulator_register(&ri->desc, &pdev->dev, - &tps_pdata->regulator, ri); + if (ricoh619_regulator_matches) + config.of_node = ricoh619_regulator_matches[id].of_node; + + if (ricoh619_regulator_dt_init(pdev, &config, id)) + if (pdata_regulator) + config.init_data = &pdata_regulator; + + rdev = regulator_register(&ri->desc, &config); if (IS_ERR_OR_NULL(rdev)) { dev_err(&pdev->dev, "failed to register regulator %s\n", ri->desc.name); return PTR_ERR(rdev); } + } platform_set_drvdata(pdev, rdev); return 0; } -static int __devexit ricoh619_regulator_remove(struct platform_device *pdev) +static int ricoh619_regulator_remove(struct platform_device *pdev) { struct regulator_dev *rdev = platform_get_drvdata(pdev); @@ -556,7 +670,7 @@ static struct platform_driver ricoh619_regulator_driver = { .owner = THIS_MODULE, }, .probe = ricoh619_regulator_probe, - .remove = __devexit_p(ricoh619_regulator_remove), + .remove = ricoh619_regulator_remove, }; static int __init ricoh619_regulator_init(void) diff --git a/drivers/regulator/syb827.c b/drivers/regulator/syb827.c new file mode 100755 index 000000000000..ec1ada5e11b3 --- /dev/null +++ b/drivers/regulator/syb827.c @@ -0,0 +1,584 @@ +/* + * Regulator driver for syb827 DCDC chip for rk32xx + * + * Copyright (C) 2010, 2011 ROCKCHIP, Inc. + + * Based on syb827.c that is work by zhangqing + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if 0 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif +#if 1 +#define DBG_INFO(x...) printk(KERN_INFO x) +#else +#define DBG_INFO(x...) +#endif +#define PM_CONTROL + +#define SYB827_SPEED 200*1000 +#define syb827_NUM_REGULATORS 1 + +struct syb827 { + struct device *dev; + struct mutex io_lock; + struct i2c_client *i2c; + int num_regulators; + struct regulator_dev **rdev; + int irq_base; + int chip_irq; + int sleep_gpio; /* */ + unsigned int dcdc_slp_voltage[3]; /* buckx_voltage in uV */ + bool pmic_sleep; + struct regmap *regmap; +}; + +struct syb827_regulator { + struct device *dev; + struct regulator_desc *desc; + struct regulator_dev *rdev; +}; +struct syb827_board { + int irq; + int irq_base; + struct regulator_init_data *syb827_init_data[syb827_NUM_REGULATORS]; + struct device_node *of_node[syb827_NUM_REGULATORS]; + int sleep_gpio; /* */ + unsigned int dcdc_slp_voltage[3]; /* buckx_voltage in uV */ + bool sleep; +}; + +struct syb827_regulator_subdev { + int id; + struct regulator_init_data *initdata; + struct device_node *reg_node; +}; + +struct syb827_platform_data { + int ono; + int num_regulators; + struct syb827_regulator_subdev *regulators; + + int sleep_gpio; /* */ + unsigned int dcdc_slp_voltage[3]; /* buckx_voltage in uV */ + bool sleep; +}; +struct syb827 *g_syb827; + +static u8 syb827_reg_read(struct syb827 *syb827, u8 reg); +static int syb827_set_bits(struct syb827 *syb827, u8 reg, u16 mask, u16 val); + + +#define SYB827_BUCK1_SET_VOL_BASE 0x00 +#define SYB827_BUCK1_SLP_VOL_BASE 0x01 +#define SYB827_CONTR_REG1 0x02 +#define SYB827_ID1_REG 0x03 +#define SYB827_ID2_REG 0x04 +#define SYB827_CONTR_REG2 0x05 + +#define BUCK_VOL_MASK 0x3f +#define VOL_MIN_IDX 0x00 +#define VOL_MAX_IDX 0x3f + +const static int buck_voltage_map[] = { + 712500, 725000, 737500,750000, 762500,775000,787500,800000, + 812500, 825000, 837500,850000, 862500,875000,887500,900000, + 912500, 925000, 937500,950000, 962500,975000,987500,1000000, + 1012500, 1025000, 1037500,1050000, 1062500,1075000,1087500,1100000, + 1112500, 1125000, 1137500,1150000, 1162500,1175000,1187500,1200000, + 1212500, 1225000, 1237500,1250000, 1262500,1275000,1287500,1300000, + 1312500, 1325000, 1337500,1350000, 1362500,1375000,1387500,1400000, + 1412500, 1425000, 1437500,1450000, 1462500,1475000,1487500,1500000, +}; + +static int syb827_dcdc_list_voltage(struct regulator_dev *dev, unsigned index) +{ + if (index >= ARRAY_SIZE(buck_voltage_map)) + return -EINVAL; + return buck_voltage_map[index]; +} +static int syb827_dcdc_is_enabled(struct regulator_dev *dev) +{ + struct syb827 *syb827 = rdev_get_drvdata(dev); + u16 val; + u16 mask=0x80; + val = syb827_reg_read(syb827, SYB827_BUCK1_SET_VOL_BASE); + if (val < 0) + return val; + val=val&~0x7f; + if (val & mask) + return 1; + else + return 0; +} +static int syb827_dcdc_enable(struct regulator_dev *dev) +{ + struct syb827 *syb827 = rdev_get_drvdata(dev); + u16 mask=0x80; + + return syb827_set_bits(syb827, SYB827_BUCK1_SET_VOL_BASE, mask, 0x80); + +} +static int syb827_dcdc_disable(struct regulator_dev *dev) +{ + struct syb827 *syb827 = rdev_get_drvdata(dev); + u16 mask=0x80; + return syb827_set_bits(syb827, SYB827_BUCK1_SET_VOL_BASE, mask, 0); +} +static int syb827_dcdc_get_voltage(struct regulator_dev *dev) +{ + struct syb827 *syb827 = rdev_get_drvdata(dev); + u16 reg = 0; + int val; + reg = syb827_reg_read(syb827,SYB827_BUCK1_SET_VOL_BASE); + reg &= BUCK_VOL_MASK; + val = buck_voltage_map[reg]; + return val; +} +static int syb827_dcdc_set_voltage(struct regulator_dev *dev, + int min_uV, int max_uV,unsigned *selector) +{ + struct syb827 *syb827 = rdev_get_drvdata(dev); + const int *vol_map = buck_voltage_map; + u16 val; + int ret = 0; + + if (min_uV < vol_map[VOL_MIN_IDX] || + min_uV > vol_map[VOL_MAX_IDX]) + return -EINVAL; + + for (val = VOL_MIN_IDX; val <= VOL_MAX_IDX; val++){ + if (vol_map[val] >= min_uV) + break; + } + + if (vol_map[val] > max_uV) + printk("WARNING:this voltage is not support!voltage set is %d mv\n",vol_map[val]); + + ret = syb827_set_bits(syb827, SYB827_BUCK1_SET_VOL_BASE ,BUCK_VOL_MASK, val); + + return ret; +} + +static unsigned int syb827_dcdc_get_mode(struct regulator_dev *dev) +{ + struct syb827 *syb827 = rdev_get_drvdata(dev); + u16 mask = 0x40; + u16 val; + val = syb827_reg_read(syb827, SYB827_BUCK1_SET_VOL_BASE); + if (val < 0) { + return val; + } + val=val & mask; + if (val== mask) + return REGULATOR_MODE_FAST; + else + return REGULATOR_MODE_NORMAL; + +} +static int syb827_dcdc_set_mode(struct regulator_dev *dev, unsigned int mode) +{ + struct syb827 *syb827 = rdev_get_drvdata(dev); + u16 mask = 0x40; + + switch(mode) + { + case REGULATOR_MODE_FAST: + return syb827_set_bits(syb827,SYB827_BUCK1_SET_VOL_BASE, mask, mask); + case REGULATOR_MODE_NORMAL: + return syb827_set_bits(syb827, SYB827_BUCK1_SET_VOL_BASE, mask, 0); + default: + printk("error:dcdc_syb827 only auto and pwm mode\n"); + return -EINVAL; + } +} +static int syb827_dcdc_set_voltage_time_sel(struct regulator_dev *dev, unsigned int old_selector, + unsigned int new_selector) +{ + int old_volt, new_volt; + + old_volt = syb827_dcdc_list_voltage(dev, old_selector); + if (old_volt < 0) + return old_volt; + + new_volt = syb827_dcdc_list_voltage(dev, new_selector); + if (new_volt < 0) + return new_volt; + + return DIV_ROUND_UP(abs(old_volt - new_volt), 10000); +} +static int syb827_dcdc_suspend_enable(struct regulator_dev *dev) +{ + struct syb827 *syb827 = rdev_get_drvdata(dev); + u16 mask=0x80; + + return syb827_set_bits(syb827, SYB827_BUCK1_SLP_VOL_BASE, mask, 0x80); + +} +static int syb827_dcdc_suspend_disable(struct regulator_dev *dev) +{ + struct syb827 *syb827 = rdev_get_drvdata(dev); + u16 mask=0x80; + return syb827_set_bits(syb827, SYB827_BUCK1_SLP_VOL_BASE, mask, 0); +} +static int syb827_dcdc_set_sleep_voltage(struct regulator_dev *dev, + int uV) +{ + struct syb827 *syb827 = rdev_get_drvdata(dev); + const int *vol_map = buck_voltage_map; + u16 val; + int ret = 0; + + if (uV < vol_map[VOL_MIN_IDX] || + uV > vol_map[VOL_MAX_IDX]) + return -EINVAL; + + for (val = VOL_MIN_IDX; val <= VOL_MAX_IDX; val++){ + if (vol_map[val] >= uV) + break; + } + + if (vol_map[val] > uV) + printk("WARNING:this voltage is not support!voltage set is %d mv\n",vol_map[val]); + ret = syb827_set_bits(syb827,SYB827_BUCK1_SLP_VOL_BASE ,BUCK_VOL_MASK, val); + return ret; +} + + +static int syb827_dcdc_set_suspend_mode(struct regulator_dev *dev, unsigned int mode) +{ + struct syb827 *syb827 = rdev_get_drvdata(dev); + u16 mask = 0x40; + + switch(mode) + { + case REGULATOR_MODE_FAST: + return syb827_set_bits(syb827,SYB827_BUCK1_SLP_VOL_BASE, mask, mask); + case REGULATOR_MODE_NORMAL: + return syb827_set_bits(syb827, SYB827_BUCK1_SLP_VOL_BASE, mask, 0); + default: + printk("error:dcdc_syb827 only auto and pwm mode\n"); + return -EINVAL; + } +} + +static struct regulator_ops syb827_dcdc_ops = { + .set_voltage = syb827_dcdc_set_voltage, + .get_voltage = syb827_dcdc_get_voltage, + .list_voltage= syb827_dcdc_list_voltage, + .is_enabled = syb827_dcdc_is_enabled, + .enable = syb827_dcdc_enable, + .disable = syb827_dcdc_disable, + .get_mode = syb827_dcdc_get_mode, + .set_mode = syb827_dcdc_set_mode, + .set_suspend_voltage = syb827_dcdc_set_sleep_voltage, + .set_suspend_enable = syb827_dcdc_suspend_enable, + .set_suspend_disable = syb827_dcdc_suspend_disable, + .set_suspend_mode = syb827_dcdc_set_suspend_mode, + .set_voltage_time_sel = syb827_dcdc_set_voltage_time_sel, +}; +static struct regulator_desc regulators[] = { + + { + .name = "SY_DCDC1", + .id = 0, + .ops = &syb827_dcdc_ops, + .n_voltages = ARRAY_SIZE(buck_voltage_map), + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, +}; + +static int syb827_i2c_read(struct i2c_client *i2c, char reg, int count, u16 *dest) +{ + int ret; + struct i2c_adapter *adap; + struct i2c_msg msgs[2]; + + if(!i2c) + return ret; + + if (count != 1) + return -EIO; + + adap = i2c->adapter; + + msgs[0].addr = i2c->addr; + msgs[0].buf = ® + msgs[0].flags = i2c->flags; + msgs[0].len = 1; + msgs[0].scl_rate = SYB827_SPEED; + + msgs[1].buf = (u8 *)dest; + msgs[1].addr = i2c->addr; + msgs[1].flags = i2c->flags | I2C_M_RD; + msgs[1].len = 1; + msgs[1].scl_rate = SYB827_SPEED; + ret = i2c_transfer(adap, msgs, 2); + + DBG("***run in %s %d msgs[1].buf = %d\n",__FUNCTION__,__LINE__,*(msgs[1].buf)); + + return 0; +} + +static int syb827_i2c_write(struct i2c_client *i2c, char reg, int count, const u16 src) +{ + int ret=-1; + + struct i2c_adapter *adap; + struct i2c_msg msg; + char tx_buf[2]; + + if(!i2c) + return ret; + if (count != 1) + return -EIO; + + adap = i2c->adapter; + tx_buf[0] = reg; + tx_buf[1] = src; + + msg.addr = i2c->addr; + msg.buf = &tx_buf[0]; + msg.len = 1 +1; + msg.flags = i2c->flags; + msg.scl_rate = SYB827_SPEED; + + ret = i2c_transfer(adap, &msg, 1); + return ret; +} + +static u8 syb827_reg_read(struct syb827 *syb827, u8 reg) +{ + u16 val = 0; + + mutex_lock(&syb827->io_lock); + + syb827_i2c_read(syb827->i2c, reg, 1, &val); + + DBG("reg read 0x%02x -> 0x%02x\n", (int)reg, (unsigned)val&0xff); + + mutex_unlock(&syb827->io_lock); + + return val & 0xff; +} + +static int syb827_set_bits(struct syb827 *syb827, u8 reg, u16 mask, u16 val) +{ + u16 tmp; + int ret; + + mutex_lock(&syb827->io_lock); + + ret = syb827_i2c_read(syb827->i2c, reg, 1, &tmp); + DBG("1 reg read 0x%02x -> 0x%02x\n", (int)reg, (unsigned)tmp&0xff); + tmp = (tmp & ~mask) | val; + if (ret == 0) { + ret = syb827_i2c_write(syb827->i2c, reg, 1, tmp); + DBG("reg write 0x%02x -> 0x%02x\n", (int)reg, (unsigned)val&0xff); + } + syb827_i2c_read(syb827->i2c, reg, 1, &tmp); + DBG("2 reg read 0x%02x -> 0x%02x\n", (int)reg, (unsigned)tmp&0xff); + mutex_unlock(&syb827->io_lock); + + return 0;//ret; +} + +#ifdef CONFIG_OF +static struct of_device_id syb827_of_match[] = { + { .compatible = "silergy,syb827"}, + { }, +}; +MODULE_DEVICE_TABLE(of, syb827_of_match); +#endif +#ifdef CONFIG_OF +static struct of_regulator_match syb827_reg_matches[] = { + { .name = "syb827_dcdc1" ,.driver_data = (void *)0}, +}; + +static struct syb827_board *syb827_parse_dt(struct syb827 *syb827) +{ + struct syb827_board *pdata; + struct device_node *regs; + struct device_node *syb827_np; + int gpio,count; + DBG("%s,line=%d\n", __func__,__LINE__); + + syb827_np = of_node_get(syb827->dev->of_node); + if (!syb827_np) { + printk("could not find pmic sub-node\n"); + return NULL; + } + + regs = of_find_node_by_name(syb827_np, "regulators"); + if (!regs) + return NULL; + count = of_regulator_match(syb827->dev, regs, syb827_reg_matches, + syb827_NUM_REGULATORS); + of_node_put(regs); + pdata = devm_kzalloc(syb827->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return NULL; + pdata->syb827_init_data[0] = syb827_reg_matches[0].init_data; + pdata->of_node[0] = syb827_reg_matches[0].of_node; + + return pdata; +} + +#else +static struct syb827_board *syb827_parse_dt(struct i2c_client *i2c) +{ + return NULL; +} +#endif + +static int syb827_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) +{ + struct syb827 *syb827; + struct syb827_board *pdev ; + const struct of_device_id *match; + struct regulator_config config = { }; + struct regulator_dev *sy_rdev; + struct regulator_init_data *reg_data; + const char *rail_name = NULL; + int ret; + + DBG("%s,line=%d\n", __func__,__LINE__); + + if (i2c->dev.of_node) { + match = of_match_device(syb827_of_match, &i2c->dev); + if (!match) { + printk("Failed to find matching dt id\n"); + return -EINVAL; + } + } + + syb827 = devm_kzalloc(&i2c->dev,sizeof(struct syb827), GFP_KERNEL); + if (syb827 == NULL) { + ret = -ENOMEM; + goto err; + } + syb827->i2c = i2c; + syb827->dev = &i2c->dev; + i2c_set_clientdata(i2c, syb827); + g_syb827 = syb827; + + mutex_init(&syb827->io_lock); + + ret = syb827_reg_read(syb827,SYB827_ID1_REG); + if ((ret <0) ||(ret ==0xff) ||(ret ==0)){ + printk("The device is not syb827 %x \n",ret); + goto err; + } + + if (syb827->dev->of_node) + pdev = syb827_parse_dt(syb827); + + if (pdev) { + syb827->num_regulators = syb827_NUM_REGULATORS; + syb827->rdev = kcalloc(syb827_NUM_REGULATORS,sizeof(struct regulator_dev *), GFP_KERNEL); + if (!syb827->rdev) { + return -ENOMEM; + } + /* Instantiate the regulators */ + reg_data = pdev->syb827_init_data[0]; + config.dev = syb827->dev; + config.driver_data = syb827; + if (syb827->dev->of_node) + config.of_node = pdev->of_node[0]; + if (reg_data && reg_data->constraints.name) + rail_name = reg_data->constraints.name; + else + rail_name = regulators[0].name; + reg_data->supply_regulator = rail_name; + + config.init_data =reg_data; + sy_rdev = regulator_register(®ulators[0],&config); + if (IS_ERR(sy_rdev)) { + printk("failed to register regulator\n"); + goto err; + } + syb827->rdev[0] = sy_rdev; + } + return 0; +err: + return ret; + +} + +static int syb827_i2c_remove(struct i2c_client *i2c) +{ + struct syb827 *syb827 = i2c_get_clientdata(i2c); + + if (syb827->rdev[0]) + regulator_unregister(syb827->rdev[0]); + i2c_set_clientdata(i2c, NULL); + return 0; +} + +static const struct i2c_device_id syb827_i2c_id[] = { + { "syb827", 0 }, + { } +}; + +MODULE_DEVICE_TABLE(i2c, syb827_i2c_id); + +static struct i2c_driver syb827_i2c_driver = { + .driver = { + .name = "syb827", + .owner = THIS_MODULE, + .of_match_table =of_match_ptr(syb827_of_match), + }, + .probe = syb827_i2c_probe, + .remove = syb827_i2c_remove, + .id_table = syb827_i2c_id, +}; + +static int __init syb827_module_init(void) +{ + int ret; + ret = i2c_add_driver(&syb827_i2c_driver); + if (ret != 0) + pr_err("Failed to register I2C driver: %d\n", ret); + return ret; +} +subsys_initcall_sync(syb827_module_init); + +static void __exit syb827_module_exit(void) +{ + i2c_del_driver(&syb827_i2c_driver); +} +module_exit(syb827_module_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("zhangqing "); +MODULE_DESCRIPTION("syb827 PMIC driver"); + diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig old mode 100644 new mode 100755 index 33d86af2a60d..33b6eb48a266 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1253,6 +1253,16 @@ config RTC_DRV_HID_SENSOR_TIME If this driver is compiled as a module, it will be named rtc-hid-sensor-time. + +config RTC_DRV_RC5T619 + tristate "RICOH RC5T619 PMU RTC driver" + depends on MFD_RICOH619 + default n + help + If you say yes here you get support for the RICOH RC5T619 RTC module. + + This driver can also be built as a module. If so, the module + will be called rtc-rc5t619. endif # RTC_CLASS diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile old mode 100644 new mode 100755 index d90aa263eec0..8cd446a70387 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -129,3 +129,5 @@ obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o obj-$(CONFIG_RK808_RTC) += rtc-rk808.o obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o +obj-$(CONFIG_RTC_DRV_RC5T619) += rtc-ricoh619.o + diff --git a/drivers/rtc/rtc-ricoh619.c b/drivers/rtc/rtc-ricoh619.c index 1db0367b0141..b70507aa4b6a 100755 --- a/drivers/rtc/rtc-ricoh619.c +++ b/drivers/rtc/rtc-ricoh619.c @@ -30,11 +30,14 @@ #include #include #include +#include #include #include #include #include #include +#include + struct ricoh619_rtc { int irq; @@ -76,7 +79,7 @@ static int ricoh619_rtc_valid_tm(struct device *dev, struct rtc_time *tm) || tm->tm_mon > 11 || tm->tm_mon < 0 || tm->tm_mday < 1 || tm->tm_mday > rtc_month_days(tm->tm_mon, tm->tm_year + os_ref_year) - || tm->tm_hour >= 24 || tm->tm_hour <0 + || tm->tm_hour >= 24 || tm->tm_hour < 0 || tm->tm_min < 0 || tm->tm_min >= 60 || tm->tm_sec < 0 || tm->tm_sec >= 60 ) @@ -144,14 +147,14 @@ static int ricoh619_rtc_periodic_disable(struct device *dev) err = ricoh619_read_regs(dev, rtc_ctrl2, 1, ®_data); if(err < 0) { - dev_err(dev->parent, "read rtc_ctrl1 error=0x%x\n", err); + dev_err(dev->parent, "read rtc_ctrl2 error=0x%x\n", err); return err; } reg_data &= ~0x85;// 1000-0101 err = ricoh619_write_regs(dev, rtc_ctrl2, 1, ®_data); if(err < 0) { - dev_err(dev->parent, "read rtc_ctrl1 error=0x%x\n", err); + dev_err(dev->parent, "read rtc_ctrl2 error=0x%x\n", err); return err; } @@ -168,7 +171,7 @@ static int ricoh619_rtc_Pon_get_clr(struct device *dev, uint8_t *Pon_f) int err; uint8_t reg_data; - err = ricoh619_read_regs(dev, rtc_ctrl2, 1, ®_data); + err = ricoh619_read_regs(dev, rtc_ctrl2,1,®_data); if(err < 0) { dev_err(dev->parent, "rtc_ctrl1 read err=0x%x\n", err); @@ -182,7 +185,7 @@ static int ricoh619_rtc_Pon_get_clr(struct device *dev, uint8_t *Pon_f) //clear VDET PON reg_data &= ~0x5b;// 0101-1011 reg_data |= 0x20; // 0010-0000 - err = ricoh619_write_regs(dev, rtc_ctrl2, 1, ®_data); + err = ricoh619_write_regs(dev, rtc_ctrl2, 1,®_data); if(err < 0) { dev_err(dev->parent, "rtc_ctrl1 write err=0x%x\n", err); @@ -245,9 +248,7 @@ static int ricoh619_rtc_read_time(struct device *dev, struct rtc_time *tm) u8 buff[7]; int err; int cent_flag; - int i; -// printk(KERN_INFO "PMU: %s\n", __func__); err = ricoh619_read_regs(dev, rtc_seconds_reg, sizeof(buff), buff); if (err < 0) { @@ -272,7 +273,10 @@ static int ricoh619_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_year = buff[6] + 100 * cent_flag; print_time(dev, tm); //for print tm->tm_mon = buff[5] - 1; //back to system 0-11 - + +// printk(KERN_INFO "PMU: %s year=%d mon=%d day=% hour=%d min =%d sec=%d\n", __func__, +// tm->tm_year,tm->tm_mon ,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec ); + return 0; } @@ -282,7 +286,8 @@ static int ricoh619_rtc_set_time(struct device *dev, struct rtc_time *tm) int err; int cent_flag; -// printk(KERN_INFO "PMU: %s\n", __func__); +// printk(KERN_INFO "PMU: %s year=%d mon=%d day=% hour=%d min =%d sec=%d\n", __func__, +// tm->tm_year,tm->tm_mon ,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec ); if(ricoh619_rtc_valid_tm(dev, tm) != 0) { @@ -325,10 +330,10 @@ static int ricoh619_rtc_alarm_is_enabled(struct device *dev, uint8_t *enabled) uint8_t reg_data; err = 0; - err = ricoh619_read_regs(dev, rtc_ctrl1, 1,®_data); - if(err) + err = ricoh619_read_regs(dev, rtc_ctrl1,1,®_data); + if(err<0) { - dev_err(dev->parent, "read rtc_ctrl1 error 0x%lx\n", err); + dev_err(dev->parent, "read rtc_ctrl1 error 0x%x\n", err); *enabled = 0; } else @@ -415,14 +420,14 @@ static int ricoh619_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) cent_flag = 0; err = ricoh619_read_regs(dev, rtc_alarm_y_sec, sizeof(buff), buff); - if(err) + if(err <0) { dev_err(dev->parent, "RTC: %s *** read rtc_alarm timer error 0x%lx\n", __func__, err); return err; } err = ricoh619_read_regs(dev, rtc_ctrl1, 1,&enabled_flag); - if(err) + if(err<0) { dev_err(dev->parent, "RTC: %s *** read rtc_enable flag error 0x%lx\n", __func__, err); return err; @@ -487,7 +492,7 @@ static int ricoh619_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) convert_decimal_to_bcd(buff, sizeof(buff)); buff[3] |= 0x80; /* set DAL_EXT */ err = ricoh619_write_regs(dev, rtc_alarm_y_sec, sizeof(buff), buff); - if (err) { + if (err<0) { dev_err(dev->parent, "\n unable to set alarm\n"); err = -EBUSY; goto ERR; @@ -514,13 +519,13 @@ static int ricoh619_rtc_alarm_flag_clr(struct device *dev) /* clear alarm-D status bits.*/ err = ricoh619_read_regs(dev, rtc_ctrl2, 1, ®_data); - if (err) + if (err<0) dev_err(dev->parent, "unable to read rtc_ctrl2 reg\n"); /* to clear alarm-D flag, and set adjustment parameter */ reg_data &= ~0x81; err = ricoh619_write_regs(dev, rtc_ctrl2, 1, ®_data); - if (err) + if (err<0) dev_err(dev->parent, "unable to program rtc_status reg\n"); return err; } @@ -537,31 +542,70 @@ static irqreturn_t ricoh619_rtc_irq(int irq, void *data) return IRQ_HANDLED; } -static int __devinit ricoh619_rtc_probe(struct platform_device *pdev) +#ifdef CONFIG_OF +static struct ricoh619_rtc_platform_data *ricoh619_rtc_dt_init(struct platform_device *pdev) +{ + struct device_node *nproot = pdev->dev.parent->of_node; + struct device_node *np; + struct ricoh619_rtc_platform_data *pdata; + + if (!nproot) + return pdev->dev.platform_data; + + np = of_find_node_by_name(nproot, "rtc"); + if (!np) { + dev_err(&pdev->dev, "failed to find rtc node\n"); + return NULL; + } + + pdata = devm_kzalloc(&pdev->dev, + sizeof(struct ricoh619_rtc_platform_data), + GFP_KERNEL); + + of_property_read_u32(np, "ricoh,rtc-tm-year", &pdata->time.tm_year); + of_property_read_u32(np, "ricoh,rtc-tm-month", &pdata->time.tm_mon); + of_property_read_u32(np, "ricoh,rtc-tm-mday", &pdata->time.tm_mday); + of_property_read_u32(np, "ricoh,rtc-tm-hour", &pdata->time.tm_hour); + of_property_read_u32(np, "ricoh,rtc-tm-min", &pdata->time.tm_min); + of_property_read_u32(np, "ricoh,rtc-tm-sec", &pdata->time.tm_sec); + of_node_put(np); + + return pdata; +} +#else +static struct ricoh619_rtc_platform_data * +ricoh619_rtc_dt_init(struct platform_device *pdev) +{ + return pdev->dev.platform_data; +} +#endif + +static int ricoh619_rtc_probe(struct platform_device *pdev) { - struct ricoh619_rtc_platform_data *pdata = pdev->dev.platform_data; + struct ricoh619_rtc_platform_data *pdata; + struct ricoh619 *ricoh619 = dev_get_drvdata(pdev->dev.parent); struct ricoh619_rtc *rtc; struct rtc_time tm; uint8_t Pon_flag,Alarm_flag; int err; uint8_t buff[6]; -// printk(KERN_INFO "******PMU RTC: Version 2013-08-01 REDS!******\n"); -// printk(KERN_INFO "PMU RTC: %s, ricoh619 driver run at 24H-mode\n", __func__); -// printk(KERN_INFO "PMU RTC: we never using periodic function and interrupt\n"); +// printk(KERN_INFO "******PMU RTC: Version 2014-01-01 REDS!******\n"); - if(!pdata) - { - dev_err(&pdev->dev, "no platform_data specified\n"); + pdata = ricoh619_rtc_dt_init(pdev); + if (!pdata) { + dev_err(&pdev->dev, "platform data isn't assigned to " + "rtc\n"); return -EINVAL; } + printk("%s,line=%d\n", __func__,__LINE__); - rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); + rtc = devm_kzalloc(ricoh619->dev,sizeof(*rtc), GFP_KERNEL); if(IS_ERR(rtc)) { err = PTR_ERR(rtc); dev_err(&pdev->dev, "no enough memory for ricoh619_rtc using\n"); - return err; + return -ENOMEM; } dev_set_drvdata(&pdev->dev, rtc); @@ -570,22 +614,19 @@ static int __devinit ricoh619_rtc_probe(struct platform_device *pdev) err = PTR_ERR(rtc->rtc); goto fail; } - - if(pdata->irq < 0) + + rtc->irq = irq_create_mapping(ricoh619->irq_domain, RICOH619_IRQ_DALE); + if(rtc->irq < 0) { dev_err(&pdev->dev, "\n no irq specified, wakeup is disabled\n"); rtc->irq = -1; rtc->irq_en = 0; } else - { - rtc->irq = pdata->irq; rtc->irq_en = 1; - } - //get interrupt flag err = ricoh619_rtc_alarm_is_enabled(&pdev->dev, &Alarm_flag); - if(err) + if (err<0) { dev_err(&pdev->dev, "5T619 RTC: Disable alarm interrupt error\n"); goto fail; @@ -594,7 +635,7 @@ static int __devinit ricoh619_rtc_probe(struct platform_device *pdev) // get PON flag err = ricoh619_rtc_Pon_get_clr(&pdev->dev, &Pon_flag); - if(err) + if (err<0) { dev_err(&pdev->dev, "5T619 RTC: get PON flag error\n"); goto fail; @@ -602,7 +643,7 @@ static int __devinit ricoh619_rtc_probe(struct platform_device *pdev) // disable rtc periodic function err = ricoh619_rtc_periodic_disable(&pdev->dev); - if(err) + if (err<0) { dev_err(&pdev->dev, "5T619 RTC: disable rtc periodic int error\n"); goto fail; @@ -610,7 +651,7 @@ static int __devinit ricoh619_rtc_probe(struct platform_device *pdev) // clearing RTC Adjust register err = ricoh619_rtc_clk_adjust(&pdev->dev, 0); - if(err) + if (err<0) { dev_err(&pdev->dev, "unable to program rtc_adjust reg\n"); err = -EBUSY; @@ -619,7 +660,7 @@ static int __devinit ricoh619_rtc_probe(struct platform_device *pdev) //disable interrupt err = ricoh619_rtc_alarm_enable(&pdev->dev, 0); - if(err) + if (err<0) { dev_err(&pdev->dev, "5T619 RTC: Disable alarm interrupt error\n"); goto fail; @@ -631,7 +672,7 @@ static int __devinit ricoh619_rtc_probe(struct platform_device *pdev) Alarm_flag = 0; // clear int flag err = ricoh619_rtc_alarm_flag_clr(&pdev->dev); - if(err) + if (err<0) { dev_err(&pdev->dev, "5T619 RTC: Pon=1 clear alarm flag error\n"); goto fail; @@ -639,7 +680,7 @@ static int __devinit ricoh619_rtc_probe(struct platform_device *pdev) // using 24h-mode err = ricoh619_rtc_hour_mode_set(&pdev->dev,1); - if(err) + if (err<0) { dev_err(&pdev->dev, "5T619 RTC: Pon=1 set 24h-mode error\n"); goto fail; @@ -691,7 +732,7 @@ static int __devinit ricoh619_rtc_probe(struct platform_device *pdev) buff[4] = tm.tm_mon +1; err = ricoh619_rtc_set_time(&pdev->dev, &tm); - if(err) + if (err<0) { dev_err(&pdev->dev, "5t619 RTC:\n failed to set time\n"); goto fail; @@ -701,7 +742,7 @@ static int __devinit ricoh619_rtc_probe(struct platform_device *pdev) buff[3] |= 0x80; /* set DAL_EXT */ err = ricoh619_write_regs(&pdev->dev, rtc_alarm_y_sec, sizeof(buff), buff); - if (err) + if (err<0) printk( "\n unable to set alarm\n"); } @@ -713,29 +754,26 @@ static int __devinit ricoh619_rtc_probe(struct platform_device *pdev) &ricoh619_rtc_ops, THIS_MODULE); // set interrupt and enable it - if(rtc->irq != -1) - { - rtc->irq = rtc->irq + RICOH619_IRQ_DALE; - err = request_threaded_irq(rtc->irq, NULL, ricoh619_rtc_irq, + if(rtc->irq != -1) { + err = devm_request_threaded_irq(&pdev->dev,rtc->irq, NULL, ricoh619_rtc_irq, IRQF_ONESHOT, "rtc_ricoh619", &pdev->dev); - if(err) + if (err<0) { dev_err(&pdev->dev, "request IRQ:%d fail\n", rtc->irq); rtc->irq = -1; err = ricoh619_rtc_alarm_enable(&pdev->dev, 0); - if(err) + if (err<0) { dev_err(&pdev->dev, "5T619 RTC: enable rtc alarm error\n"); goto fail; } } - else - { + else{ // enable wake enable_irq_wake(rtc->irq); // enable alarm_d err = ricoh619_rtc_alarm_enable(&pdev->dev, Alarm_flag); - if(err) + if (err<0) { dev_err(&pdev->dev, "failed rtc setup\n"); err = -EBUSY; @@ -747,14 +785,13 @@ static int __devinit ricoh619_rtc_probe(struct platform_device *pdev) { // system don't want to using alarm interrupt, so close it err = ricoh619_rtc_alarm_enable(&pdev->dev, 0); - if(err) + if (err<0) { dev_err(&pdev->dev, "5T619 RTC: Disable rtc alarm error\n"); goto fail; } dev_err(&pdev->dev, "ricoh619 interrupt is disabled\n"); } - printk(KERN_INFO "RICOH619 RTC Register Success\n"); ricoh619_read_regs(&pdev->dev, rtc_ctrl1, 1,&buff[0]); @@ -769,24 +806,31 @@ fail: return err; } -static int __devexit ricoh619_rtc_remove(struct platform_device *pdev) +static int ricoh619_rtc_remove(struct platform_device *pdev) { struct ricoh619_rtc *rtc = dev_get_drvdata(&pdev->dev); - if (rtc->irq != -1) - free_irq(rtc->irq, rtc); rtc_device_unregister(rtc->rtc); kfree(rtc); return 0; } +#ifdef CONFIG_OF +static const struct of_device_id ricoh619_rtc_dt_match[] = { + { .compatible = "ricoh,ricoh619-rtc", }, + {}, +}; +MODULE_DEVICE_TABLE(of, ricoh619_rtc_dt_match); +#endif + static struct platform_driver ricoh619_rtc_driver = { .driver = { - .name = "rtc_ricoh619", + .name = "ricoh619-rtc", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(ricoh619_rtc_dt_match), }, .probe = ricoh619_rtc_probe, - .remove = __devexit_p(ricoh619_rtc_remove), + .remove = ricoh619_rtc_remove, }; static int __init ricoh619_rtc_init(void) diff --git a/include/linux/mfd/ricoh619.h b/include/linux/mfd/ricoh619.h old mode 100644 new mode 100755 index b0936d0cb47f..fad38587744b --- a/include/linux/mfd/ricoh619.h +++ b/include/linux/mfd/ricoh619.h @@ -145,7 +145,7 @@ #define RICOH_LDO9_SLOT 0x23 #define RICOH_LDO10_SLOT 0x24 - +#define RICOH619_NUM_REGULATOR 17 /* RICOH619 IRQ definitions */ enum { @@ -318,6 +318,7 @@ struct ricoh619 { u8 gpedge_reg[MAX_GPEDGE_REG]; int bank_num; + struct irq_domain *irq_domain; }; struct ricoh619_platform_data { @@ -329,8 +330,11 @@ struct ricoh619_platform_data { struct ricoh619_gpio_init_data *gpio_init_data; int num_gpioinit_data; bool enable_shutdown_pin; - int (*pre_init)(struct ricoh619 *ricoh619); - int (*post_init)(struct ricoh619 *ricoh619); + bool pm_off; + struct regulator_init_data *reg_init_data[RICOH619_NUM_REGULATOR]; + int irq_gpio; + int pmic_sleep_gpio; /* */ + bool pmic_sleep; }; /* ==================================== */ @@ -366,9 +370,7 @@ extern int ricoh619_update(struct device *dev, u8 reg, uint8_t val, uint8_t mask); extern int ricoh619_update_bank1(struct device *dev, u8 reg, uint8_t val, uint8_t mask); -extern int ricoh619_power_off(void); -extern int ricoh619_irq_init(struct ricoh619 *ricoh619, int irq, int irq_base); +extern int ricoh619_irq_init(struct ricoh619 *ricoh619, int irq, struct ricoh619_platform_data *pdata); extern int ricoh619_irq_exit(struct ricoh619 *ricoh619); -extern int ricoh619_power_off(void); #endif diff --git a/include/linux/power/ricoh619_battery.h b/include/linux/power/ricoh619_battery.h old mode 100644 new mode 100755 index 32738df9a807..ec8c4fa8ec59 --- a/include/linux/power/ricoh619_battery.h +++ b/include/linux/power/ricoh619_battery.h @@ -1,5 +1,5 @@ /* - * include/linux/power/ricoh619-battery.c + * include/linux/power/ricoh619_battery.h * * RICOH RC5T619 Charger Driver * @@ -31,13 +31,12 @@ #define RICOH_FG_DBG(fmt, args...) {while(0);} #endif -/* Defined buttery information */ +/* Defined battery information */ #define ADC_VDD_MV 2800 #define MIN_VOLTAGE 3100 #define MAX_VOLTAGE 4200 #define B_VALUE 3435 - /* 619 Register information */ /* bank 0 */ #define PSWR_REG 0x07 @@ -48,13 +47,12 @@ #define ADCCNT3_REG 0x66 #define VBATDATAH_REG 0x6A #define VBATDATAL_REG 0x6B - -#define VSYSDATAH_REG 0x70 -#define VSYSDATAL_REG 0x71 +#define VSYSDATAH_REG 0x70 +#define VSYSDATAL_REG 0x71 #define CHGCTL1_REG 0xB3 -#define REGISET1_REG 0xB6 -#define REGISET2_REG 0xB7 +#define REGISET1_REG 0xB6 +#define REGISET2_REG 0xB7 #define CHGISET_REG 0xB8 #define TIMSET_REG 0xB9 #define BATSET1_REG 0xBA @@ -88,8 +86,8 @@ /* bank 1 */ /* Top address for battery initial setting */ #define BAT_INIT_TOP_REG 0xBC -#define TEMP_GAIN_H_REG 0xD6 -#define TEMP_OFF_H_REG 0xB8 +#define TEMP_GAIN_H_REG 0xD6 +#define TEMP_OFF_H_REG 0xD8 #define BAT_REL_SEL_REG 0xDA #define BAT_TA_SEL_REG 0xDB /**************************/ @@ -119,20 +117,17 @@ enum SupplyState { SUPPLY_STATE_USB, } ; -struct ricoh619_battery_platform_data { - int irq; - int alarm_vol_mv; - int multiple; - unsigned long monitor_time; +struct ricoh619_battery_type_data { int ch_vfchg; int ch_vrchg; int ch_vbatovset; int ch_ichg; + int ch_icchg; int ch_ilim_adp; int ch_ilim_usb; - int ch_icchg; int fg_target_vsys; int fg_target_ibat; + int fg_poff_vbat; int jt_en; int jt_hw_sw; int jt_temp_h; @@ -143,6 +138,15 @@ struct ricoh619_battery_platform_data { int jt_ichg_l; }; +#define BATTERY_TYPE_NUM 1 +struct ricoh619_battery_platform_data { + int irq; + int alarm_vol_mv; + int multiple; + unsigned long monitor_time; + struct ricoh619_battery_type_data type[BATTERY_TYPE_NUM]; +}; + extern struct ricoh619 *g_ricoh619; diff --git a/include/linux/power/ricoh61x_battery_init.h b/include/linux/power/ricoh61x_battery_init.h index e30ac142b2d6..9acfd09f4969 100755 --- a/include/linux/power/ricoh61x_battery_init.h +++ b/include/linux/power/ricoh61x_battery_init.h @@ -22,7 +22,7 @@ */ #ifndef __LINUX_POWER_RICOH61X_BATTERY_INIT_H #define __LINUX_POWER_RICOH61X_BATTERY_INIT_H - +/* uint8_t battery_init_para[][32] = { 0x0B, 0x3F, 0x0B, 0xCB, 0x0B, 0xEE, 0x0C, 0x08, 0x0C, 0x1E, 0x0C, 0x38, 0x0C, 0x5B, 0x0C, 0x94, @@ -34,12 +34,20 @@ uint8_t battery_init_para[][32] = { //0x0c, 0x92, 0x0c, 0xf4, 0x0d, 0x6f, 0x08, 0xca, //0x00, 0x36, 0x0f, 0xc8, 0x05, 0x2c, 0x22, 0x56 }; +*/ + +uint8_t battery_init_para[][32] = { + { + 0x0A, 0xB1, 0x0B, 0x44, 0x0B, 0xAE, 0x0C, 0x00, 0x0C, 0x11, 0x0C, 0x1B,0x0C, 0x42, 0x0C, 0x7D, + 0x0C, 0xB5, 0x0C, 0xFA, 0x0D, 0x53, 0x0A, 0xEC, 0x00, 0x46, 0x0F, 0xC8,0x05, 0x2C, 0x22, 0x56 + } +}; #endif /* -nominal_capacity=3800 +nominal_capacity=2800 cut-off_v=3400 thermistor_b=3435 board_impe=0 -- 2.34.1