mirror of
https://github.com/torvalds/linux.git
synced 2026-06-07 14:04:54 +02:00
rk312x:rt5025:support pmic rt5025
This commit is contained in:
parent
75bdc645ca
commit
476cbef830
74
Documentation/devicetree/bindings/mfd/rt5025.txt
Executable file
74
Documentation/devicetree/bindings/mfd/rt5025.txt
Executable file
|
|
@ -0,0 +1,74 @@
|
|||
Richtek RT5025 Multi-functional device
|
||||
|
||||
The RT5025 are Integrated Power Management Chips.
|
||||
These chips are connected to an i2c bus.
|
||||
|
||||
|
||||
Required properties:
|
||||
- compatible : Must be "rt,rt5025";
|
||||
- interrupts : This i2c device has an IRQ line connected to the main SoC
|
||||
- interrupt-parent : The parent interrupt controller.
|
||||
|
||||
Optional node:
|
||||
- Child nodes contain in the RT5025. The twl family is made of several variants
|
||||
that support a different number of features.
|
||||
|
||||
|
||||
Example:
|
||||
rt5025@35 {
|
||||
compatible = "rt,rt5025";
|
||||
reg = <0x35>;
|
||||
interrupt-parent = <&msmgpio>;
|
||||
interrupts = <73 0>;
|
||||
|
||||
rt5025_dcdc1: regulator_0 {
|
||||
compatible = "rt,rt5025-dcdc1";
|
||||
cell-index = <0>;
|
||||
regulator-name = "rt5025-dcdc1";
|
||||
regulator-min-microvolt = < 700000>;
|
||||
regulator-max-microvolt = <2275000>;
|
||||
rt,ramp_sel = <0x00>;
|
||||
rt,allow_mode_mask;
|
||||
qcom,comsumer-supplies = "rt5025-dcdc1", "";
|
||||
};
|
||||
|
||||
rt5025-charger {
|
||||
compatible = "rt,rt5025-charger";
|
||||
rt,te_en;
|
||||
//rt,screenon_adjust;
|
||||
rt,iprec = <0x00>;
|
||||
rt,ieoc = <0x00>;
|
||||
rt,vprec = <0x05>;
|
||||
rt,vdpm = <0x02>;
|
||||
rt,chg_volt = <4200>;
|
||||
rt,acchg_icc = <2000>;
|
||||
rt,usbtachg_icc = <2000>;
|
||||
rt,usbchg_icc = <500>;
|
||||
rt,screenon_icc = <500>;
|
||||
rt,temp = <0 150 500 600>;
|
||||
rt,temp_scalar = <0x30 0x2b 0x28 0x22 0x15 0x10 0x10 0x0d>;
|
||||
};
|
||||
|
||||
rt5025_gpiop: rt5025-gpio {
|
||||
compatible = "rt,rt5025-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
rt,ngpio = <3>;
|
||||
};
|
||||
|
||||
rt5025-irq {
|
||||
compatible = "rt,rt5025-irq";
|
||||
rt,irq-gpio = <&msmgpio 73 0x00>;
|
||||
};
|
||||
|
||||
rt5025-misc {
|
||||
compatible = "rt,rt5025-misc";
|
||||
rt,system_lv = <0x02>;
|
||||
rt,shdn_lpress = <0x01>;
|
||||
rt,start_lpress = <0x00>;
|
||||
rt,syslv_enshutdown;
|
||||
};
|
||||
|
||||
rt5025-debug {
|
||||
compatible = "rt,rt5025-debug";
|
||||
};
|
||||
14
Documentation/devicetree/bindings/power/rt5025-battery.txt
Executable file
14
Documentation/devicetree/bindings/power/rt5025-battery.txt
Executable file
|
|
@ -0,0 +1,14 @@
|
|||
Richtek RT5025 battery/fuelgauge function
|
||||
|
||||
The RT5025 battery is responsible to report the battery voltage/current
|
||||
, capacity, etc.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : Must be "rt,rt5025-battery".
|
||||
|
||||
Example:
|
||||
|
||||
rt5025-battery {
|
||||
compatible = "rt,rt5025-battery";
|
||||
};
|
||||
41
Documentation/devicetree/bindings/power/rt5025-charger.txt
Executable file
41
Documentation/devicetree/bindings/power/rt5025-charger.txt
Executable file
|
|
@ -0,0 +1,41 @@
|
|||
Richtek RT5025 Charger part
|
||||
|
||||
The RT5025 charger part is responsible to change the charging current/voltage, etc.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : Must be "rt,rt5025-charger".
|
||||
- rt,chg_volt : default charging voltage.
|
||||
- rt,ieoc : 0x0 is 10%, 0x1 is 20%.
|
||||
- rt,vdpm : 0x0 is 4V, 0x1 is 4.25V, 0x2 is 4.5V, 0x3 is disable.
|
||||
- rt,vprec: precharge voltage.
|
||||
- rt,iprec: precharge current.
|
||||
- rt,acchg_icc: rt-power ac charge current.
|
||||
- rt,usbtachg_icc: rt-power usbta charge current.
|
||||
- rt,ustchg_icc: rt-power normal usb charge current.
|
||||
- rt,screenon_icc: screen on charge current.
|
||||
- rt,te_en: enable terminate function.
|
||||
- rt,screenon_adjust: enable screen on lower charge current,
|
||||
screen off recovery to the default charge current.
|
||||
- rt,temp: jeita temperature, unit 0.1'c
|
||||
- rt,temp_scalar: jeita temperature scalar according to NTC spec.
|
||||
|
||||
Example:
|
||||
|
||||
rt5025-charger {
|
||||
compatible = "rt,rt5025-charger";
|
||||
rt,te_en;
|
||||
//rt,screenon_adjust;
|
||||
rt,iprec = <0x00>;
|
||||
rt,ieoc = <0x00>;
|
||||
rt,vprec = <0x05>;
|
||||
rt,vdpm = <0x02>;
|
||||
rt,chg_volt = <4200>;
|
||||
rt,acchg_icc = <2000>;
|
||||
rt,usbtachg_icc = <2000>;
|
||||
rt,usbchg_icc = <500>;
|
||||
rt,screenon_icc = <500>;
|
||||
rt,temp = <0 150 500 600>;
|
||||
rt,temp_scalar = <0x30 0x2b 0x28 0x22 0x15 0x10 0x10 0x0d>;
|
||||
};
|
||||
|
||||
27
Documentation/devicetree/bindings/regulator/rt5025-regulator.txt
Executable file
27
Documentation/devicetree/bindings/regulator/rt5025-regulator.txt
Executable file
|
|
@ -0,0 +1,27 @@
|
|||
Richtek RT5025 of regulators
|
||||
|
||||
Required properties:
|
||||
For rt5025 regulators/LDOs
|
||||
- compatible:
|
||||
- "rt,rt5025-dcdc1" for Buck1
|
||||
- "rt,rt5025-dcdc2" for Buck2
|
||||
- "rt,rt5025-dcdc3" for Buck3
|
||||
- "rt,rt5025-dcdc4" for Buck4/Boost
|
||||
- "rt,rt5025-ldo1" for Ldo1
|
||||
- "rt,rt5025-ldo2" for Ldo2
|
||||
- "rt,rt5025-ldo3" for Ldo3
|
||||
- "rt,rt5025-ldo4" for Ldo4
|
||||
- "rt,rt5025-ldo5" for Ldo5
|
||||
- "rt,rt5025-ldo6" for Ldo6
|
||||
|
||||
Example:
|
||||
|
||||
rt5025-dcdc1: regulator_0@0 {
|
||||
compatible = "rt,rt5025-dcdc1";
|
||||
cell-index = <0>;
|
||||
regulator-min-microvolt = < 700000>;
|
||||
regulator-max-microvolt = <2275000>;
|
||||
rt,ramp_sel = <0x00>;
|
||||
rt,allow_mode_mask;
|
||||
qcom,consumer-supplies = "rt5025-dcdc1", "";
|
||||
};
|
||||
|
|
@ -168,6 +168,11 @@ rk818: rk818@1c {
|
|||
reg = <0x1c>;
|
||||
status = "okay";
|
||||
};
|
||||
rt5025: rt5025@35 {
|
||||
compatible = "rt,rt5025";
|
||||
reg = <0x35>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
&i2c2 {
|
||||
status = "okay";
|
||||
|
|
@ -201,6 +206,106 @@ &hdmi {
|
|||
status = "okay";
|
||||
};
|
||||
|
||||
/include/ "rt5025.dtsi"
|
||||
&rt5025 {
|
||||
|
||||
rt5025_dcdc1: regulator_0 {
|
||||
regulator-name = "vdd_arm";
|
||||
regulator-min-microvolt = < 700000>;
|
||||
regulator-max-microvolt = <1500000>;
|
||||
qcom,comsumer-supplies = "vdd_arm", "";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
|
||||
};
|
||||
|
||||
rt5025_dcdc2: regulator_1 {
|
||||
regulator-name = "vdd_logic";
|
||||
regulator-min-microvolt = < 700000>;
|
||||
regulator-max-microvolt = <1500000>;
|
||||
qcom,comsumer-supplies = "vdd_logic", "";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
rt5025_dcdc3: regulator_2 {
|
||||
regulator-name = "rt5025-dcdc3";
|
||||
regulator-min-microvolt = < 1800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
qcom,comsumer-supplies = "rt5025-dcdc3", "";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
rt5025_dcdc4: regulator_3 {
|
||||
regulator-name = "rt5025-dcdc4";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
qcom,comsumer-supplies = "rt5025-dcdc4", "";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
rt5025_ldo1: regulator_4 {
|
||||
regulator-name = "rt5025-ldo1";
|
||||
regulator-min-microvolt = < 1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
qcom,comsumer-supplies = "rt5025-ldo1", "";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
rt5025_ldo2: regulator_5 {
|
||||
regulator-name = "rt5025-ldo2";
|
||||
regulator-min-microvolt = < 1200000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
qcom,comsumer-supplies = "rt5025-ldo2", "";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
rt5025_ldo3: regulator_6 {
|
||||
regulator-name = "rt5025-ldo3";
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <2800000>;
|
||||
qcom,comsumer-supplies = "rt5025-ldo3", "";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
rt5025_ldo4: regulator_7 {
|
||||
regulator-name = "rt5025-ldo4";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
qcom,comsumer-supplies = "rt5025-ldo4", "";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
rt5025_ldo5: regulator_8 {
|
||||
regulator-name = "rt5025-ldo5";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
qcom,comsumer-supplies = "rt5025-ldo5", "";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
rt5025_ldo6: regulator_9 {
|
||||
regulator-name = "rt5025-ldo6";
|
||||
regulator-min-microvolt = <330000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
qcom,comsumer-supplies = "rt5025-ldo6", "";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
rt5025-irq {
|
||||
compatible = "rt,rt5025-irq";
|
||||
rt,irq-gpio = <&gpio1 GPIO_B1 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
/include/ "rk818.dtsi"
|
||||
&rk818 {
|
||||
gpios =<&gpio1 GPIO_B1 GPIO_ACTIVE_HIGH>,<&gpio1 GPIO_A1 GPIO_ACTIVE_LOW>;
|
||||
|
|
|
|||
113
arch/arm/boot/dts/rt5025.dtsi
Executable file
113
arch/arm/boot/dts/rt5025.dtsi
Executable file
|
|
@ -0,0 +1,113 @@
|
|||
/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
&rt5025 {
|
||||
compatible = "rt,rt5025";
|
||||
// reg = <0x35>;
|
||||
|
||||
rt5025_dcdc1: regulator_0 {
|
||||
compatible = "rt,rt5025-dcdc1";
|
||||
cell-index = <0>;
|
||||
rt,ramp_sel = <0x00>;
|
||||
rt,allow_mode_mask;
|
||||
};
|
||||
|
||||
rt5025_dcdc2: regulator_1 {
|
||||
compatible = "rt,rt5025-dcdc2";
|
||||
cell-index = <1>;
|
||||
rt,ramp_sel = <0x00>;
|
||||
rt,allow_mode_mask;
|
||||
};
|
||||
|
||||
rt5025_dcdc3: regulator_2 {
|
||||
compatible = "rt,rt5025-dcdc3";
|
||||
cell-index = <2>;
|
||||
rt,ramp_sel = <0x00>;
|
||||
rt,allow_mode_mask;
|
||||
};
|
||||
|
||||
rt5025_dcdc4: regulator_3 {
|
||||
compatible = "rt,rt5025-dcdc4";
|
||||
cell-index = <3>;
|
||||
};
|
||||
|
||||
rt5025_ldo1: regulator_4 {
|
||||
compatible = "rt,rt5025-ldo1";
|
||||
cell-index = <4>;
|
||||
};
|
||||
|
||||
rt5025_ldo2: regulator_5 {
|
||||
compatible = "rt,rt5025-ldo2";
|
||||
cell-index = <5>;
|
||||
};
|
||||
|
||||
rt5025_ldo3: regulator_6 {
|
||||
compatible = "rt,rt5025-ldo3";
|
||||
cell-index = <6>;
|
||||
};
|
||||
|
||||
rt5025_ldo4: regulator_7 {
|
||||
compatible = "rt,rt5025-ldo4";
|
||||
cell-index = <7>;
|
||||
};
|
||||
|
||||
rt5025_ldo5: regulator_8 {
|
||||
compatible = "rt,rt5025-ldo5";
|
||||
cell-index = <8>;
|
||||
};
|
||||
|
||||
rt5025_ldo6: regulator_9 {
|
||||
compatible = "rt,rt5025-ldo6";
|
||||
cell-index = <9>;
|
||||
};
|
||||
|
||||
rt5025-charger {
|
||||
compatible = "rt,rt5025-charger";
|
||||
rt,te_en;
|
||||
//rt,screenon_adjust;
|
||||
rt,iprec = <0x00>;
|
||||
rt,ieoc = <0x00>;
|
||||
rt,vprec = <0x05>;
|
||||
rt,vdpm = <0x02>;
|
||||
rt,chg_volt = <4200>;
|
||||
rt,acchg_icc = <2000>;
|
||||
rt,usbtachg_icc = <2000>;
|
||||
rt,usbchg_icc = <500>;
|
||||
rt,screenon_icc = <500>;
|
||||
rt,temp = <0 150 500 600>;
|
||||
rt,temp_scalar = <0x30 0x2b 0x28 0x22 0x15 0x10 0x10 0x0d>;
|
||||
};
|
||||
|
||||
rt5025-battery {
|
||||
compatible = "rt,rt5025-battery";
|
||||
};
|
||||
|
||||
rt5025_gpio: rt5025-gpio {
|
||||
compatible = "rt,rt5025-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
rt,ngpio = <3>;
|
||||
};
|
||||
rt5025-misc {
|
||||
compatible = "rt,rt5025-misc";
|
||||
rt,vsyslv = <0x02>;
|
||||
rt,shdnlpress_time = <0x01>;
|
||||
rt,startlpress_time = <0x00>;
|
||||
rt,vsyslv_enshdn;
|
||||
rt,system-power-controller;
|
||||
|
||||
};
|
||||
|
||||
rt5025-debug {
|
||||
compatible = "rt,rt5025-debug";
|
||||
};
|
||||
};
|
||||
|
|
@ -209,6 +209,13 @@ config GPIO_RCAR
|
|||
help
|
||||
Say yes here to support GPIO on Renesas R-Car SoCs.
|
||||
|
||||
config GPIO_RT5025
|
||||
bool "Richtek RT5025 GPIO support"
|
||||
depends on MFD_RT5025
|
||||
default n
|
||||
help
|
||||
This is the gpio driver for RT5025 PMIC.
|
||||
|
||||
config GPIO_SPEAR_SPICS
|
||||
bool "ST SPEAr13xx SPI Chip Select as GPIO support"
|
||||
depends on PLAT_SPEAR
|
||||
|
|
|
|||
|
|
@ -87,3 +87,4 @@ obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o
|
|||
obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o
|
||||
obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o
|
||||
obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o
|
||||
obj-$(CONFIG_GPIO_RT5025) += gpio-rt5025.o
|
||||
|
|
|
|||
|
|
@ -2,12 +2,13 @@
|
|||
* drivers/gpio/rt5025-gpio.c
|
||||
* Driver foo Richtek RT5025 PMIC GPIO
|
||||
*
|
||||
* Copyright (C) 2013 Richtek Electronics
|
||||
* Copyright (C) 2014 Richtek Technologh Corp.
|
||||
* cy_huang <cy_huang@richtek.com>
|
||||
*
|
||||
* 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.
|
||||
* published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
|
@ -16,8 +17,8 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <linux/mfd/rt5025.h>
|
||||
#include <linux/mfd/rt5025-gpio.h>
|
||||
|
|
@ -26,21 +27,22 @@ struct rt5025_gpio_info {
|
|||
struct i2c_client *i2c;
|
||||
unsigned gpio_base;
|
||||
unsigned irq_base;
|
||||
int ngpio;
|
||||
struct gpio_chip gpio_chip;
|
||||
};
|
||||
|
||||
static inline int find_rt5025_gpioreg(unsigned off, int *gpio_reg)
|
||||
{
|
||||
int ret = 0;
|
||||
switch (off)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
*gpio_reg = RT5025_REG_GPIO0 + off;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
|
||||
switch (off) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
*gpio_reg = RT5025_REG_GPIO0 + off;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -50,17 +52,15 @@ static int rt5025_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
|||
struct rt5025_gpio_info *gi = dev_get_drvdata(chip->dev);
|
||||
int gpio_reg = 0;
|
||||
int ret = 0;
|
||||
|
||||
|
||||
ret = find_rt5025_gpioreg(offset , &gpio_reg);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
dev_err(chip->dev, "not a valid gpio index\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rt5025_clr_bits(gi->i2c, gpio_reg, RT5025_GPIO_DIRMASK);
|
||||
if (ret<0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
dev_err(chip->dev, "set gpio input fail\n");
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -68,40 +68,40 @@ static int rt5025_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int rt5025_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value)
|
||||
static int rt5025_gpio_direction_output(struct gpio_chip *chip,
|
||||
unsigned offset, int value)
|
||||
{
|
||||
struct rt5025_gpio_info *gi = dev_get_drvdata(chip->dev);
|
||||
int gpio_reg = 0;
|
||||
int ret = 0;
|
||||
|
||||
|
||||
ret = find_rt5025_gpioreg(offset, &gpio_reg);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
dev_err(chip->dev, "not a valid gpio index\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
ret = rt5025_clr_bits(gi->i2c, gpio_reg, RT5025_GPIO_DIRSHIFT);
|
||||
if (ret<0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
dev_err(chip->dev, "clr gpio direction fail\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rt5025_set_bits(gi->i2c, gpio_reg, RT5025_GPIO_OUTPUT<<RT5025_GPIO_DIRSHIFT);
|
||||
if (ret<0)
|
||||
{
|
||||
ret = rt5025_set_bits(gi->i2c, gpio_reg,
|
||||
RT5025_GPIO_OUTPUT<<RT5025_GPIO_DIRSHIFT);
|
||||
if (ret < 0) {
|
||||
dev_err(chip->dev, "set gpio output dir fail\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (value)
|
||||
ret = rt5025_set_bits(gi->i2c, gpio_reg, RT5025_GPIO_OVALUEMASK);
|
||||
ret = rt5025_set_bits(gi->i2c, gpio_reg,
|
||||
RT5025_GPIO_OVALUEMASK);
|
||||
else
|
||||
ret = rt5025_clr_bits(gi->i2c, gpio_reg, RT5025_GPIO_OVALUEMASK);
|
||||
ret = rt5025_clr_bits(gi->i2c, gpio_reg,
|
||||
RT5025_GPIO_OVALUEMASK);
|
||||
|
||||
if (ret<0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
dev_err(chip->dev, "set gpio output value fail\n");
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -114,62 +114,88 @@ static int rt5025_gpio_get_value(struct gpio_chip *chip, unsigned offset)
|
|||
struct rt5025_gpio_info *gi = dev_get_drvdata(chip->dev);
|
||||
int gpio_reg = 0;
|
||||
int ret = 0;
|
||||
|
||||
|
||||
ret = find_rt5025_gpioreg(offset, &gpio_reg);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
dev_err(chip->dev, "not a valid gpio index\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
ret = rt5025_reg_read(gi->i2c, gpio_reg);
|
||||
if (ret<0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
dev_err(chip->dev, "read gpio register fail\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return (ret&RT5025_GPIO_IVALUEMASK)?1:0;
|
||||
return (ret&RT5025_GPIO_IVALUEMASK)?1 : 0;
|
||||
}
|
||||
|
||||
static void rt5025_gpio_set_value(struct gpio_chip *chip, unsigned offset, int value)
|
||||
static void rt5025_gpio_set_value(struct gpio_chip *chip,
|
||||
unsigned offset, int value)
|
||||
{
|
||||
struct rt5025_gpio_info *gi = dev_get_drvdata(chip->dev);
|
||||
int gpio_reg = 0;
|
||||
int ret = 0;
|
||||
|
||||
|
||||
ret = find_rt5025_gpioreg(offset, &gpio_reg);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
dev_err(chip->dev, "not a valid gpio index\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (value)
|
||||
ret = rt5025_set_bits(gi->i2c, gpio_reg, RT5025_GPIO_OVALUEMASK);
|
||||
ret = rt5025_set_bits(gi->i2c, gpio_reg,
|
||||
RT5025_GPIO_OVALUEMASK);
|
||||
else
|
||||
ret = rt5025_clr_bits(gi->i2c, gpio_reg, RT5025_GPIO_OVALUEMASK);
|
||||
ret = rt5025_clr_bits(gi->i2c, gpio_reg,
|
||||
RT5025_GPIO_OVALUEMASK);
|
||||
|
||||
if (ret<0)
|
||||
{
|
||||
if (ret < 0)
|
||||
dev_err(chip->dev, "read gpio register fail\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int __devinit rt5025_gpio_probe(struct platform_device *pdev)
|
||||
static int rt_parse_dt(struct rt5025_gpio_info *gi, struct device *dev)
|
||||
{
|
||||
#ifdef CONFIG_OF
|
||||
struct device_node *np = dev->of_node;
|
||||
|
||||
of_property_read_u32(np, "rt,ngpio", &gi->ngpio);
|
||||
#endif /* #ifdef CONFIG_OF */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt_parse_pdata(struct rt5025_gpio_info *gi, struct device *dev)
|
||||
{
|
||||
struct rt5025_gpio_data *gpio_pdata = dev->platform_data;
|
||||
|
||||
gi->ngpio = gpio_pdata->ngpio;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5025_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent);
|
||||
struct rt5025_platform_data *pdata = chip->dev->platform_data;
|
||||
struct rt5025_platform_data *pdata = (pdev->dev.parent)->platform_data;
|
||||
struct rt5025_gpio_info *gi;
|
||||
int ret = 0;
|
||||
bool use_dt = pdev->dev.of_node;
|
||||
int rc = 0;
|
||||
|
||||
gi = kzalloc(sizeof(*gi), GFP_KERNEL);
|
||||
gi = devm_kzalloc(&pdev->dev, sizeof(*gi), GFP_KERNEL);
|
||||
if (!gi)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
gi->i2c = chip->i2c;
|
||||
gi->gpio_base = pdata->gpio_data->gpio_base;
|
||||
gi->irq_base = pdata->gpio_data->irq_base;
|
||||
if (use_dt) {
|
||||
rt_parse_dt(gi, &pdev->dev);
|
||||
} else {
|
||||
if (!pdata) {
|
||||
rc = -EINVAL;
|
||||
goto out_dev;
|
||||
}
|
||||
pdev->dev.platform_data = pdata->gpio_pdata;
|
||||
rt_parse_pdata(gi, &pdev->dev);
|
||||
}
|
||||
|
||||
gi->gpio_chip.direction_input = rt5025_gpio_direction_input;
|
||||
gi->gpio_chip.direction_output = rt5025_gpio_direction_output;
|
||||
|
|
@ -177,59 +203,62 @@ static int __devinit rt5025_gpio_probe(struct platform_device *pdev)
|
|||
gi->gpio_chip.set = rt5025_gpio_set_value;
|
||||
gi->gpio_chip.can_sleep = 0;
|
||||
|
||||
gi->gpio_chip.base = gi->gpio_base;
|
||||
gi->gpio_chip.ngpio = RT5025_GPIO_NR;
|
||||
gi->gpio_chip.base = -1;
|
||||
gi->gpio_chip.ngpio = gi->ngpio;
|
||||
gi->gpio_chip.label = pdev->name;
|
||||
gi->gpio_chip.dev = &pdev->dev;
|
||||
gi->gpio_chip.owner = THIS_MODULE;
|
||||
|
||||
ret = gpiochip_add(&gi->gpio_chip);
|
||||
if (ret)
|
||||
rc = gpiochip_add(&gi->gpio_chip);
|
||||
if (rc)
|
||||
goto out_dev;
|
||||
|
||||
|
||||
platform_set_drvdata(pdev, gi);
|
||||
return ret;
|
||||
dev_info(&pdev->dev, "driver successfully loaded\n");
|
||||
return rc;
|
||||
out_dev:
|
||||
kfree(gi);
|
||||
return ret;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __devexit rt5025_gpio_remove(struct platform_device *pdev)
|
||||
static int rt5025_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
int rc = 0;
|
||||
struct rt5025_gpio_info *gi = platform_get_drvdata(pdev);
|
||||
|
||||
ret = gpiochip_remove(&gi->gpio_chip);
|
||||
kfree(gi);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
rc = gpiochip_remove(&gi->gpio_chip);
|
||||
dev_info(&pdev->dev, "\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver rt5025_gpio_driver =
|
||||
{
|
||||
.driver = {
|
||||
.name = RT5025_DEVICE_NAME "-gpio",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = rt5025_gpio_probe,
|
||||
.remove = __devexit_p(rt5025_gpio_remove),
|
||||
static struct of_device_id rt_match_table[] = {
|
||||
{ .compatible = "rt,rt5025-gpio",},
|
||||
{},
|
||||
};
|
||||
|
||||
static int __init rt5025_gpio_init(void)
|
||||
static struct platform_driver rt5025_gpio_driver = {
|
||||
.driver = {
|
||||
.name = RT5025_DEV_NAME "-gpio",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = rt_match_table,
|
||||
},
|
||||
.probe = rt5025_gpio_probe,
|
||||
.remove = rt5025_gpio_remove,
|
||||
};
|
||||
|
||||
static int rt5025_gpio_init(void)
|
||||
{
|
||||
return platform_driver_register(&rt5025_gpio_driver);
|
||||
}
|
||||
subsys_initcall_sync(rt5025_gpio_init);
|
||||
fs_initcall_sync(rt5025_gpio_init);
|
||||
|
||||
static void __exit rt5025_gpio_exit(void)
|
||||
static void rt5025_gpio_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&rt5025_gpio_driver);
|
||||
}
|
||||
module_exit(rt5025_gpio_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("CY Huang <cy_huang@richtek.com>");
|
||||
MODULE_DESCRIPTION("GPIO driver for RT5025");
|
||||
MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-gpio");
|
||||
MODULE_ALIAS("platform:" RT5025_DEV_NAME "-gpio");
|
||||
MODULE_VERSION(RT5025_DRV_VER);
|
||||
|
|
@ -169,6 +169,42 @@ config MFD_MC13XXX_I2C
|
|||
help
|
||||
Select this if your MC13xxx is connected via an I2C bus.
|
||||
|
||||
config MFD_RT5025
|
||||
bool "RT5025 PMIC Chip Core driver"
|
||||
depends on I2C
|
||||
select MFD_CORE
|
||||
default n
|
||||
help
|
||||
Enable RT5025 core driver.
|
||||
|
||||
config MISC_RT5025
|
||||
bool "RT5025 PMIC chip misc configuration"
|
||||
depends on MFD_RT5025
|
||||
default n
|
||||
help
|
||||
Enable RT5025 Misc configuration.
|
||||
|
||||
config IRQ_RT5025
|
||||
bool "RT5025_PMIC chip irq driver"
|
||||
depends on MFD_RT5025
|
||||
default n
|
||||
help
|
||||
Enable RT5025 IRQ configuration and interrupt.
|
||||
|
||||
config DEBUG_RT5025
|
||||
bool "RT5025 PMIC Chip Core Debug"
|
||||
depends on MFD_RT5025 && DEBUG_FS
|
||||
default n
|
||||
help
|
||||
Enable RT5025 core debug driver.
|
||||
|
||||
config MFD_RT_SHOW_INFO
|
||||
bool "RT5025 PMIC Debug log Flag"
|
||||
depends on MFD_RT5025
|
||||
default n
|
||||
help
|
||||
Enable the RT5025 PMIC debug log.
|
||||
|
||||
config HTC_EGPIO
|
||||
bool "HTC EGPIO support"
|
||||
depends on GENERIC_HARDIRQS && GPIOLIB && ARM
|
||||
|
|
|
|||
|
|
@ -55,6 +55,11 @@ obj-$(CONFIG_MFD_WM8350) += wm8350.o
|
|||
obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o
|
||||
obj-$(CONFIG_MFD_WM8994) += wm8994-core.o wm8994-irq.o wm8994-regmap.o
|
||||
|
||||
obj-$(CONFIG_MFD_RT5025) += rt5025-i2c.o rt5025-core.o
|
||||
obj-$(CONFIG_MISC_RT5025) += rt5025-misc.o
|
||||
obj-$(CONFIG_IRQ_RT5025) += rt5025-irq.o
|
||||
obj-$(CONFIG_DEBUG_RT5025) += rt5025-debug.o
|
||||
|
||||
obj-$(CONFIG_TPS6105X) += tps6105x.o
|
||||
obj-$(CONFIG_TPS65010) += tps65010.o
|
||||
obj-$(CONFIG_TPS6507X) += tps6507x.o
|
||||
|
|
|
|||
207
drivers/mfd/rt5025-core.c
Normal file → Executable file
207
drivers/mfd/rt5025-core.c
Normal file → Executable file
|
|
@ -2,12 +2,13 @@
|
|||
* drivers/mfd/rt5025-core.c
|
||||
* Driver for Richtek RT5025 Core PMIC
|
||||
*
|
||||
* Copyright (C) 2013 Richtek Electronics
|
||||
* Copyright (C) 2014 Richtek Technology Corp.
|
||||
* cy_huang <cy_huang@richtek.com>
|
||||
*
|
||||
* 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.
|
||||
* published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
|
@ -15,101 +16,144 @@
|
|||
#include <linux/version.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/mfd/core.h>
|
||||
|
||||
#include <linux/mfd/rt5025.h>
|
||||
|
||||
#ifdef CONFIG_REGULATOR_RT5025
|
||||
#define RT5025_VR_DEVS(_id) \
|
||||
#ifdef CONFIG_OF
|
||||
#define RT5025_BUCKVR_DEVS(_id, _idx) \
|
||||
{ \
|
||||
.name = RT5025_DEVICE_NAME "-regulator", \
|
||||
.name = RT5025_DEV_NAME "-regulator", \
|
||||
.num_resources = 0, \
|
||||
.of_compatible = "rt," RT5025_DEV_NAME "-dcdc" #_idx , \
|
||||
.id = RT5025_ID_##_id, \
|
||||
}
|
||||
|
||||
#define RT5025_LDOVR_DEVS(_id, _idx) \
|
||||
{ \
|
||||
.name = RT5025_DEV_NAME "-regulator", \
|
||||
.num_resources = 0, \
|
||||
.of_compatible = "rt," RT5025_DEV_NAME "-ldo" #_idx , \
|
||||
.id = RT5025_ID_##_id, \
|
||||
}
|
||||
#else
|
||||
#define RT5025_BUCKVR_DEVS(_id, _idx) \
|
||||
{ \
|
||||
.name = RT5025_DEV_NAME "-regulator", \
|
||||
.num_resources = 0, \
|
||||
.id = RT5025_ID_##_id, \
|
||||
}
|
||||
|
||||
#define RT5025_LDOVR_DEVS(_id, _idx) \
|
||||
{ \
|
||||
.name = RT5025_DEV_NAME "-regulator", \
|
||||
.num_resources = 0, \
|
||||
.id = RT5025_ID_##_id, \
|
||||
}
|
||||
#endif /* #ifdef CONFIG_OF */
|
||||
static struct mfd_cell regulator_devs[] = {
|
||||
RT5025_VR_DEVS(DCDC1),
|
||||
RT5025_VR_DEVS(DCDC2),
|
||||
RT5025_VR_DEVS(DCDC3),
|
||||
RT5025_VR_DEVS(DCDC4),
|
||||
RT5025_VR_DEVS(LDO1),
|
||||
RT5025_VR_DEVS(LDO2),
|
||||
RT5025_VR_DEVS(LDO3),
|
||||
RT5025_VR_DEVS(LDO4),
|
||||
RT5025_VR_DEVS(LDO5),
|
||||
RT5025_VR_DEVS(LDO6),
|
||||
RT5025_BUCKVR_DEVS(DCDC1, 1),
|
||||
RT5025_BUCKVR_DEVS(DCDC2, 2),
|
||||
RT5025_BUCKVR_DEVS(DCDC3, 3),
|
||||
RT5025_BUCKVR_DEVS(DCDC4, 4),
|
||||
RT5025_LDOVR_DEVS(LDO1, 1),
|
||||
RT5025_LDOVR_DEVS(LDO2, 2),
|
||||
RT5025_LDOVR_DEVS(LDO3, 3),
|
||||
RT5025_LDOVR_DEVS(LDO4, 4),
|
||||
RT5025_LDOVR_DEVS(LDO5, 5),
|
||||
RT5025_LDOVR_DEVS(LDO6, 6),
|
||||
};
|
||||
#endif /* CONFIG_REGULATOR_RT5025 */
|
||||
#endif /* #ifdef CONFIG_REGULATOR_RT5025 */
|
||||
|
||||
#ifdef CONFIG_POWER_RT5025
|
||||
static struct mfd_cell power_devs[] = {
|
||||
#ifdef CONFIG_CHARGER_RT5025
|
||||
static struct mfd_cell chg_devs[] = {
|
||||
{
|
||||
.name = RT5025_DEVICE_NAME "-power",
|
||||
.id = -1,
|
||||
.num_resources = 0,
|
||||
},
|
||||
{
|
||||
.name = RT5025_DEVICE_NAME "-swjeita",
|
||||
.id = -1,
|
||||
.num_resources = 0,
|
||||
},
|
||||
{
|
||||
.name = RT5025_DEVICE_NAME "-battery",
|
||||
.name = RT5025_DEV_NAME "-charger",
|
||||
.id = -1,
|
||||
.num_resources = 0,
|
||||
#ifdef CONFIG_OF
|
||||
.of_compatible = "rt," RT5025_DEV_NAME "-charger" ,
|
||||
#endif /*#ifdef CONFIG_OF */
|
||||
},
|
||||
};
|
||||
#endif /* CONFIG_POWER_RT5025 */
|
||||
#endif /* #ifdef CONFIG_CHARGER_RT5025 */
|
||||
|
||||
#ifdef CONFIG_BATTERY_RT5025
|
||||
static struct mfd_cell fg_devs[] = {
|
||||
{
|
||||
.name = RT5025_DEV_NAME "-battery",
|
||||
.id = -1,
|
||||
.num_resources = 0,
|
||||
#ifdef CONFIG_OF
|
||||
.of_compatible = "rt," RT5025_DEV_NAME "-battery" ,
|
||||
#endif /*#ifdef CONFIG_OF */
|
||||
},
|
||||
};
|
||||
#endif /* #ifdef CONFIG_BATTERY_RT5025 */
|
||||
|
||||
#ifdef CONFIG_GPIO_RT5025
|
||||
static struct mfd_cell gpio_devs[] = {
|
||||
{
|
||||
.name = RT5025_DEVICE_NAME "-gpio",
|
||||
.name = RT5025_DEV_NAME "-gpio",
|
||||
.id = -1,
|
||||
.num_resources = 0,
|
||||
#ifdef CONFIG_OF
|
||||
.of_compatible = "rt," RT5025_DEV_NAME "-gpio" ,
|
||||
#endif /*#ifdef CONFIG_OF */
|
||||
},
|
||||
};
|
||||
#endif /* CONFIG_GPIO_RT5025 */
|
||||
#endif /* #ifdef CONFIG_GPIO_RT5025 */
|
||||
|
||||
#ifdef CONFIG_MFD_RT5025_MISC
|
||||
#ifdef CONFIG_MISC_RT5025
|
||||
static struct mfd_cell misc_devs[] = {
|
||||
{
|
||||
.name = RT5025_DEVICE_NAME "-misc",
|
||||
.name = RT5025_DEV_NAME "-misc",
|
||||
.id = -1,
|
||||
.num_resources = 0,
|
||||
#ifdef CONFIG_OF
|
||||
.of_compatible = "rt," RT5025_DEV_NAME "-misc" ,
|
||||
#endif /*#ifdef CONFIG_OF */
|
||||
},
|
||||
};
|
||||
#endif /* CONFIG_MFD_RT5025_MISC */
|
||||
#endif /* #ifdef CONFIG_MISC_RT5025 */
|
||||
|
||||
#ifdef CONFIG_MFD_RT5025_IRQ
|
||||
#ifdef CONFIG_IRQ_RT5025
|
||||
static struct mfd_cell irq_devs[] = {
|
||||
{
|
||||
.name = RT5025_DEVICE_NAME "-irq",
|
||||
.name = RT5025_DEV_NAME "-irq",
|
||||
.id = -1,
|
||||
.num_resources = 0,
|
||||
#ifdef CONFIG_OF
|
||||
.of_compatible = "rt," RT5025_DEV_NAME "-irq" ,
|
||||
#endif /*#ifdef CONFIG_OF */
|
||||
},
|
||||
};
|
||||
#endif /* CONFIG_MFD_RT5025_IRQ */
|
||||
#endif /* #ifdef CONFIG_IRQ_RT5025 */
|
||||
|
||||
#ifdef CONFIG_MFD_RT5025_DEBUG
|
||||
#ifdef CONFIG_DEBUG_RT5025
|
||||
static struct mfd_cell debug_devs[] = {
|
||||
{
|
||||
.name = RT5025_DEVICE_NAME "-debug",
|
||||
.name = RT5025_DEV_NAME "-debug",
|
||||
.id = -1,
|
||||
.num_resources = 0,
|
||||
#ifdef CONFIG_OF
|
||||
.of_compatible = "rt," RT5025_DEV_NAME "-debug" ,
|
||||
#endif /*#ifdef CONFIG_OF */
|
||||
},
|
||||
};
|
||||
#endif /* CONFIG_MFD_RT5025_DEBUG */
|
||||
#endif /* #ifdef CONFIG_DEBUG_RT5025 */
|
||||
|
||||
int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_data *pdata)
|
||||
int rt5025_core_init(struct rt5025_chip *chip,
|
||||
struct rt5025_platform_data *pdata)
|
||||
{
|
||||
int ret = 0;
|
||||
bool use_dt = chip->dev->of_node;
|
||||
|
||||
RTINFO("Start to initialize all device\n");
|
||||
|
||||
#ifdef CONFIG_REGULATOR_RT5025
|
||||
if (pdata && pdata->regulator[0]) {
|
||||
if (use_dt || (pdata && pdata->regulator[0])) {
|
||||
RTINFO("mfd add regulators dev\n");
|
||||
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(3,6,0))
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
|
||||
ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0],
|
||||
ARRAY_SIZE(regulator_devs),
|
||||
NULL, 0, NULL);
|
||||
|
|
@ -117,24 +161,43 @@ int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_
|
|||
ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0],
|
||||
ARRAY_SIZE(regulator_devs),
|
||||
NULL, 0);
|
||||
#endif /* LINUX_VERSION_CODE>=KERNL_VERSION(3,6,0) */
|
||||
#endif /* LINUX_VERSION_CODE >= KERNL_VERSION(3,6,0) */
|
||||
if (ret < 0) {
|
||||
dev_err(chip->dev, "Failed to add regulator subdev\n");
|
||||
goto out_dev;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_REGULATOR_RT5025 */
|
||||
#endif /* #ifdef CONFIG_REGULATOR_RT5025 */
|
||||
|
||||
#ifdef CONFIG_POWER_RT5025
|
||||
if (pdata && pdata->power_data && pdata->jeita_data) {
|
||||
RTINFO("mfd add power dev\n");
|
||||
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(3,6,0))
|
||||
ret = mfd_add_devices(chip->dev, 0, &power_devs[0],
|
||||
ARRAY_SIZE(power_devs),
|
||||
NULL, 0,NULL);
|
||||
#ifdef CONFIG_CHARGER_RT5025
|
||||
if (use_dt || (pdata && pdata->chg_pdata)) {
|
||||
RTINFO("mfd add charger dev\n");
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
|
||||
ret = mfd_add_devices(chip->dev, 0, &chg_devs[0],
|
||||
ARRAY_SIZE(chg_devs),
|
||||
NULL, 0, NULL);
|
||||
#else
|
||||
ret = mfd_add_devices(chip->dev, 0, &power_devs[0],
|
||||
ARRAY_SIZE(power_devs),
|
||||
ret = mfd_add_devices(chip->dev, 0, &chg_devs[0],
|
||||
ARRAY_SIZE(chg_devs),
|
||||
NULL, 0);
|
||||
#endif
|
||||
if (ret < 0) {
|
||||
dev_err(chip->dev, "Failed to add power supply subdev\n");
|
||||
goto out_dev;
|
||||
}
|
||||
}
|
||||
#endif /* #ifdef CONFIG_CHARGER_RT5025 */
|
||||
|
||||
#ifdef CONFIG_BATTERY_RT5025
|
||||
if (use_dt || (pdata)) {
|
||||
RTINFO("mfd add fuelgauge dev\n");
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
|
||||
ret = mfd_add_devices(chip->dev, 0, &fg_devs[0],
|
||||
ARRAY_SIZE(fg_devs),
|
||||
NULL, 0, NULL);
|
||||
#else
|
||||
ret = mfd_add_devices(chip->dev, 0, &fg_devs[0],
|
||||
ARRAY_SIZE(fg_devs),
|
||||
NULL, 0);
|
||||
#endif
|
||||
if (ret < 0) {
|
||||
|
|
@ -143,13 +206,13 @@ int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_
|
|||
goto out_dev;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_MFD_RT5025 */
|
||||
#endif /* #ifdef CONFIG_BATTERY_RT5025 */
|
||||
|
||||
//Initialize the RT5025_GPIO
|
||||
/*Initialize the RT5025_GPIO*/
|
||||
#ifdef CONFIG_GPIO_RT5025
|
||||
if (pdata && pdata->gpio_data) {
|
||||
if (use_dt || (pdata && pdata->gpio_pdata)) {
|
||||
RTINFO("mfd add gpios dev\n");
|
||||
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(3,6,0))
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
|
||||
ret = mfd_add_devices(chip->dev, 0, &gpio_devs[0],
|
||||
ARRAY_SIZE(gpio_devs),
|
||||
NULL, 0, NULL);
|
||||
|
|
@ -163,12 +226,12 @@ int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_
|
|||
goto out_dev;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_GPIO_RT5025 */
|
||||
#endif /* #ifdef CONFIG_GPIO_RT5025 */
|
||||
|
||||
#ifdef CONFIG_MFD_RT5025_MISC
|
||||
if (pdata && pdata->misc_data) {
|
||||
#ifdef CONFIG_MISC_RT5025
|
||||
if (use_dt || (pdata && pdata->misc_pdata)) {
|
||||
RTINFO("mfd add misc dev\n");
|
||||
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(3,6,0))
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
|
||||
ret = mfd_add_devices(chip->dev, 0, &misc_devs[0],
|
||||
ARRAY_SIZE(misc_devs),
|
||||
NULL, 0, NULL);
|
||||
|
|
@ -182,12 +245,12 @@ int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_
|
|||
goto out_dev;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_MFD_RT5025_MISC */
|
||||
#endif /* #ifdef CONFIG_MISC_RT5025 */
|
||||
|
||||
#ifdef CONFIG_MFD_RT5025_IRQ
|
||||
if (pdata && pdata->irq_data) {
|
||||
#ifdef CONFIG_IRQ_RT5025
|
||||
if (use_dt || (pdata && pdata->irq_pdata)) {
|
||||
RTINFO("mfd add irq dev\n");
|
||||
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(3,6,0))
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
|
||||
ret = mfd_add_devices(chip->dev, 0, &irq_devs[0],
|
||||
ARRAY_SIZE(irq_devs),
|
||||
NULL, 0, NULL);
|
||||
|
|
@ -201,11 +264,11 @@ int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_
|
|||
goto out_dev;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_MFD_RT5025_IRQ */
|
||||
#endif /* #ifdef CONFIG_IRQ_RT5025 */
|
||||
|
||||
#ifdef CONFIG_MFD_RT5025_DEBUG
|
||||
#ifdef CONFIG_DEBUG_RT5025
|
||||
RTINFO("mfd add debug dev\n");
|
||||
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(3,6,0))
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
|
||||
ret = mfd_add_devices(chip->dev, 0, &debug_devs[0],
|
||||
ARRAY_SIZE(debug_devs),
|
||||
NULL, 0, NULL);
|
||||
|
|
@ -218,7 +281,7 @@ int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_
|
|||
dev_err(chip->dev, "Failed to add debug subdev\n");
|
||||
goto out_dev;
|
||||
}
|
||||
#endif /* CONFIG_MFD_RT5025_DEBUG */
|
||||
#endif /* CONFIG_DEBUG_RT5025 */
|
||||
|
||||
RTINFO("Initialize all device successfully\n");
|
||||
return ret;
|
||||
|
|
@ -228,7 +291,7 @@ int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_
|
|||
}
|
||||
EXPORT_SYMBOL(rt5025_core_init);
|
||||
|
||||
int __devexit rt5025_core_deinit(struct rt5025_chip *chip)
|
||||
int rt5025_core_deinit(struct rt5025_chip *chip)
|
||||
{
|
||||
mfd_remove_devices(chip->dev);
|
||||
return 0;
|
||||
|
|
|
|||
232
drivers/mfd/rt5025-debug.c
Normal file → Executable file
232
drivers/mfd/rt5025-debug.c
Normal file → Executable file
|
|
@ -2,12 +2,13 @@
|
|||
* drivers/mfd/rt5025-debug.c
|
||||
* Driver foo Richtek RT5025 PMIC Debug
|
||||
*
|
||||
* Copyright (C) 2013 Richtek Electronics
|
||||
* Copyright (C) 2013 Richtek Technologh Corp.
|
||||
* cy_huang <cy_huang@richtek.com>
|
||||
*
|
||||
* 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.
|
||||
* published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
|
@ -15,26 +16,33 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <linux/mfd/rt5025.h>
|
||||
|
||||
struct rt5025_debug_info {
|
||||
struct i2c_client *i2c;
|
||||
struct device *dev;
|
||||
unsigned char reg_addr;
|
||||
unsigned char reg_data;
|
||||
};
|
||||
|
||||
static struct i2c_client *client;
|
||||
static struct dentry *debugfs_rt_dent;
|
||||
static struct dentry *debugfs_peek;
|
||||
static struct dentry *debugfs_poke;
|
||||
static struct dentry *debugfs_regs;
|
||||
static struct dentry *debugfs_reset_b;
|
||||
struct rt_debug_st {
|
||||
void *info;
|
||||
int id;
|
||||
};
|
||||
|
||||
static unsigned char read_data[10];
|
||||
enum {
|
||||
RT5025_DBG_REG,
|
||||
RT5025_DBG_DATA,
|
||||
RT5025_DBG_REGS,
|
||||
RT5025_DBG_MAX
|
||||
};
|
||||
|
||||
static struct dentry *debugfs_rt_dent;
|
||||
static struct dentry *debugfs_file[RT5025_DBG_MAX];
|
||||
static struct rt_debug_st rtdbg_data[RT5025_DBG_MAX];
|
||||
|
||||
static int reg_debug_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
|
|
@ -60,37 +68,60 @@ static int get_parameters(char *buf, long int *param1, int num_of_par)
|
|||
return -EINVAL;
|
||||
|
||||
token = strsep(&buf, " ");
|
||||
}
|
||||
else
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define LOG_FORMAT "0x%02x\n0x%02x\n0x%02x\n0x%02x\n0x%02x\n"
|
||||
|
||||
static ssize_t reg_debug_read(struct file *filp, char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char *access_str = filp->private_data;
|
||||
char lbuf[150];
|
||||
if (!strcmp(access_str, "regs"))
|
||||
{
|
||||
RTINFO("read regs file\n");
|
||||
/* read regs */
|
||||
snprintf(lbuf, sizeof(lbuf), LOG_FORMAT LOG_FORMAT, read_data[0], \
|
||||
read_data[1], read_data[2], read_data[3], read_data[4], read_data[5], \
|
||||
read_data[6], read_data[7], read_data[8], read_data[9]);
|
||||
struct rt_debug_st *st = filp->private_data;
|
||||
struct rt5025_debug_info *di = st->info;
|
||||
char lbuf[1000];
|
||||
int i = 0, j = 0;
|
||||
|
||||
lbuf[0] = '\0';
|
||||
switch (st->id) {
|
||||
case RT5025_DBG_REG:
|
||||
snprintf(lbuf, sizeof(lbuf), "0x%x\n", di->reg_addr);
|
||||
break;
|
||||
case RT5025_DBG_DATA:
|
||||
di->reg_data = (unsigned char)rt5025_reg_read(di->i2c,
|
||||
di->reg_addr);
|
||||
snprintf(lbuf, sizeof(lbuf), "0x%x\n", di->reg_data);
|
||||
break;
|
||||
case RT5025_DBG_REGS:
|
||||
for (i = RT5025_REG_RANGE1START;
|
||||
i <= RT5025_REG_RANGE1END; i++)
|
||||
j += sprintf(lbuf+j, "0x%02x:%02x\n", i, \
|
||||
rt5025_reg_read(di->i2c, i));
|
||||
for (i = RT5025_REG_RANGE2START;
|
||||
i <= RT5025_REG_RANGE2END; i++)
|
||||
j += sprintf(lbuf+j, "0x%02x:%02x\n", i, \
|
||||
rt5025_reg_read(di->i2c, i));
|
||||
for (i = RT5025_REG_RANGE3START;
|
||||
i <= RT5025_REG_RANGE3END; i++)
|
||||
j += sprintf(lbuf+j, "0x%02x:%02x\n", i, \
|
||||
rt5025_reg_read(di->i2c, i));
|
||||
for (i = RT5025_REG_RANGE4START;
|
||||
i <= RT5025_REG_RANGE4END; i++)
|
||||
j += sprintf(lbuf+j, "0x%02x:%02x\n", i, \
|
||||
rt5025_reg_read(di->i2c, i));
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
else
|
||||
snprintf(lbuf, sizeof(lbuf), "0x%02x\n", read_data[0]);
|
||||
return simple_read_from_buffer(ubuf, count, ppos, lbuf, strlen(lbuf));
|
||||
}
|
||||
|
||||
static ssize_t reg_debug_write(struct file *filp,
|
||||
const char __user *ubuf, size_t cnt, loff_t *ppos)
|
||||
{
|
||||
char *access_str = filp->private_data;
|
||||
struct rt_debug_st *st = filp->private_data;
|
||||
struct rt5025_debug_info *di = st->info;
|
||||
char lbuf[32];
|
||||
int rc;
|
||||
long int param[5];
|
||||
|
|
@ -104,56 +135,37 @@ static ssize_t reg_debug_write(struct file *filp,
|
|||
|
||||
lbuf[cnt] = '\0';
|
||||
|
||||
if (!strcmp(access_str, "poke")) {
|
||||
/* write */
|
||||
rc = get_parameters(lbuf, param, 2);
|
||||
if ((param[0] <= 0xFF) && (param[1] <= 0xFF) && (rc == 0))
|
||||
{
|
||||
rt5025_reg_write(client, param[0], (unsigned char)param[1]);
|
||||
switch (st->id) {
|
||||
case RT5025_DBG_REG:
|
||||
rc = get_parameters(lbuf, param, 1);
|
||||
if ((param[0] < RT5025_REG_MAX) && (rc == 0)) {
|
||||
if ((param[0] >= RT5025_REG_RANGE1START && param[0]
|
||||
<= RT5025_REG_RANGE1END) || \
|
||||
(param[0] >= RT5025_REG_RANGE2START && param[0]
|
||||
<= RT5025_REG_RANGE2END) || \
|
||||
(param[0] >= RT5025_REG_RANGE3START && param[0]
|
||||
<= RT5025_REG_RANGE3END) || \
|
||||
(param[0] >= RT5025_REG_RANGE4START && param[0]
|
||||
<= RT5025_REG_RANGE4END))
|
||||
di->reg_addr = (unsigned char)param[0];
|
||||
else
|
||||
rc = -EINVAL;
|
||||
} else {
|
||||
rc = -EINVAL;
|
||||
}
|
||||
break;
|
||||
case RT5025_DBG_DATA:
|
||||
rc = get_parameters(lbuf, param, 1);
|
||||
if ((param[0] <= 0xff) && (rc == 0))
|
||||
rt5025_reg_write(di->i2c, di->reg_addr, param[0]);
|
||||
else
|
||||
rc = -EINVAL;
|
||||
} else if (!strcmp(access_str, "peek")) {
|
||||
/* read */
|
||||
rc = get_parameters(lbuf, param, 1);
|
||||
if ((param[0] <= 0xFF) && (rc == 0))
|
||||
{
|
||||
read_data[0] = rt5025_reg_read(client, param[0]);
|
||||
}
|
||||
else
|
||||
rc = -EINVAL;
|
||||
} else if (!strcmp(access_str, "regs")) {
|
||||
/* read */
|
||||
rc = get_parameters(lbuf, param, 1);
|
||||
if ((param[0] <= 0xFF) && (rc == 0))
|
||||
{
|
||||
rt5025_reg_block_read(client, param[0], 10, read_data);
|
||||
RTINFO("regs 0 = 0x%02x\n", read_data[0]);
|
||||
RTINFO("regs 1 = 0x%02x\n", read_data[1]);
|
||||
RTINFO("regs 2 = 0x%02x\n", read_data[2]);
|
||||
RTINFO("regs 3 = 0x%02x\n", read_data[3]);
|
||||
RTINFO("regs 4 = 0x%02x\n", read_data[4]);
|
||||
RTINFO("regs 5 = 0x%02x\n", read_data[5]);
|
||||
RTINFO("regs 6 = 0x%02x\n", read_data[6]);
|
||||
RTINFO("regs 7 = 0x%02x\n", read_data[7]);
|
||||
RTINFO("regs 8 = 0x%02x\n", read_data[8]);
|
||||
RTINFO("regs 9 = 0x%02x\n", read_data[9]);
|
||||
}
|
||||
else
|
||||
rc = -EINVAL;
|
||||
} else if (!strcmp(access_str, "reset_b")) {
|
||||
/* read */
|
||||
rc = get_parameters(lbuf, param, 1);
|
||||
if (param[0] == 1 && rc == 0)
|
||||
{
|
||||
memset(lbuf, 0, 15);
|
||||
rt5025_reg_block_write(client, 0x21, 15, lbuf);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (rc == 0)
|
||||
rc = cnt;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -163,78 +175,84 @@ static const struct file_operations reg_debug_ops = {
|
|||
.read = reg_debug_read
|
||||
};
|
||||
|
||||
static int __devinit rt5025_debug_probe(struct platform_device *pdev)
|
||||
static int rt5025_debug_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent);
|
||||
struct rt5025_debug_info *di;
|
||||
int ret = 0;
|
||||
|
||||
di = kzalloc(sizeof(*di), GFP_KERNEL);
|
||||
di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
|
||||
if (!di)
|
||||
return -ENOMEM;
|
||||
|
||||
di->i2c = chip->i2c;
|
||||
di->dev = &pdev->dev;
|
||||
|
||||
RTINFO("add debugfs for core RT5025");
|
||||
client = chip->i2c;
|
||||
RTINFO("add debugfs for RT5025");
|
||||
debugfs_rt_dent = debugfs_create_dir("rt5025_dbg", 0);
|
||||
if (!IS_ERR(debugfs_rt_dent)) {
|
||||
debugfs_peek = debugfs_create_file("peek",
|
||||
rtdbg_data[0].info = di;
|
||||
rtdbg_data[0].id = RT5025_DBG_REG;
|
||||
debugfs_file[0] = debugfs_create_file("reg",
|
||||
S_IFREG | S_IRUGO, debugfs_rt_dent,
|
||||
(void *) "peek", ®_debug_ops);
|
||||
(void *) &rtdbg_data[0], ®_debug_ops);
|
||||
|
||||
debugfs_poke = debugfs_create_file("poke",
|
||||
rtdbg_data[1].info = di;
|
||||
rtdbg_data[1].id = RT5025_DBG_DATA;
|
||||
debugfs_file[1] = debugfs_create_file("data",
|
||||
S_IFREG | S_IRUGO, debugfs_rt_dent,
|
||||
(void *) "poke", ®_debug_ops);
|
||||
(void *) &rtdbg_data[1], ®_debug_ops);
|
||||
|
||||
debugfs_regs = debugfs_create_file("regs",
|
||||
rtdbg_data[2].info = di;
|
||||
rtdbg_data[2].id = RT5025_DBG_REGS;
|
||||
debugfs_file[2] = debugfs_create_file("regs",
|
||||
S_IFREG | S_IRUGO, debugfs_rt_dent,
|
||||
(void *) "regs", ®_debug_ops);
|
||||
|
||||
debugfs_reset_b = debugfs_create_file("reset_b",
|
||||
S_IFREG | S_IRUGO, debugfs_rt_dent,
|
||||
(void *) "reset_b", ®_debug_ops);
|
||||
(void *) &rtdbg_data[2], ®_debug_ops);
|
||||
} else {
|
||||
dev_err(&pdev->dev, "create debugfs failed\n");
|
||||
ret = -EINVAL;
|
||||
goto err_init;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, di);
|
||||
|
||||
return 0;
|
||||
err_init:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit rt5025_debug_remove(struct platform_device *pdev)
|
||||
static int rt5025_debug_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rt5025_debug_info *di = platform_get_drvdata(pdev);
|
||||
|
||||
if (!IS_ERR(debugfs_rt_dent))
|
||||
debugfs_remove_recursive(debugfs_rt_dent);
|
||||
|
||||
kfree(di);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver rt5025_debug_driver =
|
||||
{
|
||||
.driver = {
|
||||
.name = RT5025_DEVICE_NAME "-debug",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = rt5025_debug_probe,
|
||||
.remove = __devexit_p(rt5025_debug_remove),
|
||||
static const struct of_device_id rt_match_table[] = {
|
||||
{ .compatible = "rt,rt5025-debug",},
|
||||
{},
|
||||
};
|
||||
|
||||
static int __init rt5025_debug_init(void)
|
||||
static struct platform_driver rt5025_debug_driver = {
|
||||
.driver = {
|
||||
.name = RT5025_DEV_NAME "-debug",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = rt_match_table,
|
||||
},
|
||||
.probe = rt5025_debug_probe,
|
||||
.remove = rt5025_debug_remove,
|
||||
};
|
||||
|
||||
static int rt5025_debug_init(void)
|
||||
{
|
||||
return platform_driver_register(&rt5025_debug_driver);
|
||||
}
|
||||
module_init(rt5025_debug_init);
|
||||
|
||||
static void __exit rt5025_debug_exit(void)
|
||||
static void rt5025_debug_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&rt5025_debug_driver);
|
||||
}
|
||||
module_exit(rt5025_debug_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
|
||||
MODULE_DESCRIPTION("Debug driver for RT5025");
|
||||
MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-debug");
|
||||
MODULE_ALIAS("platform:" RT5025_DEV_NAME "-debug");
|
||||
MODULE_VERSION(RT5025_DRV_VER);
|
||||
|
|
|
|||
254
drivers/mfd/rt5025-i2c.c
Normal file → Executable file
254
drivers/mfd/rt5025-i2c.c
Normal file → Executable file
|
|
@ -2,51 +2,33 @@
|
|||
* I2C Driver for Richtek RT5025
|
||||
* Multi function device - multi functional baseband PMIC
|
||||
*
|
||||
* Copyright (C) 2013
|
||||
* Copyright (C) 2014 Richtek Technology Corp.
|
||||
* Author: CY Huang <cy_huang@richtek.com>
|
||||
*
|
||||
* 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.
|
||||
* published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mfd/rt5025.h>
|
||||
|
||||
#define ROCKCHIP_I2C_RATE (200*1000)
|
||||
|
||||
static inline int rt5025_read_device(struct i2c_client *i2c,
|
||||
int reg, int bytes, void *dest)
|
||||
{
|
||||
#if 1
|
||||
int ret;
|
||||
unsigned char reg_addr = reg;
|
||||
struct i2c_msg i2c_msg[2];
|
||||
i2c_msg[0].addr = i2c->addr;
|
||||
i2c_msg[0].flags = i2c->flags;
|
||||
i2c_msg[0].len = 1;
|
||||
i2c_msg[0].buf = ®_addr;
|
||||
i2c_msg[0].scl_rate = ROCKCHIP_I2C_RATE;
|
||||
i2c_msg[1].addr = i2c->addr;
|
||||
i2c_msg[1].flags = i2c->flags | I2C_M_RD;
|
||||
i2c_msg[1].len = bytes;
|
||||
i2c_msg[1].buf = dest;
|
||||
i2c_msg[1].scl_rate = ROCKCHIP_I2C_RATE;
|
||||
ret = i2c_transfer(i2c->adapter, i2c_msg, 2);
|
||||
#else
|
||||
int ret;
|
||||
if (bytes > 1)
|
||||
|
||||
if (bytes > 1) {
|
||||
ret = i2c_smbus_read_i2c_block_data(i2c, reg, bytes, dest);
|
||||
else {
|
||||
} else {
|
||||
ret = i2c_smbus_read_byte_data(i2c, reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*(unsigned char *)dest = (unsigned char)ret;
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -60,30 +42,15 @@ EXPORT_SYMBOL(rt5025_reg_block_read);
|
|||
static inline int rt5025_write_device(struct i2c_client *i2c,
|
||||
int reg, int bytes, void *dest)
|
||||
{
|
||||
#if 1
|
||||
int ret;
|
||||
struct i2c_msg i2c_msg;
|
||||
char *tx_buf = (char*)kmalloc(bytes+1, GFP_KERNEL);
|
||||
tx_buf[0] = reg;
|
||||
memcpy(tx_buf+1, dest, bytes);
|
||||
i2c_msg.addr = i2c->addr;
|
||||
i2c_msg.flags = i2c->flags;
|
||||
i2c_msg.len = bytes + 1;
|
||||
i2c_msg.buf = tx_buf;
|
||||
i2c_msg.scl_rate = ROCKCHIP_I2C_RATE;
|
||||
ret = i2c_transfer(i2c->adapter, &i2c_msg, 1);
|
||||
kfree(tx_buf);
|
||||
#else
|
||||
int ret;
|
||||
if (bytes > 1)
|
||||
|
||||
if (bytes > 1) {
|
||||
ret = i2c_smbus_write_i2c_block_data(i2c, reg, bytes, dest);
|
||||
else {
|
||||
ret = i2c_smbus_write_byte_data(i2c, reg, dest);
|
||||
} else {
|
||||
ret = i2c_smbus_write_byte_data(i2c, reg, *(u8 *)dest);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*(unsigned char *)dest = (unsigned char)ret;
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -96,65 +63,28 @@ EXPORT_SYMBOL(rt5025_reg_block_write);
|
|||
|
||||
int rt5025_reg_read(struct i2c_client *i2c, int reg)
|
||||
{
|
||||
struct rt5025_chip* chip = i2c_get_clientdata(i2c);
|
||||
struct rt5025_chip *chip = i2c_get_clientdata(i2c);
|
||||
int ret;
|
||||
#if 1
|
||||
unsigned char reg_addr = reg;
|
||||
unsigned char reg_data = 0;
|
||||
struct i2c_msg i2c_msg[2];
|
||||
|
||||
RTINFO("I2C Read (client : 0x%x) reg = 0x%x\n",
|
||||
(unsigned int)i2c,(unsigned int)reg);
|
||||
mutex_lock(&chip->io_lock);
|
||||
i2c_msg[0].addr = i2c->addr;
|
||||
i2c_msg[0].flags = i2c->flags;
|
||||
i2c_msg[0].len = 1;
|
||||
i2c_msg[0].buf = ®_addr;
|
||||
i2c_msg[0].scl_rate = ROCKCHIP_I2C_RATE;
|
||||
i2c_msg[1].addr = i2c->addr;
|
||||
i2c_msg[1].flags = i2c->flags | I2C_M_RD;
|
||||
i2c_msg[1].len = 1;
|
||||
i2c_msg[1].buf = ®_data;
|
||||
i2c_msg[1].scl_rate = ROCKCHIP_I2C_RATE;
|
||||
ret = i2c_transfer(i2c->adapter, i2c_msg, 2);
|
||||
mutex_unlock(&chip->io_lock);
|
||||
#else
|
||||
RTINFO("I2C Read (client : 0x%x) reg = 0x%x\n",
|
||||
(unsigned int)i2c,(unsigned int)reg);
|
||||
(unsigned int) i2c, (unsigned int) reg);
|
||||
mutex_lock(&chip->io_lock);
|
||||
ret = i2c_smbus_read_byte_data(i2c, reg);
|
||||
mutex_unlock(&chip->io_lock);
|
||||
#endif
|
||||
return reg_data;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(rt5025_reg_read);
|
||||
|
||||
int rt5025_reg_write(struct i2c_client *i2c, int reg, unsigned char data)
|
||||
{
|
||||
struct rt5025_chip* chip = i2c_get_clientdata(i2c);
|
||||
struct rt5025_chip *chip = i2c_get_clientdata(i2c);
|
||||
int ret;
|
||||
#if 1
|
||||
unsigned char xfer_data[2];
|
||||
struct i2c_msg i2c_msg;
|
||||
|
||||
RTINFO("I2C Write (client : 0x%x) reg = 0x%x, data = 0x%x\n",
|
||||
(unsigned int)i2c,(unsigned int)reg,(unsigned int)data);
|
||||
xfer_data[0] = reg;
|
||||
xfer_data[1] = data;
|
||||
mutex_lock(&chip->io_lock);
|
||||
i2c_msg.addr = i2c->addr;
|
||||
i2c_msg.flags = i2c->flags;
|
||||
i2c_msg.len = 2;
|
||||
i2c_msg.buf = xfer_data;
|
||||
i2c_msg.scl_rate = ROCKCHIP_I2C_RATE;
|
||||
ret = i2c_transfer(i2c->adapter, &i2c_msg, 1);
|
||||
mutex_unlock(&chip->io_lock);
|
||||
#else
|
||||
RTINFO("I2C Write (client : 0x%x) reg = 0x%x, data = 0x%x\n",
|
||||
(unsigned int)i2c,(unsigned int)reg,(unsigned int)data);
|
||||
(unsigned int) i2c, (unsigned int) reg, (unsigned int) data);
|
||||
mutex_lock(&chip->io_lock);
|
||||
ret = i2c_smbus_write_byte_data(i2c, reg, data);
|
||||
mutex_unlock(&chip->io_lock);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(rt5025_reg_write);
|
||||
|
|
@ -165,25 +95,7 @@ int rt5025_assign_bits(struct i2c_client *i2c, int reg,
|
|||
struct rt5025_chip *chip = i2c_get_clientdata(i2c);
|
||||
unsigned char value;
|
||||
int ret;
|
||||
#if 1
|
||||
struct i2c_msg i2c_msg;
|
||||
u8 xfer_data[2] = {0};
|
||||
mutex_lock(&chip->io_lock);
|
||||
ret = rt5025_read_device(i2c, reg, 1, &value);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
value &= ~mask;
|
||||
value |= (data&mask);
|
||||
xfer_data[0] = reg;
|
||||
xfer_data[1] = value;
|
||||
i2c_msg.addr = i2c->addr;
|
||||
i2c_msg.flags = i2c->flags;
|
||||
i2c_msg.len = 2;
|
||||
i2c_msg.buf = xfer_data;
|
||||
i2c_msg.scl_rate = ROCKCHIP_I2C_RATE;
|
||||
ret = i2c_transfer(i2c->adapter, &i2c_msg, 1);
|
||||
#else
|
||||
|
||||
mutex_lock(&chip->io_lock);
|
||||
|
||||
ret = rt5025_read_device(i2c, reg, 1, &value);
|
||||
|
|
@ -192,8 +104,7 @@ int rt5025_assign_bits(struct i2c_client *i2c, int reg,
|
|||
goto out;
|
||||
value &= ~mask;
|
||||
value |= (data&mask);
|
||||
ret = i2c_smbus_write_byte_data(i2c,reg,value);
|
||||
#endif
|
||||
ret = i2c_smbus_write_byte_data(i2c, reg, value);
|
||||
out:
|
||||
mutex_unlock(&chip->io_lock);
|
||||
return ret;
|
||||
|
|
@ -203,90 +114,101 @@ EXPORT_SYMBOL(rt5025_assign_bits);
|
|||
int rt5025_set_bits(struct i2c_client *i2c, int reg,
|
||||
unsigned char mask)
|
||||
{
|
||||
return rt5025_assign_bits(i2c,reg,mask,mask);
|
||||
return rt5025_assign_bits(i2c, reg, mask, mask);
|
||||
}
|
||||
EXPORT_SYMBOL(rt5025_set_bits);
|
||||
|
||||
int rt5025_clr_bits(struct i2c_client *i2c, int reg,
|
||||
unsigned char mask)
|
||||
{
|
||||
return rt5025_assign_bits(i2c,reg,mask,0);
|
||||
return rt5025_assign_bits(i2c, reg, mask, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(rt5025_clr_bits);
|
||||
|
||||
static int __devinit rt5025_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
static int rt_parse_dt(struct rt5025_chip *chip, struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt_parse_pdata(struct rt5025_chip *chip, struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5025_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct rt5025_platform_data *pdata = client->dev.platform_data;
|
||||
struct rt5025_chip *chip;
|
||||
bool use_dt = client->dev.of_node;
|
||||
int ret = 0;
|
||||
u8 val;
|
||||
u8 val = 0;
|
||||
|
||||
if (!pdata)
|
||||
return -EINVAL;
|
||||
|
||||
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
|
||||
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
|
||||
if (!chip)
|
||||
return -ENOMEM;
|
||||
|
||||
chip->irq = client->irq;
|
||||
if (use_dt) {
|
||||
rt_parse_dt(chip, &client->dev);
|
||||
} else {
|
||||
if (!pdata) {
|
||||
ret = -EINVAL;
|
||||
goto err_init;
|
||||
}
|
||||
rt_parse_pdata(chip, &client->dev);
|
||||
}
|
||||
|
||||
chip->i2c = client;
|
||||
chip->dev = &client->dev;
|
||||
|
||||
#if 0
|
||||
if (pdata->event_callback)
|
||||
{
|
||||
chip->event_callback = kzalloc(sizeof(struct rt5025_event_callback), GFP_KERNEL);
|
||||
memcpy(chip->event_callback, pdata->event_callback, sizeof(struct rt5025_event_callback));
|
||||
}
|
||||
#endif /* #if 0 */
|
||||
|
||||
i2c_set_clientdata(client, chip);
|
||||
mutex_init(&chip->io_lock);
|
||||
|
||||
rt5025_read_device(client,0x00,1,&val);
|
||||
if (val != 0x81){
|
||||
printk("The PMIC is not RT5025\n");
|
||||
i2c_set_clientdata(client, chip);
|
||||
/* off event */
|
||||
rt5025_read_device(client, 0x20, 1, &val);
|
||||
RTINFO("off event = %d\n", val);
|
||||
|
||||
rt5025_read_device(client, 0x00, 1, &val);
|
||||
if (val != 0x81) {
|
||||
dev_info(&client->dev, "The PMIC is not RT5025\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
ret = rt5025_core_init(chip, pdata);
|
||||
if (ret < 0)
|
||||
dev_err(chip->dev, "rt5025_core_init_fail\n");
|
||||
else
|
||||
pr_info("RT5025 Initialize successfully\n");
|
||||
|
||||
ret = rt5025_core_init(chip, pdata);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev, "rt5025_core_init_fail\n");
|
||||
goto err_init;
|
||||
}
|
||||
|
||||
dev_info(&client->dev, "driver successfully probed\n");
|
||||
if (pdata && pdata->pre_init) {
|
||||
ret = pdata->pre_init(chip);
|
||||
if (ret != 0) {
|
||||
if (ret != 0)
|
||||
dev_err(chip->dev, "pre_init() failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
if (pdata && pdata->post_init) {
|
||||
ret = pdata->post_init();
|
||||
if (ret != 0) {
|
||||
dev_err(chip->dev, "post_init() failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
if (pdata && pdata->post_init) {
|
||||
ret = pdata->post_init();
|
||||
if (ret != 0)
|
||||
dev_err(chip->dev, "post_init() failed: %d\n", ret);
|
||||
}
|
||||
return 0;
|
||||
err_init:
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static int __devexit rt5025_i2c_remove(struct i2c_client *client)
|
||||
static int rt5025_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct rt5025_chip *chip = i2c_get_clientdata(client);
|
||||
|
||||
rt5025_core_deinit(chip);
|
||||
#if 0
|
||||
if (chip->event_callback)
|
||||
kfree(chip->event_callback);
|
||||
#endif
|
||||
kfree(chip);
|
||||
dev_info(&client->dev, "%s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5025_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
|
||||
{
|
||||
struct rt5025_chip *chip = i2c_get_clientdata(client);
|
||||
|
||||
chip->suspend = 1;
|
||||
RTINFO("\n");
|
||||
return 0;
|
||||
|
|
@ -295,47 +217,49 @@ static int rt5025_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
|
|||
static int rt5025_i2c_resume(struct i2c_client *client)
|
||||
{
|
||||
struct rt5025_chip *chip = i2c_get_clientdata(client);
|
||||
|
||||
chip->suspend = 0;
|
||||
RTINFO("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id rt5025_id_table[] = {
|
||||
{ RT5025_DEVICE_NAME, 0 },
|
||||
{ RT5025_DEV_NAME, 0 },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, rt5025_id_table);
|
||||
|
||||
static struct i2c_driver rt5025_driver = {
|
||||
static struct of_device_id rt_match_table[] = {
|
||||
{ .compatible = "rt,rt5025",},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct i2c_driver rt5025_i2c_driver = {
|
||||
.driver = {
|
||||
.name = RT5025_DEVICE_NAME,
|
||||
.name = RT5025_DEV_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = rt_match_table,
|
||||
},
|
||||
.probe = rt5025_i2c_probe,
|
||||
.remove = __devexit_p(rt5025_i2c_remove),
|
||||
.remove = rt5025_i2c_remove,
|
||||
.suspend = rt5025_i2c_suspend,
|
||||
.resume = rt5025_i2c_resume,
|
||||
.id_table = rt5025_id_table,
|
||||
};
|
||||
|
||||
static int __init rt5025_i2c_init(void)
|
||||
static int rt5025_i2c_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = i2c_add_driver(&rt5025_driver);
|
||||
if (ret != 0)
|
||||
pr_err("Failed to register RT5025 I2C driver: %d\n", ret);
|
||||
return ret;
|
||||
return i2c_add_driver(&rt5025_i2c_driver);
|
||||
}
|
||||
subsys_initcall_sync(rt5025_i2c_init);
|
||||
|
||||
static void __exit rt5025_i2c_exit(void)
|
||||
static void rt5025_i2c_exit(void)
|
||||
{
|
||||
i2c_del_driver(&rt5025_driver);
|
||||
i2c_del_driver(&rt5025_i2c_driver);
|
||||
}
|
||||
module_exit(rt5025_i2c_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("I2C Driver for Richtek RT5025");
|
||||
MODULE_AUTHOR("CY Huang <cy_huang@richtek.com>");
|
||||
MODULE_VERSION(RT5025_DRV_VER);
|
||||
|
|
|
|||
428
drivers/mfd/rt5025-irq.c
Normal file → Executable file
428
drivers/mfd/rt5025-irq.c
Normal file → Executable file
|
|
@ -1,336 +1,204 @@
|
|||
/*
|
||||
* drivers/mfd/rt5025-irq.c
|
||||
* Driver foo Richtek RT5025 PMIC irq
|
||||
* Driver for Richtek RT5025 PMIC IRQ driver
|
||||
*
|
||||
* Copyright (C) 2013 Richtek Electronics
|
||||
* Copyright (C) 2014 Richtek Technology Corp.
|
||||
* cy_huang <cy_huang@richtek.com>
|
||||
*
|
||||
* 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.
|
||||
* published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/wakelock.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <linux/mfd/rt5025.h>
|
||||
#include <linux/mfd/rt5025-irq.h>
|
||||
|
||||
struct rt5025_irq_info {
|
||||
struct i2c_client *i2c;
|
||||
struct device *dev;
|
||||
struct rt5025_chip *chip;
|
||||
struct workqueue_struct *wq;
|
||||
struct rt5025_event_callback *event_cb;
|
||||
struct delayed_work delayed_work;
|
||||
struct wake_lock irq_wake_lock;
|
||||
int intr_pin;
|
||||
struct device *dev;
|
||||
int irq;
|
||||
int suspend;
|
||||
int acin_cnt;
|
||||
int usbin_cnt;
|
||||
unsigned char suspend:1;
|
||||
struct delayed_work irq_delayed_work;
|
||||
};
|
||||
|
||||
static void rt5025_work_func(struct work_struct *work)
|
||||
static irqreturn_t rt5025_irq_handler(int irqno, void *param)
|
||||
{
|
||||
struct delayed_work *delayed_work = (struct delayed_work *)container_of(work, struct delayed_work, work);
|
||||
struct rt5025_irq_info *ii = (struct rt5025_irq_info *)container_of(delayed_work, struct rt5025_irq_info, delayed_work);
|
||||
unsigned char irq_stat[6] = {0};
|
||||
unsigned char irq_enable[6] = {0};
|
||||
uint32_t chg_event = 0, pwr_event = 0;
|
||||
struct rt5025_irq_info *ii = param;
|
||||
unsigned char regval[6];
|
||||
unsigned int irq_event = 0;
|
||||
int ret = 0;
|
||||
|
||||
//Add this to prevent i2c xfer before i2c chip is in suspend mode
|
||||
if (ii->suspend)
|
||||
{
|
||||
queue_delayed_work(ii->wq, &ii->delayed_work, msecs_to_jiffies(1));
|
||||
return;
|
||||
if (ii->suspend) {
|
||||
schedule_delayed_work(&ii->irq_delayed_work,
|
||||
msecs_to_jiffies(10));
|
||||
goto irq_fin;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_POWER_RT5025
|
||||
if (!ii->chip->power_info || !ii->chip->jeita_info || !ii->chip->battery_info)
|
||||
{
|
||||
queue_delayed_work(ii->wq, &ii->delayed_work, msecs_to_jiffies(1));
|
||||
return;
|
||||
ret = rt5025_reg_read(ii->i2c, RT5025_REG_IRQFLG);
|
||||
if (ret < 0) {
|
||||
dev_err(ii->dev, "read gauge irq event fail\n");
|
||||
} else {
|
||||
irq_event = ret;
|
||||
RTINFO("gauge event %02x\n", irq_event);
|
||||
#ifdef CONFIG_BATTERY_RT5025
|
||||
if (irq_event)
|
||||
rt5025_gauge_irq_handler(ii->chip->battery_info,
|
||||
irq_event&(~RT5025_TALRT_MASK));
|
||||
#endif /* #ifdef CONFIG_RTC_RT5025 */
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
if (rt5025_reg_block_read(ii->i2c, RT5025_REG_IRQEN1, 10, irq_stat) >= 0)
|
||||
{
|
||||
#endif
|
||||
/* backup the irq enable bit */
|
||||
irq_enable[0] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQEN1);
|
||||
irq_enable[1] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQEN2);
|
||||
irq_enable[2] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQEN3);
|
||||
irq_enable[3] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQEN4);
|
||||
irq_enable[4] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQEN5);
|
||||
irq_enable[5] = rt5025_reg_read(ii->i2c, RT5025_REG_GAUGEIRQEN);
|
||||
#if 1
|
||||
rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN2, irq_enable[1]&(~RT5025_CHTERMI_MASK));
|
||||
ret = rt5025_reg_block_read(ii->i2c, RT5025_REG_IRQEN1, 6, regval);
|
||||
if (ret < 0) {
|
||||
dev_err(ii->dev, "read charger irq event fail\n");
|
||||
} else {
|
||||
#ifdef CONFIG_BATTERY_RT5025
|
||||
/*combine gauge talrt irq into charger event*/
|
||||
irq_event = irq_event&RT5025_TALRT_MASK;
|
||||
irq_event <<= 24;
|
||||
irq_event |= (regval[1] << 16 | regval[3] << 8 | regval[5]);
|
||||
#else
|
||||
/* disable all irq enable bit first */
|
||||
rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN1, irq_enable[0]&RT5025_ADAPIRQ_MASK);
|
||||
rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN2, 0x00);
|
||||
rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN3, 0x00);
|
||||
rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN4, 0x00);
|
||||
rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN5, 0x00);
|
||||
rt5025_reg_write(ii->i2c, RT5025_REG_GAUGEIRQEN, 0x00);
|
||||
#endif //#if 0
|
||||
/* read irq status bit */
|
||||
irq_stat[0] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQSTATUS1);
|
||||
irq_stat[1] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQSTATUS2);
|
||||
irq_stat[2] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQSTATUS3);
|
||||
irq_stat[3] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQSTATUS4);
|
||||
irq_stat[4] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQSTATUS5);
|
||||
irq_stat[5] = rt5025_reg_read(ii->i2c, RT5025_REG_GAUGEIRQFLG);
|
||||
RTINFO("irq1->0x%02x, irq2->0x%02x, irq3->0x%02x\n", irq_stat[0], irq_stat[1], irq_stat[2]);
|
||||
RTINFO("irq4->0x%02x, irq5->0x%02x, irq6->0x%02x\n", irq_stat[3], irq_stat[4], irq_stat[5]);
|
||||
RTINFO("stat value = %02x\n", rt5025_reg_read(ii->i2c, RT5025_REG_CHGSTAT));
|
||||
|
||||
chg_event = irq_stat[0]<<16 | irq_stat[1]<<8 | irq_stat[2];
|
||||
pwr_event = irq_stat[3]<<8 | irq_stat[4];
|
||||
#ifdef CONFIG_POWER_RT5025
|
||||
if ((chg_event & CHARGER_DETECT_MASK))
|
||||
{
|
||||
if (chg_event & CHG_EVENT_CHTERMI)
|
||||
{
|
||||
ii->chip->power_info->chg_term++;
|
||||
if (ii->chip->power_info->chg_term > 3)
|
||||
ii->chip->power_info->chg_term = 4;
|
||||
}
|
||||
|
||||
if (chg_event & CHG_EVENT_CHRCHGI)
|
||||
ii->chip->power_info->chg_term = 0;
|
||||
|
||||
if (chg_event & (CHG_EVENT_CHSLPI_INAC | CHG_EVENT_CHSLPI_INUSB))
|
||||
{
|
||||
ii->chip->power_info->chg_term = 0;
|
||||
if (chg_event & CHG_EVENT_CHSLPI_INAC)
|
||||
ii->acin_cnt = 0;
|
||||
if (chg_event & CHG_EVENT_CHSLPI_INUSB)
|
||||
ii->usbin_cnt = 0;
|
||||
|
||||
}
|
||||
|
||||
if (chg_event & (CHG_EVENT_INAC_PLUGIN | CHG_EVENT_INUSB_PLUGIN))
|
||||
{
|
||||
RTINFO("acin_cnt %d, usbin_cnt %d\n", ii->acin_cnt, ii->usbin_cnt);
|
||||
if (ii->acin_cnt == 0 && ii->usbin_cnt == 0)
|
||||
{
|
||||
#if 1
|
||||
rt5025_charger_reset_and_reinit(ii->chip->power_info);
|
||||
rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN1, irq_enable[0]);
|
||||
rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN2, irq_enable[1]&(~RT5025_CHTERMI_MASK));
|
||||
rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN3, irq_enable[2]);
|
||||
#else
|
||||
rt5025_set_charging_buck(ii->i2c, 0);
|
||||
mdelay(50);
|
||||
rt5025_set_charging_buck(ii->i2c, 1);
|
||||
mdelay(100);
|
||||
rt5025_set_charging_buck(ii->i2c, 0);
|
||||
mdelay(50);
|
||||
rt5025_set_charging_buck(ii->i2c, 1);
|
||||
mdelay(400);
|
||||
#endif /* #if 1 */
|
||||
}
|
||||
|
||||
if (chg_event & CHG_EVENT_INAC_PLUGIN)
|
||||
ii->acin_cnt = 1;
|
||||
if (chg_event & CHG_EVENT_INUSB_PLUGIN)
|
||||
ii->usbin_cnt = 1;
|
||||
RTINFO("acin_cnt %d, usbin_cnt %d\n", ii->acin_cnt, ii->usbin_cnt);
|
||||
}
|
||||
|
||||
if (ii->chip->power_info->chg_term <= 3)
|
||||
rt5025_power_charge_detect(ii->chip->power_info);
|
||||
|
||||
}
|
||||
#endif /* CONFIG_POWER_RT5025 */
|
||||
if (ii->event_cb)
|
||||
{
|
||||
if (chg_event)
|
||||
ii->event_cb->charger_event_callback(chg_event);
|
||||
if (pwr_event)
|
||||
ii->event_cb->power_event_callkback(pwr_event);
|
||||
}
|
||||
#if 0
|
||||
irq_event = regval[1] << 16 | regval[3] << 8 | regval[5];
|
||||
#endif
|
||||
RTINFO("chg event %08x\n", irq_event);
|
||||
#ifdef CONFIG_CHARGER_RT5025
|
||||
if (irq_event)
|
||||
rt5025_charger_irq_handler(ii->chip->charger_info,
|
||||
irq_event);
|
||||
#endif /* #ifdef CONFIG_CHARGER_RT5025 */
|
||||
}
|
||||
else
|
||||
dev_err(ii->dev, "read irq stat io fail\n");
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_POWER_RT5025
|
||||
if (irq_stat[5] & RT5025_FLG_TEMP)
|
||||
rt5025_swjeita_irq_handler(ii->chip->jeita_info, irq_stat[5] & RT5025_FLG_TEMP);
|
||||
if (irq_stat[5] & RT5025_FLG_VOLT)
|
||||
rt5025_gauge_irq_handler(ii->chip->battery_info, irq_stat[5] & RT5025_FLG_VOLT);
|
||||
#endif /* CONFIG_POWER_RT5025 */
|
||||
|
||||
#if 1
|
||||
rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN2, irq_enable[1]);
|
||||
#else
|
||||
/* restore all irq enable bit */
|
||||
rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN1, irq_enable[0]);
|
||||
rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN2, irq_enable[1]);
|
||||
rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN3, irq_enable[2]);
|
||||
rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN4, irq_enable[3]);
|
||||
rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN5, irq_enable[4]);
|
||||
if (rt5025_reg_read(ii->i2c, RT5025_REG_GAUGEIRQEN) == 0)
|
||||
rt5025_reg_write(ii->i2c, RT5025_REG_GAUGEIRQEN, irq_enable[5]);
|
||||
#endif //#if 0
|
||||
|
||||
//enable_irq(ii->irq);
|
||||
}
|
||||
|
||||
static irqreturn_t rt5025_interrupt(int irqno, void *param)
|
||||
{
|
||||
struct rt5025_irq_info *ii = (struct rt5025_irq_info *)param;
|
||||
|
||||
//disable_irq_nosync(ii->irq);
|
||||
wake_lock_timeout(&ii->irq_wake_lock, 1*HZ);
|
||||
queue_delayed_work(ii->wq, &ii->delayed_work, 0);
|
||||
ret = rt5025_reg_block_read(ii->i2c, RT5025_REG_IRQEN4, 4, regval);
|
||||
if (ret < 0) {
|
||||
dev_err(ii->dev, "read misc irq event fail\n");
|
||||
} else {
|
||||
irq_event = regval[1] << 8 | regval[3];
|
||||
RTINFO("misc event %04x\n", irq_event);
|
||||
#ifdef CONFIG_MISC_RT5025
|
||||
if (irq_event)
|
||||
rt5025_misc_irq_handler(ii->chip->misc_info, irq_event);
|
||||
#endif /* #ifdef CONFIG_MISC_RT5025 */
|
||||
}
|
||||
irq_fin:
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int __devinit rt5025_interrupt_init(struct rt5025_irq_info* ii)
|
||||
static void rt5025_irq_delayed_work(struct work_struct *work)
|
||||
{
|
||||
int ret = 0;
|
||||
struct rt5025_irq_info *ii = (struct rt5025_irq_info *)container_of(work,
|
||||
struct rt5025_irq_info, irq_delayed_work.work);
|
||||
|
||||
RTINFO("\n");
|
||||
ii->wq = create_workqueue("rt5025_wq");
|
||||
INIT_DELAYED_WORK(&ii->delayed_work, rt5025_work_func);
|
||||
|
||||
#if 0
|
||||
if (gpio_is_valid(ii->intr_pin))
|
||||
{
|
||||
ret = gpio_request(ii->intr_pin, "rt5025_interrupt");
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = gpio_direction_input(ii->intr_pin);
|
||||
if (ret)
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
if (request_irq(ii->irq, rt5025_interrupt, IRQ_TYPE_EDGE_FALLING|IRQF_DISABLED, "RT5025_IRQ", ii))
|
||||
{
|
||||
dev_err(ii->dev, "couldn't allocate IRQ_NO(%d) !\n", ii->irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
enable_irq_wake(ii->irq);
|
||||
queue_delayed_work(ii->wq, &ii->delayed_work, msecs_to_jiffies(100));
|
||||
#if 0
|
||||
|
||||
if (!gpio_get_value(ii->intr_pin))
|
||||
{
|
||||
//disable_irq_nosync(ii->irq);
|
||||
queue_delayed_work(ii->wq, &ii->delayed_work, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
return -EINVAL;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
rt5025_irq_handler(ii->irq, ii);
|
||||
}
|
||||
|
||||
static void __devexit rt5025_interrupt_deinit(struct rt5025_irq_info* ii)
|
||||
static int rt_parse_dt(struct rt5025_irq_info *ii, struct device *dev)
|
||||
{
|
||||
if (ii->irq)
|
||||
free_irq(ii->irq, ii);
|
||||
#ifdef CONFIG_OF
|
||||
struct device_node *np = dev->of_node;
|
||||
int val;
|
||||
|
||||
if (ii->wq)
|
||||
{
|
||||
cancel_delayed_work_sync(&ii->delayed_work);
|
||||
flush_workqueue(ii->wq);
|
||||
destroy_workqueue(ii->wq);
|
||||
val = of_get_named_gpio(np, "rt,irq-gpio", 0);
|
||||
if (gpio_is_valid(val)) {
|
||||
if (gpio_request(val, "rt5025-irq") >= 0) {
|
||||
gpio_direction_input(val);
|
||||
ii->irq = gpio_to_irq(val);
|
||||
} else {
|
||||
ii->irq = -1;
|
||||
}
|
||||
} else {
|
||||
ii->irq = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int __devinit rt5025_irq_reg_init(struct rt5025_irq_info* ii, struct rt5025_irq_data* irq_data)
|
||||
{
|
||||
#endif /* #ifdef CONFIG_OF */
|
||||
RTINFO("\n");
|
||||
// will just enable the interrupt that we want
|
||||
rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN1, irq_data->irq_enable1.val);
|
||||
rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN2, irq_data->irq_enable2.val);
|
||||
rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN3, irq_data->irq_enable3.val);
|
||||
rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN4, irq_data->irq_enable4.val);
|
||||
rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN5, irq_data->irq_enable5.val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit rt5025_irq_probe(struct platform_device *pdev)
|
||||
static int rt_parse_pdata(struct rt5025_irq_info *ii, struct device *dev)
|
||||
{
|
||||
struct rt5025_irq_data *pdata = dev->platform_data;
|
||||
|
||||
if (gpio_is_valid(pdata->irq_gpio)) {
|
||||
if (gpio_request(pdata->irq_gpio, "rt5025-irq") >= 0) {
|
||||
gpio_direction_input(pdata->irq_gpio);
|
||||
ii->irq = gpio_to_irq(pdata->irq_gpio);
|
||||
} else {
|
||||
ii->irq = -1;
|
||||
}
|
||||
} else {
|
||||
ii->irq = -1;
|
||||
}
|
||||
RTINFO("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5025_irq_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent);
|
||||
struct rt5025_platform_data *pdata = chip->dev->platform_data;
|
||||
struct rt5025_platform_data *pdata = (pdev->dev.parent)->platform_data;
|
||||
struct rt5025_irq_info *ii;
|
||||
bool use_dt = pdev->dev.of_node;
|
||||
int ret;
|
||||
|
||||
RTINFO("\n");
|
||||
ii = kzalloc(sizeof(*ii), GFP_KERNEL);
|
||||
ii = devm_kzalloc(&pdev->dev, sizeof(*ii), GFP_KERNEL);
|
||||
if (!ii)
|
||||
return -ENOMEM;
|
||||
|
||||
ii->i2c = chip->i2c;
|
||||
ii->dev = &pdev->dev;
|
||||
ii->chip = chip;
|
||||
ii->intr_pin = pdata->intr_pin;
|
||||
ii->irq = chip->irq;//gpio_to_irq(pdata->intr_pin);
|
||||
if (pdata->cb)
|
||||
ii->event_cb = pdata->cb;
|
||||
wake_lock_init(&ii->irq_wake_lock, WAKE_LOCK_SUSPEND, "rt_irq_wake");
|
||||
ii->dev = &pdev->dev;
|
||||
if (use_dt) {
|
||||
rt_parse_dt(ii, &pdev->dev);
|
||||
} else {
|
||||
if (!pdata)
|
||||
goto out_dev;
|
||||
pdev->dev.platform_data = pdata->irq_pdata;
|
||||
rt_parse_pdata(ii, &pdev->dev);
|
||||
dev_info(&pdev->dev, "ii->irq %d\n", ii->irq);
|
||||
}
|
||||
|
||||
rt5025_irq_reg_init(ii, pdata->irq_data);
|
||||
rt5025_interrupt_init(ii);
|
||||
INIT_DELAYED_WORK(&ii->irq_delayed_work, rt5025_irq_delayed_work);
|
||||
|
||||
platform_set_drvdata(pdev, ii);
|
||||
RTINFO("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit rt5025_irq_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rt5025_irq_info *ii = platform_get_drvdata(pdev);
|
||||
|
||||
wake_lock_destroy(&ii->irq_wake_lock);
|
||||
rt5025_interrupt_deinit(ii);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
kfree(ii);
|
||||
RTINFO("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rt5025_irq_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct rt5025_irq_info *ii = platform_get_drvdata(pdev);
|
||||
|
||||
if (ii->irq)
|
||||
free_irq(ii->irq, ii);
|
||||
|
||||
if (ii->wq)
|
||||
{
|
||||
cancel_delayed_work_sync(&ii->delayed_work);
|
||||
flush_workqueue(ii->wq);
|
||||
if (ii->irq >= 0) {
|
||||
ret = devm_request_irq(&pdev->dev, ii->irq, rt5025_irq_handler,
|
||||
IRQF_TRIGGER_FALLING|IRQF_NO_SUSPEND, "rt5025-irq", ii);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "request threaded irq fail\n");
|
||||
goto out_dev;
|
||||
}
|
||||
enable_irq_wake(ii->irq);
|
||||
schedule_delayed_work(&ii->irq_delayed_work, 1*HZ);
|
||||
}
|
||||
RTINFO("\n");
|
||||
dev_info(&pdev->dev, "driver successfully loaded\n");
|
||||
return 0;
|
||||
out_dev:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int rt5025_irq_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rt5025_irq_info *ii = platform_get_drvdata(pdev);
|
||||
|
||||
if (ii->irq >= 0)
|
||||
devm_free_irq(&pdev->dev, ii->irq, ii);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5025_irq_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
struct rt5025_irq_info *ii = platform_get_drvdata(pdev);
|
||||
|
||||
RTINFO("\n");
|
||||
ii->suspend = 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -339,38 +207,42 @@ static int rt5025_irq_resume(struct platform_device *pdev)
|
|||
{
|
||||
struct rt5025_irq_info *ii = platform_get_drvdata(pdev);
|
||||
|
||||
RTINFO("\n");
|
||||
ii->suspend = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver rt5025_irq_driver =
|
||||
{
|
||||
static const struct of_device_id rt_match_table[] = {
|
||||
{ .compatible = "rt,rt5025-irq",},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver rt5025_irq_driver = {
|
||||
.driver = {
|
||||
.name = RT5025_DEVICE_NAME "-irq",
|
||||
.name = RT5025_DEV_NAME "-irq",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = rt_match_table,
|
||||
},
|
||||
.probe = rt5025_irq_probe,
|
||||
.remove = __devexit_p(rt5025_irq_remove),
|
||||
.shutdown = rt5025_irq_shutdown,
|
||||
.remove = rt5025_irq_remove,
|
||||
.suspend = rt5025_irq_suspend,
|
||||
.resume = rt5025_irq_resume,
|
||||
};
|
||||
|
||||
static int __init rt5025_irq_init(void)
|
||||
static int rt5025_irq_init(void)
|
||||
{
|
||||
return platform_driver_register(&rt5025_irq_driver);
|
||||
}
|
||||
module_init(rt5025_irq_init);
|
||||
device_initcall(rt5025_irq_init);
|
||||
|
||||
static void __exit rt5025_irq_exit(void)
|
||||
static void rt5025_irq_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&rt5025_irq_driver);
|
||||
}
|
||||
|
||||
module_exit(rt5025_irq_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
|
||||
MODULE_DESCRIPTION("IRQ driver for RT5025");
|
||||
MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-irq");
|
||||
MODULE_ALIAS("platform:"RT5025_DEV_NAME "-irq");
|
||||
MODULE_VERSION(RT5025_DRV_VER);
|
||||
|
|
|
|||
310
drivers/mfd/rt5025-misc.c
Normal file → Executable file
310
drivers/mfd/rt5025-misc.c
Normal file → Executable file
|
|
@ -2,12 +2,13 @@
|
|||
* drivers/mfd/rt5025-misc.c
|
||||
* Driver foo Richtek RT5025 PMIC Misc Part
|
||||
*
|
||||
* Copyright (C) 2013 Richtek Electronics
|
||||
* Copyright (C) 2014 Richtek Technology Corp.
|
||||
* cy_huang <cy_huang@richtek.com>
|
||||
*
|
||||
* 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.
|
||||
* published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
|
@ -15,105 +16,306 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/power_supply.h>
|
||||
|
||||
#include <linux/mfd/rt5025.h>
|
||||
#include <linux/mfd/rt5025-misc.h>
|
||||
|
||||
struct rt5025_misc_info {
|
||||
struct i2c_client *i2c;
|
||||
static unsigned char misc_init_regval[] = {
|
||||
0x2A, /* reg 0x15 */
|
||||
0x00, /* reg 0x16 */
|
||||
0x60, /* reg 0x17 */
|
||||
0x16, /* reg 0x19 */
|
||||
0x60, /* reg 0x1A */
|
||||
0x0C, /* reg 0x1B */
|
||||
0xF3, /* reg 0x36 */
|
||||
0x90, /* reg 0x38 */
|
||||
};
|
||||
|
||||
static struct i2c_client *g_shdn;
|
||||
void rt5025_power_off(void)
|
||||
static bool rt_pm_off;
|
||||
static void rt5025_power_off(void)
|
||||
{
|
||||
rt5025_reg_write(g_shdn, RT5025_CHENH_REG, 0x00);
|
||||
rt5025_reg_write(g_shdn, RT5025_CHENL_REG, 0x80);
|
||||
rt5025_set_bits(g_shdn, RT5025_SHDNCTRL_REG, RT5025_SHDNCTRL_MASK);
|
||||
rt5025_reg_write(g_shdn, RT5025_REG_CHANNELH, 0x00);
|
||||
rt5025_reg_write(g_shdn, RT5025_REG_CHANNELL, 0x80);
|
||||
rt5025_set_bits(g_shdn, RT5025_REG_MISC3, RT5025_SHDNCTRL_MASK);
|
||||
}
|
||||
EXPORT_SYMBOL(rt5025_power_off);
|
||||
|
||||
int rt5025_cable_exist(void)
|
||||
{
|
||||
int ret = 0;
|
||||
ret = rt5025_reg_read(g_shdn, 0x01);
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
if (ret&0x3)
|
||||
return 1;
|
||||
return 0;
|
||||
#ifdef CONFIG_CHARGER_RT5025
|
||||
struct power_supply *psy = power_supply_get_by_name("rt-charger");
|
||||
union power_supply_propval pval;
|
||||
|
||||
if (!psy) {
|
||||
pr_err(" couldn't get charger power supply\n");
|
||||
} else {
|
||||
ret = psy->get_property(psy,
|
||||
POWER_SUPPLY_PROP_CHARGE_NOW, &pval);
|
||||
if (ret < 0) {
|
||||
ret = 0;
|
||||
} else {
|
||||
if (pval.intval > POWER_SUPPLY_TYPE_BATTERY)
|
||||
ret = 1;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
ret = rt5025_reg_read(g_shdn, RT5025_REG_CHGCTL1);
|
||||
if (ret < 0) {
|
||||
pr_err("couldn't get cable status\n");
|
||||
ret = 0;
|
||||
} else {
|
||||
if (ret & RT5025_CABLEIN_MASK)
|
||||
ret = 1;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
#endif /* #ifdef CONFIG_CHARGER_RT5025 */
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(rt5025_cable_exist);
|
||||
|
||||
static int __devinit rt5025_misc_reg_init(struct i2c_client *client, struct rt5025_misc_data *md)
|
||||
static void rt5025_general_irq_handler(void *info, int eventno)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
rt5025_reg_write(client, RT5025_RESETCTRL_REG, md->RSTCtrl.val);
|
||||
rt5025_assign_bits(client, RT5025_VSYSULVO_REG, RT5025_VSYSOFF_MASK, md->VSYSCtrl.val);
|
||||
rt5025_reg_write(client, RT5025_PWRONCTRL_REG, md->PwrOnCfg.val);
|
||||
rt5025_reg_write(client, RT5025_SHDNCTRL_REG, md->SHDNCtrl.val);
|
||||
rt5025_reg_write(client, RT5025_PWROFFEN_REG, md->PwrOffCond.val);
|
||||
struct rt5025_misc_info *mi = info;
|
||||
|
||||
return ret;
|
||||
RTINFO("eventno=%02d\n", eventno);
|
||||
|
||||
switch (eventno) {
|
||||
case MISCEVENT_RESETB:
|
||||
dev_warn(mi->dev, "RESETB event trigger\n");
|
||||
break;
|
||||
case MISCEVENT_KPSHDN:
|
||||
dev_warn(mi->dev, "PwrKey force shdn\n");
|
||||
break;
|
||||
case MISCEVENT_SYSLV:
|
||||
dev_warn(mi->dev, "syslv event trigger\n");
|
||||
break;
|
||||
case MISCEVENT_DCDC4LVHV:
|
||||
dev_warn(mi->dev, "DCDC4LVHV event trigger\n");
|
||||
break;
|
||||
case MISCEVENT_DCDC3LV:
|
||||
dev_warn(mi->dev, "DCDC3LV event trigger\n");
|
||||
break;
|
||||
case MISCEVENT_DCDC2LV:
|
||||
dev_warn(mi->dev, "DCDC2LV event trigger\n");
|
||||
break;
|
||||
case MISCEVENT_DCDC1LV:
|
||||
dev_warn(mi->dev, "DCDC2LV event trigger\n");
|
||||
break;
|
||||
case MISCEVENT_OT:
|
||||
dev_warn(mi->dev, "Over temperature event trigger\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int __devinit rt5025_misc_probe(struct platform_device *pdev)
|
||||
static rt_irq_handler rt_miscirq_handler[MISCEVENT_MAX] = {
|
||||
[MISCEVENT_GPIO0_IE] = rt5025_general_irq_handler,
|
||||
[MISCEVENT_GPIO1_IE] = rt5025_general_irq_handler,
|
||||
[MISCEVENT_GPIO2_IE] = rt5025_general_irq_handler,
|
||||
[MISCEVENT_RESETB] = rt5025_general_irq_handler,
|
||||
[MISCEVENT_PWRONF] = rt5025_general_irq_handler,
|
||||
[MISCEVENT_PWRONR] = rt5025_general_irq_handler,
|
||||
[MISCEVENT_KPSHDN] = rt5025_general_irq_handler,
|
||||
[MISCEVENT_SYSLV] = rt5025_general_irq_handler,
|
||||
[MISCEVENT_DCDC4LVHV] = rt5025_general_irq_handler,
|
||||
[MISCEVENT_PWRONLP_IRQ] = rt5025_general_irq_handler,
|
||||
[MISCEVENT_PWRONSP_IRQ] = rt5025_general_irq_handler,
|
||||
[MISCEVENT_DCDC3LV] = rt5025_general_irq_handler,
|
||||
[MISCEVENT_DCDC2LV] = rt5025_general_irq_handler,
|
||||
[MISCEVENT_DCDC1LV] = rt5025_general_irq_handler,
|
||||
[MISCEVENT_OT] = rt5025_general_irq_handler,
|
||||
};
|
||||
|
||||
void rt5025_misc_irq_handler(struct rt5025_misc_info *ci, unsigned int irqevent)
|
||||
{
|
||||
int i;
|
||||
unsigned int enable_irq_event = (misc_init_regval[6] << 8) |
|
||||
misc_init_regval[7];
|
||||
unsigned int final_irq_event = irqevent&enable_irq_event;
|
||||
|
||||
for (i = 0; i < MISCEVENT_MAX; i++) {
|
||||
if ((final_irq_event&(1 << i)) && rt_miscirq_handler[i])
|
||||
rt_miscirq_handler[i](ci, i);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(rt5025_misc_irq_handler);
|
||||
|
||||
static int rt5025_misc_reginit(struct i2c_client *client)
|
||||
{
|
||||
rt5025_reg_write(client, RT5025_REG_MISC1, misc_init_regval[0]);
|
||||
rt5025_reg_write(client, RT5025_REG_ONEVENT, misc_init_regval[1]);
|
||||
rt5025_assign_bits(client, RT5025_REG_DCDCONOFF,
|
||||
RT5025_VSYSOFF_MASK, misc_init_regval[2]);
|
||||
rt5025_reg_write(client, RT5025_REG_MISC2, misc_init_regval[3]);
|
||||
rt5025_reg_write(client, RT5025_REG_MISC3, misc_init_regval[4]);
|
||||
rt5025_reg_write(client, RT5025_REG_MISC4, misc_init_regval[5]);
|
||||
/*set all to be masked*/
|
||||
rt5025_reg_write(client, RT5025_REG_IRQEN4, 0x00);
|
||||
rt5025_reg_write(client, RT5025_REG_IRQEN5, 0x00);
|
||||
/*clear the old irq status*/
|
||||
rt5025_reg_read(client, RT5025_REG_IRQSTAT4);
|
||||
rt5025_reg_read(client, RT5025_REG_IRQSTAT5);
|
||||
/*set enable irqs as we want*/
|
||||
rt5025_reg_write(client, RT5025_REG_IRQEN4, misc_init_regval[6]);
|
||||
rt5025_reg_write(client, RT5025_REG_IRQEN5, misc_init_regval[7]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt_parse_dt(struct rt5025_misc_info *mi, struct device *dev)
|
||||
{
|
||||
int rc;
|
||||
#ifdef CONFIG_OF
|
||||
struct device_node *np = dev->of_node;
|
||||
unsigned int val;
|
||||
|
||||
rc = of_property_read_u32(np, "rt,vsyslv", &val);
|
||||
if (rc < 0) {
|
||||
dev_info(dev, "no system lv value, use default value\n");
|
||||
} else {
|
||||
if (val > RT5025_VOFF_MAX)
|
||||
val = RT5025_VOFF_MAX;
|
||||
misc_init_regval[2] &= ~RT5025_VSYSOFF_MASK;
|
||||
misc_init_regval[2] |= val << RT5025_VSYSOFF_SHFT;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(np, "rt,shdnlpress_time", &val);
|
||||
if (rc < 0) {
|
||||
dev_info(dev, "no shdnlpress time, use default value\n");
|
||||
} else {
|
||||
if (val > RT5025_SHDNPRESS_MAX)
|
||||
val = RT5025_SHDNPRESS_MAX;
|
||||
misc_init_regval[3] &= ~RT5025_SHDNLPRESS_MASK;
|
||||
misc_init_regval[3] |= val << RT5025_SHDNLPRESS_SHFT;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(np, "rt,startlpress_time", &val);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "no start_lpress, use default value\n");
|
||||
} else {
|
||||
if (val > RT5025_STARTIME_MAX)
|
||||
val = RT5025_STARTIME_MAX;
|
||||
misc_init_regval[3] &= ~RT5025_STARTLPRESS_MASK;
|
||||
misc_init_regval[3] |= val << RT5025_STARTLPRESS_SHFT;
|
||||
}
|
||||
|
||||
if (of_property_read_bool(np, "rt,vsyslv_enshdn"))
|
||||
misc_init_regval[5] |= RT5025_VSYSLVSHDN_MASK;
|
||||
else
|
||||
misc_init_regval[5] &= ~RT5025_VSYSLVSHDN_MASK;
|
||||
#endif
|
||||
|
||||
rt_pm_off = of_property_read_bool(np, "rt,system-power-controller");
|
||||
/* #ifdef CONFIG_OF */
|
||||
rc = rt5025_misc_reginit(mi->i2c);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int rt_parse_pdata(struct rt5025_misc_info *mi, struct device *dev)
|
||||
{
|
||||
struct rt5025_misc_data *pdata = dev->platform_data;
|
||||
int rc = 0;
|
||||
|
||||
/*system low voltage*/
|
||||
misc_init_regval[2] &= ~RT5025_VSYSOFF_MASK;
|
||||
misc_init_regval[2] |= (pdata->vsyslv << RT5025_VSYSOFF_SHFT);
|
||||
/*shutdown long press time*/
|
||||
misc_init_regval[3] &= ~RT5025_SHDNLPRESS_MASK;
|
||||
misc_init_regval[3] |= (pdata->shdnlpress_time <<
|
||||
RT5025_SHDNLPRESS_SHFT);
|
||||
/*start long press time*/
|
||||
misc_init_regval[3] &= ~RT5025_STARTLPRESS_MASK;
|
||||
misc_init_regval[3] |= (pdata->startlpress_time <<
|
||||
RT5025_STARTLPRESS_SHFT);
|
||||
/*systemlv enable shutdown*/
|
||||
misc_init_regval[5] &= ~RT5025_VSYSLVSHDN_MASK;
|
||||
misc_init_regval[5] |= (pdata->vsyslv_enshdn <<
|
||||
RT5025_VSYSLVSHDN_SHFT);
|
||||
rc = rt5025_misc_reginit(mi->i2c);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int rt5025_misc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent);
|
||||
struct rt5025_platform_data *pdata = chip->dev->platform_data;
|
||||
struct rt5025_platform_data *pdata = (pdev->dev.parent)->platform_data;
|
||||
struct rt5025_misc_info *mi;
|
||||
bool use_dt = pdev->dev.of_node;
|
||||
int ret = 0;
|
||||
|
||||
mi = kzalloc(sizeof(*mi), GFP_KERNEL);
|
||||
mi = devm_kzalloc(&pdev->dev, sizeof(*mi), GFP_KERNEL);
|
||||
if (!mi)
|
||||
return -ENOMEM;
|
||||
|
||||
mi->i2c = chip->i2c;
|
||||
rt5025_misc_reg_init(mi->i2c, pdata->misc_data);
|
||||
|
||||
//for shutdown control
|
||||
mi->dev = &pdev->dev;
|
||||
if (use_dt) {
|
||||
rt_parse_dt(mi, &pdev->dev);
|
||||
} else {
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "no initial platform data\n");
|
||||
ret = -EINVAL;
|
||||
goto err_init;
|
||||
}
|
||||
pdev->dev.platform_data = pdata->misc_pdata;
|
||||
rt_parse_pdata(mi, &pdev->dev);
|
||||
}
|
||||
/*for shutdown control*/
|
||||
g_shdn = chip->i2c;
|
||||
|
||||
if (rt_pm_off && !pm_power_off)
|
||||
pm_power_off = rt5025_power_off;
|
||||
|
||||
platform_set_drvdata(pdev, mi);
|
||||
chip->misc_info = mi;
|
||||
dev_info(&pdev->dev, "driver successfully loaded\n");
|
||||
return 0;
|
||||
err_init:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rt5025_misc_remove(struct platform_device *pdev)
|
||||
{
|
||||
dev_info(&pdev->dev, "%s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit rt5025_misc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rt5025_misc_info *mi = platform_get_drvdata(pdev);
|
||||
|
||||
kfree(mi);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver rt5025_misc_driver =
|
||||
{
|
||||
.driver = {
|
||||
.name = RT5025_DEVICE_NAME "-misc",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = rt5025_misc_probe,
|
||||
.remove = __devexit_p(rt5025_misc_remove),
|
||||
static struct of_device_id rt_match_table[] = {
|
||||
{ .compatible = "rt,rt5025-misc",},
|
||||
{},
|
||||
};
|
||||
|
||||
static int __init rt5025_misc_init(void)
|
||||
static struct platform_driver rt5025_misc_driver = {
|
||||
.driver = {
|
||||
.name = RT5025_DEV_NAME "-misc",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = rt_match_table,
|
||||
},
|
||||
.probe = rt5025_misc_probe,
|
||||
.remove = rt5025_misc_remove,
|
||||
};
|
||||
|
||||
static int rt5025_misc_init(void)
|
||||
{
|
||||
return platform_driver_register(&rt5025_misc_driver);
|
||||
}
|
||||
module_init(rt5025_misc_init);
|
||||
subsys_initcall(rt5025_misc_init);
|
||||
|
||||
static void __exit rt5025_misc_exit(void)
|
||||
static void rt5025_misc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&rt5025_misc_driver);
|
||||
}
|
||||
module_exit(rt5025_misc_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
|
||||
MODULE_DESCRIPTION("Misc driver for RT5025");
|
||||
MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-misc");
|
||||
MODULE_ALIAS("platform:" RT5025_DEV_NAME "-misc");
|
||||
MODULE_VERSION(RT5025_DRV_VER);
|
||||
|
|
|
|||
|
|
@ -64,6 +64,43 @@ config WM8350_POWER
|
|||
Say Y here to enable support for the power management unit
|
||||
provided by the Wolfson Microelectronics WM8350 PMIC.
|
||||
|
||||
config CHARGER_RT5025
|
||||
bool "RT5025 Charger Driver"
|
||||
depends on MFD_RT5025
|
||||
default n
|
||||
help
|
||||
Enable RT5025 Charger driver.
|
||||
|
||||
config RT_POWER
|
||||
bool "RT5025 PMIC cable report"
|
||||
depends on CHARGER_RT5025
|
||||
default n
|
||||
help
|
||||
Enable AC/USB report.
|
||||
|
||||
config RT_SUPPORT_ACUSB_DUALIN
|
||||
bool "RT AC/USB Dualin Option"
|
||||
depends on RT_POWER
|
||||
default n
|
||||
help
|
||||
Say Y here to enable dualin, otherwise
|
||||
N is just singlein.
|
||||
|
||||
config BATTERY_RT5025
|
||||
bool "RT5025 PMIC ADC Type gauge driver"
|
||||
depends on MFD_RT5025
|
||||
default n
|
||||
help
|
||||
Enable the RT5025 ADC Fuelgauge driver.
|
||||
|
||||
config RT_JEITA_REMOVE
|
||||
bool "RT Jeita function remobe"
|
||||
depends on CHARGER_RT5025 && BATTERY_RT5025
|
||||
default n
|
||||
help
|
||||
Say Y here to remove Jeita function.
|
||||
|
||||
|
||||
config BATTERY_RICOH619
|
||||
tristate "Ricoh RC5T619 PMIC battery driver"
|
||||
depends on MFD_RICOH619 && I2C && GENERIC_HARDIRQS
|
||||
|
|
|
|||
|
|
@ -60,3 +60,6 @@ obj-$(CONFIG_BATTERY_RICOH619) += ricoh619-battery.o
|
|||
obj-$(CONFIG_CHARGER_DISPLAY) += rk29_charger_display.o
|
||||
obj-$(CONFIG_POWER_RESET) += reset/
|
||||
obj-$(CONFIG_BATTERY_RK818) += rk818_battery.o
|
||||
obj-$(CONFIG_CHARGER_RT5025) += rt5025-charger.o
|
||||
obj-$(CONFIG_RT_POWER) += rt-power.o
|
||||
obj-$(CONFIG_BATTERY_RT5025) += rt5025-battery.o
|
||||
|
|
|
|||
407
drivers/power/rt-power.c
Executable file
407
drivers/power/rt-power.c
Executable file
|
|
@ -0,0 +1,407 @@
|
|||
/*
|
||||
* drivers/power/rt-power.c
|
||||
* Driver for Richtek RT PMIC Power driver
|
||||
*
|
||||
* Copyright (C) 2014 Richtek Technology Corp.
|
||||
* cy_huang <cy_huang@richtek.com>
|
||||
*
|
||||
* 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; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/wakelock.h>
|
||||
|
||||
#include <linux/power/rt-power.h>
|
||||
|
||||
struct rt_power_info {
|
||||
struct device *dev;
|
||||
struct power_supply ac_psy;
|
||||
struct power_supply usb_psy;
|
||||
struct wake_lock usbdet_wakelock;
|
||||
struct delayed_work usbdet_work;
|
||||
int chg_volt;
|
||||
int acchg_icc;
|
||||
int usbtachg_icc;
|
||||
int usbchg_icc;
|
||||
unsigned char ac_online:1;
|
||||
unsigned char usbta_online:1;
|
||||
unsigned char usb_online:1;
|
||||
unsigned char suspend:1;
|
||||
unsigned char usbcnt;
|
||||
};
|
||||
|
||||
#define RT_USBCNT_MAX 60
|
||||
|
||||
static char *rtpower_supply_list[] = {
|
||||
"battery",
|
||||
};
|
||||
|
||||
static enum power_supply_property rtpower_props[] = {
|
||||
POWER_SUPPLY_PROP_ONLINE,
|
||||
};
|
||||
|
||||
static int rtpower_set_charger(struct rt_power_info *pi)
|
||||
{
|
||||
struct power_supply *chg_psy;
|
||||
union power_supply_propval pval;
|
||||
int rc = 0, is_chg_on = 0;
|
||||
|
||||
chg_psy = power_supply_get_by_name("rt-charger");
|
||||
if (chg_psy) {
|
||||
rc = chg_psy->get_property(chg_psy, POWER_SUPPLY_PROP_ONLINE, &pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "get chg online prop fail\n");
|
||||
else
|
||||
is_chg_on = pval.intval;
|
||||
if (pi->ac_online) {
|
||||
pval.intval = pi->acchg_icc;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_CURRENT_AVG,\
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set acchg aicr fail\n");
|
||||
pval.intval = 500;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_CURRENT_NOW,\
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set acchg icc fail\n");
|
||||
pval.intval = POWER_SUPPLY_TYPE_MAINS;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_CHARGE_NOW,\
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set charge cable fail\n");
|
||||
if (!is_chg_on) {
|
||||
pval.intval = pi->chg_volt;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_VOLTAGE_NOW,\
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set chg voltage fail\n");
|
||||
pval.intval = 1;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_ONLINE,\
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set charger online fail\n");
|
||||
}
|
||||
pval.intval = 1;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_PRESENT,\
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set charger present fail\n");
|
||||
} else if (pi->usbta_online) {
|
||||
pval.intval = pi->usbtachg_icc;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_CURRENT_AVG,\
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set usbtachg aicr fail\n");
|
||||
pval.intval = 500;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_CURRENT_NOW,\
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set usbtachg icc fail\n");
|
||||
pval.intval = POWER_SUPPLY_TYPE_USB_DCP;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_CHARGE_NOW,\
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set charge cable fail\n");
|
||||
if (!is_chg_on) {
|
||||
pval.intval = pi->chg_volt;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_VOLTAGE_NOW,\
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set chg voltage fail\n");
|
||||
pval.intval = 1;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_ONLINE,\
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set charger online fail\n");
|
||||
}
|
||||
pval.intval = 1;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_PRESENT,\
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set charger present fail\n");
|
||||
} else if (pi->usb_online) {
|
||||
pval.intval = pi->usbchg_icc;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_CURRENT_AVG,\
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set usbchg aicr fail\n");
|
||||
pval.intval = 500;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_CURRENT_NOW,\
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set usbchg icc fail\n");
|
||||
pval.intval = POWER_SUPPLY_TYPE_USB;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_CHARGE_NOW,\
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set charge cable fail\n");
|
||||
if (!is_chg_on) {
|
||||
pval.intval = pi->chg_volt;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_VOLTAGE_NOW,\
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set chg voltage fail\n");
|
||||
pval.intval = 1;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_ONLINE,\
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set charger online fail\n");
|
||||
}
|
||||
pval.intval = 1;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_PRESENT,\
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set charger present fail\n");
|
||||
|
||||
} else {
|
||||
pval.intval = 0;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_ONLINE,\
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set charger online fail\n");
|
||||
pval.intval = 0;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_CHARGE_NOW,\
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set charge cable fail\n");
|
||||
pval.intval = pi->chg_volt;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_VOLTAGE_NOW,\
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set chg voltage fail\n");
|
||||
pval.intval = 500;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_CURRENT_AVG,\
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set chg aicr fail\n");
|
||||
pval.intval = 500;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_CURRENT_NOW,\
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set chg icc fail\n");
|
||||
}
|
||||
power_supply_changed(chg_psy);
|
||||
} else {
|
||||
rc = -EINVAL;
|
||||
dev_err(pi->dev, "cannot get rt-charger psy\n");
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int rtpower_get_property(struct power_supply *psy, enum power_supply_property psp, \
|
||||
union power_supply_propval *val)
|
||||
{
|
||||
struct rt_power_info *pi = dev_get_drvdata(psy->dev->parent);
|
||||
int rc = 0;
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
if (psy->type == POWER_SUPPLY_TYPE_MAINS)
|
||||
val->intval = (pi->ac_online || pi->usbta_online)?1 : 0;
|
||||
else if (psy->type == POWER_SUPPLY_TYPE_USB)
|
||||
val->intval = pi->usb_online;
|
||||
else
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
default:
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int rtpower_set_property(struct power_supply *psy, enum power_supply_property psp, \
|
||||
const union power_supply_propval *val)
|
||||
{
|
||||
struct rt_power_info *pi = dev_get_drvdata(psy->dev->parent);
|
||||
int rc = 0;
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
if (psy->type == POWER_SUPPLY_TYPE_MAINS) {
|
||||
if (pi->ac_online != val->intval) {
|
||||
pi->ac_online = val->intval;
|
||||
rc = rtpower_set_charger(pi);
|
||||
}
|
||||
} else if (psy->type == POWER_SUPPLY_TYPE_USB) {
|
||||
if (pi->usb_online != val->intval) {
|
||||
pi->usb_online = val->intval;
|
||||
if (val->intval) {
|
||||
pi->usbcnt = 0;
|
||||
wake_lock(&pi->usbdet_wakelock);
|
||||
schedule_delayed_work(&pi->usbdet_work, 1*HZ);
|
||||
} else {
|
||||
pi->usbcnt = RT_USBCNT_MAX;
|
||||
schedule_delayed_work(&pi->usbdet_work, 0);
|
||||
if (pi->usbta_online) {
|
||||
pi->usbta_online = 0;
|
||||
power_supply_changed(&pi->ac_psy);
|
||||
}
|
||||
}
|
||||
rc = rtpower_set_charger(pi);
|
||||
}
|
||||
} else {
|
||||
rc = -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
extern int dwc_otg_check_dpdm(bool wait);
|
||||
static void usbdet_work_func(struct work_struct *work)
|
||||
{
|
||||
struct rt_power_info *pi = container_of(work, struct rt_power_info, \
|
||||
usbdet_work.work);
|
||||
int usb_det = dwc_otg_check_dpdm(0);
|
||||
|
||||
switch (usb_det) {
|
||||
case 2:
|
||||
dev_info(pi->dev, "usb ta checked\n");
|
||||
if (pi->usb_online) {
|
||||
pi->usbta_online = 1;
|
||||
rtpower_set_charger(pi);
|
||||
power_supply_changed(&pi->ac_psy);
|
||||
}
|
||||
pi->usbcnt = RT_USBCNT_MAX;
|
||||
break;
|
||||
case 1:
|
||||
case 0:
|
||||
dev_info(pi->dev, "normal usb\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (pi->usbcnt < RT_USBCNT_MAX) {
|
||||
pi->usbcnt++;
|
||||
schedule_delayed_work(&pi->usbdet_work, 1*HZ);
|
||||
} else {
|
||||
wake_unlock(&pi->usbdet_wakelock);
|
||||
}
|
||||
}
|
||||
|
||||
static int rt_power_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rt_power_info *pi;
|
||||
struct rt_power_data *rt_power_pdata = pdev->dev.platform_data;
|
||||
int ret = 0;
|
||||
|
||||
pi = devm_kzalloc(&pdev->dev, sizeof(*pi), GFP_KERNEL);
|
||||
if (!pi)
|
||||
return -ENOMEM;
|
||||
pi->dev = &pdev->dev;
|
||||
wake_lock_init(&pi->usbdet_wakelock, WAKE_LOCK_SUSPEND, "rt-usb-det");
|
||||
INIT_DELAYED_WORK(&pi->usbdet_work, usbdet_work_func);
|
||||
pi->chg_volt = rt_power_pdata->chg_volt;
|
||||
pi->acchg_icc = rt_power_pdata->acchg_icc;
|
||||
pi->usbtachg_icc = rt_power_pdata->usbtachg_icc;
|
||||
pi->usbchg_icc = rt_power_pdata->usbchg_icc;
|
||||
platform_set_drvdata(pdev, pi);
|
||||
|
||||
/* ac power supply register*/
|
||||
pi->ac_psy.name = RT_AC_NAME;
|
||||
pi->ac_psy.type = POWER_SUPPLY_TYPE_MAINS;
|
||||
pi->ac_psy.supplied_to = rtpower_supply_list;
|
||||
pi->ac_psy.properties = rtpower_props;
|
||||
pi->ac_psy.num_properties = ARRAY_SIZE(rtpower_props);
|
||||
pi->ac_psy.get_property = rtpower_get_property;
|
||||
pi->ac_psy.set_property = rtpower_set_property;
|
||||
ret = power_supply_register(&pdev->dev, &pi->ac_psy);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, " create ac power supply fail\n");
|
||||
goto err_init;
|
||||
}
|
||||
/*usb power supply register*/
|
||||
pi->usb_psy.name = RT_USB_NAME;
|
||||
pi->usb_psy.type = POWER_SUPPLY_TYPE_USB;
|
||||
pi->usb_psy.supplied_to = rtpower_supply_list;
|
||||
pi->usb_psy.properties = rtpower_props;
|
||||
pi->usb_psy.num_properties = ARRAY_SIZE(rtpower_props);
|
||||
pi->usb_psy.get_property = rtpower_get_property;
|
||||
pi->usb_psy.set_property = rtpower_set_property;
|
||||
ret = power_supply_register(&pdev->dev, &pi->usb_psy);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, " create usb power supply fail\n");
|
||||
goto err_acpsy;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_acpsy:
|
||||
power_supply_unregister(&pi->ac_psy);
|
||||
err_init:
|
||||
wake_lock_destroy(&pi->usbdet_wakelock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rt_power_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rt_power_info *pi = platform_get_drvdata(pdev);
|
||||
|
||||
power_supply_unregister(&pi->usb_psy);
|
||||
power_supply_unregister(&pi->ac_psy);
|
||||
wake_lock_destroy(&pi->usbdet_wakelock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt_power_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
struct rt_power_info *pi = platform_get_drvdata(pdev);
|
||||
|
||||
pi->suspend = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt_power_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct rt_power_info *pi = platform_get_drvdata(pdev);
|
||||
|
||||
pi->suspend = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id rt_match_table[] = {
|
||||
{ .compatible = "rt,rt-power",},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver rt_power_driver = {
|
||||
.driver = {
|
||||
.name = "rt-power",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = rt_match_table,
|
||||
},
|
||||
.probe = rt_power_probe,
|
||||
.remove = rt_power_remove,
|
||||
.suspend = rt_power_suspend,
|
||||
.resume = rt_power_resume,
|
||||
};
|
||||
static int rt_power_init(void)
|
||||
{
|
||||
return platform_driver_register(&rt_power_driver);
|
||||
}
|
||||
subsys_initcall(rt_power_init);
|
||||
|
||||
static void rt_power_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&rt_power_driver);
|
||||
}
|
||||
module_exit(rt_power_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("CY Huang <cy_huang@richtek.com>");
|
||||
MODULE_DESCRIPTION("RT Power driver");
|
||||
MODULE_ALIAS("platform:rt-power");
|
||||
MODULE_VERSION("1.0.0_G");
|
||||
2470
drivers/power/rt5025-battery.c
Normal file → Executable file
2470
drivers/power/rt5025-battery.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
1224
drivers/power/rt5025-charger.c
Executable file
1224
drivers/power/rt5025-charger.c
Executable file
File diff suppressed because it is too large
Load Diff
0
drivers/power/rt5025-power.c
Normal file → Executable file
0
drivers/power/rt5025-power.c
Normal file → Executable file
330
drivers/power/rt5025-swjeita.c
Normal file → Executable file
330
drivers/power/rt5025-swjeita.c
Normal file → Executable file
|
|
@ -22,11 +22,12 @@
|
|||
#include <linux/mfd/rt5025.h>
|
||||
#include <linux/power/rt5025-swjeita.h>
|
||||
|
||||
#define TEMP_TOLERANCE 30 // 'c*10 gap for tolerance
|
||||
#define TEMP_TOLERANCE 30 /*'c*10 gap for tolerance*/
|
||||
|
||||
static int rt5025_set_charging_cc_switch (struct i2c_client *i2c, int onoff)
|
||||
{
|
||||
int ret;
|
||||
|
||||
RTINFO("onoff = %d\n", onoff);
|
||||
if (onoff)
|
||||
ret = rt5025_set_bits(i2c, RT5025_REG_CHGCTL7, RT5025_CHGCCEN_MASK);
|
||||
|
|
@ -44,9 +45,9 @@ static int rt5025_set_charging_cc(struct i2c_client *i2c, int cur_value)
|
|||
if (cur_value < 500)
|
||||
data = 0;
|
||||
else if (cur_value > 2000)
|
||||
data = 0xf<<RT5025_CHGICC_SHIFT;
|
||||
data = 0xf << RT5025_CHGICC_SHIFT;
|
||||
else
|
||||
data = ((cur_value-500)/100)<<RT5025_CHGICC_SHIFT;
|
||||
data = ((cur_value - 500) / 100) << RT5025_CHGICC_SHIFT;
|
||||
|
||||
ret = rt5025_assign_bits(i2c, RT5025_REG_CHGCTL4, RT5025_CHGICC_MASK, data);
|
||||
|
||||
|
|
@ -67,9 +68,9 @@ static int rt5025_set_charging_cv(struct i2c_client *i2c, int voltage)
|
|||
if (voltage < 3500)
|
||||
data = 0;
|
||||
else if (voltage > 4440)
|
||||
data = 0x2f<<RT5025_CHGCV_SHIFT;
|
||||
data = 0x2f << RT5025_CHGCV_SHIFT;
|
||||
else
|
||||
data = ((voltage-3500)/20)<<RT5025_CHGCV_SHIFT;
|
||||
data = ((voltage - 3500) / 20) << RT5025_CHGCV_SHIFT;
|
||||
|
||||
ret = rt5025_assign_bits(i2c, RT5025_REG_CHGCTL3, RT5025_CHGCV_MASK, data);
|
||||
return ret;
|
||||
|
|
@ -101,53 +102,52 @@ static int rt5025_get_external_temp_index(struct rt5025_swjeita_info *swji)
|
|||
u8 data[2];
|
||||
long int temp;
|
||||
int sect_index;
|
||||
|
||||
|
||||
RTINFO("\n");
|
||||
if (rt5025_reg_block_read(swji->i2c, RT5025_REG_AINH, 2, data) < 0)
|
||||
pr_err("%s: failed to read ext_temp register\n", __func__);
|
||||
|
||||
temp = (data[0]*256+data[1])*61/100;
|
||||
temp = (temp * (-91738) +81521000)/100000;
|
||||
temp = (data[0] * 256 + data[1]) * 61 / 100;
|
||||
temp = (temp * (-91738) + 81521000) / 100000;
|
||||
|
||||
swji->cur_temp = temp;
|
||||
|
||||
RTINFO("cur_section = %d, cur_temp = %d\n", swji->cur_section, swji->cur_temp);
|
||||
|
||||
switch (swji->cur_section)
|
||||
{
|
||||
case 0:
|
||||
if (temp < swji->temp[0]+TEMP_TOLERANCE)
|
||||
sect_index = rt5025_sel_external_temp_index(swji);
|
||||
else
|
||||
sect_index = swji->cur_section;
|
||||
break;
|
||||
case 1:
|
||||
if (temp <= swji->temp[0]-TEMP_TOLERANCE || temp >= swji->temp[1]+TEMP_TOLERANCE)
|
||||
sect_index = rt5025_sel_external_temp_index(swji);
|
||||
else
|
||||
sect_index = swji->cur_section;
|
||||
break;
|
||||
case 2:
|
||||
if (temp <= swji->temp[1]-TEMP_TOLERANCE || temp >= swji->temp[2]+TEMP_TOLERANCE)
|
||||
sect_index = rt5025_sel_external_temp_index(swji);
|
||||
else
|
||||
sect_index = swji->cur_section;
|
||||
break;
|
||||
case 3:
|
||||
if (temp <= swji->temp[2]-TEMP_TOLERANCE || temp >= swji->temp[3]+TEMP_TOLERANCE)
|
||||
sect_index = rt5025_sel_external_temp_index(swji);
|
||||
else
|
||||
sect_index = swji->cur_section;
|
||||
break;
|
||||
case 4:
|
||||
if (temp <= swji->temp[3]-TEMP_TOLERANCE)
|
||||
sect_index = rt5025_sel_external_temp_index(swji);
|
||||
else
|
||||
sect_index = swji->cur_section;
|
||||
break;
|
||||
default:
|
||||
sect_index = swji->cur_section;
|
||||
break;
|
||||
switch (swji->cur_section) {
|
||||
case 0:
|
||||
if (temp < swji->temp[0] + TEMP_TOLERANCE)
|
||||
sect_index = rt5025_sel_external_temp_index(swji);
|
||||
else
|
||||
sect_index = swji->cur_section;
|
||||
break;
|
||||
case 1:
|
||||
if (temp <= swji->temp[0] - TEMP_TOLERANCE || temp >= swji->temp[1] + TEMP_TOLERANCE)
|
||||
sect_index = rt5025_sel_external_temp_index(swji);
|
||||
else
|
||||
sect_index = swji->cur_section;
|
||||
break;
|
||||
case 2:
|
||||
if (temp <= swji->temp[1] - TEMP_TOLERANCE || temp >= swji->temp[2] + TEMP_TOLERANCE)
|
||||
sect_index = rt5025_sel_external_temp_index(swji);
|
||||
else
|
||||
sect_index = swji->cur_section;
|
||||
break;
|
||||
case 3:
|
||||
if (temp <= swji->temp[2] - TEMP_TOLERANCE || temp >= swji->temp[3] + TEMP_TOLERANCE)
|
||||
sect_index = rt5025_sel_external_temp_index(swji);
|
||||
else
|
||||
sect_index = swji->cur_section;
|
||||
break;
|
||||
case 4:
|
||||
if (temp <= swji->temp[3] - TEMP_TOLERANCE)
|
||||
sect_index = rt5025_sel_external_temp_index(swji);
|
||||
else
|
||||
sect_index = swji->cur_section;
|
||||
break;
|
||||
default:
|
||||
sect_index = swji->cur_section;
|
||||
break;
|
||||
}
|
||||
RTINFO("sect_index = %d\n", sect_index);
|
||||
return sect_index;
|
||||
|
|
@ -185,26 +185,25 @@ static int rt5025_set_exttemp_alert(struct rt5025_swjeita_info *swji, int index)
|
|||
|
||||
RTINFO("index = %d\n", index);
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[1]);
|
||||
break;
|
||||
case 1:
|
||||
rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[0]);
|
||||
rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[3]);
|
||||
break;
|
||||
case 2:
|
||||
rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[2]);
|
||||
rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[5]);
|
||||
break;
|
||||
case 3:
|
||||
rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[4]);
|
||||
rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[7]);
|
||||
break;
|
||||
case 4:
|
||||
rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[6]);
|
||||
break;
|
||||
switch (index) {
|
||||
case 0:
|
||||
rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[1]);
|
||||
break;
|
||||
case 1:
|
||||
rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[0]);
|
||||
rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[3]);
|
||||
break;
|
||||
case 2:
|
||||
rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[2]);
|
||||
rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[5]);
|
||||
break;
|
||||
case 3:
|
||||
rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[4]);
|
||||
rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[7]);
|
||||
break;
|
||||
case 4:
|
||||
rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[6]);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -212,38 +211,34 @@ static int rt5025_set_exttemp_alert(struct rt5025_swjeita_info *swji, int index)
|
|||
|
||||
static int rt5025_exttemp_alert_switch(struct rt5025_swjeita_info *swji, int onoff)
|
||||
{
|
||||
if (!onoff)
|
||||
{
|
||||
if (!onoff) {
|
||||
rt5025_clr_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK);
|
||||
rt5025_clr_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (swji->cur_section)
|
||||
{
|
||||
case 0:
|
||||
rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK);
|
||||
break;
|
||||
case 1:
|
||||
rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK);
|
||||
rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK);
|
||||
break;
|
||||
case 2:
|
||||
rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK);
|
||||
rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK);
|
||||
break;
|
||||
case 3:
|
||||
rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK);
|
||||
rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK);
|
||||
break;
|
||||
case 4:
|
||||
rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK);
|
||||
break;
|
||||
} else {
|
||||
switch (swji->cur_section) {
|
||||
case 0:
|
||||
rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK);
|
||||
break;
|
||||
case 1:
|
||||
rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK);
|
||||
rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK);
|
||||
break;
|
||||
case 2:
|
||||
rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK);
|
||||
rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK);
|
||||
break;
|
||||
case 3:
|
||||
rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK);
|
||||
rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK);
|
||||
break;
|
||||
case 4:
|
||||
rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RTINFO("index=%d, onoff=%d\n", swji->cur_section, onoff);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rt5025_notify_charging_cable(struct rt5025_swjeita_info *swji, int cable_type)
|
||||
|
|
@ -256,34 +251,32 @@ int rt5025_notify_charging_cable(struct rt5025_swjeita_info *swji, int cable_typ
|
|||
rt5025_exttemp_alert_switch(swji, 0);
|
||||
|
||||
sect_index = rt5025_get_external_temp_index(swji);
|
||||
if (swji->cur_section != sect_index || swji->init_once == 0)
|
||||
{
|
||||
if (swji->cur_section != sect_index || swji->init_once == 0) {
|
||||
rt5025_set_exttemp_alert(swji, sect_index);
|
||||
swji->cur_section = sect_index;
|
||||
swji->init_once = 1;
|
||||
}
|
||||
|
||||
switch (cable_type)
|
||||
{
|
||||
case JEITA_NORMAL_USB:
|
||||
rt5025_set_charging_cc(swji->i2c, swji->temp_cc[cable_type][swji->cur_section]\
|
||||
- swji->dec_current);
|
||||
rt5025_set_charging_cv(swji->i2c, swji->temp_cv[cable_type][swji->cur_section]);
|
||||
break;
|
||||
case JEITA_USB_TA:
|
||||
rt5025_set_charging_cc(swji->i2c, swji->temp_cc[cable_type][swji->cur_section]\
|
||||
- swji->dec_current);
|
||||
rt5025_set_charging_cv(swji->i2c, swji->temp_cv[cable_type][swji->cur_section]);
|
||||
break;
|
||||
case JEITA_AC_ADAPTER:
|
||||
rt5025_set_charging_cc(swji->i2c, swji->temp_cc[cable_type][swji->cur_section]\
|
||||
- swji->dec_current);
|
||||
rt5025_set_charging_cv(swji->i2c, swji->temp_cv[cable_type][swji->cur_section]);
|
||||
break;
|
||||
case JEITA_NO_CHARGE:
|
||||
rt5025_set_charging_cc(swji->i2c, swji->temp_cc[cable_type][swji->cur_section]);
|
||||
rt5025_set_charging_cv(swji->i2c, swji->temp_cv[cable_type][swji->cur_section]);
|
||||
break;
|
||||
switch (cable_type) {
|
||||
case JEITA_NORMAL_USB:
|
||||
rt5025_set_charging_cc(swji->i2c, swji->temp_cc[cable_type][swji->cur_section]\
|
||||
- swji->dec_current);
|
||||
rt5025_set_charging_cv(swji->i2c, swji->temp_cv[cable_type][swji->cur_section]);
|
||||
break;
|
||||
case JEITA_USB_TA:
|
||||
rt5025_set_charging_cc(swji->i2c, swji->temp_cc[cable_type][swji->cur_section]\
|
||||
- swji->dec_current);
|
||||
rt5025_set_charging_cv(swji->i2c, swji->temp_cv[cable_type][swji->cur_section]);
|
||||
break;
|
||||
case JEITA_AC_ADAPTER:
|
||||
rt5025_set_charging_cc(swji->i2c, swji->temp_cc[cable_type][swji->cur_section]\
|
||||
- swji->dec_current);
|
||||
rt5025_set_charging_cv(swji->i2c, swji->temp_cv[cable_type][swji->cur_section]);
|
||||
break;
|
||||
case JEITA_NO_CHARGE:
|
||||
rt5025_set_charging_cc(swji->i2c, swji->temp_cc[cable_type][swji->cur_section]);
|
||||
rt5025_set_charging_cv(swji->i2c, swji->temp_cv[cable_type][swji->cur_section]);
|
||||
break;
|
||||
}
|
||||
swji->cur_cable = cable_type;
|
||||
|
||||
|
|
@ -298,7 +291,7 @@ int rt5025_swjeita_irq_handler(struct rt5025_swjeita_info *swji, unsigned char e
|
|||
int ret = 0;
|
||||
RTINFO("event = 0x%02x\n", event);
|
||||
|
||||
if (event&(RT5025_TMXEN_MASK|RT5025_TMNEN_MASK))
|
||||
if (event&(RT5025_TMXEN_MASK | RT5025_TMNEN_MASK))
|
||||
rt5025_notify_charging_cable(swji, swji->cur_cable);
|
||||
|
||||
return ret;
|
||||
|
|
@ -309,54 +302,51 @@ static void rt5025_get_internal_temp(struct rt5025_swjeita_info *swji)
|
|||
{
|
||||
u8 data[2];
|
||||
s32 temp;
|
||||
if (rt5025_reg_block_read(swji->i2c, RT5025_REG_INTTEMP_MSB, 2, data) < 0){
|
||||
if (rt5025_reg_block_read(swji->i2c, RT5025_REG_INTTEMP_MSB, 2, data) < 0)
|
||||
pr_err("%s: Failed to read internal TEMPERATURE\n", __func__);
|
||||
}
|
||||
|
||||
temp = ((data[0]&0x1F)<<8) + data[1];
|
||||
temp = ((data[0] & 0x1F) << 8) + data[1];
|
||||
temp *= 15625;
|
||||
temp /= 100000;
|
||||
|
||||
temp = (data[0]&0x20)?-temp:temp;
|
||||
temp = (data[0] & 0x20) ? -temp : temp;
|
||||
swji->cur_inttemp = temp;
|
||||
|
||||
RTINFO("internal temperature: %d\n", temp);
|
||||
}
|
||||
|
||||
|
||||
static void thermal_reg_work_func(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *delayed_work = (struct delayed_work *)container_of(work, struct delayed_work, work);
|
||||
struct rt5025_swjeita_info *swji = (struct rt5025_swjeita_info *)container_of(delayed_work, struct rt5025_swjeita_info, thermal_reg_work);
|
||||
int therm_region = 0;
|
||||
|
||||
|
||||
RTINFO("%s ++", __func__);
|
||||
rt5025_get_internal_temp(swji);
|
||||
|
||||
#if 1
|
||||
switch (swji->cur_therm_region)
|
||||
{
|
||||
case 0:
|
||||
if (swji->cur_inttemp >=820)
|
||||
therm_region = 1;
|
||||
else
|
||||
therm_region = 0;
|
||||
break;
|
||||
case 1:
|
||||
if (swji->cur_inttemp <= 780)
|
||||
therm_region = 0;
|
||||
else if (swji->cur_inttemp >= 1020)
|
||||
therm_region = 2;
|
||||
else
|
||||
therm_region = 1;
|
||||
break;
|
||||
case 2:
|
||||
if (swji->cur_inttemp <= 980)
|
||||
therm_region = 1;
|
||||
else
|
||||
therm_region = 2;
|
||||
break;
|
||||
|
||||
}
|
||||
switch (swji->cur_therm_region) {
|
||||
case 0:
|
||||
if (swji->cur_inttemp >= 820)
|
||||
therm_region = 1;
|
||||
else
|
||||
therm_region = 0;
|
||||
break;
|
||||
case 1:
|
||||
if (swji->cur_inttemp <= 780)
|
||||
therm_region = 0;
|
||||
else if (swji->cur_inttemp >= 1020)
|
||||
therm_region = 2;
|
||||
else
|
||||
therm_region = 1;
|
||||
break;
|
||||
case 2:
|
||||
if (swji->cur_inttemp <= 980)
|
||||
therm_region = 1;
|
||||
else
|
||||
therm_region = 2;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
if (swji->cur_inttemp < 800)
|
||||
therm_region = 0;
|
||||
|
|
@ -366,19 +356,17 @@ static void thermal_reg_work_func(struct work_struct *work)
|
|||
therm_region = 2;
|
||||
#endif /* #if 1*/
|
||||
|
||||
if (therm_region != swji->cur_therm_region)
|
||||
{
|
||||
switch (therm_region)
|
||||
{
|
||||
case 0:
|
||||
swji->dec_current = 0;
|
||||
break;
|
||||
case 1:
|
||||
swji->dec_current = 300;
|
||||
break;
|
||||
case 2:
|
||||
swji->dec_current = 800;
|
||||
break;
|
||||
if (therm_region != swji->cur_therm_region) {
|
||||
switch (therm_region) {
|
||||
case 0:
|
||||
swji->dec_current = 0;
|
||||
break;
|
||||
case 1:
|
||||
swji->dec_current = 300;
|
||||
break;
|
||||
case 2:
|
||||
swji->dec_current = 800;
|
||||
break;
|
||||
}
|
||||
swji->cur_therm_region = therm_region;
|
||||
rt5025_notify_charging_cable(swji, swji->cur_cable);
|
||||
|
|
@ -390,10 +378,10 @@ static void thermal_reg_work_func(struct work_struct *work)
|
|||
RTINFO("%s --", __func__);
|
||||
}
|
||||
|
||||
static int __devinit rt5025_swjeita_probe(struct platform_device *pdev)
|
||||
static int rt5025_swjeita_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent);
|
||||
struct rt5025_platform_data *pdata = chip->dev->platform_data;
|
||||
struct rt5025_platform_data *pdata = chip->dev->platform_data;
|
||||
struct rt5025_swjeita_info *swji;
|
||||
int ret = 0;
|
||||
|
||||
|
|
@ -401,23 +389,20 @@ static int __devinit rt5025_swjeita_probe(struct platform_device *pdev)
|
|||
if (!swji)
|
||||
return -ENOMEM;
|
||||
|
||||
#if 0 // for debug pdata->jeita_data
|
||||
for (ret=0; ret<4; ret++)
|
||||
#if 0 /* for debug pdata->jeita_data*/
|
||||
for (ret = 0; ret < 4; ret++)
|
||||
RTINFO("jeita temp value %d\n", pdata->jeita_data->temp[ret]);
|
||||
for (ret=0; ret<4; ret++)
|
||||
{
|
||||
for (ret = 0; ret < 4; ret++) {
|
||||
RTINFO("jeita temp_cc value %d, %d, %d, %d, %d\n", pdata->jeita_data->temp_cc[ret][0], \
|
||||
pdata->jeita_data->temp_cc[ret][1], pdata->jeita_data->temp_cc[ret][2], \
|
||||
pdata->jeita_data->temp_cc[ret][3], pdata->jeita_data->temp_cc[ret][4]);
|
||||
}
|
||||
for (ret=0; ret<4; ret++)
|
||||
{
|
||||
for (ret = 0; ret < 4; ret++) {
|
||||
RTINFO("jeita temp_cv value %d, %d, %d, %d, %d\n", pdata->jeita_data->temp_cv[ret][0], \
|
||||
pdata->jeita_data->temp_cv[ret][1], pdata->jeita_data->temp_cv[ret][2], \
|
||||
pdata->jeita_data->temp_cv[ret][3], pdata->jeita_data->temp_cv[ret][4]);
|
||||
}
|
||||
for (ret=0; ret<8; ret++)
|
||||
{
|
||||
for (ret = 0; ret < 8; ret++) {
|
||||
RTINFO("temp_scalar[%d] = 0x%02x\n", ret, pdata->jeita_data->temp_scalar[ret]);
|
||||
}
|
||||
ret = 0;
|
||||
|
|
@ -425,7 +410,8 @@ static int __devinit rt5025_swjeita_probe(struct platform_device *pdev)
|
|||
|
||||
swji->i2c = chip->i2c;
|
||||
swji->chip = chip;
|
||||
swji->cur_section = 2; //initial as the normal temperature
|
||||
swji->cur_section = 2;
|
||||
/*initial as the normal temperature*/
|
||||
swji->cur_cable = JEITA_NO_CHARGE;
|
||||
swji->temp = pdata->jeita_data->temp;
|
||||
swji->temp_scalar = pdata->jeita_data->temp_scalar;
|
||||
|
|
@ -445,7 +431,7 @@ static int __devinit rt5025_swjeita_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit rt5025_swjeita_remove(struct platform_device *pdev)
|
||||
static int rt5025_swjeita_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rt5025_swjeita_info *swji = platform_get_drvdata(pdev);
|
||||
|
||||
|
|
@ -458,6 +444,7 @@ static int __devexit rt5025_swjeita_remove(struct platform_device *pdev)
|
|||
static int rt5025_swjeita_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
struct rt5025_swjeita_info *swji = platform_get_drvdata(pdev);
|
||||
|
||||
swji->suspend = 1;
|
||||
cancel_delayed_work_sync(&swji->thermal_reg_work);
|
||||
swji->cur_therm_region = swji->dec_current = 0;
|
||||
|
|
@ -476,8 +463,7 @@ static int rt5025_swjeita_resume(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver rt5025_swjeita_driver =
|
||||
{
|
||||
static struct platform_driver rt5025_swjeita_driver = {
|
||||
.driver = {
|
||||
.name = RT5025_DEVICE_NAME "-swjeita",
|
||||
.owner = THIS_MODULE,
|
||||
|
|
@ -488,13 +474,13 @@ static struct platform_driver rt5025_swjeita_driver =
|
|||
.resume = rt5025_swjeita_resume,
|
||||
};
|
||||
|
||||
static int __init rt5025_swjeita_init(void)
|
||||
static int rt5025_swjeita_init(void)
|
||||
{
|
||||
return platform_driver_register(&rt5025_swjeita_driver);
|
||||
}
|
||||
module_init(rt5025_swjeita_init);
|
||||
|
||||
static void __exit rt5025_swjeita_exit(void)
|
||||
static void rt5025_swjeita_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&rt5025_swjeita_driver);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -262,6 +262,13 @@ config ACT8846_SUPPORT_RESET
|
|||
help
|
||||
Support short press key to restart.
|
||||
|
||||
config REGULATOR_RT5025
|
||||
bool "Richtek RT5025 PMIC Voltage regulstors"
|
||||
depends on MFD_RT5025
|
||||
default n
|
||||
help
|
||||
This driver supports voltage regulator in RT5025 PMIC chips.
|
||||
|
||||
config ROCKCHIP_PWM_REGULATOR
|
||||
tristate "rockchip pwm voltage regulator for discrete dcdc or ldo"
|
||||
help
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o
|
|||
obj-$(CONFIG_REGULATOR_ACT8846) += act8846.o
|
||||
obj-$(CONFIG_REGULATOR_SYR82X) += syr82x.o
|
||||
obj-$(CONFIG_REGULATOR_RICOH619) += ricoh619-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_RT5025) += rt5025-regulator.o
|
||||
|
||||
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip_io_vol_domain.o
|
||||
|
||||
|
|
|
|||
|
|
@ -2,12 +2,13 @@
|
|||
* drivers/regulator/rt5025-regulator.c
|
||||
* Driver foo Richtek RT5025 PMIC Regulator
|
||||
*
|
||||
* Copyright (C) 2013 Richtek Electronics
|
||||
* Copyright (C) 2014 Richtek Technology Corp.
|
||||
* cy_huang <cy_huang@richtek.com>
|
||||
*
|
||||
* 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.
|
||||
* published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
|
@ -18,6 +19,10 @@
|
|||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/version.h>
|
||||
#ifdef CONFIG_OF
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
#endif /* #ifdef CONFIG_OF */
|
||||
|
||||
#include <linux/mfd/rt5025.h>
|
||||
#include <linux/regulator/rt5025-regulator.h>
|
||||
|
||||
|
|
@ -25,7 +30,6 @@ struct rt5025_regulator_info {
|
|||
struct regulator_desc desc;
|
||||
struct regulator_dev *regulator;
|
||||
struct i2c_client *i2c;
|
||||
struct rt5025_chip *chip;
|
||||
const unsigned int *vol_output_list;
|
||||
const int vol_output_size;
|
||||
int min_uV;
|
||||
|
|
@ -37,11 +41,12 @@ struct rt5025_regulator_info {
|
|||
int enable_reg;
|
||||
int mode_bit;
|
||||
int mode_reg;
|
||||
int ramp_bit;
|
||||
int ramp_reg;
|
||||
};
|
||||
|
||||
//for DCDC1
|
||||
static const unsigned int rt5025_vol_output_list1[] =
|
||||
{
|
||||
/*for DCDC1*/
|
||||
static const unsigned int rt5025_vol_output_list1[] = {
|
||||
700*1000, 725*1000, 750*1000, 775*1000, 800*1000, 825*1000, 850*1000, 875*1000,
|
||||
900*1000, 925*1000, 950*1000, 975*1000, 1000*1000, 1025*1000, 1050*1000, 1075*1000,
|
||||
1100*1000, 1125*1000, 1150*1000, 1175*1000, 1200*1000, 1225*1000, 1250*1000, 1275*1000,
|
||||
|
|
@ -53,9 +58,8 @@ static const unsigned int rt5025_vol_output_list1[] =
|
|||
};
|
||||
#define rt5025_vol_output_size1 ARRAY_SIZE(rt5025_vol_output_list1)
|
||||
|
||||
//DCDC2, LDO1, LDO2
|
||||
static const unsigned int rt5025_vol_output_list2[] =
|
||||
{
|
||||
/*DCDC2, LDO1, LDO2*/
|
||||
static const unsigned int rt5025_vol_output_list2[] = {
|
||||
700*1000, 725*1000, 750*1000, 775*1000, 800*1000, 825*1000, 850*1000, 875*1000,
|
||||
900*1000, 925*1000, 950*1000, 975*1000, 1000*1000, 1025*1000, 1050*1000, 1075*1000,
|
||||
1100*1000, 1125*1000, 1150*1000, 1175*1000, 1200*1000, 1225*1000, 1250*1000, 1275*1000,
|
||||
|
|
@ -75,9 +79,8 @@ static const unsigned int rt5025_vol_output_list2[] =
|
|||
};
|
||||
#define rt5025_vol_output_size2 ARRAY_SIZE(rt5025_vol_output_list2)
|
||||
|
||||
//DCDC3
|
||||
static const unsigned int rt5025_vol_output_list3[] =
|
||||
{
|
||||
/*DCDC3*/
|
||||
static const unsigned int rt5025_vol_output_list3[] = {
|
||||
700*1000, 750*1000, 800*1000, 850*1000, 900*1000, 950*1000, 1000*1000, 1050*1000,
|
||||
1100*1000, 1150*1000, 1200*1000, 1250*1000, 1300*1000, 1350*1000, 1400*1000, 1450*1000,
|
||||
1500*1000, 1550*1000, 1600*1000, 1650*1000, 1700*1000, 1750*1000, 1800*1000, 1850*1000,
|
||||
|
|
@ -89,17 +92,15 @@ static const unsigned int rt5025_vol_output_list3[] =
|
|||
};
|
||||
#define rt5025_vol_output_size3 ARRAY_SIZE(rt5025_vol_output_list3)
|
||||
|
||||
//DCDC4
|
||||
static const unsigned int rt5025_vol_output_list4[] =
|
||||
{
|
||||
/*DCDC4*/
|
||||
static const unsigned int rt5025_vol_output_list4[] = {
|
||||
4500*1000, 4600*1000, 4700*1000, 4800*1000, 4900*1000, 5000*1000, 5100*1000, 5200*1000,
|
||||
5300*1000, 5400*1000, 5500*1000, 5500*1000, 5500*1000, 5500*1000, 5500*1000, 5500*1000,
|
||||
};
|
||||
#define rt5025_vol_output_size4 ARRAY_SIZE(rt5025_vol_output_list4)
|
||||
|
||||
//LDO3, LDO4, LDO5, LDO6
|
||||
static const unsigned int rt5025_vol_output_list5[] =
|
||||
{
|
||||
/*LDO3, LDO4, LDO5, LDO6*/
|
||||
static const unsigned int rt5025_vol_output_list5[] = {
|
||||
1000*1000, 1100*1000, 1200*1000, 1300*1000, 1400*1000, 1500*1000, 1600*1000, 1700*1000,
|
||||
1800*1000, 1900*1000, 2000*1000, 2100*1000, 2200*1000, 2300*1000, 2400*1000, 2500*1000,
|
||||
2600*1000, 2700*1000, 2800*1000, 2900*1000, 3000*1000, 3100*1000, 3200*1000, 3300*1000,
|
||||
|
|
@ -121,29 +122,29 @@ static int rt5025_list_voltage(struct regulator_dev *rdev, unsigned index)
|
|||
{
|
||||
struct rt5025_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
|
||||
return (index>=info->vol_output_size)? \
|
||||
-EINVAL: \
|
||||
info->vol_output_list[index];
|
||||
return (index >= info->vol_output_size) ? -EINVAL : info->vol_output_list[index];
|
||||
}
|
||||
|
||||
#if 0 //(LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,38))
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38))
|
||||
static int rt5025_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
|
||||
{
|
||||
struct rt5025_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
unsigned char data;
|
||||
const int count = info->vol_output_size;
|
||||
|
||||
if (selector>count)
|
||||
if (selector > count)
|
||||
return -EINVAL;
|
||||
data = (unsigned char)selector;
|
||||
data <<= info->vol_shift;
|
||||
return rt5025_assign_bits(info->i2c, info->vol_reg, info->vol_mask, data);
|
||||
return rt5025_assign_bits(info->i2c, info->vol_reg,
|
||||
info->vol_mask, data);
|
||||
}
|
||||
|
||||
static int rt5025_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
struct rt5025_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
|
||||
ret = rt5025_reg_read(info->i2c, info->vol_reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
@ -154,12 +155,12 @@ static int rt5025_find_voltage(struct regulator_dev *rdev,
|
|||
int min_uV, int max_uV)
|
||||
{
|
||||
struct rt5025_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
int i=0;
|
||||
int i = 0;
|
||||
const int count = info->vol_output_size;
|
||||
for (i=0;i<count;i++)
|
||||
{
|
||||
if ((info->vol_output_list[i]>=min_uV)
|
||||
&& (info->vol_output_list[i]<=max_uV))
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if ((info->vol_output_list[i] >= min_uV)
|
||||
&& (info->vol_output_list[i] <= max_uV))
|
||||
return i;
|
||||
}
|
||||
return -EINVAL;
|
||||
|
|
@ -167,20 +168,20 @@ static int rt5025_find_voltage(struct regulator_dev *rdev,
|
|||
|
||||
static int rt5025_set_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV, unsigned *selector)
|
||||
|
||||
{
|
||||
struct rt5025_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
unsigned char data;
|
||||
|
||||
if (check_range(info, min_uV, max_uV)) {
|
||||
dev_err(info->chip->dev, "invalid voltage range (%d, %d) uV\n",
|
||||
dev_err(&rdev->dev, "invalid voltage range (%d, %d) uV\n",
|
||||
min_uV, max_uV);
|
||||
return -EINVAL;
|
||||
}
|
||||
data = rt5025_find_voltage(rdev,min_uV,max_uV);
|
||||
data = rt5025_find_voltage(rdev, min_uV, max_uV);
|
||||
data <<= info->vol_shift;
|
||||
|
||||
return rt5025_assign_bits(info->i2c, info->vol_reg, info->vol_mask, data);
|
||||
return rt5025_assign_bits(info->i2c, info->vol_reg,
|
||||
info->vol_mask, data);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -188,6 +189,7 @@ static int rt5025_get_voltage(struct regulator_dev *rdev)
|
|||
{
|
||||
struct rt5025_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
|
||||
ret = rt5025_reg_read(info->i2c, info->vol_reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
@ -220,29 +222,29 @@ static int rt5025_is_enabled(struct regulator_dev *rdev)
|
|||
ret = rt5025_reg_read(info->i2c, info->enable_reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return (ret & (info->enable_bit))?1:0;
|
||||
return (ret & (info->enable_bit))?1 : 0;
|
||||
}
|
||||
|
||||
static int rt5025_set_mode(struct regulator_dev *rdev, unsigned int mode)
|
||||
{
|
||||
struct rt5025_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
if (!info->mode_bit)
|
||||
|
||||
if (!info->mode_bit) {
|
||||
ret = 0;
|
||||
else
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
ret = rt5025_set_bits(info->i2c, info->mode_reg, info->mode_bit);
|
||||
break;
|
||||
case REGULATOR_MODE_FAST:
|
||||
ret = rt5025_clr_bits(info->i2c, info->mode_reg, info->mode_bit);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
} else {
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
ret = rt5025_set_bits(info->i2c, info->mode_reg,
|
||||
info->mode_bit);
|
||||
break;
|
||||
case REGULATOR_MODE_FAST:
|
||||
ret = rt5025_clr_bits(info->i2c, info->mode_reg,
|
||||
info->mode_bit);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
|
@ -254,19 +256,18 @@ static unsigned int rt5025_get_mode(struct regulator_dev *rdev)
|
|||
unsigned int mode;
|
||||
int data;
|
||||
|
||||
if (!info->mode_bit)
|
||||
if (!info->mode_bit) {
|
||||
mode = REGULATOR_MODE_NORMAL;
|
||||
else
|
||||
{
|
||||
} else {
|
||||
data = rt5025_reg_read(info->i2c, info->mode_reg);
|
||||
mode = (data & info->mode_bit)?REGULATOR_MODE_NORMAL:REGULATOR_MODE_FAST;
|
||||
mode = (data & info->mode_bit)?REGULATOR_MODE_NORMAL : REGULATOR_MODE_FAST;
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
|
||||
static struct regulator_ops rt5025_regulator_ops = {
|
||||
.list_voltage = rt5025_list_voltage,
|
||||
#if 0 //(LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,38))
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38))
|
||||
.get_voltage_sel = rt5025_get_voltage_sel,
|
||||
.set_voltage_sel = rt5025_set_voltage_sel,
|
||||
#else
|
||||
|
|
@ -306,24 +307,26 @@ static struct regulator_ops rt5025_regulator_ops = {
|
|||
#define RT5025_DCDC(_id, min, max) \
|
||||
{ \
|
||||
.desc = { \
|
||||
.name = "rt5025-dcdc" #_id, \
|
||||
.name = "rt5025-dcdc" #_id, \
|
||||
.n_voltages = RT5025_DCDCVOUT_SIZE##_id, \
|
||||
.ops = &rt5025_regulator_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.id = RT5025_ID_DCDC##_id, \
|
||||
.owner = THIS_MODULE, \
|
||||
}, \
|
||||
.vol_output_list= RT5025_DCDCVOUT_LIST##_id, \
|
||||
.vol_output_size= RT5025_DCDCVOUT_SIZE##_id, \
|
||||
.min_uV = min , \
|
||||
.max_uV = max , \
|
||||
.vol_output_list = RT5025_DCDCVOUT_LIST##_id, \
|
||||
.vol_output_size = RT5025_DCDCVOUT_SIZE##_id, \
|
||||
.min_uV = min * 1000, \
|
||||
.max_uV = max * 1000, \
|
||||
.vol_reg = RT5025_DCDCVOUT##_id, \
|
||||
.vol_shift = RT5025_DCDCVOUT_SHIFT##_id, \
|
||||
.vol_mask = RT5025_DCDCVOUT_MASK##_id, \
|
||||
.enable_reg = RT5025_DCDC_OUTPUT_EN, \
|
||||
.enable_reg = RT5025_REG_DCDCONOFF, \
|
||||
.enable_bit = RT5025_DCDCEN_MASK##_id, \
|
||||
.mode_reg = RT5025_REG_DCDCVRC, \
|
||||
.mode_bit = RT5025_DCDCMODE_MASK##_id \
|
||||
.mode_reg = RT5025_DCDCMODE_REG##_id, \
|
||||
.mode_bit = RT5025_DCDCMODE_MASK##_id, \
|
||||
.ramp_reg = RT5025_DCDCVOUT##_id, \
|
||||
.ramp_bit = RT5025_DCDCRAMP_MASK##_id, \
|
||||
}
|
||||
|
||||
#define RT5025_LDO(_id, min, max) \
|
||||
|
|
@ -336,34 +339,31 @@ static struct regulator_ops rt5025_regulator_ops = {
|
|||
.id = RT5025_ID_LDO##_id, \
|
||||
.owner = THIS_MODULE, \
|
||||
}, \
|
||||
.vol_output_list= RT5025_LDOVOUT_LIST##_id, \
|
||||
.vol_output_size= RT5025_LDOVOUT_SIZE##_id, \
|
||||
.min_uV = min , \
|
||||
.max_uV = max, \
|
||||
.vol_output_list = RT5025_LDOVOUT_LIST##_id, \
|
||||
.vol_output_size = RT5025_LDOVOUT_SIZE##_id, \
|
||||
.min_uV = min * 1000, \
|
||||
.max_uV = max * 1000, \
|
||||
.vol_reg = RT5025_LDOVOUT##_id, \
|
||||
.vol_shift = RT5025_LDOVOUT_SHIFT##_id, \
|
||||
.vol_mask = RT5025_LDOVOUT_MASK##_id, \
|
||||
.enable_reg = RT5025_LDO_OUTPUT_EN, \
|
||||
.enable_reg = RT5025_REG_LDOONOFF, \
|
||||
.enable_bit = RT5025_LDOEN_MASK##_id, \
|
||||
.mode_reg = RT5025_REG_LDOVRC, \
|
||||
.mode_bit = RT5025_LDOMODE_MASK##_id, \
|
||||
}
|
||||
|
||||
static struct rt5025_regulator_info rt5025_regulator_info[] =
|
||||
{
|
||||
RT5025_DCDC(1, 700000, 2275000),
|
||||
RT5025_DCDC(2, 700000, 3500000),
|
||||
RT5025_DCDC(3, 700000, 3500000),
|
||||
RT5025_DCDC(4, 4500000, 5500000),
|
||||
RT5025_LDO( 1, 700000, 3500000),
|
||||
RT5025_LDO( 2, 700000, 3500000),
|
||||
RT5025_LDO( 3, 1000000, 3300000),
|
||||
RT5025_LDO( 4, 1000000, 3300000),
|
||||
RT5025_LDO( 5, 1000000, 3300000),
|
||||
RT5025_LDO( 6, 1000000, 3300000),
|
||||
static struct rt5025_regulator_info rt5025_regulator_info[] = {
|
||||
RT5025_DCDC(1, 700, 2275),
|
||||
RT5025_DCDC(2, 700, 3500),
|
||||
RT5025_DCDC(3, 700, 3500),
|
||||
RT5025_DCDC(4, 4500, 5500),
|
||||
RT5025_LDO(1, 700, 3500),
|
||||
RT5025_LDO(2, 700, 3500),
|
||||
RT5025_LDO(3, 1000, 3300),
|
||||
RT5025_LDO(4, 1000, 3300),
|
||||
RT5025_LDO(5, 1000, 3300),
|
||||
RT5025_LDO(6, 1000, 3300),
|
||||
};
|
||||
|
||||
static struct rt5025_regulator_info * __devinit find_regulator_info(int id)
|
||||
static struct rt5025_regulator_info *find_regulator_info(int id)
|
||||
{
|
||||
struct rt5025_regulator_info *ri;
|
||||
int i;
|
||||
|
|
@ -375,43 +375,87 @@ static struct rt5025_regulator_info * __devinit find_regulator_info(int id)
|
|||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline struct regulator_dev* rt5025_regulator_register(struct regulator_desc *regulator_desc,
|
||||
struct device *dev, struct regulator_init_data *init_data,
|
||||
void *driver_data)
|
||||
struct regulator_dev *rt5025_regulator_register(struct regulator_desc *regulator_desc,
|
||||
struct device *dev, struct regulator_init_data *init_data,
|
||||
void *driver_data)
|
||||
{
|
||||
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(3,5,0))
|
||||
struct regulator_config config = {
|
||||
.dev = dev,
|
||||
.init_data = init_data,
|
||||
.driver_data = driver_data,
|
||||
};
|
||||
return regulator_register(®ulator_desc, &config);
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
|
||||
struct regulator_config config = {
|
||||
.dev = dev,
|
||||
.init_data = init_data,
|
||||
.driver_data = driver_data,
|
||||
.of_node = dev->of_node,
|
||||
};
|
||||
return regulator_register(regulator_desc, &config);
|
||||
#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 37))
|
||||
return regulator_register(regulator_desc, dev, init_data,
|
||||
driver_data, dev->of_node);
|
||||
#else
|
||||
return regulator_register(regulator_desc,dev,init_data,driver_data);
|
||||
return regulator_register(regulator_desc, dev, init_data, driver_data);
|
||||
#endif /* LINUX_VERSION_CODE>=KERNEL_VERSION(3,5,0)) */
|
||||
}
|
||||
|
||||
static int __devinit rt5025_regulator_probe(struct platform_device *pdev)
|
||||
static struct regulator_init_data *of_parse_dt(struct rt5025_regulator_info *ri,
|
||||
struct device *dev)
|
||||
{
|
||||
struct regulator_init_data *init_data = NULL;
|
||||
#ifdef CONFIG_OF
|
||||
struct device_node *np = dev->of_node;
|
||||
int rc;
|
||||
u32 tmp;
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
|
||||
init_data = of_get_regulator_init_data(dev, dev->of_node);
|
||||
#else
|
||||
init_data = of_get_regulator_init_data(dev);
|
||||
#endif /* #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) */
|
||||
rc = of_property_read_u32(np, "rt,ramp_sel", &tmp);
|
||||
if (rc) {
|
||||
dev_info(dev, "no ramp_sel property, use default value\n");
|
||||
} else {
|
||||
if (tmp > RT5025_DCDCRAMP_MAX)
|
||||
tmp = RT5025_DCDCRAMP_MAX;
|
||||
rt5025_assign_bits(ri->i2c, ri->ramp_reg, ri->ramp_bit, tmp);
|
||||
}
|
||||
|
||||
if (of_property_read_bool(np, "rt,allow_mode_mask")) {
|
||||
init_data->constraints.valid_modes_mask |=
|
||||
(REGULATOR_MODE_FAST|\
|
||||
REGULATOR_MODE_NORMAL);
|
||||
init_data->constraints.valid_ops_mask |= REGULATOR_CHANGE_MODE;
|
||||
}
|
||||
#endif /* #ifdef CONFIG_OF */
|
||||
return init_data;
|
||||
}
|
||||
|
||||
static int rt5025_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent);
|
||||
struct rt5025_platform_data *pdata = chip->dev->platform_data;
|
||||
struct rt5025_platform_data *pdata = (pdev->dev.parent)->platform_data;
|
||||
struct rt5025_regulator_info *ri;
|
||||
struct rt5025_regulator_ramp *ramp;
|
||||
struct regulator_dev *rdev;
|
||||
struct regulator_init_data* init_data;
|
||||
struct regulator_init_data *init_data;
|
||||
bool use_dt = pdev->dev.of_node;
|
||||
|
||||
ri = find_regulator_info(pdev->id);
|
||||
if (ri == NULL) {
|
||||
dev_err(&pdev->dev, "invalid regulator ID specified\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
init_data = pdata->regulator[pdev->id];
|
||||
if (init_data == NULL) {
|
||||
ri->i2c = chip->i2c;
|
||||
if (use_dt) {
|
||||
init_data = of_parse_dt(ri, &pdev->dev);
|
||||
} else {
|
||||
init_data = pdata->regulator[pdev->id];
|
||||
ramp = init_data->driver_data;
|
||||
if (ramp)
|
||||
rt5025_assign_bits(ri->i2c, ri->ramp_reg,
|
||||
ri->ramp_bit, ramp->ramp_sel);
|
||||
}
|
||||
if (!init_data) {
|
||||
dev_err(&pdev->dev, "no initializing data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
ri->i2c = chip->i2c;
|
||||
ri->chip = chip;
|
||||
|
||||
rdev = rt5025_regulator_register(&ri->desc, &pdev->dev,
|
||||
init_data, ri);
|
||||
|
|
@ -420,46 +464,59 @@ static int __devinit rt5025_regulator_probe(struct platform_device *pdev)
|
|||
ri->desc.name);
|
||||
return PTR_ERR(rdev);
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, rdev);
|
||||
|
||||
/* dev_info(&pdev->dev, "driver successfully loaded\n");*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit rt5025_regulator_remove(struct platform_device *pdev)
|
||||
static int rt5025_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct regulator_dev *rdev = platform_get_drvdata(pdev);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
regulator_unregister(rdev);
|
||||
|
||||
dev_info(&pdev->dev, "%s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver rt5025_regulator_driver =
|
||||
{
|
||||
.driver = {
|
||||
.name = RT5025_DEVICE_NAME "-regulator",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = rt5025_regulator_probe,
|
||||
.remove = __devexit_p(rt5025_regulator_remove),
|
||||
static struct of_device_id rt_match_table[] = {
|
||||
{ .compatible = "rt,rt5025-dcdc1",},
|
||||
{ .compatible = "rt,rt5025-dcdc2",},
|
||||
{ .compatible = "rt,rt5025-dcdc3",},
|
||||
{ .compatible = "rt,rt5025-dcdc4",},
|
||||
{ .compatible = "rt,rt5025-ldo1",},
|
||||
{ .compatible = "rt,rt5025-ldo2",},
|
||||
{ .compatible = "rt,rt5025-ldo3",},
|
||||
{ .compatible = "rt,rt5025-ldo4",},
|
||||
{ .compatible = "rt,rt5025-ldo5",},
|
||||
{ .compatible = "rt,rt5025-ldo6",},
|
||||
{},
|
||||
};
|
||||
|
||||
static int __init rt5025_regulator_init(void)
|
||||
static struct platform_driver rt5025_regulator_driver = {
|
||||
.driver = {
|
||||
.name = RT5025_DEV_NAME "-regulator",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = rt_match_table,
|
||||
},
|
||||
.probe = rt5025_regulator_probe,
|
||||
.remove = rt5025_regulator_remove,
|
||||
};
|
||||
|
||||
static int rt5025_regulator_init(void)
|
||||
{
|
||||
return platform_driver_register(&rt5025_regulator_driver);
|
||||
}
|
||||
subsys_initcall_sync(rt5025_regulator_init);
|
||||
subsys_initcall(rt5025_regulator_init);
|
||||
|
||||
static void __exit rt5025_regulator_exit(void)
|
||||
static void rt5025_regulator_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&rt5025_regulator_driver);
|
||||
}
|
||||
module_exit(rt5025_regulator_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("CY Huang <cy_huang@richtek.com>");
|
||||
MODULE_DESCRIPTION("Regulator driver for RT5025");
|
||||
MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-regulator");
|
||||
MODULE_ALIAS("platform:" RT5025_DEV_NAME "-regulator");
|
||||
MODULE_VERSION(RT5025_DRV_VER);
|
||||
|
|
|
|||
|
|
@ -1,26 +1,21 @@
|
|||
/*
|
||||
* include/linux/mfd/rt5025-gpio.h
|
||||
* include/linux/mfd/rt5025/rt5025-gpio.h
|
||||
* Include header file for Richtek RT5025 PMIC GPIO file
|
||||
*
|
||||
* Copyright (C) 2013 Richtek Electronics
|
||||
* Copyright (C) 2013 Richtek Technology Corp.
|
||||
* cy_huang <cy_huang@richtek.com>
|
||||
*
|
||||
* 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.
|
||||
* published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_RT5025_GPIO_H
|
||||
#define __LINUX_RT5025_GPIO_H
|
||||
|
||||
#define RT5025_REG_GPIO0 0x1C
|
||||
#define RT5025_REG_GPIO1 0x1D
|
||||
#define RT5025_REG_GPIO2 0x1E
|
||||
|
||||
#define RT5025_GPIO_NR 3
|
||||
|
||||
#define RT5025_GPIO_INPUT 0x00
|
||||
#define RT5025_GPIO_OUTPUT 0x02
|
||||
#define RT5025_GPIO_INPUT 0x00
|
||||
#define RT5025_GPIO_OUTPUT 0x02
|
||||
|
||||
#define RT5025_GPIO_DIRSHIFT 6
|
||||
#define RT5025_GPIO_DIRMASK 0xC0
|
||||
|
|
|
|||
30
include/linux/mfd/rt5025-irq.h
Normal file → Executable file
30
include/linux/mfd/rt5025-irq.h
Normal file → Executable file
|
|
@ -1,39 +1,19 @@
|
|||
/*
|
||||
* include/linux/mfd/rt5025-irq.h
|
||||
* include/linux/mfd/rt5025/rt5025-irq.h
|
||||
* Include header file for Richtek RT5025 PMIC IRQ file
|
||||
*
|
||||
* Copyright (C) 2013 Richtek Electronics
|
||||
* Copyright (C) 2014 Richtek Technology Corp.
|
||||
* cy_huang <cy_huang@richtek.com>
|
||||
*
|
||||
* 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.
|
||||
* published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_RT5025_IRQ_H
|
||||
#define __LINUX_RT5025_IRQ_H
|
||||
|
||||
#define RT5025_REG_CHGSTAT 0x01
|
||||
|
||||
#define RT5025_REG_IRQEN1 0x30
|
||||
#define RT5025_REG_IRQSTATUS1 0x31
|
||||
#define RT5025_REG_IRQEN2 0x32
|
||||
#define RT5025_REG_IRQSTATUS2 0x33
|
||||
#define RT5025_REG_IRQEN3 0x34
|
||||
#define RT5025_REG_IRQSTATUS3 0x35
|
||||
#define RT5025_REG_IRQEN4 0x36
|
||||
#define RT5025_REG_IRQSTATUS4 0x37
|
||||
#define RT5025_REG_IRQEN5 0x38
|
||||
#define RT5025_REG_IRQSTATUS5 0x39
|
||||
|
||||
#define RT5025_INACIRQ_MASK 0x40
|
||||
#define RT5025_INUSBIRQ_MASK 0x08
|
||||
#define RT5025_ADAPIRQ_MASK (RT5025_INACIRQ_MASK|RT5025_INUSBIRQ_MASK)
|
||||
#define RT5025_CHTERMI_MASK 0x01
|
||||
|
||||
#define RT5025_REG_GAUGEIRQEN 0x50
|
||||
#define RT5025_REG_GAUGEIRQFLG 0x51
|
||||
#define RT5025_FLG_TEMP 0x30
|
||||
#define RT5025_FLG_VOLT 0x07
|
||||
#define RT5025_TALRT_MASK 0x30
|
||||
|
||||
#endif /* #ifndef __LINUX_RT5025_IRQ_H */
|
||||
|
|
|
|||
37
include/linux/mfd/rt5025-misc.h
Normal file → Executable file
37
include/linux/mfd/rt5025-misc.h
Normal file → Executable file
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* include/linux/mfd/rt5025-misc.h
|
||||
* include/linux/mfd/rt5025/rt5025-misc.h
|
||||
* Include header file for Richtek RT5025 PMIC Misc
|
||||
*
|
||||
* Copyright (C) 2013 Richtek Technology Corp.
|
||||
|
|
@ -14,15 +14,36 @@
|
|||
#ifndef __LINUX_RT5025_MISC_H
|
||||
#define __LINUX_RT5025_MISC_H
|
||||
|
||||
#define RT5025_RESETCTRL_REG 0x15
|
||||
#define RT5025_VSYSULVO_REG 0x17
|
||||
#define RT5025_PWRONCTRL_REG 0x19
|
||||
#define RT5025_SHDNCTRL_REG 0x1A
|
||||
#define RT5025_PWROFFEN_REG 0x1B
|
||||
#define RT5025_CHENH_REG 0x62
|
||||
#define RT5025_CHENL_REG 0x63
|
||||
enum {
|
||||
MISCEVENT_GPIO0_IE = 1,
|
||||
MISCEVENT_GPIO1_IE,
|
||||
MISCEVENT_GPIO2_IE,
|
||||
MISCEVENT_RESETB,
|
||||
MISCEVENT_PWRONF,
|
||||
MISCEVENT_PWRONR,
|
||||
MISCEVENT_KPSHDN,
|
||||
MISCEVENT_SYSLV,
|
||||
MISCEVENT_DCDC4LVHV,
|
||||
MISCEVENT_PWRONLP_IRQ,
|
||||
MISCEVENT_PWRONSP_IRQ,
|
||||
MISCEVENT_DCDC3LV,
|
||||
MISCEVENT_DCDC2LV,
|
||||
MISCEVENT_DCDC1LV,
|
||||
MISCEVENT_OT,
|
||||
MISCEVENT_MAX,
|
||||
};
|
||||
|
||||
#define RT5025_SHDNCTRL_MASK 0x80
|
||||
#define RT5025_VSYSOFF_MASK 0xE0
|
||||
#define RT5025_VSYSOFF_SHFT 5
|
||||
#define RT5025_SHDNLPRESS_MASK 0x0C
|
||||
#define RT5025_SHDNLPRESS_SHFT 2
|
||||
#define RT5025_STARTLPRESS_MASK 0xC0
|
||||
#define RT5025_STARTLPRESS_SHFT 6
|
||||
#define RT5025_VSYSLVSHDN_MASK 0x80
|
||||
#define RT5025_VSYSLVSHDN_SHFT 7
|
||||
#define RT5025_CABLEIN_MASK 0x03
|
||||
|
||||
extern int rt5025_cable_exist(void);
|
||||
|
||||
#endif /* #ifndef __LINUX_RT5025_MISC_H */
|
||||
|
|
|
|||
844
include/linux/mfd/rt5025.h
Normal file → Executable file
844
include/linux/mfd/rt5025.h
Normal file → Executable file
|
|
@ -1,36 +1,147 @@
|
|||
/*
|
||||
* include/linux/mfd/rt5025.h
|
||||
* include/linux/mfd/rt5025/rt5025.h
|
||||
* Include header file for Richtek RT5025 Core file
|
||||
*
|
||||
* Copyright (C) 2013 Richtek Electronics
|
||||
* Copyright (C) 2013 Richtek Technology Corp.
|
||||
* cy_huang <cy_huang@richtek.com>
|
||||
*
|
||||
* 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.
|
||||
* published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_MFD_RT5025_H
|
||||
#define __LINUX_MFD_RT5025_H
|
||||
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/android_alarm.h>
|
||||
#include <linux/alarmtimer.h>
|
||||
#include <linux/wakelock.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif /* CONFIG_HAS_EARLYSUSPEND */
|
||||
|
||||
#define RT5025_DEVICE_NAME "RT5025"
|
||||
#define RT5025_DRV_VER "1.0.8_R"
|
||||
#define RT5025_DEV_NAME "rt5025"
|
||||
#define RT5025_DRV_VER "1.1.0_R"
|
||||
|
||||
#define RT_BATT_NAME "rt-battery"
|
||||
|
||||
enum {
|
||||
RT5025_RSTDELAY1_100MS,
|
||||
RT5025_RSTDELAY1_500MS,
|
||||
RT5025_RSTDELAY1_1S,
|
||||
RT5025_RSTDELAY1_2S,
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5025_RSTDELAY2_100MS,
|
||||
RT5025_RSTDELAY2_500MS,
|
||||
RT5025_RSTDELAY2_1S,
|
||||
RT5025_RSTDELAY2_2S,
|
||||
RT5025_REG_DEVID,
|
||||
RT5025_REG_RANGE1START = RT5025_REG_DEVID,
|
||||
RT5025_REG_CHGCTL1,
|
||||
RT5025_REG_CHGCTL2,
|
||||
RT5025_REG_CHGCTL3,
|
||||
RT5025_REG_CHGCTL4,
|
||||
RT5025_REG_CHGCTL5,
|
||||
RT5025_REG_CHGCTL6,
|
||||
RT5025_REG_CHGCTL7,
|
||||
RT5025_REG_DCDCCTL1,
|
||||
RT5025_REG_DCDCCTL2,
|
||||
RT5025_REG_DCDCCTL3,
|
||||
RT5025_REG_VRCCTL,
|
||||
RT5025_REG_DCDCCTL4,
|
||||
RT5025_REG_LDOCTL1,
|
||||
RT5025_REG_LDOCTL2,
|
||||
RT5025_REG_LDOCTL3,
|
||||
RT5025_REG_LDOCTL4,
|
||||
RT5025_REG_LDOCTL5,
|
||||
RT5025_REG_LDOCTL6,
|
||||
RT5025_REG_RESV0,
|
||||
RT5025_REG_LDOOMS,
|
||||
RT5025_REG_MISC1,
|
||||
RT5025_REG_ONEVENT,
|
||||
RT5025_REG_DCDCONOFF,
|
||||
RT5025_REG_LDOONOFF,
|
||||
RT5025_REG_MISC2,
|
||||
RT5025_REG_MISC3,
|
||||
RT5025_REG_MISC4,
|
||||
RT5025_REG_GPIO0,
|
||||
RT5025_REG_GPIO1,
|
||||
RT5025_REG_GPIO2,
|
||||
RT5025_REG_RANGE1END = RT5025_REG_GPIO2,
|
||||
RT5025_REG_OFFEVENT = 0x20,
|
||||
RT5025_REG_RANGE2START = RT5025_REG_OFFEVENT,
|
||||
RT5025_REG_RESV1,
|
||||
RT5025_REG_RESV2,
|
||||
RT5025_REG_RESV3,
|
||||
RT5025_REG_RESV4,
|
||||
RT5025_REG_RESV5,
|
||||
RT5025_REG_RESV6,
|
||||
RT5025_REG_RESV7,
|
||||
RT5025_REG_RESV8,
|
||||
RT5025_REG_RESV9,
|
||||
RT5025_REG_RESV10,
|
||||
RT5025_REG_RESV11,
|
||||
RT5025_REG_RESV12,
|
||||
RT5025_REG_RESV13,
|
||||
RT5025_REG_RESV14,
|
||||
RT5025_REG_RESV15,
|
||||
RT5025_REG_IRQEN1,
|
||||
RT5025_REG_IRQSTAT1,
|
||||
RT5025_REG_IRQEN2,
|
||||
RT5025_REG_IRQSTAT2,
|
||||
RT5025_REG_IRQEN3,
|
||||
RT5025_REG_IRQSTAT3,
|
||||
RT5025_REG_IRQEN4,
|
||||
RT5025_REG_IRQSTAT4,
|
||||
RT5025_REG_IRQEN5,
|
||||
RT5025_REG_IRQSTAT5,
|
||||
RT5025_REG_RANGE2END = RT5025_REG_IRQSTAT5,
|
||||
RT5025_REG_IRQCTL = 0x50,
|
||||
RT5025_REG_RANGE3START = RT5025_REG_IRQCTL,
|
||||
RT5025_REG_IRQFLG,
|
||||
RT5025_REG_FGRESV1,
|
||||
RT5025_REG_VALRTMAX,
|
||||
RT5025_REG_VALRTMIN1,
|
||||
RT5025_REG_VALRTMIN2,
|
||||
RT5025_REG_TALRTMAX,
|
||||
RT5025_REG_TALRTMIN,
|
||||
RT5025_REG_VBATSH,
|
||||
RT5025_REG_VBATSL,
|
||||
RT5025_REG_INTEMPH,
|
||||
RT5025_REG_INTEMPL,
|
||||
RT5025_REG_FGRESV2,
|
||||
RT5025_REG_CONFIG,
|
||||
RT5025_REG_AINH,
|
||||
RT5025_REG_AINL,
|
||||
RT5025_REG_TIMERH,
|
||||
RT5025_REG_TIMERL,
|
||||
RT5025_REG_CHANNELH,
|
||||
RT5025_REG_CHANNELL,
|
||||
RT5025_REG_INACVLTH,
|
||||
RT5025_REG_INACVLTL,
|
||||
RT5025_REG_INUSBVLTH,
|
||||
RT5025_REG_INUSBVLTL,
|
||||
RT5025_REG_VSYSVLTH,
|
||||
RT5025_REG_VSYSVLTL,
|
||||
RT5025_REG_GPIO0VLTH,
|
||||
RT5025_REG_GPIO0VLTL,
|
||||
RT5025_REG_GPIO1VLTH,
|
||||
RT5025_REG_GPIO1VLTL,
|
||||
RT5025_REG_GPIO2VLTH,
|
||||
RT5025_REG_GPIO2VLTL,
|
||||
RT5025_REG_DCDC1VLTH,
|
||||
RT5025_REG_DCDC1VLTL,
|
||||
RT5025_REG_DCDC2VLTH,
|
||||
RT5025_REG_DCDC2VLTL,
|
||||
RT5025_REG_DCDC3VLTH,
|
||||
RT5025_REG_DCDC3VLTL,
|
||||
RT5025_REG_CURRH,
|
||||
RT5025_REG_CURRL,
|
||||
RT5025_REG_QCHGHH,
|
||||
RT5025_REG_QCHGHL,
|
||||
RT5025_REG_QCHGLH,
|
||||
RT5025_REG_QCHGLL,
|
||||
RT5025_REG_QDCHGHH,
|
||||
RT5025_REG_QDCHGHL,
|
||||
RT5025_REG_QDCHGLH,
|
||||
RT5025_REG_QDCHGLL,
|
||||
RT5025_REG_RANGE3END = RT5025_REG_QDCHGLL,
|
||||
RT5025_REG_DCDC4OVP = 0xA9,
|
||||
RT5025_REG_RANGE4START = RT5025_REG_DCDC4OVP,
|
||||
RT5025_REG_RANGE4END = RT5025_REG_DCDC4OVP,
|
||||
RT5025_REG_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
@ -42,6 +153,7 @@ enum {
|
|||
RT5025_VOFF_3P3V,
|
||||
RT5025_VOFF_3P4V,
|
||||
RT5025_VOFF_3P5V,
|
||||
RT5025_VOFF_MAX = RT5025_VOFF_3P5V,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
@ -49,13 +161,7 @@ enum {
|
|||
RT5025_STARTIME_1S,
|
||||
RT5025_STARTIME_2S,
|
||||
RT5025_STARTIME_3S,
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5025_LPRESS_1S,
|
||||
RT5025_LPRESS_1P5S,
|
||||
RT5025_LPRESS_2S,
|
||||
RT5025_LPRESS_2P5S,
|
||||
RT5025_STARTIME_MAX = RT5025_STARTIME_3S,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
@ -63,68 +169,21 @@ enum {
|
|||
RT5025_SHDNPRESS_6S,
|
||||
RT5025_SHDNPRESS_8S,
|
||||
RT5025_SHDNPRESS_10S,
|
||||
RT5025_SHDNPRESS_MAX = RT5025_SHDNPRESS_10S,
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5025_PGDLY_10MS,
|
||||
RT5025_PGDLY_50MS,
|
||||
RT5025_PGDLY_100MS,
|
||||
RT5025_PGDLY_200MS,
|
||||
RT5025_VDPM_4V,
|
||||
RT5025_VDPM_4P25V,
|
||||
RT5025_VDPM_4P5V,
|
||||
RT5025_VDPM_DIS,
|
||||
RT5025_VDPM_MAX = RT5025_VDPM_DIS,
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5025_SHDNDLY_100MS,
|
||||
RT5025_SHDNDLY_500MS,
|
||||
RT5025_SHDNDLY_1S,
|
||||
RT5025_SHDNDLY_2S,
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5025_CCCHG_TO_4H,
|
||||
RT5025_CCCHG_TO_6H,
|
||||
RT5025_CCCHG_TO_8H,
|
||||
RT5025_CCCHG_TO_10H,
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5025_PRECHG_TO_30M,
|
||||
RT5025_PRECHG_TO_40M,
|
||||
RT5025_PRECHG_TO_50M,
|
||||
RT5025_PRECHG_TO_60M,
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5025_ICC_0P5A,
|
||||
RT5025_ICC_0P6A,
|
||||
RT5025_ICC_0P7A,
|
||||
RT5025_ICC_0P8A,
|
||||
RT5025_ICC_0P9A,
|
||||
RT5025_ICC_1A,
|
||||
RT5025_ICC_1P1A,
|
||||
RT5025_ICC_1P2A,
|
||||
RT5025_ICC_1P3A,
|
||||
RT5025_ICC_1P4A,
|
||||
RT5025_ICC_1P5A,
|
||||
RT5025_ICC_1P6A,
|
||||
RT5025_ICC_1P7A,
|
||||
RT5025_ICC_1P8A,
|
||||
RT5025_ICC_1P9A,
|
||||
RT5025_ICC_2A,
|
||||
RT5025_ICC_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5025_AICR_100MA,
|
||||
RT5025_AICR_500MA,
|
||||
RT5025_AICR_1A,
|
||||
RT5025_AICR_NOLIMIT,
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5025_DPM_4V,
|
||||
RT5025_DPM_4P25V,
|
||||
RT5025_DPM_4P5V,
|
||||
RT5025_DPM_DIS,
|
||||
RT5025_IEOC_10P,
|
||||
RT5025_IEOC_20P,
|
||||
RT5025_IEOC_MAX = RT5025_IEOC_20P,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
@ -134,18 +193,13 @@ enum {
|
|||
RT5025_VPREC_2P6V,
|
||||
RT5025_VPREC_2P8V,
|
||||
RT5025_VPREC_3V,
|
||||
RT5025_VPREC_3V_1,
|
||||
RT5025_VPREC_3V_2,
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5025_IEOC_10P,
|
||||
RT5025_IEOC_20P,
|
||||
RT5025_VPREC_MAX = RT5025_VPREC_3V,
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5025_IPREC_10P,
|
||||
RT5025_IPREC_20P,
|
||||
RT5025_IPREC_MAX = RT5025_IPREC_20P,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
@ -162,306 +216,58 @@ enum {
|
|||
RT5025_MAX_REGULATOR,
|
||||
};
|
||||
|
||||
struct rt5025_power_data {
|
||||
union {
|
||||
struct {
|
||||
unsigned char Resv1:1;
|
||||
unsigned char CHGBC_EN:1;
|
||||
unsigned char TE:1;
|
||||
unsigned char Resv2:1;
|
||||
unsigned char CCCHG_TIMEOUT:2;
|
||||
unsigned char PRECHG_TIMEOUT:2;
|
||||
}bitfield;
|
||||
unsigned char val;
|
||||
}CHGControl2;
|
||||
union {
|
||||
struct {
|
||||
unsigned char Resv:2;
|
||||
unsigned char VOREG:6;
|
||||
}bitfield;
|
||||
unsigned char val;
|
||||
}CHGControl3;
|
||||
union {
|
||||
struct {
|
||||
unsigned char AICR_CON:1;
|
||||
unsigned char AICR:2;
|
||||
unsigned char ICC:4;
|
||||
unsigned char CHG_RST:1;
|
||||
}bitfield;
|
||||
unsigned char val;
|
||||
}CHGControl4;
|
||||
union {
|
||||
struct {
|
||||
unsigned char Resv1:4;
|
||||
unsigned char DPM:2;
|
||||
unsigned char Resv2:2;
|
||||
}bitfield;
|
||||
unsigned char val;
|
||||
}CHGControl5;
|
||||
union {
|
||||
struct {
|
||||
unsigned char IPREC:1;
|
||||
unsigned char IEOC:1;
|
||||
unsigned char VPREC:3;
|
||||
unsigned char Resv:3;
|
||||
}bitfield;
|
||||
unsigned char val;
|
||||
}CHGControl6;
|
||||
union {
|
||||
struct {
|
||||
unsigned char Resv1:4;
|
||||
unsigned char CHGC_EN:1;
|
||||
unsigned char CHG_DCDC_MODE:1;
|
||||
unsigned char BATD_EN:1;
|
||||
unsigned char Resv2:1;
|
||||
}bitfield;
|
||||
unsigned char val;
|
||||
}CHGControl7;
|
||||
typedef void (*rt_irq_handler)(void *info, int eventno);
|
||||
|
||||
#define RT5025_DCDCRAMP_MAX 0x03
|
||||
struct rt5025_regulator_ramp {
|
||||
unsigned char ramp_sel:2;
|
||||
};
|
||||
|
||||
struct rt5025_gpio_data {
|
||||
unsigned gpio_base;
|
||||
unsigned irq_base;
|
||||
};
|
||||
|
||||
struct rt5025_misc_data {
|
||||
union {
|
||||
struct {
|
||||
unsigned char Action:2;
|
||||
unsigned char Delayed1:2;
|
||||
unsigned char Delayed2:2;
|
||||
unsigned char Resv:2;
|
||||
}bitfield;
|
||||
unsigned char val;
|
||||
}RSTCtrl;
|
||||
union {
|
||||
struct {
|
||||
unsigned char Resv:5;
|
||||
unsigned char VOFF:3;
|
||||
}bitfield;
|
||||
unsigned char val;
|
||||
}VSYSCtrl;
|
||||
union {
|
||||
struct {
|
||||
unsigned char PG_DLY:2;
|
||||
unsigned char SHDN_PRESS:2;
|
||||
unsigned char LPRESS_TIME:2;
|
||||
unsigned char START_TIME:2;
|
||||
}bitfield;
|
||||
unsigned char val;
|
||||
}PwrOnCfg;
|
||||
union {
|
||||
struct {
|
||||
unsigned char Resv:4;
|
||||
unsigned char SHDN_DLYTIME:2;
|
||||
unsigned char SHDN_TIMING:1;
|
||||
unsigned char SHDN_CTRL:1;
|
||||
}bitfield;
|
||||
unsigned char val;
|
||||
}SHDNCtrl;
|
||||
union {
|
||||
struct {
|
||||
unsigned char Resv:2;
|
||||
unsigned char OT_ENSHDN:1;
|
||||
unsigned char PWRON_ENSHDN:1;
|
||||
unsigned char DCDC3LV_ENSHDN:1;
|
||||
unsigned char DCDC2LV_ENSHDN:1;
|
||||
unsigned char DCDC1LV_ENSHDN:1;
|
||||
unsigned char SYSLV_ENSHDN:1;
|
||||
}bitfield;
|
||||
unsigned char val;
|
||||
}PwrOffCond;
|
||||
};
|
||||
|
||||
struct rt5025_irq_data {
|
||||
union {
|
||||
struct {
|
||||
unsigned char BATABS:1;
|
||||
unsigned char Resv1:2;
|
||||
unsigned char INUSB_PLUGIN:1;
|
||||
unsigned char INUSBOVP:1;
|
||||
unsigned char Resv2:1;
|
||||
unsigned char INAC_PLUGIN:1;
|
||||
unsigned char INACOVP:1;
|
||||
}bitfield;
|
||||
unsigned char val;
|
||||
}irq_enable1;
|
||||
union {
|
||||
struct {
|
||||
unsigned char CHTERMI:1;
|
||||
unsigned char CHBATOVI:1;
|
||||
unsigned char CHGOODI_INUSB:1;
|
||||
unsigned char CHBADI_INUSB:1;
|
||||
unsigned char CHSLPI_INUSB:1;
|
||||
unsigned char CHGOODI_INAC:1;
|
||||
unsigned char CHBADI_INAC:1;
|
||||
unsigned char CHSLPI_INAC:1;
|
||||
}bitfield;
|
||||
unsigned char val;
|
||||
}irq_enable2;
|
||||
union {
|
||||
struct {
|
||||
unsigned char TIMEOUT_CC:1;
|
||||
unsigned char TIMEOUT_PC:1;
|
||||
unsigned char Resv:3;
|
||||
unsigned char CHVSREGI:1;
|
||||
unsigned char CHTREGI:1;
|
||||
unsigned char CHRCHGI:1;
|
||||
}bitfield;
|
||||
unsigned char val;
|
||||
}irq_enable3;
|
||||
union {
|
||||
struct {
|
||||
unsigned char SYSLV:1;
|
||||
unsigned char DCDC4LVHV:1;
|
||||
unsigned char PWRONLP:1;
|
||||
unsigned char PWRONSP:1;
|
||||
unsigned char DCDC3LV:1;
|
||||
unsigned char DCDC2LV:1;
|
||||
unsigned char DCDC1LV:1;
|
||||
unsigned char OT:1;
|
||||
}bitfield;
|
||||
unsigned char val;
|
||||
}irq_enable4;
|
||||
union {
|
||||
struct {
|
||||
unsigned char Resv:1;
|
||||
unsigned char GPIO0_IE:1;
|
||||
unsigned char GPIO1_IE:1;
|
||||
unsigned char GPIO2_IE:1;
|
||||
unsigned char RESETB:1;
|
||||
unsigned char PWRONF:1;
|
||||
unsigned char PWRONR:1;
|
||||
unsigned char KPSHDN:1;
|
||||
}bitfield;
|
||||
unsigned char val;
|
||||
}irq_enable5;
|
||||
};
|
||||
|
||||
enum {
|
||||
JEITA_NO_CHARGE,
|
||||
JEITA_NORMAL_USB,
|
||||
JEITA_USB_TA,
|
||||
JEITA_AC_ADAPTER,
|
||||
JEITA_CHARGER_MAX,
|
||||
};
|
||||
|
||||
struct rt5025_jeita_data {
|
||||
int* temp;
|
||||
u8* temp_scalar;
|
||||
int (*temp_cc)[5];
|
||||
int (*temp_cv)[5];
|
||||
};
|
||||
|
||||
#define CHG_EVENT_INACOVP (0x80<<16)
|
||||
#define CHG_EVENT_INAC_PLUGIN (0x40<<16)
|
||||
#define CHG_EVENT_INUSBOVP (0x10<<16)
|
||||
#define CHG_EVENT_INUSB_PLUGIN (0x08<<16)
|
||||
#define CHG_EVENT_BAT_ABS (0x01<<16)
|
||||
|
||||
#define CHG_EVENT_CHSLPI_INAC (0x80<<8)
|
||||
#define CHG_EVENT_CHBADI_INAC (0x40<<8)
|
||||
#define CHG_EVENT_CHGOODI_INAC (0x20<<8)
|
||||
#define CHG_EVENT_CHSLPI_INUSB (0x10<<8)
|
||||
#define CHG_EVENT_CHBADI_INUSB (0x08<<8)
|
||||
#define CHG_EVENT_CHGOODI_INUSB (0x04<<8)
|
||||
#define CHG_EVENT_CHBATOVI (0x02<<8)
|
||||
#define CHG_EVENT_CHTERMI (0x01<<8)
|
||||
|
||||
#define CHG_EVENT_CHRCHGI (0x80<<0)
|
||||
#define CHG_EVENT_CHTREGI (0x40<<0)
|
||||
#define CHG_EVENT_CHVSREGI (0x20<<0)
|
||||
#define CHG_EVENT_TIMEOUTPC (0x02<<0)
|
||||
#define CHG_EVENT_TIMEOUTCC (0x01<<0)
|
||||
|
||||
#define CHARGER_DETECT_MASK (CHG_EVENT_INAC_PLUGIN | CHG_EVENT_INUSB_PLUGIN | \
|
||||
CHG_EVENT_CHSLPI_INAC | CHG_EVENT_CHSLPI_INUSB | \
|
||||
CHG_EVENT_CHBADI_INAC | CHG_EVENT_CHBADI_INUSB | \
|
||||
CHG_EVENT_CHTERMI | CHG_EVENT_CHRCHGI)
|
||||
|
||||
|
||||
#define PWR_EVENT_OTIQ (0x80<<8)
|
||||
#define PWR_EVENT_DCDC1LV (0x40<<8)
|
||||
#define PWR_EVENT_DCDC2LV (0x20<<8)
|
||||
#define PWR_EVENT_DCDC3LV (0x10<<8)
|
||||
#define PWR_EVENT_PWRONSP (0x08<<8)
|
||||
#define PWR_EVENT_PWRONLP (0x04<<8)
|
||||
#define PWR_EVENT_DCDC4LVHV (0x02<<8)
|
||||
#define PWR_EVENT_SYSLV (0x01<<8)
|
||||
|
||||
#define PWR_EVENT_KPSHDN (0x80<<0)
|
||||
#define PWR_EVNET_PWRONR (0x40<<0)
|
||||
#define PWR_EVENT_PWRONF (0x20<<0)
|
||||
#define PWR_EVENT_RESETB (0x10<<0)
|
||||
#define PWR_EVENT_GPIO2IE (0x08<<0)
|
||||
#define PWR_EVENT_GPIO1IE (0x04<<0)
|
||||
#define PWR_EVENT_GPIO0IE (0x02<<0)
|
||||
|
||||
struct rt5025_event_callback {
|
||||
#if 1
|
||||
void (*charger_event_callback)(uint32_t detected);
|
||||
void (*power_event_callkback)(uint32_t detected);
|
||||
#else
|
||||
void (*over_temperature_callback)(uint8_t detected);
|
||||
void (*charging_complete_callback)(void);
|
||||
void (*over_voltage_callback)(uint8_t detected);
|
||||
void (*under_voltage_callback)(uint8_t detected);
|
||||
void (*charge_fault_callback)(uint8_t detected);
|
||||
void (*charge_warning_callback)(uint8_t detected);
|
||||
#endif
|
||||
};
|
||||
|
||||
struct rt5025_power_info {
|
||||
struct rt5025_charger_info {
|
||||
struct i2c_client *i2c;
|
||||
struct device *dev;
|
||||
struct rt5025_chip *chip;
|
||||
//struct rt5025_gauge_callbacks *event_callback;
|
||||
struct power_supply ac;
|
||||
struct power_supply usb;
|
||||
struct mutex var_lock;
|
||||
struct delayed_work usb_detect_work;
|
||||
int usb_cnt;
|
||||
int chg_term;
|
||||
int otg_en;
|
||||
unsigned ac_online:1;
|
||||
unsigned usb_online:1;
|
||||
unsigned chg_stat:3;
|
||||
};
|
||||
|
||||
struct rt5025_swjeita_info {
|
||||
struct i2c_client *i2c;
|
||||
struct rt5025_chip *chip;
|
||||
struct delayed_work thermal_reg_work;
|
||||
int *temp;
|
||||
u8 *temp_scalar;
|
||||
int (*temp_cc)[5];
|
||||
int (*temp_cv)[5];
|
||||
int dec_current;
|
||||
int cur_section;
|
||||
int cur_therm_region;
|
||||
int cur_cable;
|
||||
int cur_temp;
|
||||
int cur_inttemp;
|
||||
int init_once;
|
||||
int suspend;
|
||||
struct power_supply psy;
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
struct early_suspend early_suspend;
|
||||
#endif /* CONFIG_HAS_EARLYSUSPEND */
|
||||
struct delayed_work tempmon_work;
|
||||
int temp[4];
|
||||
u32 temp_scalar[8];
|
||||
unsigned int te_en:1;
|
||||
unsigned int online:1;
|
||||
unsigned int batabs:1;
|
||||
unsigned int battemp_region:3;
|
||||
unsigned int inttemp_region:2;
|
||||
unsigned int otg_en:1;
|
||||
unsigned int init_once:1;
|
||||
unsigned int suspend:1;
|
||||
unsigned int screenon_adjust:1;
|
||||
unsigned int screen_on:1;
|
||||
int chg_status;
|
||||
int charger_cable;
|
||||
int chg_volt;
|
||||
int acchg_icc;
|
||||
int usbtachg_icc;
|
||||
int usbchg_icc;
|
||||
int screenon_icc;
|
||||
};
|
||||
|
||||
struct rt5025_battery_info {
|
||||
struct i2c_client *client;
|
||||
struct rt5025_chip *chip;
|
||||
//struct rt5025_gauge_callbacks cb;
|
||||
|
||||
struct power_supply battery;
|
||||
|
||||
struct delayed_work monitor_work;
|
||||
struct wake_lock monitor_wake_lock;
|
||||
struct wake_lock low_battery_wake_lock;
|
||||
struct wake_lock status_wake_lock;
|
||||
//#if RT5025_TEST_WAKE_LOCK
|
||||
struct wake_lock test_wake_lock;
|
||||
//#endif
|
||||
struct wake_lock smooth0_wake_lock;
|
||||
struct wake_lock smooth100_wake_lock;
|
||||
struct wake_lock full_battery_wake_lock;
|
||||
/*#if RT5025_TEST_WAKE_LOCK
|
||||
// struct wake_lock test_wake_lock;
|
||||
//#endif*/
|
||||
struct mutex status_change_lock;
|
||||
struct alarm wakeup_alarm;
|
||||
|
||||
|
||||
bool temp_range_0_5;
|
||||
bool temp_range_5_10;
|
||||
bool temp_range_10_15;
|
||||
|
|
@ -471,7 +277,7 @@ struct rt5025_battery_info {
|
|||
bool temp_range_35_40;
|
||||
bool temp_range_40_45;
|
||||
bool temp_range_45_50;
|
||||
|
||||
|
||||
bool range_0_5_done;
|
||||
bool range_5_10_done;
|
||||
bool range_10_15_done;
|
||||
|
|
@ -481,159 +287,183 @@ struct rt5025_battery_info {
|
|||
bool range_35_40_done;
|
||||
bool range_40_45_done;
|
||||
bool range_45_50_done;
|
||||
|
||||
|
||||
|
||||
|
||||
bool suspend_poll;
|
||||
ktime_t last_poll;
|
||||
// ktime_t last_event;
|
||||
struct timespec last_event;
|
||||
/* ktime_t last_event;*/
|
||||
struct timespec last_event;
|
||||
|
||||
u16 update_time;
|
||||
|
||||
/* previous battery voltage */
|
||||
u16 pre_vcell;
|
||||
/* previous battery current */
|
||||
s16 pre_curr;
|
||||
/* battery voltage */
|
||||
u16 vcell;
|
||||
/* battery current */
|
||||
s16 curr;
|
||||
/* battery current offset */
|
||||
u16 curr_offset;
|
||||
/* AIN voltage */
|
||||
u16 ain_volt;
|
||||
/* battery internal temperature */
|
||||
s16 int_temp;
|
||||
/* battery external temperature */
|
||||
s16 ext_temp;
|
||||
/* charge coulomb counter */
|
||||
u32 chg_cc;
|
||||
u32 chg_cc_unuse;
|
||||
/* discharge coulomb counter */
|
||||
u32 dchg_cc;
|
||||
u32 dchg_cc_unuse;
|
||||
/* battery capacity */
|
||||
u16 soc;
|
||||
u16 temp_soc;
|
||||
u16 pre_soc;
|
||||
|
||||
u16 time_interval;
|
||||
u16 pre_gauge_timer;
|
||||
|
||||
u8 online;
|
||||
u8 status;
|
||||
u8 internal_status;
|
||||
u8 health;
|
||||
u8 present;
|
||||
u16 update_time;
|
||||
|
||||
/* IRQ flag */
|
||||
u8 irq_flag;
|
||||
|
||||
/* max voltage IRQ flag */
|
||||
bool max_volt_irq;
|
||||
/* min voltage1 IRQ flag */
|
||||
bool min_volt1_irq;
|
||||
/* min voltage2 IRQ flag */
|
||||
bool min_volt2_irq;
|
||||
/* max temperature IRQ flag */
|
||||
bool max_temp_irq;
|
||||
/* min temperature IRQ flag */
|
||||
bool min_temp_irq;
|
||||
/* previous battery voltage */
|
||||
u16 pre_vcell;
|
||||
/* previous battery current */
|
||||
s16 pre_curr;
|
||||
/* battery voltage */
|
||||
u16 vcell;
|
||||
/* battery current */
|
||||
s16 curr;
|
||||
/* battery current offset */
|
||||
u16 curr_offset;
|
||||
/* AIN voltage */
|
||||
u16 ain_volt;
|
||||
/* battery internal temperature */
|
||||
s16 int_temp;
|
||||
/* battery external temperature */
|
||||
s16 ext_temp;
|
||||
/* charge coulomb counter */
|
||||
u32 chg_cc;
|
||||
u32 chg_cc_unuse;
|
||||
/* discharge coulomb counter */
|
||||
u32 dchg_cc;
|
||||
u32 dchg_cc_unuse;
|
||||
/* battery capacity */
|
||||
u16 soc;
|
||||
u16 temp_soc;
|
||||
u16 pre_soc;
|
||||
|
||||
bool min_volt2_alert;
|
||||
u16 time_interval;
|
||||
u16 pre_gauge_timer;
|
||||
|
||||
u8 online;
|
||||
u8 status;
|
||||
u8 internal_status;
|
||||
u8 health;
|
||||
u8 present;
|
||||
u8 batt_present;
|
||||
|
||||
/* IRQ flag */
|
||||
u8 irq_flag;
|
||||
|
||||
/* max voltage IRQ flag */
|
||||
bool max_volt_irq;
|
||||
/* min voltage1 IRQ flag */
|
||||
bool min_volt1_irq;
|
||||
/* min voltage2 IRQ flag */
|
||||
bool min_volt2_irq;
|
||||
/* max temperature IRQ flag */
|
||||
bool max_temp_irq;
|
||||
/* min temperature IRQ flag */
|
||||
bool min_temp_irq;
|
||||
|
||||
bool min_volt2_alert;
|
||||
|
||||
u8 temp_high_cnt;
|
||||
u8 temp_low_cnt;
|
||||
u8 temp_recover_cnt;
|
||||
|
||||
|
||||
bool init_cap;
|
||||
bool avg_flag;
|
||||
|
||||
/* remain capacity */
|
||||
u32 rm;
|
||||
/* SOC permille */
|
||||
u16 permille;
|
||||
/* full capccity */
|
||||
u16 fcc_aging;
|
||||
u16 fcc;
|
||||
u16 dc;
|
||||
s16 tempcmp;
|
||||
#if 0
|
||||
u32 time_to_empty;
|
||||
u32 time_to_full;
|
||||
#endif
|
||||
|
||||
bool edv_flag;
|
||||
bool edv_detection;
|
||||
u8 edv_cnt;
|
||||
|
||||
bool tp_flag;
|
||||
u8 tp_cnt;
|
||||
|
||||
u8 cycle_cnt;
|
||||
u32 acc_dchg_cap;
|
||||
|
||||
bool smooth_flag;
|
||||
|
||||
u16 gauge_timer;
|
||||
s16 curr_raw;
|
||||
u32 empty_edv;
|
||||
u8 edv_region;
|
||||
/* remain capacity */
|
||||
u32 rm;
|
||||
/* SOC permille */
|
||||
u16 permille;
|
||||
/* full capccity */
|
||||
u16 fcc_aging;
|
||||
u16 fcc;
|
||||
u16 dc;
|
||||
s16 tempcmp;
|
||||
|
||||
bool init_once;
|
||||
bool device_suspend;
|
||||
bool last_suspend;
|
||||
bool last_tp_flag;
|
||||
u32 cal_fcc;
|
||||
u8 test_temp;
|
||||
bool edv_flag;
|
||||
bool edv_detection;
|
||||
u8 edv_cnt;
|
||||
|
||||
bool tp_flag;
|
||||
u8 tp_cnt;
|
||||
|
||||
u8 cycle_cnt;
|
||||
u32 acc_dchg_cap;
|
||||
|
||||
bool smooth_flag;
|
||||
|
||||
u16 gauge_timer;
|
||||
s16 curr_raw;
|
||||
u32 empty_edv;
|
||||
u8 edv_region;
|
||||
u32 soc1_lock_cnt;
|
||||
u32 soc99_lock_cnt;
|
||||
|
||||
bool init_once;
|
||||
bool device_suspend;
|
||||
bool last_suspend;
|
||||
bool last_tp_flag;
|
||||
bool fcc_update_flag;
|
||||
u32 cal_fcc;
|
||||
u8 test_temp;
|
||||
u8 last_tp;
|
||||
u32 cal_eoc_fcc;
|
||||
u32 cal_soc_offset;
|
||||
};
|
||||
|
||||
|
||||
struct rt5025_charger_data {
|
||||
int *temp;
|
||||
u32 *temp_scalar;
|
||||
int chg_volt;
|
||||
int acchg_icc;
|
||||
int usbtachg_icc;
|
||||
int usbchg_icc;
|
||||
int screenon_icc;
|
||||
unsigned int ieoc:1;
|
||||
unsigned int vdpm:2;
|
||||
unsigned int te_en:1;
|
||||
unsigned int vprec:3;
|
||||
unsigned int iprec:1;
|
||||
unsigned int screenon_adjust:1;
|
||||
};
|
||||
|
||||
struct rt5025_gpio_data {
|
||||
int ngpio;
|
||||
};
|
||||
|
||||
struct rt5025_misc_data {
|
||||
unsigned char vsyslv:3;
|
||||
unsigned char shdnlpress_time:2;
|
||||
unsigned char startlpress_time:2;
|
||||
unsigned char vsyslv_enshdn:1;
|
||||
};
|
||||
|
||||
struct rt5025_irq_data {
|
||||
int irq_gpio;
|
||||
};
|
||||
|
||||
struct rt5025_chip;
|
||||
struct rt5025_platform_data {
|
||||
struct regulator_init_data *regulator[RT5025_MAX_REGULATOR];
|
||||
struct rt5025_charger_data *chg_pdata;
|
||||
struct rt5025_gpio_data *gpio_pdata;
|
||||
struct rt5025_misc_data *misc_pdata;
|
||||
struct rt5025_irq_data *irq_pdata;
|
||||
int (*pre_init)(struct rt5025_chip *rt5025_chip);
|
||||
/** Called after subdevices are set up */
|
||||
int (*post_init)(void);
|
||||
};
|
||||
|
||||
struct rt5025_misc_info {
|
||||
struct i2c_client *i2c;
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
struct rt5025_chip {
|
||||
struct i2c_client *i2c;
|
||||
struct workqueue_struct *wq;
|
||||
struct device *dev;
|
||||
struct rt5025_power_info *power_info;
|
||||
struct rt5025_swjeita_info *jeita_info;
|
||||
struct rt5025_charger_info *charger_info;
|
||||
struct rt5025_battery_info *battery_info;
|
||||
int suspend;
|
||||
int irq;
|
||||
struct delayed_work delayed_work;
|
||||
struct rt5025_misc_info *misc_info;
|
||||
struct mutex io_lock;
|
||||
int suspend;
|
||||
};
|
||||
|
||||
struct rt5025_platform_data {
|
||||
struct regulator_init_data* regulator[RT5025_MAX_REGULATOR];
|
||||
struct rt5025_power_data* power_data;
|
||||
struct rt5025_gpio_data* gpio_data;
|
||||
struct rt5025_misc_data* misc_data;
|
||||
struct rt5025_irq_data* irq_data;
|
||||
struct rt5025_jeita_data* jeita_data;
|
||||
struct rt5025_event_callback *cb;
|
||||
int (*pre_init)(struct rt5025_chip *rt5025_chip);
|
||||
/** Called after subdevices are set up */
|
||||
int (*post_init)(void);
|
||||
int (*set_otg_enable)(int);
|
||||
int intr_pin;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MFD_RT5025_MISC
|
||||
extern void rt5025_power_off(void);
|
||||
extern int rt5025_cable_exist(void);
|
||||
#endif /* CONFIG_MFD_RT5025_MISC */
|
||||
|
||||
#ifdef CONFIG_POWER_RT5025
|
||||
extern int rt5025_charger_reset_and_reinit(struct rt5025_power_info *);
|
||||
extern int rt5025_ext_set_charging_buck(int);
|
||||
extern int rt5025_set_charging_buck(struct i2c_client *, int);
|
||||
extern int rt5025_set_charging_current_switch(struct i2c_client *, int);
|
||||
extern void rt5025_gauge_set_status(struct rt5025_battery_info *, int);
|
||||
extern void rt5025_gauge_set_online(struct rt5025_battery_info *, bool);
|
||||
extern void rt5025_gauge_irq_handler(struct rt5025_battery_info *, u8);
|
||||
extern int rt5025_power_charge_detect(struct rt5025_power_info *);
|
||||
extern int rt5025_notify_charging_cable(struct rt5025_swjeita_info *, int);
|
||||
extern int rt5025_swjeita_irq_handler(struct rt5025_swjeita_info *, unsigned char);
|
||||
#endif /* CONFIG_POEWR_RT5025 */
|
||||
#ifdef CONFIG_CHARGER_RT5025
|
||||
void rt5025_charger_irq_handler(struct rt5025_charger_info *ci, unsigned int event);
|
||||
#endif /* #ifdef CONFIG_CHARGER_RT5025 */
|
||||
#ifdef CONFIG_MISC_RT5025
|
||||
void rt5025_misc_irq_handler(struct rt5025_misc_info *mi, unsigned int event);
|
||||
#endif /* #ifdef CONFIG_MISC_RT5025 */
|
||||
#ifdef CONFIG_BATTERY_RT5025
|
||||
void rt5025_gauge_irq_handler(struct rt5025_battery_info *bi, unsigned int event);
|
||||
#endif /* #ifdef CONFIG_BATTERY_RT5025 */
|
||||
|
||||
extern int rt5025_reg_block_read(struct i2c_client *, int, int, void *);
|
||||
extern int rt5025_reg_block_write(struct i2c_client *, int, int, void *);
|
||||
|
|
@ -648,9 +478,9 @@ extern int rt5025_core_deinit(struct rt5025_chip *);
|
|||
|
||||
#ifdef CONFIG_MFD_RT_SHOW_INFO
|
||||
#define RTINFO(format, args...) \
|
||||
printk(KERN_INFO "%s:%s() line-%d: " format, RT5025_DEVICE_NAME,__FUNCTION__,__LINE__, ##args)
|
||||
printk(KERN_INFO "%s:%s() line-%d: " format, RT5025_DEV_NAME, __FUNCTION__, __LINE__, ##args)
|
||||
#else
|
||||
#define RTINFO(format,args...)
|
||||
#define RTINFO(format, args...)
|
||||
#endif /* CONFIG_MFD_RT_SHOW_INFO */
|
||||
|
||||
#endif /* __LINUX_MFD_RT5025_H */
|
||||
|
|
|
|||
|
|
@ -1,26 +1,24 @@
|
|||
battery_graph_prop rt5025_battery_param1[] =
|
||||
{
|
||||
battery_graph_prop rt5025_battery_param1[] = {
|
||||
{4190, 1000},
|
||||
{4120, 980},
|
||||
{4037, 890},
|
||||
{3970, 800},
|
||||
{3914, 710},
|
||||
{3835, 580},
|
||||
{3796, 490},
|
||||
{3773, 400},
|
||||
{3736, 240},
|
||||
{3697, 140},
|
||||
{3665, 70},
|
||||
{3651, 50},
|
||||
{3545, 20},
|
||||
{3400, 0},
|
||||
{4153, 980},
|
||||
{4067, 890},
|
||||
{3991, 800},
|
||||
{3931, 710},
|
||||
{3845, 580},
|
||||
{3799, 490},
|
||||
{3776, 400},
|
||||
{3743, 240},
|
||||
{3695, 140},
|
||||
{3660, 70},
|
||||
{3642, 50},
|
||||
{3509, 20},
|
||||
{3300, 0},
|
||||
};
|
||||
|
||||
battery_graph_prop rt5025_battery_param2[] =
|
||||
{
|
||||
{450,14},
|
||||
battery_graph_prop rt5025_battery_param2[] = {
|
||||
{450, 30},
|
||||
{250, 0},
|
||||
{50,-78},
|
||||
{50, 10},
|
||||
{3400, 3671},
|
||||
{50, -90},
|
||||
{50, 10},
|
||||
{3400, 6900},
|
||||
};
|
||||
|
|
|
|||
27
include/linux/power/rt-power.h
Executable file
27
include/linux/power/rt-power.h
Executable file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* include/linux/power/rt5025/rt-power.h
|
||||
* Include header file for Richtek RT5025 Core charger Driver
|
||||
*
|
||||
* Copyright (C) 2014 Richtek Technology Corp.
|
||||
* cy_huang <cy_huang@richtek.com>
|
||||
*
|
||||
* 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; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_RT_POWER_H
|
||||
#define __LINUX_RT_POWER_H
|
||||
|
||||
#define RT_AC_NAME "rt-ac"
|
||||
#define RT_USB_NAME "rt-usb"
|
||||
|
||||
struct rt_power_data {
|
||||
int chg_volt;
|
||||
int acchg_icc;
|
||||
int usbtachg_icc;
|
||||
int usbchg_icc;
|
||||
};
|
||||
#endif /* #ifndef __LINUX_RT_POWER_H */
|
||||
|
||||
123
include/linux/power/rt5025-battery.h
Normal file → Executable file
123
include/linux/power/rt5025-battery.h
Normal file → Executable file
|
|
@ -1,13 +1,14 @@
|
|||
/*
|
||||
* include/linux/power/rt5025-battery.h
|
||||
* include/linux/power/rt5025/rt5025-battery.h
|
||||
* Include header file for Richtek RT5025 battery Driver
|
||||
*
|
||||
* Copyright (C) 2013 Richtek Electronics
|
||||
* Copyright (C) 2013 Richtek Technology Corp.
|
||||
* cy_huang <cy_huang@richtek.com>
|
||||
*
|
||||
* 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.
|
||||
* published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_RT5025_BATTERY_H
|
||||
|
|
@ -16,38 +17,38 @@
|
|||
#undef ROCKCHIP_BATTERY_6900MAH
|
||||
#undef ROCKCHIP_BATTERY_4000MAH
|
||||
|
||||
#define RT5025_REG_IRQ_CTL 0x50
|
||||
#define RT5025_REG_IRQ_FLAG 0x51
|
||||
#define RT5025_REG_VALRT_MAXTH 0x53
|
||||
#define RT5025_REG_VALRT_MIN1TH 0x54
|
||||
#define RT5025_REG_VALRT_MIN2TH 0x55
|
||||
#define RT5025_REG_TALRT_MAXTH 0x56
|
||||
#define RT5025_REG_TALRT_MINTH 0x57
|
||||
#define RT5025_REG_VCELL_MSB 0x58
|
||||
#define RT5025_REG_VCELL_LSB 0x59
|
||||
#define RT5025_REG_INT_TEMPERATUE_MSB 0x5A
|
||||
#define RT5025_REG_INT_TEMPERATUE_LSB 0x5B
|
||||
#define RT5025_REG_EXT_TEMPERATUE_MSB 0x5E
|
||||
#define RT5025_REG_EXT_TEMPERATUE_LSB 0x5F
|
||||
#define RT5025_REG_TIMER 0x60
|
||||
#define RT5025_REG_CHANNEL_MSB 0x62
|
||||
#define RT5025_REG_CHANNEL_LSB 0x63
|
||||
#define RT5025_REG_CURRENT_MSB 0x76
|
||||
#define RT5025_REG_CURRENT_LSB 0x77
|
||||
#define RT5025_REG_QCHGH_MSB 0x78
|
||||
#define RT5025_REG_QCHGH_LSB 0x79
|
||||
#define RT5025_REG_QCHGL_MSB 0x7A
|
||||
#define RT5025_REG_QCHGL_LSB 0x7B
|
||||
#define RT5025_REG_QDCHGH_MSB 0x7C
|
||||
#define RT5025_REG_QDCHGH_LSB 0x7D
|
||||
#define RT5025_REG_QDCHGL_MSB 0x7E
|
||||
#define RT5025_REG_QDCHGL_LSB 0x7F
|
||||
#define RT5025_REG_IRQ_CTL 0x50
|
||||
#define RT5025_REG_IRQ_FLAG 0x51
|
||||
#define RT5025_REG_VALRT_MAXTH 0x53
|
||||
#define RT5025_REG_VALRT_MIN1TH 0x54
|
||||
#define RT5025_REG_VALRT_MIN2TH 0x55
|
||||
#define RT5025_REG_TALRT_MAXTH 0x56
|
||||
#define RT5025_REG_TALRT_MINTH 0x57
|
||||
#define RT5025_REG_VCELL_MSB 0x58
|
||||
#define RT5025_REG_VCELL_LSB 0x59
|
||||
#define RT5025_REG_INT_TEMPERATUE_MSB 0x5A
|
||||
#define RT5025_REG_INT_TEMPERATUE_LSB 0x5B
|
||||
#define RT5025_REG_EXT_TEMPERATUE_MSB 0x5E
|
||||
#define RT5025_REG_EXT_TEMPERATUE_LSB 0x5F
|
||||
#define RT5025_REG_TIMER 0x60
|
||||
#define RT5025_REG_CHANNEL_MSB 0x62
|
||||
#define RT5025_REG_CHANNEL_LSB 0x63
|
||||
#define RT5025_REG_CURRENT_MSB 0x76
|
||||
#define RT5025_REG_CURRENT_LSB 0x77
|
||||
#define RT5025_REG_QCHGH_MSB 0x78
|
||||
#define RT5025_REG_QCHGH_LSB 0x79
|
||||
#define RT5025_REG_QCHGL_MSB 0x7A
|
||||
#define RT5025_REG_QCHGL_LSB 0x7B
|
||||
#define RT5025_REG_QDCHGH_MSB 0x7C
|
||||
#define RT5025_REG_QDCHGH_LSB 0x7D
|
||||
#define RT5025_REG_QDCHGL_MSB 0x7E
|
||||
#define RT5025_REG_QDCHGL_LSB 0x7F
|
||||
|
||||
#define IRQ_CTL_BIT_TMX (1 << 5)
|
||||
#define IRQ_CTL_BIT_TMN (1 << 4)
|
||||
#define IRQ_CTL_BIT_VMX (1 << 2)
|
||||
#define IRQ_CTL_BIT_VMN1 (1 << 1)
|
||||
#define IRQ_CTL_BIT_VMN2 (1 << 0)
|
||||
#define IRQ_CTL_BIT_TMX (1 << 5)
|
||||
#define IRQ_CTL_BIT_TMN (1 << 4)
|
||||
#define IRQ_CTL_BIT_VMX (1 << 2)
|
||||
#define IRQ_CTL_BIT_VMN1 (1 << 1)
|
||||
#define IRQ_CTL_BIT_VMN2 (1 << 0)
|
||||
|
||||
#define IRQ_FLG_BIT_TMX (1 << 5)
|
||||
#define IRQ_FLG_BIT_TMN (1 << 4)
|
||||
|
|
@ -81,61 +82,25 @@
|
|||
#define EDV_HYS 100
|
||||
#define IRQ_THRES_UNIT 1953
|
||||
|
||||
#define TALRTMAX_VALUE 0x38 //65.39'C
|
||||
#define TALRTMIN_VALUE 0x9 //-18.75'C
|
||||
#define TRLS_VALUE 55 //5'C ; unit:mV
|
||||
#define VRLS_VALUE 100 //100mV
|
||||
#define TALRTMAX_VALUE 0x38 /*65.39'C*/
|
||||
#define TALRTMIN_VALUE 0x9 /*-18.75'C*/
|
||||
#define TRLS_VALUE 55 /*5'C ; unit:mV*/
|
||||
#define VRLS_VALUE 100 /*100mV*/
|
||||
|
||||
|
||||
#define DEADBAND 10
|
||||
|
||||
//#define SLEEP_CURRENT 3 //mA
|
||||
|
||||
u16 crctab16[256] =
|
||||
{
|
||||
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
|
||||
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
|
||||
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
|
||||
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
|
||||
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
|
||||
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
|
||||
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
|
||||
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
|
||||
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
|
||||
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
|
||||
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
|
||||
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
|
||||
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
|
||||
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
|
||||
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
|
||||
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
|
||||
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
|
||||
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
|
||||
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
|
||||
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
|
||||
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
|
||||
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
|
||||
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
|
||||
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
|
||||
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
|
||||
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
|
||||
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
|
||||
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
|
||||
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
|
||||
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
|
||||
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
|
||||
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78,
|
||||
};
|
||||
/*#define SLEEP_CURRENT 3 //mA*/
|
||||
|
||||
typedef enum{
|
||||
CHG,
|
||||
DCHG
|
||||
}operation_mode;
|
||||
} operation_mode;
|
||||
|
||||
typedef struct{
|
||||
int x;
|
||||
int y;
|
||||
}battery_graph_prop;
|
||||
} battery_graph_prop;
|
||||
|
||||
typedef enum {
|
||||
MAXTEMP,
|
||||
|
|
@ -146,7 +111,7 @@ typedef enum {
|
|||
TEMP_RLS,
|
||||
VOLT_RLS,
|
||||
LAST_TYPE,
|
||||
}alert_type;
|
||||
} alert_type;
|
||||
|
||||
#if defined(ROCKCHIP_BATTERY_6900MAH)
|
||||
#include <linux/power/rockchip-6900ma-bat.h>
|
||||
|
|
@ -156,6 +121,6 @@ typedef enum {
|
|||
#include <linux/power/rockchip-general-bat.h>
|
||||
#endif
|
||||
|
||||
#define VALRTMIN2_VALUE (rt5025_battery_param2[4].x * 100 / IRQ_THRES_UNIT + 1) //EDV0 voltage
|
||||
#define VALRTMIN2_VALUE (rt5025_battery_param2[4].x * 100 / IRQ_THRES_UNIT + 1) /*EDV0 voltage*/
|
||||
|
||||
#endif /* #ifndef __LINUX_RT5025_BATTERY_H */
|
||||
|
|
|
|||
86
include/linux/power/rt5025-charger.h
Executable file
86
include/linux/power/rt5025-charger.h
Executable file
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* include/linux/power/rt5025/rt5025-charger.h
|
||||
* Include header file for Richtek RT5025 Core charger Driver
|
||||
*
|
||||
* Copyright (C) 2014 Richtek Technology Corp.
|
||||
* cy_huang <cy_huang@richtek.com>
|
||||
*
|
||||
* 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; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_RT5025_CHARGER_H
|
||||
#define __LINUX_RT5025_CHARGER_H
|
||||
|
||||
enum {
|
||||
CHGEVENT_TIMEOUT_CC,
|
||||
CHGEVENT_TIMEOUT_PC,
|
||||
CHGEVENT_CHVSREGI = 5,
|
||||
CHGEVENT_CHTREGI,
|
||||
CHGEVENT_CHRCHGI,
|
||||
CHGEVENT_CHTERMI,
|
||||
CHGEVENT_CHBATOVI,
|
||||
CHGEVENT_CHGOODI_INUSB,
|
||||
CHGEVENT_CHBADI_INUSB,
|
||||
CHGEVENT_CHSLPI_INUSB,
|
||||
CHGEVENT_CHGOODI_INAC,
|
||||
CHGEVENT_CHBADI_INAC,
|
||||
CHGEVENT_CHSLPI_INAC,
|
||||
CHGEVENT_BATABS,
|
||||
CHGEVENT_INUSB_PLUGIN = 19,
|
||||
CHGEVENT_INUSBOVP,
|
||||
CHGEVENT_INAC_PLUGIN = 22,
|
||||
CHGEVENT_INACOVP,
|
||||
/*append TALRT IRQ*/
|
||||
CHGEVENT_TALRTMIN = 28,
|
||||
CHGEVENT_TALRTMAX = 29,
|
||||
CHGEVENT_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5025_BATTEMP_COLD,
|
||||
RT5025_BATTEMP_COOL,
|
||||
RT5025_BATTEMP_NORMAL,
|
||||
RT5025_BATTEMP_WARM,
|
||||
RT5025_BATTEMP_HOT,
|
||||
RT5025_BATTEMP_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5025_INTTEMP_NORMAL,
|
||||
RT5025_INTTEMP_WARM,
|
||||
RT5025_INTTEMP_HOT,
|
||||
RT5025_INTTEMP_MAX,
|
||||
};
|
||||
|
||||
#define RT5025_CHGIPREC_MASK 0x01
|
||||
#define RT5025_CHGIPREC_SHFT 0
|
||||
#define RT5025_CHGIEOC_MASK 0x02
|
||||
#define RT5025_CHGIEOC_SHFT 1
|
||||
#define RT5025_CHGVPREC_MASK 0x1C
|
||||
#define RT5025_CHGVPREC_SHFT 2
|
||||
#define RT5025_CHGVDPM_MASK 0x30
|
||||
#define RT5025_CHGVDPM_SHFT 4
|
||||
|
||||
#define RT5025_CHGCEN_MASK 0x10
|
||||
#define RT5025_CHGAICR_MASK 0x06
|
||||
#define RT5025_CHGAICR_SHFT 1
|
||||
#define RT5025_CHGICC_MASK 0x78
|
||||
#define RT5025_CHGICC_SHFT 3
|
||||
#define RT5025_CHGCV_MASK 0xFC
|
||||
#define RT5025_CHGCV_SHFT 2
|
||||
#define RT5025_CHGTEEN_MASK 0x04
|
||||
#define RT5025_BATDEN_MASK 0x40
|
||||
#define RT5025_VBUSHZ_MASK 0x01
|
||||
#define RT5025_CHGBCEN_MASK 0x02
|
||||
#define RT5025_CHRCHGI_MASK 0x80
|
||||
#define RT5025_CHTERMI_MASK 0x01
|
||||
#define RT5025_ACUSABLE_MASK 0x02
|
||||
#define RT5025_USBUSABLE_MASK 0x01
|
||||
|
||||
#define RT5025_TALRTMX_MASK 0x20
|
||||
#define RT5025_TALRTMN_MASK 0x10
|
||||
|
||||
#endif /* #ifndef __LINUX_RT5025_POWER_H */
|
||||
123
include/linux/regulator/rt5025-regulator.h
Normal file → Executable file
123
include/linux/regulator/rt5025-regulator.h
Normal file → Executable file
|
|
@ -2,88 +2,75 @@
|
|||
* include/linux/regulator/rt5025-regulator.h
|
||||
* Include header file to Richtek RT5025 Regulator driver
|
||||
*
|
||||
* Copyright (C) 2013 Richtek Electronics
|
||||
* Copyright (C) 2013 Richtek Technology Corp.
|
||||
* cy_huang <cy_huang@richtek.com>
|
||||
*
|
||||
* 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.
|
||||
* published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_RT5025_REGULATOR_H
|
||||
#define __LINUX_RT5025_REGULATOR_H
|
||||
|
||||
#define RT5025_REG_DCDCCTRL1 0x08
|
||||
#define RT5025_REG_DCDCCTRL2 0x09
|
||||
#define RT5025_REG_DCDCCTRL3 0x0A
|
||||
#define RT5025_REG_DCDCCTRL4 0x0B
|
||||
#define RT5025_REG_LDOCTRL1 0x0D
|
||||
#define RT5025_REG_LDOCTRL2 0x0E
|
||||
#define RT5025_REG_LDOCTRL3 0x0F
|
||||
#define RT5025_REG_LDOCTRL4 0x10
|
||||
#define RT5025_REG_LDOCTRL5 0x11
|
||||
#define RT5025_REG_LDOCTRL6 0x12
|
||||
#define RT5025_REG_DCDCEN 0x17
|
||||
#define RT5025_REG_LDOEN 0x18
|
||||
#define RT5025_REG_DCDCVRC 0x0B
|
||||
#define RT5025_REG_LDOVRC 0x00
|
||||
#define RT5025_DCDCVOUT1 RT5025_REG_DCDCCTL1
|
||||
#define RT5025_DCDCVOUT2 RT5025_REG_DCDCCTL2
|
||||
#define RT5025_DCDCVOUT3 RT5025_REG_DCDCCTL3
|
||||
#define RT5025_DCDCVOUT4 RT5025_REG_VRCCTL
|
||||
#define RT5025_LDOVOUT1 RT5025_REG_LDOCTL1
|
||||
#define RT5025_LDOVOUT2 RT5025_REG_LDOCTL2
|
||||
#define RT5025_LDOVOUT3 RT5025_REG_LDOCTL3
|
||||
#define RT5025_LDOVOUT4 RT5025_REG_LDOCTL4
|
||||
#define RT5025_LDOVOUT5 RT5025_REG_LDOCTL5
|
||||
#define RT5025_LDOVOUT6 RT5025_REG_LDOCTL6
|
||||
|
||||
#define RT5025_DCDCVOUT1 RT5025_REG_DCDCCTRL1
|
||||
#define RT5025_DCDCVOUT2 RT5025_REG_DCDCCTRL2
|
||||
#define RT5025_DCDCVOUT3 RT5025_REG_DCDCCTRL3
|
||||
#define RT5025_DCDCVOUT4 RT5025_REG_DCDCCTRL4
|
||||
#define RT5025_LDOVOUT1 RT5025_REG_LDOCTRL1
|
||||
#define RT5025_LDOVOUT2 RT5025_REG_LDOCTRL2
|
||||
#define RT5025_LDOVOUT3 RT5025_REG_LDOCTRL3
|
||||
#define RT5025_LDOVOUT4 RT5025_REG_LDOCTRL4
|
||||
#define RT5025_LDOVOUT5 RT5025_REG_LDOCTRL5
|
||||
#define RT5025_LDOVOUT6 RT5025_REG_LDOCTRL6
|
||||
#define RT5025_DCDCVOUT_SHIFT1 2
|
||||
#define RT5025_DCDCVOUT_SHIFT2 1
|
||||
#define RT5025_DCDCVOUT_SHIFT3 2
|
||||
#define RT5025_DCDCVOUT_SHIFT4 0
|
||||
#define RT5025_LDOVOUT_SHIFT1 0
|
||||
#define RT5025_LDOVOUT_SHIFT2 0
|
||||
#define RT5025_LDOVOUT_SHIFT3 3
|
||||
#define RT5025_LDOVOUT_SHIFT4 3
|
||||
#define RT5025_LDOVOUT_SHIFT5 3
|
||||
#define RT5025_LDOVOUT_SHIFT6 3
|
||||
|
||||
#define RT5025_DCDCVOUT_SHIFT1 2
|
||||
#define RT5025_DCDCVOUT_SHIFT2 1
|
||||
#define RT5025_DCDCVOUT_SHIFT3 2
|
||||
#define RT5025_DCDCVOUT_SHIFT4 0
|
||||
#define RT5025_LDOVOUT_SHIFT1 0
|
||||
#define RT5025_LDOVOUT_SHIFT2 0
|
||||
#define RT5025_LDOVOUT_SHIFT3 3
|
||||
#define RT5025_LDOVOUT_SHIFT4 3
|
||||
#define RT5025_LDOVOUT_SHIFT5 3
|
||||
#define RT5025_LDOVOUT_SHIFT6 3
|
||||
#define RT5025_DCDCVOUT_MASK1 0xFC
|
||||
#define RT5025_DCDCVOUT_MASK2 0xFE
|
||||
#define RT5025_DCDCVOUT_MASK3 0xFC
|
||||
#define RT5025_DCDCVOUT_MASK4 0x0F
|
||||
#define RT5025_LDOVOUT_MASK1 0x7F
|
||||
#define RT5025_LDOVOUT_MASK2 0x7F
|
||||
#define RT5025_LDOVOUT_MASK3 0xF8
|
||||
#define RT5025_LDOVOUT_MASK4 0xF8
|
||||
#define RT5025_LDOVOUT_MASK5 0xF8
|
||||
#define RT5025_LDOVOUT_MASK6 0xF8
|
||||
|
||||
#define RT5025_DCDCVOUT_MASK1 0xFC
|
||||
#define RT5025_DCDCVOUT_MASK2 0xFE
|
||||
#define RT5025_DCDCVOUT_MASK3 0xFC
|
||||
#define RT5025_DCDCVOUT_MASK4 0x0F
|
||||
#define RT5025_LDOVOUT_MASK1 0x7F
|
||||
#define RT5025_LDOVOUT_MASK2 0x7F
|
||||
#define RT5025_LDOVOUT_MASK3 0xF8
|
||||
#define RT5025_LDOVOUT_MASK4 0xF8
|
||||
#define RT5025_LDOVOUT_MASK5 0xF8
|
||||
#define RT5025_LDOVOUT_MASK6 0xF8
|
||||
#define RT5025_DCDCEN_MASK1 0x01
|
||||
#define RT5025_DCDCEN_MASK2 0x02
|
||||
#define RT5025_DCDCEN_MASK3 0x04
|
||||
#define RT5025_DCDCEN_MASK4 0x08
|
||||
#define RT5025_LDOEN_MASK1 0x01
|
||||
#define RT5025_LDOEN_MASK2 0x02
|
||||
#define RT5025_LDOEN_MASK3 0x04
|
||||
#define RT5025_LDOEN_MASK4 0x08
|
||||
#define RT5025_LDOEN_MASK5 0x10
|
||||
#define RT5025_LDOEN_MASK6 0x20
|
||||
|
||||
#define RT5025_DCDC_OUTPUT_EN RT5025_REG_DCDCEN
|
||||
#define RT5025_LDO_OUTPUT_EN RT5025_REG_LDOEN
|
||||
#define RT5025_DCDCMODE_REG1 RT5025_REG_VRCCTL
|
||||
#define RT5025_DCDCMODE_REG2 RT5025_REG_VRCCTL
|
||||
#define RT5025_DCDCMODE_REG3 RT5025_REG_VRCCTL
|
||||
#define RT5025_DCDCMODE_REG4 0
|
||||
|
||||
#define RT5025_DCDCEN_MASK1 0x01
|
||||
#define RT5025_DCDCEN_MASK2 0x02
|
||||
#define RT5025_DCDCEN_MASK3 0x04
|
||||
#define RT5025_DCDCEN_MASK4 0x08
|
||||
#define RT5025_LDOEN_MASK1 0x01
|
||||
#define RT5025_LDOEN_MASK2 0x02
|
||||
#define RT5025_LDOEN_MASK3 0x04
|
||||
#define RT5025_LDOEN_MASK4 0x08
|
||||
#define RT5025_LDOEN_MASK5 0x10
|
||||
#define RT5025_LDOEN_MASK6 0x20
|
||||
#define RT5025_DCDCMODE_MASK1 0x40
|
||||
#define RT5025_DCDCMODE_MASK2 0x20
|
||||
#define RT5025_DCDCMODE_MASK3 0x10
|
||||
#define RT5025_DCDCMODE_MASK4 0x00
|
||||
|
||||
#define RT5025_DCDCMODE_MASK1 0x40
|
||||
#define RT5025_DCDCMODE_MASK2 0x20
|
||||
#define RT5025_DCDCMODE_MASK3 0x10
|
||||
#define RT5025_DCDCMODE_MASK4 0x00
|
||||
#define RT5025_LDOMODE_MASK1 0x00
|
||||
#define RT5025_LDOMODE_MASK2 0x00
|
||||
#define RT5025_LDOMODE_MASK3 0x00
|
||||
#define RT5025_LDOMODE_MASK4 0x00
|
||||
#define RT5025_LDOMODE_MASK5 0x00
|
||||
#define RT5025_LDOMODE_MASK6 0x00
|
||||
#define RT5025_DCDCRAMP_MASK1 0x03
|
||||
#define RT5025_DCDCRAMP_MASK2 0x01
|
||||
#define RT5025_DCDCRAMP_MASK3 0x03
|
||||
#define RT5025_DCDCRAMP_MASK4 0x00
|
||||
|
||||
#endif /* __LINUX_RT5025_REGULATOR_H */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user