rk2928:sdk:support pwm set voltage

This commit is contained in:
张晴
2012-08-15 17:20:59 +08:00
parent 32eb239e65
commit e592356dbb
4 changed files with 200 additions and 43 deletions

View File

@@ -237,6 +237,10 @@ int tps65910_post_init(struct tps65910 *tps65910)
struct regulator *dcdc;
struct regulator *ldo;
printk("%s,line=%d\n", __func__,__LINE__);
#ifdef CONFIG_RK30_PWM_REGULATOR
platform_device_register(&pwm_regulator_device[0]);
#endif
dcdc = regulator_get(NULL, "vio"); //vcc_io
regulator_set_voltage(dcdc, 3300000, 3300000);
@@ -315,15 +319,6 @@ int tps65910_post_init(struct tps65910 *tps65910)
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;

View File

@@ -379,6 +379,59 @@ static struct platform_device device_ion = {
};
#endif
#if CONFIG_RK30_PWM_REGULATOR
const static int pwm_voltage_map[] = {
1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, 1400000
};
static struct regulator_consumer_supply pwm_dcdc1_consumers[] = {
{
.supply = "vdd_core",
}
};
struct regulator_init_data pwm_regulator_init_dcdc[1] =
{
{
.constraints = {
.name = "PWM_DCDC1",
.min_uV = 600000,
.max_uV = 1800000, //0.6-1.8V
.apply_uV = true,
.valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE,
},
.num_consumer_supplies = ARRAY_SIZE(pwm_dcdc1_consumers),
.consumer_supplies = pwm_dcdc1_consumers,
},
};
static struct pwm_platform_data pwm_regulator_info[1] = {
{
.pwm_id = 2,
.pwm_gpio = RK2928_PIN0_PD4,
.pwm_iomux_name = GPIO0D4_PWM_2_NAME,
.pwm_iomux_pwm = GPIO0D_PWM_2,
.pwm_iomux_gpio = GPIO0D_GPIO0D4,
.pwm_voltage = 1200000,
.suspend_voltage = 1050000,
.min_uV = 1000000,
.max_uV = 1400000,
.coefficient = 455, //45.5%
.pwm_voltage_map = pwm_voltage_map,
.init_data = &pwm_regulator_init_dcdc[0],
},
};
struct platform_device pwm_regulator_device[1] = {
{
.name = "pwm-voltage-regulator",
.id = 0,
.dev = {
.platform_data = &pwm_regulator_info[0],
}
},
};
#endif
/**************************************************************************************************
* SDMMC devices, include the module of SD,MMC,and sdio.noted by xbw at 2012-03-05
**************************************************************************************************/
@@ -717,10 +770,15 @@ static void __init rk30_i2c_register_board_info(void)
//end of i2c
#define POWER_ON_PIN RK2928_PIN3_PC5 //power_hold
static void rk30_pm_power_off(void)
static void rk2928_pm_power_off(void)
{
printk(KERN_ERR "rk30_pm_power_off start...\n");
printk(KERN_ERR "rk2928_pm_power_off start...\n");
#if defined(CONFIG_MFD_TPS65910)
tps65910_device_shutdown();//tps65910 shutdown
#endif
gpio_direction_output(POWER_ON_PIN, GPIO_LOW);
};
static void __init rk2928_board_init(void)
@@ -729,7 +787,7 @@ static void __init rk2928_board_init(void)
gpio_direction_output(POWER_ON_PIN, GPIO_HIGH);
gpio_free(POWER_ON_PIN);
pm_power_off = rk30_pm_power_off;
pm_power_off = rk2928_pm_power_off;
rk30_i2c_register_board_info();
spi_register_board_info(board_spi_devices, ARRAY_SIZE(board_spi_devices));

View File

