ricoh619:support pmic ricoh619

This commit is contained in:
张晴
2013-04-27 15:45:44 +08:00
parent 92aaf2cc7e
commit e35e3fe4e4
24 changed files with 6468 additions and 33 deletions

View File

@@ -0,0 +1,556 @@
#include <linux/regulator/machine.h>
#include <linux/mfd/ricoh619.h>
#include <linux/regulator/ricoh619-regulator.h>
#include <linux/power/ricoh619_battery.h>
#include <linux/rtc/rtc-ricoh619.h>
#include <mach/sram.h>
#include <linux/platform_device.h>
#include <mach/gpio.h>
#include <mach/iomux.h>
#include <mach/board.h>
#ifdef CONFIG_MFD_RICOH619
static struct ricoh619 *Ricoh619;
static int ricoh619_pre_init(struct ricoh619 *ricoh619){
Ricoh619 = ricoh619;
printk("%s,line=%d\n", __func__,__LINE__);
uint8_t cont;
int ret;
ret = ricoh619_clr_bits(ricoh619->dev,RICOH619_PWR_REP_CNT,(1 << 0)); //set restart when power off
/**********set dcdc mode when in sleep mode **************/
/*****************************************************/
return 0;
}
static int ricoh619_post_init(struct ricoh619 *ricoh619)
{
struct regulator *dcdc;
struct regulator *ldo;
int i = 0,ret=0;
printk("%s,line=%d\n", __func__,__LINE__);
#ifndef CONFIG_RK_CONFIG
g_pmic_type = PMIC_TYPE_RICOH619;
#endif
printk("%s:g_pmic_type=%d\n",__func__,g_pmic_type);
for(i = 0; i < ARRAY_SIZE(ricoh619_dcdc_info); i++)
{
if(ricoh619_dcdc_info[i].min_uv == 0 && ricoh619_dcdc_info[i].max_uv == 0)
continue;
dcdc =regulator_get(NULL, ricoh619_dcdc_info[i].name);
regulator_set_voltage(dcdc, ricoh619_dcdc_info[i].min_uv, ricoh619_dcdc_info[i].max_uv);
regulator_set_suspend_voltage(dcdc, ricoh619_dcdc_info[i].suspend_vol);
regulator_set_mode(dcdc, REGULATOR_MODE_NORMAL);
regulator_enable(dcdc);
printk("%s %s =%duV end\n", __func__,ricoh619_dcdc_info[i].name, regulator_get_voltage(dcdc));
regulator_put(dcdc);
udelay(100);
}
for(i = 0; i < ARRAY_SIZE(ricoh619_ldo_info); i++)
{
if(ricoh619_ldo_info[i].min_uv == 0 && ricoh619_ldo_info[i].max_uv == 0)
continue;
ldo =regulator_get(NULL, ricoh619_ldo_info[i].name);
regulator_set_voltage(ldo, ricoh619_ldo_info[i].min_uv, ricoh619_ldo_info[i].max_uv);
regulator_enable(ldo);
printk("%s %s =%duV end\n", __func__,ricoh619_ldo_info[i].name, regulator_get_voltage(ldo));
regulator_put(ldo);
}
#ifdef CONFIG_RK_CONFIG
if(sram_gpio_init(get_port_config(pmic_slp).gpio, &pmic_sleep) < 0){
printk(KERN_ERR "sram_gpio_init failed\n");
return -EINVAL;
}
if(port_output_init(pmic_slp, 0, "pmic_slp") < 0){
printk(KERN_ERR "port_output_init failed\n");
return -EINVAL;
}
#else
if(sram_gpio_init(PMU_POWER_SLEEP, &pmic_sleep) < 0){
printk(KERN_ERR "sram_gpio_init failed\n");
return -EINVAL;
}
gpio_request(PMU_POWER_SLEEP, "NULL");
gpio_direction_output(PMU_POWER_SLEEP, GPIO_LOW);
#endif
ret = ricoh619_clr_bits(ricoh619->dev,0xb1,(7<< 0)); //set vbatdec voltage 3.0v
ret = ricoh619_set_bits(ricoh619->dev,0xb1,(3<< 0)); //set vbatdec voltage 3.0v
printk("%s,line=%d END\n", __func__,__LINE__);
return 0;
}
static struct regulator_consumer_supply ricoh619_dcdc1_supply[] = {
{
.supply = "ricoh_dc1",
},
{
.supply = "vdd_cpu",
},
};
static struct regulator_consumer_supply ricoh619_dcdc2_supply[] = {
{
.supply = "ricoh_dc2",
},
{
.supply = "vdd_core",
},
};
static struct regulator_consumer_supply ricoh619_dcdc3_supply[] = {
{
.supply = "ricoh_dc3",
},
};
static struct regulator_consumer_supply ricoh619_dcdc4_supply[] = {
{
.supply = "ricoh_dc4",
},
};
static struct regulator_consumer_supply ricoh619_dcdc5_supply[] = {
{
.supply = "ricoh_dc5",
},
};
static struct regulator_consumer_supply ricoh619_ldo1_supply[] = {
{
.supply = "ricoh_ldo1",
},
};
static struct regulator_consumer_supply ricoh619_ldo2_supply[] = {
{
.supply = "ricoh_ldo2",
},
};
static struct regulator_consumer_supply ricoh619_ldo3_supply[] = {
{
.supply = "ricoh_ldo3",
},
};
static struct regulator_consumer_supply ricoh619_ldo4_supply[] = {
{
.supply = "ricoh_ldo4",
},
};
static struct regulator_consumer_supply ricoh619_ldo5_supply[] = {
{
.supply = "ricoh_ldo5",
},
};
static struct regulator_consumer_supply ricoh619_ldo6_supply[] = {
{
.supply = "ricoh_ldo6",
},
};
static struct regulator_consumer_supply ricoh619_ldo7_supply[] = {
{
.supply = "ricoh_ldo7",
},
};
static struct regulator_consumer_supply ricoh619_ldo8_supply[] = {
{
.supply = "ricoh_ldo8",
},
};
static struct regulator_consumer_supply ricoh619_ldo9_supply[] = {
{
.supply = "ricoh_ldo9",
},
};
static struct regulator_consumer_supply ricoh619_ldo10_supply[] = {
{
.supply = "ricoh_ldo10",
},
};
static struct regulator_consumer_supply ricoh619_ldortc1_supply[] = {
{
.supply = "ricoh_ldortc1",
},
};
static struct regulator_init_data ricoh619_dcdc1 = {
.constraints = {
.name = "RICOH_DC1",
.min_uV = 600000,
.max_uV = 3500000,
.apply_uV = 1,
.always_on = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
.valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL | REGULATOR_MODE_FAST,
},
.num_consumer_supplies = ARRAY_SIZE(ricoh619_dcdc1_supply),
.consumer_supplies = ricoh619_dcdc1_supply,
};
/* */
static struct regulator_init_data ricoh619_dcdc2 = {
.constraints = {
.name = "RICOH_DC2",
.min_uV = 600000,
.max_uV = 3500000,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
.valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL | REGULATOR_MODE_FAST,
},
.num_consumer_supplies = ARRAY_SIZE(ricoh619_dcdc2_supply),
.consumer_supplies = ricoh619_dcdc2_supply,
};
/* */
static struct regulator_init_data ricoh619_dcdc3 = {
.constraints = {
.name = "RICOH_DC3",
.min_uV = 600000,
.max_uV = 3500000,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
.valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL | REGULATOR_MODE_FAST,
},
.num_consumer_supplies = ARRAY_SIZE(ricoh619_dcdc3_supply),
.consumer_supplies = ricoh619_dcdc3_supply,
};
static struct regulator_init_data ricoh619_dcdc4 = {
.constraints = {
.name = "RICOH_DC4",
.min_uV = 600000,
.max_uV = 3500000,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
.valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL | REGULATOR_MODE_FAST,
},
.num_consumer_supplies = ARRAY_SIZE(ricoh619_dcdc4_supply),
.consumer_supplies = ricoh619_dcdc4_supply,
};
static struct regulator_init_data ricoh619_dcdc5 = {
.constraints = {
.name = "RICOH_DC5",
.min_uV = 600000,
.max_uV = 3500000,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
.valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL | REGULATOR_MODE_FAST,
},
.num_consumer_supplies = ARRAY_SIZE(ricoh619_dcdc5_supply),
.consumer_supplies = ricoh619_dcdc5_supply,
};
static struct regulator_init_data ricoh619_ldo1 = {
.constraints = {
.name = "RICOH_LDO1",
.min_uV = 900000,
.max_uV = 3500000,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
.valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL,
},
.num_consumer_supplies = ARRAY_SIZE(ricoh619_ldo1_supply),
.consumer_supplies = ricoh619_ldo1_supply,
};
/* */
static struct regulator_init_data ricoh619_ldo2 = {
.constraints = {
.name = "RICOH_LDO2",
.min_uV = 900000,
.max_uV = 3500000,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
.valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL,
},
.num_consumer_supplies = ARRAY_SIZE(ricoh619_ldo2_supply),
.consumer_supplies = ricoh619_ldo2_supply,
};
/* */
static struct regulator_init_data ricoh619_ldo3 = {
.constraints = {
.name = "RICOH_LDO3",
.min_uV = 900000,
.max_uV = 3500000,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
.valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL,
},
.num_consumer_supplies = ARRAY_SIZE(ricoh619_ldo3_supply),
.consumer_supplies = ricoh619_ldo3_supply,
};
/* */
static struct regulator_init_data ricoh619_ldo4 = {
.constraints = {
.name = "RICOH_LDO4",
.min_uV = 900000,
.max_uV = 3500000,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
.valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL,
},
.num_consumer_supplies = ARRAY_SIZE(ricoh619_ldo4_supply),
.consumer_supplies = ricoh619_ldo4_supply,
};
/* */
static struct regulator_init_data ricoh619_ldo5 = {
.constraints = {
.name = "RICOH_LDO5",
.min_uV = 900000,
.max_uV = 3500000,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
.valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL,
},
.num_consumer_supplies = ARRAY_SIZE(ricoh619_ldo5_supply),
.consumer_supplies = ricoh619_ldo5_supply,
};
static struct regulator_init_data ricoh619_ldo6 = {
.constraints = {
.name = "RICOH_LDO6",
.min_uV = 900000,
.max_uV = 3500000,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
.valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL,
},
.num_consumer_supplies = ARRAY_SIZE(ricoh619_ldo6_supply),
.consumer_supplies = ricoh619_ldo6_supply,
};
static struct regulator_init_data ricoh619_ldo7 = {
.constraints = {
.name = "RICOH_LDO7",
.min_uV = 900000,
.max_uV = 3500000,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
.valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL,
},
.num_consumer_supplies = ARRAY_SIZE(ricoh619_ldo7_supply),
.consumer_supplies = ricoh619_ldo7_supply,
};
static struct regulator_init_data ricoh619_ldo8 = {
.constraints = {
.name = "RICOH_LDO8",
.min_uV = 900000,
.max_uV = 3500000,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
.valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL,
},
.num_consumer_supplies = ARRAY_SIZE(ricoh619_ldo8_supply),
.consumer_supplies = ricoh619_ldo8_supply,
};
static struct regulator_init_data ricoh619_ldo9 = {
.constraints = {
.name = "RICOH_LDO9",
.min_uV = 900000,
.max_uV = 3500000,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
.valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL,
},
.num_consumer_supplies = ARRAY_SIZE(ricoh619_ldo9_supply),
.consumer_supplies = ricoh619_ldo9_supply,
};
static struct regulator_init_data ricoh619_ldo10 = {
.constraints = {
.name = "RICOH_LDO10",
.min_uV = 900000,
.max_uV = 3500000,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
.valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL,
},
.num_consumer_supplies = ARRAY_SIZE(ricoh619_ldo10_supply),
.consumer_supplies = ricoh619_ldo10_supply,
};
/* */
static struct regulator_init_data ricoh619_ldortc1 = {
.constraints = {
.name = "RICOH_LDORTC1",
.min_uV = 1700000,
.max_uV = 3500000,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE,
.valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL,
},
.num_consumer_supplies = ARRAY_SIZE(ricoh619_ldortc1_supply),
.consumer_supplies = ricoh619_ldortc1_supply,
};
static struct ricoh619_battery_platform_data ricoh619_power_battery = {
.irq = IRQ_BOARD_BASE,
.alarm_vol_mv = 3300,
.multiple =0,
.monitor_time = 1,
};
static struct rtc_time rk_time = { // 2012.1.1 12:00:00 Saturday
.tm_wday = 6,
.tm_year = 111,
.tm_mon = 0,
.tm_mday = 1,
.tm_hour = 12,
.tm_min = 0,
.tm_sec = 0,
};
static struct ricoh619_rtc_platform_data ricoh619_rtc_data = {
.irq = IRQ_BOARD_BASE ,
.time = &rk_time,
};
#define RICOH_REG(_id, _data) \
{ \
.id = RICOH619_ID_##_id, \
.name = "ricoh619-regulator", \
.platform_data = _data, \
} \
static struct ricoh619_pwrkey_platform_data ricoh619_pwrkey_data= {
.irq = IRQ_BOARD_BASE + RICOH619_IRQ_POWER_ON,
.delay_ms = 20,
};
static struct ricoh619_subdev_info ricoh619_devs[] = {
RICOH_REG(DC1, &ricoh619_dcdc1),
RICOH_REG(DC2, &ricoh619_dcdc2),
RICOH_REG(DC3, &ricoh619_dcdc3),
RICOH_REG(DC4, &ricoh619_dcdc4),
RICOH_REG(DC5, &ricoh619_dcdc5),
RICOH_REG(LDO1, &ricoh619_ldo1),
RICOH_REG(LDO2, &ricoh619_ldo2),
RICOH_REG(LDO3, &ricoh619_ldo3),
RICOH_REG(LDO4, &ricoh619_ldo4),
RICOH_REG(LDO5, &ricoh619_ldo5),
RICOH_REG(LDO6, &ricoh619_ldo6),
RICOH_REG(LDO7, &ricoh619_ldo7),
RICOH_REG(LDO8, &ricoh619_ldo8),
RICOH_REG(LDO9, &ricoh619_ldo9),
RICOH_REG(LDO10, &ricoh619_ldo10),
RICOH_REG(LDORTC1, &ricoh619_ldortc1),
{
.id = 16,
.name ="ricoh619-battery",
.platform_data = &ricoh619_power_battery,
},
{
.id = 17,
.name ="rtc_ricoh619",
.platform_data = &ricoh619_rtc_data,
},
{
.id = 18,
.name ="ricoh619-pwrkey",
.platform_data = &ricoh619_pwrkey_data,
},
};
#define RICOH_GPIO_INIT(_init_apply, _output_mode, _output_val, _led_mode, _led_func) \
{ \
.output_mode_en = _output_mode, \
.output_val = _output_val, \
.init_apply = _init_apply, \
.led_mode = _led_mode, \
.led_func = _led_func, \
} \
struct ricoh619_gpio_init_data ricoh_gpio_data[] = {
RICOH_GPIO_INIT(0, 1, 0, 0, 1),
RICOH_GPIO_INIT(0, 0, 0, 0, 0),
RICOH_GPIO_INIT(0, 0, 0, 0, 0),
RICOH_GPIO_INIT(0, 0, 0, 0, 0),
RICOH_GPIO_INIT(0, 0, 0, 0, 0),
};
static struct ricoh619_platform_data ricoh619_data={
.irq_base = IRQ_BOARD_BASE,
// .init_port = RICOH619_HOST_IRQ,
.num_subdevs = ARRAY_SIZE(ricoh619_devs),
.subdevs = ricoh619_devs,
.pre_init = ricoh619_pre_init,
.post_init = ricoh619_post_init,
//.gpio_base = RICOH619_GPIO_EXPANDER_BASE,
.gpio_init_data = ricoh_gpio_data,
.num_gpioinit_data = ARRAY_SIZE(ricoh_gpio_data),
.enable_shutdown_pin = 0,
};
void __sramfunc board_pmu_ricoh619_suspend(void)
{
#ifdef CONFIG_CLK_SWITCH_TO_32K
sram_gpio_set_value(pmic_sleep, GPIO_HIGH);
#endif
}
void __sramfunc board_pmu_ricoh619_resume(void)
{
#ifdef CONFIG_CLK_SWITCH_TO_32K
sram_gpio_set_value(pmic_sleep, GPIO_LOW);
sram_udelay(2000);
#endif
}
#endif

185
arch/arm/mach-rk30/board-rk3168-tb.c Executable file → Normal file
View File

