mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 04:48:04 +09:00
ricoh619:support pmic ricoh619
This commit is contained in:
556
arch/arm/mach-rk30/board-pmu-ricoh619.c
Normal file
556
arch/arm/mach-rk30/board-pmu-ricoh619.c
Normal 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
185
arch/arm/mach-rk30/board-rk3168-tb.c
Executable file → Normal 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);
|
||||
|
||||
@@ -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
10
drivers/input/misc/Kconfig
Executable file → Normal 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
2
drivers/input/misc/Makefile
Executable file → Normal 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
|
||||
|
||||
|
||||
332
drivers/input/misc/ricoh619-pwrkey.c
Normal file
332
drivers/input/misc/ricoh619-pwrkey.c
Normal 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");
|
||||
@@ -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
|
||||
|
||||
@@ -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
534
drivers/mfd/ricoh619-irq.c
Normal 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
852
drivers/mfd/ricoh619.c
Normal 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, ®_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, ®_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, ®_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, ®_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, ®_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, ®_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, ®_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
7
drivers/power/Kconfig
Executable file → Normal 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
|
||||
|
||||
@@ -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
|
||||
|
||||
2338
drivers/power/ricoh619-battery.c
Normal file
2338
drivers/power/ricoh619-battery.c
Normal file
File diff suppressed because it is too large
Load Diff
7
drivers/regulator/Kconfig
Executable file → Normal file
7
drivers/regulator/Kconfig
Executable file → Normal 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
1
drivers/regulator/Makefile
Executable file → Normal 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
|
||||
|
||||
578
drivers/regulator/ricoh619-regulator.c
Normal file
578
drivers/regulator/ricoh619-regulator.c
Normal 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");
|
||||
@@ -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
|
||||
|
||||
@@ -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
413
drivers/rtc/rtc-ricoh619.c
Normal 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, ®);
|
||||
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, ®);
|
||||
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, ®);
|
||||
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, ®);
|
||||
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, ®);
|
||||
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");
|
||||
|
||||
354
include/linux/mfd/ricoh619.h
Normal file
354
include/linux/mfd/ricoh619.h
Normal 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
|
||||
121
include/linux/power/ricoh619_battery.h
Normal file
121
include/linux/power/ricoh619_battery.h
Normal 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
|
||||
54
include/linux/power/ricoh61x_battery_init.h
Normal file
54
include/linux/power/ricoh61x_battery_init.h
Normal 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
|
||||
*/
|
||||
|
||||
72
include/linux/regulator/ricoh619-regulator.h
Executable file
72
include/linux/regulator/ricoh619-regulator.h
Executable 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
|
||||
57
include/linux/rtc/rtc-ricoh619.h
Executable file
57
include/linux/rtc/rtc-ricoh619.h
Executable 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
|
||||
Reference in New Issue
Block a user