rk2928:support pmic tps65910

This commit is contained in:
张晴 2012-08-09 18:07:51 +08:00
parent 0a75238e77
commit 426997197d
19 changed files with 2287 additions and 177 deletions

View File

@ -247,9 +247,10 @@ CONFIG_SPI_FPGA_GPIO_IRQ_NUM=0
CONFIG_POWER_SUPPLY=y
CONFIG_TEST_POWER=y
# CONFIG_HWMON is not set
CONFIG_MFD_WM831X_I2C=y
CONFIG_MFD_TPS65910=y
CONFIG_MFD_TPS65090=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_WM831X=y
CONFIG_REGULATOR_TPS65910=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_VIDEO_DEV=y
CONFIG_SOC_CAMERA=y
@ -359,7 +360,7 @@ CONFIG_SDMMC_RK29=y
CONFIG_SWITCH=y
CONFIG_SWITCH_GPIO=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_WM831X=y
CONFIG_TPS65910_RTC=y
CONFIG_STAGING=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y

View File

@ -44,6 +44,8 @@
#include <linux/regulator/machine.h>
#include <linux/rfkill-rk.h>
#include <linux/sensor-dev.h>
#include <linux/mfd/tps65910.h>
#include <linux/regulator/rk29-pwm-regulator.h>
#if defined(CONFIG_HDMI_RK30)
#include "../../../drivers/video/rockchip/hdmi/rk_hdmi.h"
#endif
@ -821,6 +823,7 @@ static struct platform_device device_ion = {
},
};
#endif
/**************************************************************************************************
* SDMMC devices, include the module of SD,MMC,and sdio.noted by xbw at 2012-03-05
**************************************************************************************************/
@ -1075,7 +1078,22 @@ static struct i2c_board_info __initdata i2c0_info[] = {
};
#endif
#ifdef CONFIG_I2C1_RK30
#ifdef CONFIG_MFD_TPS65910
#define TPS65910_HOST_IRQ RK2928_PIN3_PC6
#include "board-rk30-sdk-tps65910.c"
#endif
static struct i2c_board_info __initdata i2c1_info[] = {
#if defined (CONFIG_MFD_TPS65910)
{
.type = "tps65910",
.addr = TPS65910_I2C_ID0,
.flags = 0,
.irq = TPS65910_HOST_IRQ,
.platform_data = &tps65910_data,
},
#endif
};
#endif
#ifdef CONFIG_I2C2_RK30

View File