@@ -47,6 +47,7 @@
#include <linux/mfd/tps65910.h>
#include <linux/regulator/act8846.h>
#include <linux/mfd/rk808.h>
#include <linux/mfd/ricoh619.h>
#include <linux/regulator/rk29-pwm-regulator.h>
#ifdef CONFIG_CW2015_BATTERY
@@ -1932,6 +1933,103 @@ static struct pmu_info rk808_ldo_info[] = {
#include "board-pmu-rk808.c"
#endif
#ifdef CONFIG_MFD_RICOH619
#define PMU_POWER_SLEEP RK30_PIN0_PA1
#define RICOH619_HOST_IRQ RK30_PIN0_PB3
static struct pmu_info ricoh619_dcdc_info[] = {
{
.name = "vdd_cpu", //arm
.min_uv = 1000000,
.max_uv = 1000000,
.suspend_vol = 900000,
},
{
.name = "vdd_core", //logic
.min_uv = 1000000,
.max_uv = 1000000,
.suspend_vol = 900000,
},
{
.name = "ricoh_dc3", //vcc18
.min_uv = 1800000,
.max_uv = 1800000,
.suspend_vol = 1800000,
},
{
.name = "ricoh_dc4", //vccio
.min_uv = 3300000,
.max_uv = 3300000,
.suspend_vol = 3300000,
},
{
.name = "ricoh_dc5", //ddr
.min_uv = 1200000,
.max_uv = 1200000,
.suspend_vol = 1200000,
},
};
static struct pmu_info ricoh619_ldo_info[] = {
{
.name = "ricoh_ldo1", //vcc30
.min_uv = 3000000,
.max_uv = 3000000,
},
{
.name = "ricoh_ldo2", //vcca33
.min_uv = 3300000,
.max_uv = 3300000,
},
{
.name = "ricoh_ldo3", //vcctp
.min_uv = 3300000,
.max_uv = 3300000,
},
{
.name = "ricoh_ldo4", //vccsd
.min_uv = 3300000,
.max_uv = 3300000,
},
{
.name = "ricoh_ldo5", //vcc18_cif
.min_uv = 1800000,
.max_uv = 1800000,
},
{
.name = "ricoh_ldo6", //vdd12
.min_uv = 1200000,
.max_uv = 1200000,
},
{
.name = "ricoh_ldo7", //vcc28_cif
.min_uv = 2800000,
.max_uv = 2800000,
},
{
.name = "ricoh_ldo8", //vcc25
.min_uv = 2500000,
.max_uv = 2500000,
},
{
.name = "ricoh_ldo9", //vdd10
.min_uv = 1000000,
.max_uv = 1000000,
},
{
.name = "ricoh_ldo10", //vcca18
.min_uv = 1800000,
.max_uv = 1800000,
},
};
#include "board-pmu-ricoh619.c"
#endif
static struct i2c_board_info __initdata i2c1_info[] = {
@@ -1973,6 +2071,16 @@ static struct i2c_board_info __initdata i2c1_info[] = {
},
#endif
#if defined (CONFIG_MFD_RICOH619)
{
.type = "ricoh619",
.addr = 0x32,
.flags = 0,
.irq = RICOH619_HOST_IRQ,
.platform_data=&ricoh619_data,
},
#endif
#if defined (CONFIG_RTC_HYM8563)
{
.type = "rtc_hym8563",
@@ -1995,43 +2103,51 @@ static struct i2c_board_info __initdata i2c1_info[] = {
void __sramfunc board_pmu_suspend(void)
{
#if defined (CONFIG_MFD_WM831X_I2C)
if(pmic_is_wm8326())
board_pmu_wm8326_suspend();
#endif
#if defined (CONFIG_MFD_TPS65910)
if(pmic_is_tps65910())
board_pmu_tps65910_suspend();
#endif
#if defined (CONFIG_REGULATOR_ACT8846)
if(pmic_is_act8846())
board_pmu_act8846_suspend();
#endif
#if defined (CONFIG_MFD_RK808)
if(pmic_is_rk808())
board_pmu_rk808_suspend();
#endif
#if defined (CONFIG_MFD_WM831X_I2C)
if(pmic_is_wm8326())
board_pmu_wm8326_suspend();
#endif
#if defined (CONFIG_MFD_TPS65910)
if(pmic_is_tps65910())
board_pmu_tps65910_suspend();
#endif
#if defined (CONFIG_REGULATOR_ACT8846)
if(pmic_is_act8846())
board_pmu_act8846_suspend();
#endif
#if defined (CONFIG_MFD_RK808)
if(pmic_is_rk808())
board_pmu_rk808_suspend();
#endif
#if defined (CONFIG_MFD_RICOH619)
if(pmic_is_ricoh619())
board_pmu_ricoh619_suspend();
#endif
}
void __sramfunc board_pmu_resume(void)
{
#if defined (CONFIG_MFD_WM831X_I2C)
if(pmic_is_wm8326())
board_pmu_wm8326_resume();
#endif
#if defined (CONFIG_MFD_TPS65910)
if(pmic_is_tps65910())
board_pmu_tps65910_resume();
#endif
#if defined (CONFIG_REGULATOR_ACT8846)
if(pmic_is_act8846())
board_pmu_act8846_resume();
#endif
#if defined (CONFIG_MFD_RK808)
if(pmic_is_rk808())
board_pmu_rk808_resume();
#endif
#if defined (CONFIG_MFD_WM831X_I2C)
if(pmic_is_wm8326())
board_pmu_wm8326_resume();
#endif
#if defined (CONFIG_MFD_TPS65910)
if(pmic_is_tps65910())
board_pmu_tps65910_resume();
#endif
#if defined (CONFIG_REGULATOR_ACT8846)
if(pmic_is_act8846())
board_pmu_act8846_resume();
#endif
#if defined (CONFIG_MFD_RK808)
if(pmic_is_rk808())
board_pmu_rk808_resume();
#endif
#if defined (CONFIG_MFD_RICOH619)
if(pmic_is_ricoh619())
board_pmu_ricoh619_resume();
#endif
}
@@ -2267,6 +2383,11 @@ static void rk30_pm_power_off(void)
rk808_device_shutdown();//rk808 shutdown
}
#endif
#if defined(CONFIG_MFD_RICOH619)
if(pmic_is_ricoh619()){
ricoh619_power_off(); //ricoh619 shutdown
}
#endif
gpio_direction_output(POWER_ON_PIN, GPIO_LOW);
while (1);

View File

@@ -90,6 +90,7 @@ enum {
PMIC_TYPE_ACT8931 =3,
PMIC_TYPE_ACT8846 =3,
PMIC_TYPE_RK808 =4,
PMIC_TYPE_RICOH619 =5,
PMIC_TYPE_MAX,
};
extern __sramdata int g_pmic_type;
@@ -98,6 +99,7 @@ extern __sramdata int g_pmic_type;
#define pmic_is_act8931() (g_pmic_type == PMIC_TYPE_ACT8931)
#define pmic_is_act8846() (g_pmic_type == PMIC_TYPE_ACT8846)
#define pmic_is_rk808() (g_pmic_type == PMIC_TYPE_RK808)
#define pmic_is_ricoh619() (g_pmic_type == PMIC_TYPE_RICOH619)
struct pmu_info {
char *name;

10
drivers/input/misc/Kconfig Executable file → Normal file
View File

@@ -294,6 +294,16 @@ config INPUT_TWL6030_PWRBUTTON
To compile this driver as a module, choose M here. The module will
be called twl6030_pwrbutton.
config INPUT_RICOH619_PWRKEY
tristate "RICOH RC5T619 PMU PWRKEY driver"
depends on MFD_RICOH619
default n
help
If you say yes here you get support for the RICOH RC5T619 PWRKEY module.
This driver can also be built as a module. If so, the module
will be called rc5t619-pwrkey.
config INPUT_TWL4030_VIBRA
tristate "Support for TWL4030 Vibrator"
depends on TWL4030_CORE

2
drivers/input/misc/Makefile Executable file → Normal file
View File

@@ -52,3 +52,5 @@ obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o
obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o
obj-$(CONFIG_INPUT_YEALINK) += yealink.o
obj-$(CONFIG_INPUT_LPSENSOR_AL3006) += al3006.o
obj-$(CONFIG_INPUT_RICOH619_PWRKEY) += ricoh619-pwrkey.o

View File

@@ -0,0 +1,332 @@
/*
* driver/input/misc/ricoh619-pwrkey.c
*
* Power Key driver for RICOH RC5T619 power management chip.
*
* Copyright (C) 2012-2013 RICOH COMPANY,LTD
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/mfd/ricoh619.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <linux/workqueue.h>
#include <linux/gpio.h>
#include <linux/mfd/ricoh619.h>
#define RICOH619_ONKEY_TRIGGER_LEVEL 0
#define RICOH619_ONKEY_OFF_IRQ 0
struct ricoh619_pwrkey {
struct device * dev;
struct input_dev *pwr;
#if RICOH619_ONKEY_TRIGGER_LEVEL
struct timer_list timer;
#endif
struct workqueue_struct * workqueue;
struct work_struct work;
unsigned long delay;
int key_irq;
bool pressed_first;
struct ricoh619_pwrkey_platform_data *pdata;
spinlock_t lock;
};
struct ricoh619_pwrkey *g_pwrkey;
//static int test_set = 0;
#if RICOH619_ONKEY_TRIGGER_LEVEL
void ricoh619_pwrkey_timer(unsigned long t)
{
queue_work(g_pwrkey->workqueue, &g_pwrkey->work);
}
#endif
extern int pwrkey_wakeup;
static void ricoh619_irq_work(struct work_struct * work)
{
unsigned long flags;
uint8_t val;
// printk("PMU: %s: \n",__func__);
//spin_lock_irqsave(&g_pwrkey->lock, flags);
if(pwrkey_wakeup){
// printk("PMU: %s: pwrkey_wakeup\n",__func__);
pwrkey_wakeup = 0;
input_event(g_pwrkey->pwr, EV_KEY, KEY_POWER, 1);
input_event(g_pwrkey->pwr, EV_SYN, 0, 0);
input_event(g_pwrkey->pwr, EV_KEY, KEY_POWER, 0);
input_event(g_pwrkey->pwr, EV_SYN, 0, 0);
return;
}
ricoh619_read(g_pwrkey->dev->parent, RICOH619_INT_MON_SYS, &val);
dev_dbg(g_pwrkey->dev, "pwrkey is pressed?(0x%x): 0x%x\n", RICOH619_INT_MON_SYS, val);
// printk("PMU: %s: val=0x%x\n",__func__,val);
val &= 0x1;
if(val){
#if (RICOH619_ONKEY_TRIGGER_LEVEL)
g_pwrkey->timer.expires = jiffies + g_pwrkey->delay;
dd_timer(&g_pwrkey->timer);
#endif
if (!g_pwrkey->pressed_first){
g_pwrkey->pressed_first = true;
// printk("PMU1: %s: Power Key!!!\n",__func__);
//input_report_key(g_pwrkey->pwr, KEY_POWER, 1);
//input_sync(g_pwrkey->pwr);
input_event(g_pwrkey->pwr, EV_KEY, KEY_POWER, 1);
input_event(g_pwrkey->pwr, EV_SYN, 0, 0);
}
}
else{
if (g_pwrkey->pressed_first){
// printk("PMU2: %s: Power Key!!!\n",__func__);
//input_report_key(g_pwrkey->pwr, KEY_POWER, 0);
//input_sync(g_pwrkey->pwr);
input_event(g_pwrkey->pwr, EV_KEY, KEY_POWER, 0);
input_event(g_pwrkey->pwr, EV_SYN, 0, 0);
}
g_pwrkey->pressed_first = false;
}
//spin_unlock_irqrestore(&g_pwrkey->lock, flags);
}
extern struct ricoh619 *g_ricoh619;
static irqreturn_t pwrkey_irq(int irq, void *_pwrkey)
{
// printk("PMU: %s: \n",__func__);
struct ricoh619 *ricoh619 = g_ricoh619;
#if (RICOH619_ONKEY_TRIGGER_LEVEL)
g_pwrkey->timer.expires = jiffies + g_pwrkey->delay;
add_timer(&g_pwrkey->timer);
#else
queue_work(g_pwrkey->workqueue, &g_pwrkey->work);
#endif
ricoh619_clr_bits(g_ricoh619->dev, RICOH619_INT_IR_SYS, 0x1); //clr power-on interrupt
return IRQ_HANDLED;
}
#if RICOH619_ONKEY_OFF_IRQ
static irqreturn_t pwrkey_irq_off(int irq, void *_pwrkey)
{
dev_warn(g_pwrkey->dev, "ONKEY is pressed long time!\n");
return IRQ_HANDLED;
}
#endif
static int __devinit ricoh619_pwrkey_probe(struct platform_device *pdev)
{
struct input_dev *pwr;
int key_irq;
int err;
struct ricoh619_pwrkey *pwrkey;
struct ricoh619_pwrkey_platform_data *pdata = pdev->dev.platform_data;
uint8_t val;
// printk("PMU: %s: \n",__func__);
if (!pdata) {
dev_err(&pdev->dev, "power key platform data not supplied\n");
return -EINVAL;
}
key_irq = (pdata->irq + RICOH619_IRQ_POWER_ON);
printk(KERN_INFO "PMU1: %s: key_irq=%d\n", __func__, key_irq);
pwrkey = kzalloc(sizeof(*pwrkey), GFP_KERNEL);
if (!pwrkey)
return -ENOMEM;
pwrkey->dev = &pdev->dev;
pwrkey->pdata = pdata;
pwrkey->pressed_first = false;
pwrkey->delay = HZ / 1000 * pdata->delay_ms;
g_pwrkey = pwrkey;
pwr = input_allocate_device();
if (!pwr) {
dev_dbg(&pdev->dev, "Can't allocate power button\n");
err = -ENOMEM;
goto free_pwrkey;
}
input_set_capability(pwr, EV_KEY, KEY_POWER);
pwr->name = "ricoh619_pwrkey";
pwr->phys = "ricoh619_pwrkey/input0";
pwr->dev.parent = &pdev->dev;
#if RICOH619_ONKEY_TRIGGER_LEVEL
init_timer(&pwrkey->timer);
pwrkey->timer.function = ricoh619_pwrkey_timer;
#endif
spin_lock_init(&pwrkey->lock);
err = input_register_device(pwr);
if (err) {
dev_dbg(&pdev->dev, "Can't register power key: %d\n", err);
goto free_input_dev;
}
pwrkey->key_irq = key_irq;
pwrkey->pwr = pwr;
platform_set_drvdata(pdev, pwrkey);
// Check if power-key is pressed at boot up
err = ricoh619_read(pwrkey->dev->parent, RICOH619_INT_MON_SYS, &val);
if (err < 0) {
dev_err(&pdev->dev, "Key-press status at boot failed rc=%d\n",
err);
goto unreg_input_dev;
}
val &= 0x1;
if (val) {
input_report_key(pwrkey->pwr, KEY_POWER, 1);
// printk(KERN_INFO "******KEY_POWER:1\n");
input_sync(pwrkey->pwr);
pwrkey->pressed_first = true;
}
#if !(RICOH619_ONKEY_TRIGGER_LEVEL)
ricoh619_set_bits(pwrkey->dev->parent, RICOH619_PWR_IRSEL, 0x1); //trigger both edge
#endif
err = request_threaded_irq(key_irq, NULL, pwrkey_irq,
IRQF_ONESHOT, "ricoh619_pwrkey", pwrkey);
if (err < 0) {
dev_err(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n",
key_irq, err);
goto unreg_input_dev;
}
#if RICOH619_ONKEY_OFF_IRQ
err = request_threaded_irq(key_irq + RICOH619_IRQ_ONKEY_OFF, NULL,
pwrkey_irq_off, IRQF_ONESHOT,
"ricoh619_pwrkey_off", pwrkey);
if (err < 0) {
dev_err(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n",
key_irq + RICOH619_IRQ_ONKEY_OFF, err);
free_irq(key_irq, pwrkey);
goto unreg_input_dev;
}
#endif
pwrkey->workqueue = create_singlethread_workqueue("ricoh619_pwrkey");
INIT_WORK(&pwrkey->work, ricoh619_irq_work);
/* Enable power key IRQ */
/* trigger both edge */
ricoh619_set_bits(pwrkey->dev->parent, RICOH619_PWR_IRSEL, 0x1);
/* Enable system interrupt */
ricoh619_set_bits(pwrkey->dev->parent, RICOH619_INTC_INTEN, 0x1);
/* Enable power-on interrupt */
ricoh619_set_bits(pwrkey->dev->parent, RICOH619_INT_EN_SYS, 0x1);
// printk(KERN_INFO "PMU: %s is OK!\n", __func__);
return 0;
unreg_input_dev:
input_unregister_device(pwr);
pwr = NULL;
free_input_dev:
input_free_device(pwr);
free_pwrkey:
kfree(pwrkey);
return err;
}
static int __devexit ricoh619_pwrkey_remove(struct platform_device *pdev)
{
struct ricoh619_pwrkey *pwrkey = platform_get_drvdata(pdev);
flush_workqueue(pwrkey->workqueue);
destroy_workqueue(pwrkey->workqueue);
free_irq(pwrkey->key_irq, pwrkey);
input_unregister_device(pwrkey->pwr);
kfree(pwrkey);
return 0;
}
#ifdef CONFIG_PM
static int ricoh619_pwrkey_suspend(struct device *dev)
{
struct ricoh619_pwrkey *info = dev_get_drvdata(dev);
// printk(KERN_INFO "PMU: %s\n", __func__);
if (info->key_irq)
disable_irq(info->key_irq);
cancel_work_sync(&info->work);
flush_workqueue(info->workqueue);
return 0;
}
static int ricoh619_pwrkey_resume(struct device *dev)
{
struct ricoh619_pwrkey *info = dev_get_drvdata(dev);
// printk(KERN_INFO "PMU: %s\n", __func__);
queue_work(info->workqueue, &info->work);
if (info->key_irq)
enable_irq(info->key_irq);
return 0;
}
static const struct dev_pm_ops ricoh619_pwrkey_pm_ops = {
.suspend = ricoh619_pwrkey_suspend,
.resume = ricoh619_pwrkey_resume,
};
#endif
static struct platform_driver ricoh619_pwrkey_driver = {
.probe = ricoh619_pwrkey_probe,
.remove = __devexit_p(ricoh619_pwrkey_remove),
.driver = {
.name = "ricoh619-pwrkey",
.owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &ricoh619_pwrkey_pm_ops,
#endif
},
};
static int __init ricoh619_pwrkey_init(void)
{
return platform_driver_register(&ricoh619_pwrkey_driver);
}
subsys_initcall_sync(ricoh619_pwrkey_init);
static void __exit ricoh619_pwrkey_exit(void)
{
platform_driver_unregister(&ricoh619_pwrkey_driver);
}
module_exit(ricoh619_pwrkey_exit);
MODULE_ALIAS("platform:ricoh619-pwrkey");
MODULE_AUTHOR("zhangqing <zhangqing@rock-chips.com>");
MODULE_DESCRIPTION("ricoh619 Power Key");
MODULE_LICENSE("GPL v2");

View File

@@ -307,6 +307,18 @@ config MFD_RK808
if you say yes here you get support for the RK808 series of
Power Management chips.
config MFD_RICOH619
bool "Ricoh RC5T619 Power Management system device"
depends on I2C && GPIOLIB && GENERIC_HARDIRQS
select MFD_CORE
default n
help
If you say yes here you get support for the RICOH619 Power
Management system device.
This driver provides common support for accessing the device,
additional drivers must be enabled in order to use the
functionality of the device.
config AIC3262_CODEC
bool "Support TI Codec Aic3262"
select MFD_CORE

View File

@@ -110,3 +110,4 @@ obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o
obj-$(CONFIG_MFD_RK610) += rk610-core.o
obj-$(CONFIG_MFD_RK808) += rk808.o rk808-irq.o
obj-$(CONFIG_MFD_RK616) += rk616-core.o
obj-$(CONFIG_MFD_RICOH619) += ricoh619.o ricoh619-irq.o

534
drivers/mfd/ricoh619-irq.c Normal file
View File

@@ -0,0 +1,534 @@
/*
* driver/mfd/ricoh619-irq.c
*
* Interrupt driver for RICOH RC5T619 power management chip.
*
* Copyright (C) 2012-2013 RICOH COMPANY,LTD
*
* Based on code
* Copyright (C) 2011 NVIDIA Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/mfd/ricoh619.h>
enum int_type {
SYS_INT = 0x1,
DCDC_INT = 0x2,
RTC_INT = 0x4,
ADC_INT = 0x8,
GPIO_INT = 0x10,
CHG_INT = 0x40,
};
static int gpedge_add[] = {
RICOH619_GPIO_GPEDGE1,
RICOH619_GPIO_GPEDGE2
};
static int irq_en_add[] = {
RICOH619_INT_EN_SYS,
RICOH619_INT_EN_DCDC,
RICOH619_INT_EN_RTC,
RICOH619_INT_EN_ADC1,
RICOH619_INT_EN_ADC2,
RICOH619_INT_EN_ADC3,
RICOH619_INT_EN_GPIO,
RICOH619_INT_EN_GPIO2,
RICOH619_INT_MSK_CHGCTR,
RICOH619_INT_MSK_CHGSTS1,
RICOH619_INT_MSK_CHGSTS2,
RICOH619_INT_MSK_CHGERR,
RICOH619_INT_MSK_CHGEXTIF
};
static int irq_mon_add[] = {
RICOH619_INT_IR_SYS, //RICOH619_INT_MON_SYS,
RICOH619_INT_IR_DCDC, //RICOH619_INT_MON_DCDC,
RICOH619_INT_IR_RTC, //RICOH619_INT_MON_RTC,
RICOH619_INT_IR_ADCL,
RICOH619_INT_IR_ADCH,
RICOH619_INT_IR_ADCEND,
RICOH619_INT_IR_GPIOR,
RICOH619_INT_IR_GPIOF,
RICOH619_INT_IR_CHGCTR, //RICOH619_INT_MON_CHGCTR,
RICOH619_INT_IR_CHGSTS1, //RICOH619_INT_MON_CHGSTS1,
RICOH619_INT_IR_CHGSTS2, //RICOH619_INT_MON_CHGSTS2,
RICOH619_INT_IR_CHGERR, //RICOH619_INT_MON_CHGERR
RICOH619_INT_IR_CHGEXTIF //RICOH619_INT_MON_CHGEXTIF
};
static int irq_clr_add[] = {
RICOH619_INT_IR_SYS,
RICOH619_INT_IR_DCDC,
RICOH619_INT_IR_RTC,
RICOH619_INT_IR_ADCL,
RICOH619_INT_IR_ADCH,
RICOH619_INT_IR_ADCEND,
RICOH619_INT_IR_GPIOR,
RICOH619_INT_IR_GPIOF,
RICOH619_INT_IR_CHGCTR,
RICOH619_INT_IR_CHGSTS1,
RICOH619_INT_IR_CHGSTS2,
RICOH619_INT_IR_CHGERR,
RICOH619_INT_IR_CHGEXTIF
};
static int main_int_type[] = {
SYS_INT,
DCDC_INT,
RTC_INT,
ADC_INT,
ADC_INT,
ADC_INT,
GPIO_INT,
GPIO_INT,
CHG_INT,
CHG_INT,
CHG_INT,
CHG_INT,
CHG_INT,
};
struct ricoh619_irq_data {
u8 int_type;
u8 master_bit;
u8 int_en_bit;
u8 mask_reg_index;
int grp_index;
};
#define RICOH619_IRQ(_int_type, _master_bit, _grp_index, _int_bit, _mask_ind) \
{ \
.int_type = _int_type, \
.master_bit = _master_bit, \
.grp_index = _grp_index, \
.int_en_bit = _int_bit, \
.mask_reg_index = _mask_ind, \
}
static const struct ricoh619_irq_data ricoh619_irqs[RICOH619_NR_IRQS] = {
[RICOH619_IRQ_POWER_ON] = RICOH619_IRQ(SYS_INT, 0, 0, 0, 0),
[RICOH619_IRQ_EXTIN] = RICOH619_IRQ(SYS_INT, 0, 1, 1, 0),
[RICOH619_IRQ_PRE_VINDT] = RICOH619_IRQ(SYS_INT, 0, 2, 2, 0),
[RICOH619_IRQ_PREOT] = RICOH619_IRQ(SYS_INT, 0, 3, 3, 0),
[RICOH619_IRQ_POWER_OFF] = RICOH619_IRQ(SYS_INT, 0, 4, 4, 0),
[RICOH619_IRQ_NOE_OFF] = RICOH619_IRQ(SYS_INT, 0, 5, 5, 0),
[RICOH619_IRQ_WD] = RICOH619_IRQ(SYS_INT, 0, 6, 6, 0),
[RICOH619_IRQ_DC1LIM] = RICOH619_IRQ(DCDC_INT, 1, 0, 0, 1),
[RICOH619_IRQ_DC2LIM] = RICOH619_IRQ(DCDC_INT, 1, 1, 1, 1),
[RICOH619_IRQ_DC3LIM] = RICOH619_IRQ(DCDC_INT, 1, 2, 2, 1),
[RICOH619_IRQ_DC4LIM] = RICOH619_IRQ(DCDC_INT, 1, 3, 3, 1),
[RICOH619_IRQ_DC5LIM] = RICOH619_IRQ(DCDC_INT, 1, 4, 4, 1),
[RICOH619_IRQ_CTC] = RICOH619_IRQ(RTC_INT, 2, 0, 0, 2),
[RICOH619_IRQ_DALE] = RICOH619_IRQ(RTC_INT, 2, 1, 6, 2),
[RICOH619_IRQ_ILIMLIR] = RICOH619_IRQ(ADC_INT, 3, 0, 0, 3),
[RICOH619_IRQ_VBATLIR] = RICOH619_IRQ(ADC_INT, 3, 1, 1, 3),
[RICOH619_IRQ_VADPLIR] = RICOH619_IRQ(ADC_INT, 3, 2, 2, 3),
[RICOH619_IRQ_VUSBLIR] = RICOH619_IRQ(ADC_INT, 3, 3, 3, 3),
[RICOH619_IRQ_VSYSLIR] = RICOH619_IRQ(ADC_INT, 3, 4, 4, 3),
[RICOH619_IRQ_VTHMLIR] = RICOH619_IRQ(ADC_INT, 3, 5, 5, 3),
[RICOH619_IRQ_AIN1LIR] = RICOH619_IRQ(ADC_INT, 3, 6, 6, 3),
[RICOH619_IRQ_AIN0LIR] = RICOH619_IRQ(ADC_INT, 3, 7, 7, 3),
[RICOH619_IRQ_ILIMHIR] = RICOH619_IRQ(ADC_INT, 3, 8, 0, 4),
[RICOH619_IRQ_VBATHIR] = RICOH619_IRQ(ADC_INT, 3, 9, 1, 4),
[RICOH619_IRQ_VADPHIR] = RICOH619_IRQ(ADC_INT, 3, 10, 2, 4),
[RICOH619_IRQ_VUSBHIR] = RICOH619_IRQ(ADC_INT, 3, 11, 3, 4),
[RICOH619_IRQ_VSYSHIR] = RICOH619_IRQ(ADC_INT, 3, 12, 4, 4),
[RICOH619_IRQ_VTHMHIR] = RICOH619_IRQ(ADC_INT, 3, 13, 5, 4),
[RICOH619_IRQ_AIN1HIR] = RICOH619_IRQ(ADC_INT, 3, 14, 6, 4),
[RICOH619_IRQ_AIN0HIR] = RICOH619_IRQ(ADC_INT, 3, 15, 7, 4),
[RICOH619_IRQ_ADC_ENDIR] = RICOH619_IRQ(ADC_INT, 3, 16, 0, 5),
[RICOH619_IRQ_GPIO0] = RICOH619_IRQ(GPIO_INT, 4, 0, 0, 6),
[RICOH619_IRQ_GPIO1] = RICOH619_IRQ(GPIO_INT, 4, 1, 1, 6),
[RICOH619_IRQ_GPIO2] = RICOH619_IRQ(GPIO_INT, 4, 2, 2, 6),
[RICOH619_IRQ_GPIO3] = RICOH619_IRQ(GPIO_INT, 4, 3, 3, 6),
[RICOH619_IRQ_GPIO4] = RICOH619_IRQ(GPIO_INT, 4, 4, 4, 6),
[RICOH619_IRQ_FVADPDETSINT] = RICOH619_IRQ(CHG_INT, 6, 0, 0, 8),
[RICOH619_IRQ_FVUSBDETSINT] = RICOH619_IRQ(CHG_INT, 6, 1, 1, 8),
[RICOH619_IRQ_FVADPLVSINT] = RICOH619_IRQ(CHG_INT, 6, 2, 2, 8),
[RICOH619_IRQ_FVUSBLVSINT] = RICOH619_IRQ(CHG_INT, 6, 3, 3, 8),
[RICOH619_IRQ_FWVADPSINT] = RICOH619_IRQ(CHG_INT, 6, 4, 4, 8),
[RICOH619_IRQ_FWVUSBSINT] = RICOH619_IRQ(CHG_INT, 6, 5, 5, 8),
[RICOH619_IRQ_FONCHGINT] = RICOH619_IRQ(CHG_INT, 6, 6, 0, 9),
[RICOH619_IRQ_FCHGCMPINT] = RICOH619_IRQ(CHG_INT, 6, 7, 1, 9),
[RICOH619_IRQ_FBATOPENINT] = RICOH619_IRQ(CHG_INT, 6, 8, 2, 9),
[RICOH619_IRQ_FSLPMODEINT] = RICOH619_IRQ(CHG_INT, 6, 9, 3, 9),
[RICOH619_IRQ_FBTEMPJTA1INT] = RICOH619_IRQ(CHG_INT, 6, 10, 4, 9),
[RICOH619_IRQ_FBTEMPJTA2INT] = RICOH619_IRQ(CHG_INT, 6, 11, 5, 9),
[RICOH619_IRQ_FBTEMPJTA3INT] = RICOH619_IRQ(CHG_INT, 6, 12, 6, 9),
[RICOH619_IRQ_FBTEMPJTA4INT] = RICOH619_IRQ(CHG_INT, 6, 13, 7, 9),
[RICOH619_IRQ_FCURTERMINT] = RICOH619_IRQ(CHG_INT, 6, 14, 0, 10),
[RICOH619_IRQ_FVOLTERMINT] = RICOH619_IRQ(CHG_INT, 6, 15, 1, 10),
[RICOH619_IRQ_FICRVSINT] = RICOH619_IRQ(CHG_INT, 6, 16, 2, 10),
[RICOH619_IRQ_FPOOR_CHGCURINT] = RICOH619_IRQ(CHG_INT, 6, 17, 3, 10),
[RICOH619_IRQ_FOSCFDETINT1] = RICOH619_IRQ(CHG_INT, 6, 18, 4, 10),
[RICOH619_IRQ_FOSCFDETINT2] = RICOH619_IRQ(CHG_INT, 6, 19, 5, 10),
[RICOH619_IRQ_FOSCFDETINT3] = RICOH619_IRQ(CHG_INT, 6, 20, 6, 10),
[RICOH619_IRQ_FOSCMDETINT] = RICOH619_IRQ(CHG_INT, 6, 21, 7, 10),
[RICOH619_IRQ_FDIEOFFINT] = RICOH619_IRQ(CHG_INT, 6, 22, 0, 11),
[RICOH619_IRQ_FDIEERRINT] = RICOH619_IRQ(CHG_INT, 6, 23, 1, 11),
[RICOH619_IRQ_FBTEMPERRINT] = RICOH619_IRQ(CHG_INT, 6, 24, 2, 11),
[RICOH619_IRQ_FVBATOVINT] = RICOH619_IRQ(CHG_INT, 6, 25, 3, 11),
[RICOH619_IRQ_FTTIMOVINT] = RICOH619_IRQ(CHG_INT, 6, 26, 4, 11),
[RICOH619_IRQ_FRTIMOVINT] = RICOH619_IRQ(CHG_INT, 6, 27, 5, 11),
[RICOH619_IRQ_FVADPOVSINT] = RICOH619_IRQ(CHG_INT, 6, 28, 6, 11),
[RICOH619_IRQ_FVUSBOVSINT] = RICOH619_IRQ(CHG_INT, 6, 29, 7, 11),
[RICOH619_IRQ_FGCDET] = RICOH619_IRQ(CHG_INT, 6, 30, 0, 12),
[RICOH619_IRQ_FPCDET] = RICOH619_IRQ(CHG_INT, 6, 31, 1, 12),
[RICOH619_IRQ_FWARN_ADP] = RICOH619_IRQ(CHG_INT, 6, 32, 3, 12),
};
static void ricoh619_irq_lock(struct irq_data *irq_data)
{
struct ricoh619 *ricoh619 = irq_data_get_irq_chip_data(irq_data);
mutex_lock(&ricoh619->irq_lock);
}
static void ricoh619_irq_unmask(struct irq_data *irq_data)
{
struct ricoh619 *ricoh619 = irq_data_get_irq_chip_data(irq_data);
unsigned int __irq = irq_data->irq - ricoh619->irq_base;
const struct ricoh619_irq_data *data = &ricoh619_irqs[__irq];
ricoh619->group_irq_en[data->master_bit] |= (1 << data->grp_index);
if (ricoh619->group_irq_en[data->master_bit])
ricoh619->intc_inten_reg |= 1 << data->master_bit;
if (data->master_bit == 6) /* if Charger */
ricoh619->irq_en_reg[data->mask_reg_index]
&= ~(1 << data->int_en_bit);
else
ricoh619->irq_en_reg[data->mask_reg_index]
|= 1 << data->int_en_bit;
}
static void ricoh619_irq_mask(struct irq_data *irq_data)
{
struct ricoh619 *ricoh619 = irq_data_get_irq_chip_data(irq_data);
unsigned int __irq = irq_data->irq - ricoh619->irq_base;
const struct ricoh619_irq_data *data = &ricoh619_irqs[__irq];
ricoh619->group_irq_en[data->master_bit] &= ~(1 << data->grp_index);
if (!ricoh619->group_irq_en[data->master_bit])
ricoh619->intc_inten_reg &= ~(1 << data->master_bit);
if (data->master_bit == 6) /* if Charger */
ricoh619->irq_en_reg[data->mask_reg_index]
|= 1 << data->int_en_bit;
else
ricoh619->irq_en_reg[data->mask_reg_index]
&= ~(1 << data->int_en_bit);
}
static void ricoh619_irq_sync_unlock(struct irq_data *irq_data)
{
struct ricoh619 *ricoh619 = irq_data_get_irq_chip_data(irq_data);
int i;
for (i = 0; i < ARRAY_SIZE(ricoh619->gpedge_reg); i++) {
if (ricoh619->gpedge_reg[i] != ricoh619->gpedge_cache[i]) {
if (!WARN_ON(ricoh619_write(ricoh619->dev,
gpedge_add[i],
ricoh619->gpedge_reg[i])))
ricoh619->gpedge_cache[i] =
ricoh619->gpedge_reg[i];
}
}
for (i = 0; i < ARRAY_SIZE(ricoh619->irq_en_reg); i++) {
if (ricoh619->irq_en_reg[i] != ricoh619->irq_en_cache[i]) {
if (!WARN_ON(ricoh619_write(ricoh619->dev,
irq_en_add[i],
ricoh619->irq_en_reg[i])))
ricoh619->irq_en_cache[i] =
ricoh619->irq_en_reg[i];
}
}
if (ricoh619->intc_inten_reg != ricoh619->intc_inten_cache) {
if (!WARN_ON(ricoh619_write(ricoh619->dev,
RICOH619_INTC_INTEN, ricoh619->intc_inten_reg)))
ricoh619->intc_inten_cache = ricoh619->intc_inten_reg;
}
mutex_unlock(&ricoh619->irq_lock);
}
static int ricoh619_irq_set_type(struct irq_data *irq_data, unsigned int type)
{
struct ricoh619 *ricoh619 = irq_data_get_irq_chip_data(irq_data);
unsigned int __irq = irq_data->irq - ricoh619->irq_base;
const struct ricoh619_irq_data *data = &ricoh619_irqs[__irq];
int val = 0;
int gpedge_index;
int gpedge_bit_pos;
if (data->int_type & GPIO_INT) {
gpedge_index = data->int_en_bit / 4;
gpedge_bit_pos = data->int_en_bit % 4;
if (type & IRQ_TYPE_EDGE_FALLING)
val |= 0x2;
if (type & IRQ_TYPE_EDGE_RISING)
val |= 0x1;
ricoh619->gpedge_reg[gpedge_index] &= ~(3 << gpedge_bit_pos);
ricoh619->gpedge_reg[gpedge_index] |= (val << gpedge_bit_pos);
ricoh619_irq_unmask(irq_data);
}
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int ricoh619_irq_set_wake(struct irq_data *irq_data, unsigned int on)
{
struct ricoh619 *ricoh619 = irq_data_get_irq_chip_data(irq_data);
return irq_set_irq_wake(ricoh619->chip_irq, on); //i2c->irq
}
#else
#define ricoh619_irq_set_wake NULL
#endif
static irqreturn_t ricoh619_irq(int irq, void *data)
{
struct ricoh619 *ricoh619 = data;
u8 int_sts[MAX_INTERRUPT_MASKS];
u8 master_int;
int i;
int ret;
unsigned int rtc_int_sts = 0;
/* Clear the status */
for (i = 0; i < MAX_INTERRUPT_MASKS; i++)
int_sts[i] = 0;
ret = ricoh619_read(ricoh619->dev, RICOH619_INTC_INTMON,
&master_int);
// printk("PMU1: %s: master_int=0x%x\n", __func__, master_int);
if (ret < 0) {
dev_err(ricoh619->dev, "Error in reading reg 0x%02x "
"error: %d\n", RICOH619_INTC_INTMON, ret);
return IRQ_HANDLED;
}
/* Mask Charger Interrupt */
if((CHG_INT | ADC_INT) & master_int){
for (i=8; i < MAX_INTERRUPT_MASKS; i++) {
ret = ricoh619_write(ricoh619->dev,
irq_en_add[i], 0xff);
if (ret < 0) {
dev_err(ricoh619->dev,
"Error in write reg 0x%02x "
"error: %d\n",
irq_en_add[i], ret);
}
}
//Disable ADC interrupt
for (i=3; i < 6; i++) {
ret = ricoh619_write(ricoh619->dev, irq_en_add[i], 0x0);
if (ret < 0) {
dev_err(ricoh619->dev, "Error in write reg 0x%02x "
"error: %d\n", irq_en_add[i],
ret);
}
}
}
for (i = 0; i < MAX_INTERRUPT_MASKS; ++i) {
/* Even if INTC_INTMON register = 1, INT signal might not output
because INTC_INTMON register indicates only interrupt facter level.
So remove the following procedure */
// if (!(master_int & main_int_type[i]))
// continue;
ret = ricoh619_read(ricoh619->dev,
irq_mon_add[i], &int_sts[i]);
// printk("PMU2: %s: int_sts[%d]=0x%x\n", __func__,i, int_sts[i]);
if (ret < 0) {
dev_err(ricoh619->dev, "Error in reading reg 0x%02x "
"error: %d\n", irq_mon_add[i], ret);
int_sts[i] = 0;
continue;
}
if (main_int_type[i] & RTC_INT) {
// Changes status bit position from RTCCNT2 to RTCCNT1
rtc_int_sts = 0;
if (int_sts[i] & 0x1)
rtc_int_sts |= BIT(6);
if (int_sts[i] & 0x4)
rtc_int_sts |= BIT(0);
}
ret = ricoh619_write(ricoh619->dev,
irq_clr_add[i], ~int_sts[i]);
if (ret < 0) {
dev_err(ricoh619->dev, "Error in reading reg 0x%02x "
"error: %d\n", irq_clr_add[i], ret);
}
if (main_int_type[i] & RTC_INT)
int_sts[i] = rtc_int_sts;
}
/* Merge gpio interrupts for rising and falling case*/
int_sts[6] |= int_sts[7];
/* Call interrupt handler if enabled */
for (i = 0; i < RICOH619_NR_IRQS; ++i) {
const struct ricoh619_irq_data *data = &ricoh619_irqs[i];
if ((int_sts[data->mask_reg_index] & (1 << data->int_en_bit)) &&
(ricoh619->group_irq_en[data->master_bit] &
(1 << data->grp_index)))
handle_nested_irq(ricoh619->irq_base + i);
}
// printk(KERN_INFO "PMU: %s: out\n", __func__);
return IRQ_HANDLED;
}
static struct irq_chip ricoh619_irq_chip = {
.name = "ricoh619",
.irq_mask = ricoh619_irq_mask,
.irq_unmask = ricoh619_irq_unmask,
.irq_bus_lock = ricoh619_irq_lock,
.irq_bus_sync_unlock = ricoh619_irq_sync_unlock,
.irq_set_type = ricoh619_irq_set_type,
.irq_set_wake = ricoh619_irq_set_wake,
};
int ricoh619_irq_init(struct ricoh619 *ricoh619, int irq,
int irq_base)
{
int i, ret;
if (!irq_base) {
dev_warn(ricoh619->dev, "No interrupt support on IRQ base\n");
return -EINVAL;
}
mutex_init(&ricoh619->irq_lock);
/* Initialize all locals to 0 */
for (i = 0; i < 8; i++) {
ricoh619->irq_en_cache[i] = 0;
ricoh619->irq_en_reg[i] = 0;
}
// Charger Mask register must be set to 1 for masking Int output.
for (i = 8; i < MAX_INTERRUPT_MASKS; i++) {
ricoh619->irq_en_cache[i] = 0xff;
ricoh619->irq_en_reg[i] = 0xff;
}
ricoh619->intc_inten_cache = 0;
ricoh619->intc_inten_reg = 0;
for (i = 0; i < MAX_GPEDGE_REG; i++) {
ricoh619->gpedge_cache[i] = 0;
ricoh619->gpedge_reg[i] = 0;
}
/* Initailize all int register to 0 */
for (i = 0; i < MAX_INTERRUPT_MASKS; i++) {
ret = ricoh619_write(ricoh619->dev,
irq_en_add[i],
ricoh619->irq_en_reg[i]);
if (ret < 0)
dev_err(ricoh619->dev, "Error in writing reg 0x%02x "
"error: %d\n", irq_en_add[i], ret);
}
for (i = 0; i < MAX_GPEDGE_REG; i++) {
ret = ricoh619_write(ricoh619->dev,
gpedge_add[i],
ricoh619->gpedge_reg[i]);
if (ret < 0)
dev_err(ricoh619->dev, "Error in writing reg 0x%02x "
"error: %d\n", gpedge_add[i], ret);
}
ret = ricoh619_write(ricoh619->dev, RICOH619_INTC_INTEN, 0x0);
if (ret < 0)
dev_err(ricoh619->dev, "Error in writing reg 0x%02x "
"error: %d\n", RICOH619_INTC_INTEN, ret);
/* Clear all interrupts in case they woke up active. */
for (i = 0; i < MAX_INTERRUPT_MASKS; i++) {
ret = ricoh619_write(ricoh619->dev,
irq_clr_add[i], 0);
if (ret < 0)
dev_err(ricoh619->dev, "Error in writing reg 0x%02x "
"error: %d\n", irq_clr_add[i], ret);
}
ricoh619->irq_base = irq_base;
ricoh619->chip_irq = irq;
for (i = 0; i < RICOH619_NR_IRQS; i++) {
int __irq = i + ricoh619->irq_base;
irq_set_chip_data(__irq, ricoh619);
irq_set_chip_and_handler(__irq, &ricoh619_irq_chip,
handle_simple_irq);
irq_set_nested_thread(__irq, 1);
#ifdef CONFIG_ARM
set_irq_flags(__irq, IRQF_VALID);
#endif
}
ret = request_threaded_irq(irq, NULL, ricoh619_irq,
IRQ_TYPE_EDGE_FALLING|IRQF_DISABLED|IRQF_ONESHOT,
"ricoh619", ricoh619);
if (ret < 0)
dev_err(ricoh619->dev, "Error in registering interrupt "
"error: %d\n", ret);
/*
if (!ret) {
device_init_wakeup(ricoh619->dev, 1);
enable_irq_wake(irq);
}
*/
return ret;
}
int ricoh619_irq_exit(struct ricoh619 *ricoh619)
{
if (ricoh619->chip_irq)
free_irq(ricoh619->chip_irq, ricoh619);
return 0;
}

852
drivers/mfd/ricoh619.c Normal file
View File

@@ -0,0 +1,852 @@
/*
* driver/mfd/ricoh619.c
*
* Core driver implementation to access RICOH RC5T619 power management chip.
*
* Copyright (C) 2012-2013 RICOH COMPANY,LTD
*
* Based on code
* Copyright (C) 2011 NVIDIA Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*#define DEBUG 1*/
/*#define VERBOSE_DEBUG 1*/
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/mfd/core.h>
#include <linux/mfd/ricoh619.h>
struct ricoh619 *g_ricoh619;
struct sleep_control_data {
u8 reg_add;
};
#define SLEEP_INIT(_id, _reg) \
[RICOH619_DS_##_id] = {.reg_add = _reg}
static struct sleep_control_data sleep_data[] = {
SLEEP_INIT(DC1, 0x16),
SLEEP_INIT(DC2, 0x17),
SLEEP_INIT(DC3, 0x18),
SLEEP_INIT(DC4, 0x19),
SLEEP_INIT(DC5, 0x1A),
SLEEP_INIT(LDO1, 0x1B),
SLEEP_INIT(LDO2, 0x1C),
SLEEP_INIT(LDO3, 0x1D),
SLEEP_INIT(LDO4, 0x1E),
SLEEP_INIT(LDO5, 0x1F),
SLEEP_INIT(LDO6, 0x20),
SLEEP_INIT(LDO7, 0x21),
SLEEP_INIT(LDO8, 0x22),
SLEEP_INIT(LDO9, 0x23),
SLEEP_INIT(LDO10, 0x24),
SLEEP_INIT(PSO0, 0x25),
SLEEP_INIT(PSO1, 0x26),
SLEEP_INIT(PSO2, 0x27),
SLEEP_INIT(PSO3, 0x28),
SLEEP_INIT(PSO4, 0x29),
SLEEP_INIT(LDORTC1, 0x2A),
};
static inline int __ricoh619_read(struct i2c_client *client,
u8 reg, uint8_t *val)
{
int ret;
ret = i2c_smbus_read_byte_data(client, reg);
if (ret < 0) {
dev_err(&client->dev, "failed reading at 0x%02x\n", reg);
return ret;
}
*val = (uint8_t)ret;
dev_dbg(&client->dev, "ricoh619: reg read reg=%x, val=%x\n",
reg, *val);
return 0;
}
static inline int __ricoh619_bulk_reads(struct i2c_client *client, u8 reg,
int len, uint8_t *val)
{
int ret;
int i;
ret = i2c_smbus_read_i2c_block_data(client, reg, len, val);
if (ret < 0) {
dev_err(&client->dev, "failed reading from 0x%02x\n", reg);
return ret;
}
for (i = 0; i < len; ++i) {
dev_dbg(&client->dev, "ricoh619: reg read reg=%x, val=%x\n",
reg + i, *(val + i));
}
return 0;
}
static inline int __ricoh619_write(struct i2c_client *client,
u8 reg, uint8_t val)
{
int ret;
dev_dbg(&client->dev, "ricoh619: reg write reg=%x, val=%x\n",
reg, val);
ret = i2c_smbus_write_byte_data(client, reg, val);
if (ret < 0) {
dev_err(&client->dev, "failed writing 0x%02x to 0x%02x\n",
val, reg);
return ret;
}
return 0;
}
static inline int __ricoh619_bulk_writes(struct i2c_client *client, u8 reg,
int len, uint8_t *val)
{
int ret;
int i;
for (i = 0; i < len; ++i) {
dev_dbg(&client->dev, "ricoh619: reg write reg=%x, val=%x\n",
reg + i, *(val + i));
}
ret = i2c_smbus_write_i2c_block_data(client, reg, len, val);
if (ret < 0) {
dev_err(&client->dev, "failed writings to 0x%02x\n", reg);
return ret;
}
return 0;
}
static inline int set_bank_ricoh619(struct device *dev, int bank)
{
struct ricoh619 *ricoh619 = dev_get_drvdata(dev);
int ret;
if (bank != (bank & 1))
return -EINVAL;
if (bank == ricoh619->bank_num)
return 0;
ret = __ricoh619_write(to_i2c_client(dev), RICOH619_REG_BANKSEL, bank);
if (!ret)
ricoh619->bank_num = bank;
return ret;
}
int ricoh619_write(struct device *dev, u8 reg, uint8_t val)
{
struct ricoh619 *ricoh619 = dev_get_drvdata(dev);
int ret = 0;
mutex_lock(&ricoh619->io_lock);
ret = set_bank_ricoh619(dev, 0);
if( !ret )
ret = __ricoh619_write(to_i2c_client(dev), reg, val);
mutex_unlock(&ricoh619->io_lock);
return ret;
}
EXPORT_SYMBOL_GPL(ricoh619_write);
int ricoh619_write_bank1(struct device *dev, u8 reg, uint8_t val)
{
struct ricoh619 *ricoh619 = dev_get_drvdata(dev);
int ret = 0;
mutex_lock(&ricoh619->io_lock);
ret = set_bank_ricoh619(dev, 1);
if( !ret )
ret = __ricoh619_write(to_i2c_client(dev), reg, val);
mutex_unlock(&ricoh619->io_lock);
return ret;
}
EXPORT_SYMBOL_GPL(ricoh619_write_bank1);
int ricoh619_bulk_writes(struct device *dev, u8 reg, u8 len, uint8_t *val)
{
struct ricoh619 *ricoh619 = dev_get_drvdata(dev);
int ret = 0;
mutex_lock(&ricoh619->io_lock);
ret = set_bank_ricoh619(dev, 0);
if( !ret )
ret = __ricoh619_bulk_writes(to_i2c_client(dev), reg, len, val);
mutex_unlock(&ricoh619->io_lock);
return ret;
}
EXPORT_SYMBOL_GPL(ricoh619_bulk_writes);
int ricoh619_bulk_writes_bank1(struct device *dev, u8 reg, u8 len, uint8_t *val)
{
struct ricoh619 *ricoh619 = dev_get_drvdata(dev);
int ret = 0;
mutex_lock(&ricoh619->io_lock);
ret = set_bank_ricoh619(dev, 1);
if( !ret )
ret = __ricoh619_bulk_writes(to_i2c_client(dev), reg, len, val);
mutex_unlock(&ricoh619->io_lock);
return ret;
}
EXPORT_SYMBOL_GPL(ricoh619_bulk_writes_bank1);
int ricoh619_read(struct device *dev, u8 reg, uint8_t *val)
{
struct ricoh619 *ricoh619 = dev_get_drvdata(dev);
int ret = 0;
mutex_lock(&ricoh619->io_lock);
ret = set_bank_ricoh619(dev, 0);
if( !ret )
ret = __ricoh619_read(to_i2c_client(dev), reg, val);
mutex_unlock(&ricoh619->io_lock);
return ret;
}
EXPORT_SYMBOL_GPL(ricoh619_read);
int ricoh619_read_bank1(struct device *dev, u8 reg, uint8_t *val)
{
struct ricoh619 *ricoh619 = dev_get_drvdata(dev);
int ret = 0;
mutex_lock(&ricoh619->io_lock);
ret = set_bank_ricoh619(dev, 1);
if( !ret )
ret = __ricoh619_read(to_i2c_client(dev), reg, val);
mutex_unlock(&ricoh619->io_lock);
return ret;
}
EXPORT_SYMBOL_GPL(ricoh619_read_bank1);
int ricoh619_bulk_reads(struct device *dev, u8 reg, u8 len, uint8_t *val)
{
struct ricoh619 *ricoh619 = dev_get_drvdata(dev);
int ret = 0;
mutex_lock(&ricoh619->io_lock);
ret = set_bank_ricoh619(dev, 0);
if( !ret )
ret = __ricoh619_bulk_reads(to_i2c_client(dev), reg, len, val);
mutex_unlock(&ricoh619->io_lock);
return ret;
}
EXPORT_SYMBOL_GPL(ricoh619_bulk_reads);
int ricoh619_bulk_reads_bank1(struct device *dev, u8 reg, u8 len, uint8_t *val)
{
struct ricoh619 *ricoh619 = dev_get_drvdata(dev);
int ret = 0;
mutex_lock(&ricoh619->io_lock);
ret = set_bank_ricoh619(dev, 1);
if( !ret )
ret = __ricoh619_bulk_reads(to_i2c_client(dev), reg, len, val);
mutex_unlock(&ricoh619->io_lock);
return ret;
}
EXPORT_SYMBOL_GPL(ricoh619_bulk_reads_bank1);
int ricoh619_set_bits(struct device *dev, u8 reg, uint8_t bit_mask)
{
struct ricoh619 *ricoh619 = dev_get_drvdata(dev);
uint8_t reg_val;
int ret = 0;
mutex_lock(&ricoh619->io_lock);
ret = set_bank_ricoh619(dev, 0);
if (!ret) {
ret = __ricoh619_read(to_i2c_client(dev), reg, &reg_val);
if (ret)
goto out;
if ((reg_val & bit_mask) != bit_mask) {
reg_val |= bit_mask;
ret = __ricoh619_write(to_i2c_client(dev), reg,
reg_val);
}
}
out:
mutex_unlock(&ricoh619->io_lock);
return ret;
}
EXPORT_SYMBOL_GPL(ricoh619_set_bits);
int ricoh619_clr_bits(struct device *dev, u8 reg, uint8_t bit_mask)
{
struct ricoh619 *ricoh619 = dev_get_drvdata(dev);
uint8_t reg_val;
int ret = 0;
mutex_lock(&ricoh619->io_lock);
ret = set_bank_ricoh619(dev, 0);
if( !ret ){
ret = __ricoh619_read(to_i2c_client(dev), reg, &reg_val);
if (ret)
goto out;
if (reg_val & bit_mask) {
reg_val &= ~bit_mask;
ret = __ricoh619_write(to_i2c_client(dev), reg,
reg_val);
}
}
out:
mutex_unlock(&ricoh619->io_lock);
return ret;
}
EXPORT_SYMBOL_GPL(ricoh619_clr_bits);
int ricoh619_update(struct device *dev, u8 reg, uint8_t val, uint8_t mask)
{
struct ricoh619 *ricoh619 = dev_get_drvdata(dev);
uint8_t reg_val;
int ret = 0;
mutex_lock(&ricoh619->io_lock);
ret = set_bank_ricoh619(dev, 0);
if( !ret ){
ret = __ricoh619_read(ricoh619->client, reg, &reg_val);
if (ret)
goto out;
if ((reg_val & mask) != val) {
reg_val = (reg_val & ~mask) | (val & mask);
ret = __ricoh619_write(ricoh619->client, reg, reg_val);
}
}
out:
mutex_unlock(&ricoh619->io_lock);
return ret;
}
EXPORT_SYMBOL_GPL(ricoh619_update);
int ricoh619_update_bank1(struct device *dev, u8 reg, uint8_t val, uint8_t mask)
{
struct ricoh619 *ricoh619 = dev_get_drvdata(dev);
uint8_t reg_val;
int ret = 0;
mutex_lock(&ricoh619->io_lock);
ret = set_bank_ricoh619(dev, 1);
if( !ret ){
ret = __ricoh619_read(ricoh619->client, reg, &reg_val);
if (ret)
goto out;
if ((reg_val & mask) != val) {
reg_val = (reg_val & ~mask) | (val & mask);
ret = __ricoh619_write(ricoh619->client, reg, reg_val);
}
}
out:
mutex_unlock(&ricoh619->io_lock);
return ret;
}
static struct i2c_client *ricoh619_i2c_client;
int ricoh619_power_off(void)
{
int ret;
uint8_t val;
int err = -1;
struct ricoh619 *ricoh619 = g_ricoh619;
val = g_soc;
val &= 0x7f;
ret = ricoh619_write(ricoh619->dev, RICOH619_PSWR, val);
if (ret < 0)
dev_err(ricoh619->dev, "Error in writing PSWR_REG\n");
if (g_fg_on_mode == 0) {
ret = ricoh619_clr_bits(ricoh619->dev,
RICOH619_FG_CTRL, 0x01);
if (ret < 0)
dev_err(ricoh619->dev, "Error in writing FG_CTRL\n");
}
if (!ricoh619_i2c_client)
return -EINVAL;
//__ricoh618_write(ricoh618_i2c_client, RICOH618_PWR_REP_CNT, 0x0); //Not repeat power ON after power off(Power Off/N_OE)
// __ricoh618_write(ricoh618_i2c_client, RICOH618_PWR_SLP_CNT, 0x1); //Power OFF
ret = ricoh619_clr_bits(ricoh619->dev,RICOH619_PWR_REP_CNT,(0x1<<0));//Not repeat power ON after power off(Power Off/N_OE)
ret = ricoh619_set_bits(ricoh619->dev, RICOH619_PWR_SLP_CNT,(0x1<<0));//Power OFF
if (ret < 0) {
printk("ricoh619 power off error!\n");
return err;
}
return 0;
}
EXPORT_SYMBOL_GPL(ricoh619_power_off);
static int ricoh619_gpio_get(struct gpio_chip *gc, unsigned offset)
{
struct ricoh619 *ricoh619 = container_of(gc, struct ricoh619, gpio_chip);
uint8_t val;
int ret;
ret = ricoh619_read(ricoh619->dev, RICOH619_GPIO_MON_IOIN, &val);
if (ret < 0)
return ret;
return ((val & (0x1 << offset)) != 0);
}
static void ricoh619_gpio_set(struct gpio_chip *gc, unsigned offset,
int value)
{
struct ricoh619 *ricoh619 = container_of(gc, struct ricoh619, gpio_chip);
if (value)
ricoh619_set_bits(ricoh619->dev, RICOH619_GPIO_IOOUT,
1 << offset);
else
ricoh619_clr_bits(ricoh619->dev, RICOH619_GPIO_IOOUT,
1 << offset);
}
static int ricoh619_gpio_input(struct gpio_chip *gc, unsigned offset)
{
struct ricoh619 *ricoh619 = container_of(gc, struct ricoh619, gpio_chip);
return ricoh619_clr_bits(ricoh619->dev, RICOH619_GPIO_IOSEL,
1 << offset);
}
static int ricoh619_gpio_output(struct gpio_chip *gc, unsigned offset,
int value)
{
struct ricoh619 *ricoh619 = container_of(gc, struct ricoh619, gpio_chip);
ricoh619_gpio_set(gc, offset, value);
return ricoh619_set_bits(ricoh619->dev, RICOH619_GPIO_IOSEL,
1 << offset);
}
static int ricoh619_gpio_to_irq(struct gpio_chip *gc, unsigned off)
{
struct ricoh619 *ricoh619 = container_of(gc, struct ricoh619, gpio_chip);
if ((off >= 0) && (off < 8))
return ricoh619->irq_base + RICOH619_IRQ_GPIO0 + off;
return -EIO;
}
static void __devinit ricoh619_gpio_init(struct ricoh619 *ricoh619,
struct ricoh619_platform_data *pdata)
{
int ret;
int i;
struct ricoh619_gpio_init_data *ginit;
if (pdata->gpio_base <= 0)
return;
for (i = 0; i < pdata->num_gpioinit_data; ++i) {
ginit = &pdata->gpio_init_data[i];
if (!ginit->init_apply)
continue;
if (ginit->output_mode_en) {
/* GPIO output mode */
if (ginit->output_val)
/* output H */
ret = ricoh619_set_bits(ricoh619->dev,
RICOH619_GPIO_IOOUT, 1 << i);
else
/* output L */
ret = ricoh619_clr_bits(ricoh619->dev,
RICOH619_GPIO_IOOUT, 1 << i);
if (!ret)
ret = ricoh619_set_bits(ricoh619->dev,
RICOH619_GPIO_IOSEL, 1 << i);
} else
/* GPIO input mode */
ret = ricoh619_clr_bits(ricoh619->dev,
RICOH619_GPIO_IOSEL, 1 << i);
/* if LED function enabled in OTP */
if (ginit->led_mode) {
/* LED Mode 1 */
if (i == 0) /* GP0 */
ret = ricoh619_set_bits(ricoh619->dev,
RICOH619_GPIO_LED_FUNC,
0x04 | (ginit->led_func & 0x03));
if (i == 1) /* GP1 */
ret = ricoh619_set_bits(ricoh619->dev,
RICOH619_GPIO_LED_FUNC,
0x40 | (ginit->led_func & 0x03) << 4);
}
if (ret < 0)
dev_err(ricoh619->dev, "Gpio %d init "
"dir configuration failed: %d\n", i, ret);
}
ricoh619->gpio_chip.owner = THIS_MODULE;
ricoh619->gpio_chip.label = ricoh619->client->name;
ricoh619->gpio_chip.dev = ricoh619->dev;
ricoh619->gpio_chip.base = pdata->gpio_base;
ricoh619->gpio_chip.ngpio = RICOH619_NR_GPIO;
ricoh619->gpio_chip.can_sleep = 1;
ricoh619->gpio_chip.direction_input = ricoh619_gpio_input;
ricoh619->gpio_chip.direction_output = ricoh619_gpio_output;
ricoh619->gpio_chip.set = ricoh619_gpio_set;
ricoh619->gpio_chip.get = ricoh619_gpio_get;
ricoh619->gpio_chip.to_irq = ricoh619_gpio_to_irq;
ret = gpiochip_add(&ricoh619->gpio_chip);
if (ret)
dev_warn(ricoh619->dev, "GPIO registration failed: %d\n", ret);
}
static int ricoh619_remove_subdev(struct device *dev, void *unused)
{
platform_device_unregister(to_platform_device(dev));
return 0;
}
static int ricoh619_remove_subdevs(struct ricoh619 *ricoh619)
{
return device_for_each_child(ricoh619->dev, NULL,
ricoh619_remove_subdev);
}
static int __devinit ricoh619_add_subdevs(struct ricoh619 *ricoh619,
struct ricoh619_platform_data *pdata)
{
struct ricoh619_subdev_info *subdev;
struct platform_device *pdev;
int i, ret = 0;
for (i = 0; i < pdata->num_subdevs; i++) {
subdev = &pdata->subdevs[i];
pdev = platform_device_alloc(subdev->name, subdev->id);
pdev->dev.parent = ricoh619->dev;
pdev->dev.platform_data = subdev->platform_data;
ret = platform_device_add(pdev);
if (ret)
goto failed;
}
return 0;
failed:
ricoh619_remove_subdevs(ricoh619);
return ret;
}
#ifdef CONFIG_DEBUG_FS
#include <linux/debugfs.h>
#include <linux/seq_file.h>
static void print_regs(const char *header, struct seq_file *s,
struct i2c_client *client, int start_offset,
int end_offset)
{
uint8_t reg_val;
int i;
int ret;
seq_printf(s, "%s\n", header);
for (i = start_offset; i <= end_offset; ++i) {
ret = __ricoh619_read(client, i, &reg_val);
if (ret >= 0)
seq_printf(s, "Reg 0x%02x Value 0x%02x\n", i, reg_val);
}
seq_printf(s, "------------------\n");
}
static int dbg_ricoh_show(struct seq_file *s, void *unused)
{
struct ricoh619 *ricoh = s->private;
struct i2c_client *client = ricoh->client;
seq_printf(s, "RICOH619 Registers\n");
seq_printf(s, "------------------\n");
print_regs("System Regs", s, client, 0x0, 0x05);
print_regs("Power Control Regs", s, client, 0x07, 0x2B);
print_regs("DCDC Regs", s, client, 0x2C, 0x43);
print_regs("LDO Regs", s, client, 0x44, 0x61);
print_regs("ADC Regs", s, client, 0x64, 0x8F);
print_regs("GPIO Regs", s, client, 0x90, 0x98);
print_regs("INTC Regs", s, client, 0x9C, 0x9E);
print_regs("RTC Regs", s, client, 0xA0, 0xAF);
print_regs("OPT Regs", s, client, 0xB0, 0xB1);
print_regs("CHG Regs", s, client, 0xB2, 0xDF);
print_regs("FUEL Regs", s, client, 0xE0, 0xFC);
return 0;
}
static int dbg_ricoh_open(struct inode *inode, struct file *file)
{
return single_open(file, dbg_ricoh_show, inode->i_private);
}
static const struct file_operations debug_fops = {
.open = dbg_ricoh_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static void __init ricoh619_debuginit(struct ricoh619 *ricoh)
{
(void)debugfs_create_file("ricoh619", S_IRUGO, NULL,
ricoh, &debug_fops);
}
#else
static void print_regs(const char *header, struct i2c_client *client,
int start_offset, int end_offset)
{
uint8_t reg_val;
int i;
int ret;
printk(KERN_INFO "%s\n", header);
for (i = start_offset; i <= end_offset; ++i) {
ret = __ricoh619_read(client, i, &reg_val);
if (ret >= 0)
printk(KERN_INFO "Reg 0x%02x Value 0x%02x\n",
i, reg_val);
}
printk(KERN_INFO "------------------\n");
}
static void __init ricoh619_debuginit(struct ricoh619 *ricoh)
{
struct i2c_client *client = ricoh->client;
printk(KERN_INFO "RICOH619 Registers\n");
printk(KERN_INFO "------------------\n");
print_regs("System Regs", client, 0x0, 0x05);
print_regs("Power Control Regs", client, 0x07, 0x2B);
print_regs("DCDC Regs", client, 0x2C, 0x43);
print_regs("LDO Regs", client, 0x44, 0x5C);
print_regs("ADC Regs", client, 0x64, 0x8F);
print_regs("GPIO Regs", client, 0x90, 0x9B);
print_regs("INTC Regs", client, 0x9C, 0x9E);
print_regs("OPT Regs", client, 0xB0, 0xB1);
print_regs("CHG Regs", client, 0xB2, 0xDF);
print_regs("FUEL Regs", client, 0xE0, 0xFC);
return 0;
}
#endif
static void __devinit ricoh619_noe_init(struct ricoh619 *ricoh)
{
struct i2c_client *client = ricoh->client;
__ricoh619_write(client, RICOH619_PWR_NOE_TIMSET, 0x0); //N_OE timer setting to 128mS
__ricoh619_write(client, RICOH619_PWR_REP_CNT, 0x1); //Repeat power ON after reset (Power Off/N_OE)
}
static int ricoh619_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct ricoh619 *ricoh619;
struct ricoh619_platform_data *pdata = client->dev.platform_data;
int ret;
uint8_t control;
printk(KERN_INFO "PMU: %s:\n", __func__);
ricoh619 = kzalloc(sizeof(struct ricoh619), GFP_KERNEL);
if (ricoh619 == NULL)
return -ENOMEM;
ricoh619->client = client;
ricoh619->dev = &client->dev;
i2c_set_clientdata(client, ricoh619);
mutex_init(&ricoh619->io_lock);
ret = ricoh619_read(ricoh619->dev, 0x36, &control);
if ((control < 0) || (control == 0xff)) {
printk(KERN_INFO "The device is not ricoh619\n");
return 0;
}
/***************set noe time 128ms**************/
ret = ricoh619_set_bits(ricoh619->dev,0x11,(0x1 <<3));
ret = ricoh619_clr_bits(ricoh619->dev,0x11,(0x7 <<0));
ret = ricoh619_clr_bits(ricoh619->dev,0x11,(0x1 <<3));
/**********************************************/
/***************set PKEY long press time 0sec*******/
ret = ricoh619_set_bits(ricoh619->dev,0x10,(0x1 <<7));
ret = ricoh619_clr_bits(ricoh619->dev,0x10,(0x1 <<3));
ret = ricoh619_clr_bits(ricoh619->dev,0x10,(0x1 <<7));
/**********************************************/
ricoh619->bank_num = 0;
// ret = pdata->init_port(client->irq); // For init PMIC_IRQ port
if (client->irq) {
ret = ricoh619_irq_init(ricoh619, client->irq, pdata->irq_base);
if (ret) {
dev_err(&client->dev, "IRQ init failed: %d\n", ret);
goto err_irq_init;
}
}
ret = ricoh619_add_subdevs(ricoh619, pdata);
if (ret) {
dev_err(&client->dev, "add devices failed: %d\n", ret);
goto err_add_devs;
}
ricoh619_noe_init(ricoh619);
g_ricoh619 = ricoh619;
if (pdata && pdata->pre_init) {
ret = pdata->pre_init(ricoh619);
if (ret != 0) {
dev_err(ricoh619->dev, "pre_init() failed: %d\n", ret);
goto err;
}
}
//ricoh619_gpio_init(ricoh619, pdata);
ricoh619_debuginit(ricoh619);
if (pdata && pdata->post_init) {
ret = pdata->post_init(ricoh619);
if (ret != 0) {
dev_err(ricoh619->dev, "post_init() failed: %d\n", ret);
goto err;
}
}
ricoh619_i2c_client = client;
return 0;
err:
mfd_remove_devices(ricoh619->dev);
kfree(ricoh619);
err_add_devs:
if (client->irq)
ricoh619_irq_exit(ricoh619);
err_irq_init:
kfree(ricoh619);
return ret;
}
static int __devexit ricoh619_i2c_remove(struct i2c_client *client)
{
struct ricoh619 *ricoh619 = i2c_get_clientdata(client);
if (client->irq)
ricoh619_irq_exit(ricoh619);
ricoh619_remove_subdevs(ricoh619);
kfree(ricoh619);
return 0;
}
#ifdef CONFIG_PM
static int ricoh619_i2c_suspend(struct i2c_client *client, pm_message_t state)
{
if (client->irq)
disable_irq(client->irq);
return 0;
}
int pwrkey_wakeup;
static int ricoh619_i2c_resume(struct i2c_client *client)
{
uint8_t reg_val;
int ret;
ret = __ricoh619_read(client, RICOH619_INT_IR_SYS, &reg_val);
if(reg_val & 0x01) { //If PWR_KEY wakeup
// printk("PMU: %s: PWR_KEY Wakeup\n",__func__);
pwrkey_wakeup = 1;
__ricoh619_write(client, RICOH619_INT_IR_SYS, 0x0); //Clear PWR_KEY IRQ
}
enable_irq(client->irq);
return 0;
}
#endif
static const struct i2c_device_id ricoh619_i2c_id[] = {
{"ricoh619", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, ricoh619_i2c_id);
static struct i2c_driver ricoh619_i2c_driver = {
.driver = {
.name = "ricoh619",
.owner = THIS_MODULE,
},
.probe = ricoh619_i2c_probe,
.remove = __devexit_p(ricoh619_i2c_remove),
#ifdef CONFIG_PM
.suspend = ricoh619_i2c_suspend,
.resume = ricoh619_i2c_resume,
#endif
.id_table = ricoh619_i2c_id,
};
static int __init ricoh619_i2c_init(void)
{
int ret = -ENODEV;
ret = i2c_add_driver(&ricoh619_i2c_driver);
if (ret != 0)
pr_err("Failed to register I2C driver: %d\n", ret);
return ret;
}
subsys_initcall_sync(ricoh619_i2c_init);
static void __exit ricoh619_i2c_exit(void)
{
i2c_del_driver(&ricoh619_i2c_driver);
}
module_exit(ricoh619_i2c_exit);
MODULE_DESCRIPTION("RICOH RC5T619 PMU multi-function core driver");
MODULE_AUTHOR("zhangqing <zhangqing@rock-chips.com>");
MODULE_LICENSE("GPL");

7
drivers/power/Kconfig Executable file → Normal file
View File

@@ -71,6 +71,13 @@ config WM8350_POWER
Say Y here to enable support for the power management unit
provided by the Wolfson Microelectronics WM8350 PMIC.
config BATTERY_RICOH619
tristate "Ricoh RC5T619 PMIC battery driver"
depends on MFD_RICOH619 && I2C && GENERIC_HARDIRQS
help
Say Y to enable support for the battery control of the Ricoh RC5T619
Power Management device.
config TEST_POWER
tristate "Test power driver"
help

View File

@@ -48,4 +48,4 @@ obj-$(CONFIG_BATTERY_RK30_ADC) += rk30_adc_battery.o
obj-$(CONFIG_PLAT_RK) += rk29_charger_display.o
obj-$(CONFIG_BATTERY_RK30_ADC_FAC) += rk30_factory_adc_battery.o
obj-$(CONFIG_CW2015_BATTERY) += cw2015_battery.o
obj-$(CONFIG_BATTERY_RICOH619) += ricoh619-battery.o

File diff suppressed because it is too large Load Diff

7
drivers/regulator/Kconfig Executable file → Normal file
View File

@@ -171,6 +171,13 @@ config REGULATOR_WM8994
This driver provides support for the voltage regulators on the
WM8994 CODEC.
config REGULATOR_RICOH619
tristate "RICOH 619 Power regulators"
depends on MFD_RICOH619
default n
help
This driver supports regulator driver for RICOH619 PMIC.
config REGULATOR_DA903X
tristate "Support regulators on Dialog Semiconductor DA9030/DA9034 PMIC"
depends on PMIC_DA903X

1
drivers/regulator/Makefile Executable file → Normal file
View File

@@ -53,5 +53,6 @@ obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
obj-$(CONFIG_REGULATOR_ACT8891) += act8891.o
obj-$(CONFIG_REGULATOR_ACT8931) += act8931.o
obj-$(CONFIG_REGULATOR_ACT8846) += act8846.o
obj-$(CONFIG_REGULATOR_RICOH619) += ricoh619-regulator.o
ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG

View File

@@ -0,0 +1,578 @@
/*
* drivers/regulator/ricoh619-regulator.c
*
* Regulator driver for RICOH619 power management chip.
*
* Copyright (C) 2012-2013 RICOH COMPANY,LTD
*
* Based on code
* Copyright (C) 2011 NVIDIA Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*#define DEBUG 1*/
/*#define VERBOSE_DEBUG 1*/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/mfd/ricoh619.h>
#include <linux/regulator/ricoh619-regulator.h>
struct ricoh619_regulator {
int id;
int sleep_id;
/* Regulator register address.*/
u8 reg_en_reg;
u8 en_bit;
u8 reg_disc_reg;
u8 disc_bit;
u8 vout_reg;
u8 vout_mask;
u8 vout_reg_cache;
u8 sleep_reg;
u8 eco_reg;
u8 eco_bit;
u8 eco_slp_reg;
u8 eco_slp_bit;
/* chip constraints on regulator behavior */
int min_uV;
int max_uV;
int step_uV;
int nsteps;
/* regulator specific turn-on delay */
u16 delay;
/* used by regulator core */
struct regulator_desc desc;
/* Device */
struct device *dev;
};
//static unsigned int ricoh619_suspend_status = 0;
static inline struct device *to_ricoh619_dev(struct regulator_dev *rdev)
{
return rdev_get_dev(rdev)->parent->parent;
}
static int ricoh619_regulator_enable_time(struct regulator_dev *rdev)
{
struct ricoh619_regulator *ri = rdev_get_drvdata(rdev);
return ri->delay;
}
static int ricoh619_reg_is_enabled(struct regulator_dev *rdev)
{
struct ricoh619_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_ricoh619_dev(rdev);
uint8_t control;
int ret;
ret = ricoh619_read(parent, ri->reg_en_reg, &control);
if (ret < 0) {
dev_err(&rdev->dev, "Error in reading the control register\n");
return ret;
}
return (((control >> ri->en_bit) & 1) == 1);
}
static int ricoh619_reg_enable(struct regulator_dev *rdev)
{
struct ricoh619_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_ricoh619_dev(rdev);
int ret;
ret = ricoh619_set_bits(parent, ri->reg_en_reg, (1 << ri->en_bit));
if (ret < 0) {
dev_err(&rdev->dev, "Error in updating the STATE register\n");
return ret;
}
udelay(ri->delay);
return ret;
}
static int ricoh619_reg_disable(struct regulator_dev *rdev)
{
struct ricoh619_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_ricoh619_dev(rdev);
int ret;
ret = ricoh619_clr_bits(parent, ri->reg_en_reg, (1 << ri->en_bit));
if (ret < 0)
dev_err(&rdev->dev, "Error in updating the STATE register\n");
return ret;
}
static int ricoh619_list_voltage(struct regulator_dev *rdev, unsigned index)
{
struct ricoh619_regulator *ri = rdev_get_drvdata(rdev);
return ri->min_uV + (ri->step_uV * index);
}
static int __ricoh619_set_s_voltage(struct device *parent,
struct ricoh619_regulator *ri, int min_uV, int max_uV)
{
int vsel;
int ret;
if ((min_uV < ri->min_uV) || (max_uV > ri->max_uV))
return -EDOM;
vsel = (min_uV - ri->min_uV + ri->step_uV - 1)/ri->step_uV;
if (vsel > ri->nsteps)
return -EDOM;
ret = ricoh619_update(parent, ri->sleep_reg, vsel, ri->vout_mask);
if (ret < 0)
dev_err(ri->dev, "Error in writing the sleep register\n");
return ret;
}
static int __ricoh619_set_voltage(struct device *parent,
struct ricoh619_regulator *ri, int min_uV, int max_uV,
unsigned *selector)
{
int vsel;
int ret;
uint8_t vout_val;
if ((min_uV < ri->min_uV) || (max_uV > ri->max_uV))
return -EDOM;
vsel = (min_uV - ri->min_uV + ri->step_uV - 1)/ri->step_uV;
if (vsel > ri->nsteps)
return -EDOM;
if (selector)
*selector = vsel;
vout_val = (ri->vout_reg_cache & ~ri->vout_mask) |
(vsel & ri->vout_mask);
ret = ricoh619_write(parent, ri->vout_reg, vout_val);
if (ret < 0)
dev_err(ri->dev, "Error in writing the Voltage register\n");
else
ri->vout_reg_cache = vout_val;
return ret;
}
static int ricoh619_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV, unsigned *selector)
{
struct ricoh619_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_ricoh619_dev(rdev);
// if(ricoh619_suspend_status)
// return -EBUSY;
return __ricoh619_set_voltage(parent, ri, min_uV, max_uV, selector);
}
static int ricoh619_set_suspend_voltage(struct regulator_dev *rdev,
int uV)
{
struct ricoh619_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_ricoh619_dev(rdev);
return __ricoh619_set_s_voltage(parent, ri, uV, uV);
}
static int ricoh619_get_voltage(struct regulator_dev *rdev)
{
struct ricoh619_regulator *ri = rdev_get_drvdata(rdev);
uint8_t vsel;
vsel = ri->vout_reg_cache & ri->vout_mask;
return ri->min_uV + vsel * ri->step_uV;
}
int ricoh619_regulator_enable_eco_mode(struct regulator_dev *rdev)
{
struct ricoh619_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_ricoh619_dev(rdev);
int ret;
ret = ricoh619_set_bits(parent, ri->eco_reg, (1 << ri->eco_bit));
if (ret < 0)
dev_err(&rdev->dev, "Error Enable LDO eco mode\n");
return ret;
}
EXPORT_SYMBOL_GPL(ricoh619_regulator_enable_eco_mode);
int ricoh619_regulator_disable_eco_mode(struct regulator_dev *rdev)
{
struct ricoh619_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_ricoh619_dev(rdev);
int ret;
ret = ricoh619_clr_bits(parent, ri->eco_reg, (1 << ri->eco_bit));
if (ret < 0)
dev_err(&rdev->dev, "Error Disable LDO eco mode\n");
return ret;
}
EXPORT_SYMBOL_GPL(ricoh619_regulator_disable_eco_mode);
int ricoh619_regulator_enable_eco_slp_mode(struct regulator_dev *rdev)
{
struct ricoh619_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_ricoh619_dev(rdev);
int ret;
ret = ricoh619_set_bits(parent, ri->eco_slp_reg, (1 << ri->eco_slp_bit));
if (ret < 0)
dev_err(&rdev->dev, "Error Enable LDO eco mode in d during sleep\n");
return ret;
}
EXPORT_SYMBOL_GPL(ricoh619_regulator_enable_eco_slp_mode);
int ricoh619_regulator_disable_eco_slp_mode(struct regulator_dev *rdev)
{
struct ricoh619_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_ricoh619_dev(rdev);
int ret;
ret = ricoh619_clr_bits(parent, ri->eco_slp_reg, (1 << ri->eco_slp_bit));
if (ret < 0)
dev_err(&rdev->dev, "Error Enable LDO eco mode in d during sleep\n");
return ret;
}
EXPORT_SYMBOL_GPL(ricoh619_regulator_disable_eco_slp_mode);
static unsigned int ricoh619_dcdc_get_mode(struct regulator_dev *rdev)
{
struct ricoh619_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_ricoh619_dev(rdev);
int ret;
uint8_t control;
u8 mask = 0x30;
ret = ricoh619_read(parent, ri->reg_en_reg,&control);
if (ret < 0) {
return ret;
}
control=(control & mask) >> 4;
switch (control) {
case 1:
return REGULATOR_MODE_FAST;
case 0:
return REGULATOR_MODE_NORMAL;
case 2:
return REGULATOR_MODE_STANDBY;
case 4:
return REGULATOR_MODE_NORMAL;
default:
return -1;
}
}
static int ricoh619_dcdc_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
struct ricoh619_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_ricoh619_dev(rdev);
int ret;
uint8_t control;
ret = ricoh619_read(parent, ri->reg_en_reg,&control);
switch(mode)
{
case REGULATOR_MODE_FAST:
return ricoh619_write(parent, ri->reg_en_reg, ((control & 0xef) | 0x10));
case REGULATOR_MODE_NORMAL:
return ricoh619_write(parent, ri->reg_en_reg, (control & 0xcf));
case REGULATOR_MODE_STANDBY:
return ricoh619_write(parent, ri->reg_en_reg, ((control & 0xdf) | 0x20));
default:
printk("error:pmu_619 only powersave pwm psm mode\n");
return -EINVAL;
}
}
static int ricoh619_dcdc_set_voltage_time_sel(struct regulator_dev *rdev, unsigned int old_selector,
unsigned int new_selector)
{
int old_volt, new_volt;
old_volt = ricoh619_list_voltage(rdev, old_selector);
if (old_volt < 0)
return old_volt;
new_volt = ricoh619_list_voltage(rdev, new_selector);
if (new_volt < 0)
return new_volt;
return DIV_ROUND_UP(abs(old_volt - new_volt)*2, 14000);
}
static struct regulator_ops ricoh619_ops = {
.list_voltage = ricoh619_list_voltage,
.set_voltage = ricoh619_set_voltage,
.get_voltage = ricoh619_get_voltage,
.set_suspend_voltage = ricoh619_set_suspend_voltage,
.set_voltage_time_sel = ricoh619_dcdc_set_voltage_time_sel,
.get_mode = ricoh619_dcdc_get_mode,
.set_mode = ricoh619_dcdc_set_mode,
.enable = ricoh619_reg_enable,
.disable = ricoh619_reg_disable,
.is_enabled = ricoh619_reg_is_enabled,
};
#define RICOH619_REG(_id, _en_reg, _en_bit, _disc_reg, _disc_bit, _vout_reg, \
_vout_mask, _ds_reg, _min_uv, _max_uv, _step_uV, _nsteps, \
_ops, _delay, _eco_reg, _eco_bit, _eco_slp_reg, _eco_slp_bit) \
{ \
.reg_en_reg = _en_reg, \
.en_bit = _en_bit, \
.reg_disc_reg = _disc_reg, \
.disc_bit = _disc_bit, \
.vout_reg = _vout_reg, \
.vout_mask = _vout_mask, \
.sleep_reg = _ds_reg, \
.min_uV = _min_uv, \
.max_uV = _max_uv , \
.step_uV = _step_uV, \
.nsteps = _nsteps, \
.delay = _delay, \
.id = RICOH619_ID_##_id, \
.sleep_id = RICOH619_DS_##_id, \
.eco_reg = _eco_reg, \
.eco_bit = _eco_bit, \
.eco_slp_reg = _eco_slp_reg, \
.eco_slp_bit = _eco_slp_bit, \
.desc = { \
.name = ricoh619_rails(_id), \
.id = RICOH619_ID_##_id, \
.n_voltages = _nsteps, \
.ops = &_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
}, \
}
static struct ricoh619_regulator ricoh619_regulator[] = {
RICOH619_REG(DC1, 0x2C, 0, 0x2C, 1, 0x36, 0xFF, 0x3B,
600000, 3500000, 12500, 0xE8, ricoh619_ops, 500,
0x00, 0, 0x00, 0),
RICOH619_REG(DC2, 0x2E, 0, 0x2E, 1, 0x37, 0xFF, 0x3C,
600000, 3500000, 12500, 0xE8, ricoh619_ops, 500,
0x00, 0, 0x00, 0),
RICOH619_REG(DC3, 0x30, 0, 0x30, 1, 0x38, 0xFF, 0x3D,
600000, 3500000, 12500, 0xE8, ricoh619_ops, 500,
0x00, 0, 0x00, 0),
RICOH619_REG(DC4, 0x32, 0, 0x32, 1, 0x39, 0xFF, 0x3E,
600000, 3500000, 12500, 0xE8, ricoh619_ops, 500,
0x00, 0, 0x00, 0),
RICOH619_REG(DC5, 0x34, 0, 0x34, 1, 0x3A, 0xFF, 0x3F,
600000, 3500000, 12500, 0xE8, ricoh619_ops, 500,
0x00, 0, 0x00, 0),
RICOH619_REG(LDO1, 0x44, 0, 0x46, 0, 0x4C, 0x7F, 0x58,
900000, 3500000, 25000, 0x68, ricoh619_ops, 500,
0x48, 0, 0x4A, 0),
RICOH619_REG(LDO2, 0x44, 1, 0x46, 1, 0x4D, 0x7F, 0x59,
900000, 3500000, 25000, 0x68, ricoh619_ops, 500,
0x48, 1, 0x4A, 1),
RICOH619_REG(LDO3, 0x44, 2, 0x46, 2, 0x4E, 0x7F, 0x5A,
900000, 3500000, 25000, 0x68, ricoh619_ops, 500,
0x48, 2, 0x4A, 2),
RICOH619_REG(LDO4, 0x44, 3, 0x46, 3, 0x4F, 0x7F, 0x5B,
900000, 3500000, 25000, 0x68, ricoh619_ops, 500,
0x48, 3, 0x4A, 3),
RICOH619_REG(LDO5, 0x44, 4, 0x46, 4, 0x50, 0x7F, 0x5C,
600000, 3500000, 25000, 0x74, ricoh619_ops, 500,
0x48, 4, 0x4A, 4),
RICOH619_REG(LDO6, 0x44, 5, 0x46, 5, 0x51, 0x7F, 0x5D,
600000, 3500000, 25000, 0x74, ricoh619_ops, 500,
0x48, 5, 0x4A, 5),
RICOH619_REG(LDO7, 0x44, 6, 0x46, 6, 0x52, 0x7F, 0x5E,
900000, 3500000, 25000, 0x68, ricoh619_ops, 500,
0x00, 0, 0x00, 0),
RICOH619_REG(LDO8, 0x44, 7, 0x46, 7, 0x53, 0x7F, 0x5F,
900000, 3500000, 25000, 0x68, ricoh619_ops, 500,
0x00, 0, 0x00, 0),
RICOH619_REG(LDO9, 0x45, 0, 0x47, 0, 0x54, 0x7F, 0x60,
900000, 3500000, 25000, 0x68, ricoh619_ops, 500,
0x00, 0, 0x00, 0),
RICOH619_REG(LDO10, 0x45, 1, 0x47, 1, 0x55, 0x7F, 0x61,
900000, 3500000, 25000, 0x68, ricoh619_ops, 500,
0x00, 0, 0x00, 0),
RICOH619_REG(LDORTC1, 0x45, 4, 0x00, 0, 0x56, 0x7F, 0x00,
1700000, 3500000, 25000, 0x48, ricoh619_ops, 500,
0x00, 0, 0x00, 0),
RICOH619_REG(LDORTC2, 0x45, 5, 0x00, 0, 0x57, 0x7F, 0x00,
900000, 3500000, 25000, 0x68, ricoh619_ops, 500,
0x00, 0, 0x00, 0),
};
static inline struct ricoh619_regulator *find_regulator_info(int id)
{
struct ricoh619_regulator *ri;
int i;
for (i = 0; i < ARRAY_SIZE(ricoh619_regulator); i++) {
ri = &ricoh619_regulator[i];
if (ri->desc.id == id)
return ri;
}
return NULL;
}
static int ricoh619_regulator_preinit(struct device *parent,
struct ricoh619_regulator *ri,
struct ricoh619_regulator_platform_data *ricoh619_pdata)
{
int ret = 0;
if (!ricoh619_pdata->init_apply)
return 0;
/*
if (ricoh619_pdata->init_uV >= 0) {
ret = __ricoh619_set_voltage(parent, ri,
ricoh619_pdata->init_uV,
ricoh619_pdata->init_uV, 0);
if (ret < 0) {
dev_err(ri->dev, "Not able to initialize voltage %d "
"for rail %d err %d\n", ricoh619_pdata->init_uV,
ri->desc.id, ret);
return ret;
}
}
*/
if (ricoh619_pdata->init_enable)
ret = ricoh619_set_bits(parent, ri->reg_en_reg,
(1 << ri->en_bit));
else
ret = ricoh619_clr_bits(parent, ri->reg_en_reg,
(1 << ri->en_bit));
if (ret < 0)
dev_err(ri->dev, "Not able to %s rail %d err %d\n",
(ricoh619_pdata->init_enable) ? "enable" : "disable",
ri->desc.id, ret);
return ret;
}
static inline int ricoh619_cache_regulator_register(struct device *parent,
struct ricoh619_regulator *ri)
{
ri->vout_reg_cache = 0;
return ricoh619_read(parent, ri->vout_reg, &ri->vout_reg_cache);
}
static int __devinit ricoh619_regulator_probe(struct platform_device *pdev)
{
struct ricoh619_regulator *ri = NULL;
struct regulator_dev *rdev;
struct ricoh619_regulator_platform_data *tps_pdata;
int id = pdev->id;
int err;
ri = find_regulator_info(id);
if (ri == NULL) {
dev_err(&pdev->dev, "invalid regulator ID specified\n");
return -EINVAL;
}
tps_pdata = pdev->dev.platform_data;
ri->dev = &pdev->dev;
/*
err = ricoh619_cache_regulator_register(pdev->dev.parent, ri);
if (err) {
dev_err(&pdev->dev, "Fail in caching register\n");
return err;
}
err = ricoh619_regulator_preinit(pdev->dev.parent, ri, tps_pdata);
if (err) {
dev_err(&pdev->dev, "Fail in pre-initialisation\n");
return err;
}
*/
rdev = regulator_register(&ri->desc, &pdev->dev,
&tps_pdata->regulator, ri);
if (IS_ERR_OR_NULL(rdev)) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
ri->desc.name);
return PTR_ERR(rdev);
}
platform_set_drvdata(pdev, rdev);
return 0;
}
static int __devexit ricoh619_regulator_remove(struct platform_device *pdev)
{
struct regulator_dev *rdev = platform_get_drvdata(pdev);
regulator_unregister(rdev);
return 0;
}
static struct platform_driver ricoh619_regulator_driver = {
.driver = {
.name = "ricoh619-regulator",
.owner = THIS_MODULE,
},
.probe = ricoh619_regulator_probe,
.remove = __devexit_p(ricoh619_regulator_remove),
};
static int __init ricoh619_regulator_init(void)
{
return platform_driver_register(&ricoh619_regulator_driver);
}
subsys_initcall_sync(ricoh619_regulator_init);
static void __exit ricoh619_regulator_exit(void)
{
platform_driver_unregister(&ricoh619_regulator_driver);
}
module_exit(ricoh619_regulator_exit);
MODULE_DESCRIPTION("RICOH619 regulator driver");
MODULE_ALIAS("platform:ricoh619-regulator");
MODULE_AUTHOR("zhangqing <zhangqing@rock-chips.com>");
MODULE_LICENSE("GPL");

