mirror of
https://github.com/torvalds/linux.git
synced 2026-06-08 14:42:37 +02:00
rk2928:support pmic tps65910
This commit is contained in:
parent
0a75238e77
commit
426997197d
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
633
arch/arm/mach-rk2928/board-rk30-sdk-tps65910.c
Executable file
633
arch/arm/mach-rk2928/board-rk30-sdk-tps65910.c
Executable 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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
118
drivers/gpio/gpio-tps65910.c
Executable 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
0
drivers/gpio/tps65910-gpio.c
Normal file → Executable 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
|
||||
|
|
|
|||
|
|
@ -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
30
drivers/mfd/tps65910-irq.c
Normal file → Executable 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, ®);
|
||||
irq_sts = reg;
|
||||
tps65910->read(tps65910, TPS65910_INT_STS2, 1, ®);
|
||||
|
|
@ -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, ®);
|
||||
tps65910->write(tps65910, TPS65910_INT_STS, 1, ®);
|
||||
tps65910->read(tps65910, TPS65910_INT_STS2, 1, ®);
|
||||
tps65910->write(tps65910, TPS65910_INT_STS2, 1, ®);
|
||||
tps65910->read(tps65910, TPS65910_INT_STS3, 1, ®);
|
||||
tps65910->write(tps65910, TPS65910_INT_STS3, 1, ®);
|
||||
|
||||
/* 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
168
drivers/mfd/tps65910.c
Normal file → Executable 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 = ®
|
||||
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
0
drivers/mfd/tps65911-comparator.c
Normal file → Executable 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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
592
drivers/regulator/tps65910-regulator.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
695
drivers/rtc/rtc-tps65910.c
Executable 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
113
include/linux/mfd/tps65910.h
Normal file → Executable 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)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user