@ -0,0 +1,633 @@
#include <linux/regulator/machine.h>
#include <linux/i2c/twl.h>
#include <linux/mfd/tps65910.h>
#include <mach/sram.h>
#include <linux/platform_device.h>
#include <mach/gpio.h>
#include <mach/iomux.h>
#define grf_readl(offset) readl_relaxed(RK30_GRF_BASE + offset)
#define grf_writel(v, offset) do { writel_relaxed(v, RK30_GRF_BASE + offset); dsb(); } while (0)
#define CRU_CLKGATE5_CON_ADDR 0x00e4
#define GRF_GPIO6L_DIR_ADDR 0x0030
#define GRF_GPIO6L_DO_ADDR 0x0068
#define GRF_GPIO6L_EN_ADDR 0x00a0
#define GPIO6_PB3_DIR_OUT 0x08000800
#define GPIO6_PB3_DO_LOW 0x08000000
#define GPIO6_PB3_DO_HIGH 0x08000800
#define GPIO6_PB3_EN_MASK 0x08000800
#define GPIO6_PB3_UNEN_MASK 0x08000000
#define GPIO6_PB1_DIR_OUT 0x02000200
#define GPIO6_PB1_DO_LOW 0x02000000
#define GPIO6_PB1_DO_HIGH 0x02000200
#define GPIO6_PB1_EN_MASK 0x02000200
#define GPIO6_PB1_UNEN_MASK 0x02000000
#ifdef CONFIG_MFD_TPS65910
#define PMU_POWER_SLEEP RK2928_PIN3_PD2
extern int platform_device_register(struct platform_device *pdev);
int tps65910_pre_init(struct tps65910 *tps65910){
int val = 0;
int i = 0;
int err = -1;
printk("%s,line=%d\n", __func__,__LINE__);
gpio_request(PMU_POWER_SLEEP, "NULL");
gpio_direction_output(PMU_POWER_SLEEP, GPIO_LOW);
val = tps65910_reg_read(tps65910, TPS65910_DEVCTRL2);
if (val<0) {
printk(KERN_ERR "Unable to read TPS65910_DEVCTRL2 reg\n");
return val;
}
/* Set sleep state active high and allow device turn-off after PWRON long press */
val |= (DEVCTRL2_SLEEPSIG_POL_MASK | DEVCTRL2_PWON_LP_OFF_MASK);
err = tps65910_reg_write(tps65910, TPS65910_DEVCTRL2, val);
if (err) {
printk(KERN_ERR "Unable to write TPS65910_DEVCTRL2 reg\n");
return err;
}
#if 1
/* set PSKIP=0 */
val = tps65910_reg_read(tps65910, TPS65910_DCDCCTRL);
if (val<0) {
printk(KERN_ERR "Unable to read TPS65910_DCDCCTRL reg\n");
return val;
}
val &= ~DEVCTRL_DEV_OFF_MASK;
val &= ~DEVCTRL_DEV_SLP_MASK;
err = tps65910_reg_write(tps65910, TPS65910_DCDCCTRL, val);
if (err) {
printk(KERN_ERR "Unable to write TPS65910_DCDCCTRL reg\n");
return err;
}
#endif
/* Set the maxinum load current */
/* VDD1 */
val = tps65910_reg_read(tps65910, TPS65910_VDD1);
if (val<0) {
printk(KERN_ERR "Unable to read TPS65910_VDD1 reg\n");
return val;
}
val |= (1<<5); //when 1: 1.5 A
val |= (0x07<<2); //TSTEP[2:0] = 111 : 2.5 mV/|¨¬s(sampling 3 Mhz/5)
err = tps65910_reg_write(tps65910, TPS65910_VDD1, val);
if (err) {
printk(KERN_ERR "Unable to write TPS65910_VDD1 reg\n");
return err;
}
/* VDD2 */
val = tps65910_reg_read(tps65910, TPS65910_VDD2);
if (val<0) {
printk(KERN_ERR "Unable to read TPS65910_VDD2 reg\n");
return val;
}
val |= (1<<5); //when 1: 1.5 A
err = tps65910_reg_write(tps65910, TPS65910_VDD2, val);
if (err) {
printk(KERN_ERR "Unable to write TPS65910_VDD2 reg\n");
return err;
}
/* VIO */
val = tps65910_reg_read(tps65910, TPS65910_VIO);
if (val<0) {
printk(KERN_ERR "Unable to read TPS65910_VIO reg\n");
return -EIO;
}
val |= (1<<6); //when 01: 1.0 A
err = tps65910_reg_write(tps65910, TPS65910_VIO, val);
if (err) {
printk(KERN_ERR "Unable to write TPS65910_VIO reg\n");
return err;
}
#if 1
/* Mask ALL interrupts */
err = tps65910_reg_write(tps65910,TPS65910_INT_MSK, 0xFF);
if (err) {
printk(KERN_ERR "Unable to write TPS65910_INT_MSK reg\n");
return err;
}
err = tps65910_reg_write(tps65910, TPS65910_INT_MSK2, 0x03);
if (err) {
printk(KERN_ERR "Unable to write TPS65910_INT_MSK2 reg\n");
return err;
}
/* Set RTC Power, disable Smart Reflex in DEVCTRL_REG */
#if 1
val = 0;
val |= (DEVCTRL_SR_CTL_I2C_SEL_MASK);
err = tps65910_reg_write(tps65910, TPS65910_DEVCTRL, val);
if (err) {
printk(KERN_ERR "Unable to write TPS65910_DEVCTRL reg\n");
return err;
}
printk(KERN_INFO "TPS65910 Set default voltage.\n");
#endif
#if 0
//read sleep control register for debug
for(i=0; i<6; i++)
{
err = tps65910_reg_read(tps65910, &val, TPS65910_DEVCTRL+i);
if (err) {
printk(KERN_ERR "Unable to read TPS65910_DCDCCTRL reg\n");
return -EIO;
}
else
printk("%s.......is 0x%04x\n",__FUNCTION__,val);
}
#endif
#if 1
//sleep control register
/*set func when in sleep mode */
val = tps65910_reg_read(tps65910, TPS65910_DEVCTRL);
if (val<0) {
printk(KERN_ERR "Unable to read TPS65910_DCDCCTRL reg\n");
return val;
}
val |= (1 << 1);
err = tps65910_reg_write(tps65910, TPS65910_DEVCTRL, val);
if (err) {
printk(KERN_ERR "Unable to read TPS65910 Reg at offset 0x%x= \
\n", TPS65910_VDIG1);
return err;
}
/* open ldo when in sleep mode */
val = tps65910_reg_read(tps65910, TPS65910_SLEEP_KEEP_LDO_ON);
if (val<0) {
printk(KERN_ERR "Unable to read TPS65910_DCDCCTRL reg\n");
return val;
}
val &= 0;
err = tps65910_reg_write(tps65910, TPS65910_SLEEP_KEEP_LDO_ON, val);
if (err) {
printk(KERN_ERR "Unable to read TPS65910 Reg at offset 0x%x= \
\n", TPS65910_VDIG1);
return err;
}
/*set dc mode when in sleep mode */
val = tps65910_reg_read(tps65910, TPS65910_SLEEP_KEEP_RES_ON);
if (val<0) {
printk(KERN_ERR "Unable to read TPS65910_DCDCCTRL reg\n");
return val;
}
val |= 0xff;
err = tps65910_reg_write(tps65910, TPS65910_SLEEP_KEEP_RES_ON, val);
if (err) {
printk(KERN_ERR "Unable to read TPS65910 Reg at offset 0x%x= \
\n", TPS65910_VDIG1);
return err;
}
/*close ldo when in sleep mode */
val = tps65910_reg_read(tps65910, TPS65910_SLEEP_SET_LDO_OFF);
if (val<0) {
printk(KERN_ERR "Unable to read TPS65910_DCDCCTRL reg\n");
return val;
}
val |= 0x9B;
err = tps65910_reg_write(tps65910, TPS65910_SLEEP_SET_LDO_OFF, val);
if (err) {
printk(KERN_ERR "Unable to read TPS65910 Reg at offset 0x%x= \
\n", TPS65910_VDIG1);
return err;
}
#endif
#if 0
//read sleep control register for debug
for(i=0; i<6; i++)
{
err = tps65910_reg_read(tps65910, &val, TPS65910_DEVCTRL+i);
if (err) {
printk(KERN_ERR "Unable to read TPS65910_DCDCCTRL reg\n");
return -EIO;
}
else
printk("%s.......is 0x%4x\n",__FUNCTION__,val);
}
#endif
#endif
printk("%s,line=%d\n", __func__,__LINE__);
return 0;
}
int tps65910_post_init(struct tps65910 *tps65910)
{
struct regulator *dcdc;
struct regulator *ldo;
printk("%s,line=%d\n", __func__,__LINE__);
dcdc = regulator_get(NULL, "vio"); //vcc_io
regulator_set_voltage(dcdc, 3300000, 3300000);
regulator_enable(dcdc);
printk("%s set vio vcc_io=%dmV end\n", __func__, regulator_get_voltage(dcdc));
regulator_put(dcdc);
udelay(100);
ldo = regulator_get(NULL, "vpll"); // vcc25
regulator_set_voltage(ldo, 2500000, 2500000);
regulator_enable(ldo);
printk("%s set vpll vcc25=%dmV end\n", __func__, regulator_get_voltage(ldo));
regulator_put(ldo);
udelay(100);
ldo = regulator_get(NULL, "vdig2"); // vdd11
regulator_set_voltage(ldo, 1200000, 1200000);
regulator_enable(ldo);
printk("%s set vdig2 vdd11=%dmV end\n", __func__, regulator_get_voltage(ldo));
regulator_put(ldo);
udelay(100);
ldo = regulator_get(NULL, "vaux33"); //vcc_tp
regulator_set_voltage(ldo, 3300000, 3300000);
regulator_enable(ldo);
printk("%s set vaux33 vcc_tp=%dmV end\n", __func__, regulator_get_voltage(ldo));
regulator_put(ldo);
udelay(100);
dcdc = regulator_get(NULL, "vdd_cpu"); //vdd_cpu
regulator_set_voltage(dcdc, 1200000, 1200000);
regulator_enable(dcdc);
printk("%s set vdd1 vdd_cpu=%dmV end\n", __func__, regulator_get_voltage(dcdc));
regulator_put(dcdc);
udelay(100);
dcdc = regulator_get(NULL, "vdd2"); //vcc_ddr
regulator_set_voltage(dcdc, 1200000, 1200000); // 1.5*4/5 = 1.2 and Vout=1.5v
regulator_enable(dcdc);
printk("%s set vdd2 vcc_ddr=%dmV end\n", __func__, regulator_get_voltage(dcdc));
regulator_put(dcdc);
udelay(100);
ldo = regulator_get(NULL, "vdig1"); //vcc18_cif
regulator_set_voltage(ldo, 1800000, 1800000);
regulator_enable(ldo);
printk("%s set vdig1 vcc18_cif=%dmV end\n", __func__, regulator_get_voltage(ldo));
regulator_put(ldo);
udelay(100);
dcdc = regulator_get(NULL, "vaux1"); //vcc25_hdmi
regulator_set_voltage(dcdc,2500000,2500000);
regulator_enable(dcdc);
printk("%s set vaux1 vcc25_hdmi=%dmV end\n", __func__, regulator_get_voltage(dcdc));
regulator_put(dcdc);
udelay(100);
ldo = regulator_get(NULL, "vaux2"); //vcca33
regulator_set_voltage(ldo, 3300000, 3300000);
regulator_enable(ldo);
printk("%s set vaux2 vcca33=%dmV end\n", __func__, regulator_get_voltage(ldo));
regulator_put(ldo);
udelay(100);
ldo = regulator_get(NULL, "vdac"); // vccio_wl
regulator_set_voltage(ldo,1800000,1800000);
regulator_enable(ldo);
printk("%s set vdac vccio_wl=%dmV end\n", __func__, regulator_get_voltage(ldo));
regulator_put(ldo);
udelay(100);
ldo = regulator_get(NULL, "vmmc"); //vcc28_cif
regulator_set_voltage(ldo,2800000,2800000);
regulator_enable(ldo);
printk("%s set vmmc vcc28_cif=%dmV end\n", __func__, regulator_get_voltage(ldo));
regulator_put(ldo);
udelay(100);
#ifdef CONFIG_RK30_PWM_REGULATOR
dcdc = regulator_get(NULL, "vdd_core"); // vdd_log
regulator_set_voltage(dcdc, 1100000, 1100000);
regulator_enable(dcdc);
printk("%s set vdd_core=%dmV end\n", __func__, regulator_get_voltage(dcdc));
regulator_put(dcdc);
udelay(100);
#endif
printk("%s,line=%d END\n", __func__,__LINE__);
return 0;
}
static struct regulator_consumer_supply tps65910_smps1_supply[] = {
{
.supply = "vdd1",
},
{
.supply = "vdd_cpu",
},
};
static struct regulator_consumer_supply tps65910_smps2_supply[] = {
{
.supply = "vdd2",
},
};
static struct regulator_consumer_supply tps65910_smps3_supply[] = {
{
.supply = "vdd3",
},
};
static struct regulator_consumer_supply tps65910_smps4_supply[] = {
{
.supply = "vio",
},
};
static struct regulator_consumer_supply tps65910_ldo1_supply[] = {
{
.supply = "vdig1",
},
};
static struct regulator_consumer_supply tps65910_ldo2_supply[] = {
{
.supply = "vdig2",
},
};
static struct regulator_consumer_supply tps65910_ldo3_supply[] = {
{
.supply = "vaux1",
},
};
static struct regulator_consumer_supply tps65910_ldo4_supply[] = {
{
.supply = "vaux2",
},
};
static struct regulator_consumer_supply tps65910_ldo5_supply[] = {
{
.supply = "vaux33",
},
};
static struct regulator_consumer_supply tps65910_ldo6_supply[] = {
{
.supply = "vmmc",
},
};
static struct regulator_consumer_supply tps65910_ldo7_supply[] = {
{
.supply = "vdac",
},
};
static struct regulator_consumer_supply tps65910_ldo8_supply[] = {
{
.supply = "vpll",
},
};
static struct regulator_init_data tps65910_smps1 = {
.constraints = {
.name = "VDD1",
.min_uV = 600000,
.max_uV = 1500000,
.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,
},
.num_consumer_supplies = ARRAY_SIZE(tps65910_smps1_supply),
.consumer_supplies = tps65910_smps1_supply,
};
/* */
static struct regulator_init_data tps65910_smps2 = {
.constraints = {
.name = "VDD2",
.min_uV = 600000,
.max_uV = 1500000,
.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,
},
.num_consumer_supplies = ARRAY_SIZE(tps65910_smps2_supply),
.consumer_supplies = tps65910_smps2_supply,
};
/* */
static struct regulator_init_data tps65910_smps3 = {
.constraints = {
.name = "VDD3",
.min_uV = 1000000,
.max_uV = 1400000,
.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,
},
.num_consumer_supplies = ARRAY_SIZE(tps65910_smps3_supply),
.consumer_supplies = tps65910_smps3_supply,
};
static struct regulator_init_data tps65910_smps4 = {
.constraints = {
.name = "VIO",
.min_uV = 1800000,
.max_uV = 3300000,
.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,
},
.num_consumer_supplies = ARRAY_SIZE(tps65910_smps4_supply),
.consumer_supplies = tps65910_smps4_supply,
};
static struct regulator_init_data tps65910_ldo1 = {
.constraints = {
.name = "VDIG1",
.min_uV = 1200000,
.max_uV = 2700000,
.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(tps65910_ldo1_supply),
.consumer_supplies = tps65910_ldo1_supply,
};
/* */
static struct regulator_init_data tps65910_ldo2 = {
.constraints = {
.name = "VDIG2",
.min_uV = 1000000,
.max_uV = 1800000,
.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(tps65910_ldo2_supply),
.consumer_supplies = tps65910_ldo2_supply,
};
/* */
static struct regulator_init_data tps65910_ldo3 = {
.constraints = {
.name = "VAUX1",
.min_uV = 1800000,
.max_uV = 3300000,
.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(tps65910_ldo3_supply),
.consumer_supplies = tps65910_ldo3_supply,
};
/* */
static struct regulator_init_data tps65910_ldo4 = {
.constraints = {
.name = "VAUX2",
.min_uV = 1800000,
.max_uV = 3300000,
.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(tps65910_ldo4_supply),
.consumer_supplies = tps65910_ldo4_supply,
};
/* */
static struct regulator_init_data tps65910_ldo5 = {
.constraints = {
.name = "VAUX33",
.min_uV = 1800000,
.max_uV = 3300000,
.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(tps65910_ldo5_supply),
.consumer_supplies = tps65910_ldo5_supply,
};
/* */
static struct regulator_init_data tps65910_ldo6 = {
.constraints = {
.name = "VMMC",
.min_uV = 1800000,
.max_uV = 3300000,
.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(tps65910_ldo6_supply),
.consumer_supplies = tps65910_ldo6_supply,
};
/* */
static struct regulator_init_data tps65910_ldo7 = {
.constraints = {
.name = "VDAC",
.min_uV = 1800000,
.max_uV = 2850000,
.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(tps65910_ldo7_supply),
.consumer_supplies = tps65910_ldo7_supply,
};
/* */
static struct regulator_init_data tps65910_ldo8 = {
.constraints = {
.name = "VPLL",
.min_uV = 1000000,
.max_uV = 2500000,
.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,
},
.num_consumer_supplies = ARRAY_SIZE(tps65910_ldo8_supply),
.consumer_supplies = tps65910_ldo8_supply,
};
/*
void __sramfunc board_pmu_tps65910_suspend(void)
{
grf_writel(GPIO6_PB1_DIR_OUT, GRF_GPIO6L_DIR_ADDR);
grf_writel(GPIO6_PB1_DO_HIGH, GRF_GPIO6L_DO_ADDR); //set gpio6_b1 output low
grf_writel(GPIO6_PB1_EN_MASK, GRF_GPIO6L_EN_ADDR);
}
void __sramfunc board_pmu_tps65910_resume(void)
{
grf_writel(GPIO6_PB1_DIR_OUT, GRF_GPIO6L_DIR_ADDR);
grf_writel(GPIO6_PB1_DO_LOW, GRF_GPIO6L_DO_ADDR); //set gpio6_b1 output low
grf_writel(GPIO6_PB1_EN_MASK, GRF_GPIO6L_EN_ADDR);
#ifdef CONFIG_CLK_SWITCH_TO_32K //switch clk to 24M
sram_32k_udelay(10000);
#else
sram_udelay(2000);
#endif
}
*/
static struct tps65910_board tps65910_data = {
.irq = (unsigned)TPS65910_HOST_IRQ,
.irq_base = NR_GIC_IRQS + NR_GPIO_IRQS,
// .gpio_base = TPS65910_GPIO_EXPANDER_BASE,
.pre_init = tps65910_pre_init,
.post_init = tps65910_post_init,
//TPS65910_NUM_REGS = 13
// Regulators
.tps65910_pmic_init_data[TPS65910_REG_VRTC] = NULL,
.tps65910_pmic_init_data[TPS65910_REG_VIO] = &tps65910_smps4,
.tps65910_pmic_init_data[TPS65910_REG_VDD1] = &tps65910_smps1,
.tps65910_pmic_init_data[TPS65910_REG_VDD2] = &tps65910_smps2,
.tps65910_pmic_init_data[TPS65910_REG_VDD3] = &tps65910_smps3,
.tps65910_pmic_init_data[TPS65910_REG_VDIG1] = &tps65910_ldo1,
.tps65910_pmic_init_data[TPS65910_REG_VDIG2] = &tps65910_ldo2,
.tps65910_pmic_init_data[TPS65910_REG_VPLL] = &tps65910_ldo8,
.tps65910_pmic_init_data[TPS65910_REG_VDAC] = &tps65910_ldo7,
.tps65910_pmic_init_data[TPS65910_REG_VAUX1] = &tps65910_ldo3,
.tps65910_pmic_init_data[TPS65910_REG_VAUX2] = &tps65910_ldo4,
.tps65910_pmic_init_data[TPS65910_REG_VAUX33] = &tps65910_ldo5,
.tps65910_pmic_init_data[TPS65910_REG_VMMC] = &tps65910_ldo6,
};
#endif

View File

@ -261,6 +261,12 @@ config GPIO_TC3589X
This enables support for the GPIOs found on the TC3589X
I/O Expander.
config GPIO_TPS65912
tristate "TI TPS65912 GPIO"
depends on (MFD_TPS65912_I2C || MFD_TPS65912_SPI)
help
This driver supports TPS65912 gpio chip
config GPIO_TWL4030
tristate "TWL4030, TWL5030, and TPS659x0 GPIOs"
depends on TWL4030_CORE

View File

@ -54,4 +54,5 @@ obj-$(CONFIG_GPIO_SX150X) += sx150x.o
obj-$(CONFIG_GPIO_VX855) += vx855_gpio.o
obj-$(CONFIG_GPIO_ML_IOH) += ml_ioh_gpio.o
obj-$(CONFIG_AB8500_GPIO) += ab8500-gpio.o
obj-$(CONFIG_GPIO_TPS65910) += tps65910-gpio.o
obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o
obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o

118
drivers/gpio/gpio-tps65910.c Executable file
View File

@ -0,0 +1,118 @@
/*
* TI TPS6591x GPIO driver
*
* Copyright 2010 Texas Instruments Inc.
*
* Author: Graeme Gregory <gg@slimlogic.co.uk>
* Author: Jorge Eduardo Candelaria jedu@slimlogic.co.uk>
*
* 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.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/mfd/tps65910.h>
static int tps65910_gpio_get(struct gpio_chip *gc, unsigned offset)
{
struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
uint8_t val;
tps65910->read(tps65910, TPS65910_GPIO0 + offset, 1, &val);
if (val & GPIO_STS_MASK)
return 1;
return 0;
}
static void tps65910_gpio_set(struct gpio_chip *gc, unsigned offset,
int value)
{
struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
if (value)
tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset,
GPIO_SET_MASK);
else
tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset,
GPIO_SET_MASK);
}
static int tps65910_gpio_output(struct gpio_chip *gc, unsigned offset,
int value)
{
struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
/* Set the initial value */
tps65910_gpio_set(gc, offset, value);
return tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset,
GPIO_CFG_MASK);
}
static int tps65910_gpio_input(struct gpio_chip *gc, unsigned offset)
{
struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
return tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset,
GPIO_CFG_MASK);
}
void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base)
{
int ret;
struct tps65910_board *board_data;
if (!gpio_base)
return;
tps65910->gpio.owner = THIS_MODULE;
tps65910->gpio.label = tps65910->i2c_client->name;
tps65910->gpio.dev = tps65910->dev;
tps65910->gpio.base = gpio_base;
switch(tps65910_chip_id(tps65910)) {
case TPS65910:
tps65910->gpio.ngpio = TPS65910_NUM_GPIO;
break;
case TPS65911:
tps65910->gpio.ngpio = TPS65911_NUM_GPIO;
break;
default:
return;
}
tps65910->gpio.can_sleep = 1;
tps65910->gpio.direction_input = tps65910_gpio_input;
tps65910->gpio.direction_output = tps65910_gpio_output;
tps65910->gpio.set = tps65910_gpio_set;
tps65910->gpio.get = tps65910_gpio_get;
/* Configure sleep control for gpios */
board_data = dev_get_platdata(tps65910->dev);
if (board_data) {
int i;
for (i = 0; i < tps65910->gpio.ngpio; ++i) {
if (board_data->en_gpio_sleep[i]) {
ret = tps65910_set_bits(tps65910,
TPS65910_GPIO0 + i, GPIO_SLEEP_MASK);
if (ret < 0)
dev_warn(tps65910->dev,
"GPIO Sleep setting failed\n");
}
}
}
ret = gpiochip_add(&tps65910->gpio);
if (ret)
dev_warn(tps65910->dev, "GPIO registration failed: %d\n", ret);
}

0
drivers/gpio/tps65910-gpio.c Normal file → Executable file
View File

View File

@ -171,6 +171,37 @@ config MFD_TPS6586X
This driver can also be built as a module. If so, the module
will be called tps6586x.
config MFD_TPS65910
bool "TPS65910 Power Management chip"
depends on I2C=y && GPIOLIB
select MFD_CORE
select GPIO_TPS65910
select REGMAP_I2C
help
if you say yes here you get support for the TPS65910 series of
Power Management chips.
config MFD_TPS65912
bool
depends on GPIOLIB
config MFD_TPS65912_I2C
bool "TPS65912 Power Management chip with I2C"
select MFD_CORE
select MFD_TPS65912
depends on I2C=y && GPIOLIB
help
If you say yes here you get support for the TPS65912 series of
PM chips with I2C interface.
config MFD_TPS65912_SPI
bool "TPS65912 Power Management chip with SPI"
select MFD_CORE
select MFD_TPS65912
depends on SPI_MASTER && GPIOLIB
help
If you say yes here you get support for the TPS65912 series of
PM chips with SPI interface.
config MENELAUS
bool "Texas Instruments TWL92330/Menelaus PM chip"
depends on I2C=y && ARCH_OMAP2
@ -769,18 +800,21 @@ config MFD_PM8XXX_IRQ
This is required to use certain other PM 8xxx features, such as GPIO
and MPP.
config MFD_TPS65910
bool "TPS65910 Power Management chip"
depends on I2C=y && GPIOLIB
select MFD_CORE
select GPIO_TPS65910
help
if you say yes here you get support for the TPS65910 series of
Power Management chips.
config TPS65911_COMPARATOR
tristate
config MFD_TPS65090
bool "TPS65090 Power Management chips"
depends on I2C=y && GENERIC_HARDIRQS
select MFD_CORE
select REGMAP_I2C
help
If you say yes here you get support for the TPS65090 series of
Power Management chips.
This driver provides common support for accessing the device,
additional drivers must be enabled in order to use the
functionality of the device.
config MFD_RK610
bool "RK610(Jetta) Multimedia support"
depends on I2C=y && GPIOLIB

View File

@ -36,6 +36,11 @@ obj-$(CONFIG_MFD_WM8994) += wm8994-core.o wm8994-irq.o
obj-$(CONFIG_TPS6105X) += tps6105x.o
obj-$(CONFIG_TPS65010) += tps65010.o
obj-$(CONFIG_TPS6507X) += tps6507x.o
obj-$(CONFIG_MFD_TPS65910) += tps65910.o tps65910-irq.o
tps65912-objs := tps65912-core.o tps65912-irq.o
obj-$(CONFIG_MFD_TPS65912) += tps65912.o
obj-$(CONFIG_MFD_TPS65912_I2C) += tps65912-i2c.o
obj-$(CONFIG_MFD_TPS65912_SPI) += tps65912-spi.o
obj-$(CONFIG_MENELAUS) += menelaus.o
obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o

30
drivers/mfd/tps65910-irq.c Normal file → Executable file
View File

@ -45,7 +45,7 @@ static irqreturn_t tps65910_irq(int irq, void *irq_data)
u32 irq_mask;
u8 reg;
int i;
tps65910->read(tps65910, TPS65910_INT_STS, 1, &reg);
irq_sts = reg;
tps65910->read(tps65910, TPS65910_INT_STS2, 1, &reg);
@ -145,12 +145,23 @@ static void tps65910_irq_disable(struct irq_data *data)
tps65910->irq_mask |= ( 1 << irq_to_tps65910_irq(tps65910, data->irq));
}
#ifdef CONFIG_PM_SLEEP
static int tps65910_irq_set_wake(struct irq_data *data, unsigned int enable)
{
struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data);
return irq_set_irq_wake(tps65910->chip_irq, enable);
}
#else
#define tps65910_irq_set_wake NULL
#endif
static struct irq_chip tps65910_irq_chip = {
.name = "tps65910",
.irq_bus_lock = tps65910_irq_lock,
.irq_bus_sync_unlock = tps65910_irq_sync_unlock,
.irq_disable = tps65910_irq_disable,
.irq_enable = tps65910_irq_enable,
.irq_set_wake = tps65910_irq_set_wake,
};
int tps65910_irq_init(struct tps65910 *tps65910, int irq,
@ -158,17 +169,27 @@ int tps65910_irq_init(struct tps65910 *tps65910, int irq,
{
int ret, cur_irq;
int flags = IRQF_ONESHOT;
u8 reg;
if (!irq) {
dev_warn(tps65910->dev, "No interrupt support, no core IRQ\n");
return -EINVAL;
return 0;
}
if (!pdata || !pdata->irq_base) {
dev_warn(tps65910->dev, "No interrupt support, no IRQ base\n");
return -EINVAL;
return 0;
}
/* Clear unattended interrupts */
tps65910->read(tps65910, TPS65910_INT_STS, 1, &reg);
tps65910->write(tps65910, TPS65910_INT_STS, 1, &reg);
tps65910->read(tps65910, TPS65910_INT_STS2, 1, &reg);
tps65910->write(tps65910, TPS65910_INT_STS2, 1, &reg);
tps65910->read(tps65910, TPS65910_INT_STS3, 1, &reg);
tps65910->write(tps65910, TPS65910_INT_STS3, 1, &reg);
/* Mask top level interrupts */
tps65910->irq_mask = 0xFFFFFF;
mutex_init(&tps65910->irq_lock);
@ -215,6 +236,7 @@ int tps65910_irq_init(struct tps65910 *tps65910, int irq,
int tps65910_irq_exit(struct tps65910 *tps65910)
{
free_irq(tps65910->chip_irq, tps65910);
if (tps65910->chip_irq)
free_irq(tps65910->chip_irq, tps65910);
return 0;
}

168
drivers/mfd/tps65910.c Normal file → Executable file
View File

@ -22,6 +22,8 @@
#include <linux/mfd/core.h>
#include <linux/mfd/tps65910.h>
struct tps65910 *g_tps65910;
static struct mfd_cell tps65910s[] = {
{
.name = "tps65910-pmic",
@ -34,6 +36,7 @@ static struct mfd_cell tps65910s[] = {
},
};
#define TPS65910_SPEED 200 * 1000
static int tps65910_i2c_read(struct tps65910 *tps65910, u8 reg,
int bytes, void *dest)
@ -41,25 +44,30 @@ static int tps65910_i2c_read(struct tps65910 *tps65910, u8 reg,
struct i2c_client *i2c = tps65910->i2c_client;
struct i2c_msg xfer[2];
int ret;
//int i;
/* Write register */
xfer[0].addr = i2c->addr;
xfer[0].flags = 0;
xfer[0].len = 1;
xfer[0].buf = &reg;
xfer[0].scl_rate = TPS65910_SPEED;
/* Read data */
xfer[1].addr = i2c->addr;
xfer[1].flags = I2C_M_RD;
xfer[1].len = bytes;
xfer[1].buf = dest;
xfer[1].scl_rate = TPS65910_SPEED;
ret = i2c_transfer(i2c->adapter, xfer, 2);
//for(i=0;i<bytes;i++)
//printk("%s:reg=0x%x,value=0x%x\n",__func__,reg+i,*(u8 *)dest++);
if (ret == 2)
ret = 0;
else if (ret >= 0)
ret = -EIO;
return ret;
}
@ -70,21 +78,114 @@ static int tps65910_i2c_write(struct tps65910 *tps65910, u8 reg,
/* we add 1 byte for device register */
u8 msg[TPS65910_MAX_REGISTER + 1];
int ret;
//int i;
if (bytes > TPS65910_MAX_REGISTER)
return -EINVAL;
msg[0] = reg;
memcpy(&msg[1], src, bytes);
//for(i=0;i<bytes;i++)
//printk("%s:reg=0x%x,value=0x%x\n",__func__,reg+i,msg[i+1]);
ret = i2c_master_send(i2c, msg, bytes + 1);
if (ret < 0)
return ret;
if (ret != bytes + 1)
return -EIO;
return 0;
}
static inline int tps65910_read(struct tps65910 *tps65910, u8 reg)
{
u8 val;
int err;
err = tps65910->read(tps65910, reg, 1, &val);
if (err < 0)
return err;
return val;
}
static inline int tps65910_write(struct tps65910 *tps65910, u8 reg, u8 val)
{
return tps65910->write(tps65910, reg, 1, &val);
}
int tps65910_reg_read(struct tps65910 *tps65910, u8 reg)
{
int data;
mutex_lock(&tps65910->io_mutex);
data = tps65910_read(tps65910, reg);
if (data < 0)
dev_err(tps65910->dev, "Read from reg 0x%x failed\n", reg);
mutex_unlock(&tps65910->io_mutex);
return data;
}
EXPORT_SYMBOL_GPL(tps65910_reg_read);
int tps65910_reg_write(struct tps65910 *tps65910, u8 reg, u8 val)
{
int err;
mutex_lock(&tps65910->io_mutex);
err = tps65910_write(tps65910, reg, val);
if (err < 0)
dev_err(tps65910->dev, "Write for reg 0x%x failed\n", reg);
mutex_unlock(&tps65910->io_mutex);
return err;
}
EXPORT_SYMBOL_GPL(tps65910_reg_write);
/**
* tps65910_bulk_read: Read multiple tps65910 registers
*
* @tps65910: Device to read from
* @reg: First register
* @count: Number of registers
* @buf: Buffer to fill.
*/
int tps65910_bulk_read(struct tps65910 *tps65910, u8 reg,
int count, u8 *buf)
{
int ret;
mutex_lock(&tps65910->io_mutex);
ret = tps65910->read(tps65910, reg, count, buf);
mutex_unlock(&tps65910->io_mutex);
return ret;
}
EXPORT_SYMBOL_GPL(tps65910_bulk_read);
int tps65910_bulk_write(struct tps65910 *tps65910, u8 reg,
int count, u8 *buf)
{
int ret;
mutex_lock(&tps65910->io_mutex);
ret = tps65910->write(tps65910, reg, count, buf);
mutex_unlock(&tps65910->io_mutex);
return ret;
}
EXPORT_SYMBOL_GPL(tps65910_bulk_write);
int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask)
{
u8 data;
@ -93,14 +194,14 @@ int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask)
mutex_lock(&tps65910->io_mutex);
err = tps65910_i2c_read(tps65910, reg, 1, &data);
if (err) {
dev_err(tps65910->dev, "read from reg %x failed\n", reg);
dev_err(tps65910->dev, "%s:read from reg %x failed\n", __func__,reg);
goto out;
}
data |= mask;
err = tps65910_i2c_write(tps65910, reg, 1, &data);
if (err)
dev_err(tps65910->dev, "write to reg %x failed\n", reg);
dev_err(tps65910->dev, "%s:write to reg %x failed\n", __func__,reg);
out:
mutex_unlock(&tps65910->io_mutex);
@ -120,7 +221,7 @@ int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask)
goto out;
}
data &= mask;
data &= ~mask;
err = tps65910_i2c_write(tps65910, reg, 1, &data);
if (err)
dev_err(tps65910->dev, "write to reg %x failed\n", reg);
@ -138,7 +239,7 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
struct tps65910_board *pmic_plat_data;
struct tps65910_platform_data *init_data;
int ret = 0;
pmic_plat_data = dev_get_platdata(&i2c->dev);
if (!pmic_plat_data)
return -EINVAL;
@ -148,7 +249,7 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
return -ENOMEM;
init_data->irq = pmic_plat_data->irq;
init_data->irq_base = pmic_plat_data->irq;
init_data->irq_base = pmic_plat_data->irq_base;
tps65910 = kzalloc(sizeof(struct tps65910), GFP_KERNEL);
if (tps65910 == NULL)
@ -167,6 +268,16 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
NULL, 0);
if (ret < 0)
goto err;
g_tps65910 = tps65910;
if (pmic_plat_data && pmic_plat_data->pre_init) {
ret = pmic_plat_data->pre_init(tps65910);
if (ret != 0) {
dev_err(tps65910->dev, "pre_init() failed: %d\n", ret);
goto err;
}
}
tps65910_gpio_init(tps65910, pmic_plat_data->gpio_base);
@ -174,6 +285,15 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
if (ret < 0)
goto err;
if (pmic_plat_data && pmic_plat_data->post_init) {
ret = pmic_plat_data->post_init(tps65910);
if (ret != 0) {
dev_err(tps65910->dev, "post_init() failed: %d\n", ret);
goto err;
}
}
printk("%s:irq=%d,irq_base=%d,gpio_base=%d\n",__func__,init_data->irq,init_data->irq_base,pmic_plat_data->gpio_base);
return ret;
err:
@ -182,6 +302,36 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
return ret;
}
int tps65910_device_shutdown(void)
{
int val = 0;
int err = -1;
struct tps65910 *tps65910 = g_tps65910;
printk("%s\n",__func__);
val = tps65910_reg_read(tps65910, TPS65910_DEVCTRL);
if (val<0) {
printk(KERN_ERR "Unable to read TPS65910_REG_DCDCCTRL reg\n");
return -EIO;
}
val |= DEVCTRL_DEV_OFF_MASK;
val &= ~DEVCTRL_CK32K_CTRL_MASK; //keep rtc
err = tps65910_reg_write(tps65910, TPS65910_DEVCTRL, val);
if (err) {
printk(KERN_ERR "Unable to read TPS65910 Reg at offset 0x%x= \
\n", TPS65910_REG_VDIG1);
return err;
}
return 0;
}
EXPORT_SYMBOL_GPL(tps65910_device_shutdown);
static int tps65910_i2c_remove(struct i2c_client *i2c)
{
struct tps65910 *tps65910 = i2c_get_clientdata(i2c);
@ -215,7 +365,7 @@ static int __init tps65910_i2c_init(void)
return i2c_add_driver(&tps65910_i2c_driver);
}
/* init early so consumer devices can complete system boot */
subsys_initcall(tps65910_i2c_init);
subsys_initcall_sync(tps65910_i2c_init);
static void __exit tps65910_i2c_exit(void)
{

0
drivers/mfd/tps65911-comparator.c Normal file → Executable file
View File

View File

@ -125,6 +125,17 @@ config REGULATOR_MAX8998
via I2C bus. The provided regulator is suitable for S3C6410
and S5PC1XX chips to control VCC_CORE and VCC_USIM voltages.
config REGULATOR_TPS65910
tristate "TI TPS65910/TPS65911 Power Regulators"
depends on MFD_TPS65910
help
This driver supports TPS65910/TPS65911 voltage regulator chips.
config REGULATOR_TPS65912
tristate "TI TPS65912 Power regulator"
depends on (MFD_TPS65912_I2C || MFD_TPS65912_SPI)
help
This driver supports TPS65912 voltage regulator chip.
config REGULATOR_TWL4030
bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 PMIC"
depends on TWL4030_CORE
@ -324,11 +335,7 @@ config REGULATOR_TPS6524X
serial interface currently supported on the sequencer serial
port controller.
config REGULATOR_TPS65910
tristate "TI TPS65910 Power Regulator"
depends on MFD_TPS65910
help
This driver supports TPS65910 voltage regulator chips.
endif

View File

@ -49,6 +49,7 @@ obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o
obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
obj-$(CONFIG_REGULATOR_ACT8891) += act8891.o
ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG

592
drivers/regulator/tps65910-regulator.c Normal file → Executable file

File diff suppressed because it is too large Load Diff

View File

@ -1110,5 +1110,10 @@ config RTC_DRV_PUV3
This drive can also be built as a module. If so, the module
will be called rtc-puv3.
config TPS65910_RTC
tristate "tps65910 rtc for rk"
depends on MFD_TPS65910
help
enable tps65910 rtc for system
endif # RTC_CLASS

View File

@ -115,3 +115,4 @@ obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o
obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
obj-$(CONFIG_RTC_HYM8563) += rtc-HYM8563.o
obj-$(CONFIG_RTC_M41T66) += rtc-m41t66.o
obj-$(CONFIG_TPS65910_RTC) += rtc-tps65910.o

695
drivers/rtc/rtc-tps65910.c Executable file
View File

@ -0,0 +1,695 @@
/*
* Real Time Clock driver for Wolfson Microelectronics tps65910
*
* Copyright (C) 2009 Wolfson Microelectronics PLC.
*
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
*
* 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.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/time.h>
#include <linux/rtc.h>
#include <linux/slab.h>
#include <linux/bcd.h>
#include <linux/interrupt.h>
#include <linux/ioctl.h>
#include <linux/completion.h>
#include <linux/mfd/tps65910.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
/* RTC Definitions */
/* RTC_CTRL_REG bitfields */
#define BIT_RTC_CTRL_REG_STOP_RTC_M 0x01
#define BIT_RTC_CTRL_REG_ROUND_30S_M 0x02
#define BIT_RTC_CTRL_REG_AUTO_COMP_M 0x04
#define BIT_RTC_CTRL_REG_MODE_12_24_M 0x08
#define BIT_RTC_CTRL_REG_TEST_MODE_M 0x10
#define BIT_RTC_CTRL_REG_SET_32_COUNTER_M 0x20
#define BIT_RTC_CTRL_REG_GET_TIME_M 0x40
#define BIT_RTC_CTRL_REG_RTC_V_OPT_M 0x80
/* RTC_STATUS_REG bitfields */
#define BIT_RTC_STATUS_REG_RUN_M 0x02
#define BIT_RTC_STATUS_REG_1S_EVENT_M 0x04
#define BIT_RTC_STATUS_REG_1M_EVENT_M 0x08
#define BIT_RTC_STATUS_REG_1H_EVENT_M 0x10
#define BIT_RTC_STATUS_REG_1D_EVENT_M 0x20
#define BIT_RTC_STATUS_REG_ALARM_M 0x40
#define BIT_RTC_STATUS_REG_POWER_UP_M 0x80
/* RTC_INTERRUPTS_REG bitfields */
#define BIT_RTC_INTERRUPTS_REG_EVERY_M 0x03
#define BIT_RTC_INTERRUPTS_REG_IT_TIMER_M 0x04
#define BIT_RTC_INTERRUPTS_REG_IT_ALARM_M 0x08
/* DEVCTRL bitfields */
#define BIT_RTC_PWDN 0x40
/* REG_SECONDS_REG through REG_YEARS_REG is how many registers? */
#define ALL_TIME_REGS 7
#define ALL_ALM_REGS 6
#define RTC_SET_TIME_RETRIES 5
#define RTC_GET_TIME_RETRIES 5
struct tps65910_rtc {
struct tps65910 *tps65910;
struct rtc_device *rtc;
unsigned int alarm_enabled:1;
};
/*
* Read current time and date in RTC
*/
static int tps65910_rtc_readtime(struct device *dev, struct rtc_time *tm)
{
struct tps65910_rtc *tps65910_rtc = dev_get_drvdata(dev);
struct tps65910 *tps65910 = tps65910_rtc->tps65910;
int ret;
int count = 0;
unsigned char rtc_data[ALL_TIME_REGS + 1];
u8 rtc_ctl;
/*Dummy read*/
ret = tps65910_reg_read(tps65910, TPS65910_RTC_CTRL);
/* Has the RTC been programmed? */
ret = tps65910_reg_read(tps65910, TPS65910_RTC_CTRL);
if (ret < 0) {
dev_err(dev, "Failed to read RTC control: %d\n", ret);
return ret;
}
rtc_ctl = ret & (~BIT_RTC_CTRL_REG_RTC_V_OPT_M);
ret = tps65910_reg_write(tps65910, TPS65910_RTC_CTRL, rtc_ctl);
if (ret < 0) {
dev_err(dev, "Failed to write RTC control: %d\n", ret);
return ret;
}
/* Read twice to make sure we don't read a corrupt, partially
* incremented, value.
*/
do {
ret = tps65910_bulk_read(tps65910, TPS65910_SECONDS,
ALL_TIME_REGS, rtc_data);
if (ret != 0)
continue;
tm->tm_sec = bcd2bin(rtc_data[0]);
tm->tm_min = bcd2bin(rtc_data[1]);
tm->tm_hour = bcd2bin(rtc_data[2]);
tm->tm_mday = bcd2bin(rtc_data[3]);
tm->tm_mon = bcd2bin(rtc_data[4]) - 1;
tm->tm_year = bcd2bin(rtc_data[5]) + 100;
tm->tm_wday = bcd2bin(rtc_data[6]);
dev_dbg(dev, "RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, tm->tm_wday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
return ret;
} while (++count < RTC_GET_TIME_RETRIES);
dev_err(dev, "Timed out reading current time\n");
return -EIO;
}
/*
* Set current time and date in RTC
*/
static int tps65910_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct tps65910_rtc *tps65910_rtc = dev_get_drvdata(dev);
struct tps65910 *tps65910 = tps65910_rtc->tps65910;
int ret;
u8 rtc_ctl;
unsigned char rtc_data[ALL_TIME_REGS + 1];
rtc_data[0] = bin2bcd(tm->tm_sec);
rtc_data[1] = bin2bcd(tm->tm_min);
rtc_data[2] = bin2bcd(tm->tm_hour);
rtc_data[3] = bin2bcd(tm->tm_mday);
rtc_data[4] = bin2bcd(tm->tm_mon + 1);
rtc_data[5] = bin2bcd(tm->tm_year - 100);
rtc_data[6] = bin2bcd(tm->tm_wday);
/*Dummy read*/
ret = tps65910_reg_read(tps65910, TPS65910_RTC_CTRL);
/* Stop RTC while updating the TC registers */
ret = tps65910_reg_read(tps65910, TPS65910_RTC_CTRL);
if (ret < 0) {
dev_err(dev, "Failed to read RTC control: %d\n", ret);
return ret;
}
rtc_ctl = ret & (~BIT_RTC_CTRL_REG_STOP_RTC_M);
ret = tps65910_reg_write(tps65910, TPS65910_RTC_CTRL, rtc_ctl);
if (ret < 0) {
dev_err(dev, "Failed to write RTC control: %d\n", ret);
return ret;
}
/* update all the time registers in one shot */
ret = tps65910_bulk_write(tps65910, TPS65910_SECONDS,
ALL_TIME_REGS, rtc_data);
if (ret < 0) {
dev_err(dev, "Failed to read RTC times: %d\n", ret);
return ret;
}
/*Dummy read*/
ret = tps65910_reg_read(tps65910, TPS65910_RTC_CTRL);
/* Start RTC again */
ret = tps65910_reg_read(tps65910, TPS65910_RTC_CTRL);
if (ret < 0) {
dev_err(dev, "Failed to read RTC control: %d\n", ret);
return ret;
}
rtc_ctl = ret | BIT_RTC_CTRL_REG_STOP_RTC_M;
ret = tps65910_reg_write(tps65910, TPS65910_RTC_CTRL, rtc_ctl);
if (ret < 0) {
dev_err(dev, "Failed to write RTC control: %d\n", ret);
return ret;
}
return 0;
}
/*
* Read alarm time and date in RTC
*/
static int tps65910_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct tps65910_rtc *tps65910_rtc = dev_get_drvdata(dev);
int ret;
unsigned char alrm_data[ALL_ALM_REGS + 1];
ret = tps65910_bulk_read(tps65910_rtc->tps65910, TPS65910_ALARM_SECONDS,
ALL_ALM_REGS, alrm_data);
if (ret != 0) {
dev_err(dev, "Failed to read alarm time: %d\n", ret);
return ret;
}
/* some of these fields may be wildcard/"match all" */
alrm->time.tm_sec = bcd2bin(alrm_data[0]);
alrm->time.tm_min = bcd2bin(alrm_data[1]);
alrm->time.tm_hour = bcd2bin(alrm_data[2]);
alrm->time.tm_mday = bcd2bin(alrm_data[3]);
alrm->time.tm_mon = bcd2bin(alrm_data[4]) - 1;
alrm->time.tm_year = bcd2bin(alrm_data[5]) + 100;
ret = tps65910_reg_read(tps65910_rtc->tps65910, TPS65910_RTC_INTERRUPTS);
if (ret < 0) {
dev_err(dev, "Failed to read RTC control: %d\n", ret);
return ret;
}
if (ret & BIT_RTC_INTERRUPTS_REG_IT_ALARM_M)
alrm->enabled = 1;
else
alrm->enabled = 0;
return 0;
}
static int tps65910_rtc_stop_alarm(struct tps65910_rtc *tps65910_rtc)
{
tps65910_rtc->alarm_enabled = 0;
return tps65910_clear_bits(tps65910_rtc->tps65910, TPS65910_RTC_INTERRUPTS,
BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
}
static int tps65910_rtc_start_alarm(struct tps65910_rtc *tps65910_rtc)
{
tps65910_rtc->alarm_enabled = 1;
return tps65910_set_bits(tps65910_rtc->tps65910, TPS65910_RTC_INTERRUPTS,
BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
}
static int tps65910_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct tps65910_rtc *tps65910_rtc = dev_get_drvdata(dev);
int ret;
unsigned char alrm_data[ALL_TIME_REGS + 1];
ret = tps65910_rtc_stop_alarm(tps65910_rtc);
if (ret < 0) {
dev_err(dev, "Failed to stop alarm: %d\n", ret);
return ret;
}
alrm_data[0] = bin2bcd(alrm->time.tm_sec);
alrm_data[1] = bin2bcd(alrm->time.tm_min);
alrm_data[2] = bin2bcd(alrm->time.tm_hour);
alrm_data[3] = bin2bcd(alrm->time.tm_mday);
alrm_data[4] = bin2bcd(alrm->time.tm_mon + 1);
alrm_data[5] = bin2bcd(alrm->time.tm_year - 100);
ret = tps65910_bulk_write(tps65910_rtc->tps65910, TPS65910_ALARM_SECONDS,
ALL_ALM_REGS, alrm_data);
if (ret != 0) {
dev_err(dev, "Failed to read alarm time: %d\n", ret);
return ret;
}
if (alrm->enabled) {
ret = tps65910_rtc_start_alarm(tps65910_rtc);
if (ret < 0) {
dev_err(dev, "Failed to start alarm: %d\n", ret);
return ret;
}
}
return 0;
}
static int tps65910_rtc_alarm_irq_enable(struct device *dev,
unsigned int enabled)
{
struct tps65910_rtc *tps65910_rtc = dev_get_drvdata(dev);
if (enabled)
return tps65910_rtc_start_alarm(tps65910_rtc);
else
return tps65910_rtc_stop_alarm(tps65910_rtc);
}
static int tps65910_rtc_update_irq_enable(struct device *dev,
unsigned int enabled)
{
struct tps65910_rtc *tps65910_rtc = dev_get_drvdata(dev);
if (enabled)
return tps65910_set_bits(tps65910_rtc->tps65910, TPS65910_RTC_INTERRUPTS,
BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
else
return tps65910_clear_bits(tps65910_rtc->tps65910, TPS65910_RTC_INTERRUPTS,
BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
}
/*
* We will just handle setting the frequency and make use the framework for
* reading the periodic interupts.
*
* @freq: Current periodic IRQ freq:
* bit 0: every second
* bit 1: every minute
* bit 2: every hour
* bit 3: every day
*/
static int tps65910_rtc_irq_set_freq(struct device *dev, int freq)
{
struct tps65910_rtc *tps65910_rtc = dev_get_drvdata(dev);
int ret;
u8 rtc_ctl;
if (freq < 0 || freq > 3)
return -EINVAL;
ret = tps65910_reg_read(tps65910_rtc->tps65910, TPS65910_RTC_INTERRUPTS);
if (ret < 0) {
dev_err(dev, "Failed to read RTC interrupt: %d\n", ret);
return ret;
}
rtc_ctl = ret | freq;
ret = tps65910_reg_write(tps65910_rtc->tps65910, TPS65910_RTC_INTERRUPTS, rtc_ctl);
if (ret < 0) {
dev_err(dev, "Failed to write RTC control: %d\n", ret);
return ret;
}
return ret;
}
static irqreturn_t tps65910_alm_irq(int irq, void *data)
{
struct tps65910_rtc *tps65910_rtc = data;
rtc_update_irq(tps65910_rtc->rtc, 1, RTC_IRQF | RTC_AF);
return IRQ_HANDLED;
}
static irqreturn_t tps65910_per_irq(int irq, void *data)
{
struct tps65910_rtc *tps65910_rtc = data;
rtc_update_irq(tps65910_rtc->rtc, 1, RTC_IRQF | RTC_UF);
//printk("%s:irq=%d\n",__func__,irq);
return IRQ_HANDLED;
}
static const struct rtc_class_ops tps65910_rtc_ops = {
.read_time = tps65910_rtc_readtime,
//.set_mmss = tps65910_rtc_set_mmss,
.set_time = tps65910_rtc_set_time,
.read_alarm = tps65910_rtc_readalarm,
.set_alarm = tps65910_rtc_setalarm,
.alarm_irq_enable = tps65910_rtc_alarm_irq_enable,
//.update_irq_enable = tps65910_rtc_update_irq_enable,
//.irq_set_freq = tps65910_rtc_irq_set_freq,
};
#ifdef CONFIG_PM
/* Turn off the alarm if it should not be a wake source. */
static int tps65910_rtc_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct tps65910_rtc *tps65910_rtc = dev_get_drvdata(&pdev->dev);
int ret;
if (tps65910_rtc->alarm_enabled && device_may_wakeup(&pdev->dev))
ret = tps65910_rtc_start_alarm(tps65910_rtc);
else
ret = tps65910_rtc_stop_alarm(tps65910_rtc);
if (ret != 0)
dev_err(&pdev->dev, "Failed to update RTC alarm: %d\n", ret);
return 0;
}
/* Enable the alarm if it should be enabled (in case it was disabled to
* prevent use as a wake source).
*/
static int tps65910_rtc_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct tps65910_rtc *tps65910_rtc = dev_get_drvdata(&pdev->dev);
int ret;
if (tps65910_rtc->alarm_enabled) {
ret = tps65910_rtc_start_alarm(tps65910_rtc);
if (ret != 0)
dev_err(&pdev->dev,
"Failed to restart RTC alarm: %d\n", ret);
}
return 0;
}
/* Unconditionally disable the alarm */
static int tps65910_rtc_freeze(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct tps65910_rtc *tps65910_rtc = dev_get_drvdata(&pdev->dev);
int ret;
ret = tps65910_rtc_stop_alarm(tps65910_rtc);
if (ret != 0)
dev_err(&pdev->dev, "Failed to stop RTC alarm: %d\n", ret);
return 0;
}
#else
#define tps65910_rtc_suspend NULL
#define tps65910_rtc_resume NULL
#define tps65910_rtc_freeze NULL
#endif
struct platform_device *g_pdev;
static int tps65910_rtc_probe(struct platform_device *pdev)
{
struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
struct tps65910_rtc *tps65910_rtc;
int per_irq;
int alm_irq;
int ret = 0;
u8 rtc_ctl;
struct rtc_time tm;
struct rtc_time tm_def = { // 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,
};
tps65910_rtc = kzalloc(sizeof(*tps65910_rtc), GFP_KERNEL);
if (tps65910_rtc == NULL)
return -ENOMEM;
platform_set_drvdata(pdev, tps65910_rtc);
tps65910_rtc->tps65910 = tps65910;
per_irq = tps65910->irq_base + TPS65910_IRQ_RTC_PERIOD;
alm_irq = tps65910->irq_base + TPS65910_IRQ_RTC_ALARM;
/* Take rtc out of reset */
ret = tps65910_reg_read(tps65910, TPS65910_DEVCTRL);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to read TPS65910_DEVCTRL: %d\n", ret);
return ret;
}
if(ret & BIT_RTC_PWDN)
{
rtc_ctl = ret & (~BIT_RTC_PWDN);
ret = tps65910_reg_write(tps65910, TPS65910_DEVCTRL, rtc_ctl);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to write RTC control: %d\n", ret);
return ret;
}
}
/*start rtc default*/
ret = tps65910_reg_read(tps65910, TPS65910_RTC_CTRL);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to read RTC control: %d\n", ret);
return ret;
}
if(!(ret & BIT_RTC_CTRL_REG_STOP_RTC_M))
{
rtc_ctl = ret | BIT_RTC_CTRL_REG_STOP_RTC_M;
ret = tps65910_reg_write(tps65910, TPS65910_RTC_CTRL, rtc_ctl);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to write RTC control: %d\n", ret);
return ret;
}
}
ret = tps65910_reg_read(tps65910, TPS65910_RTC_STATUS);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to read RTC status: %d\n", ret);
return ret;
}
/*set init time*/
ret = tps65910_rtc_readtime(&pdev->dev, &tm);
if (ret)
{
dev_err(&pdev->dev, "Failed to read RTC time\n");
return ret;
}
ret = rtc_valid_tm(&tm);
if (ret) {
dev_err(&pdev->dev,"invalid date/time and init time\n");
tps65910_rtc_set_time(&pdev->dev, &tm_def); // 2011-01-01 12:00:00
dev_info(&pdev->dev, "set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
1900 + tm_def.tm_year, tm_def.tm_mon + 1, tm_def.tm_mday, tm_def.tm_wday,
tm_def.tm_hour, tm_def.tm_min, tm_def.tm_sec);
}
device_init_wakeup(&pdev->dev, 1);
tps65910_rtc->rtc = rtc_device_register("tps65910", &pdev->dev,
&tps65910_rtc_ops, THIS_MODULE);
if (IS_ERR(tps65910_rtc->rtc)) {
ret = PTR_ERR(tps65910_rtc->rtc);
goto err;
}
/*request rtc and alarm irq of tps65910*/
ret = request_threaded_irq(per_irq, NULL, tps65910_per_irq,
IRQF_TRIGGER_RISING, "RTC period",
tps65910_rtc);
if (ret != 0) {
dev_err(&pdev->dev, "Failed to request periodic IRQ %d: %d\n",
per_irq, ret);
}
ret = request_threaded_irq(alm_irq, NULL, tps65910_alm_irq,
IRQF_TRIGGER_RISING, "RTC alarm",
tps65910_rtc);
if (ret != 0) {
dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n",
alm_irq, ret);
}
//for rtc irq test
//tps65910_set_bits(tps65910_rtc->tps65910, TPS65910_RTC_INTERRUPTS,
// BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
g_pdev = pdev;
printk("%s:ok\n",__func__);
return 0;
err:
kfree(tps65910_rtc);
return ret;
}
static int __devexit tps65910_rtc_remove(struct platform_device *pdev)
{
struct tps65910_rtc *tps65910_rtc = platform_get_drvdata(pdev);
int per_irq = tps65910_rtc->tps65910->irq_base + TPS65910_IRQ_RTC_PERIOD;
int alm_irq = tps65910_rtc->tps65910->irq_base + TPS65910_IRQ_RTC_ALARM;
free_irq(alm_irq, tps65910_rtc);
free_irq(per_irq, tps65910_rtc);
rtc_device_unregister(tps65910_rtc->rtc);
kfree(tps65910_rtc);
return 0;
}
static const struct dev_pm_ops tps65910_rtc_pm_ops = {
.suspend = tps65910_rtc_suspend,
.resume = tps65910_rtc_resume,
.freeze = tps65910_rtc_freeze,
.thaw = tps65910_rtc_resume,
.restore = tps65910_rtc_resume,
.poweroff = tps65910_rtc_suspend,
};
static struct platform_driver tps65910_rtc_driver = {
.probe = tps65910_rtc_probe,
.remove = __devexit_p(tps65910_rtc_remove),
.driver = {
.name = "tps65910-rtc",
.pm = &tps65910_rtc_pm_ops,
},
};
static ssize_t rtc_tps65910_test_write(struct file *file,
const char __user *buf, size_t count, loff_t *offset)
{
char nr_buf[8];
int nr = 0, ret;
struct platform_device *pdev;
struct rtc_time tm;
if(count > 3)
return -EFAULT;
ret = copy_from_user(nr_buf, buf, count);
if(ret < 0)
return -EFAULT;
sscanf(nr_buf, "%d", &nr);
if(nr >= 2 || nr < 0)
{
printk("%s:data is error\n",__func__);
return -EFAULT;
}
if(!g_pdev)
return -EFAULT;
else
pdev = g_pdev;
if(nr == 0)
{
tm.tm_wday = 6;
tm.tm_year = 111;
tm.tm_mon = 0;
tm.tm_mday = 1;
tm.tm_hour = 12;
tm.tm_min = 0;
tm.tm_sec = 0;
ret = tps65910_rtc_set_time(&pdev->dev, &tm); // 2011-01-01 12:00:00
if (ret)
{
dev_err(&pdev->dev, "Failed to set RTC time\n");
return -EFAULT;
}
}
/*set init time*/
ret = tps65910_rtc_readtime(&pdev->dev, &tm);
if (ret)
dev_err(&pdev->dev, "Failed to read RTC time\n");
else
dev_info(&pdev->dev, "RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
1900 + tm.tm_year, tm.tm_mon + 1, tm.tm_mday, tm.tm_wday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
if(!ret)
printk("%s:ok\n",__func__);
else
printk("%s:error\n",__func__);
return count;
}
static const struct file_operations rtc_tps65910_test_fops = {
.write = rtc_tps65910_test_write,
};
static struct miscdevice rtc_tps65910_test_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = "rtc_tps65910_test",
.fops = &rtc_tps65910_test_fops,
};
static int __init tps65910_rtc_init(void)
{
misc_register(&rtc_tps65910_test_misc);
return platform_driver_register(&tps65910_rtc_driver);
}
subsys_initcall_sync(tps65910_rtc_init);
static void __exit tps65910_rtc_exit(void)
{
misc_deregister(&rtc_tps65910_test_misc);
platform_driver_unregister(&tps65910_rtc_driver);
}
module_exit(tps65910_rtc_exit);
MODULE_DESCRIPTION("RTC driver for the tps65910 series PMICs");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:tps65910-rtc");

