mirror of
https://github.com/hardkernel/linux.git
synced 2026-03-24 19:40:21 +09:00
ODROIDC: PWM Duty cycle range 0 to 1024
Change-Id: I4bce549c369c079573e14f3f6fa6d21a0a21dc9f
This commit is contained in:
@@ -28,6 +28,10 @@ struct pwm_ctrl {
|
||||
int duty0,duty1;
|
||||
};
|
||||
|
||||
#define FREQ_MIN 10 // 10Hz
|
||||
#define FREQ_MAX 1000000 // 1MHz
|
||||
#define DUTY_MAX 1024 // Duty cycle Max
|
||||
|
||||
//[*]------------------------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// driver sysfs attribute define
|
||||
@@ -43,15 +47,15 @@ static ssize_t set_enable0 (struct device *dev, struct device_attribute *attr, c
|
||||
|
||||
mutex_lock(&ctrl->mutex);
|
||||
if(val) {
|
||||
ctrl->pwm0_status = 1;
|
||||
pwm_disable(ctrl->pwm0);
|
||||
pwm_config(ctrl->pwm0, ctrl->duty0, ctrl->freq0);
|
||||
pwm_enable(ctrl->pwm0);
|
||||
ctrl->pwm0_status = 1;
|
||||
}
|
||||
else {
|
||||
ctrl->pwm0_status = 0;
|
||||
pwm_disable(ctrl->pwm0);
|
||||
pwm_config(ctrl->pwm0, 0, ctrl->freq0);
|
||||
ctrl->pwm0_status = 0;
|
||||
}
|
||||
mutex_unlock(&ctrl->mutex);
|
||||
|
||||
@@ -75,24 +79,22 @@ static ssize_t set_duty0 (struct device *dev, struct device_attribute *attr, con
|
||||
|
||||
if(!(sscanf(buf, "%u\n", &val))) return -EINVAL;
|
||||
|
||||
if((val > 100)||(val < 0)){
|
||||
if((val > DUTY_MAX)||(val < 0)){
|
||||
dev_err(dev, "PWM_0 : Invalid param. Duty cycle range is 0 to 100 \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
dev_info(dev, "PWM_0 : %s [%d] \n",__FUNCTION__,val);
|
||||
|
||||
mutex_lock(&ctrl->mutex);
|
||||
ctrl->duty0 = val;
|
||||
|
||||
mutex_lock(&ctrl->mutex);
|
||||
if(ctrl->pwm0_status){
|
||||
pwm_disable(ctrl->pwm0);
|
||||
pwm_config(ctrl->pwm0, ctrl->duty0, ctrl->freq0);
|
||||
pwm_enable(ctrl->pwm0);
|
||||
}
|
||||
else {
|
||||
pwm_disable(ctrl->pwm0);
|
||||
pwm_config(ctrl->pwm0, 0, ctrl->freq0);
|
||||
pwm_disable(ctrl->pwm0);
|
||||
}
|
||||
mutex_unlock(&ctrl->mutex);
|
||||
|
||||
@@ -115,24 +117,22 @@ static ssize_t set_freq0 (struct device *dev, struct device_attribute *attr, con
|
||||
|
||||
if(!(sscanf(buf, "%u\n", &val))) return -EINVAL;
|
||||
|
||||
if((val < 0)){
|
||||
dev_err(dev, "PWM_0 : Invalid param. Duty cycle range is 0 to 100 \n");
|
||||
if((val < FREQ_MIN)||(val > FREQ_MAX)){
|
||||
dev_err(dev, "PWM_0 : Invalid param. Frequency range is 10Hz to 1MHz \n");
|
||||
return count;
|
||||
}
|
||||
|
||||
dev_info(dev, "PWM_0 : %s [%d] \n",__FUNCTION__,val);
|
||||
|
||||
mutex_lock(&ctrl->mutex);
|
||||
ctrl->freq0 = val;
|
||||
|
||||
mutex_lock(&ctrl->mutex);
|
||||
if(ctrl->pwm0_status){
|
||||
pwm_disable(ctrl->pwm0);
|
||||
pwm_config(ctrl->pwm0, ctrl->duty0, ctrl->freq0);
|
||||
pwm_enable(ctrl->pwm0);
|
||||
}
|
||||
else {
|
||||
pwm_disable(ctrl->pwm0);
|
||||
pwm_config(ctrl->pwm0, 0, ctrl->freq0);
|
||||
pwm_disable(ctrl->pwm0);
|
||||
}
|
||||
mutex_unlock(&ctrl->mutex);
|
||||
|
||||
@@ -176,13 +176,12 @@ static ssize_t set_enable1 (struct device *dev, struct device_attribute *attr, c
|
||||
mutex_lock(&ctrl->mutex);
|
||||
if(val) {
|
||||
ctrl->pwm1_status = 1;
|
||||
pwm_disable(ctrl->pwm1);
|
||||
pwm_config(ctrl->pwm1, ctrl->duty1, ctrl->freq1);
|
||||
pwm_enable(ctrl->pwm1);
|
||||
}
|
||||
else {
|
||||
pwm_disable(ctrl->pwm1);
|
||||
pwm_config(ctrl->pwm1, 0, ctrl->freq1);
|
||||
pwm_disable(ctrl->pwm1);
|
||||
ctrl->pwm1_status = 0;
|
||||
}
|
||||
mutex_unlock(&ctrl->mutex);
|
||||
@@ -207,23 +206,22 @@ static ssize_t set_duty1 (struct device *dev, struct device_attribute *attr, con
|
||||
|
||||
if(!(sscanf(buf, "%u\n", &val))) return -EINVAL;
|
||||
|
||||
if((val > 100)||(val < 0)){
|
||||
if((val > DUTY_MAX)||(val < 0)){
|
||||
dev_err(dev, "PWM_1 : Invalid param. Duty cycle range is 0 to 100 \n");
|
||||
return count;
|
||||
}
|
||||
dev_info(dev, "PWM_1 : %s [%d] \n",__FUNCTION__,val);
|
||||
|
||||
mutex_lock(&ctrl->mutex);
|
||||
ctrl->duty1 = val;
|
||||
|
||||
mutex_lock(&ctrl->mutex);
|
||||
if(ctrl->pwm1_status){
|
||||
pwm_disable(ctrl->pwm1);
|
||||
pwm_config(ctrl->pwm1, ctrl->duty1, ctrl->freq1);
|
||||
pwm_enable(ctrl->pwm1);
|
||||
}
|
||||
else {
|
||||
pwm_disable(ctrl->pwm1);
|
||||
pwm_config(ctrl->pwm1, 0, ctrl->freq1);
|
||||
pwm_disable(ctrl->pwm1);
|
||||
}
|
||||
mutex_unlock(&ctrl->mutex);
|
||||
|
||||
@@ -246,22 +244,22 @@ static ssize_t set_freq1 (struct device *dev, struct device_attribute *attr, con
|
||||
|
||||
if(!(sscanf(buf, "%u\n", &val))) return -EINVAL;
|
||||
|
||||
if((val < 10)||(val > 1000000)){
|
||||
dev_err(dev, "PWM_1 : Invalid param. Duty cycle range is 10 to 1MHz \n");
|
||||
if((val < FREQ_MIN)||(val > FREQ_MAX)){
|
||||
dev_err(dev, "PWM_1 : Invalid param. Frequency range is 10Hz to 1MHz \n");
|
||||
return count;
|
||||
}
|
||||
dev_info(dev, "PWM_1 : %s [%d] \n",__FUNCTION__,val);
|
||||
mutex_lock(&ctrl->mutex);
|
||||
ctrl->freq1 = val;
|
||||
|
||||
mutex_lock(&ctrl->mutex);
|
||||
if(ctrl->pwm1_status){
|
||||
pwm_disable(ctrl->pwm1);
|
||||
pwm_config(ctrl->pwm1, ctrl->duty1, ctrl->freq1);
|
||||
pwm_enable(ctrl->pwm1);
|
||||
}
|
||||
else {
|
||||
pwm_disable(ctrl->pwm1);
|
||||
pwm_config(ctrl->pwm1, 0, ctrl->freq1);
|
||||
pwm_disable(ctrl->pwm1);
|
||||
}
|
||||
mutex_unlock(&ctrl->mutex);
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ MODULE_PARM_DESC(npwm,"\n odroid-c1 The number of available pwm (max 2-port)\n")
|
||||
#define PWM_B 0
|
||||
#define PWM_E 1
|
||||
#define FIN_FREQ (24 * 1000)
|
||||
#define DUTY_MAX 1024
|
||||
|
||||
struct meson_pwm_device {
|
||||
unsigned int freq;
|
||||
@@ -55,17 +56,12 @@ struct meson_chip {
|
||||
|
||||
static void meson_pwm_init(struct device *dev, int pwmn)
|
||||
{
|
||||
unsigned long flags;
|
||||
if(pwmn == 1) {
|
||||
local_irq_save(flags);
|
||||
aml_write_reg32(P_PWM_MISC_REG_AB, (aml_read_reg32(P_PWM_MISC_REG_AB) & ~(0x7f << 16)) | ((1 << 23)));
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
else {
|
||||
local_irq_save(flags);
|
||||
aml_write_reg32(P_PWM_MISC_REG_AB, (aml_read_reg32(P_PWM_MISC_REG_AB) & ~(0x7f << 16)) | ((1 << 23)));
|
||||
aml_write_reg32(P_PWM_MISC_REG_EF, (aml_read_reg32(P_PWM_MISC_REG_EF) & ~(0x7f << 8)) | ((1 << 15)));
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -75,10 +71,8 @@ static int meson_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
struct meson_chip *meson = to_meson_chip(chip);
|
||||
struct meson_pwm_device *meson_pwm;
|
||||
unsigned int id = pwm->pwm;
|
||||
unsigned long flags;
|
||||
|
||||
meson_pwm = meson->meson_pwm[id];
|
||||
local_irq_save(flags);
|
||||
switch (id) {
|
||||
case PWM_B:
|
||||
aml_set_reg32_bits(P_PWM_MISC_REG_AB, 1, 1, 1); //enable pwm_b
|
||||
@@ -87,7 +81,6 @@ static int meson_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
aml_set_reg32_bits(P_PWM_MISC_REG_EF, 1, 0, 1); //enable pwm_e
|
||||
break;
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -97,10 +90,8 @@ static void meson_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
struct meson_chip *meson = to_meson_chip(chip);
|
||||
struct meson_pwm_device *meson_pwm;
|
||||
unsigned int id = pwm->pwm;
|
||||
unsigned long flags;
|
||||
|
||||
meson_pwm = meson->meson_pwm[id];
|
||||
local_irq_save(flags);
|
||||
switch (id) {
|
||||
case PWM_B:
|
||||
aml_set_reg32_bits(P_PWM_MISC_REG_AB, 0, 1, 1); //disable pwm_b
|
||||
@@ -109,12 +100,11 @@ static void meson_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
aml_set_reg32_bits(P_PWM_MISC_REG_EF, 0, 0, 1); //disable pwm_e
|
||||
break;
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
return;
|
||||
}
|
||||
|
||||
static int meson_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
int duty_percent, int pwm_freq)
|
||||
int duty, int pwm_freq)
|
||||
{
|
||||
struct meson_chip *meson = to_meson_chip(chip);
|
||||
struct meson_pwm_device *meson_pwm;
|
||||
@@ -122,11 +112,11 @@ static int meson_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
struct device *dev = chip->dev;
|
||||
unsigned pwm_hi = 0, pwm_lo = 0;
|
||||
unsigned fout_freq=0, pwm_cnt, pwm_pre_div;
|
||||
unsigned long flags=0;
|
||||
unsigned long temp=0;
|
||||
int i=0;
|
||||
|
||||
if((duty_percent<0)||(duty_percent>100)){
|
||||
dev_err(dev, "Not available duty_percent... error!!!\n");
|
||||
if((duty<0)||(duty>DUTY_MAX)){
|
||||
dev_err(dev, "Not available duty... error!!!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
meson_pwm = meson->meson_pwm[id];
|
||||
@@ -138,21 +128,24 @@ static int meson_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
if (pwm_cnt <= 0xffff)
|
||||
break;
|
||||
}
|
||||
if(duty_percent==0) {
|
||||
|
||||
if(duty==0) {
|
||||
pwm_hi=0;
|
||||
pwm_lo=pwm_cnt;
|
||||
goto div_set;
|
||||
}
|
||||
if(duty_percent==100) {
|
||||
else if(duty==DUTY_MAX) {
|
||||
pwm_hi=pwm_cnt;
|
||||
pwm_lo=0;
|
||||
goto div_set;
|
||||
}
|
||||
pwm_hi = (pwm_cnt*duty_percent)/100;
|
||||
pwm_lo = (pwm_cnt*(100-duty_percent))/100;
|
||||
|
||||
temp = pwm_cnt*duty;
|
||||
temp /= DUTY_MAX;
|
||||
pwm_hi = (unsigned)temp;
|
||||
pwm_lo = pwm_cnt - pwm_hi;
|
||||
|
||||
div_set :
|
||||
local_irq_save(flags);
|
||||
switch(id){
|
||||
case PWM_B:
|
||||
aml_set_reg32_bits(P_PWM_MISC_REG_AB, pwm_pre_div, 16, 7); //pwm_b_clk_div
|
||||
@@ -165,7 +158,6 @@ div_set :
|
||||
default:
|
||||
break;
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -402,9 +402,13 @@ EXPORT_SYMBOL_GPL(pwm_free);
|
||||
*/
|
||||
int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
|
||||
{
|
||||
#if !defined(CONFIG_MACH_MESON8B_ODROIDC)
|
||||
if (!pwm || duty_ns < 0 || period_ns <= 0 || duty_ns > period_ns)
|
||||
return -EINVAL;
|
||||
|
||||
#else
|
||||
if (!pwm || duty_ns < 0 || period_ns <= 0)
|
||||
return -EINVAL;
|
||||
#endif
|
||||
return pwm->chip->ops->config(pwm->chip, pwm, duty_ns, period_ns);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pwm_config);
|
||||
|
||||
Reference in New Issue
Block a user