From e592356dbbf6b403b4389d0ec2e1c4d4048b5fa6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E5=BC=A0=E6=99=B4?= Date: Wed, 15 Aug 2012 17:20:59 +0800 Subject: [PATCH] rk2928:sdk:support pwm set voltage --- .../mach-rk2928/board-rk2928-sdk-tps65910.c | 13 +- arch/arm/mach-rk2928/board-rk2928-sdk.c | 64 ++++++- drivers/regulator/rk30-pwm-regulator.c | 161 ++++++++++++++---- include/linux/regulator/rk29-pwm-regulator.h | 5 + 4 files changed, 200 insertions(+), 43 deletions(-) mode change 100644 => 100755 include/linux/regulator/rk29-pwm-regulator.h diff --git a/arch/arm/mach-rk2928/board-rk2928-sdk-tps65910.c b/arch/arm/mach-rk2928/board-rk2928-sdk-tps65910.c index 51cf60dc2029..4b8d6058d3ee 100755 --- a/arch/arm/mach-rk2928/board-rk2928-sdk-tps65910.c +++ b/arch/arm/mach-rk2928/board-rk2928-sdk-tps65910.c @@ -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; diff --git a/arch/arm/mach-rk2928/board-rk2928-sdk.c b/arch/arm/mach-rk2928/board-rk2928-sdk.c index fb48103c0245..57eef7b606de 100755 --- a/arch/arm/mach-rk2928/board-rk2928-sdk.c +++ b/arch/arm/mach-rk2928/board-rk2928-sdk.c @@ -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)); diff --git a/drivers/regulator/rk30-pwm-regulator.c b/drivers/regulator/rk30-pwm-regulator.c index 7a89527b0b06..ce7aee35eee5 100755 --- a/drivers/regulator/rk30-pwm-regulator.c +++ b/drivers/regulator/rk30-pwm-regulator.c @@ -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 , ÆäÖÐDΪPWMÕ¼¿Õ±È, - pwm_value = (1325000-vol)/5800; // pwm_value % - + // VDD12 = 1.40 - 0.455*D , ÆäÖÐDΪPWMÕ¼¿Õ±È, + 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); diff --git a/include/linux/regulator/rk29-pwm-regulator.h b/include/linux/regulator/rk29-pwm-regulator.h old mode 100644 new mode 100755 index e0a0487d2a85..e74b812f73d3 --- a/include/linux/regulator/rk29-pwm-regulator.h +++ b/include/linux/regulator/rk29-pwm-regulator.h @@ -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; }; -- 2.34.1