113
include/linux/mfd/tps65910.h Normal file → Executable file
View File

@ -17,6 +17,8 @@
#ifndef __LINUX_MFD_TPS65910_H
#define __LINUX_MFD_TPS65910_H
#include <linux/gpio.h>
/* TPS chip id list */
#define TPS65910 0
#define TPS65911 1
@ -25,6 +27,10 @@
#define REGULATOR_LDO 0
#define REGULATOR_DCDC 1
/* I2C Slave Address 7-bit */
#define TPS65910_I2C_ID0 0x2D /* general-purpose */
#define TPS65910_I2C_ID1 0x12 /* Smart Reflex */
/*
* List of registers for component TPS65910
*
@ -243,7 +249,8 @@
/*Registers VDD1, VDD2 voltage values definitions */
#define VDD1_2_NUM_VOLTS 73
#define VDD1_2_NUM_VOLT_FINE 73
#define VDD1_2_NUM_VOLT_COARSE 3
#define VDD1_2_MIN_VOLT 6000
#define VDD1_2_OFFSET 125
@ -269,7 +276,7 @@
#define LDO1_SEL_MASK 0xFC
#define LDO3_SEL_MASK 0x7C
#define LDO_MIN_VOLT 1000
#define LDO_MAX_VOLT 3300;
#define LDO_MAX_VOLT 3300
/*Register VDIG1 (0x80) register.RegisterDescription */
@ -361,7 +368,7 @@
#define DCDCCTRL_DCDCCKSYNC_SHIFT 0
/*Register DEVCTRL (0x80) register.RegisterDescription */
/*Register DEVCTRL (0x3F) register.RegisterDescription */
#define DEVCTRL_RTC_PWDN_MASK 0x40
#define DEVCTRL_RTC_PWDN_SHIFT 6
#define DEVCTRL_CK32K_CTRL_MASK 0x20
@ -378,7 +385,7 @@
#define DEVCTRL_DEV_OFF_SHIFT 0
/*Register DEVCTRL2 (0x80) register.RegisterDescription */
/*Register DEVCTRL2 (0x40) register.RegisterDescription */
#define DEVCTRL2_TSLOT_LENGTH_MASK 0x30
#define DEVCTRL2_TSLOT_LENGTH_SHIFT 4
#define DEVCTRL2_SLEEPSIG_POL_MASK 0x08
@ -656,6 +663,8 @@
/*Register GPIO (0x80) register.RegisterDescription */
#define GPIO_SLEEP_MASK 0x80
#define GPIO_SLEEP_SHIFT 7
#define GPIO_DEB_MASK 0x10
#define GPIO_DEB_SHIFT 4
#define GPIO_PUEN_MASK 0x08
@ -739,19 +748,50 @@
#define TPS65910_GPIO_STS BIT(1)
#define TPS65910_GPIO_SET BIT(0)
/**
* struct tps65910_board
* Board platform data may be used to initialize regulators.
*/
/* Max number of TPS65910/11 GPIOs */
#define TPS65910_NUM_GPIO 6
#define TPS65911_NUM_GPIO 9
#define TPS6591X_MAX_NUM_GPIO 9
/* Regulator Index Definitions */
#define TPS65910_REG_VRTC 0
#define TPS65910_REG_VIO 1
#define TPS65910_REG_VDD1 2
#define TPS65910_REG_VDD2 3
#define TPS65910_REG_VDD3 4
#define TPS65910_REG_VDIG1 5
#define TPS65910_REG_VDIG2 6
#define TPS65910_REG_VPLL 7
#define TPS65910_REG_VDAC 8
#define TPS65910_REG_VAUX1 9
#define TPS65910_REG_VAUX2 10
#define TPS65910_REG_VAUX33 11
#define TPS65910_REG_VMMC 12
#define TPS65911_REG_VDDCTRL 4
#define TPS65911_REG_LDO1 5
#define TPS65911_REG_LDO2 6
#define TPS65911_REG_LDO3 7
#define TPS65911_REG_LDO4 8
#define TPS65911_REG_LDO5 9
#define TPS65911_REG_LDO6 10
#define TPS65911_REG_LDO7 11
#define TPS65911_REG_LDO8 12
/* Max number of TPS65910/11 regulators */
#define TPS65910_NUM_REGS 13
/* External sleep controls through EN1/EN2/EN3/SLEEP inputs */
#define TPS65910_SLEEP_CONTROL_EXT_INPUT_EN1 0x1
#define TPS65910_SLEEP_CONTROL_EXT_INPUT_EN2 0x2
#define TPS65910_SLEEP_CONTROL_EXT_INPUT_EN3 0x4
#define TPS65911_SLEEP_CONTROL_EXT_INPUT_SLEEP 0x8
struct tps65910_board {
int gpio_base;
int irq;
int irq_base;
int vmbch_threshold;
int vmbch2_threshold;
struct regulator_init_data *tps65910_pmic_init_data;
};
/**
* struct tps65910 - tps65910 sub-driver chip access routines
@ -760,15 +800,16 @@ struct tps65910_board {
struct tps65910 {
struct device *dev;
struct i2c_client *i2c_client;
struct regmap *regmap;
struct mutex io_mutex;
unsigned int id;
int (*read)(struct tps65910 *tps65910, u8 reg, int size, void *dest);
int (*write)(struct tps65910 *tps65910, u8 reg, int size, void *src);
/* Client devices */
struct tps65910_pmic *pmic;
struct tps65910_rtc *rtc;
struct tps65910_power *power;
//struct tps65910_pmic *pmic;
//struct tps65910_rtc *rtc;
//struct tps65910_power *power;
/* GPIO Handling */
struct gpio_chip gpio;
@ -786,11 +827,45 @@ struct tps65910_platform_data {
int irq_base;
};
/**
* struct tps65910_board
* Board platform data may be used to initialize regulators.
*/
struct tps65910_board {
int gpio_base;
int irq;
int irq_base;
int vmbch_threshold;
int vmbch2_threshold;
bool en_gpio_sleep[TPS6591X_MAX_NUM_GPIO];
unsigned long regulator_ext_sleep_control[TPS65910_NUM_REGS];
struct regulator_init_data *tps65910_pmic_init_data[TPS65910_NUM_REGS];
/** Called before subdevices are set up */
int (*pre_init)(struct tps65910 *tps65910);
/** Called after subdevices are set up */
int (*post_init)(struct tps65910 *tps65910);
/** Called before subdevices are power down */
int (*last_deinit)(struct tps65910 *tps65910);
};
int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask);
int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask);
void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base);
int tps65910_irq_init(struct tps65910 *tps65910, int irq,
struct tps65910_platform_data *pdata);
int tps65910_irq_exit(struct tps65910 *tps65910);
int tps65910_reg_read(struct tps65910 *tps65910, u8 reg);
int tps65910_reg_write(struct tps65910 *tps65910, u8 reg, u8 val);
int tps65910_bulk_read(struct tps65910 *tps65910, u8 reg,
int count, u8 *buf);
int tps65910_bulk_write(struct tps65910 *tps65910, u8 reg,
int count, u8 *buf);
int tps65910_device_shutdown(void);
static inline int tps65910_chip_id(struct tps65910 *tps65910)
{