From 19b937babeb3b393c9e70300e870027f010924cf Mon Sep 17 00:00:00 2001 From: hxy Date: Tue, 21 Dec 2010 16:53:47 +0800 Subject: [PATCH] add pwm voltage regulator --- arch/arm/mach-rk29/board-rk29sdk.c | 90 ++++-- arch/arm/mach-rk29/clock.c | 2 +- drivers/regulator/Kconfig | 4 + drivers/regulator/Makefile | 1 + drivers/regulator/rk29-pwm-regulator.c | 294 +++++++++++++++++++ include/linux/regulator/rk29-pwm-regulator.h | 64 ++++ 6 files changed, 423 insertions(+), 32 deletions(-) create mode 100644 drivers/regulator/rk29-pwm-regulator.c create mode 100644 include/linux/regulator/rk29-pwm-regulator.h diff --git a/arch/arm/mach-rk29/board-rk29sdk.c b/arch/arm/mach-rk29/board-rk29sdk.c index 75d110c50949..08d911a7225c 100755 --- a/arch/arm/mach-rk29/board-rk29sdk.c +++ b/arch/arm/mach-rk29/board-rk29sdk.c @@ -43,6 +43,8 @@ #include /* ddl@rock-chips.com : camera support */ #include +#include +#include #include #include @@ -59,7 +61,7 @@ #endif #define PMEM_GPU_SIZE SZ_64M #define PMEM_UI_SIZE SZ_32M -#define PMEM_VPU_SIZE SZ_64M +#define PMEM_VPU_SIZE SZ_32M #define PMEM_CAM_SIZE 0x00c00000 #ifdef CONFIG_VIDEO_RK29_WORK_IPP #define MEM_CAMIPP_SIZE SZ_4M @@ -328,9 +330,9 @@ int p1003_init_platform_hw(void) } gpio_pull_updown(TOUCH_INT_PIN, 1); gpio_direction_output(TOUCH_RESET_PIN, 0); - msleep(500); + mdelay(500); gpio_set_value(TOUCH_RESET_PIN,GPIO_LOW); - msleep(500); + mdelay(500); gpio_set_value(TOUCH_RESET_PIN,GPIO_HIGH); return 0; @@ -521,15 +523,6 @@ static struct i2c_board_info __initdata board_i2c1_devices[] = { .irq = RK29_PIN4_PA1, }, #endif -#if defined (CONFIG_ANX7150) - { - .type = "anx7150", - .addr = 0x39, //0x39, 0x3d - .flags = 0, - .irq = RK29_PIN1_PD7, - }, -#endif - }; #endif @@ -849,6 +842,55 @@ struct rk29_bl_info rk29_bl_info = { .io_deinit = rk29_backlight_io_deinit, }; #endif +/***************************************************************************************** +* pwm voltage regulator devices +******************************************************************************************/ +#if defined (CONFIG_RK29_PWM_REGULATOR) + +#define REGULATOR_PWM_ID 2 +#define REGULATOR_PWM_MUX_NAME GPIO2A3_SDMMC0WRITEPRT_PWM2_NAME +#define REGULATOR_PWM_MUX_MODE GPIO2L_PWM2 +#define REGULATOR_PWM_MUX_MODE_GPIO GPIO2L_GPIO2A3 +#define REGULATOR_PWM_GPIO RK29_PIN2_PA3 + +static struct regulator_consumer_supply pwm_consumers[] = { + { + .supply = "pwm-voltage", + } +}; + +static struct regulator_init_data rk29_pwm_regulator_data = { + .constraints = { + .name = "PWM2", + .min_uV = 1200000, + .max_uV = 1400000, + .apply_uV = 1, + .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE, + }, + .num_consumer_supplies = ARRAY_SIZE(pwm_consumers), + .consumer_supplies = pwm_consumers, +}; + +static struct pwm_platform_data rk29_regulator_pwm_platform_data = { + .pwm_id = REGULATOR_PWM_ID, + .pwm_gpio = REGULATOR_PWM_GPIO, + //.pwm_iomux_name[] = REGULATOR_PWM_MUX_NAME; + .pwm_iomux_name = REGULATOR_PWM_MUX_NAME, + .pwm_iomux_pwm = REGULATOR_PWM_MUX_MODE, + .pwm_iomux_gpio = REGULATOR_PWM_MUX_MODE_GPIO, + .init_data = &rk29_pwm_regulator_data, +}; + +static struct platform_device rk29_device_pwm_regulator = { + .name = "pwm-voltage-regulator", + .id = -1, + .dev = { + .platform_data = &rk29_regulator_pwm_platform_data, + }, +}; + +#endif + /***************************************************************************************** * SDMMC devices *****************************************************************************************/ @@ -1041,14 +1083,6 @@ static struct platform_device rk29sdk_wifi_device = { }; #endif - -/* bluetooth rfkill device */ -static struct platform_device rk29sdk_rfkill = { - .name = "rk29sdk_rfkill", - .id = -1, -}; - - #ifdef CONFIG_VIVANTE static struct resource resources_gpu[] = { [0] = { @@ -1143,19 +1177,18 @@ static void __init rk29_board_iomux_init(void) rk29_mux_api_set(GPIO0A7_MIIMDCLK_NAME, GPIO0L_MII_MDCLK); rk29_mux_api_set(GPIO0A6_MIIMD_NAME, GPIO0L_MII_MD); #endif + #ifdef CONFIG_RK29_PWM_REGULATOR + rk29_mux_api_set(REGULATOR_PWM_MUX_NAME,REGULATOR_PWM_MUX_MODE); + #endif } static struct platform_device *devices[] __initdata = { #ifdef CONFIG_UART1_RK29 &rk29_device_uart1, #endif -#ifdef CONFIG_UART0_RK29 - &rk29_device_uart0, -#endif -#ifdef CONFIG_UART2_RK29 - &rk29_device_uart2, +#ifdef CONFIG_RK29_PWM_REGULATOR + &rk29_device_pwm_regulator, #endif - #ifdef CONFIG_SPIM0_RK29 &rk29xx_device_spi0m, #endif @@ -1202,11 +1235,6 @@ static struct platform_device *devices[] __initdata = { #ifdef CONFIG_WIFI_CONTROL_FUNC &rk29sdk_wifi_device, #endif - -#ifdef CONFIG_BT - &rk29sdk_rfkill, -#endif - #ifdef CONFIG_MTD_NAND_RK29 &rk29_device_nand, #endif diff --git a/arch/arm/mach-rk29/clock.c b/arch/arm/mach-rk29/clock.c index 771f8215c20b..b13d61c35107 100755 --- a/arch/arm/mach-rk29/clock.c +++ b/arch/arm/mach-rk29/clock.c @@ -469,7 +469,7 @@ static int arm_pll_clk_set_rate(struct clk *clk, unsigned long rate) pt++; } - PWMInit(1 * MHZ, PWM_VCORE_135); // 1.35V + PWMInit(1 * MHZ, PWM_VCORE_130); // 1.30V /* make aclk safe & reparent to periph pll */ cru_writel((cru_readl(CRU_CLKSEL0_CON) & ~(CORE_PARENT_MASK | CORE_ACLK_MASK)) | CORE_PARENT_PERIPH_PLL | CORE_ACLK_21, CRU_CLKSEL0_CON); diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index b833192d75c2..0b93f4ad25f4 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -166,5 +166,9 @@ config RK2818_REGULATOR_LP8725 depends on I2C help Say Y to enable support for the voltage regulators pmic lp8725 on the RK2818. +config RK29_PWM_REGULATOR + tristate "rk2918 pwm voltage regulator" + help + Say Y to enable support for the voltage regulators charge on the RK2918. endif diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index c19b61747f0b..77befcd24bf3 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_REGULATOR_MC13783) += mc13783.o obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o obj-$(CONFIG_RK2818_REGULATOR_LP8725) += rk2818_lp8725.o obj-$(CONFIG_RK2818_REGULATOR_CHARGE) += charge-regulator.o +obj-$(CONFIG_RK29_PWM_REGULATOR) += rk29-pwm-regulator.o obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o diff --git a/drivers/regulator/rk29-pwm-regulator.c b/drivers/regulator/rk29-pwm-regulator.c new file mode 100644 index 000000000000..da22de577662 --- /dev/null +++ b/drivers/regulator/rk29-pwm-regulator.c @@ -0,0 +1,294 @@ +/* drivers/regulator/rk29-pwm-regulator.c + * + * Copyright (C) 2010 ROCKCHIP, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +/*******************************************************************/ +/* COPYRIGHT (C) ROCK-CHIPS FUZHOU . ALL RIGHTS RESERVED. */ +/******************************************************************* +FILE : rk29-pwm-regulator.c +DESC : rk29 pwm regulator driver +AUTHOR : hxy +DATE : 2010-12-20 +NOTES : +$LOG: GPIO.C,V $ +REVISION 0.01 +********************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#if 0 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif + + +#define PWM_VCORE_120 40 +#define PWM_VCORE_125 32 +#define PWM_VCORE_130 21 +#define PWM_VCORE_135 10 +#define PWM_VCORE_140 0 + + +#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)) + + +const static int pwm_voltage_map[] = { + 1200, 1250, 1300, 1350, 1400 +}; + +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; + struct clk *pwm_clk = clk_get(NULL, "pwm"); + + clkrate = clk_get_rate(pwm_clk); + + if ( id >3 || id <0 ) + return -1; + + if(rate == 0) + { + // iomux pwm2 to gpio2_a[3] + rk29_mux_api_set(pdata->pwm_iomux_name, pdata->pwm_iomux_gpio); + // set gpio to low level + gpio_set_value(pdata->pwm_gpio,GPIO_LOW); + + pdata->pwm_voltage = 1400; + + } + else if (rate <= 100) + { + // iomux pwm2 + rk29_mux_api_set(pdata->pwm_iomux_name, pdata->pwm_iomux_pwm); + + pwm_write_reg(id,PWM_REG_CTRL, PWM_DIV|PWM_RESET); + divh = clkrate / nHz; + divh = divh >> (1+(PWM_DIV>>9)); + pwm_write_reg(id,PWM_REG_LRC,(divh == 0)?1:divh); + + divTotal =pwm_read_reg(id,PWM_REG_LRC); + divh = divTotal*rate/100; + pwm_write_reg(id, PWM_REG_HRC, divh?divh:1); + 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); + + pdata->pwm_voltage = 1400 - 476*rate/100; + + } + else + { + return -1; + } + + msleep(50); + + + return (0); +} + +static int pwm_init(struct pwm_platform_data *pdata, int nHz, int rate) +{ + + struct clk *pwm_clk = clk_get(NULL, "pwm"); + + // pwm2 clk enable + clk_enable(pwm_clk); + + if(pwm_set_rate(pdata,nHz,rate)!=0) + return -1; + + + return 0; +} + +static int pwm_regulator_list_voltage(struct regulator_dev *dev,unsigned int index) +{ + int *pwm_voltage_table = pwm_voltage_map; + + DBG("Enter %s, index =%d\n",__FUNCTION__,index); + if (index < sizeof(pwm_voltage_map)/sizeof(int)) + return pwm_voltage_table[index]; + else + return -1; +} + +static int pwm_regulator_is_enabled(struct regulator_dev *dev) +{ + DBG("Enter %s\n",__FUNCTION__); + return 0; +} + +static int pwm_regulator_enable(struct regulator_dev *dev) +{ + DBG("Enter %s\n",__FUNCTION__); + return 0; +} + +static int pwm_regulator_disable(struct regulator_dev *dev) +{ + DBG("Enter %s\n",__FUNCTION__); + return 0; +} + +static int pwm_regulator_get_voltage(struct regulator_dev *dev) +{ + struct pwm_platform_data *pdata = rdev_get_drvdata(dev); + + DBG("Enter %s\n",__FUNCTION__); + + return (pdata->pwm_voltage*1000); +} + +static int pwm_regulator_set_voltage(struct regulator_dev *dev, + int min_uV, int max_uV) +{ + struct pwm_platform_data *pdata = rdev_get_drvdata(dev); + + const int *voltage_map = pwm_voltage_map; + + int min_mV = min_uV /1000, max_mA = max_uV / 1000; + + u32 size = sizeof(pwm_voltage_map)/sizeof(int), 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]) + return -EINVAL; + + for (i = 0; i < size; i++) + { + if (voltage_map[i] >= min_mV) + break; + } + + + vol = voltage_map[i]; + + pdata->pwm_voltage = vol; + + // VDD12 = 1.4 - 0.476*D , ÆäÖÐDΪPWMÕ¼¿Õ±È, + pwm_value = 100*(1400-vol)/476; // pwm_value % + + + if (pwm_set_rate(pdata,1000*1000,pwm_value)!=0) + return -1; + + return 0; + +} + +static struct regulator_ops pwm_voltage_ops = { + .list_voltage = pwm_regulator_list_voltage, + .set_voltage =pwm_regulator_set_voltage, + .get_voltage = pwm_regulator_get_voltage, + .enable = pwm_regulator_enable, + .disable = pwm_regulator_disable, + .is_enabled = pwm_regulator_is_enabled, +}; + +static struct regulator_desc pwm_regulator= { + .name = "pwm-regulator", + .ops = &pwm_voltage_ops, + .type = REGULATOR_VOLTAGE, +}; + +static int __devinit pwm_regulator_probe(struct platform_device *pdev) +{ + + struct pwm_platform_data *pdata = pdev->dev.platform_data; + struct regulator_dev *rdev; + int ret ; + + rdev = regulator_register(&pwm_regulator, &pdev->dev, + pdata->init_data, pdata); + if (IS_ERR(rdev)) { + dev_dbg(&pdev->dev, "couldn't register regulator\n"); + return PTR_ERR(rdev); + } + + ret = gpio_request(pdata->pwm_gpio,"pwm"); + + if (ret) { + dev_err(&pdev->dev,"failed to request pwm gpio\n"); + goto err_gpio; + } + + //pwm_init(pdata,1000*1000,PWM_VCORE_130); + + + platform_set_drvdata(pdev, rdev); + printk(KERN_INFO "pwm_regulator: driver initialized\n"); + + return 0; + + +err_gpio: + gpio_free(pdata->pwm_gpio); + + + return ret; + +} +static int __devexit pwm_regulator_remove(struct platform_device *pdev) +{ + struct pwm_platform_data *pdata = pdev->dev.platform_data; + struct regulator_dev *rdev = platform_get_drvdata(pdev); + + regulator_unregister(rdev); + gpio_free(pdata->pwm_gpio); + + return 0; +} + +static struct platform_driver pwm_regulator_driver = { + .driver = { + .name = "pwm-voltage-regulator", + }, + .remove = __devexit_p(pwm_regulator_remove), +}; + + +static int __init pwm_regulator_module_init(void) +{ + return platform_driver_probe(&pwm_regulator_driver, pwm_regulator_probe); +} + +static void __exit pwm_regulator_module_exit(void) +{ + platform_driver_unregister(&pwm_regulator_driver); +} + + +module_init(pwm_regulator_module_init); + +module_exit(pwm_regulator_module_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("hxy "); +MODULE_DESCRIPTION("k29 pwm change driver"); diff --git a/include/linux/regulator/rk29-pwm-regulator.h b/include/linux/regulator/rk29-pwm-regulator.h new file mode 100644 index 000000000000..e0a0487d2a85 --- /dev/null +++ b/include/linux/regulator/rk29-pwm-regulator.h @@ -0,0 +1,64 @@ +/* include/linux/regulator/charge-regulator.h + * + * Copyright (C) 2010 ROCKCHIP, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#ifndef __LINUX_REGULATOR_PWM_H + +#define __LINUX_REGULATOR_PWM_H + +#include + + +#define PWM_REG_CNTR 0x00 +#define PWM_REG_HRC 0x04 +#define PWM_REG_LRC 0x08 +#define PWM_REG_CTRL 0x0c + +#define PWM_DIV2 (0<<9) +#define PWM_DIV4 (1<<9) +#define PWM_DIV8 (2<<9) +#define PWM_DIV16 (3<<9) +#define PWM_DIV32 (4<<9) +#define PWM_DIV64 (5<<9) +#define PWM_DIV128 (6<<9) +#define PWM_DIV256 (7<<9) +#define PWM_DIV512 (8<<9) +#define PWM_DIV1024 (9<<9) + +#define PWM_CAPTURE (1<<8) +#define PWM_RESET (1<<7) +#define PWM_INTCLR (1<<6) +#define PWM_INTEN (1<<5) +#define PWM_SINGLE (1<<6) + +#define PWM_ENABLE (1<<3) +#define PWM_TimeEN (1) + +#define PWM_DIV PWM_DIV2 + + +struct regulator_init_data; + +struct pwm_platform_data { + int pwm_id; + int pwm_gpio; + //char pwm_iomux_name[50]; + char* pwm_iomux_name; + unsigned int pwm_iomux_pwm; + int pwm_iomux_gpio; + int pwm_voltage; + struct regulator_init_data *init_data; +}; + +#endif + -- 2.34.1