regulator: rk29-pwm: fix sleep in atomic

fix this bug, only happens when cpu run in 1.2G.
BUG: scheduling while atomic: VideoTrackEncod/414/0x00000202
[<c0431198>] (unwind_backtrace+0x0/0xd8) from [<c079df38>] (schedule+0x74/0x540)
[<c079df38>] (schedule+0x74/0x540) from [<c079f5d0>] (schedule_hrtimeout_range+0x138/0x178)
[<c079f5d0>] (schedule_hrtimeout_range+0x138/0x178) from [<c045bae8>] (usleep_range+0x44/0x48)
[<c045bae8>] (usleep_range+0x44/0x48) from [<c059e010>] (pwm_regulator_set_voltage+0x140/0x168)
[<c059e010>] (pwm_regulator_set_voltage+0x140/0x168) from [<c059d66c>] (regulator_set_voltage+0xe8/0x100)
[<c059d66c>] (regulator_set_voltage+0xe8/0x100) from [<c043f7c8>] (rk29_cpufreq_target+0x5f4/0x6cc)
[<c043f7c8>] (rk29_cpufreq_target+0x5f4/0x6cc) from [<c0671d44>] (__cpufreq_driver_target+0x28/0x38)
[<c0671d44>] (__cpufreq_driver_target+0x28/0x38) from [<c06736c0>] (cpufreq_driver_target+0x44/0x60)
[<c06736c0>] (cpufreq_driver_target+0x44/0x60) from [<c043ec84>] (rk29_cpufreq_aclk_vepu_notifier_event+0x78/0x94)
[<c043ec84>] (rk29_cpufreq_aclk_vepu_notifier_event+0x78/0x94) from [<c046bfd4>] (notifier_call_chain+0x2c/0x70)
[<c046bfd4>] (notifier_call_chain+0x2c/0x70) from [<c046c0a4>] (raw_notifier_call_chain+0x14/0x18)
[<c046c0a4>] (raw_notifier_call_chain+0x14/0x18) from [<c04384b4>] (clk_notify+0x68/0xec)
[<c04384b4>] (clk_notify+0x68/0xec) from [<c04386fc>] (clk_enable_nolock+0x4c/0xc4)
[<c04386fc>] (clk_enable_nolock+0x4c/0xc4) from [<c04391ac>] (clk_enable+0x70/0xb4)
[<c04391ac>] (clk_enable+0x70/0xb4) from [<c0442708>] (vpu_service_power_on+0x48/0xec)
[<c0442708>] (vpu_service_power_on+0x48/0xec) from [<c0442e34>] (vpu_service_ioctl+0x688/0x6e4)
[<c0442e34>] (vpu_service_ioctl+0x688/0x6e4) from [<c04bfa60>] (vfs_ioctl+0x2c/0x8c)
[<c04bfa60>] (vfs_ioctl+0x2c/0x8c) from [<c04c0110>] (do_vfs_ioctl+0x558/0x5c4)
[<c04c0110>] (do_vfs_ioctl+0x558/0x5c4) from [<c04c01b0>] (sys_ioctl+0x34/0x54)
[<c04c01b0>] (sys_ioctl+0x34/0x54) from [<c042bf40>] (ret_fast_syscall+0x0/0x2c)
This commit is contained in:
黄涛
2011-10-18 11:29:36 +08:00
parent a123ff3d4e
commit 045e8a7d9e

View File

@@ -1,48 +1,49 @@
/* 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. */
/*******************************************************************
*
* 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 <linux/bug.h>
NOTES :
$LOG: GPIO.C,V $
REVISION 0.01
********************************************************************/
#include <linux/bug.h>
#include <linux/err.h>
#include <linux/hardirq.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/clk.h>
#include <asm/io.h>
#include <linux/delay.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/rk29-pwm-regulator.h>
#include <mach/iomux.h>
#include <linux/gpio.h>
#if 0
#define DBG(x...) printk(KERN_INFO x)
#else
#define DBG(x...)
#endif
#if 0
#define DBG(x...) printk(KERN_INFO x)
#else
#define DBG(x...)
#endif
#define PWM_VCORE_120 40
@@ -101,7 +102,10 @@ static int pwm_set_rate(struct pwm_platform_data *pdata,int nHz,u32 rate)
return -1;
}
usleep_range(10*1000, 10*1000);
if (in_atomic() || irqs_disabled())
mdelay(10);
else
usleep_range(10*1000, 10*1000);
return (0);
@@ -120,20 +124,20 @@ 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);
@@ -141,8 +145,8 @@ static int pwm_regulator_get_voltage(struct regulator_dev *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)
{
@@ -157,14 +161,14 @@ static int pwm_regulator_set_voltage(struct regulator_dev *dev,
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;
return -EINVAL;
for (i = 0; i < size; i++)
{
if (voltage_map[i] >= min_mV)
break;
break;
}
vol = voltage_map[i];
@@ -179,8 +183,8 @@ static int pwm_regulator_set_voltage(struct regulator_dev *dev,
return 0;
}
}
static struct regulator_ops pwm_voltage_ops = {
.list_voltage = pwm_regulator_list_voltage,
.set_voltage =pwm_regulator_set_voltage,
@@ -189,30 +193,30 @@ static struct regulator_ops pwm_voltage_ops = {
.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 ;
if (!pdata)
return -ENODEV;
if (!pdata->pwm_voltage)
pdata->pwm_voltage = 1200; // default 1.2v
if (!pdata)
return -ENODEV;
if (!pdata->pwm_voltage)
pdata->pwm_voltage = 1200; // default 1.2v
rdev = regulator_register(&pwm_regulator, &pdev->dev,
pdata->init_data, pdata);
if (IS_ERR(rdev)) {
dev_dbg(&pdev->dev, "couldn't register regulator\n");
dev_dbg(&pdev->dev, "couldn't register regulator\n");
return PTR_ERR(rdev);
}
@@ -239,7 +243,7 @@ err_gpio:
return ret;
}
}
static int __devexit pwm_regulator_remove(struct platform_device *pdev)
{
struct pwm_platform_data *pdata = pdev->dev.platform_data;
@@ -257,23 +261,23 @@ static struct platform_driver pwm_regulator_driver = {
},
.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);
}
}
subsys_initcall(pwm_regulator_module_init);
module_exit(pwm_regulator_module_exit);
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("hxy <hxy@rock-chips.com>");
MODULE_DESCRIPTION("k29 pwm change driver");