mirror of
https://github.com/torvalds/linux.git
synced 2026-06-07 22:14:04 +02:00
rk312x:pmic:rt5036:support pmic rt5036 drivers
This commit is contained in:
parent
d4834e8084
commit
1142cc6021
|
|
@ -172,7 +172,12 @@ rk818: rk818@1c {
|
|||
rt5025: rt5025@35 {
|
||||
compatible = "rt,rt5025";
|
||||
reg = <0x35>;
|
||||
status = "okay";
|
||||
status = "disabled";
|
||||
};
|
||||
rt5036: rt5036@38 {
|
||||
compatible = "rt,rt5036";
|
||||
reg = <0x38>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -305,6 +310,136 @@ rt5025-irq {
|
|||
};
|
||||
};
|
||||
|
||||
/include/ "rt5036.dtsi"
|
||||
&rt5036 {
|
||||
|
||||
rt5036_dcdc1: regulator_0 {
|
||||
regulator-name = "vdd_arm";
|
||||
regulator-min-microvolt = < 800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
qcom,comsumer-supplies = "vdd_arm", "";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
rt,standby_enabled;
|
||||
rt,standby_vol = <950000>;
|
||||
};
|
||||
|
||||
rt5036_dcdc2: regulator_1 {
|
||||
regulator-name = "vdd_logic";
|
||||
regulator-min-microvolt = < 800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
qcom,comsumer-supplies = "vdd_logic", "";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
rt,standby_enabled;
|
||||
rt,standby_vol = <950000>;
|
||||
};
|
||||
|
||||
rt5036_dcdc3: regulator_2 {
|
||||
regulator-name = "rt5036-dcdc3";
|
||||
regulator-min-microvolt = < 800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
qcom,comsumer-supplies = "rt5036-dcdc3", "";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
rt,standby_enabled;
|
||||
rt,standby_vol = <2800000>;
|
||||
};
|
||||
|
||||
rt5036_dcdc4: regulator_3 {
|
||||
regulator-name = "rt5036-dcdc4";
|
||||
regulator-min-microvolt = < 800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
qcom,comsumer-supplies = "rt5036-dcdc4", "";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
rt,standby_enabled;
|
||||
rt,standby_vol = <1200000>;
|
||||
};
|
||||
|
||||
rt5036_ldo1: regulator_4 {
|
||||
regulator-name = "rt5036-ldo1";
|
||||
regulator-min-microvolt = < 3000000>;
|
||||
regulator-max-microvolt = <3000000>;
|
||||
qcom,comsumer-supplies = "rt5036-ldo1", "";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
rt,standby_enabled;
|
||||
rt,standby_vol = <3000000>;
|
||||
};
|
||||
|
||||
rt5036_ldo2: regulator_5 {
|
||||
regulator-name = "rt5036-ldo2";
|
||||
regulator-min-microvolt = < 1100000>;
|
||||
regulator-max-microvolt = <1100000>;
|
||||
qcom,comsumer-supplies = "rt5036-ldo2", "";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
rt,standby_enabled;
|
||||
rt,standby_vol = <1100000>;
|
||||
};
|
||||
|
||||
rt5036_ldo3: regulator_6 {
|
||||
regulator-name = "rt5036-ldo3";
|
||||
regulator-min-microvolt = < 1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
qcom,comsumer-supplies = "rt5036-ldo3", "";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
rt,standby_enabled;
|
||||
rt,standby_vol = <1800000>;
|
||||
};
|
||||
|
||||
rt5036_ldo4: regulator_7 {
|
||||
regulator-name = "rt5036-ldo4";
|
||||
regulator-min-microvolt = < 1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
qcom,comsumer-supplies = "rt5036-ldo4", "";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
rt,standby_enabled;
|
||||
rt,standby_vol = <1800000>;
|
||||
};
|
||||
|
||||
rt5036_ldo5: regulator_8 {
|
||||
regulator-name = "rt5036-ldo5";
|
||||
qcom,comsumer-supplies = "rt5036-ldo5", "";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
rt,standby_enabled;
|
||||
};
|
||||
|
||||
rt5036_ldo6: regulator_9 {
|
||||
regulator-name = "rt5036-ldo6";
|
||||
qcom,comsumer-supplies = "rt5036-ldo6", "";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
rt,standby_enabled;
|
||||
};
|
||||
|
||||
rt5036-irq {
|
||||
compatible = "rt,rt5036-irq";
|
||||
rt,irq-gpio = <&gpio1 GPIO_B1 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
rt5036-charger {
|
||||
compatible = "rt,rt5036-charger";
|
||||
rt,te_en;
|
||||
rt,iprec = <0x2>;
|
||||
rt,ieoc = <0x3>;
|
||||
rt,vprec = <0xA>;
|
||||
rt,batlv = <0x4>;
|
||||
rt,vrechg = <1>;
|
||||
rt,chg_volt = <4200>;
|
||||
rt,otg_volt = <5025>;
|
||||
rt,acchg_icc = <2000>;
|
||||
rt,usbtachg_icc = <2000>;
|
||||
rt,usbchg_icc = <900>;
|
||||
/*rt,acdet_gpio = <&gpio1 GPIO_B1 GPIO_ACTIVE_HIGH>;*/
|
||||
/*rt,usbdet_gpio = <&gpio1 GPIO_B1 GPIO_ACTIVE_HIGH>;*/
|
||||
};
|
||||
};
|
||||
|
||||
/include/ "rk818.dtsi"
|
||||
&rk818 {
|
||||
gpios =<&gpio1 GPIO_B1 GPIO_ACTIVE_HIGH>,<&gpio1 GPIO_A1 GPIO_ACTIVE_LOW>;
|
||||
|
|
@ -483,11 +618,11 @@ battery {
|
|||
&clk_core_dvfs_table {
|
||||
operating-points = <
|
||||
/* KHz uV */
|
||||
408000 1250000
|
||||
600000 1250000
|
||||
696000 1250000
|
||||
816000 1250000
|
||||
1008000 1250000
|
||||
408000 1300000
|
||||
600000 1300000
|
||||
696000 1300000
|
||||
816000 1300000
|
||||
1008000 1300000
|
||||
>;
|
||||
status="okay";
|
||||
};
|
||||
|
|
|
|||
108
arch/arm/boot/dts/rt5036.dtsi
Executable file
108
arch/arm/boot/dts/rt5036.dtsi
Executable file
|
|
@ -0,0 +1,108 @@
|
|||
/* Copyright (c) 2014, 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.
|
||||
*/
|
||||
|
||||
&rt5036 {
|
||||
compatible = "rt,rt5036";
|
||||
|
||||
rt5036_dcdc1: regulator_0 {
|
||||
compatible = "rt,rt5036-dcdc1";
|
||||
cell-index = <0>;
|
||||
rt,nramp_sel = <0x00>;
|
||||
rt,sramp_sel = <0x00>;
|
||||
rt,allow_mode_mask;
|
||||
};
|
||||
rt5036_dcdc2: regulator_1 {
|
||||
compatible = "rt,rt5036-dcdc2";
|
||||
cell-index = <1>;
|
||||
rt,nramp_sel = <0x00>;
|
||||
rt,sramp_sel = <0x00>;
|
||||
rt,allow_mode_mask;
|
||||
};
|
||||
rt5036_dcdc3: regulator_2 {
|
||||
compatible = "rt,rt5036-dcdc3";
|
||||
cell-index = <2>;
|
||||
rt,nramp_sel = <0x00>;
|
||||
rt,sramp_sel = <0x00>;
|
||||
rt,allow_mode_mask;
|
||||
};
|
||||
rt5036_dcdc4: regulator_3 {
|
||||
compatible = "rt,rt5036-dcdc4";
|
||||
cell-index = <3>;
|
||||
rt,nramp_sel = <0x00>;
|
||||
rt,sramp_sel = <0x00>;
|
||||
rt,allow_mode_mask;
|
||||
};
|
||||
rt5036_ldo1: regulator_4 {
|
||||
supply-regulator = "rt5036-dcdc3";
|
||||
compatible = "rt,rt5036-ldo1";
|
||||
cell-index = <4>;
|
||||
rt,nramp_sel = <0x00>;
|
||||
rt,sramp_sel = <0x00>;
|
||||
rt,allow_mode_mask;
|
||||
};
|
||||
rt5036_ldo2: regulator_5 {
|
||||
supply-regulator = "rt5036-dcdc3";
|
||||
compatible = "rt,rt5036-ldo2";
|
||||
cell-index = <5>;
|
||||
rt,nramp_sel = <0x00>;
|
||||
rt,sramp_sel = <0x00>;
|
||||
rt,allow_mode_mask;
|
||||
};
|
||||
rt5036_ldo3: regulator_6 {
|
||||
supply-regulator = "rt5036-dcdc3";
|
||||
compatible = "rt,rt5036-ldo3";
|
||||
cell-index = <6>;
|
||||
rt,nramp_sel = <0x00>;
|
||||
rt,sramp_sel = <0x00>;
|
||||
rt,allow_mode_mask;
|
||||
};
|
||||
rt5036_ldo4: regulator_7 {
|
||||
supply-regulator = "rt5036-dcdc3";
|
||||
compatible = "rt,rt5036-ldo4";
|
||||
cell-index = <7>;
|
||||
rt,nramp_sel = <0x00>;
|
||||
rt,sramp_sel = <0x00>;
|
||||
rt,allow_mode_mask;
|
||||
};
|
||||
rt5036_lsw1: regulator_8 {
|
||||
supply-regulator = "rt5036-dcdc3";
|
||||
compatible = "rt,rt5036-lsw1";
|
||||
cell-index = <8>;
|
||||
rt,nramp_sel = <0x00>;
|
||||
rt,sramp_sel = <0x00>;
|
||||
rt,allow_mode_mask;
|
||||
};
|
||||
rt5036_lsw2: regulator_9 {
|
||||
supply-regulator = "rt5036-dcdc3";
|
||||
compatible = "rt,rt5036-lsw2";
|
||||
cell-index = <9>;
|
||||
rt,nramp_sel = <0x00>;
|
||||
rt,sramp_sel = <0x00>;
|
||||
rt,allow_mode_mask;
|
||||
};
|
||||
rt5036-rtc {
|
||||
compatible = "rt,rt5036-rtc";
|
||||
};
|
||||
rt5036-misc {
|
||||
compatible = "rt,rt5036-misc";
|
||||
rt,shdn_press = <0x1>;
|
||||
rt,stb_en = <1>;
|
||||
rt,lp_enshdn;
|
||||
rt,vsysuvlo = <0x2>;
|
||||
rt,syslv_enshdn;
|
||||
rt,system-power-controller;
|
||||
};
|
||||
rt5036-debug {
|
||||
compatible = "rt,rt5036-debug";
|
||||
};
|
||||
};
|
||||
|
||||
14
arch/arm/configs/rockchip_defconfig
Normal file → Executable file
14
arch/arm/configs/rockchip_defconfig
Normal file → Executable file
|
|
@ -329,12 +329,23 @@ CONFIG_SPI_ROCKCHIP_DMA=y
|
|||
CONFIG_SPI_ROCKCHIP_TEST=y
|
||||
CONFIG_DEBUG_GPIO=y
|
||||
CONFIG_GPIO_SYSFS=y
|
||||
CONFIG_CHARGER_RT5025=y
|
||||
CONFIG_BATTERY_RT5025=y
|
||||
CONFIG_CHARGER_RT5036=y
|
||||
CONFIG_RT_POWER=y
|
||||
CONFIG_BATTERY_RICOH619=y
|
||||
CONFIG_BATTERY_BQ24296=y
|
||||
CONFIG_BATTERY_BQ27320=y
|
||||
CONFIG_CW2015_BATTERY=y
|
||||
CONFIG_SENSORS_ROCKCHIP_TSADC=y
|
||||
CONFIG_THERMAL=y
|
||||
CONFIG_MFD_RT5025=y
|
||||
CONFIG_MISC_RT5025=y
|
||||
CONFIG_IRQ_RT5025=y
|
||||
CONFIG_DEBUG_RT5025=y
|
||||
CONFIG_MFD_RT5036=y
|
||||
CONFIG_MISC_RT5036=y
|
||||
CONFIG_IRQ_RT5036=y
|
||||
CONFIG_MFD_RK808=y
|
||||
CONFIG_MFD_RK818=y
|
||||
CONFIG_MFD_RICOH619=y
|
||||
|
|
@ -342,6 +353,8 @@ CONFIG_REGULATOR=y
|
|||
CONFIG_REGULATOR_FIXED_VOLTAGE=y
|
||||
CONFIG_REGULATOR_ACT8846=y
|
||||
CONFIG_ACT8846_SUPPORT_RESET=y
|
||||
CONFIG_REGULATOR_RT5025=y
|
||||
CONFIG_REGULATOR_RT5036=y
|
||||
CONFIG_ROCKCHIP_PWM_REGULATOR=y
|
||||
CONFIG_REGULATOR_SYR82X=y
|
||||
CONFIG_REGULATOR_RICOH619=y
|
||||
|
|
@ -509,6 +522,7 @@ CONFIG_SWITCH=y
|
|||
CONFIG_RTC_CLASS=y
|
||||
CONFIG_RTC_HYM8563=y
|
||||
CONFIG_RK808_RTC=y
|
||||
CONFIG_RTC_RT5036=y
|
||||
CONFIG_RTC_DRV_RC5T619=y
|
||||
CONFIG_STAGING=y
|
||||
CONFIG_ZSMALLOC=y
|
||||
|
|
|
|||
|
|
@ -205,6 +205,49 @@ config MFD_RT_SHOW_INFO
|
|||
help
|
||||
Enable the RT5025 PMIC debug log.
|
||||
|
||||
config MFD_RT5036
|
||||
bool "Richtek RT5036 PMIC support"
|
||||
select MFD_CORE
|
||||
default n
|
||||
help
|
||||
Enable the RT5036 MFD driver.
|
||||
|
||||
config MFD_RT5036_DBGINFO
|
||||
bool "Richtek RT5036 debug message enable."
|
||||
depends on MFD_RT5036
|
||||
default n
|
||||
help
|
||||
Enable the RT5036 debug log.
|
||||
|
||||
config MISC_RT5036
|
||||
bool "Richtek RT5036 MISC option driver support"
|
||||
depends on MFD_RT5036
|
||||
default n
|
||||
help
|
||||
Enable the RT5036 Misc option driver support.
|
||||
|
||||
config MISC_RT5036_PWRKEY
|
||||
bool "Richtek RT5036 Power key report in Misc module"
|
||||
depends on MISC_RT5036
|
||||
default n
|
||||
help
|
||||
Enable the RT5036 Power Key report in Misc module.
|
||||
|
||||
config IRQ_RT5036
|
||||
bool "Richtek RT5036 irq option driver support"
|
||||
depends on MFD_RT5036
|
||||
default n
|
||||
help
|
||||
Enable the Rt5036 IRQ option driver support.
|
||||
|
||||
config DEBUG_RT5036
|
||||
bool "Richtek RT5036 PMIC DEBUGFS Support"
|
||||
depends on DEBUG_FS && MFD_RT5036
|
||||
default n
|
||||
help
|
||||
Enable the RT5036 debugfs node that support
|
||||
read/write registers.
|
||||
|
||||
config HTC_EGPIO
|
||||
bool "HTC EGPIO support"
|
||||
depends on GENERIC_HARDIRQS && GPIOLIB && ARM
|
||||
|
|
|
|||
|
|
@ -60,6 +60,11 @@ obj-$(CONFIG_MISC_RT5025) += rt5025-misc.o
|
|||
obj-$(CONFIG_IRQ_RT5025) += rt5025-irq.o
|
||||
obj-$(CONFIG_DEBUG_RT5025) += rt5025-debug.o
|
||||
|
||||
obj-$(CONFIG_MFD_RT5036) += rt5036-i2c.o rt5036-core.o
|
||||
obj-$(CONFIG_MISC_RT5036) += rt5036-misc.o
|
||||
obj-$(CONFIG_IRQ_RT5036) += rt5036-irq.o
|
||||
obj-$(CONFIG_DEBUG_RT5036) += rt5036-debug.o
|
||||
|
||||
obj-$(CONFIG_TPS6105X) += tps6105x.o
|
||||
obj-$(CONFIG_TPS65010) += tps65010.o
|
||||
obj-$(CONFIG_TPS6507X) += tps6507x.o
|
||||
|
|
|
|||
|
|
@ -205,24 +205,31 @@ static int rt5025_i2c_remove(struct i2c_client *client)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int rt5025_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
|
||||
static int rt5025_i2c_suspend(struct device *dev)
|
||||
{
|
||||
struct rt5025_chip *chip = i2c_get_clientdata(client);
|
||||
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
|
||||
struct rt5025_chip *chip = i2c_get_clientdata(i2c);
|
||||
|
||||
RTINFO("\n");
|
||||
chip->suspend = 1;
|
||||
RTINFO("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5025_i2c_resume(struct i2c_client *client)
|
||||
static int rt5025_i2c_resume(struct device *dev)
|
||||
{
|
||||
struct rt5025_chip *chip = i2c_get_clientdata(client);
|
||||
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
|
||||
struct rt5025_chip *chip = i2c_get_clientdata(i2c);
|
||||
|
||||
chip->suspend = 0;
|
||||
RTINFO("\n");
|
||||
chip->suspend = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops rt5025_pm_ops = {
|
||||
.suspend = rt5025_i2c_suspend,
|
||||
.resume = rt5025_i2c_resume,
|
||||
};
|
||||
|
||||
static const struct i2c_device_id rt5025_id_table[] = {
|
||||
{ RT5025_DEV_NAME, 0 },
|
||||
{ },
|
||||
|
|
@ -238,12 +245,11 @@ static struct i2c_driver rt5025_i2c_driver = {
|
|||
.driver = {
|
||||
.name = RT5025_DEV_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &rt5025_pm_ops,
|
||||
.of_match_table = rt_match_table,
|
||||
},
|
||||
.probe = rt5025_i2c_probe,
|
||||
.remove = rt5025_i2c_remove,
|
||||
.suspend = rt5025_i2c_suspend,
|
||||
.resume = rt5025_i2c_resume,
|
||||
.id_table = rt5025_id_table,
|
||||
};
|
||||
|
||||
|
|
|
|||
268
drivers/mfd/rt5036-core.c
Executable file
268
drivers/mfd/rt5036-core.c
Executable file
|
|
@ -0,0 +1,268 @@
|
|||
/*
|
||||
* drivers/mfd/rt5036-core.c
|
||||
* Driver for Richtek RT5036 Core PMIC
|
||||
*
|
||||
* 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/version.h>
|
||||
#include <linux/mfd/core.h>
|
||||
|
||||
#include <linux/mfd/rt5036/rt5036.h>
|
||||
|
||||
#ifdef CONFIG_REGULATOR_RT5036
|
||||
#ifdef CONFIG_OF
|
||||
#define RT5036_BUCKVR_DEVS(_id, _idx) \
|
||||
{ \
|
||||
.name = RT5036_DEV_NAME "-regulator", \
|
||||
.num_resources = 0, \
|
||||
.of_compatible = "rt," RT5036_DEV_NAME "-dcdc" #_idx, \
|
||||
.id = RT5036_ID_##_id, \
|
||||
}
|
||||
|
||||
#define RT5036_LDOVR_DEVS(_id, _idx) \
|
||||
{ \
|
||||
.name = RT5036_DEV_NAME "-regulator", \
|
||||
.num_resources = 0, \
|
||||
.of_compatible = "rt," RT5036_DEV_NAME "-ldo" #_idx, \
|
||||
.id = RT5036_ID_##_id, \
|
||||
}
|
||||
|
||||
#define RT5036_LSWVR_DEVS(_id, _idx) \
|
||||
{ \
|
||||
.name = RT5036_DEV_NAME "-regulator", \
|
||||
.num_resources = 0, \
|
||||
.of_compatible = "rt," RT5036_DEV_NAME "-lsw" #_idx, \
|
||||
.id = RT5036_ID_##_id, \
|
||||
}
|
||||
#else
|
||||
#define RT5036_BUCKVR_DEVS(_id, _idx) \
|
||||
{ \
|
||||
.name = RT5036_DEV_NAME "-regulator", \
|
||||
.num_resources = 0, \
|
||||
.id = RT5036_ID_##_id, \
|
||||
}
|
||||
|
||||
#define RT5036_LDOVR_DEVS(_id, _idx) \
|
||||
{ \
|
||||
.name = RT5036_DEV_NAME "-regulator", \
|
||||
.num_resources = 0, \
|
||||
.id = RT5036_ID_##_id, \
|
||||
}
|
||||
|
||||
#define RT5036_LSWVR_DEVS(_id, _idx) \
|
||||
{ \
|
||||
.name = RT5036_DEV_NAME "-regulator", \
|
||||
.num_resources = 0, \
|
||||
.id = RT5036_ID_##_id, \
|
||||
}
|
||||
#endif /* #ifdef CONFIG_OF */
|
||||
|
||||
static struct mfd_cell regulator_devs[] = {
|
||||
RT5036_BUCKVR_DEVS(DCDC1, 1),
|
||||
RT5036_BUCKVR_DEVS(DCDC2, 2),
|
||||
RT5036_BUCKVR_DEVS(DCDC3, 3),
|
||||
RT5036_BUCKVR_DEVS(DCDC4, 4),
|
||||
RT5036_LDOVR_DEVS(LDO1, 1),
|
||||
RT5036_LDOVR_DEVS(LDO2, 2),
|
||||
RT5036_LDOVR_DEVS(LDO3, 3),
|
||||
RT5036_LDOVR_DEVS(LDO4, 4),
|
||||
RT5036_LSWVR_DEVS(LSW1, 1),
|
||||
RT5036_LSWVR_DEVS(LSW2, 2),
|
||||
};
|
||||
#endif /* CONFIG_REGULATOR_RT5036 */
|
||||
|
||||
#ifdef CONFIG_CHARGER_RT5036
|
||||
static struct mfd_cell chg_devs[] = {
|
||||
{
|
||||
.name = RT5036_DEV_NAME "-charger",
|
||||
.id = -1,
|
||||
.num_resources = 0,
|
||||
#ifdef CONFIG_OF
|
||||
.of_compatible = "rt," RT5036_DEV_NAME "-charger",
|
||||
#endif /*#ifdef CONFIG_OF */
|
||||
},
|
||||
};
|
||||
#endif /* CONFIG_CHARGER_RT5036 */
|
||||
|
||||
#ifdef CONFIG_RTC_RT5036
|
||||
static struct mfd_cell rtc_devs[] = {
|
||||
{
|
||||
.name = RT5036_DEV_NAME "-rtc",
|
||||
.id = -1,
|
||||
.num_resources = 0,
|
||||
#ifdef CONFIG_OF
|
||||
.of_compatible = "rt," RT5036_DEV_NAME "-rtc",
|
||||
#endif /*#ifdef CONFIG_OF */
|
||||
},
|
||||
};
|
||||
#endif /* CONFIG_RTC_RT5036 */
|
||||
|
||||
#ifdef CONFIG_MISC_RT5036
|
||||
static struct mfd_cell misc_devs[] = {
|
||||
{
|
||||
.name = RT5036_DEV_NAME "-misc",
|
||||
.id = -1,
|
||||
.num_resources = 0,
|
||||
#ifdef CONFIG_OF
|
||||
.of_compatible = "rt," RT5036_DEV_NAME "-misc",
|
||||
#endif /*#ifdef CONFIG_OF */
|
||||
},
|
||||
};
|
||||
#endif /* CONFIG_MISC_RT5036 */
|
||||
|
||||
#ifdef CONFIG_IRQ_RT5036
|
||||
static struct mfd_cell irq_devs[] = {
|
||||
{
|
||||
.name = RT5036_DEV_NAME "-irq",
|
||||
.id = -1,
|
||||
.num_resources = 0,
|
||||
#ifdef CONFIG_OF
|
||||
.of_compatible = "rt," RT5036_DEV_NAME "-irq",
|
||||
#endif /*#ifdef CONFIG_OF */
|
||||
},
|
||||
};
|
||||
#endif /* CONFIG_IRQ_RT5036 */
|
||||
|
||||
#ifdef CONFIG_DEBUG_RT5036
|
||||
static struct mfd_cell debug_devs[] = {
|
||||
{
|
||||
.name = RT5036_DEV_NAME "-debug",
|
||||
.id = -1,
|
||||
.num_resources = 0,
|
||||
#ifdef CONFIG_OF
|
||||
.of_compatible = "rt," RT5036_DEV_NAME "-debug",
|
||||
#endif /*#ifdef CONFIG_OF */
|
||||
},
|
||||
};
|
||||
#endif /* CONFIG_DEBUG_RT5036 */
|
||||
|
||||
int rt5036_core_init(struct device *dev,
|
||||
struct rt5036_platform_data *pdata)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
RTINFO("Start to initialize all device\n");
|
||||
#ifdef CONFIG_REGULATOR_RT5036
|
||||
if (dev->of_node || (pdata && pdata->regulator[0])) {
|
||||
RTINFO("mfd add regulators dev\n");
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
|
||||
ret = mfd_add_devices(dev, 0, ®ulator_devs[0],
|
||||
ARRAY_SIZE(regulator_devs),
|
||||
NULL, 0, NULL);
|
||||
#else
|
||||
ret = mfd_add_devices(dev, 0, ®ulator_devs[0],
|
||||
ARRAY_SIZE(regulator_devs), NULL, 0);
|
||||
#endif /* LINUX_VERSION_CODE>=KERNL_VERSION(3,6,0) */
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to add regulator subdev\n");
|
||||
goto out_dev;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_REGULATOR_RT5036 */
|
||||
|
||||
#ifdef CONFIG_CHARGER_RT5036
|
||||
if (dev->of_node || (pdata && pdata->chg_pdata)) {
|
||||
RTINFO("mfd add charger dev\n");
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
|
||||
ret = mfd_add_devices(dev, 0, &chg_devs[0],
|
||||
ARRAY_SIZE(chg_devs), NULL, 0, NULL);
|
||||
#else
|
||||
ret = mfd_add_devices(dev, 0, &chg_devs[0],
|
||||
ARRAY_SIZE(chg_devs), NULL, 0);
|
||||
#endif /* LINUX_VERSION_CODE>=KERNL_VERSION(3,6,0) */
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to add charger subdev\n");
|
||||
goto out_dev;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_CHARGER_RT5036 */
|
||||
|
||||
#ifdef CONFIG_RTC_RT5036
|
||||
if (dev->of_node || pdata) {
|
||||
RTINFO("mfd add rtc dev\n");
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
|
||||
ret = mfd_add_devices(dev, 0, &rtc_devs[0],
|
||||
ARRAY_SIZE(rtc_devs), NULL, 0, NULL);
|
||||
#else
|
||||
ret = mfd_add_devices(dev, 0, &rtc_devs[0],
|
||||
ARRAY_SIZE(rtc_devs), NULL, 0);
|
||||
#endif /* LINUX_VERSION_CODE>=KERNL_VERSION(3,6,0) */
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to add rtc subdev\n");
|
||||
goto out_dev;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_RTC_RT5036 */
|
||||
|
||||
#ifdef CONFIG_MISC_RT5036
|
||||
if (dev->of_node || (pdata && pdata->misc_pdata)) {
|
||||
RTINFO("mfd add misc dev\n");
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
|
||||
ret = mfd_add_devices(dev, 0, &misc_devs[0],
|
||||
ARRAY_SIZE(misc_devs), NULL, 0, NULL);
|
||||
#else
|
||||
ret = mfd_add_devices(dev, 0, &misc_devs[0],
|
||||
ARRAY_SIZE(misc_devs), NULL, 0);
|
||||
#endif /* LINUX_VERSION_CODE>=KERNL_VERSION(3,6,0) */
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to add misc subdev\n");
|
||||
goto out_dev;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_MISC_RT5036 */
|
||||
|
||||
#ifdef CONFIG_IRQ_RT5036
|
||||
if (dev->of_node || (pdata && pdata->irq_pdata)) {
|
||||
RTINFO("mfd add irq dev\n");
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
|
||||
ret = mfd_add_devices(dev, 0, &irq_devs[0],
|
||||
ARRAY_SIZE(irq_devs), NULL, 0, NULL);
|
||||
#else
|
||||
ret = mfd_add_devices(dev, 0, &irq_devs[0],
|
||||
ARRAY_SIZE(irq_devs), NULL, 0);
|
||||
#endif /* LINUX_VERSION_CODE>=KERNL_VERSION(3,6,0) */
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to add irq subdev\n");
|
||||
goto out_dev;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IRQ_RT5036 */
|
||||
|
||||
#ifdef CONFIG_DEBUG_RT5036
|
||||
RTINFO("mfd add debug dev\n");
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
|
||||
ret = mfd_add_devices(dev, 0, &debug_devs[0],
|
||||
ARRAY_SIZE(debug_devs), NULL, 0, NULL);
|
||||
#else
|
||||
ret = mfd_add_devices(dev, 0, &debug_devs[0],
|
||||
ARRAY_SIZE(debug_devs), NULL, 0);
|
||||
#endif /* LINUX_VERSION_CODE>=KERNL_VERSION(3,6,0) */
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to add debug subdev\n");
|
||||
goto out_dev;
|
||||
}
|
||||
#endif /* CONFIG_DEBUG_RT5036 */
|
||||
|
||||
RTINFO("Initialize all device successfully\n");
|
||||
return ret;
|
||||
out_dev:
|
||||
mfd_remove_devices(dev);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(rt5036_core_init);
|
||||
|
||||
int rt5036_core_deinit(struct device *dev)
|
||||
{
|
||||
mfd_remove_devices(dev);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(rt5036_core_deinit);
|
||||
261
drivers/mfd/rt5036-debug.c
Executable file
261
drivers/mfd/rt5036-debug.c
Executable file
|
|
@ -0,0 +1,261 @@
|
|||
/*
|
||||
* drivers/mfd/rt5036-debug.c
|
||||
* Driver for Richtek RT5036 PMIC debug
|
||||
*
|
||||
* 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/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <linux/mfd/rt5036/rt5036.h>
|
||||
|
||||
struct rt5036_debug_info {
|
||||
struct i2c_client *i2c;
|
||||
unsigned char reg_addr;
|
||||
unsigned char reg_data;
|
||||
};
|
||||
|
||||
struct rt_debug_st {
|
||||
void *info;
|
||||
int id;
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5036_DBG_REG,
|
||||
RT5036_DBG_DATA,
|
||||
RT5036_DBG_REGS,
|
||||
RT5036_DBG_MAX
|
||||
};
|
||||
|
||||
static struct dentry *debugfs_rt_dent;
|
||||
static struct dentry *debugfs_file[RT5036_DBG_MAX];
|
||||
static struct rt_debug_st rtdbg_data[RT5036_DBG_MAX];
|
||||
|
||||
static int reg_debug_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
file->private_data = inode->i_private;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_parameters(char *buf, long int *param1, int num_of_par)
|
||||
{
|
||||
char *token;
|
||||
int base, cnt;
|
||||
|
||||
token = strsep(&buf, " ");
|
||||
|
||||
for (cnt = 0; cnt < num_of_par; cnt++) {
|
||||
if (token != NULL) {
|
||||
if ((token[1] == 'x') || (token[1] == 'X'))
|
||||
base = 16;
|
||||
else
|
||||
base = 10;
|
||||
|
||||
if (kstrtoul(token, base, ¶m1[cnt]) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
token = strsep(&buf, " ");
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t reg_debug_read(struct file *filp, char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct rt_debug_st *st = filp->private_data;
|
||||
struct rt5036_debug_info *di = st->info;
|
||||
char lbuf[1000];
|
||||
int i = 0, j = 0;
|
||||
|
||||
lbuf[0] = '\0';
|
||||
switch (st->id) {
|
||||
case RT5036_DBG_REG:
|
||||
snprintf(lbuf, sizeof(lbuf), "0x%x\n", di->reg_addr);
|
||||
break;
|
||||
case RT5036_DBG_DATA:
|
||||
di->reg_data =
|
||||
(unsigned char)rt5036_reg_read(di->i2c, di->reg_addr);
|
||||
snprintf(lbuf, sizeof(lbuf), "0x%x\n", di->reg_data);
|
||||
break;
|
||||
case RT5036_DBG_REGS:
|
||||
for (i = RT5036_REG_RANGE1START; i <= RT5036_REG_RANGE1END; i++)
|
||||
j += sprintf(lbuf + j, "reg_%02x:%02x\n", i,
|
||||
rt5036_reg_read(di->i2c, i));
|
||||
for (i = RT5036_REG_RANGE2START; i <= RT5036_REG_RANGE2END; i++)
|
||||
j += sprintf(lbuf + j, "reg_%02x:%02x\n", i,
|
||||
rt5036_reg_read(di->i2c, i));
|
||||
for (i = RT5036_REG_RANGE3START; i <= RT5036_REG_RANGE3END; i++)
|
||||
j += sprintf(lbuf + j, "reg_%02x:%02x\n", i,
|
||||
rt5036_reg_read(di->i2c, i));
|
||||
for (i = RT5036_REG_RANGE4START; i <= RT5036_REG_RANGE4END; i++)
|
||||
j += sprintf(lbuf + j, "reg_%02x:%02x\n", i,
|
||||
rt5036_reg_read(di->i2c, i));
|
||||
for (i = RT5036_REG_RANGE5START; i <= RT5036_REG_RANGE5END; i++)
|
||||
j += sprintf(lbuf + j, "reg_%02x:%02x\n", i,
|
||||
rt5036_reg_read(di->i2c, i));
|
||||
for (i = RT5036_REG_RANGE6START; i <= RT5036_REG_RANGE6END; i++)
|
||||
j += sprintf(lbuf + j, "reg_%02x:%02x\n", i,
|
||||
rt5036_reg_read(di->i2c, i));
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
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)
|
||||
{
|
||||
struct rt_debug_st *st = filp->private_data;
|
||||
struct rt5036_debug_info *di = st->info;
|
||||
char lbuf[32];
|
||||
int rc;
|
||||
long int param[5];
|
||||
|
||||
if (cnt > sizeof(lbuf) - 1)
|
||||
return -EINVAL;
|
||||
|
||||
rc = copy_from_user(lbuf, ubuf, cnt);
|
||||
if (rc)
|
||||
return -EFAULT;
|
||||
|
||||
lbuf[cnt] = '\0';
|
||||
|
||||
switch (st->id) {
|
||||
case RT5036_DBG_REG:
|
||||
rc = get_parameters(lbuf, param, 1);
|
||||
if ((param[0] < RT5036_REG_MAX) && (rc == 0)) {
|
||||
if ((param[0] >= RT5036_REG_RANGE1START
|
||||
&& param[0] <= RT5036_REG_RANGE1END)
|
||||
|| (param[0] >= RT5036_REG_RANGE2START
|
||||
&& param[0] <= RT5036_REG_RANGE2END)
|
||||
|| (param[0] >= RT5036_REG_RANGE3START
|
||||
&& param[0] <= RT5036_REG_RANGE3END)
|
||||
|| (param[0] >= RT5036_REG_RANGE4START
|
||||
&& param[0] <= RT5036_REG_RANGE4END)
|
||||
|| (param[0] >= RT5036_REG_RANGE5START
|
||||
&& param[0] <= RT5036_REG_RANGE5END))
|
||||
di->reg_addr = (unsigned char)param[0];
|
||||
else
|
||||
rc = -EINVAL;
|
||||
} else
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
case RT5036_DBG_DATA:
|
||||
rc = get_parameters(lbuf, param, 1);
|
||||
if ((param[0] <= 0xff) && (rc == 0))
|
||||
rt5036_reg_write(di->i2c, di->reg_addr, param[0]);
|
||||
else
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
if (rc == 0)
|
||||
rc = cnt;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct file_operations reg_debug_ops = {
|
||||
.open = reg_debug_open,
|
||||
.write = reg_debug_write,
|
||||
.read = reg_debug_read
|
||||
};
|
||||
|
||||
static int rt5036_debug_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rt5036_chip *chip = dev_get_drvdata(pdev->dev.parent);
|
||||
struct rt5036_debug_info *di;
|
||||
|
||||
di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
|
||||
if (!di)
|
||||
return -ENOMEM;
|
||||
|
||||
di->i2c = chip->i2c;
|
||||
|
||||
RTINFO("add debugfs for RT5036");
|
||||
debugfs_rt_dent = debugfs_create_dir("rt5036_dbg", 0);
|
||||
if (!IS_ERR(debugfs_rt_dent)) {
|
||||
rtdbg_data[0].info = di;
|
||||
rtdbg_data[0].id = RT5036_DBG_REG;
|
||||
debugfs_file[0] = debugfs_create_file("reg",
|
||||
S_IFREG | S_IRUGO,
|
||||
debugfs_rt_dent,
|
||||
(void *)&rtdbg_data[0],
|
||||
®_debug_ops);
|
||||
|
||||
rtdbg_data[1].info = di;
|
||||
rtdbg_data[1].id = RT5036_DBG_DATA;
|
||||
debugfs_file[1] = debugfs_create_file("data",
|
||||
S_IFREG | S_IRUGO,
|
||||
debugfs_rt_dent,
|
||||
(void *)&rtdbg_data[1],
|
||||
®_debug_ops);
|
||||
|
||||
rtdbg_data[2].info = di;
|
||||
rtdbg_data[2].id = RT5036_DBG_REGS;
|
||||
debugfs_file[2] = debugfs_create_file("regs",
|
||||
S_IFREG | S_IRUGO,
|
||||
debugfs_rt_dent,
|
||||
(void *)&rtdbg_data[2],
|
||||
®_debug_ops);
|
||||
}
|
||||
platform_set_drvdata(pdev, di);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5036_debug_remove(struct platform_device *pdev)
|
||||
{
|
||||
if (!IS_ERR(debugfs_rt_dent))
|
||||
debugfs_remove_recursive(debugfs_rt_dent);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id rt_match_table[] = {
|
||||
{.compatible = "rt,rt5036-debug",},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver rt5036_debug_driver = {
|
||||
.driver = {
|
||||
.name = RT5036_DEV_NAME "-debug",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = rt_match_table,
|
||||
},
|
||||
.probe = rt5036_debug_probe,
|
||||
.remove = rt5036_debug_remove,
|
||||
};
|
||||
|
||||
static int __init rt5036_debug_init(void)
|
||||
{
|
||||
return platform_driver_register(&rt5036_debug_driver);
|
||||
}
|
||||
module_init(rt5036_debug_init);
|
||||
|
||||
static void __exit rt5036_debug_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&rt5036_debug_driver);
|
||||
}
|
||||
module_exit(rt5036_debug_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
|
||||
MODULE_DESCRIPTION("Debugfs driver for RT5036");
|
||||
MODULE_ALIAS("platform:" RT5036_DEV_NAME "-debug");
|
||||
MODULE_VERSION(RT5036_DRV_VER);
|
||||
279
drivers/mfd/rt5036-i2c.c
Executable file
279
drivers/mfd/rt5036-i2c.c
Executable file
|
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
* drivers/mfd/rt5036-i2c.c
|
||||
* Source file for Richtek RT5036
|
||||
*
|
||||
* 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/i2c.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <linux/mfd/rt5036/rt5036.h>
|
||||
|
||||
static inline int rt5036_read_device(struct i2c_client *i2c,
|
||||
int reg, int bytes, void *dest)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (bytes > 1) {
|
||||
ret = i2c_smbus_read_i2c_block_data(i2c, reg, bytes, dest);
|
||||
} else {
|
||||
ret = i2c_smbus_read_byte_data(i2c, reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*(unsigned char *)dest = (unsigned char)ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rt5036_reg_block_read(struct i2c_client *i2c,
|
||||
int reg, int bytes, void *dest)
|
||||
{
|
||||
return rt5036_read_device(i2c, reg, bytes, dest);
|
||||
}
|
||||
EXPORT_SYMBOL(rt5036_reg_block_read);
|
||||
|
||||
static inline int rt5036_write_device(struct i2c_client *i2c,
|
||||
int reg, int bytes, void *dest)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (bytes > 1) {
|
||||
ret = i2c_smbus_write_i2c_block_data(i2c, reg, bytes, dest);
|
||||
} else {
|
||||
ret = i2c_smbus_write_byte_data(i2c, reg, *(u8 *) dest);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rt5036_reg_block_write(struct i2c_client *i2c,
|
||||
int reg, int bytes, void *dest)
|
||||
{
|
||||
return rt5036_write_device(i2c, reg, bytes, dest);
|
||||
}
|
||||
EXPORT_SYMBOL(rt5036_reg_block_write);
|
||||
|
||||
int rt5036_reg_read(struct i2c_client *i2c, int reg)
|
||||
{
|
||||
struct rt5036_chip *chip = i2c_get_clientdata(i2c);
|
||||
int ret;
|
||||
|
||||
RTINFO("I2C Read (client : 0x%x) reg = 0x%x\n",
|
||||
(unsigned int)i2c, (unsigned int)reg);
|
||||
mutex_lock(&chip->io_lock);
|
||||
ret = i2c_smbus_read_byte_data(i2c, reg);
|
||||
mutex_unlock(&chip->io_lock);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(rt5036_reg_read);
|
||||
|
||||
int rt5036_reg_write(struct i2c_client *i2c, int reg, unsigned char data)
|
||||
{
|
||||
struct rt5036_chip *chip = i2c_get_clientdata(i2c);
|
||||
int ret;
|
||||
|
||||
RTINFO("I2C Write (client : 0x%x) reg = 0x%x, data = 0x%x\n",
|
||||
(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);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(rt5036_reg_write);
|
||||
|
||||
int rt5036_assign_bits(struct i2c_client *i2c, int reg,
|
||||
unsigned char mask, unsigned char data)
|
||||
{
|
||||
struct rt5036_chip *chip = i2c_get_clientdata(i2c);
|
||||
unsigned char value;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&chip->io_lock);
|
||||
ret = rt5036_read_device(i2c, reg, 1, &value);
|
||||
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
value &= ~mask;
|
||||
value |= (data & mask);
|
||||
ret = i2c_smbus_write_byte_data(i2c, reg, value);
|
||||
out:
|
||||
mutex_unlock(&chip->io_lock);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(rt5036_assign_bits);
|
||||
|
||||
int rt5036_set_bits(struct i2c_client *i2c, int reg, unsigned char mask)
|
||||
{
|
||||
return rt5036_assign_bits(i2c, reg, mask, mask);
|
||||
}
|
||||
EXPORT_SYMBOL(rt5036_set_bits);
|
||||
|
||||
int rt5036_clr_bits(struct i2c_client *i2c, int reg, unsigned char mask)
|
||||
{
|
||||
return rt5036_assign_bits(i2c, reg, mask, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(rt5036_clr_bits);
|
||||
|
||||
static int rt_parse_dt(struct rt5036_chip *chip, struct device *dev)
|
||||
{
|
||||
RTINFO("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt_parse_pdata(struct rt5036_chip *chip,
|
||||
struct device *dev)
|
||||
{
|
||||
RTINFO("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5036_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct rt5036_platform_data *pdata = client->dev.platform_data;
|
||||
struct rt5036_chip *chip;
|
||||
bool use_dt = client->dev.of_node;
|
||||
int val, ret = 0;
|
||||
|
||||
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
|
||||
if (!chip)
|
||||
return -ENOMEM;
|
||||
|
||||
chip->i2c = client;
|
||||
mutex_init(&chip->io_lock);
|
||||
i2c_set_clientdata(client, chip);
|
||||
|
||||
val = rt5036_reg_read(client, RT5036_REG_DEVID);
|
||||
if (val < 0) {
|
||||
ret = -EIO;
|
||||
goto out_err;
|
||||
} else {
|
||||
if (val != 0x36) {
|
||||
dev_err(&client->dev, "id 0x%02x is not correct\n",
|
||||
val);
|
||||
ret = ENODEV;
|
||||
goto out_err;
|
||||
}
|
||||
val = rt5036_reg_read(client, RT5036_REG_ONOFFEVENT);
|
||||
dev_info(&client->dev, "last onoff event %02x\n", val);
|
||||
/*set ldo lsw vrc to default enable*/
|
||||
rt5036_reg_write(client, 0x4D, 0xF0);
|
||||
rt5036_reg_write(client, 0x7D, 0xF0);
|
||||
rt5036_reg_write(client, 0x85, 0xCC);
|
||||
}
|
||||
|
||||
if (use_dt) {
|
||||
rt_parse_dt(chip, &client->dev);
|
||||
} else {
|
||||
if (!pdata) {
|
||||
dev_err(&client->dev, "no platform data included\n");
|
||||
ret = -EINVAL;
|
||||
goto out_err;
|
||||
}
|
||||
rt_parse_pdata(chip, &client->dev);
|
||||
}
|
||||
|
||||
ret = rt5036_core_init(&client->dev, pdata);
|
||||
if (ret < 0) {
|
||||
ret = -EINVAL;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (pdata && pdata->pre_init) {
|
||||
ret = pdata->pre_init(chip);
|
||||
if (ret != 0)
|
||||
dev_err(&client->dev, "pre_init() failed: %d\n", ret);
|
||||
}
|
||||
if (pdata && pdata->post_init) {
|
||||
ret = pdata->post_init();
|
||||
if (ret != 0)
|
||||
dev_err(&client->dev, "post_init() failed: %d\n", ret);
|
||||
}
|
||||
dev_info(&client->dev, "driver successfully loaded\n");
|
||||
return 0;
|
||||
out_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rt5036_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
RTINFO("\n");
|
||||
rt5036_core_deinit(&client->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5036_i2c_suspend(struct device *dev)
|
||||
{
|
||||
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
|
||||
struct rt5036_chip *chip = i2c_get_clientdata(i2c);
|
||||
|
||||
RTINFO("\n");
|
||||
chip->suspend = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5036_i2c_resume(struct device *dev)
|
||||
{
|
||||
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
|
||||
struct rt5036_chip *chip = i2c_get_clientdata(i2c);
|
||||
|
||||
RTINFO("\n");
|
||||
chip->suspend = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops rt5036_pm_ops = {
|
||||
.suspend = rt5036_i2c_suspend,
|
||||
.resume = rt5036_i2c_resume,
|
||||
};
|
||||
|
||||
static const struct i2c_device_id rt5036_id_table[] = {
|
||||
{RT5036_DEV_NAME, 0},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, rt5036_id_table);
|
||||
|
||||
static const struct of_device_id rt_match_table[] = {
|
||||
{.compatible = "rt,rt5036",},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct i2c_driver rt5036_driver = {
|
||||
.driver = {
|
||||
.name = RT5036_DEV_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &rt5036_pm_ops,
|
||||
.of_match_table = rt_match_table,
|
||||
},
|
||||
.probe = rt5036_i2c_probe,
|
||||
.remove = rt5036_i2c_remove,
|
||||
.id_table = rt5036_id_table,
|
||||
};
|
||||
|
||||
static int __init rt5036_i2c_init(void)
|
||||
{
|
||||
return i2c_add_driver(&rt5036_driver);
|
||||
}
|
||||
subsys_initcall_sync(rt5036_i2c_init);
|
||||
|
||||
static void __exit rt5036_i2c_exit(void)
|
||||
{
|
||||
i2c_del_driver(&rt5036_driver);
|
||||
}
|
||||
module_exit(rt5036_i2c_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("I2C Driver for Richtek RT5036");
|
||||
MODULE_AUTHOR("CY Huang <cy_huang@richtek.com>");
|
||||
MODULE_VERSION(RT5036_DRV_VER);
|
||||
245
drivers/mfd/rt5036-irq.c
Executable file
245
drivers/mfd/rt5036-irq.c
Executable file
|
|
@ -0,0 +1,245 @@
|
|||
/*
|
||||
* drivers/mfd/rt5036-irq.c
|
||||
* Driver for Richtek RT5036 PMIC IRQ 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/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <linux/mfd/rt5036/rt5036.h>
|
||||
#include <linux/mfd/rt5036/rt5036-irq.h>
|
||||
|
||||
struct rt5036_irq_info {
|
||||
struct i2c_client *i2c;
|
||||
struct rt5036_chip *chip;
|
||||
struct device *dev;
|
||||
int irq;
|
||||
unsigned char suspend:1;
|
||||
struct delayed_work irq_delayed_work;
|
||||
};
|
||||
|
||||
static irqreturn_t rt5036_irq_handler(int irqno, void *param)
|
||||
{
|
||||
struct rt5036_irq_info *ii = param;
|
||||
unsigned char regval[3];
|
||||
unsigned int irq_event;
|
||||
int ret = 0;
|
||||
|
||||
if (ii->suspend) {
|
||||
schedule_delayed_work(&ii->irq_delayed_work,
|
||||
msecs_to_jiffies(10));
|
||||
goto irq_fin;
|
||||
}
|
||||
|
||||
ret =
|
||||
rt5036_reg_block_read(ii->i2c, RT5036_REG_CHGIRQ1,
|
||||
ARRAY_SIZE(regval), regval);
|
||||
if (ret < 0) {
|
||||
dev_err(ii->dev, "read charger irq event fail\n");
|
||||
} else {
|
||||
irq_event = regval[0] << 16 | regval[1] << 8 | regval[2];
|
||||
RTINFO("chg event %06x\n", irq_event);
|
||||
#ifdef CONFIG_CHARGER_RT5036
|
||||
if (irq_event && ii->chip->chg_info)
|
||||
rt5036_charger_irq_handler(ii->chip->chg_info,
|
||||
irq_event);
|
||||
#endif /* #ifdef CONFIG_CHARGER_RT5036 */
|
||||
}
|
||||
|
||||
ret =
|
||||
rt5036_reg_block_read(ii->i2c, RT5036_REG_BUCKLDOIRQ,
|
||||
ARRAY_SIZE(regval), regval);
|
||||
if (ret < 0) {
|
||||
dev_err(ii->dev, "read misc irq event fail\n");
|
||||
} else {
|
||||
irq_event = regval[0] << 16 | regval[1] << 8 | regval[2];
|
||||
RTINFO("misc event %06x\n", irq_event);
|
||||
#ifdef CONFIG_MISC_RT5036
|
||||
if (irq_event && ii->chip->misc_info)
|
||||
rt5036_misc_irq_handler(ii->chip->misc_info, irq_event);
|
||||
#endif /* #ifdef CONFIG_MISC_RT5036 */
|
||||
}
|
||||
|
||||
ret = rt5036_reg_read(ii->i2c, RT5036_REG_STBWACKIRQ);
|
||||
if (ret < 0) {
|
||||
dev_err(ii->dev, "read rtc irq event fail\n");
|
||||
} else {
|
||||
irq_event = ret;
|
||||
RTINFO("rtc event %02x\n", irq_event);
|
||||
#ifdef CONFIG_RTC_RT5036
|
||||
if (irq_event && ii->chip->rtc_info)
|
||||
rt5036_rtc_irq_handler(ii->chip->rtc_info, irq_event);
|
||||
#endif /* #ifdef CONFIG_RTC_RT5036 */
|
||||
}
|
||||
rt5036_set_bits(ii->i2c, RT5036_REG_BUCKVN1, RT5036_IRQPREZ_MASK);
|
||||
irq_fin:
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void rt5036_irq_delayed_work(struct work_struct *work)
|
||||
{
|
||||
struct rt5036_irq_info *ii =
|
||||
(struct rt5036_irq_info *)container_of(work, struct rt5036_irq_info,
|
||||
irq_delayed_work.work);
|
||||
rt5036_irq_handler(ii->irq, ii);
|
||||
}
|
||||
|
||||
static int rt_parse_dt(struct rt5036_irq_info *ii, struct device *dev)
|
||||
{
|
||||
#ifdef CONFIG_OF
|
||||
struct device_node *np = dev->of_node;
|
||||
int val;
|
||||
|
||||
val = of_get_named_gpio(np, "rt,irq-gpio", 0);
|
||||
if (gpio_is_valid(val)) {
|
||||
if (gpio_request(val, "rt5036_irq") >= 0) {
|
||||
gpio_direction_input(val);
|
||||
ii->irq = gpio_to_irq(val);
|
||||
} else {
|
||||
ii->irq = -1;
|
||||
}
|
||||
} else {
|
||||
ii->irq = -1;
|
||||
}
|
||||
#endif /* #ifdef CONFIG_OF */
|
||||
RTINFO("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt_parse_pdata(struct rt5036_irq_info *ii,
|
||||
struct device *dev)
|
||||
{
|
||||
struct rt5036_irq_data *pdata = dev->platform_data;
|
||||
|
||||
if (gpio_is_valid(pdata->irq_gpio)) {
|
||||
if (gpio_request(pdata->irq_gpio, "rt5036_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 rt5036_irq_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rt5036_chip *chip = dev_get_drvdata(pdev->dev.parent);
|
||||
struct rt5036_platform_data *pdata = (pdev->dev.parent)->platform_data;
|
||||
struct rt5036_irq_info *ii;
|
||||
bool use_dt = pdev->dev.of_node;
|
||||
|
||||
ii = devm_kzalloc(&pdev->dev, sizeof(*ii), GFP_KERNEL);
|
||||
if (!ii)
|
||||
return -ENOMEM;
|
||||
|
||||
ii->i2c = chip->i2c;
|
||||
ii->chip = chip;
|
||||
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);
|
||||
}
|
||||
INIT_DELAYED_WORK(&ii->irq_delayed_work, rt5036_irq_delayed_work);
|
||||
|
||||
platform_set_drvdata(pdev, ii);
|
||||
if (ii->irq >= 0) {
|
||||
if (devm_request_irq
|
||||
(&pdev->dev, ii->irq, rt5036_irq_handler,
|
||||
IRQF_TRIGGER_FALLING | IRQF_NO_SUSPEND | IRQF_DISABLED,
|
||||
"rt5036_irq", ii)) {
|
||||
dev_err(&pdev->dev, "request threaded irq fail\n");
|
||||
goto out_dev;
|
||||
}
|
||||
enable_irq_wake(ii->irq);
|
||||
schedule_delayed_work(&ii->irq_delayed_work,
|
||||
msecs_to_jiffies(500));
|
||||
}
|
||||
dev_info(&pdev->dev, "driver successfully loaded\n");
|
||||
return 0;
|
||||
out_dev:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int rt5036_irq_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rt5036_irq_info *ii = platform_get_drvdata(pdev);
|
||||
|
||||
if (ii->irq >= 0)
|
||||
devm_free_irq(&pdev->dev, ii->irq, ii);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5036_irq_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
struct rt5036_irq_info *ii = platform_get_drvdata(pdev);
|
||||
|
||||
ii->suspend = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5036_irq_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct rt5036_irq_info *ii = platform_get_drvdata(pdev);
|
||||
|
||||
ii->suspend = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id rt_match_table[] = {
|
||||
{.compatible = "rt,rt5036-irq",},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver rt5036_irq_driver = {
|
||||
.driver = {
|
||||
.name = RT5036_DEV_NAME "-irq",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = rt_match_table,
|
||||
},
|
||||
.probe = rt5036_irq_probe,
|
||||
.remove = rt5036_irq_remove,
|
||||
.suspend = rt5036_irq_suspend,
|
||||
.resume = rt5036_irq_resume,
|
||||
};
|
||||
|
||||
static int __init rt5036_irq_init(void)
|
||||
{
|
||||
return platform_driver_register(&rt5036_irq_driver);
|
||||
}
|
||||
subsys_initcall_sync(rt5036_irq_init);
|
||||
|
||||
static void __exit rt5036_irq_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&rt5036_irq_driver);
|
||||
}
|
||||
module_exit(rt5036_irq_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
|
||||
MODULE_DESCRIPTION("IRQ driver for RT5036");
|
||||
MODULE_ALIAS("platform:" RT5036_DEV_NAME "-irq");
|
||||
MODULE_VERSION(RT5036_DRV_VER);
|
||||
334
drivers/mfd/rt5036-misc.c
Executable file
334
drivers/mfd/rt5036-misc.c
Executable file
|
|
@ -0,0 +1,334 @@
|
|||
/*
|
||||
* drivers/mfd/rt5036-misc.c
|
||||
* Driver for Richtek RT5036 PMIC misc option
|
||||
*
|
||||
* 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/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/power_supply.h>
|
||||
#ifdef CONFIG_MISC_RT5036_PWRKEY
|
||||
#include <linux/input.h>
|
||||
#endif /* #ifdef CONFIG_MISC_RT5036_PWRKEY */
|
||||
|
||||
#include <linux/mfd/rt5036/rt5036.h>
|
||||
#include <linux/mfd/rt5036/rt5036-misc.h>
|
||||
|
||||
static struct i2c_client *g_shdn;
|
||||
|
||||
static unsigned char misc_init_regval[] = {
|
||||
0xA8, /*REG 0x51*/
|
||||
0x96, /*REG 0x52*/
|
||||
0x48, /*REG 0x53*/
|
||||
0x00, /*REG 0x54*/
|
||||
0x06, /*REG 0x55*/
|
||||
0xA0, /*REG 0x65*/
|
||||
0xFF, /*REG 0x5A*/
|
||||
0xE0, /*REG 0x5B*/
|
||||
#ifdef CONFIG_MISC_RT5036_PWRKEY
|
||||
0x18, /*REG 0x5C*/
|
||||
#else
|
||||
0x78, /*REG 0x5C*/
|
||||
#endif /* #ifdef CONFIG_RT5036_PWRKEY */
|
||||
};
|
||||
|
||||
int rt5036_vin_exist(void)
|
||||
{
|
||||
int ret = 0;
|
||||
#ifdef CONFIG_CHARGER_RT5036
|
||||
union power_supply_propval pval;
|
||||
struct power_supply *psy = power_supply_get_by_name("rt-charger");
|
||||
|
||||
if (psy) {
|
||||
ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &pval);
|
||||
if (ret < 0)
|
||||
ret = 0;
|
||||
else
|
||||
ret = pval.intval;
|
||||
} else {
|
||||
pr_err("couldn't get rt-charger psy\n");
|
||||
}
|
||||
return ret;
|
||||
#else
|
||||
if (g_shdn)
|
||||
ret = rt5036_reg_read(g_shdn, RT5036_REG_CHGSTAT2);
|
||||
return ret < 0 ? 0 : ret & RT5036_PWRRDY_MASK;
|
||||
#endif /* #ifdef CONFIG_CHARGER_RT5036 */
|
||||
}
|
||||
EXPORT_SYMBOL(rt5036_vin_exist);
|
||||
static bool rt_pm_off;
|
||||
void rt5036_chip_shutdown(void)
|
||||
{
|
||||
if (g_shdn) {
|
||||
rt5036_set_bits(g_shdn, RT5036_REG_MISC3, RT5036_CHIPSHDN_MASK);
|
||||
rt5036_clr_bits(g_shdn, RT5036_REG_MISC3, RT5036_CHIPSHDN_MASK);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(rt5036_chip_shutdown);
|
||||
|
||||
static void rt5036_general_irq_handler(void *info, int eventno)
|
||||
{
|
||||
struct rt5036_misc_info *mi = info;
|
||||
|
||||
dev_info(mi->dev, "eventno=%02d\n", eventno);
|
||||
#ifdef CONFIG_MISC_RT5036_PWRKEY
|
||||
switch (eventno) {
|
||||
case MISCEVENT_PWRONF:
|
||||
if (!mi->pwr_key_pressed) {
|
||||
input_report_key(mi->pwr_key, KEY_POWER, 1);
|
||||
input_sync(mi->pwr_key);
|
||||
mi->pwr_key_pressed = 1;
|
||||
}
|
||||
break;
|
||||
case MISCEVENT_PWRONR:
|
||||
if (mi->pwr_key_pressed) {
|
||||
input_report_key(mi->pwr_key, KEY_POWER, 0);
|
||||
input_sync(mi->pwr_key);
|
||||
mi->pwr_key_pressed = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif /* #ifdef CONFIG_MISC_RT5036_PWRKEY */
|
||||
}
|
||||
|
||||
static rt_irq_handler rt_miscirq_handler[MISCEVENT_MAX] = {
|
||||
[MISCEVENT_PWRONLP] = rt5036_general_irq_handler,
|
||||
[MISCEVENT_PWRONSP] = rt5036_general_irq_handler,
|
||||
[MISCEVENT_PWRONF] = rt5036_general_irq_handler,
|
||||
[MISCEVENT_PWRONR] = rt5036_general_irq_handler,
|
||||
[MISCEVENT_KPSHDN] = rt5036_general_irq_handler,
|
||||
[MISCEVENT_VDDALV] = rt5036_general_irq_handler,
|
||||
[MISCEVNET_OTM] = rt5036_general_irq_handler,
|
||||
[MISCEVENT_PMICSYSLV] = rt5036_general_irq_handler,
|
||||
[MISCEVENT_LSW2LV] = rt5036_general_irq_handler,
|
||||
[MISCEVENT_LSW1LV] = rt5036_general_irq_handler,
|
||||
[MISCEVENT_LDO4LV] = rt5036_general_irq_handler,
|
||||
[MISCEVENT_LDO3LV] = rt5036_general_irq_handler,
|
||||
[MISCEVENT_LDO2LV] = rt5036_general_irq_handler,
|
||||
[MISCEVENT_LDO1LV] = rt5036_general_irq_handler,
|
||||
[MISCEVENT_BUCK4LV] = rt5036_general_irq_handler,
|
||||
[MISCEVENT_BUCK3LV] = rt5036_general_irq_handler,
|
||||
[MISCEVENT_BUCK2LV] = rt5036_general_irq_handler,
|
||||
[MISCEVENT_BUCK1LV] = rt5036_general_irq_handler,
|
||||
};
|
||||
|
||||
void rt5036_misc_irq_handler(struct rt5036_misc_info *mi, unsigned int irqevent)
|
||||
{
|
||||
int i;
|
||||
unsigned int masked_irq_event =
|
||||
(misc_init_regval[6] << 16) | (misc_init_regval[7] << 8) |
|
||||
misc_init_regval[8];
|
||||
unsigned int final_irq_event = irqevent & (~masked_irq_event);
|
||||
|
||||
for (i = 0; i < MISCEVENT_MAX; i++) {
|
||||
if ((final_irq_event & (1 << i)) && rt_miscirq_handler[i])
|
||||
rt_miscirq_handler[i] (mi, i);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(rt5036_misc_irq_handler);
|
||||
|
||||
static int rt5036_misc_reginit(struct i2c_client *i2c)
|
||||
{
|
||||
rt5036_reg_write(i2c, RT5036_REG_MISC6, misc_init_regval[5]);
|
||||
rt5036_reg_block_write(i2c, RT5036_REG_MISC1, 5, misc_init_regval);
|
||||
rt5036_reg_block_write(i2c, RT5036_REG_BUCKLDOIRQMASK,
|
||||
3, &misc_init_regval[6]);
|
||||
/*always clear at the first time*/
|
||||
rt5036_reg_read(i2c, RT5036_REG_BUCKLDOIRQ);
|
||||
rt5036_reg_read(i2c, RT5036_REG_LSWBASEIRQ);
|
||||
rt5036_reg_read(i2c, RT5036_REG_PWRKEYIRQ);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt_parse_dt(struct rt5036_misc_info *mi,
|
||||
struct device *dev)
|
||||
{
|
||||
#ifdef CONFIG_OF
|
||||
struct device_node *np = dev->of_node;
|
||||
u32 val;
|
||||
|
||||
if (of_property_read_u32(np, "rt,shdn_press", &val)) {
|
||||
dev_info(dev,
|
||||
"no shut_lpress property, use the default value\n");
|
||||
} else {
|
||||
if (val > RT5036_SHDNPRESS_MASK)
|
||||
val = RT5036_SHDNPRESS_MAX;
|
||||
misc_init_regval[1] &= (~RT5036_SHDNPRESS_MASK);
|
||||
misc_init_regval[1] |= (val << RT5036_SHDNPRESS_SHIFT);
|
||||
}
|
||||
|
||||
if (of_property_read_u32(np, "rt,stb_en", &val)) {
|
||||
dev_info(dev, "no stb_en prpperty , use the default value\n");
|
||||
} else {
|
||||
if (val > RT5036_STB_MAX)
|
||||
val = RT5036_STB_MAX;
|
||||
misc_init_regval[2] &= (~RT5036_STBEN_MASK);
|
||||
misc_init_regval[2] |= (val << RT5036_STBEN_SHIFT);
|
||||
}
|
||||
|
||||
if (of_property_read_bool(np, "rt,lp_enshdn"))
|
||||
misc_init_regval[4] |= RT5036_LPSHDNEN_MASK;
|
||||
else
|
||||
misc_init_regval[4] &= (~RT5036_LPSHDNEN_MASK);
|
||||
|
||||
if (of_property_read_u32(np, "rt,vsysuvlo", &val)) {
|
||||
dev_info(dev, "no vsysuvlo prpperty , use the default value\n");
|
||||
} else {
|
||||
if (val > RT5036_SYSLV_MAX)
|
||||
val = RT5036_SYSLV_MAX;
|
||||
misc_init_regval[5] &= (~RT5036_SYSUVLO_MASK);
|
||||
misc_init_regval[5] |= (val << RT5036_SYSUVLO_SHIFT);
|
||||
}
|
||||
|
||||
if (of_property_read_bool(np, "rt,syslv_enshdn"))
|
||||
misc_init_regval[4] |= RT5036_SYSLVENSHDN_MASK;
|
||||
else
|
||||
misc_init_regval[4] &= (~RT5036_SYSLVENSHDN_MASK);
|
||||
|
||||
rt_pm_off = of_property_read_bool(np, "rt,system-power-controller");
|
||||
#endif /* #ifdef CONFIG_OF */
|
||||
rt5036_misc_reginit(mi->i2c);
|
||||
RTINFO("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt_parse_pdata(struct rt5036_misc_info *mi,
|
||||
struct device *dev)
|
||||
{
|
||||
struct rt5036_misc_data *misc_pdata = dev->platform_data;
|
||||
/*SHDN_PRESS_TIME property*/
|
||||
misc_init_regval[1] &= (~RT5036_SHDNPRESS_MASK);
|
||||
misc_init_regval[1] |=
|
||||
(misc_pdata->shdn_press << RT5036_SHDNPRESS_SHIFT);
|
||||
/*STB_EN property*/
|
||||
misc_init_regval[2] &= (~RT5036_STBEN_MASK);
|
||||
misc_init_regval[2] |= (misc_pdata->stb_en << RT5036_STBEN_SHIFT);
|
||||
/*LP_ENSHEN property*/
|
||||
if (misc_pdata->lp_enshdn)
|
||||
misc_init_regval[4] |= RT5036_LPSHDNEN_MASK;
|
||||
else
|
||||
misc_init_regval[4] &= (~RT5036_LPSHDNEN_MASK);
|
||||
|
||||
misc_init_regval[5] &= (~RT5036_SYSUVLO_MASK);
|
||||
misc_init_regval[5] |= (misc_pdata->vsysuvlo << RT5036_SYSUVLO_SHIFT);
|
||||
|
||||
if (misc_pdata->syslv_enshdn)
|
||||
misc_init_regval[4] |= RT5036_SYSLVENSHDN_MASK;
|
||||
else
|
||||
misc_init_regval[4] &= (~RT5036_SYSLVENSHDN_MASK);
|
||||
|
||||
rt5036_misc_reginit(mi->i2c);
|
||||
RTINFO("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5036_misc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rt5036_chip *chip = dev_get_drvdata(pdev->dev.parent);
|
||||
struct rt5036_platform_data *pdata = (pdev->dev.parent)->platform_data;
|
||||
struct rt5036_misc_info *mi;
|
||||
bool use_dt = pdev->dev.of_node;
|
||||
|
||||
mi = devm_kzalloc(&pdev->dev, sizeof(*mi), GFP_KERNEL);
|
||||
if (!mi)
|
||||
return -ENOMEM;
|
||||
|
||||
mi->i2c = chip->i2c;
|
||||
if (use_dt) {
|
||||
rt_parse_dt(mi, &pdev->dev);
|
||||
} else {
|
||||
if (!pdata)
|
||||
goto out_dev;
|
||||
pdev->dev.platform_data = pdata->misc_pdata;
|
||||
rt_parse_pdata(mi, &pdev->dev);
|
||||
}
|
||||
#ifdef CONFIG_MISC_RT5036_PWRKEY
|
||||
mi->pwr_key = input_allocate_device();
|
||||
if (!mi->pwr_key) {
|
||||
dev_err(&pdev->dev, "Allocate pwr_key input fail\n");
|
||||
goto out_dev;
|
||||
}
|
||||
input_set_capability(mi->pwr_key, EV_KEY, KEY_POWER);
|
||||
mi->pwr_key->name = "rt5036_pwr_key";
|
||||
mi->pwr_key->phys = "rt5036_pwr_key/input0";
|
||||
mi->pwr_key->dev.parent = &pdev->dev;
|
||||
if (input_register_device(mi->pwr_key)) {
|
||||
dev_err(&pdev->dev, "register pwr key fail\n");
|
||||
goto free_input;
|
||||
}
|
||||
#endif /* #ifdef CONFIG_MISC_RT5036_PWRKEY */
|
||||
mi->dev = &pdev->dev;
|
||||
g_shdn = mi->i2c;
|
||||
chip->misc_info = mi;
|
||||
platform_set_drvdata(pdev, mi);
|
||||
|
||||
if (rt_pm_off && !pm_power_off)
|
||||
pm_power_off = rt5036_chip_shutdown;
|
||||
|
||||
dev_info(&pdev->dev, "driver successfully loaded\n");
|
||||
return 0;
|
||||
#ifdef CONFIG_MISC_RT5036_PWRKEY
|
||||
free_input:
|
||||
input_free_device(mi->pwr_key);
|
||||
#endif /* #ifdef CONFIG_MISC_RT5036_PWRKEY */
|
||||
out_dev:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int rt5036_misc_remove(struct platform_device *pdev)
|
||||
{
|
||||
#ifdef CONFIG_MISC_RT5036_PWRKEY
|
||||
struct rt5036_misc_info *mi = platform_get_drvdata(pdev);
|
||||
|
||||
input_unregister_device(mi->pwr_key);
|
||||
input_free_device(mi->pwr_key);
|
||||
#endif /* #ifdef CONFIG_MISC_RT5036_PWRKEY */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id rt_match_table[] = {
|
||||
{.compatible = "rt,rt5036-misc",},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver rt5036_misc_driver = {
|
||||
.driver = {
|
||||
.name = RT5036_DEV_NAME "-misc",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = rt_match_table,
|
||||
},
|
||||
.probe = rt5036_misc_probe,
|
||||
.remove = rt5036_misc_remove,
|
||||
};
|
||||
|
||||
static int __init rt5036_misc_init(void)
|
||||
{
|
||||
return platform_driver_register(&rt5036_misc_driver);
|
||||
}
|
||||
subsys_initcall(rt5036_misc_init);
|
||||
|
||||
static void __exit rt5036_misc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&rt5036_misc_driver);
|
||||
}
|
||||
module_exit(rt5036_misc_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
|
||||
MODULE_DESCRIPTION("Misc driver for RT5036");
|
||||
MODULE_ALIAS("platform:" RT5036_DEV_NAME "-misc");
|
||||
MODULE_VERSION(RT5036_DRV_VER);
|
||||
|
|
@ -71,21 +71,6 @@ config CHARGER_RT5025
|
|||
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
|
||||
|
|
@ -100,6 +85,34 @@ config RT_JEITA_REMOVE
|
|||
help
|
||||
Say Y here to remove Jeita function.
|
||||
|
||||
config CHARGER_RT5036
|
||||
bool "RT5036 charger support"
|
||||
depends on MFD_RT5036
|
||||
default n
|
||||
help
|
||||
Say Y here to enable support for RT5036 chip charger subdevice.
|
||||
|
||||
config RT_POWER
|
||||
bool "RT PMIC cable report"
|
||||
depends on CHARGER_RT5036 || 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 RT_BATTERY
|
||||
bool "RT Test Battery"
|
||||
depends on CHARGER_RT5036
|
||||
default n
|
||||
help
|
||||
Enable Test Battery report.
|
||||
|
||||
config BATTERY_RICOH619
|
||||
tristate "Ricoh RC5T619 PMIC battery driver"
|
||||
|
|
|
|||
|
|
@ -63,3 +63,5 @@ 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
|
||||
obj-$(CONFIG_CHARGER_RT5036) += rt5036-charger.o
|
||||
obj-$(CONFIG_RT_BATTERY) += rt-battery.o
|
||||
|
|
|
|||
189
drivers/power/rt-battery.c
Executable file
189
drivers/power/rt-battery.c
Executable file
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* drivers/power/rt-battery.c
|
||||
* Driver for Richtek RT Test Battery 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/power/rt-battery.h>
|
||||
|
||||
struct rt_battery_info {
|
||||
struct device *dev;
|
||||
struct power_supply psy;
|
||||
int chg_status;
|
||||
unsigned char batt_present:1;
|
||||
unsigned char suspend:1;
|
||||
};
|
||||
|
||||
static enum power_supply_property rt_battery_props[] = {
|
||||
POWER_SUPPLY_PROP_STATUS,
|
||||
POWER_SUPPLY_PROP_HEALTH,
|
||||
POWER_SUPPLY_PROP_PRESENT,
|
||||
POWER_SUPPLY_PROP_ONLINE,
|
||||
POWER_SUPPLY_PROP_CAPACITY,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
||||
};
|
||||
|
||||
static int rt_battery_set_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
const union power_supply_propval *val)
|
||||
{
|
||||
struct rt_battery_info *rbi = dev_get_drvdata(psy->dev->parent);
|
||||
int ret = 0;
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_STATUS:
|
||||
rbi->chg_status = val->intval;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_PRESENT:
|
||||
rbi->batt_present = val->intval;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
||||
case POWER_SUPPLY_PROP_HEALTH:
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
case POWER_SUPPLY_PROP_CAPACITY:
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rt_battery_get_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
union power_supply_propval *val)
|
||||
{
|
||||
struct rt_battery_info *rbi = dev_get_drvdata(psy->dev->parent);
|
||||
int ret = 0;
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_STATUS:
|
||||
val->intval = rbi->chg_status;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_HEALTH:
|
||||
val->intval = POWER_SUPPLY_HEALTH_GOOD;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_PRESENT:
|
||||
val->intval = rbi->batt_present;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
val->intval = 1;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
||||
val->intval = 4000 * 1000;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CAPACITY:
|
||||
if (rbi->chg_status == POWER_SUPPLY_STATUS_FULL)
|
||||
val->intval = 100;
|
||||
else
|
||||
val->intval = 50;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rt_battery_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rt_battery_info *rbi;
|
||||
int ret;
|
||||
|
||||
rbi = devm_kzalloc(&pdev->dev, sizeof(*rbi), GFP_KERNEL);
|
||||
if (!rbi)
|
||||
return -ENOMEM;
|
||||
rbi->dev = &pdev->dev;
|
||||
rbi->chg_status = POWER_SUPPLY_STATUS_DISCHARGING;
|
||||
rbi->batt_present = 1;
|
||||
platform_set_drvdata(pdev, rbi);
|
||||
|
||||
rbi->psy.name = RT_BATT_NAME;
|
||||
rbi->psy.type = POWER_SUPPLY_TYPE_BATTERY;
|
||||
rbi->psy.set_property = rt_battery_set_property;
|
||||
rbi->psy.get_property = rt_battery_get_property;
|
||||
rbi->psy.properties = rt_battery_props;
|
||||
rbi->psy.num_properties = ARRAY_SIZE(rt_battery_props);
|
||||
ret = power_supply_register(&pdev->dev, &rbi->psy);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "battery supply registered fail\n");
|
||||
goto out_dev;
|
||||
}
|
||||
dev_info(&pdev->dev, "driver successfully loaded\n");
|
||||
return 0;
|
||||
out_dev:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rt_battery_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rt_battery_info *rbi = platform_get_drvdata(pdev);
|
||||
|
||||
power_supply_unregister(&rbi->psy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt_battery_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
struct rt_battery_info *rbi = platform_get_drvdata(pdev);
|
||||
|
||||
rbi->suspend = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt_battery_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct rt_battery_info *rbi = platform_get_drvdata(pdev);
|
||||
|
||||
rbi->suspend = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id rt_match_table[] = {
|
||||
{.compatible = "rt,rt-battery",},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver rt_battery_driver = {
|
||||
.driver = {
|
||||
.name = "rt-battery",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = rt_match_table,
|
||||
},
|
||||
.probe = rt_battery_probe,
|
||||
.remove = rt_battery_remove,
|
||||
.suspend = rt_battery_suspend,
|
||||
.resume = rt_battery_resume,
|
||||
};
|
||||
|
||||
static int __init rt_battery_init(void)
|
||||
{
|
||||
return platform_driver_register(&rt_battery_driver);
|
||||
}
|
||||
subsys_initcall(rt_battery_init);
|
||||
|
||||
static void __exit rt_battery_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&rt_battery_driver);
|
||||
}
|
||||
module_exit(rt_battery_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("CY Huang <cy_huang@richtek.com>");
|
||||
MODULE_DESCRIPTION("RT Test Battery driver");
|
||||
MODULE_ALIAS("platform:rt-battery");
|
||||
MODULE_VERSION("1.0.0_G");
|
||||
153
drivers/power/rt-power.c
Executable file → Normal file
153
drivers/power/rt-power.c
Executable file → Normal file
|
|
@ -58,135 +58,164 @@ static int rtpower_set_charger(struct rt_power_info *pi)
|
|||
|
||||
chg_psy = power_supply_get_by_name("rt-charger");
|
||||
if (chg_psy) {
|
||||
rc = chg_psy->get_property(chg_psy, POWER_SUPPLY_PROP_ONLINE, &pval);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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,\
|
||||
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");
|
||||
dev_err(pi->dev,
|
||||
"set chg voltage fail\n");
|
||||
pval.intval = 1;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_ONLINE,\
|
||||
rc = chg_psy->set_property(chg_psy,
|
||||
POWER_SUPPLY_PROP_ONLINE,
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set charger online fail\n");
|
||||
dev_err(pi->dev,
|
||||
"set charger online fail\n");
|
||||
}
|
||||
pval.intval = 1;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_PRESENT,\
|
||||
&pval);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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");
|
||||
dev_err(pi->dev,
|
||||
"set chg voltage fail\n");
|
||||
pval.intval = 1;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_ONLINE,\
|
||||
&pval);
|
||||
rc = chg_psy->set_property(chg_psy,
|
||||
POWER_SUPPLY_PROP_ONLINE,
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set charger online fail\n");
|
||||
dev_err(pi->dev,
|
||||
"set charger online fail\n");
|
||||
}
|
||||
pval.intval = 1;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_PRESENT,\
|
||||
&pval);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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");
|
||||
dev_err(pi->dev,
|
||||
"set chg voltage fail\n");
|
||||
pval.intval = 1;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_ONLINE,\
|
||||
&pval);
|
||||
rc = chg_psy->set_property(chg_psy,
|
||||
POWER_SUPPLY_PROP_ONLINE,
|
||||
&pval);
|
||||
if (rc < 0)
|
||||
dev_err(pi->dev, "set charger online fail\n");
|
||||
dev_err(pi->dev,
|
||||
"set charger online fail\n");
|
||||
}
|
||||
pval.intval = 1;
|
||||
rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_PRESENT,\
|
||||
&pval);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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");
|
||||
}
|
||||
|
|
@ -198,8 +227,9 @@ static int rtpower_set_charger(struct rt_power_info *pi)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int rtpower_get_property(struct power_supply *psy, enum power_supply_property psp, \
|
||||
union power_supply_propval *val)
|
||||
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;
|
||||
|
|
@ -207,7 +237,8 @@ static int rtpower_get_property(struct power_supply *psy, enum power_supply_prop
|
|||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
if (psy->type == POWER_SUPPLY_TYPE_MAINS)
|
||||
val->intval = (pi->ac_online || pi->usbta_online)?1 : 0;
|
||||
val->intval = (pi->ac_online
|
||||
|| pi->usbta_online) ? 1 : 0;
|
||||
else if (psy->type == POWER_SUPPLY_TYPE_USB)
|
||||
val->intval = pi->usb_online;
|
||||
else
|
||||
|
|
@ -220,7 +251,8 @@ static int rtpower_get_property(struct power_supply *psy, enum power_supply_prop
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int rtpower_set_property(struct power_supply *psy, enum power_supply_property psp, \
|
||||
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);
|
||||
|
|
@ -239,13 +271,16 @@ static int rtpower_set_property(struct power_supply *psy, enum power_supply_prop
|
|||
if (val->intval) {
|
||||
pi->usbcnt = 0;
|
||||
wake_lock(&pi->usbdet_wakelock);
|
||||
schedule_delayed_work(&pi->usbdet_work, 1*HZ);
|
||||
schedule_delayed_work(&pi->usbdet_work,
|
||||
1 * HZ);
|
||||
} else {
|
||||
pi->usbcnt = RT_USBCNT_MAX;
|
||||
schedule_delayed_work(&pi->usbdet_work, 0);
|
||||
schedule_delayed_work(&pi->usbdet_work,
|
||||
0);
|
||||
if (pi->usbta_online) {
|
||||
pi->usbta_online = 0;
|
||||
power_supply_changed(&pi->ac_psy);
|
||||
power_supply_changed
|
||||
(&pi->ac_psy);
|
||||
}
|
||||
}
|
||||
rc = rtpower_set_charger(pi);
|
||||
|
|
|
|||
1234
drivers/power/rt5036-charger.c
Executable file
1234
drivers/power/rt5036-charger.c
Executable file
File diff suppressed because it is too large
Load Diff
|
|
@ -269,6 +269,12 @@ config REGULATOR_RT5025
|
|||
help
|
||||
This driver supports voltage regulator in RT5025 PMIC chips.
|
||||
|
||||
config REGULATOR_RT5036
|
||||
bool "RT5036 regulator support"
|
||||
depends on MFD_RT5036
|
||||
help
|
||||
This driver support voltage regulator in Richtek RT5036.
|
||||
|
||||
config ROCKCHIP_PWM_REGULATOR
|
||||
tristate "rockchip pwm voltage regulator for discrete dcdc or ldo"
|
||||
help
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ 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_REGULATOR_RT5036) += rt5036-regulator.o
|
||||
|
||||
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip_io_vol_domain.o
|
||||
|
||||
|
|
|
|||
665
drivers/regulator/rt5036-regulator.c
Normal file
665
drivers/regulator/rt5036-regulator.c
Normal file
|
|
@ -0,0 +1,665 @@
|
|||
/*
|
||||
* drivers/regulator/rt5036-regulator.c
|
||||
* Driver for Richtek RT5036 PMIC Regulator
|
||||
*
|
||||
* 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/err.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/platform_device.h>
|
||||
#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/rt5036/rt5036.h>
|
||||
#include <linux/regulator/rt5036-regulator.h>
|
||||
|
||||
struct rt5036_regulator_info {
|
||||
struct regulator_desc desc;
|
||||
struct regulator_dev *regulator;
|
||||
struct i2c_client *i2c;
|
||||
const unsigned int *vol_output_list;
|
||||
const int vol_output_size;
|
||||
int min_uV;
|
||||
int max_uV;
|
||||
unsigned char nvol_reg;
|
||||
unsigned char nvol_shift;
|
||||
unsigned char nvol_mask;
|
||||
unsigned char nenable_reg;
|
||||
unsigned char nenable_bit;
|
||||
unsigned char nmode_reg;
|
||||
unsigned char nmode_bit;
|
||||
unsigned char nramp_reg;
|
||||
unsigned char nramp_bit;
|
||||
unsigned char nramp_shift;
|
||||
unsigned char svol_reg;
|
||||
unsigned char svol_shift;
|
||||
unsigned char svol_mask;
|
||||
unsigned char senable_reg;
|
||||
unsigned char senable_bit;
|
||||
unsigned char smode_reg;
|
||||
unsigned char smode_bit;
|
||||
unsigned char sramp_reg;
|
||||
unsigned char sramp_bit;
|
||||
unsigned char sramp_shift;
|
||||
};
|
||||
|
||||
/*For DCDC1~4 and LDO1~4 and LSW1~2*/
|
||||
static const unsigned int rt5036_vol_output_list[] = {
|
||||
/*0~7 */
|
||||
800 * 1000, 825 * 1000, 850 * 1000, 875 * 1000, 900 * 1000, 925 * 1000,
|
||||
950 * 1000, 975 * 1000,
|
||||
/*8~15 */
|
||||
1000 * 1000, 1025 * 1000, 1050 * 1000, 1075 * 1000, 1100 * 1000,
|
||||
1125 * 1000, 1150 * 1000, 1175 * 1000,
|
||||
/*16~23 */
|
||||
1200 * 1000, 1225 * 1000, 1250 * 1000, 1275 * 1000, 1300 * 1000,
|
||||
1325 * 1000, 1350 * 1000, 1375 * 1000,
|
||||
/*24~31 */
|
||||
1400 * 1000, 1425 * 1000, 1450 * 1000, 1475 * 1000, 1500 * 1000,
|
||||
1525 * 1000, 1550 * 1000, 1575 * 1000,
|
||||
/*32~39 */
|
||||
1600 * 1000, 1625 * 1000, 1650 * 1000, 1675 * 1000, 1700 * 1000,
|
||||
1725 * 1000, 1750 * 1000, 1775 * 1000,
|
||||
/*40~47 */
|
||||
1800 * 1000, 1825 * 1000, 1850 * 1000, 1875 * 1000, 1900 * 1000,
|
||||
1925 * 1000, 1950 * 1000, 1975 * 1000,
|
||||
/*48~55 */
|
||||
2000 * 1000, 2025 * 1000, 2050 * 1000, 2075 * 1000, 2100 * 1000,
|
||||
2125 * 1000, 2150 * 1000, 2175 * 1000,
|
||||
/*56~63 */
|
||||
2200 * 1000, 2225 * 1000, 2250 * 1000, 2275 * 1000, 2300 * 1000,
|
||||
2325 * 1000, 2350 * 1000, 2375 * 1000,
|
||||
/*64~71 */
|
||||
2400 * 1000, 2425 * 1000, 2450 * 1000, 2475 * 1000, 2500 * 1000,
|
||||
2525 * 1000, 2550 * 1000, 2575 * 1000,
|
||||
/*72~79 */
|
||||
2600 * 1000, 2625 * 1000, 2650 * 1000, 2675 * 1000, 2700 * 1000,
|
||||
2725 * 1000, 2750 * 1000, 2775 * 1000,
|
||||
/*80~87 */
|
||||
2800 * 1000, 2825 * 1000, 2850 * 1000, 2875 * 1000, 2900 * 1000,
|
||||
2925 * 1000, 2950 * 1000, 2975 * 1000,
|
||||
/*88~95 */
|
||||
3000 * 1000, 3025 * 1000, 3050 * 1000, 3075 * 1000, 3100 * 1000,
|
||||
3125 * 1000, 3150 * 1000, 3175 * 1000,
|
||||
/*96~103 */
|
||||
3200 * 1000, 3225 * 1000, 3250 * 1000, 3275 * 1000, 3300 * 1000,
|
||||
3300 * 1000, 3300 * 1000, 3300 * 1000,
|
||||
/*104~111 */
|
||||
3300 * 1000, 3300 * 1000, 3300 * 1000, 3300 * 1000, 3300 * 1000,
|
||||
3300 * 1000, 3300 * 1000, 3300 * 1000,
|
||||
/*112~119 */
|
||||
3300 * 1000, 3300 * 1000, 3300 * 1000, 3300 * 1000, 3300 * 1000,
|
||||
3300 * 1000, 3300 * 1000, 3300 * 1000,
|
||||
/*120~127 */
|
||||
3300 * 1000, 3300 * 1000, 3300 * 1000, 3300 * 1000, 3300 * 1000,
|
||||
3300 * 1000, 3300 * 1000, 3300 * 1000,
|
||||
};
|
||||
|
||||
#define rt5036_vol_output_size ARRAY_SIZE(rt5036_vol_output_list)
|
||||
|
||||
static inline int check_range(struct rt5036_regulator_info *info,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
if (min_uV < info->min_uV || min_uV > info->max_uV)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5036_list_voltage(struct regulator_dev *rdev, unsigned index)
|
||||
{
|
||||
struct rt5036_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
|
||||
return (index >= info->vol_output_size) ?
|
||||
-EINVAL : info->vol_output_list[index];
|
||||
}
|
||||
|
||||
static int rt5036_find_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
struct rt5036_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
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))
|
||||
return i;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38))
|
||||
static int rt5036_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
|
||||
{
|
||||
struct rt5036_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
unsigned char data;
|
||||
const int count = info->vol_output_size;
|
||||
|
||||
if (selector > count)
|
||||
return -EINVAL;
|
||||
data = (unsigned char)selector;
|
||||
data <<= info->nvol_shift;
|
||||
return rt5036_assign_bits(info->i2c, info->nvol_reg, info->nvol_mask,
|
||||
data);
|
||||
}
|
||||
|
||||
static int rt5036_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
struct rt5036_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
|
||||
ret = rt5036_reg_read(info->i2c, info->nvol_reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return (ret & info->nvol_mask) >> info->nvol_shift;
|
||||
}
|
||||
#else
|
||||
|
||||
static int rt5036_set_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV, unsigned *selector)
|
||||
{
|
||||
struct rt5036_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
unsigned char data;
|
||||
|
||||
if (check_range(info, min_uV, max_uV)) {
|
||||
dev_err(&rdev->dev, "invalid voltage range (%d, %d) uV\n",
|
||||
min_uV, max_uV);
|
||||
return -EINVAL;
|
||||
}
|
||||
data = rt5036_find_voltage(rdev, min_uV, max_uV);
|
||||
data <<= info->nvol_shift;
|
||||
return rt5036_assign_bits(info->i2c, info->nvol_reg, info->nvol_mask,
|
||||
data);
|
||||
}
|
||||
|
||||
static int rt5036_get_voltage(struct regulator_dev *rdev)
|
||||
{
|
||||
struct rt5036_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
|
||||
ret = rt5036_reg_read(info->i2c, info->nvol_reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = (ret & info->nvol_mask) >> info->nvol_shift;
|
||||
return rt5036_list_voltage(rdev, ret);
|
||||
}
|
||||
#endif /* LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,38) */
|
||||
|
||||
static int rt5036_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct rt5036_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
|
||||
return rt5036_set_bits(info->i2c, info->nenable_reg, info->nenable_bit);
|
||||
}
|
||||
|
||||
static int rt5036_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct rt5036_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
|
||||
return rt5036_clr_bits(info->i2c, info->nenable_reg, info->nenable_bit);
|
||||
}
|
||||
|
||||
static int rt5036_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
struct rt5036_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
|
||||
ret = rt5036_reg_read(info->i2c, info->nenable_reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return (ret & info->nenable_bit) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int rt5036_set_mode(struct regulator_dev *rdev, unsigned int mode)
|
||||
{
|
||||
struct rt5036_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
ret =
|
||||
rt5036_set_bits(info->i2c, info->nmode_reg,
|
||||
info->nmode_bit);
|
||||
break;
|
||||
case REGULATOR_MODE_FAST:
|
||||
ret =
|
||||
rt5036_clr_bits(info->i2c, info->nmode_reg,
|
||||
info->nmode_bit);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned int rt5036_get_mode(struct regulator_dev *rdev)
|
||||
{
|
||||
struct rt5036_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
unsigned int mode;
|
||||
int data;
|
||||
|
||||
data = rt5036_reg_read(info->i2c, info->nmode_reg);
|
||||
mode =
|
||||
(data & info->nmode_bit) ? REGULATOR_MODE_NORMAL :
|
||||
REGULATOR_MODE_FAST;
|
||||
return mode;
|
||||
}
|
||||
|
||||
static int rt5036_set_suspend_voltage(struct regulator_dev *rdev, int uV)
|
||||
{
|
||||
struct rt5036_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
unsigned char data;
|
||||
|
||||
if (check_range(info, uV, uV)) {
|
||||
dev_err(&rdev->dev, "invalid voltage range (%d, %d) uV\n",
|
||||
uV, uV);
|
||||
return -EINVAL;
|
||||
}
|
||||
data = rt5036_find_voltage(rdev, uV, uV);
|
||||
data <<= info->svol_shift;
|
||||
return rt5036_assign_bits(info->i2c, info->svol_reg, info->svol_mask,
|
||||
data);
|
||||
}
|
||||
|
||||
static int rt5036_set_suspend_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct rt5036_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
|
||||
return rt5036_set_bits(info->i2c, info->senable_reg, info->senable_bit);
|
||||
}
|
||||
|
||||
static int rt5036_set_suspend_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct rt5036_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
|
||||
return rt5036_clr_bits(info->i2c, info->senable_reg, info->senable_bit);
|
||||
}
|
||||
|
||||
static int rt5036_set_suspend_mode(struct regulator_dev *rdev,
|
||||
unsigned int mode)
|
||||
{
|
||||
struct rt5036_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
ret =
|
||||
rt5036_set_bits(info->i2c, info->smode_reg,
|
||||
info->smode_bit);
|
||||
break;
|
||||
case REGULATOR_MODE_FAST:
|
||||
ret =
|
||||
rt5036_clr_bits(info->i2c, info->smode_reg,
|
||||
info->smode_bit);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct regulator_ops rt5036_regulator_ops = {
|
||||
.list_voltage = rt5036_list_voltage,
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38))
|
||||
.get_voltage_sel = rt5036_get_voltage_sel,
|
||||
.set_voltage_sel = rt5036_set_voltage_sel,
|
||||
#else
|
||||
.set_voltage = rt5036_set_voltage,
|
||||
.get_voltage = rt5036_get_voltage,
|
||||
#endif /* LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,38) */
|
||||
.enable = rt5036_enable,
|
||||
.disable = rt5036_disable,
|
||||
.is_enabled = rt5036_is_enabled,
|
||||
.set_mode = rt5036_set_mode,
|
||||
.get_mode = rt5036_get_mode,
|
||||
.set_suspend_voltage = rt5036_set_suspend_voltage,
|
||||
.set_suspend_enable = rt5036_set_suspend_enable,
|
||||
.set_suspend_disable = rt5036_set_suspend_disable,
|
||||
.set_suspend_mode = rt5036_set_suspend_mode,
|
||||
};
|
||||
|
||||
#define RT5036_VOUT_LIST rt5036_vol_output_list
|
||||
#define RT5036_VOUT_SIZE rt5036_vol_output_size
|
||||
|
||||
#define RT5036_DCDC(_id, min, max) \
|
||||
{ \
|
||||
.desc = { \
|
||||
.name = "rt5036-dcdc" #_id, \
|
||||
.n_voltages = RT5036_VOUT_SIZE, \
|
||||
.ops = &rt5036_regulator_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.id = RT5036_ID_DCDC##_id, \
|
||||
.owner = THIS_MODULE, \
|
||||
}, \
|
||||
.vol_output_list = RT5036_VOUT_LIST, \
|
||||
.vol_output_size = RT5036_VOUT_SIZE, \
|
||||
.min_uV = min * 1000, \
|
||||
.max_uV = max * 1000, \
|
||||
.nvol_reg = RT5036_REG_BUCKVN##_id, \
|
||||
.nvol_shift = RT5036_DCDCVOUT_SHIFT##_id, \
|
||||
.nvol_mask = RT5036_DCDCVOUT_MASK##_id, \
|
||||
.nenable_reg = RT5036_REG_BUCKLDONEN, \
|
||||
.nenable_bit = RT5036_DCDCEN_MASK##_id, \
|
||||
.nmode_reg = RT5036_REG_BUCKVRCNEN, \
|
||||
.nmode_bit = RT5036_DCDCMODE_MASK##_id, \
|
||||
.nramp_reg = RT5036_REG_BUCKVRCN, \
|
||||
.nramp_bit = RT5036_DCDCRAMP_MASK##_id, \
|
||||
.nramp_shift = RT5036_DCDCRAMP_SHIFT##_id, \
|
||||
.svol_reg = RT5036_REG_BUCKVS##_id, \
|
||||
.svol_shift = RT5036_DCDCVOUT_SHIFT##_id, \
|
||||
.svol_mask = RT5036_DCDCVOUT_MASK##_id, \
|
||||
.senable_reg = RT5036_REG_BUCKLDOSEN, \
|
||||
.senable_bit = RT5036_DCDCEN_MASK##_id, \
|
||||
.smode_reg = RT5036_REG_BUCKVRCSEN, \
|
||||
.smode_bit = RT5036_DCDCMODE_MASK##_id, \
|
||||
.sramp_reg = RT5036_REG_BUCKVRCS, \
|
||||
.sramp_bit = RT5036_DCDCRAMP_MASK##_id, \
|
||||
.sramp_shift = RT5036_DCDCRAMP_SHIFT##_id, \
|
||||
}
|
||||
|
||||
#define RT5036_LDO(_id, min, max) \
|
||||
{ \
|
||||
.desc = { \
|
||||
.name = "rt5036-ldo" #_id, \
|
||||
.n_voltages = RT5036_VOUT_SIZE, \
|
||||
.ops = &rt5036_regulator_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.id = RT5036_ID_LDO##_id, \
|
||||
.owner = THIS_MODULE, \
|
||||
}, \
|
||||
.vol_output_list = RT5036_VOUT_LIST, \
|
||||
.vol_output_size = RT5036_VOUT_SIZE, \
|
||||
.min_uV = min * 1000, \
|
||||
.max_uV = max * 1000, \
|
||||
.nvol_reg = RT5036_REG_LDOVN##_id, \
|
||||
.nvol_shift = RT5036_LDOVOUT_SHIFT##_id, \
|
||||
.nvol_mask = RT5036_LDOVOUT_MASK##_id, \
|
||||
.nenable_reg = RT5036_REG_BUCKLDONEN, \
|
||||
.nenable_bit = RT5036_LDOEN_MASK##_id, \
|
||||
.nmode_reg = RT5036_REG_LDOVRCNEN, \
|
||||
.nmode_bit = RT5036_LDOMODE_MASK##_id, \
|
||||
.nramp_reg = RT5036_REG_LDOVRCN, \
|
||||
.nramp_bit = RT5036_LDORAMP_MASK##_id, \
|
||||
.nramp_shift = RT5036_LDORAMP_SHIFT##_id, \
|
||||
.svol_reg = RT5036_REG_LDOVS##_id, \
|
||||
.svol_shift = RT5036_LDOVOUT_SHIFT##_id, \
|
||||
.svol_mask = RT5036_LDOVOUT_MASK##_id, \
|
||||
.senable_reg = RT5036_REG_BUCKLDOSEN, \
|
||||
.senable_bit = RT5036_LDOEN_MASK##_id, \
|
||||
.smode_reg = RT5036_REG_LDOVRCSEN, \
|
||||
.smode_bit = RT5036_LDOMODE_MASK##_id, \
|
||||
.sramp_reg = RT5036_REG_LDOVRCS, \
|
||||
.sramp_bit = RT5036_LDORAMP_MASK##_id, \
|
||||
.sramp_shift = RT5036_LDORAMP_SHIFT##_id, \
|
||||
}
|
||||
|
||||
#define RT5036_LSW(_id, min, max) \
|
||||
{ \
|
||||
.desc = { \
|
||||
.name = "rt5036-lsw" #_id, \
|
||||
.n_voltages = RT5036_VOUT_SIZE, \
|
||||
.ops = &rt5036_regulator_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.id = RT5036_ID_LSW##_id, \
|
||||
.owner = THIS_MODULE, \
|
||||
}, \
|
||||
.vol_output_list = RT5036_VOUT_LIST, \
|
||||
.vol_output_size = RT5036_VOUT_SIZE, \
|
||||
.min_uV = min * 1000, \
|
||||
.max_uV = max * 1000, \
|
||||
.nvol_reg = RT5036_REG_LSWVN##_id, \
|
||||
.nvol_shift = RT5036_LSWVOUT_SHIFT##_id, \
|
||||
.nvol_mask = RT5036_LSWVOUT_MASK##_id, \
|
||||
.nenable_reg = RT5036_REG_LSWEN, \
|
||||
.nenable_bit = RT5036_LSWNEN_MASK##_id, \
|
||||
.nmode_reg = RT5036_REG_LSWVRCEN, \
|
||||
.nmode_bit = RT5036_LSWNMODE_MASK##_id, \
|
||||
.nramp_reg = RT5036_REG_LSWVRC, \
|
||||
.nramp_bit = RT5036_LSWNRAMP_MASK##_id, \
|
||||
.nramp_shift = RT5036_LSWNRAMP_SHIFT##_id, \
|
||||
.svol_reg = RT5036_REG_LSWVS##_id, \
|
||||
.svol_shift = RT5036_LSWVOUT_SHIFT##_id, \
|
||||
.svol_mask = RT5036_LSWVOUT_MASK##_id, \
|
||||
.senable_reg = RT5036_REG_LSWEN, \
|
||||
.senable_bit = RT5036_LSWSEN_MASK##_id, \
|
||||
.smode_reg = RT5036_REG_LSWVRCEN, \
|
||||
.smode_bit = RT5036_LSWSMODE_MASK##_id, \
|
||||
.sramp_reg = RT5036_REG_LSWVRC, \
|
||||
.sramp_bit = RT5036_LSWSRAMP_MASK##_id, \
|
||||
.sramp_shift = RT5036_LSWSRAMP_SHIFT##_id, \
|
||||
}
|
||||
|
||||
static struct rt5036_regulator_info rt5036_regulator_info[] = {
|
||||
RT5036_DCDC(1, 800, 3300),
|
||||
RT5036_DCDC(2, 800, 3300),
|
||||
RT5036_DCDC(3, 800, 3300),
|
||||
RT5036_DCDC(4, 800, 3300),
|
||||
RT5036_LDO(1, 800, 3300),
|
||||
RT5036_LDO(2, 800, 3300),
|
||||
RT5036_LDO(3, 800, 3300),
|
||||
RT5036_LDO(4, 800, 3300),
|
||||
RT5036_LSW(1, 800, 3300),
|
||||
RT5036_LSW(2, 800, 3300),
|
||||
};
|
||||
|
||||
static struct rt5036_regulator_info *find_regulator_info(int id)
|
||||
{
|
||||
struct rt5036_regulator_info *ri;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rt5036_regulator_info); i++) {
|
||||
ri = &rt5036_regulator_info[i];
|
||||
if (ri->desc.id == id)
|
||||
return ri;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline struct regulator_dev *rt5036_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,
|
||||
.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);
|
||||
#endif /* LINUX_VERSION_CODE>=KERNEL_VERSION(3,5,0)) */
|
||||
}
|
||||
|
||||
static struct regulator_init_data *rt_parse_dt(struct
|
||||
rt5036_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_KERNEL_VERSION >= KERNEL_VERSION(3,3,0)) */
|
||||
|
||||
if (init_data) {
|
||||
init_data->supply_regulator = (char *)of_get_property(np,
|
||||
"supply-regulator",
|
||||
NULL);
|
||||
rc = of_property_read_u32(np, "rt,standby_vol", &tmp);
|
||||
if (rc)
|
||||
dev_info(dev, "no standby voltage specified\n");
|
||||
else
|
||||
init_data->constraints.state_standby.uV = tmp;
|
||||
if (of_property_read_bool(np, "rt,standby_enabled")) {
|
||||
init_data->constraints.state_standby.enabled = 1;
|
||||
init_data->constraints.initial_state =
|
||||
PM_SUSPEND_STANDBY;
|
||||
}
|
||||
if (of_property_read_bool(np, "rt,standby_disabled")) {
|
||||
init_data->constraints.state_standby.disabled = 1;
|
||||
init_data->constraints.initial_state =
|
||||
PM_SUSPEND_STANDBY;
|
||||
}
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(np, "rt,nramp_sel", &tmp);
|
||||
if (rc) {
|
||||
dev_info(dev, "no nramp_sel property, use default value\n");
|
||||
} else {
|
||||
if (tmp > RT5036_RAMP_MAX)
|
||||
tmp = RT5036_RAMP_MAX;
|
||||
rt5036_assign_bits(ri->i2c, ri->nramp_reg, ri->nramp_bit,
|
||||
tmp << ri->nramp_shift);
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(np, "rt,sramp_sel", &tmp);
|
||||
if (rc) {
|
||||
dev_info(dev, "no sramp_sel property, use default value\n");
|
||||
} else {
|
||||
if (tmp > RT5036_RAMP_MAX)
|
||||
tmp = RT5036_RAMP_MAX;
|
||||
rt5036_assign_bits(ri->i2c, ri->sramp_reg, ri->sramp_bit,
|
||||
tmp << ri->sramp_shift);
|
||||
}
|
||||
|
||||
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 rt5036_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rt5036_chip *chip = dev_get_drvdata(pdev->dev.parent);
|
||||
struct rt5036_platform_data *pdata = (pdev->dev.parent)->platform_data;
|
||||
struct rt5036_regulator_info *ri;
|
||||
struct rt5036_regulator_ramp *ramp;
|
||||
struct regulator_dev *rdev;
|
||||
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;
|
||||
}
|
||||
|
||||
ri->i2c = chip->i2c;
|
||||
if (use_dt) {
|
||||
init_data = rt_parse_dt(ri, &pdev->dev);
|
||||
} else {
|
||||
if (!pdata)
|
||||
return -EINVAL;
|
||||
init_data = pdata->regulator[pdev->id];
|
||||
ramp = init_data ? init_data->driver_data : NULL;
|
||||
if (ramp) {
|
||||
rt5036_assign_bits(ri->i2c, ri->nramp_reg,
|
||||
ri->nramp_bit,
|
||||
ramp->nramp_sel << ri->nramp_shift);
|
||||
rt5036_assign_bits(ri->i2c, ri->sramp_reg,
|
||||
ri->sramp_bit,
|
||||
ramp->sramp_sel << ri->sramp_shift);
|
||||
}
|
||||
}
|
||||
|
||||
if (!init_data) {
|
||||
dev_err(&pdev->dev, "no initializing data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rdev = rt5036_regulator_register(&ri->desc, &pdev->dev, init_data, ri);
|
||||
if (IS_ERR(rdev)) {
|
||||
dev_err(&pdev->dev, "failed to register regulator %s\n",
|
||||
ri->desc.name);
|
||||
return PTR_ERR(rdev);
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, rdev);
|
||||
/*dev_info(&pdev->dev, "regulator successfully registered\n");*/
|
||||
RTINFO("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5036_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct regulator_dev *rdev = platform_get_drvdata(pdev);
|
||||
|
||||
regulator_unregister(rdev);
|
||||
RTINFO("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id rt_match_table[] = {
|
||||
{.compatible = "rt,rt5036-dcdc1",},
|
||||
{.compatible = "rt,rt5036-dcdc2",},
|
||||
{.compatible = "rt,rt5036-dcdc3",},
|
||||
{.compatible = "rt,rt5036-dcdc4",},
|
||||
{.compatible = "rt,rt5036-ldo1",},
|
||||
{.compatible = "rt,rt5036-ldo2",},
|
||||
{.compatible = "rt,rt5036-ldo3",},
|
||||
{.compatible = "rt,rt5036-ldo4",},
|
||||
{.compatible = "rt,rt5036-lsw1",},
|
||||
{.compatible = "rt,rt5036-lsw2",},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver rt5036_regulator_driver = {
|
||||
.driver = {
|
||||
.name = RT5036_DEV_NAME "-regulator",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = rt_match_table,
|
||||
},
|
||||
.probe = rt5036_regulator_probe,
|
||||
.remove = rt5036_regulator_remove,
|
||||
};
|
||||
|
||||
static int __init rt5036_regulator_init(void)
|
||||
{
|
||||
return platform_driver_register(&rt5036_regulator_driver);
|
||||
}
|
||||
subsys_initcall(rt5036_regulator_init);
|
||||
|
||||
static void __exit rt5036_regulator_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&rt5036_regulator_driver);
|
||||
}
|
||||
module_exit(rt5036_regulator_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
|
||||
MODULE_DESCRIPTION("Regulator driver for RT5036");
|
||||
MODULE_ALIAS("platform:" RT5036_DEV_NAME "-regulator");
|
||||
MODULE_VERSION(RT5036_DRV_VER);
|
||||
|
|
@ -435,6 +435,13 @@ config RK818_RTC
|
|||
help
|
||||
enable rk818 rtc for system
|
||||
|
||||
config RTC_RT5036
|
||||
bool "RT5036 RTC driver support"
|
||||
depends on MFD_RT5036
|
||||
default n
|
||||
help
|
||||
Say Y here if you want to support Richtek RT5036 RTC.
|
||||
|
||||
config RTC_DRV_TPS80031
|
||||
tristate "TI TPS80031/TPS80032 RTC driver"
|
||||
depends on MFD_TPS80031
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ obj-$(CONFIG_RTC_DRV_VT8500) += rtc-vt8500.o
|
|||
obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o
|
||||
obj-$(CONFIG_RK808_RTC) += rtc-rk808.o
|
||||
obj-$(CONFIG_RK818_RTC) += rtc-rk818.o
|
||||
obj-$(CONFIG_RTC_RT5036) += rtc-rt5036.o
|
||||
obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o
|
||||
obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
|
||||
obj-$(CONFIG_RTC_DRV_RC5T619) += rtc-ricoh619.o
|
||||
|
|
|
|||
336
drivers/rtc/rtc-rt5036.c
Executable file
336
drivers/rtc/rtc-rt5036.c
Executable file
|
|
@ -0,0 +1,336 @@
|
|||
/*
|
||||
* drivers/rtc/rt5036-rtc.c
|
||||
* Driver for Richtek RT5036 PMIC RTC 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/err.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <linux/mfd/rt5036/rt5036.h>
|
||||
#include <linux/rtc/rtc-rt5036.h>
|
||||
|
||||
static unsigned char rtc_init_regval[] = {
|
||||
0x1, /*REG 0x97*/
|
||||
0x3, /*REG 0xA5*/
|
||||
};
|
||||
|
||||
static int rt5036_read_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
struct rt5036_rtc_info *ri = dev_get_drvdata(dev);
|
||||
unsigned char val[6];
|
||||
int rc;
|
||||
|
||||
RTINFO("\n");
|
||||
rc = rt5036_reg_block_read(ri->i2c, RT5036_REG_RTCTSEC, ARRAY_SIZE(val),
|
||||
val);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "reading rtc time io error\n");
|
||||
} else {
|
||||
tm->tm_sec = val[0] & RT5036_RTC_SECMASK;
|
||||
tm->tm_min = val[1] & RT5036_RTC_MINMASK;
|
||||
tm->tm_hour = val[2] & RT5036_RTC_HOURMASK;
|
||||
tm->tm_year = (val[3] & RT5036_RTC_YEARMASK) + 100;
|
||||
tm->tm_mon = (val[4] & RT5036_RTC_MONMASK) - 1;
|
||||
tm->tm_mday = val[5] & RT5036_RTC_DAYMASK;
|
||||
RTINFO("%04d:%02d:%02d, %02d:%02d:%02d\n", tm->tm_year + 1900,
|
||||
tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min,
|
||||
tm->tm_sec);
|
||||
rc = rtc_valid_tm(tm);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "not invalid time reading from RT5036\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int rt5036_set_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
struct rt5036_rtc_info *ri = dev_get_drvdata(dev);
|
||||
unsigned char val[6];
|
||||
int rc;
|
||||
|
||||
RTINFO("\n");
|
||||
rc = rt5036_reg_block_read(ri->i2c, RT5036_REG_RTCTSEC, ARRAY_SIZE(val),
|
||||
val);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "reading rtc time io error\n");
|
||||
} else {
|
||||
val[0] &= ~RT5036_RTC_SECMASK;
|
||||
val[0] |= (tm->tm_sec & RT5036_RTC_SECMASK);
|
||||
val[1] &= ~RT5036_RTC_MINMASK;
|
||||
val[1] |= (tm->tm_min & RT5036_RTC_MINMASK);
|
||||
val[2] &= ~RT5036_RTC_HOURMASK;
|
||||
val[2] |= (tm->tm_hour & RT5036_RTC_HOURMASK);
|
||||
val[3] &= ~RT5036_RTC_YEARMASK;
|
||||
val[3] |= ((tm->tm_year - 100) & RT5036_RTC_YEARMASK);
|
||||
val[4] &= ~RT5036_RTC_MONMASK;
|
||||
val[4] |= ((tm->tm_mon + 1) & RT5036_RTC_MONMASK);
|
||||
val[5] &= ~RT5036_RTC_DAYMASK;
|
||||
val[5] |= (tm->tm_mday & RT5036_RTC_DAYMASK);
|
||||
val[5] &= ~RT5036_RTC_WEEKMASK;
|
||||
val[5] |=
|
||||
((tm->
|
||||
tm_wday & RT5036_RTC_WEEKMASK) << RT5036_RTC_WEEKSHIFT);
|
||||
RTINFO("%04d:%02d:%02d, %02d:%02d:%02d\n", tm->tm_year + 1900,
|
||||
tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min,
|
||||
tm->tm_sec);
|
||||
|
||||
if (tm->tm_year < 100)
|
||||
return -EINVAL;
|
||||
|
||||
rc = rt5036_reg_block_write(ri->i2c, RT5036_REG_RTCTSEC,
|
||||
ARRAY_SIZE(val), val);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "writing rtc time io error\n");
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int rt5036_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
|
||||
{
|
||||
struct rt5036_rtc_info *ri = dev_get_drvdata(dev);
|
||||
struct rtc_time *tm = &(alarm->time);
|
||||
unsigned char val[6];
|
||||
int rc;
|
||||
|
||||
RTINFO("\n");
|
||||
rc = rt5036_reg_block_read(ri->i2c, RT5036_REG_RTCASEC, ARRAY_SIZE(val),
|
||||
val);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "reading alarm time io error\n");
|
||||
} else {
|
||||
tm->tm_sec = val[0] & RT5036_RTC_SECMASK;
|
||||
tm->tm_min = val[1] & RT5036_RTC_MINMASK;
|
||||
tm->tm_hour = val[2] & RT5036_RTC_HOURMASK;
|
||||
tm->tm_year = (val[3] & RT5036_RTC_YEARMASK) + 100;
|
||||
tm->tm_mon = (val[4] & RT5036_RTC_MONMASK) - 1;
|
||||
tm->tm_mday = val[5] & RT5036_RTC_DAYMASK;
|
||||
RTINFO("%04d_%02d_%02d, %02d:%02d:%02d\n", tm->tm_year + 1900,
|
||||
tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min,
|
||||
tm->tm_sec);
|
||||
rc = rtc_valid_tm(tm);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "not invalid alarm reading from RT5036\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int rt5036_alarm_irq_enable(struct device *dev, unsigned int enabled);
|
||||
|
||||
static int rt5036_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
|
||||
{
|
||||
struct rt5036_rtc_info *ri = dev_get_drvdata(dev);
|
||||
struct rtc_time *tm = &alarm->time;
|
||||
unsigned char val[6];
|
||||
int rc;
|
||||
|
||||
RTINFO("\n");
|
||||
rt5036_alarm_irq_enable(ri->dev, 0);
|
||||
rc = rt5036_reg_block_read(ri->i2c, RT5036_REG_RTCASEC, ARRAY_SIZE(val),
|
||||
val);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "reading rtc time io error\n");
|
||||
} else {
|
||||
val[0] &= ~RT5036_RTC_SECMASK;
|
||||
val[0] |= (tm->tm_sec & RT5036_RTC_SECMASK);
|
||||
val[1] &= ~RT5036_RTC_MINMASK;
|
||||
val[1] |= (tm->tm_min & RT5036_RTC_MINMASK);
|
||||
val[2] &= ~RT5036_RTC_HOURMASK;
|
||||
val[2] |= (tm->tm_hour & RT5036_RTC_HOURMASK);
|
||||
val[3] &= ~RT5036_RTC_YEARMASK;
|
||||
val[3] |= ((tm->tm_year - 100) & RT5036_RTC_YEARMASK);
|
||||
val[4] &= ~RT5036_RTC_MONMASK;
|
||||
val[4] |= ((tm->tm_mon + 1) & RT5036_RTC_MONMASK);
|
||||
val[5] &= ~RT5036_RTC_DAYMASK;
|
||||
val[5] |= (tm->tm_mday & RT5036_RTC_DAYMASK);
|
||||
RTINFO("%04d:%02d:%02d, %02d:%02d:%02d\n", tm->tm_year + 1900,
|
||||
tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min,
|
||||
tm->tm_sec);
|
||||
|
||||
if (tm->tm_year < 100)
|
||||
return -EINVAL;
|
||||
|
||||
rc = rt5036_reg_block_write(ri->i2c, RT5036_REG_RTCASEC,
|
||||
ARRAY_SIZE(val), val);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "writing alarm time io error\n");
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
rt5036_alarm_irq_enable(ri->dev, alarm->enabled);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int rt5036_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
||||
{
|
||||
struct rt5036_rtc_info *ri = dev_get_drvdata(dev);
|
||||
|
||||
RTINFO("enable=%d\n", enabled);
|
||||
if (enabled) {
|
||||
rt5036_clr_bits(ri->i2c, RT5036_REG_STBWACKIRQMASK,
|
||||
RT5036_RTCAIRQ_MASK);
|
||||
rt5036_set_bits(ri->i2c, RT5036_REG_STBMODE,
|
||||
RT5036_RTCAEN_MASK);
|
||||
} else {
|
||||
rt5036_clr_bits(ri->i2c, RT5036_REG_STBMODE,
|
||||
RT5036_RTCAEN_MASK);
|
||||
rt5036_set_bits(ri->i2c, RT5036_REG_STBWACKIRQMASK,
|
||||
RT5036_RTCAIRQ_MASK);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct rtc_class_ops rt5036_rtc_ops = {
|
||||
.read_time = rt5036_read_time,
|
||||
.set_time = rt5036_set_time,
|
||||
.read_alarm = rt5036_read_alarm,
|
||||
.set_alarm = rt5036_set_alarm,
|
||||
.alarm_irq_enable = rt5036_alarm_irq_enable,
|
||||
};
|
||||
|
||||
static void rt5036_general_irq_handler(void *info, int eventno)
|
||||
{
|
||||
struct rt5036_rtc_info *ri = info;
|
||||
|
||||
dev_info(ri->dev, "eventno=%02d\n", eventno);
|
||||
switch (eventno) {
|
||||
case RTCEVENT_CAIRQ:
|
||||
rt5036_alarm_irq_enable(ri->dev, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static rt_irq_handler rt_rtcirq_handler[RTCEVENT_MAX] = {
|
||||
[RTCEVENT_CAIRQ] = rt5036_general_irq_handler,
|
||||
[RTCEVENT_CDIRQ] = rt5036_general_irq_handler,
|
||||
};
|
||||
|
||||
void rt5036_rtc_irq_handler(struct rt5036_rtc_info *ri, unsigned int irqevent)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < RTCEVENT_MAX; i++) {
|
||||
if ((irqevent & (1 << i)) && rt_rtcirq_handler[i])
|
||||
rt_rtcirq_handler[i] (ri, i);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(rt5036_rtc_irq_handler);
|
||||
|
||||
static int rt5036_rtc_reginit(struct i2c_client *i2c)
|
||||
{
|
||||
rt5036_reg_write(i2c, RT5036_REG_STBMODE, rtc_init_regval[0]);
|
||||
rt5036_reg_write(i2c, RT5036_REG_STBWACKIRQMASK, rtc_init_regval[1]);
|
||||
/*always clear at the fist time*/
|
||||
rt5036_reg_read(i2c, RT5036_REG_STBWACKIRQ);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt_parse_dt(struct rt5036_rtc_info *ri, struct device *dev)
|
||||
{
|
||||
rt5036_rtc_reginit(ri->i2c);
|
||||
RTINFO("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt_parse_pdata(struct rt5036_rtc_info *ri,
|
||||
struct device *dev)
|
||||
{
|
||||
rt5036_rtc_reginit(ri->i2c);
|
||||
RTINFO("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5036_rtc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rt5036_chip *chip = dev_get_drvdata(pdev->dev.parent);
|
||||
struct rt5036_rtc_info *ri;
|
||||
bool use_dt = pdev->dev.of_node;
|
||||
|
||||
ri = devm_kzalloc(&pdev->dev, sizeof(*ri), GFP_KERNEL);
|
||||
if (!ri)
|
||||
return -ENOMEM;
|
||||
|
||||
ri->i2c = chip->i2c;
|
||||
if (use_dt)
|
||||
rt_parse_dt(ri, &pdev->dev);
|
||||
else
|
||||
rt_parse_pdata(ri, &pdev->dev);
|
||||
|
||||
ri->dev = &pdev->dev;
|
||||
platform_set_drvdata(pdev, ri);
|
||||
|
||||
ri->rtc = rtc_device_register("rt5036-rtc", &pdev->dev,
|
||||
&rt5036_rtc_ops, THIS_MODULE);
|
||||
if (IS_ERR(ri->rtc)) {
|
||||
dev_err(&pdev->dev, "rtc device register failed\n");
|
||||
goto out_dev;
|
||||
}
|
||||
chip->rtc_info = ri;
|
||||
device_init_wakeup(&pdev->dev, 1);
|
||||
dev_info(&pdev->dev, "driver successfully loaded\n");
|
||||
return 0;
|
||||
out_dev:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int rt5036_rtc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rt5036_rtc_info *ri = platform_get_drvdata(pdev);
|
||||
|
||||
rtc_device_unregister(ri->rtc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id rt_match_table[] = {
|
||||
{.compatible = "rt,rt5036-rtc",},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver rt5036_rtc_driver = {
|
||||
.driver = {
|
||||
.name = RT5036_DEV_NAME "-rtc",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = rt_match_table,
|
||||
},
|
||||
.probe = rt5036_rtc_probe,
|
||||
.remove = rt5036_rtc_remove,
|
||||
};
|
||||
|
||||
static int __init rt5036_rtc_init(void)
|
||||
{
|
||||
return platform_driver_register(&rt5036_rtc_driver);
|
||||
}
|
||||
subsys_initcall(rt5036_rtc_init);
|
||||
|
||||
static void __exit rt5036_rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&rt5036_rtc_driver);
|
||||
}
|
||||
module_exit(rt5036_rtc_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
|
||||
MODULE_DESCRIPTION("RTC driver for RT5036");
|
||||
MODULE_ALIAS("platform:" RT5036_DEV_NAME "-rtc");
|
||||
MODULE_VERSION(RT5036_DRV_VER);
|
||||
19
include/linux/mfd/rt5036/rt5036-irq.h
Executable file
19
include/linux/mfd/rt5036/rt5036-irq.h
Executable file
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* include/linux/mfd/rt5036/rt5036-irq.h
|
||||
* Include header file for Richtek RT5036 irq option 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_MFD_RT5036_IRQ_H
|
||||
#define _LINUX_MFD_RT5036_IRQ_H
|
||||
|
||||
#define RT5036_IRQPREZ_MASK 0x80
|
||||
|
||||
#endif /* #ifndef _LINUX_MFD_RT5036_IRQ_H */
|
||||
55
include/linux/mfd/rt5036/rt5036-misc.h
Executable file
55
include/linux/mfd/rt5036/rt5036-misc.h
Executable file
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* include/linux/mfd/rt5036/rt5036-misc.h
|
||||
* Include header file for Richtek RT5036 Misc option
|
||||
*
|
||||
* 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_MFD_RT5036_MISC_H
|
||||
#define _LINUX_MFD_RT5036_MISC_H
|
||||
|
||||
enum {
|
||||
MISCEVENT_PWRONLP = 3,
|
||||
MISCEVENT_PWRONSP,
|
||||
MISCEVENT_PWRONF,
|
||||
MISCEVENT_PWRONR,
|
||||
MISCEVENT_KPSHDN,
|
||||
MISCEVENT_VDDALV,
|
||||
MISCEVNET_OTM,
|
||||
MISCEVENT_PMICSYSLV = 13,
|
||||
MISCEVENT_LSW2LV,
|
||||
MISCEVENT_LSW1LV,
|
||||
MISCEVENT_LDO4LV,
|
||||
MISCEVENT_LDO3LV,
|
||||
MISCEVENT_LDO2LV,
|
||||
MISCEVENT_LDO1LV,
|
||||
MISCEVENT_BUCK4LV,
|
||||
MISCEVENT_BUCK3LV,
|
||||
MISCEVENT_BUCK2LV,
|
||||
MISCEVENT_BUCK1LV,
|
||||
MISCEVENT_MAX,
|
||||
};
|
||||
|
||||
#define RT5036_SHDNPRESS_MASK 0x0C
|
||||
#define RT5036_SHDNPRESS_SHIFT 2
|
||||
|
||||
#define RT5036_STBEN_MASK 0x06
|
||||
#define RT5036_STBEN_SHIFT 1
|
||||
|
||||
#define RT5036_LPSHDNEN_MASK 0x04
|
||||
#define RT5036_CHIPSHDN_MASK 0x80
|
||||
#define RT5036_SYSUVLO_SHIFT 5
|
||||
#define RT5036_SYSUVLO_MASK 0xE0
|
||||
#define RT5036_SYSLVENSHDN_MASK 0x20
|
||||
#define RT5036_PWRRDY_MASK 0x80
|
||||
|
||||
extern int rt5036_vin_exist(void);
|
||||
extern void rt5036_chip_shutdown(void);
|
||||
|
||||
#endif /* #ifndef _LINUX_MFD_RT5036_MISC_H */
|
||||
369
include/linux/mfd/rt5036/rt5036.h
Normal file
369
include/linux/mfd/rt5036/rt5036.h
Normal file
|
|
@ -0,0 +1,369 @@
|
|||
/*
|
||||
* include/linux/mfd/rt5036/rt5036.h
|
||||
* Include header file for Richtek RT5036 Core file
|
||||
*
|
||||
* 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_MFD_RT5036_H
|
||||
#define _LINUX_MFD_RT5036_H
|
||||
#include <linux/power_supply.h>
|
||||
|
||||
#define RT5036_DEV_NAME "rt5036"
|
||||
#define RT5036_DRV_VER "1.0.8_R"
|
||||
|
||||
enum {
|
||||
RT5036_ID_DCDC1,
|
||||
RT5036_ID_DCDC2,
|
||||
RT5036_ID_DCDC3,
|
||||
RT5036_ID_DCDC4,
|
||||
RT5036_ID_LDO1,
|
||||
RT5036_ID_LDO2,
|
||||
RT5036_ID_LDO3,
|
||||
RT5036_ID_LDO4,
|
||||
RT5036_ID_LSW1,
|
||||
RT5036_ID_LSW2,
|
||||
RT5036_MAX_REGULATOR,
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5036_REG_DEVID,
|
||||
RT5036_REG_RANGE1START = RT5036_REG_DEVID,
|
||||
RT5036_REG_CHGCTL1,
|
||||
RT5036_REG_CHGCTL2,
|
||||
RT5036_REG_RESV1,
|
||||
RT5036_REG_CHGCTL3,
|
||||
RT5036_REG_CHGCTL4,
|
||||
RT5036_REG_CHGCTL5,
|
||||
RT5036_REG_CHGCTL6,
|
||||
RT5036_REG_CHGCTL7,
|
||||
RT5036_REG_RSTCHG,
|
||||
RT5036_REG_RANGE1END = RT5036_REG_RSTCHG,
|
||||
RT5036_REG_CHGIRQ1 = 0x10,
|
||||
RT5036_REG_RANGE2START = RT5036_REG_CHGIRQ1,
|
||||
RT5036_REG_CHGIRQ2,
|
||||
RT5036_REG_CHGIRQ3,
|
||||
RT5036_REG_CHGIRQMASK1,
|
||||
RT5036_REG_CHGIRQMASK2,
|
||||
RT5036_REG_CHGIRQMASK3,
|
||||
RT5036_REG_CHGSTAT1,
|
||||
RT5036_REG_CHGSTAT2,
|
||||
RT5036_REG_CHGSTAT2MASK,
|
||||
RT5036_REG_RANGE2END = RT5036_REG_CHGSTAT2MASK,
|
||||
RT5036_REG_BUCKVN1 = 0x41,
|
||||
RT5036_REG_RANGE3START = RT5036_REG_BUCKVN1,
|
||||
RT5036_REG_BUCKVN2,
|
||||
RT5036_REG_BUCKVN3,
|
||||
RT5036_REG_BUCKVN4,
|
||||
RT5036_REG_BUCKVRCN,
|
||||
RT5036_REG_BUCKVRCNEN,
|
||||
RT5036_REG_BUCKMODE,
|
||||
RT5036_REG_LDOVN1,
|
||||
RT5036_REG_LDOVN2,
|
||||
RT5036_REG_LDOVN3,
|
||||
RT5036_REG_LDOVN4,
|
||||
RT5036_REG_LDOVRCN,
|
||||
RT5036_REG_LDOVRCNEN,
|
||||
RT5036_REG_LDOMODE,
|
||||
RT5036_REG_BUCKLDONEN,
|
||||
RT5036_REG_LSWEN,
|
||||
RT5036_REG_MISC1,
|
||||
RT5036_REG_MISC2,
|
||||
RT5036_REG_MISC3,
|
||||
RT5036_REG_MISC4,
|
||||
RT5036_REG_MISC5,
|
||||
RT5036_REG_ONOFFEVENT,
|
||||
RT5036_REG_BUCKLDOIRQ,
|
||||
RT5036_REG_LSWBASEIRQ,
|
||||
RT5036_REG_PWRKEYIRQ,
|
||||
RT5036_REG_BUCKLDOIRQMASK,
|
||||
RT5036_REG_LSWBASEIRQMASK,
|
||||
RT5036_REG_PWRKEYIRQMASK,
|
||||
RT5036_REG_RANGE3END = RT5036_REG_PWRKEYIRQMASK,
|
||||
RT5036_REG_MISC6 = 0x65,
|
||||
RT5036_REG_RANGE4START = RT5036_REG_MISC6,
|
||||
RT5036_REG_RANGE4END = RT5036_REG_MISC6,
|
||||
RT5036_REG_BUCKVS1 = 0x71,
|
||||
RT5036_REG_RANGE5START = RT5036_REG_BUCKVS1,
|
||||
RT5036_REG_BUCKVS2,
|
||||
RT5036_REG_BUCKVS3,
|
||||
RT5036_REG_BUCKVS4,
|
||||
RT5036_REG_BUCKVRCS,
|
||||
RT5036_REG_BUCKVRCSEN,
|
||||
RT5036_REG_RESV2,
|
||||
RT5036_REG_LDOVS1,
|
||||
RT5036_REG_LDOVS2,
|
||||
RT5036_REG_LDOVS3,
|
||||
RT5036_REG_LDOVS4,
|
||||
RT5036_REG_LDOVRCS,
|
||||
RT5036_REG_LDOVRCSEN,
|
||||
RT5036_REG_RESV3,
|
||||
RT5036_REG_BUCKLDOSEN,
|
||||
RT5036_REG_LSWVN2,
|
||||
RT5036_REG_LSWVN1,
|
||||
RT5036_REG_LSWVS2,
|
||||
RT5036_REG_LSWVS1,
|
||||
RT5036_REG_LSWVRC,
|
||||
RT5036_REG_LSWVRCEN,
|
||||
RT5036_REG_BUCKOCPSEL,
|
||||
RT5036_REG_RANGE5END = RT5036_REG_BUCKOCPSEL,
|
||||
RT5036_REG_RTCADJ = 0x90,
|
||||
RT5036_REG_RANGE6START = RT5036_REG_RTCADJ,
|
||||
RT5036_REG_RTCTSEC,
|
||||
RT5036_REG_RTCTMINUTE,
|
||||
RT5036_REG_RTCTHOUR,
|
||||
RT5036_REG_RTCTYEAR,
|
||||
RT5036_REG_RTCTMON,
|
||||
RT5036_REG_RTCTDATEW,
|
||||
RT5036_REG_STBMODE,
|
||||
RT5036_REG_RTCASEC,
|
||||
RT5036_REG_RTCAMINUTE,
|
||||
RT5036_REG_RTCAHOUR,
|
||||
RT5036_REG_RTCAYEAR,
|
||||
RT5036_REG_RTCAMONTH,
|
||||
RT5036_REG_RTCADATE,
|
||||
RT5036_REG_STBCDSEC,
|
||||
RT5036_REG_STBCDMINUTE,
|
||||
RT5036_REG_STBCDHOUR,
|
||||
RT5036_REG_STBCDDATEL,
|
||||
RT5036_REG_STBCDDATEH,
|
||||
RT5036_REG_RESV4,
|
||||
RT5036_REG_STBWACKIRQ,
|
||||
RT5036_REG_STBWACKIRQMASK,
|
||||
RT5036_REG_RANGE6END = RT5036_REG_STBWACKIRQMASK,
|
||||
RT5036_REG_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5036_RAMP_25mV,
|
||||
RT5036_RAMP_50mV,
|
||||
RT5036_RAMP_75mV,
|
||||
RT5036_RAMP_100mV,
|
||||
RT5036_RAMP_MAX = RT5036_RAMP_100mV,
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5036_SHDHPRESS_4S,
|
||||
RT5036_SHDNPRESS_6S,
|
||||
RT5036_SHDNPRESS_8S,
|
||||
RT5036_SHDNPRESS_10S,
|
||||
RT5036_SHDNPRESS_MAX = RT5036_SHDNPRESS_10S,
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5036_STB_DISABLE,
|
||||
RT5036_STB_EN1MS,
|
||||
RT5036_STB_EN2MS,
|
||||
RT5036_STB_EN4MS,
|
||||
RT5036_STB_MAX = RT5036_STB_EN4MS,
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5036_SYSLV_2P8V,
|
||||
RT5036_SYSLV_2P9V,
|
||||
RT5036_SYSLV_3P0V,
|
||||
RT5036_SYSLV_3P1V,
|
||||
RT5036_SYSLV_3P2V,
|
||||
RT5036_SYSLV_3P3V,
|
||||
RT5036_SYSLV_3P4V,
|
||||
RT5036_SYSLV_3P5V,
|
||||
RT5036_SYSLV_MAX = RT5036_SYSLV_3P5V
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5036_IPREC_150mA,
|
||||
RT5036_IPREC_250mA,
|
||||
RT5036_IPREC_350mA,
|
||||
RT5036_IPREC_450mA,
|
||||
RT5036_IPREC_MAX = RT5036_IPREC_450mA,
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5036_IEOC_DISABLE,
|
||||
RT5036_IEOC_150mA,
|
||||
RT5036_IEOC_200mA,
|
||||
RT5036_IEOC_250mA,
|
||||
RT5036_IEOC_300mA,
|
||||
RT5036_IEOC_400mA,
|
||||
RT5036_IEOC_500mA,
|
||||
RT5036_IEOC_600mA,
|
||||
RT5036_IEOC_MAX = RT5036_IEOC_600mA,
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5036_VPREC_2P3V,
|
||||
RT5036_VPREC_2P4V,
|
||||
RT5036_VPREC_2P5V,
|
||||
RT5036_VPREC_2P6V,
|
||||
RT5036_VPREC_2P7V,
|
||||
RT5036_VPREC_2P8V,
|
||||
RT5036_VPREC_2P9V,
|
||||
RT5036_VPREC_3P0V,
|
||||
RT5036_VPREC_3P1V,
|
||||
RT5036_VPREC_3P2V,
|
||||
RT5036_VPREC_3P3V,
|
||||
RT5036_VPREC_3P4V,
|
||||
RT5036_VPREC_3P5V,
|
||||
RT5036_VPREC_3P6V,
|
||||
RT5036_VPREC_3P7V,
|
||||
RT5036_VPREC_3P8V,
|
||||
RT5036_VPREC_MAX = RT5036_VPREC_3P8V,
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5036_BATLV_2P4V,
|
||||
RT5036_BATLV_2P5V,
|
||||
RT5036_BATLV_2P6V,
|
||||
RT5036_BATLV_2P7V,
|
||||
RT5036_BATLV_2P8V,
|
||||
RT5036_BATLV_2P9V,
|
||||
RT5036_BATLV_3P0V,
|
||||
RT5036_BATLV_3P1V,
|
||||
RT5036_BATLV_MAX = RT5036_BATLV_3P1V,
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5036_VRECHG_0P1V,
|
||||
RT5036_VRECHG_0P2V,
|
||||
RT5036_VRECHG_0P3V,
|
||||
RT5036_VRECHG_0P3V_1,
|
||||
RT5036_VRECHG_MAX = RT5036_VRECHG_0P3V_1,
|
||||
};
|
||||
|
||||
typedef void (*rt_irq_handler) (void *info, int eventno);
|
||||
|
||||
struct rt5036_regulator_ramp {
|
||||
unsigned char nramp_sel:2;
|
||||
unsigned char sramp_sel:2;
|
||||
};
|
||||
|
||||
struct rt5036_chg_data {
|
||||
int chg_volt;
|
||||
int otg_volt;
|
||||
int acchg_icc;
|
||||
int usbtachg_icc;
|
||||
int usbchg_icc;
|
||||
#ifdef CONFIG_RT_SUPPORT_ACUSB_DUALIN
|
||||
int acdet_gpio;
|
||||
int usbdet_gpio;
|
||||
#endif /* #ifdef CONFIG_RT_SUPPORT_ACUSB_DUALIN */
|
||||
u16 te_en:1;
|
||||
u16 iprec:2;
|
||||
u16 ieoc:3;
|
||||
u16 vprec:4;
|
||||
u16 batlv:3;
|
||||
u16 vrechg:2;
|
||||
};
|
||||
|
||||
struct rt5036_misc_data {
|
||||
u16 shdn_press:2;
|
||||
u16 stb_en:2;
|
||||
u16 lp_enshdn:1;
|
||||
u16 vsysuvlo:3;
|
||||
u16 syslv_enshdn:1;
|
||||
};
|
||||
|
||||
struct rt5036_irq_data {
|
||||
int irq_gpio;
|
||||
};
|
||||
|
||||
struct rt5036_chip;
|
||||
struct rt5036_platform_data {
|
||||
struct regulator_init_data *regulator[RT5036_MAX_REGULATOR];
|
||||
struct rt5036_chg_data *chg_pdata;
|
||||
struct rt5036_misc_data *misc_pdata;
|
||||
struct rt5036_irq_data *irq_pdata;
|
||||
int (*pre_init)(struct rt5036_chip *rt5036_chip);
|
||||
int (*post_init)(void);
|
||||
};
|
||||
|
||||
struct rt5036_charger_info {
|
||||
struct i2c_client *i2c;
|
||||
struct device *dev;
|
||||
struct power_supply psy;
|
||||
struct delayed_work dwork;
|
||||
int chg_volt;
|
||||
int otg_volt;
|
||||
int acchg_icc;
|
||||
int usbtachg_icc;
|
||||
int usbchg_icc;
|
||||
int charge_cable;
|
||||
#ifdef CONFIG_RT_SUPPORT_ACUSB_DUALIN
|
||||
int acdet_gpio;
|
||||
int usbdet_gpio;
|
||||
int acdet_irq;
|
||||
int usbdet_irq;
|
||||
unsigned char usbinit_delay:1;
|
||||
#endif /* #ifdef CONFIG_RT_SUPPORT_ACUSB_DUALIN */
|
||||
unsigned char online:1;
|
||||
unsigned char batabs:1;
|
||||
unsigned char te_en:1;
|
||||
unsigned char otg_en:1;
|
||||
unsigned char stat2;
|
||||
};
|
||||
|
||||
struct rt5036_misc_info {
|
||||
struct i2c_client *i2c;
|
||||
struct device *dev;
|
||||
#ifdef CONFIG_MISC_RT5036_PWRKEY
|
||||
struct input_dev *pwr_key;
|
||||
unsigned char pwr_key_pressed:1;
|
||||
#endif /* #ifdef CONFIG_MISC_RT5036_PWRKEY */
|
||||
};
|
||||
|
||||
struct rt5036_rtc_info {
|
||||
struct i2c_client *i2c;
|
||||
struct device *dev;
|
||||
struct rtc_device *rtc;
|
||||
};
|
||||
|
||||
struct rt5036_chip {
|
||||
struct i2c_client *i2c;
|
||||
struct rt5036_charger_info *chg_info;
|
||||
struct rt5036_misc_info *misc_info;
|
||||
struct rt5036_rtc_info *rtc_info;
|
||||
struct mutex io_lock;
|
||||
unsigned char suspend:1;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_CHARGER_RT5036
|
||||
void rt5036_charger_irq_handler(struct rt5036_charger_info *ci,
|
||||
unsigned int event);
|
||||
#endif /* #ifdef CONFIG_CHARGER_RT5036 */
|
||||
#ifdef CONFIG_MISC_RT5036
|
||||
void rt5036_misc_irq_handler(struct rt5036_misc_info *mi, unsigned int event);
|
||||
#endif /* #ifdef CONFIG_MISC_RT5036 */
|
||||
#ifdef CONFIG_RTC_RT5036
|
||||
void rt5036_rtc_irq_handler(struct rt5036_rtc_info *ri, unsigned int event);
|
||||
#endif /* #ifdef CONFIG_RTC_RT5036 */
|
||||
|
||||
extern int rt5036_reg_block_read(struct i2c_client *i2c, int reg, int byte,
|
||||
void *dest);
|
||||
extern int rt5036_reg_block_write(struct i2c_client *i2c, int reg, int byte,
|
||||
void *dest);
|
||||
extern int rt5036_reg_read(struct i2c_client *i2c, int reg);
|
||||
extern int rt5036_reg_write(struct i2c_client *i2c, int reg,
|
||||
unsigned char data);
|
||||
extern int rt5036_assign_bits(struct i2c_client *i2c, int reg,
|
||||
unsigned char mask, unsigned char data);
|
||||
extern int rt5036_set_bits(struct i2c_client *i2c, int reg, unsigned char mask);
|
||||
extern int rt5036_clr_bits(struct i2c_client *i2c, int reg, unsigned char mask);
|
||||
|
||||
extern int rt5036_core_init(struct device *dev,
|
||||
struct rt5036_platform_data *pdata);
|
||||
extern int rt5036_core_deinit(struct device *dev);
|
||||
|
||||
#ifdef CONFIG_MFD_RT5036_DBGINFO
|
||||
#define RTINFO(format, args...) \
|
||||
pr_info("%s:%s() line-%d: " format, RT5036_DEV_NAME, __func__, \
|
||||
__LINE__, ##args)
|
||||
#else
|
||||
#define RTINFO(format, args...)
|
||||
#endif /* CONFIG_MFD_RT5036_DBGINFO */
|
||||
#endif /* #ifndef _LINUX_MFD_RT5036_H */
|
||||
19
include/linux/power/rt-battery.h
Executable file
19
include/linux/power/rt-battery.h
Executable file
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* include/linux/power/rt-battery.h
|
||||
* Include header file for Richtek Richtek Battery 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_BATTERY_H
|
||||
#define __LINUX_RT_BATTERY_H
|
||||
|
||||
#define RT_BATT_NAME "rt-battery"
|
||||
|
||||
#endif /* #ifndef __LINUX_RT_BATTERY_H */
|
||||
4
include/linux/power/rt-power.h
Executable file → Normal file
4
include/linux/power/rt-power.h
Executable file → Normal file
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* include/linux/power/rt5025/rt-power.h
|
||||
* Include header file for Richtek RT5025 Core charger Driver
|
||||
* include/linux/power/rt-power.h
|
||||
* Include header file for Richtek Richtek Power Driver
|
||||
*
|
||||
* Copyright (C) 2014 Richtek Technology Corp.
|
||||
* cy_huang <cy_huang@richtek.com>
|
||||
|
|
|
|||
72
include/linux/power/rt5036-charger.h
Executable file
72
include/linux/power/rt5036-charger.h
Executable file
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* include/linux/power/rt5036-charger.h
|
||||
* Include header file for Richtek RT5036 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_POWER_RT5036_CHARGER_H
|
||||
#define _LINUX_POWER_RT5036_CHARGER_H
|
||||
|
||||
enum {
|
||||
CHGEVENT_STAT2ALT,
|
||||
CHGEVENT_CHBSTLOWVI = 5,
|
||||
CHGEVENT_BSTOLI,
|
||||
CHGEVENT_BSTVIMIDOVP,
|
||||
CHGEVENT_CHTMRFI = 10,
|
||||
CHGEVENT_CHRCHGI,
|
||||
CHGEVENT_CHTERMI,
|
||||
CHGEVENT_CHBATOVI,
|
||||
CHGEVENT_CHRVPI = 15,
|
||||
CHGEVENT_BATABSENSE,
|
||||
CHGEVENT_CHBADADPI,
|
||||
CHGEVENT_VINCHGPLUGOUT,
|
||||
CHGEVENT_VINCHGPLUGIN,
|
||||
CHGEVENT_PPBATLVI,
|
||||
CHGEVENT_IEOCI,
|
||||
CHGEVENT_VINOVPI,
|
||||
CHGEVENT_MAX,
|
||||
};
|
||||
|
||||
#define RT5036_CHGTEEN_MASK 0x08
|
||||
|
||||
#define RT5036_CHGIPREC_MASK 0x18
|
||||
#define RT5036_CHGIPREC_SHIFT 3
|
||||
|
||||
#define RT5036_CHGIEOC_MASK 0x07
|
||||
|
||||
#define RT5036_CHGVPREC_MASK 0x0F
|
||||
|
||||
#define RT5036_CHGBATLV_MASK 0x07
|
||||
|
||||
#define RT5036_CHGVRECHG_MASK 0x0C
|
||||
#define RT5036_CHGVRECHG_SHIFT 2
|
||||
|
||||
#define RT5036_CHGSTAT_MASK 0x30
|
||||
#define RT5036_CHGSTAT_SHIFT 4
|
||||
#define RT5036_CHGDIS_MASK 0x01
|
||||
#define RT5036_CHGAICR_MASK 0xE0
|
||||
#define RT5036_CHGAICR_SHIFT 5
|
||||
#define RT5036_CHGICC_MASK 0xF0
|
||||
#define RT5036_CHGICC_SHIFT 4
|
||||
#define RT5036_CHGCV_MASK 0xFC
|
||||
#define RT5036_CHGCV_SHIFT 2
|
||||
#define RT5036_CHGOPAMODE_MASK 0x01
|
||||
#define RT5036_CHGOPASTAT_MASK 0x08
|
||||
|
||||
#define RT5036_PWRRDY_MASK 0x80
|
||||
#define RT5036_TSEVENT_MASK 0x0F
|
||||
#define RT5036_TSWC_MASK 0x06
|
||||
#define RT5036_TSHC_MASK 0x09
|
||||
#define RT5036_CCJEITA_MASK 0x80
|
||||
#define RT5036_CHGOTGEN_MASK 0x40
|
||||
#define RT5036_BATDEN_MASK 0x80
|
||||
#define RT5036_TERST_MASK 0x10
|
||||
|
||||
#endif /* #ifndef _LINUX_POWER_RT5036_CHARGER_H */
|
||||
91
include/linux/regulator/rt5036-regulator.h
Executable file
91
include/linux/regulator/rt5036-regulator.h
Executable file
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* include/linux/regulator/rt5036-regulator.h
|
||||
* Include header file to Richtek RT5036 Regulator 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_RT5036_REGULATOR_H
|
||||
#define __LINUX_RT5036_REGULATOR_H
|
||||
|
||||
/*BUCK*/
|
||||
#define RT5036_DCDCVOUT_SHIFT1 0
|
||||
#define RT5036_DCDCVOUT_MASK1 0x7F
|
||||
#define RT5036_DCDCVOUT_SHIFT2 0
|
||||
#define RT5036_DCDCVOUT_MASK2 0x7F
|
||||
#define RT5036_DCDCVOUT_SHIFT3 0
|
||||
#define RT5036_DCDCVOUT_MASK3 0x7F
|
||||
#define RT5036_DCDCVOUT_SHIFT4 0
|
||||
#define RT5036_DCDCVOUT_MASK4 0x7F
|
||||
#define RT5036_DCDCEN_MASK1 0x08
|
||||
#define RT5036_DCDCEN_MASK2 0x04
|
||||
#define RT5036_DCDCEN_MASK3 0x02
|
||||
#define RT5036_DCDCEN_MASK4 0x01
|
||||
#define RT5036_DCDCMODE_MASK1 0x80
|
||||
#define RT5036_DCDCMODE_MASK2 0x40
|
||||
#define RT5036_DCDCMODE_MASK3 0x20
|
||||
#define RT5036_DCDCMODE_MASK4 0x10
|
||||
#define RT5036_DCDCRAMP_MASK1 0xC0
|
||||
#define RT5036_DCDCRAMP_SHIFT1 6
|
||||
#define RT5036_DCDCRAMP_MASK2 0x30
|
||||
#define RT5036_DCDCRAMP_SHIFT2 4
|
||||
#define RT5036_DCDCRAMP_MASK3 0x0C
|
||||
#define RT5036_DCDCRAMP_SHIFT3 2
|
||||
#define RT5036_DCDCRAMP_MASK4 0x03
|
||||
#define RT5036_DCDCRAMP_SHIFT4 0
|
||||
|
||||
/*LDO*/
|
||||
#define RT5036_LDOVOUT_SHIFT1 0
|
||||
#define RT5036_LDOVOUT_MASK1 0x7F
|
||||
#define RT5036_LDOVOUT_SHIFT2 0
|
||||
#define RT5036_LDOVOUT_MASK2 0x7F
|
||||
#define RT5036_LDOVOUT_SHIFT3 0
|
||||
#define RT5036_LDOVOUT_MASK3 0x7F
|
||||
#define RT5036_LDOVOUT_SHIFT4 0
|
||||
#define RT5036_LDOVOUT_MASK4 0x7F
|
||||
#define RT5036_LDOEN_MASK1 0x80
|
||||
#define RT5036_LDOEN_MASK2 0x40
|
||||
#define RT5036_LDOEN_MASK3 0x20
|
||||
#define RT5036_LDOEN_MASK4 0x10
|
||||
#define RT5036_LDOMODE_MASK1 0x80
|
||||
#define RT5036_LDOMODE_MASK2 0x40
|
||||
#define RT5036_LDOMODE_MASK3 0x20
|
||||
#define RT5036_LDOMODE_MASK4 0x10
|
||||
#define RT5036_LDORAMP_MASK1 0xC0
|
||||
#define RT5036_LDORAMP_SHIFT1 6
|
||||
#define RT5036_LDORAMP_MASK2 0x30
|
||||
#define RT5036_LDORAMP_SHIFT2 4
|
||||
#define RT5036_LDORAMP_MASK3 0x0C
|
||||
#define RT5036_LDORAMP_SHIFT3 2
|
||||
#define RT5036_LDORAMP_MASK4 0x03
|
||||
#define RT5036_LDORAMP_SHIFT4 0
|
||||
|
||||
/*LSW*/
|
||||
#define RT5036_LSWVOUT_SHIFT1 0
|
||||
#define RT5036_LSWVOUT_MASK1 0x7F
|
||||
#define RT5036_LSWVOUT_SHIFT2 0
|
||||
#define RT5036_LSWVOUT_MASK2 0x7F
|
||||
#define RT5036_LSWNEN_MASK2 0x02
|
||||
#define RT5036_LSWNEN_MASK1 0x01
|
||||
#define RT5036_LSWSEN_MASK2 0x08
|
||||
#define RT5036_LSWSEN_MASK1 0x04
|
||||
#define RT5036_LSWNMODE_MASK2 0x80
|
||||
#define RT5036_LSWNMODE_MASK1 0x40
|
||||
#define RT5036_LSWSMODE_MASK2 0x08
|
||||
#define RT5036_LSWSMODE_MASK1 0x04
|
||||
#define RT5036_LSWNRAMP_MASK2 0xC0
|
||||
#define RT5036_LSWNRAMP_SHIFT2 6
|
||||
#define RT5036_LSWNRAMP_MASK1 0x30
|
||||
#define RT5036_LSWNRAMP_SHIFT1 4
|
||||
#define RT5036_LSWSRAMP_MASK2 0x0C
|
||||
#define RT5036_LSWSRAMP_SHIFT2 2
|
||||
#define RT5036_LSWSRAMP_MASK1 0x03
|
||||
#define RT5036_LSWSRAMP_SHIFT1 0
|
||||
|
||||
#endif /* __LINUX_RT5036_REGULATOR_H */
|
||||
39
include/linux/rtc/rtc-rt5036.h
Executable file
39
include/linux/rtc/rtc-rt5036.h
Executable file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* include/linux/rtc/rt5036-rtc.h
|
||||
* Include header file for Richtek RT5036 RTC 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_RTC_RT5036_RTC_H
|
||||
#define _LINUX_RTC_RT5036_RTC_H
|
||||
|
||||
enum {
|
||||
RTCEVENT_CAIRQ,
|
||||
RTCEVENT_CDIRQ,
|
||||
RTCEVENT_MAX,
|
||||
};
|
||||
|
||||
#define RT5036_RTC_SECMASK 0x3F
|
||||
#define RT5036_RTC_MINMASK 0x3F
|
||||
#define RT5036_RTC_HOURMASK 0x1F
|
||||
#define RT5036_RTC_YEARMASK 0x7F
|
||||
#define RT5036_RTC_MONMASK 0x0F
|
||||
#define RT5036_RTC_DAYMASK 0x1F
|
||||
#define RT5036_RTC_WEEKMASK 0xE0
|
||||
#define RT5036_RTC_WEEKSHIFT 5
|
||||
|
||||
#define RT5036_STBCTL_MASK 0x01
|
||||
#define RT5036_RTCCDEN_MASK 0x02
|
||||
#define RT5036_RTCAEN_MASK 0x04
|
||||
|
||||
#define RT5036_RTCCDIRQ_MASK 0x02
|
||||
#define RT5036_RTCAIRQ_MASK 0x01
|
||||
|
||||
#endif /* #ifndef _LINUX_RTC_RT5036_RTC_H */
|
||||
Loading…
Reference in New Issue
Block a user