@@ -66,34 +66,37 @@ struct rk_pwm_dcdc {
#define pwm_read_reg(id, addr) __raw_readl(addr+(RK30_PWM01_BASE+(id>>1)*0x20000+id*0x10))
#elif defined(CONFIG_ARCH_RK29)
#define pwm_write_reg(id, addr, val) __raw_writel(val, addr+(RK29_PWM_BASE+id*0x10))
#define pwm_read_reg(id, addr) __raw_readl(addr+(RK29_PWM_BASE+id*0x10))
#define pwm_read_reg(id, addr) __raw_readl(addr+(RK29_PWM_BASE+id*0x10))
#elif defined(CONFIG_ARCH_RK2928)
#define pwm_write_reg(id, addr, val) __raw_writel(val, addr+(RK2928_PWM_BASE+id*0x10))
#define pwm_read_reg(id, addr) __raw_readl(addr+(RK2928_PWM_BASE+id*0x10))
#endif
const static int pwm_voltage_map[] = {
850000,875000,900000,925000,950000, 975000, 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000, 1325000
1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, 1400000
};
static struct clk *pwm_clk[2];
static struct rk_pwm_dcdc *g_dcdc;
static int pwm_set_rate(struct pwm_platform_data *pdata,int nHz,u32 rate)
{
u32 divh,divTotal;
int id = pdata->pwm_id;
unsigned long clkrate;
if ( id >3 || id <0 )
/*
if ( id >2 || id <0 )
{
printk("%s:pwm id error,id=%d\n",__func__,id);
return -1;
}
if((id==0) || (id == 1))
*/
clkrate = clk_get_rate(pwm_clk[0]);
else
clkrate = clk_get_rate(pwm_clk[1]);
DBG("%s:id=%d,rate=%d,clkrate=%d\n",__func__,id,rate,clkrate);
DBG("%s:id=%d,rate=%d,clkrate=%d\n",__func__,id,rate,clkrate);
if(rate == 0)
{
// iomux pwm to gpio
@@ -101,9 +104,9 @@ static int pwm_set_rate(struct pwm_platform_data *pdata,int nHz,u32 rate)
//disable pull up or down
gpio_pull_updown(pdata->pwm_gpio,PullDisable);
// set gpio to low level
gpio_set_value(pdata->pwm_gpio,GPIO_LOW);
gpio_direction_output(pdata->pwm_gpio,GPIO_LOW);
}
else if (rate <= 100)
else if (rate < 100)
{
// iomux pwm
rk29_mux_api_set(pdata->pwm_iomux_name, pdata->pwm_iomux_pwm);
@@ -119,6 +122,16 @@ static int pwm_set_rate(struct pwm_platform_data *pdata,int nHz,u32 rate)
pwm_write_reg(id,PWM_REG_CNTR,0);
pwm_write_reg(id, PWM_REG_CTRL,pwm_read_reg(id,PWM_REG_CTRL)|PWM_DIV|PWM_ENABLE|PWM_TimeEN);
}
else if (rate == 100)
{
// iomux pwm to gpio
rk29_mux_api_set(pdata->pwm_iomux_name, pdata->pwm_iomux_gpio);
//disable pull up or down
gpio_pull_updown(pdata->pwm_gpio,PullDisable);
// set gpio to low level
gpio_direction_output(pdata->pwm_gpio,GPIO_HIGH);
}
else
{
printk("%s:rate error\n",__func__);
@@ -132,8 +145,9 @@ static int pwm_set_rate(struct pwm_platform_data *pdata,int nHz,u32 rate)
static int pwm_regulator_list_voltage(struct regulator_dev *dev,unsigned int index)
{
if (index < sizeof(pwm_voltage_map)/sizeof(int))
return pwm_voltage_map[index];
struct rk_pwm_dcdc *dcdc = rdev_get_drvdata(dev);
if (index < dcdc->desc.n_voltages)
return dcdc->pdata->pwm_voltage_map[index];
else
return -1;
}
@@ -176,15 +190,14 @@ static int pwm_regulator_set_voltage(struct regulator_dev *dev,
#endif
{
struct rk_pwm_dcdc *dcdc = rdev_get_drvdata(dev);
const int *voltage_map = pwm_voltage_map;
int min_mV = min_uV, max_mA = max_uV;
u32 size = sizeof(pwm_voltage_map)/sizeof(int), i, vol,pwm_value;
const int *voltage_map = dcdc->pdata->pwm_voltage_map;
int max = dcdc->pdata->max_uV;
int coefficient = dcdc->pdata->coefficient;
u32 size = dcdc->desc.n_voltages, i, vol,pwm_value;
DBG("%s: min_uV = %d, max_uV = %d\n",__FUNCTION__, min_uV,max_uV);
if (min_mV < voltage_map[0] ||max_mA > voltage_map[size-1])
if (min_uV < voltage_map[0] ||max_uV > voltage_map[size-1])
{
printk("%s:voltage is out of table\n",__func__);
return -EINVAL;
@@ -192,7 +205,7 @@ static int pwm_regulator_set_voltage(struct regulator_dev *dev,
for (i = 0; i < size; i++)
{
if (voltage_map[i] >= min_mV)
if (voltage_map[i] >= min_uV)
break;
}
@@ -201,9 +214,8 @@ static int pwm_regulator_set_voltage(struct regulator_dev *dev,
dcdc->pdata->pwm_voltage = vol;
// VDD12 = 1.42 - 0.56*D , <20><><EFBFBD><EFBFBD>DΪPWMռ<4D>ձ<EFBFBD>,
pwm_value = (1325000-vol)/5800; // pwm_value %
// VDD12 = 1.40 - 0.455*D , <20><><EFBFBD><EFBFBD>DΪPWMռ<4D>ձ<EFBFBD>,
pwm_value = (max-vol)/coefficient/10; // pwm_value %, coefficient *1000
if (pwm_set_rate(dcdc->pdata,1000*1000,pwm_value)!=0)
{
@@ -242,7 +254,6 @@ static int __devinit pwm_regulator_probe(struct platform_device *pdev)
struct pwm_platform_data *pdata = pdev->dev.platform_data;
struct rk_pwm_dcdc *dcdc;
int pwm_id = pdata->pwm_id;
struct regulator_dev *rdev;
int id = pdev->id;
int ret ;
char gpio_name[20];
@@ -251,8 +262,23 @@ static int __devinit pwm_regulator_probe(struct platform_device *pdev)
return -ENODEV;
if (!pdata->pwm_voltage)
pdata->pwm_voltage = 1200000; // default 1.2v
pdata->pwm_voltage = 1100000; // default 1.1v
if(!pdata->pwm_voltage_map)
pdata->pwm_voltage_map = pwm_voltage_map;
if(!pdata->max_uV)
pdata->max_uV = 1400000;
if(!pdata->min_uV)
pdata->min_uV = 1000000;
if(pdata->suspend_voltage < pdata->min_uV)
pdata->suspend_voltage = pdata->min_uV;
if(pdata->suspend_voltage > pdata->max_uV)
pdata->suspend_voltage = pdata->max_uV;
dcdc = kzalloc(sizeof(struct rk_pwm_dcdc), GFP_KERNEL);
if (dcdc == NULL) {
dev_err(&pdev->dev, "Unable to allocate private data\n");
@@ -263,11 +289,11 @@ static int __devinit pwm_regulator_probe(struct platform_device *pdev)
dcdc->desc.name = dcdc->name;
dcdc->desc.id = id;
dcdc->desc.type = REGULATOR_VOLTAGE;
dcdc->desc.n_voltages = 50;
dcdc->desc.n_voltages = ARRAY_SIZE(pwm_voltage_map);
dcdc->desc.ops = &pwm_voltage_ops;
dcdc->desc.owner = THIS_MODULE;
dcdc->pdata = pdata;
printk("%s:n_voltages=%d\n",__func__,dcdc->desc.n_voltages);
dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev,
pdata->init_data, dcdc);
if (IS_ERR(dcdc->regulator)) {
@@ -297,10 +323,17 @@ static int __devinit pwm_regulator_probe(struct platform_device *pdev)
pwm_clk[1] = clk_get(NULL, "pwm23");
clk_enable(pwm_clk[1]);
}
#elif defined(CONFIG_ARCH_RK2928)
pwm_clk[0] = clk_get(NULL, "pwm01");
if (IS_ERR(pwm_clk[0])) {
printk("pwm_clk get error %p\n", pwm_clk[0]);
return -EINVAL;
}
clk_enable(pwm_clk[0]);
#endif
platform_set_drvdata(pdev, dcdc);
g_dcdc = dcdc;
platform_set_drvdata(pdev, dcdc);
printk(KERN_INFO "pwm_regulator.%d: driver initialized\n",id);
return 0;
@@ -314,10 +347,73 @@ err:
}
static int __sramdata g_PWM_REG_LRC = 0;
static int __sramdata g_PWM_REG_HRC = 0;
void pwm_suspend_voltage(void)
{
struct rk_pwm_dcdc *dcdc = g_dcdc;
int suspend_voltage = 0;
int pwm_id = 0;
if(!dcdc)
return;
pwm_id = dcdc->pdata->pwm_id;
suspend_voltage = dcdc->pdata->suspend_voltage;
g_PWM_REG_LRC = pwm_read_reg(pwm_id, PWM_REG_LRC);
g_PWM_REG_HRC = pwm_read_reg(pwm_id,PWM_REG_HRC);
switch(suspend_voltage)
{
case 1000000:
pwm_write_reg(pwm_id, PWM_REG_LRC, 0x25);
pwm_write_reg(pwm_id,PWM_REG_HRC,0x20); // 1 .00
break;
case 1050000:
pwm_write_reg(pwm_id, PWM_REG_LRC, 0x25);
pwm_write_reg(pwm_id,PWM_REG_HRC,0x1c); // 1 .05
break;
case 1100000:
pwm_write_reg(pwm_id, PWM_REG_LRC, 0x25);
pwm_write_reg(pwm_id,PWM_REG_HRC,0x18); // 1 .1
break;
case 1150000:
pwm_write_reg(pwm_id, PWM_REG_LRC, 0x25);
pwm_write_reg(pwm_id,PWM_REG_HRC,0x13); // 1 .15
break;
default:
pwm_write_reg(pwm_id, PWM_REG_LRC, 0x25);
pwm_write_reg(pwm_id,PWM_REG_HRC,0x20); // 1 .00
break;
}
}
void pwm_resume_voltage(void)
{
struct rk_pwm_dcdc *dcdc = g_dcdc;
int pwm_id = 0;
if(!dcdc)
return;
pwm_id = dcdc->pdata->pwm_id;
pwm_write_reg(pwm_id, PWM_REG_LRC, g_PWM_REG_LRC);
pwm_write_reg(pwm_id,PWM_REG_HRC, g_PWM_REG_HRC);
}
static int pwm_regulator_suspend(struct platform_device *pdev, pm_message_t state)
{
struct pwm_platform_data *pdata = pdev->dev.platform_data;
pwm_set_rate(pdata,1000*1000,0);//pwm clk will change to 24M after suspend
//struct rk_pwm_dcdc *dcdc = platform_get_drvdata(pdev);
//unsigned selector = 0;
//pwm_regulator_set_voltage(dcdc->regulator, 1100000, 1100000, &selector);
DBG("%s,pwm_id=%d\n",__func__,pdata->pwm_id);
return 0;
}
@@ -325,6 +421,9 @@ static int pwm_regulator_suspend(struct platform_device *pdev, pm_message_t stat
static int pwm_regulator_resume(struct platform_device *pdev)
{
struct pwm_platform_data *pdata = pdev->dev.platform_data;
//struct rk_pwm_dcdc *dcdc = platform_get_drvdata(pdev);
//unsigned selector = 0;
//pwm_regulator_set_voltage(dcdc->regulator, 1150000, 1150000, &selector);
DBG("%s,pwm_id=%d\n",__func__,pdata->pwm_id);
return 0;
}
@@ -361,7 +460,7 @@ static void __exit pwm_regulator_module_exit(void)
}
subsys_initcall(pwm_regulator_module_init);
fs_initcall(pwm_regulator_module_init);
module_exit(pwm_regulator_module_exit);

5
include/linux/regulator/rk29-pwm-regulator.h Normal file → Executable file
View File

@@ -57,6 +57,11 @@ struct pwm_platform_data {
unsigned int pwm_iomux_pwm;
int pwm_iomux_gpio;
int pwm_voltage;
int suspend_voltage;
int coefficient;
int min_uV;
int max_uV;
int *pwm_voltage_map;
struct regulator_init_data *init_data;
};