mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 12:57:06 +09:00
rk2928:sdk:support pwm set voltage
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
5
include/linux/regulator/rk29-pwm-regulator.h
Normal file → Executable 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;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user