View File

@@ -1121,5 +1121,15 @@ config RK808_RTC
depends on MFD_RK808
help
enable rk808 rtc for system
config RTC_DRV_RC5T619
tristate "RICOH RC5T619 PMU RTC driver"
depends on MFD_RICOH619
default n
help
If you say yes here you get support for the RICOH RC5T619 RTC module.
This driver can also be built as a module. If so, the module
will be called rtc-rc5t619.
endif # RTC_CLASS

View File

@@ -117,3 +117,4 @@ obj-$(CONFIG_RTC_HYM8563) += rtc-HYM8563.o
obj-$(CONFIG_RTC_M41T66) += rtc-m41t66.o
obj-$(CONFIG_TPS65910_RTC) += rtc-tps65910.o
obj-$(CONFIG_RK808_RTC) += rtc-rk808.o
obj-$(CONFIG_RTC_DRV_RC5T619) += rtc-ricoh619.o

413
drivers/rtc/rtc-ricoh619.c Normal file
View File

@@ -0,0 +1,413 @@
/*
* drivers/rtc/rtc-ricoh619.c
*
* Real time clock driver for RICOH RC5T619 power management chip.
*
* Copyright (C) 2012-2013 RICOH COMPANY,LTD
*
* Based on code
* Copyright (C) 2011 NVIDIA Corporation
*
* this program is free software; you can redistribute it and/or modify
* it under the terms of the gnu general public license as published by
* the free software foundation; either version 2 of the license, or
* (at your option) any later version.
*
* this program is distributed in the hope that it will be useful, but without
* any warranty; without even the implied warranty of merchantability or
* fitness for a particular purpose. see the gnu general public license for
* more details.
*
* you should have received a copy of the gnu general public license
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* #define debug 1 */
/* #define verbose_debug 1 */
#include <linux/device.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mfd/ricoh619.h>
#include <linux/rtc/rtc-ricoh619.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
#include <linux/slab.h>
struct ricoh619_rtc {
unsigned long epoch_start;
int irq;
struct rtc_device *rtc;
bool irq_en;
};
static int ricoh619_read_regs(struct device *dev, int reg, int len,
uint8_t *val)
{
int ret;
ret = ricoh619_bulk_reads(dev->parent, reg, len, val);
if (ret < 0) {
dev_err(dev->parent, "\n %s failed reading from 0x%02x\n",
__func__, reg);
WARN_ON(1);
}
return ret;
}
static int ricoh619_write_regs(struct device *dev, int reg, int len,
uint8_t *val)
{
int ret;
ret = ricoh619_bulk_writes(dev->parent, reg, len, val);
if (ret < 0) {
dev_err(dev->parent, "\n %s failed writing\n", __func__);
WARN_ON(1);
}
return ret;
}
static int ricoh619_rtc_valid_tm(struct device *dev, struct rtc_time *tm)
{
if (tm->tm_year >= (rtc_year_offset + 99)
|| tm->tm_mon > 12
|| tm->tm_mday < 1
|| tm->tm_mday > rtc_month_days(tm->tm_mon,
tm->tm_year + os_ref_year)
|| tm->tm_hour >= 24
|| tm->tm_min >= 60
|| tm->tm_sec >= 60) {
dev_err(dev->parent, "\n returning error due to time"
"%d/%d/%d %d:%d:%d", tm->tm_mon, tm->tm_mday,
tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec);
return -EINVAL;
}
return 0;
}
static u8 dec2bcd(u8 dec)
{
return ((dec/10)<<4)+(dec%10);
}
static u8 bcd2dec(u8 bcd)
{
return (bcd >> 4)*10+(bcd & 0xf);
}
static void convert_bcd_to_decimal(u8 *buf, u8 len)
{
int i = 0;
for (i = 0; i < len; i++)
buf[i] = bcd2dec(buf[i]);
}
static void convert_decimal_to_bcd(u8 *buf, u8 len)
{
int i = 0;
for (i = 0; i < len; i++)
buf[i] = dec2bcd(buf[i]);
}
static void print_time(struct device *dev, struct rtc_time *tm)
{
dev_info(dev, "rtc-time : %d/%d/%d %d:%d\n",
(tm->tm_mon + 1), tm->tm_mday, (tm->tm_year + os_ref_year),
tm->tm_hour, tm->tm_min);
}
static int ricoh619_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
u8 buff[7];
int err;
err = ricoh619_read_regs(dev, rtc_seconds_reg, sizeof(buff), buff);
if (err < 0) {
dev_err(dev, "\n %s :: failed to read time\n", __FILE__);
return err;
}
convert_bcd_to_decimal(buff, sizeof(buff));
tm->tm_sec = buff[0];
tm->tm_min = buff[1];
tm->tm_hour = buff[2];
tm->tm_wday = buff[3];
tm->tm_mday = buff[4];
tm->tm_mon = buff[5] - 1;
tm->tm_year = buff[6] + rtc_year_offset;
// print_time(dev, tm);
return ricoh619_rtc_valid_tm(dev, tm);
}
static int ricoh619_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
u8 buff[7];
int err;
// print_time(dev, tm);
buff[0] = tm->tm_sec;
buff[1] = tm->tm_min;
buff[2] = tm->tm_hour;
buff[3] = tm->tm_wday;
buff[4] = tm->tm_mday;
buff[5] = tm->tm_mon + 1;
buff[6] = tm->tm_year - rtc_year_offset;
convert_decimal_to_bcd(buff, sizeof(buff));
err = ricoh619_write_regs(dev, rtc_seconds_reg, sizeof(buff), buff);
if (err < 0) {
dev_err(dev->parent, "\n failed to program new time\n");
return err;
}
return 0;
}
static int ricoh619_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm);
static int ricoh619_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct ricoh619_rtc *rtc = dev_get_drvdata(dev);
unsigned long seconds;
u8 buff[6];
int err;
struct rtc_time tm;
if (rtc->irq == -1)
return -EIO;
rtc_tm_to_time(&alrm->time, &seconds);
err = ricoh619_rtc_read_time(dev, &tm);
if (err) {
dev_err(dev, "\n failed to read time\n");
return err;
}
rtc_tm_to_time(&tm, &rtc->epoch_start);
dev_info(dev->parent, "\n setting alarm to requested time::\n");
// print_time(dev->parent, &alrm->time);
if (WARN_ON(alrm->enabled && (seconds < rtc->epoch_start))) {
dev_err(dev->parent, "\n can't set alarm to requested time\n");
return -EINVAL;
}
if (alrm->enabled && !rtc->irq_en)
rtc->irq_en = true;
else if (!alrm->enabled && rtc->irq_en)
rtc->irq_en = false;
buff[0] = alrm->time.tm_sec;
buff[1] = alrm->time.tm_min;
buff[2] = alrm->time.tm_hour;
buff[3] = alrm->time.tm_mday;
buff[4] = alrm->time.tm_mon + 1;
buff[5] = alrm->time.tm_year - rtc_year_offset;
convert_decimal_to_bcd(buff, sizeof(buff));
buff[3] |= 0x80; /* set DAL_EXT */
err = ricoh619_write_regs(dev, rtc_alarm_y_sec, sizeof(buff), buff);
if (err) {
dev_err(dev->parent, "\n unable to set alarm\n");
return -EBUSY;
}
err = ricoh619_read_regs(dev, rtc_ctrl2, 1, buff);
if (err) {
dev_err(dev->parent, "unable to read rtc_ctrl2 reg\n");
return -EBUSY;
}
buff[1] = buff[0] & ~0x81; /* to clear alarm-D flag, and set adjustment parameter */
buff[0] = 0x60; /* to enable alarm_d and 24-hour format */
err = ricoh619_write_regs(dev, rtc_ctrl1, 2, buff);
if (err) {
dev_err(dev, "failed programming rtc ctrl regs\n");
return -EBUSY;
}
return err;
}
static int ricoh619_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
u8 buff[6];
int err;
err = ricoh619_read_regs(dev, rtc_alarm_y_sec, sizeof(buff), buff);
if (err)
return err;
buff[3] &= ~0x80; /* clear DAL_EXT */
convert_bcd_to_decimal(buff, sizeof(buff));
alrm->time.tm_sec = buff[0];
alrm->time.tm_min = buff[1];
alrm->time.tm_hour = buff[2];
alrm->time.tm_mday = buff[3];
alrm->time.tm_mon = buff[4] - 1;
alrm->time.tm_year = buff[5] + rtc_year_offset;
// dev_info(dev->parent, "\n getting alarm time::\n");
// print_time(dev, &alrm->time);
return 0;
}
static const struct rtc_class_ops ricoh619_rtc_ops = {
.read_time = ricoh619_rtc_read_time,
.set_time = ricoh619_rtc_set_time,
.set_alarm = ricoh619_rtc_set_alarm,
.read_alarm = ricoh619_rtc_read_alarm,
};
static irqreturn_t ricoh619_rtc_irq(int irq, void *data)
{
struct device *dev = data;
struct ricoh619_rtc *rtc = dev_get_drvdata(dev);
u8 reg;
int err;
/* clear alarm-D status bits.*/
err = ricoh619_read_regs(dev, rtc_ctrl2, 1, &reg);
if (err) {
dev_err(dev->parent, "unable to read rtc_ctrl2 reg\n");
}
reg &= ~0x81; /* to clear alarm-D flag, and set adjustment parameter */
err = ricoh619_write_regs(dev, rtc_ctrl2, 1, &reg);
if (err) {
dev_err(dev->parent, "unable to program rtc_status reg\n");
}
rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF);
return IRQ_HANDLED;
}
static int __devinit ricoh619_rtc_probe(struct platform_device *pdev)
{
struct ricoh619_rtc_platform_data *pdata = pdev->dev.platform_data;
struct ricoh619_rtc *rtc;
struct rtc_time tm;
int err;
u8 reg;
rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
// printk("%s,line=%d\n", __func__,__LINE__);
if (!rtc)
return -ENOMEM;
rtc->irq = -1;
if (!pdata) {
dev_err(&pdev->dev, "no platform_data specified\n");
return -EINVAL;
}
if (pdata->irq < 0)
dev_err(&pdev->dev, "\n no irq specified, wakeup is disabled\n");
dev_set_drvdata(&pdev->dev, rtc);
device_init_wakeup(&pdev->dev, 1);
rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
&ricoh619_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc->rtc)) {
err = PTR_ERR(rtc->rtc);
goto fail;
}
reg = 0x20; /* to clear power-on-reset flag */
err = ricoh619_write_regs(&pdev->dev, rtc_ctrl2, 1, &reg);
if (err) {
dev_err(&pdev->dev, "failed rtc setup\n");
return -EBUSY;
}
reg = 0x60; /* to enable alarm_d and 24-hour format */
err = ricoh619_write_regs(&pdev->dev, rtc_ctrl1, 1, &reg);
if (err) {
dev_err(&pdev->dev, "failed rtc setup\n");
return -EBUSY;
}
reg = 0; /* clearing RTC Adjust register */
err = ricoh619_write_regs(&pdev->dev, rtc_adjust, 1, &reg);
if (err) {
dev_err(&pdev->dev, "unable to program rtc_adjust reg\n");
return -EBUSY;
}
err = ricoh619_rtc_read_time(&pdev->dev, &tm);
if (err) {
dev_err(&pdev->dev, "\n failed to read time\n");
return err;
}
if (ricoh619_rtc_valid_tm(&pdev->dev, &tm)) {
if (pdata->time.tm_year < 2000 || pdata->time.tm_year > 2100) {
memset(&pdata->time, 0, sizeof(pdata->time));
pdata->time.tm_year = rtc_year_offset;
pdata->time.tm_mday = 1;
} else
pdata->time.tm_year -= os_ref_year;
err = ricoh619_rtc_set_time(&pdev->dev, &pdata->time);
if (err) {
dev_err(&pdev->dev, "\n failed to set time\n");
return err;
}
}
if (pdata && (pdata->irq >= 0)) {
rtc->irq = pdata->irq + RICOH619_IRQ_DALE;
err = request_threaded_irq(rtc->irq, NULL, ricoh619_rtc_irq,
IRQF_ONESHOT, "rtc_ricoh619",
&pdev->dev);
if (err) {
dev_err(&pdev->dev, "request IRQ:%d fail\n", rtc->irq);
rtc->irq = -1;
} else {
device_init_wakeup(&pdev->dev, 1);
enable_irq_wake(rtc->irq);
}
}
return 0;
fail:
if (!IS_ERR_OR_NULL(rtc->rtc))
rtc_device_unregister(rtc->rtc);
kfree(rtc);
return err;
}
static int __devexit ricoh619_rtc_remove(struct platform_device *pdev)
{
struct ricoh619_rtc *rtc = dev_get_drvdata(&pdev->dev);
if (rtc->irq != -1)
free_irq(rtc->irq, rtc);
rtc_device_unregister(rtc->rtc);
kfree(rtc);
return 0;
}
static struct platform_driver ricoh619_rtc_driver = {
.driver = {
.name = "rtc_ricoh619",
.owner = THIS_MODULE,
},
.probe = ricoh619_rtc_probe,
.remove = __devexit_p(ricoh619_rtc_remove),
};
static int __init ricoh619_rtc_init(void)
{
return platform_driver_register(&ricoh619_rtc_driver);
}
subsys_initcall_sync(ricoh619_rtc_init);
static void __exit ricoh619_rtc_exit(void)
{
platform_driver_unregister(&ricoh619_rtc_driver);
}
module_exit(ricoh619_rtc_exit);
MODULE_DESCRIPTION("RICOH RICOH619 RTC driver");
MODULE_ALIAS("platform:rtc_ricoh619");
MODULE_AUTHOR("zhangqing <zhangqing@rock-chips.com>");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,354 @@
/*
* include/linux/mfd/ricoh619.h
*
* Core driver interface to access RICOH RC5T619 power management chip.
*
* Copyright (C) 2012-2013 RICOH COMPANY,LTD
*
* Based on code
* Copyright (C) 2011 NVIDIA Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef __LINUX_MFD_RICOH619_H
#define __LINUX_MFD_RICOH619_H
#include <linux/mutex.h>
#include <linux/types.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
/* Maximum number of main interrupts */
#define MAX_INTERRUPT_MASKS 13
#define MAX_MAIN_INTERRUPT 7
#define MAX_GPEDGE_REG 2
/* Power control register */
#define RICOH619_PWR_WD 0x0B
#define RICOH619_PWR_WD_COUNT 0x0C
#define RICOH619_PWR_FUNC 0x0D
#define RICOH619_PWR_SLP_CNT 0x0E
#define RICOH619_PWR_REP_CNT 0x0F
#define RICOH619_PWR_ON_TIMSET 0x10
#define RICOH619_PWR_NOE_TIMSET 0x11
#define RICOH619_PWR_IRSEL 0x15
/* Interrupt enable register */
#define RICOH619_INT_EN_SYS 0x12
#define RICOH619_INT_EN_DCDC 0x40
#define RICOH619_INT_EN_RTC 0xAE
#define RICOH619_INT_EN_ADC1 0x88
#define RICOH619_INT_EN_ADC2 0x89
#define RICOH619_INT_EN_ADC3 0x8A
#define RICOH619_INT_EN_GPIO 0x94
#define RICOH619_INT_EN_GPIO2 0x94 // dummy
#define RICOH619_INT_MSK_CHGCTR 0xBE
#define RICOH619_INT_MSK_CHGSTS1 0xBF
#define RICOH619_INT_MSK_CHGSTS2 0xC0
#define RICOH619_INT_MSK_CHGERR 0xC1
#define RICOH619_INT_MSK_CHGEXTIF 0xD1
/* Interrupt select register */
#define RICOH619_PWR_IRSEL 0x15
#define RICOH619_CHG_CTRL_DETMOD1 0xCA
#define RICOH619_CHG_CTRL_DETMOD2 0xCB
#define RICOH619_CHG_STAT_DETMOD1 0xCC
#define RICOH619_CHG_STAT_DETMOD2 0xCD
#define RICOH619_CHG_STAT_DETMOD3 0xCE
/* interrupt status registers (monitor regs)*/
#define RICOH619_INTC_INTPOL 0x9C
#define RICOH619_INTC_INTEN 0x9D
#define RICOH619_INTC_INTMON 0x9E
#define RICOH619_INT_MON_SYS 0x14
#define RICOH619_INT_MON_DCDC 0x42
#define RICOH619_INT_MON_RTC 0xAF
#define RICOH619_INT_MON_CHGCTR 0xC6
#define RICOH619_INT_MON_CHGSTS1 0xC7
#define RICOH619_INT_MON_CHGSTS2 0xC8
#define RICOH619_INT_MON_CHGERR 0xC9
#define RICOH619_INT_MON_CHGEXTIF 0xD3
/* interrupt clearing registers */
#define RICOH619_INT_IR_SYS 0x13
#define RICOH619_INT_IR_DCDC 0x41
#define RICOH619_INT_IR_RTC 0xAF
#define RICOH619_INT_IR_ADCL 0x8C
#define RICOH619_INT_IR_ADCH 0x8D
#define RICOH619_INT_IR_ADCEND 0x8E
#define RICOH619_INT_IR_GPIOR 0x95
#define RICOH619_INT_IR_GPIOF 0x96
#define RICOH619_INT_IR_CHGCTR 0xC2
#define RICOH619_INT_IR_CHGSTS1 0xC3
#define RICOH619_INT_IR_CHGSTS2 0xC4
#define RICOH619_INT_IR_CHGERR 0xC5
#define RICOH619_INT_IR_CHGEXTIF 0xD2
/* GPIO register base address */
#define RICOH619_GPIO_IOSEL 0x90
#define RICOH619_GPIO_IOOUT 0x91
#define RICOH619_GPIO_GPEDGE1 0x92
#define RICOH619_GPIO_GPEDGE2 0x93
//#define RICOH619_GPIO_EN_GPIR 0x94
//#define RICOH619_GPIO_IR_GPR 0x95
//#define RICOH619_GPIO_IR_GPF 0x96
#define RICOH619_GPIO_MON_IOIN 0x97
#define RICOH619_GPIO_LED_FUNC 0x98
#define RICOH619_REG_BANKSEL 0xFF
/* Charger Control register */
#define RICOH619_CHG_CTL1 0xB3
/* ADC Control register */
#define RICOH619_ADC_CNT1 0x64
#define RICOH619_ADC_CNT2 0x65
#define RICOH619_ADC_CNT3 0x66
#define RICOH619_ADC_VADP_THL 0x7C
#define RICOH619_ADC_VSYS_THL 0x80
#define RICOH619_FG_CTRL 0xE0
#define RICOH619_PSWR 0x07
/* RICOH619 IRQ definitions */
enum {
RICOH619_IRQ_POWER_ON,
RICOH619_IRQ_EXTIN,
RICOH619_IRQ_PRE_VINDT,
RICOH619_IRQ_PREOT,
RICOH619_IRQ_POWER_OFF,
RICOH619_IRQ_NOE_OFF,
RICOH619_IRQ_WD,
RICOH619_IRQ_CLK_STP,
RICOH619_IRQ_DC1LIM,
RICOH619_IRQ_DC2LIM,
RICOH619_IRQ_DC3LIM,
RICOH619_IRQ_DC4LIM,
RICOH619_IRQ_DC5LIM,
RICOH619_IRQ_ILIMLIR,
RICOH619_IRQ_VBATLIR,
RICOH619_IRQ_VADPLIR,
RICOH619_IRQ_VUSBLIR,
RICOH619_IRQ_VSYSLIR,
RICOH619_IRQ_VTHMLIR,
RICOH619_IRQ_AIN1LIR,
RICOH619_IRQ_AIN0LIR,
RICOH619_IRQ_ILIMHIR,
RICOH619_IRQ_VBATHIR,
RICOH619_IRQ_VADPHIR,
RICOH619_IRQ_VUSBHIR,
RICOH619_IRQ_VSYSHIR,
RICOH619_IRQ_VTHMHIR,
RICOH619_IRQ_AIN1HIR,
RICOH619_IRQ_AIN0HIR,
RICOH619_IRQ_ADC_ENDIR,
RICOH619_IRQ_GPIO0,
RICOH619_IRQ_GPIO1,
RICOH619_IRQ_GPIO2,
RICOH619_IRQ_GPIO3,
RICOH619_IRQ_GPIO4,
RICOH619_IRQ_CTC,
RICOH619_IRQ_DALE,
RICOH619_IRQ_FVADPDETSINT,
RICOH619_IRQ_FVUSBDETSINT,
RICOH619_IRQ_FVADPLVSINT,
RICOH619_IRQ_FVUSBLVSINT,
RICOH619_IRQ_FWVADPSINT,
RICOH619_IRQ_FWVUSBSINT,
RICOH619_IRQ_FONCHGINT,
RICOH619_IRQ_FCHGCMPINT,
RICOH619_IRQ_FBATOPENINT,
RICOH619_IRQ_FSLPMODEINT,
RICOH619_IRQ_FBTEMPJTA1INT,
RICOH619_IRQ_FBTEMPJTA2INT,
RICOH619_IRQ_FBTEMPJTA3INT,
RICOH619_IRQ_FBTEMPJTA4INT,
RICOH619_IRQ_FCURTERMINT,
RICOH619_IRQ_FVOLTERMINT,
RICOH619_IRQ_FICRVSINT,
RICOH619_IRQ_FPOOR_CHGCURINT,
RICOH619_IRQ_FOSCFDETINT1,
RICOH619_IRQ_FOSCFDETINT2,
RICOH619_IRQ_FOSCFDETINT3,
RICOH619_IRQ_FOSCMDETINT,
RICOH619_IRQ_FDIEOFFINT,
RICOH619_IRQ_FDIEERRINT,
RICOH619_IRQ_FBTEMPERRINT,
RICOH619_IRQ_FVBATOVINT,
RICOH619_IRQ_FTTIMOVINT,
RICOH619_IRQ_FRTIMOVINT,
RICOH619_IRQ_FVADPOVSINT,
RICOH619_IRQ_FVUSBOVSINT,
RICOH619_IRQ_FGCDET,
RICOH619_IRQ_FPCDET,
RICOH619_IRQ_FWARN_ADP,
/* Should be last entry */
RICOH619_NR_IRQS,
};
/* Ricoh619 gpio definitions */
enum {
RICOH619_GPIO0,
RICOH619_GPIO1,
RICOH619_GPIO2,
RICOH619_GPIO3,
RICOH619_GPIO4,
RICOH619_NR_GPIO,
};
enum ricoh619_sleep_control_id {
RICOH619_DS_DC1,
RICOH619_DS_DC2,
RICOH619_DS_DC3,
RICOH619_DS_DC4,
RICOH619_DS_DC5,
RICOH619_DS_LDO1,
RICOH619_DS_LDO2,
RICOH619_DS_LDO3,
RICOH619_DS_LDO4,
RICOH619_DS_LDO5,
RICOH619_DS_LDO6,
RICOH619_DS_LDO7,
RICOH619_DS_LDO8,
RICOH619_DS_LDO9,
RICOH619_DS_LDO10,
RICOH619_DS_LDORTC1,
RICOH619_DS_LDORTC2,
RICOH619_DS_PSO0,
RICOH619_DS_PSO1,
RICOH619_DS_PSO2,
RICOH619_DS_PSO3,
RICOH619_DS_PSO4,
};
struct ricoh619_subdev_info {
int id;
const char *name;
void *platform_data;
};
/*
struct ricoh619_rtc_platform_data {
int irq;
struct rtc_time time;
};
*/
struct ricoh619_gpio_init_data {
unsigned output_mode_en:1; /* Enable output mode during init */
unsigned output_val:1; /* Output value if it is in output mode */
unsigned init_apply:1; /* Apply init data on configuring gpios*/
unsigned led_mode:1; /* Select LED mode during init */
unsigned led_func:1; /* Set LED function if LED mode is 1 */
};
struct ricoh619 {
struct device *dev;
struct i2c_client *client;
struct mutex io_lock;
int gpio_base;
struct gpio_chip gpio_chip;
int irq_base;
// struct irq_chip irq_chip;
int chip_irq;
struct mutex irq_lock;
unsigned long group_irq_en[MAX_MAIN_INTERRUPT];
/* For main interrupt bits in INTC */
u8 intc_inten_cache;
u8 intc_inten_reg;
/* For group interrupt bits and address */
u8 irq_en_cache[MAX_INTERRUPT_MASKS];
u8 irq_en_reg[MAX_INTERRUPT_MASKS];
/* For gpio edge */
u8 gpedge_cache[MAX_GPEDGE_REG];
u8 gpedge_reg[MAX_GPEDGE_REG];
int bank_num;
};
struct ricoh619_platform_data {
int num_subdevs;
struct ricoh619_subdev_info *subdevs;
int (*init_port)(int irq_num); // Init GPIO for IRQ pin
int gpio_base;
int irq_base;
struct ricoh619_gpio_init_data *gpio_init_data;
int num_gpioinit_data;
bool enable_shutdown_pin;
int (*pre_init)(struct ricoh619 *ricoh619);
int (*post_init)(struct ricoh619 *ricoh619);
};
/* ==================================== */
/* RICOH619 Power_Key device data */
/* ==================================== */
struct ricoh619_pwrkey_platform_data {
int irq;
unsigned long delay_ms;
};
extern int pwrkey_wakeup;
extern struct ricoh619 *g_ricoh619;
/* ==================================== */
/* RICOH619 battery device data */
/* ==================================== */
extern int g_soc;
extern int g_fg_on_mode;
extern int ricoh619_read(struct device *dev, uint8_t reg, uint8_t *val);
extern int ricoh619_read_bank1(struct device *dev, uint8_t reg, uint8_t *val);
extern int ricoh619_bulk_reads(struct device *dev, u8 reg, u8 count,
uint8_t *val);
extern int ricoh619_bulk_reads_bank1(struct device *dev, u8 reg, u8 count,
uint8_t *val);
extern int ricoh619_write(struct device *dev, u8 reg, uint8_t val);
extern int ricoh619_write_bank1(struct device *dev, u8 reg, uint8_t val);
extern int ricoh619_bulk_writes(struct device *dev, u8 reg, u8 count,
uint8_t *val);
extern int ricoh619_bulk_writes_bank1(struct device *dev, u8 reg, u8 count,
uint8_t *val);
extern int ricoh619_set_bits(struct device *dev, u8 reg, uint8_t bit_mask);
extern int ricoh619_clr_bits(struct device *dev, u8 reg, uint8_t bit_mask);
extern int ricoh619_update(struct device *dev, u8 reg, uint8_t val,
uint8_t mask);
extern int ricoh619_update_bank1(struct device *dev, u8 reg, uint8_t val,
uint8_t mask);
extern int ricoh619_power_off(void);
extern int ricoh619_irq_init(struct ricoh619 *ricoh619, int irq, int irq_base);
extern int ricoh619_irq_exit(struct ricoh619 *ricoh619);
extern int ricoh619_power_off(void);
#endif

