rk30_phone:set VDD_ARM and VDD_LOG of discrete dcdc
authorlw@rock-chips.com <lw@rock-chips.com>
Thu, 19 Apr 2012 10:05:18 +0000 (18:05 +0800)
committerlw <lw@rock-chips.com>
Thu, 19 Apr 2012 10:05:48 +0000 (18:05 +0800)
arch/arm/mach-rk30/board-rk30-phone-wm831x.c
drivers/regulator/rk30-pwm-regulator.c [new file with mode: 0755]

index 20f4e7b68a2b4592d7d4abeda11fade14dc91f69..199ea78c644c75e6a8f026216f0ec64346892d94 100755 (executable)
@@ -216,14 +216,14 @@ int wm831x_post_init(struct wm831x *Wm831x)
 //discrete dcdc device
 #ifdef CONFIG_RK30_PWM_REGULATOR
        dcdc = regulator_get(NULL, "vdd_core"); // vdd_log
-       regulator_set_voltage(dcdc, 1200000, 1200000);
+       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);
 
        dcdc = regulator_get(NULL, "vdd_cpu");  // vdd_arm
-       regulator_set_voltage(dcdc, 1200000, 1200000);
+       regulator_set_voltage(dcdc, 1100000, 1100000);
        regulator_enable(dcdc);
        printk("%s set vdd_cpu=%dmV end\n", __func__, regulator_get_voltage(dcdc));
        regulator_put(dcdc);
