rk312x:support pwm set arm and logic voltages
author张晴 <zhangqing@rock-chips.com>
Thu, 7 Aug 2014 02:54:52 +0000 (10:54 +0800)
committer张晴 <zhangqing@rock-chips.com>
Thu, 7 Aug 2014 02:54:52 +0000 (10:54 +0800)
arch/arm/boot/dts/rk312x-sdk.dtsi
drivers/regulator/rockchip-pwm-regulator.c
include/linux/regulator/rockchip-pwm-regulator.h

index 18cc9b67c6e04e6b325fa49b53f339dbb66ecc42..e4ffe2098d69ca04052705c5e3c1b865d0eddb9f 100755 (executable)
                rockchip,remote_wakeup;
                rockchip,usb_irq_wakeup;
        };
+
+        pwm_regulator1 {
+               compatible = "rockchip_pwm_regulator";
+               pwms = <&pwm1 0 25000>;
+               rockchip,pwm_id= <1>;
+               rockchip,pwm_voltage_map= <950000 975000 1000000 1025000 1050000 1075000 1100000 1125000 1150000 1175000 1200000 1225000 1250000 1275000 1300000 1325000 1350000 1375000 1400000 1425000 1450000>;
+               rockchip,pwm_voltage= <1250000>;
+               rockchip,pwm_min_voltage= <950000>;
+               rockchip,pwm_max_voltage= <1450000>;
+               rockchip,pwm_suspend_voltage= <1250000>;
+               rockchip,pwm_coefficient= <475>;
+               status = "okay";
+               regulators {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       pwm_reg0: regulator@0 {
+                               regulator-compatible = "pwm_dcdc1";
+                               regulator-name= "vdd_arm";
+                               regulator-min-microvolt = <950000>;
+                               regulator-max-microvolt = <1450000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+               };
+       };
+
+        pwm_regulator2 {
+               compatible = "rockchip_pwm_regulator";
+               pwms = <&pwm2 0 25000>;
+               rockchip,pwm_id= <2>;
+               rockchip,pwm_voltage_map= <950000 975000 1000000 1025000 1050000 1075000 1100000 1125000 1150000 1175000 1200000 1225000 1250000 1275000 1300000 1325000 1350000 1375000 1400000 1425000 1450000>;
+               rockchip,pwm_voltage= <1200000>;
+               rockchip,pwm_min_voltage= <950000>;
+               rockchip,pwm_max_voltage= <1450000>;
+               rockchip,pwm_suspend_voltage= <1250000>;
+               rockchip,pwm_coefficient= <475>;
+               status = "okay";
+               regulators {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       pwm_reg1: regulator@1 {
+                               regulator-compatible = "pwm_dcdc2";
+                               regulator-name= "vdd_logic";
+                               regulator-min-microvolt = <950000>;
+                               regulator-max-microvolt = <1450000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+               };
+       };
+
 };
 
 &nandc {
        status = "okay";
        rk818: rk818@1c {
                reg = <0x1c>;
-               status = "okay";
+               status = "disable";
        };
 };
 &i2c2 {
index f88ec03f4e57d130b839a66e6c28f8844c5d5154..3d8fc8871488c11a8a16f2de151a76bfa2ad74ad 100755 (executable)
-/*\r
- *\r
- * Copyright (C) 2013 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
-#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/rockchip-pwm-regulator.h>\r
-#include <linux/gpio.h>\r
-#include <linux/of_gpio.h>\r
-#include <linux/module.h>\r
-#include <linux/init.h>\r
-#include <linux/err.h>\r
-#include <linux/pwm.h>\r
-\r
-#include <linux/of.h>\r
-#include <linux/of_device.h>\r
-#include <linux/regulator/of_regulator.h>\r
-#include <linux/regulator/driver.h>\r
-#include <linux/regulator/machine.h>\r
-\r
-\r
-#if 0\r
-#define DBG(x...)      printk(KERN_INFO x)\r
-#else\r
-#define DBG(x...)\r
-#endif\r
-\r
-const static int pwm_voltage_map[] = {\r
-       925000 ,950000, 975000,1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000,1375000,1400000\r
-};\r
-       \r
-static struct pwm_platform_data *g_pdata;\r
-\r
-static int pwm_set_rate(struct pwm_platform_data *pdata,u32 rate)\r
-{\r
-       int duty_cycle;\r
-       DBG("%s:id=%d,rate=%d clkrate =%d\n",__func__,pdata->pwm_id,rate,pdata->period); \r
-\r
-       duty_cycle = (rate * (pdata->period ) / 100) ;\r
-\r
-       pwm_config(pdata->pwm, duty_cycle, pdata->period);\r
-\r
-       pwm_enable(pdata->pwm);\r
-       \r
-       return (0);\r
-}\r
-\r
-static int pwm_regulator_list_voltage(struct regulator_dev *dev,unsigned int index)\r
-{\r
-       if (index <( g_pdata->pwm_vol_map_count +1))\r
-       return g_pdata->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
-       u32 vol;\r
-\r
-       DBG("Enter %s\n",__FUNCTION__);  \r
-\r
-       vol = g_pdata->pwm_voltage;\r
-\r
-       return vol;\r
-}\r
-\r
-static int pwm_regulator_set_voltage(struct regulator_dev *dev,\r
-               int min_uV, int max_uV, unsigned *selector)\r
-{         \r
-       const int *voltage_map = g_pdata->pwm_voltage_map;\r
-       int max = g_pdata->max_uV;\r
-       int coefficient = g_pdata->coefficient;\r
-       u32 size = g_pdata->pwm_vol_map_count;\r
-       u32 i, vol,pwm_value;\r
-\r
-       DBG("%s:  min_uV = %d, max_uV = %d\n",__FUNCTION__, min_uV,max_uV);\r
-\r
-       if (min_uV < voltage_map[0] ||max_uV > voltage_map[size-1])\r
-       {\r
-               printk("%s: voltage_map 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_uV)\r
-                       break;\r
-       }\r
-       vol =  voltage_map[i];\r
-       g_pdata->pwm_voltage = vol;\r
-\r
-       // VDD12 = 1.40 - 0.455*D , ÆäÖÐDΪPWMÕ¼¿Õ±È, \r
-       pwm_value = (max-vol)/coefficient/10;  // pwm_value %, coefficient *1000\r
-\r
-       if (pwm_set_rate(g_pdata,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
-       *selector = i;\r
-\r
-       DBG("%s:ok,vol=%d,pwm_value=%d %d\n",__FUNCTION__,vol,pwm_value,g_pdata->pwm_voltage);\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
-static struct regulator_desc regulators[] = {\r
-\r
-        {\r
-               .name = "PWM_DCDC1",\r
-               .id = 0,\r
-               .ops = &pwm_voltage_ops,\r
-               .n_voltages =  ARRAY_SIZE(pwm_voltage_map),\r
-               .type = REGULATOR_VOLTAGE,\r
-               .owner = THIS_MODULE,\r
-       },\r
-};\r
-\r
-#ifdef CONFIG_OF\r
-static struct of_device_id pwm_of_match[] = {\r
-       { .compatible = "rockchip_pwm_regulator"},\r
-       { },\r
-};\r
-MODULE_DEVICE_TABLE(of, pwm_of_match);\r
-\r
-static struct of_regulator_match pwm_matches[] = {\r
-       { .name = "pwm_dcdc1",  .driver_data = (void *)0  },\r
-};\r
-\r
-static struct pwm_regulator_board *pwm_regulator_parse_dt(\r
-               struct platform_device *pdev,\r
-               struct of_regulator_match **pwm_reg_matches)\r
-{\r
-       struct pwm_regulator_board *pwm_plat_data;\r
-       struct device_node *np, *regulators;\r
-       struct of_regulator_match *matches;\r
-       int idx = 0, ret, count;\r
-       struct property *prop;\r
-       int length;\r
-       const __be32 *init_vol, *max_vol,*min_vol,*suspend_vol,*coefficient,*id;\r
-       \r
-        DBG("%s,line=%d\n", __func__,__LINE__);\r
-\r
-       pwm_plat_data = devm_kzalloc(&pdev->dev, sizeof(*pwm_plat_data),\r
-                                       GFP_KERNEL);\r
-\r
-       if (!pwm_plat_data) {\r
-               dev_err(&pdev->dev, "Failure to alloc pdata for regulators.\n");\r
-               return NULL;\r
-       }\r
-\r
-       np = of_node_get(pdev->dev.of_node);\r
-       regulators = of_find_node_by_name(np, "regulators");\r
-       if (!regulators) {\r
-               dev_err(&pdev->dev, "regulator node not found\n");\r
-               return NULL;\r
-       }\r
-       count = ARRAY_SIZE(pwm_matches);\r
-       matches = pwm_matches;  \r
-       ret = of_regulator_match(&pdev->dev, regulators, matches, count);\r
-       of_node_put(regulators);\r
-       if (ret < 0) {\r
-               dev_err(&pdev->dev, "Error parsing regulator init data: %d\n",\r
-                       ret);\r
-               return NULL;\r
-       }\r
-       \r
-       pwm_plat_data ->num_regulators = count;\r
-       *pwm_reg_matches = matches;\r
-       \r
-       for (idx = 0; idx < count; idx++) {\r
-               if (!matches[idx].init_data || !matches[idx].of_node)\r
-                       continue;\r
-               pwm_plat_data->pwm_init_data[idx] =matches[idx].init_data;\r
-               pwm_plat_data->of_node[idx]=matches[idx].of_node;\r
-       }\r
-       \r
-       init_vol = of_get_property(np, "rockchip,pwm_voltage", NULL);\r
-       if (init_vol)\r
-               pwm_plat_data->pwm_init_vol = be32_to_cpu(*init_vol);\r
-       \r
-       max_vol = of_get_property(np, "rockchip,pwm_max_voltage", NULL);\r
-       if (max_vol)\r
-               pwm_plat_data->pwm_max_vol = be32_to_cpu(*max_vol);\r
-       \r
-       min_vol = of_get_property(np, "rockchip,pwm_min_voltage", NULL);\r
-       if (min_vol)\r
-               pwm_plat_data->pwm_min_vol = be32_to_cpu(*min_vol);\r
-       \r
-       suspend_vol = of_get_property(np, "rockchip,pwm_suspend_voltage", NULL);\r
-       if (suspend_vol)\r
-               pwm_plat_data->pwm_suspend_vol = be32_to_cpu(*suspend_vol);\r
-\r
-       coefficient  = of_get_property(np, "rockchip,pwm_coefficient", NULL);\r
-       if (coefficient )\r
-               pwm_plat_data->pwm_coefficient = be32_to_cpu(*coefficient );\r
-       \r
-       id  = of_get_property(np, "rockchip,pwm_id", NULL);\r
-       if (id )\r
-               pwm_plat_data->pwm_id = be32_to_cpu(*id );\r
-\r
-       prop = of_find_property(np, "rockchip,pwm_voltage_map", &length);\r
-       if (!prop)\r
-               return NULL;\r
-       pwm_plat_data->pwm_vol_map_count = length / sizeof(u32);\r
-       if (pwm_plat_data->pwm_vol_map_count > 0) {\r
-               size_t size = sizeof(*pwm_plat_data->pwm_voltage_map) * pwm_plat_data->pwm_vol_map_count;\r
-\r
-       pwm_plat_data->pwm_voltage_map = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);\r
-       if (! pwm_plat_data->pwm_voltage_map)\r
-               return NULL;\r
-       ret = of_property_read_u32_array(np, "rockchip,pwm_voltage_map",pwm_plat_data->pwm_voltage_map, pwm_plat_data->pwm_vol_map_count);\r
-       if (ret < 0)\r
-               printk("pwm voltage map not specified\n");\r
-       }\r
-       return pwm_plat_data;\r
-}\r
-#else\r
-static inline struct pwm_regulator_board *pwm_regulator_parse_dt(\r
-                       struct platform_device *pdev,\r
-                       struct of_regulator_match **pwm_reg_matches)\r
-{\r
-       return NULL;\r
-}\r
-#endif\r
-\r
-\r
-static int __init pwm_regulator_probe(struct platform_device *pdev)\r
-{\r
-       struct pwm_platform_data *pdata = pdev->dev.platform_data;\r
-       struct pwm_regulator_board *pwm_pdev;\r
-       struct of_regulator_match *pwm_reg_matches = NULL;\r
-       struct regulator_init_data *reg_data;\r
-       struct regulator_config config = { };\r
-       const char *rail_name = NULL;\r
-       struct regulator_dev *pwm_rdev;\r
-       int ret,i=0;\r
-       struct regulator *dc;\r
-\r
-       pwm_pdev = devm_kzalloc(&pdev->dev, sizeof(*pwm_pdev),\r
-                                       GFP_KERNEL);\r
-       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata),\r
-                                       GFP_KERNEL);\r
-       \r
-       if (pdev->dev.of_node)\r
-               pwm_pdev = pwm_regulator_parse_dt(pdev,&pwm_reg_matches);\r
-\r
-       if (!pwm_pdev) {\r
-               dev_err(&pdev->dev, "Platform data not found\n");\r
-               return -EINVAL;\r
-       }\r
-       \r
-       if (!pwm_pdev->pwm_init_vol)\r
-               pdata->pwm_voltage = 1100000;   // default 1.1v\r
-       else\r
-               pdata->pwm_voltage = pwm_pdev->pwm_init_vol;    \r
-\r
-       if(!pwm_pdev->pwm_max_vol)\r
-               pdata->max_uV = 1400000;\r
-       else\r
-               pdata->max_uV = pwm_pdev->pwm_max_vol;\r
-\r
-       if(!pwm_pdev->pwm_min_vol)\r
-               pdata->min_uV = 1000000;\r
-       else\r
-               pdata->min_uV = pwm_pdev->pwm_min_vol;\r
-\r
-       if(pwm_pdev->pwm_suspend_vol < pwm_pdev->pwm_min_vol)\r
-               pdata->suspend_voltage = pwm_pdev->pwm_min_vol;\r
-       else if(pwm_pdev->pwm_suspend_vol > pwm_pdev->pwm_max_vol)\r
-               pdata->suspend_voltage = pwm_pdev->pwm_max_vol;\r
-       else\r
-               pdata->suspend_voltage = pwm_pdev->pwm_suspend_vol;\r
-       \r
-       pdata->pwm_voltage_map = pwm_pdev->pwm_voltage_map;\r
-       pdata->pwm_id = pwm_pdev->pwm_id;\r
-       pdata->coefficient = pwm_pdev->pwm_coefficient;\r
-       pdata->pwm_vol_map_count = pwm_pdev->pwm_vol_map_count;\r
-       \r
-       pdata->pwm = devm_pwm_get(&pdev->dev, NULL);\r
-       if (IS_ERR(pdata->pwm)) {\r
-               dev_err(&pdev->dev, "unable to request PWM, trying legacy API\n");\r
-\r
-               pdata->pwm = pwm_request(pdata->pwm_id, "pwm-regulator");\r
-               if (IS_ERR(pdata->pwm)) {\r
-                       dev_err(&pdev->dev, "unable to request legacy PWM\n");\r
-                       ret = PTR_ERR(pdata->pwm);\r
-                       goto err;\r
-               }\r
-       }\r
-       if (pdata->pwm_period_ns > 0)\r
-               pwm_set_period(pdata->pwm, pdata->pwm_period_ns);\r
-\r
-       pdata->period = pwm_get_period(pdata->pwm);\r
-\r
-       g_pdata = pdata;\r
-       \r
-       if (pwm_pdev){\r
-               pdata->num_regulators = pwm_pdev ->num_regulators;\r
-               pdata->rdev = kcalloc(pdata->num_regulators,sizeof(struct regulator_dev *), GFP_KERNEL);\r
-               if (!pdata->rdev) {\r
-                       return -ENOMEM;\r
-               }\r
-               /* Instantiate the regulators */\r
-               for (i = 0; i < pdata->num_regulators; i++) {\r
-               reg_data = pwm_pdev->pwm_init_data[i];\r
-               if (!reg_data)\r
-                       continue;\r
-               config.dev = &pdev->dev;\r
-               config.driver_data = pdata;\r
-               if (&pdev->dev.of_node)\r
-                       config.of_node = pwm_pdev->of_node[i];\r
-               if (reg_data && reg_data->constraints.name)\r
-                               rail_name = reg_data->constraints.name;\r
-                       else\r
-                               rail_name = regulators[i].name;\r
-                       reg_data->supply_regulator = rail_name;\r
-       \r
-               config.init_data =reg_data;\r
-\r
-               pwm_rdev = regulator_register(&regulators[i],&config);\r
-               if (IS_ERR(pwm_rdev)) {\r
-                       printk("failed to register %d regulator\n",i);\r
-               goto err;\r
-               }\r
-               pdata->rdev[i] = pwm_rdev;\r
-               \r
-               /*********set pwm vol by defult***********/\r
-               dc = regulator_get(NULL,rail_name);\r
-               regulator_set_voltage(dc,pdata->pwm_voltage,pdata->pwm_voltage);\r
-               regulator_put(dc);\r
-               /**************************************/\r
-               }\r
-       }\r
-       return 0;\r
-err:\r
-       printk("%s:error\n",__func__);\r
-       return ret;\r
-\r
-}\r
-\r
-void pwm_suspend_voltage(void)\r
-{\r
-       \r
-}\r
-\r
-void pwm_resume_voltage(void)\r
-{\r
-\r
-}\r
-\r
-static int pwm_regulator_remove(struct platform_device *pdev)\r
-{\r
-       struct pwm_platform_data *pdata = pdev->dev.platform_data;\r
-       int i;\r
-\r
-       for (i = 0; i < pdata->num_regulators; i++)\r
-               if (pdata->rdev[i])\r
-                       regulator_unregister(pdata->rdev[i]);\r
-       kfree(pdata->rdev);\r
-       return 0;\r
-}\r
-\r
-static struct platform_driver pwm_regulator_driver = {\r
-       .driver = {\r
-               .name = "pwm-voltage-regulator",\r
-               .of_match_table =of_match_ptr(pwm_of_match),\r
-       },\r
-       .remove = 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
-//fs_initcall(pwm_regulator_module_init);\r
-module_init(pwm_regulator_module_init);\r
-module_exit(pwm_regulator_module_exit);\r
-MODULE_LICENSE("GPL");\r
+/*
+ *
+ * Copyright (C) 2013 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.
+ *
+ */
+#include <linux/bug.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/regulator/rockchip-pwm-regulator.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/pwm.h>
+
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+
+
+#if 0
+#define DBG(x...)      printk(KERN_INFO x)
+#else
+#define DBG(x...)
+#endif
+
+const static int pwm_voltage_map[] = {
+       925000 , 950000, 975000, 1000000, 1025000, 1050000,
+       1075000, 1100000, 1125000, 1150000, 1175000,
+       1200000, 1225000, 1250000, 1275000, 1300000,
+       1325000, 1350000, 1375000, 1400000
+};
+
+static int pwm_set_rate(struct pwm_platform_data *pdata, u32 rate)
+{
+       int duty_cycle;
+       DBG("%s:id=%d,rate=%d clkrate =%d\n", __func__, pdata->pwm_id, rate, pdata->period);
+
+       duty_cycle = (rate * (pdata->period) / 100) ;
+
+       pwm_config(pdata->pwm, duty_cycle, pdata->period);
+
+       pwm_enable(pdata->pwm);
+
+       return 0;
+}
+
+static int pwm_regulator_list_voltage(struct regulator_dev *dev, unsigned int index)
+{
+       struct pwm_platform_data *pdata = rdev_get_drvdata(dev);
+
+       DBG("%s:line=%d,pdata=%p,pwm_id=%d\n", __func__,
+               __LINE__, pdata, pdata->pwm_id);
+       if (index < (pdata->pwm_vol_map_count + 1))
+       return pdata->pwm_voltage_map[index];
+       else
+               return -1;
+}
+
+static int pwm_regulator_is_enabled(struct regulator_dev *dev)
+{
+       DBG("Enter %s\n", __func__);
+       return 0;
+}
+
+static int pwm_regulator_enable(struct regulator_dev *dev)
+{
+       DBG("Enter %s\n", __func__);
+       return 0;
+}
+
+static int pwm_regulator_disable(struct regulator_dev *dev)
+{
+       DBG("Enter %s\n", __func__);
+       return 0;
+}
+
+static int pwm_regulator_get_voltage(struct regulator_dev *dev)
+{
+       u32 vol;
+       struct pwm_platform_data *pdata = rdev_get_drvdata(dev);
+
+       DBG("%s:line=%d,pdata=%p,pwm_id=%d\n", __func__, __LINE__,
+               pdata, pdata->pwm_id);
+       vol = pdata->pwm_voltage;
+
+       return vol;
+}
+
+static int pwm_regulator_set_voltage(struct regulator_dev *dev,
+               int min_uV, int max_uV, unsigned *selector)
+{
+       struct pwm_platform_data *pdata = rdev_get_drvdata(dev);
+       const int *voltage_map = pdata->pwm_voltage_map;
+       int max = pdata->max_uV;
+       int coefficient = pdata->coefficient;
+       u32 size = pdata->pwm_vol_map_count;
+       u32 i, vol, pwm_value;
+
+       DBG("%s:  min_uV = %d, max_uV = %d\n", __func__, min_uV, max_uV);
+       DBG("%s:line=%d,pdata=%p,pwm_id=%d\n", __func__, __LINE__,
+               pdata, pdata->pwm_id);
+       mutex_lock(&pdata->mutex_pwm);
+
+       if (min_uV < voltage_map[0] || max_uV > voltage_map[size-1]) {
+               printk("%s: voltage_map voltage is out of table\n", __func__);
+               mutex_unlock(&pdata->mutex_pwm);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < size; i++) {
+               if (voltage_map[i] >= min_uV)
+                       break;
+       }
+       vol =  voltage_map[i];
+       pdata->pwm_voltage = vol;
+
+       /* VDD12 = 1.40 - 0.455*D , DΪPWMÕ¼¿Õ±È*/
+       pwm_value = (max-vol) / coefficient / 10;
+       /*pwm_value %, coefficient *1000*/
+
+       if (pwm_set_rate(pdata, pwm_value) != 0) {
+               printk("%s:fail to set pwm rate,pwm_value=%d\n", __func__, pwm_value);
+               mutex_unlock(&pdata->mutex_pwm);
+               return -1;
+
+       }
+       *selector = i;
+
+       mutex_unlock(&pdata->mutex_pwm);
+
+       DBG("%s:ok,vol=%d,pwm_value=%d %d\n", __func__, vol,
+               pwm_value, pdata->pwm_voltage);
+
+       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 regulators[] = {
+
+       {
+               .name = "PWM_DCDC1",
+               .id = 0,
+               .ops = &pwm_voltage_ops,
+               .n_voltages =  ARRAY_SIZE(pwm_voltage_map),
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+       },
+
+       {
+               .name = "PWM_DCDC2",
+               .id = 1,
+               .ops = &pwm_voltage_ops,
+               .n_voltages =  ARRAY_SIZE(pwm_voltage_map),
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+       },
+
+};
+
+#ifdef CONFIG_OF
+static struct of_device_id pwm_of_match[] = {
+       { .compatible = "rockchip_pwm_regulator"},
+       { },
+};
+MODULE_DEVICE_TABLE(of, pwm_of_match);
+
+static struct of_regulator_match pwm_matches[] = {
+       { .name = "pwm_dcdc1",  .driver_data = (void *)0  },
+       { .name = "pwm_dcdc2",  .driver_data = (void *)1  },
+};
+
+static struct pwm_regulator_board *pwm_regulator_parse_dt(
+               struct platform_device *pdev,
+               struct of_regulator_match **pwm_reg_matches)
+{
+       struct pwm_regulator_board *pwm_plat_data;
+       struct device_node *np, *regulators;
+       struct of_regulator_match *matches;
+       int idx = 0, ret, count;
+       struct property *prop;
+       int length;
+       const __be32 *init_vol, *max_vol, *min_vol, *suspend_vol, *coefficient, *id;
+
+       DBG("%s,line=%d\n", __func__, __LINE__);
+
+       pwm_plat_data = devm_kzalloc(&pdev->dev, sizeof(*pwm_plat_data),
+                                       GFP_KERNEL);
+
+       if (!pwm_plat_data) {
+               dev_err(&pdev->dev, "Failure to alloc pdata for regulators.\n");
+               return NULL;
+       }
+
+       np = of_node_get(pdev->dev.of_node);
+       regulators = of_find_node_by_name(np, "regulators");
+       if (!regulators) {
+               dev_err(&pdev->dev, "regulator node not found\n");
+               return NULL;
+       }
+       count = ARRAY_SIZE(pwm_matches);
+       matches = pwm_matches;
+       ret = of_regulator_match(&pdev->dev, regulators, matches, count);
+       of_node_put(regulators);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Error parsing regulator init data: %d\n",
+                       ret);
+               return NULL;
+       }
+
+       pwm_plat_data->num_regulators = count;
+       *pwm_reg_matches = matches;
+
+       for (idx = 0; idx < count; idx++) {
+               if (!matches[idx].init_data || !matches[idx].of_node)
+                       continue;
+               pwm_plat_data->pwm_init_data[idx] = matches[idx].init_data;
+               pwm_plat_data->of_node[idx] = matches[idx].of_node;
+       }
+
+       init_vol = of_get_property(np, "rockchip,pwm_voltage", NULL);
+       if (init_vol)
+               pwm_plat_data->pwm_init_vol = be32_to_cpu(*init_vol);
+
+       max_vol = of_get_property(np, "rockchip,pwm_max_voltage", NULL);
+       if (max_vol)
+               pwm_plat_data->pwm_max_vol = be32_to_cpu(*max_vol);
+
+       min_vol = of_get_property(np, "rockchip,pwm_min_voltage", NULL);
+       if (min_vol)
+               pwm_plat_data->pwm_min_vol = be32_to_cpu(*min_vol);
+
+       suspend_vol = of_get_property(np, "rockchip,pwm_suspend_voltage", NULL);
+       if (suspend_vol)
+               pwm_plat_data->pwm_suspend_vol = be32_to_cpu(*suspend_vol);
+
+       coefficient  = of_get_property(np, "rockchip,pwm_coefficient", NULL);
+       if (coefficient)
+               pwm_plat_data->pwm_coefficient = be32_to_cpu(*coefficient);
+
+       id  = of_get_property(np, "rockchip,pwm_id", NULL);
+       if (id)
+               pwm_plat_data->pwm_id = be32_to_cpu(*id);
+
+       prop = of_find_property(np, "rockchip,pwm_voltage_map", &length);
+       if (!prop)
+               return NULL;
+       pwm_plat_data->pwm_vol_map_count = length / sizeof(u32);
+       if (pwm_plat_data->pwm_vol_map_count > 0) {
+               size_t size = sizeof(*pwm_plat_data->pwm_voltage_map) * pwm_plat_data->pwm_vol_map_count;
+
+       pwm_plat_data->pwm_voltage_map = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+       if (!pwm_plat_data->pwm_voltage_map)
+               return NULL;
+       ret = of_property_read_u32_array(np, "rockchip,pwm_voltage_map",
+               pwm_plat_data->pwm_voltage_map, pwm_plat_data->pwm_vol_map_count);
+       if (ret < 0)
+               printk("pwm voltage map not specified\n");
+       }
+       return pwm_plat_data;
+}
+#else
+static inline struct pwm_regulator_board *pwm_regulator_parse_dt(
+                       struct platform_device *pdev,
+                       struct of_regulator_match **pwm_reg_matches)
+{
+       return NULL;
+}
+#endif
+
+
+static int __init pwm_regulator_probe(struct platform_device *pdev)
+{
+       struct pwm_platform_data *pdata = pdev->dev.platform_data;
+       struct pwm_regulator_board *pwm_pdev;
+       struct of_regulator_match *pwm_reg_matches = NULL;
+       struct regulator_init_data *reg_data;
+       struct regulator_config config = { };
+       const char *rail_name = NULL;
+       struct regulator_dev *pwm_rdev;
+       int ret, i = 0;
+       struct regulator *dc;
+
+       pwm_pdev = devm_kzalloc(&pdev->dev, sizeof(*pwm_pdev),
+                                       GFP_KERNEL);
+       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata),
+                                       GFP_KERNEL);
+
+       if (pdev->dev.of_node)
+               pwm_pdev = pwm_regulator_parse_dt(pdev, &pwm_reg_matches);
+
+       if (!pwm_pdev) {
+               dev_err(&pdev->dev, "Platform data not found\n");
+               return -EINVAL;
+       }
+
+       if (!pwm_pdev->pwm_init_vol)
+               pdata->pwm_voltage = 1100000;   /* default 1.1v*/
+       else
+               pdata->pwm_voltage = pwm_pdev->pwm_init_vol;
+
+       if (!pwm_pdev->pwm_max_vol)
+               pdata->max_uV = 1400000;
+       else
+               pdata->max_uV = pwm_pdev->pwm_max_vol;
+
+       if (!pwm_pdev->pwm_min_vol)
+               pdata->min_uV = 1000000;
+       else
+               pdata->min_uV = pwm_pdev->pwm_min_vol;
+
+       if (pwm_pdev->pwm_suspend_vol < pwm_pdev->pwm_min_vol)
+               pdata->suspend_voltage = pwm_pdev->pwm_min_vol;
+       else if (pwm_pdev->pwm_suspend_vol > pwm_pdev->pwm_max_vol)
+               pdata->suspend_voltage = pwm_pdev->pwm_max_vol;
+       else
+               pdata->suspend_voltage = pwm_pdev->pwm_suspend_vol;
+
+       pdata->pwm_voltage_map = pwm_pdev->pwm_voltage_map;
+       pdata->pwm_id = pwm_pdev->pwm_id;
+       pdata->coefficient = pwm_pdev->pwm_coefficient;
+       pdata->pwm_vol_map_count = pwm_pdev->pwm_vol_map_count;
+
+       pdata->pwm = devm_pwm_get(&pdev->dev, NULL);
+       if (IS_ERR(pdata->pwm)) {
+               dev_err(&pdev->dev, "unable to request PWM, trying legacy API\n");
+
+               pdata->pwm = pwm_request(pdata->pwm_id, "pwm-regulator");
+               if (IS_ERR(pdata->pwm)) {
+                       dev_err(&pdev->dev, "unable to request legacy PWM\n");
+                       ret = PTR_ERR(pdata->pwm);
+                       goto err;
+               }
+       }
+       if (pdata->pwm_period_ns > 0)
+               pwm_set_period(pdata->pwm, pdata->pwm_period_ns);
+
+       pdata->period = pwm_get_period(pdata->pwm);
+
+       mutex_init(&pdata->mutex_pwm);
+
+       if (pwm_pdev) {
+               pdata->num_regulators = pwm_pdev->num_regulators;
+               pdata->rdev = kcalloc(pdata->num_regulators, sizeof(struct regulator_dev *), GFP_KERNEL);
+               if (!pdata->rdev) {
+                       return -ENOMEM;
+               }
+               /* Instantiate the regulators */
+               for (i = 0; i < pdata->num_regulators; i++) {
+               reg_data = pwm_pdev->pwm_init_data[i];
+               if (!reg_data)
+                       continue;
+               config.dev = &pdev->dev;
+               config.driver_data = pdata;
+               if (&pdev->dev.of_node)
+                       config.of_node = pwm_pdev->of_node[i];
+               if (reg_data && reg_data->constraints.name)
+                               rail_name = reg_data->constraints.name;
+                       else
+                               rail_name = regulators[i].name;
+                       reg_data->supply_regulator = rail_name;
+
+               config.init_data = reg_data;
+
+               pwm_rdev = regulator_register(&regulators[i], &config);
+               if (IS_ERR(pwm_rdev)) {
+                       printk("failed to register %d regulator\n", i);
+               goto err;
+               }
+               pdata->rdev[i] = pwm_rdev;
+
+               /*********set pwm vol by defult***********/
+               dc = regulator_get(NULL, rail_name);
+               regulator_set_voltage(dc, pdata->pwm_voltage, pdata->pwm_voltage);
+               regulator_put(dc);
+               /**************************************/
+               }
+       }
+       return 0;
+err:
+       printk("%s:error\n", __func__);
+       return ret;
+
+}
+
+void pwm_suspend_voltage(void)
+{
+
+}
+
+void pwm_resume_voltage(void)
+{
+
+}
+
+static int pwm_regulator_remove(struct platform_device *pdev)
+{
+       struct pwm_platform_data *pdata = pdev->dev.platform_data;
+       int i;
+
+       for (i = 0; i < pdata->num_regulators; i++)
+               if (pdata->rdev[i])
+                       regulator_unregister(pdata->rdev[i]);
+       kfree(pdata->rdev);
+       return 0;
+}
+
+static struct platform_driver pwm_regulator_driver = {
+       .driver = {
+               .name = "pwm-voltage-regulator",
+               .of_match_table = of_match_ptr(pwm_of_match),
+       },
+       .remove = 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);
+}
+
+/*fs_initcall(pwm_regulator_module_init);*/
+module_init(pwm_regulator_module_init);
+module_exit(pwm_regulator_module_exit);
+MODULE_LICENSE("GPL");
index 973be235a24b399cee987cae6e8854621a51d22b..1dc1f1c63e5234145dde21517c188d1cd676d9c9 100755 (executable)
@@ -1,64 +1,65 @@
-/* include/linux/regulator/charge-regulator.h\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
-#ifndef __LINUX_REGULATOR_PWM_H\r
-\r
-#define __LINUX_REGULATOR_PWM_H\r
-\r
-#include <linux/regulator/machine.h>\r
-//#include <plat/pwm.h>\r
-\r
-#define PWM_DIV              PWM_DIV2\r
-\r
-\r
-struct regulator_init_data;\r
-\r
-struct pwm_platform_data {\r
-       int     pwm_id;\r
-       int     pwm_gpio;\r
-       struct pwm_device       *pwm;\r
-       unsigned int            period;\r
-       unsigned int pwm_period_ns;\r
-       unsigned int            scale;\r
-       unsigned int    pwm_voltage;\r
-       unsigned int    suspend_voltage;\r
-       unsigned int    coefficient;\r
-       unsigned int    min_uV;\r
-       unsigned int    max_uV;\r
-       unsigned int    *pwm_voltage_map;\r
-       struct regulator_init_data *init_data;\r
-       int num_regulators;\r
-       struct regulator_dev **rdev;\r
-       int pwm_vol_map_count;\r
-};\r
-\r
-struct pwm_regulator_board {\r
-       int pwm_gpio;\r
-       struct pwm_device       *pwm;\r
-       struct regulator_init_data *pwm_init_data[4];\r
-       struct device_node *of_node[4];\r
-       int     pwm_id;\r
-       unsigned int *pwm_voltage_map; \r
-       unsigned int pwm_init_vol;\r
-       unsigned int pwm_max_vol;\r
-       unsigned int pwm_min_vol;\r
-       unsigned int pwm_suspend_vol;\r
-       unsigned int pwm_coefficient;\r
-       int num_regulators;\r
-       struct regulator_dev **rdev;\r
-       int pwm_vol_map_count;\r
-};\r
-\r
-#endif\r
-\r
+/* 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 <linux/regulator/machine.h>
+/*#include <plat/pwm.h>*/
+
+#define PWM_DIV              PWM_DIV2
+
+
+struct regulator_init_data;
+
+struct pwm_platform_data {
+       int     pwm_id;
+       int     pwm_gpio;
+       struct pwm_device       *pwm;
+       unsigned int            period;
+       unsigned int pwm_period_ns;
+       unsigned int            scale;
+       unsigned int    pwm_voltage;
+       unsigned int    suspend_voltage;
+       unsigned int    coefficient;
+       unsigned int    min_uV;
+       unsigned int    max_uV;
+       unsigned int    *pwm_voltage_map;
+       struct regulator_init_data *init_data;
+       int num_regulators;
+       struct regulator_dev **rdev;
+       int pwm_vol_map_count;
+       struct mutex mutex_pwm;
+};
+
+struct pwm_regulator_board {
+       int pwm_gpio;
+       struct pwm_device       *pwm;
+       struct regulator_init_data *pwm_init_data[4];
+       struct device_node *of_node[4];
+       int     pwm_id;
+       unsigned int *pwm_voltage_map;
+       unsigned int pwm_init_vol;
+       unsigned int pwm_max_vol;
+       unsigned int pwm_min_vol;
+       unsigned int pwm_suspend_vol;
+       unsigned int pwm_coefficient;
+       int num_regulators;
+       struct regulator_dev **rdev;
+       int pwm_vol_map_count;
+};
+
+#endif
+