View File

@@ -0,0 +1,121 @@
/*
* include/linux/power/ricoh619-battery.c
*
* RICOH RC5T619 Charger Driver
*
* Copyright (C) 2012-2013 RICOH COMPANY,LTD
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef __LINUX_POWER_RICOH619_H_
#define __LINUX_POWER_RICOH619_H_
/* #include <linux/power_supply.h> */
/* #include <linux/types.h> */
#if 0
#define RICOH_FG_DBG(fmt, args...) printk(KERN_DEBUG "RICOH_FG_DBG:\t"fmt, ##args)
#else
#define RICOH_FG_DBG(fmt, args...) {while(0);}
#endif
/* Defined buttery information */
#define ADC_VDD_MV 2800
#define MIN_VOLTAGE 3100
#define MAX_VOLTAGE 4200
/* 619 Register information */
/* bank 0 */
#define PSWR_REG 0x07
/* for ADC */
#define INTEN_REG 0x9D
#define EN_ADCIR3_REG 0x8A
#define ADCCNT3_REG 0x66
#define VBATDATAH_REG 0x6A
#define VBATDATAL_REG 0x6B
#define CHGCTL1_REG 0xB3
#define REGISET1_REG 0xB6
#define REGISET2_REG 0xB7
#define CHGISET_REG 0xB8
#define BATSET2_REG 0xBB
#define CHGSTATE_REG 0xBD
#define FG_CTRL_REG 0xE0
#define SOC_REG 0xE1
#define RE_CAP_H_REG 0xE2
#define RE_CAP_L_REG 0xE3
#define FA_CAP_H_REG 0xE4
#define FA_CAP_L_REG 0xE5
#define TT_EMPTY_H_REG 0xE7
#define TT_EMPTY_L_REG 0xE8
#define TT_FULL_H_REG 0xE9
#define TT_FULL_L_REG 0xEA
#define VOLTAGE_1_REG 0xEB
#define VOLTAGE_2_REG 0xEC
#define TEMP_1_REG 0xED
#define TEMP_2_REG 0xEE
#define CC_CTRL_REG 0xEF
#define CC_SUMREG3_REG 0xF3
#define CC_SUMREG2_REG 0xF4
#define CC_SUMREG1_REG 0xF5
#define CC_SUMREG0_REG 0xF6
#define CC_AVERAGE1_REG 0xFB
#define CC_AVERAGE0_REG 0xFC
/* bank 1 */
/* Top address for battery initial setting */
#define BAT_INIT_TOP_REG 0xBC
#define BAT_REL_SEL_REG 0xDA
/**************************/
/* detailed status in CHGSTATE (0xBD) */
enum ChargeState {
CHG_STATE_CHG_OFF = 0,
CHG_STATE_CHG_READY_VADP,
CHG_STATE_CHG_TRICKLE,
CHG_STATE_CHG_RAPID,
CHG_STATE_CHG_COMPLETE,
CHG_STATE_SUSPEND,
CHG_STATE_VCHG_OVER_VOL,
CHG_STATE_BAT_ERROR,
CHG_STATE_NO_BAT,
CHG_STATE_BAT_OVER_VOL,
CHG_STATE_BAT_TEMP_ERR,
CHG_STATE_DIE_ERR,
CHG_STATE_DIE_SHUTDOWN,
CHG_STATE_NO_BAT2,
CHG_STATE_CHG_READY_VUSB,
};
enum SupplyState {
SUPPLY_STATE_BAT = 0,
SUPPLY_STATE_ADP,
SUPPLY_STATE_USB,
} ;
struct ricoh619_battery_platform_data {
int irq;
int alarm_vol_mv;
int multiple;
unsigned long monitor_time;
};
extern struct ricoh619 *g_ricoh619;
#endif