diff --git a/drivers/regulator/rk30-pwm-regulator.c b/drivers/regulator/rk30-pwm-regulator.c
new file mode 100755 (executable)
index 0000000..2a7439d
--- /dev/null
@@ -0,0 +1,353 @@
+/* drivers/regulator/rk29-pwm-regulator.c\r
+ *\r
+ * Copyright (C) 2010 ROCKCHIP, Inc.\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+/*******************************************************************/\r
+/*       COPYRIGHT (C)  ROCK-CHIPS FUZHOU . ALL RIGHTS RESERVED.                         */\r
+/*******************************************************************\r
+FILE           :               rk29-pwm-regulator.c\r
+DESC           :       rk29 pwm regulator driver\r
+AUTHOR         :       hxy\r
+DATE           :       2010-12-20\r
+NOTES          :\r
+$LOG: GPIO.C,V $\r
+REVISION 0.01\r
+********************************************************************/\r
+#include <linux/bug.h>\r
+#include <linux/err.h>\r
+#include <linux/platform_device.h>\r
+#include <linux/kernel.h>\r
+#include <linux/clk.h>\r
+#include <asm/io.h>\r
+#include <linux/delay.h>\r
+#include <linux/slab.h>\r
+#include <linux/regulator/driver.h>\r
+#include <linux/regulator/rk29-pwm-regulator.h>\r
+#include <mach/iomux.h>\r
+#include <linux/gpio.h>\r
+#include <mach/board.h>\r
+\r
+\r
+#if 1\r
+#define DBG(x...)      printk(KERN_INFO x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+\r
+#define        PWM_VCORE_120           40\r
+#define PWM_VCORE_125          32\r
+#define        PWM_VCORE_130           21\r
+#define        PWM_VCORE_135           10\r
+#define        PWM_VCORE_140           0\r
+\r
+#define PWM_DCDC_MAX_NAME      2\r
+struct rk_pwm_dcdc {\r
+        char name[PWM_DCDC_MAX_NAME];\r
+        struct regulator_desc desc;\r
+        int pwm_id;\r
+        struct regulator_dev *regulator;\r
+               struct pwm_platform_data *pdata;\r
+};\r
+\r
+\r
+#if defined(CONFIG_ARCH_RK30)\r
+#define pwm_write_reg(id, addr, val)        __raw_writel(val, addr+(RK30_PWM01_BASE+(id>>1)*0x20000)+id*0x10)\r
+#define pwm_read_reg(id, addr)              __raw_readl(addr+(RK30_PWM01_BASE+(id>>1)*0x20000+id*0x10))\r
+#elif defined(CONFIG_ARCH_RK29)\r
+#define pwm_write_reg(id, addr, val)        __raw_writel(val, addr+(RK29_PWM_BASE+id*0x10))\r
+#define pwm_read_reg(id, addr)              __raw_readl(addr+(RK29_PWM_BASE+id*0x10))    \r
+#endif\r
+\r
+const static int pwm_voltage_map[] = {\r
+       950000, 975000, 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, 1420000\r
+};\r
+\r
+static struct clk *pwm_clk[2];\r
+\r
+static int pwm_set_rate(struct pwm_platform_data *pdata,int nHz,u32 rate)\r
+{\r
+       u32 divh,divTotal;\r
+       int id = pdata->pwm_id;\r
+       unsigned long clkrate;\r
+       \r
+       if ( id >3 || id <0 )\r
+       {\r
+               printk("%s:pwm id error,id=%d\n",__func__,id);\r
+               return -1;\r
+       }\r
+\r
+       if((id==0) || (id == 1))\r
+       clkrate = clk_get_rate(pwm_clk[0]);\r
+       else    \r
+       clkrate = clk_get_rate(pwm_clk[1]);\r
+       \r
+       DBG("%s:id=%d,rate=%d,clkrate=%d\n",__func__,id,rate,clkrate);\r
+       \r
+       if(rate == 0)\r
+       {\r
+               // iomux pwm to gpio\r
+               rk29_mux_api_set(pdata->pwm_iomux_name, pdata->pwm_iomux_gpio);\r
+               //disable pull up or down\r
+               gpio_pull_updown(pdata->pwm_gpio,PullDisable);\r
+               // set gpio to low level\r
+               gpio_set_value(pdata->pwm_gpio,GPIO_LOW);\r
+       }\r
+       else if (rate <= 100)\r
+       {\r
+               // iomux pwm\r
+               rk29_mux_api_set(pdata->pwm_iomux_name, pdata->pwm_iomux_pwm);\r
+\r
+               pwm_write_reg(id,PWM_REG_CTRL, PWM_DIV|PWM_RESET);\r
+               divh = clkrate / nHz;\r
+               divh = divh >> (1+(PWM_DIV>>9));\r
+               pwm_write_reg(id,PWM_REG_LRC,(divh == 0)?1:divh);\r
+\r
+               divTotal =pwm_read_reg(id,PWM_REG_LRC);\r
+               divh = divTotal*rate/100;\r
+               pwm_write_reg(id, PWM_REG_HRC, divh?divh:1);\r
+               pwm_write_reg(id,PWM_REG_CNTR,0);\r
+               pwm_write_reg(id, PWM_REG_CTRL,pwm_read_reg(id,PWM_REG_CTRL)|PWM_DIV|PWM_ENABLE|PWM_TimeEN);\r
+       }\r
+       else\r
+       {\r
+               printk("%s:rate error\n",__func__);\r
+               return -1;\r
+       }\r
+\r
+       usleep_range(10*1000, 10*1000);\r
+\r
+       return (0);\r
+}\r
+\r
+static int pwm_regulator_list_voltage(struct regulator_dev *dev,unsigned int index)\r
+{\r
+       DBG("Enter %s, index =%d\n",__FUNCTION__,index);\r
+       if (index < sizeof(pwm_voltage_map)/sizeof(int))\r
+               return pwm_voltage_map[index];\r
+       else\r
+               return -1;\r
+}\r
+\r
+static int pwm_regulator_is_enabled(struct regulator_dev *dev)\r
+{\r
+       DBG("Enter %s\n",__FUNCTION__);\r
+       return 0;\r
+}\r
+\r
+static int pwm_regulator_enable(struct regulator_dev *dev)\r
+{\r
+       DBG("Enter %s\n",__FUNCTION__);\r
+       return 0;\r
+}\r
+\r
+static int pwm_regulator_disable(struct regulator_dev *dev)\r
+{\r
+       DBG("Enter %s\n",__FUNCTION__);\r
+       return 0;\r
+}\r
+\r
+static int pwm_regulator_get_voltage(struct regulator_dev *dev)\r
+{\r
+       //struct pwm_platform_data *pdata = rdev_get_drvdata(dev);\r
+       \r
+       struct rk_pwm_dcdc *dcdc = rdev_get_drvdata(dev);\r
+\r
+       DBG("Enter %s\n",__FUNCTION__);  \r
+\r
+       return (dcdc->pdata->pwm_voltage);\r
+}\r
+\r
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38))\r
+static int pwm_regulator_set_voltage(struct regulator_dev *dev,\r
+               int min_uV, int max_uV, unsigned *selector)\r
+#else\r
+static int pwm_regulator_set_voltage(struct regulator_dev *dev,\r
+               int min_uV, int max_uV)\r
+#endif\r
+{         \r
+       struct rk_pwm_dcdc *dcdc = rdev_get_drvdata(dev);\r
+       const int *voltage_map = pwm_voltage_map;\r
+\r
+       int min_mV = min_uV, max_mA = max_uV;\r
+\r
+       u32 size = sizeof(pwm_voltage_map)/sizeof(int), i, vol,pwm_value;\r
+\r
+       DBG("%s:  min_uV = %d, max_uV = %d\n",__FUNCTION__, min_uV,max_uV);\r
+\r
+       if (min_mV < voltage_map[0] ||max_mA > voltage_map[size-1])\r
+       {\r
+               printk("%s:voltage is out of table\n",__func__);\r
+               return -EINVAL;\r
+       }\r
+\r
+       for (i = 0; i < size; i++)\r
+       {\r
+               if (voltage_map[i] >= min_mV)\r
+                       break;\r
+       }\r
+\r
+\r
+       vol =  voltage_map[i];\r
+\r
+       dcdc->pdata->pwm_voltage = vol;\r
+\r
+       // VDD12 = 1.42 - 0.56*D , ÆäÖÐDΪPWMÕ¼¿Õ±È, \r
+       pwm_value = (1420000-vol)/5600;  // pwm_value %\r
+\r
+\r
+       if (pwm_set_rate(dcdc->pdata,1000*1000,pwm_value)!=0)\r
+       {\r
+               printk("%s:fail to set pwm rate,pwm_value=%d\n",__func__,pwm_value);\r
+               return -1;\r
+\r
+       }\r
+\r
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38))\r
+       *selector = i;\r
+#endif\r
+\r
+       DBG("%s:  set successful,pwm_value=%d\n",__FUNCTION__,pwm_value);\r
+\r
+       return 0;\r
+\r
+}\r
+\r
+static struct regulator_ops pwm_voltage_ops = {\r
+       .list_voltage   = pwm_regulator_list_voltage,\r
+       .set_voltage    =pwm_regulator_set_voltage,\r
+       .get_voltage    = pwm_regulator_get_voltage,\r
+       .enable         = pwm_regulator_enable,\r
+       .disable        = pwm_regulator_disable,\r
+       .is_enabled     = pwm_regulator_is_enabled,\r
+};\r
+\r
+static struct regulator_desc pwm_regulator= {\r
+       .name = "pwm-regulator",\r
+       .ops = &pwm_voltage_ops,\r
+       .type = REGULATOR_VOLTAGE,\r
+};\r
+\r
+static int __devinit pwm_regulator_probe(struct platform_device *pdev)\r
+{\r
+       struct pwm_platform_data *pdata = pdev->dev.platform_data;\r
+       struct rk_pwm_dcdc *dcdc;\r
+       int pwm_id  =  pdata->pwm_id;\r
+       struct regulator_dev *rdev;\r
+       int id = pdev->id;\r
+       int ret ;\r
+    char gpio_name[20];\r
+\r
+       if (!pdata)\r
+               return -ENODEV;\r
+\r
+       if (!pdata->pwm_voltage)\r
+               pdata->pwm_voltage = 1200000;   // default 1.2v\r
+\r
+       dcdc = kzalloc(sizeof(struct rk_pwm_dcdc), GFP_KERNEL);\r
+       if (dcdc == NULL) {
+               dev_err(&pdev->dev, "Unable to allocate private data\n");
+               return -ENOMEM;
+       }\r
+\r
+       snprintf(dcdc->name, sizeof(dcdc->name), "PWM_DCDC%d", id + 1);\r
+       dcdc->desc.name = dcdc->name;
+       dcdc->desc.id = id;
+       dcdc->desc.type = REGULATOR_VOLTAGE;
+       dcdc->desc.n_voltages = 50;\r
+       dcdc->desc.ops = &pwm_voltage_ops;\r
+       dcdc->desc.owner = THIS_MODULE;\r
+       dcdc->pdata = pdata;\r
+\r
+       dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev,\r
+                                            pdata->init_data, dcdc);\r
+       if (IS_ERR(dcdc->regulator)) {
+               ret = PTR_ERR(dcdc->regulator);
+               dev_err(&pdev->dev, "Failed to register PWM_DCDC%d: %d\n",\r
+                       id + 1, ret);
+               goto err;
+       }\r
+\r
+       snprintf(gpio_name, sizeof(gpio_name), "PWM_DCDC%d", id + 1);\r
+       ret = gpio_request(pdata->pwm_gpio,gpio_name);\r
+       if (ret) {\r
+               dev_err(&pdev->dev,"failed to request pwm gpio\n");\r
+               goto err_gpio;\r
+       }\r
+       \r
+#if defined(CONFIG_ARCH_RK29)\r
+               pwm_clk[0] = clk_get(NULL, "pwm");\r
+#elif defined(CONFIG_ARCH_RK30)\r
+               if (pwm_id == 0 || pwm_id == 1)\r
+               {\r
+                       pwm_clk[0] = clk_get(NULL, "pwm01");    \r
+                       clk_enable(pwm_clk[0]);\r
+               }\r
+               else if (pwm_id== 2 || pwm_id == 3)\r
+               {\r
+                       pwm_clk[1] = clk_get(NULL, "pwm23");            \r
+                       clk_enable(pwm_clk[1]);\r
+               }\r
+#endif\r
+\r
+\r
+       platform_set_drvdata(pdev, dcdc);\r
+       printk(KERN_INFO "pwm_regulator.%d: driver initialized\n",id);\r
+\r
+       return 0;\r
+\r
+\r
+err_gpio:\r
+       gpio_free(pdata->pwm_gpio);\r
+err:\r
+       printk("%s:error\n",__func__);\r
+       return ret;\r
+\r
+}\r
+static int __devexit pwm_regulator_remove(struct platform_device *pdev)\r
+{\r
+       struct pwm_platform_data *pdata = pdev->dev.platform_data;\r
+       struct regulator_dev *rdev = platform_get_drvdata(pdev);\r
+\r
+       regulator_unregister(rdev);\r
+       gpio_free(pdata->pwm_gpio);\r
+\r
+       return 0;\r
+}\r
+\r
+static struct platform_driver pwm_regulator_driver = {\r
+       .driver = {\r
+               .name = "pwm-voltage-regulator",\r
+       },\r
+       .remove = __devexit_p(pwm_regulator_remove),\r
+};\r
+\r
+\r
+static int __init pwm_regulator_module_init(void)\r
+{\r
+       return platform_driver_probe(&pwm_regulator_driver, pwm_regulator_probe);\r
+}\r
+\r
+static void __exit pwm_regulator_module_exit(void)\r
+{\r
+       platform_driver_unregister(&pwm_regulator_driver);\r
+}\r
+\r
+\r
+subsys_initcall(pwm_regulator_module_init);\r
+\r
+module_exit(pwm_regulator_module_exit);\r
+\r
+MODULE_LICENSE("GPL");\r
+MODULE_AUTHOR("hxy <hxy@rock-chips.com>");\r
+MODULE_DESCRIPTION("k29 pwm change driver");\r