View File

@@ -0,0 +1,54 @@
/*
* include/linux/power/ricoh61x_battery_init.h
*
* Battery initial parameter for RICOH RN5T618/619 power management chip.
*
* Copyright (C) 2012-2013 RICOH COMPANY,LTD
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef __LINUX_POWER_RICOH61X_BATTERY_INIT_H
#define __LINUX_POWER_RICOH61X_BATTERY_INIT_H
uint8_t battery_init_para[32] = {
0x0B, 0x3F, 0x0B, 0xCB, 0x0B, 0xEE, 0x0C, 0x08, 0x0C, 0x1E, 0x0C, 0x38, 0x0C, 0x5B, 0x0C, 0x94,
0x0C, 0xC8, 0x0D, 0x08, 0x0D, 0x55, 0x0E, 0x14, 0x00, 0x39, 0x0F, 0xC8, 0x05, 0x2C, 0x22, 0x56
// 0x0C, 0xC8, 0x0D, 0x08, 0x0D, 0x55, 0x0E, 0x14, 0x00, 0x3E, 0x0F, 0xC8, 0x05, 0x2C, 0x22, 0x56 //150ohme
// 0x0C, 0xC8, 0x0D, 0x08, 0x0D, 0x55, 0x0E, 0x14, 0x00, 0x32, 0x0F, 0xC8, 0x05, 0x2C, 0x22, 0x56 //120ohme
//0x08, 0xa3, 0x0a, 0xf9, 0x0b, 0x4b, 0x0b, 0x74,
//0x0b, 0x94, 0x0b, 0xb5, 0x0b, 0xe6, 0x0c, 0x30,
//0x0c, 0x92, 0x0c, 0xf4, 0x0d, 0x6f, 0x08, 0xca,
//0x00, 0x36, 0x0f, 0xc8, 0x05, 0x2c, 0x22, 0x56
};
#endif
/*
<Other Parameter>
nominal_capacity=3800
cut-off_v=3400
thermistor_b=3435
board_impe=0
bat_impe=0.1363
load_c=768
available_c=3604
battery_v=3515
MakingMode=Normal
ChargeV=4.20V
LoadMode=Resistor
*/

View File

@@ -0,0 +1,72 @@
/*
* linux/regulator/ricoh619-regulator.h
*
* Regulator driver for RICOH619 power management chip.
*
* Copyright (C) 2012-2013 RICOH COMPANY,LTD
*
* Based on code
* Copyright (C) 2011 NVIDIA Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef __LINUX_REGULATOR_RICOH619_H
#define __LINUX_REGULATOR_RICOH619_H
#include <linux/regulator/machine.h>
#include <linux/regulator/driver.h>
#define ricoh619_rails(_name) "RICOH619_"#_name
/* RICHOH Regulator IDs */
enum regulator_id {
RICOH619_ID_DC1,
RICOH619_ID_DC2,
RICOH619_ID_DC3,
RICOH619_ID_DC4,
RICOH619_ID_DC5,
RICOH619_ID_LDO1,
RICOH619_ID_LDO2,
RICOH619_ID_LDO3,
RICOH619_ID_LDO4,
RICOH619_ID_LDO5,
RICOH619_ID_LDO6,
RICOH619_ID_LDO7,
RICOH619_ID_LDO8,
RICOH619_ID_LDO9,
RICOH619_ID_LDO10,
RICOH619_ID_LDORTC1,
RICOH619_ID_LDORTC2,
};
struct ricoh619_regulator_platform_data {
struct regulator_init_data regulator;
int init_uV;
unsigned init_enable:1;
unsigned init_apply:1;
int sleep_uV;
int sleep_slots;
unsigned long ext_pwr_req;
unsigned long flags;
};
extern int ricoh619_regulator_enable_eco_mode(struct regulator_dev *rdev);
extern int ricoh619_regulator_disable_eco_mode(struct regulator_dev *rdev);
extern int ricoh619_regulator_enable_eco_slp_mode(struct regulator_dev *rdev);
extern int ricoh619_regulator_disable_eco_slp_mode(struct regulator_dev *rdev);
#endif

View File

@@ -0,0 +1,57 @@
/*
* include/linux/rtc/rtc-ricoh619.h
*
* Real time clock driver for RICOH RC5T619 power management chip.
*
* Copyright (C) 2012-2013 RICOH COMPANY,LTD
*
* Based on code
* Copyright (C) 2011 NVIDIA Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* you should have received a copy of the gnu general public license
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef __LINUX_RTC_RICOH619_H_
#define __LINUX_RTC_RICOH619_H_
#include <linux/rtc.h>
#define rtc_ctrl1 0xAE
#define rtc_ctrl2 0xAF
#define rtc_seconds_reg 0xA0
#define rtc_alarm_y_sec 0xA8
#define rtc_adjust 0xA7
/*
linux rtc driver refers 1900 as base year in many calculations.
(e.g. refer drivers/rtc/rtc-lib.c)
*/
#define os_ref_year 1900
/*
pmu rtc have only 2 nibbles to store year information, so using an
offset of 100 to set the base year as 2000 for our driver.
*/
#define rtc_year_offset 100
struct ricoh619_rtc_platform_data {
int irq;
struct rtc_time time;
};
#endif