From: Yusuf Caglar Akyuz <cag...@bilkon-kontrol.com.tr> With the aid of simple sysfs interface driver, functionality can be verified easily without writing a test program.
Signed-off-by: Yusuf Caglar Akyuz <cag...@bilkon-kontrol.com.tr> --- arch/arm/mach-davinci/pwm.c | 91 +++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 91 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/pwm.c b/arch/arm/mach-davinci/pwm.c index ab66d82..f9aa5f4 100644 --- a/arch/arm/mach-davinci/pwm.c +++ b/arch/arm/mach-davinci/pwm.c @@ -47,6 +47,7 @@ struct pwm_davinci_device { davinci_pwmregsovly regs; wait_queue_head_t intr_wait; struct clk *pwm_clk; + int running; }; char *dm644x_name[] = { "PWM0_CLK", "PWM1_CLK", "PWM2_CLK" }; @@ -338,6 +339,92 @@ static irqreturn_t pwm_isr(int irq, void *dev_id) return IRQ_HANDLED; } +#define PWM_FREQ 0x10000 / 48 + +static ssize_t +pwm_show(struct device *d, struct device_attribute *a, char *buf) +{ + struct pwm_davinci_device *pwm_dev; + + pwm_dev = pwm_dev_get_by_minor(to_platform_device(d)->id); + + return sprintf(buf, "%s\n", pwm_dev->running == 1 ? "running" : "stopped"); +} +static ssize_t +pwm_start(struct device *d, struct device_attribute *a, const char *buf + , size_t count) +{ + struct pwm_davinci_device *pwm_dev; + + if(count < 1) + return count; + + pwm_dev = pwm_dev_get_by_minor(to_platform_device(d)->id); + if(buf[0] == '1' && pwm_dev->running == 0) { + /* sample configuration */ + pwm_dev->regs->per = PWM_FREQ; + pwm_dev->regs->ph1d = 0x0; + pwm_dev->regs->cfg |= 0x2; + pwm_dev->intr_complete = 0; + pwm_dev->running = 1; + pwm_dev->regs->start = 0x1; + } + + if(buf[0] == '0' && pwm_dev->running == 1) { + pwm_dev->regs->cfg &= 0xFFFFFFFC; + pwm_dev->running = 0; + } + + return count; +} +static DEVICE_ATTR(control, S_IRUGO | S_IWUSR, pwm_show, pwm_start); + +static ssize_t +duty_read(struct device *d, struct device_attribute *a, char *buf) +{ + struct pwm_davinci_device *pwm_dev; + + pwm_dev = pwm_dev_get_by_minor(to_platform_device(d)->id); + + return sprintf(buf, "%d\n", pwm_dev->regs->ph1d); +} +static ssize_t +duty_write(struct device *d, struct device_attribute *a, const char *buf + , size_t count) +{ + struct pwm_davinci_device *pwm_dev; + int val = 0; + + pwm_dev = pwm_dev_get_by_minor(to_platform_device(d)->id); + + if(count == 1) + val = (buf[0] - 48); + if(count == 2) + val = (buf[0] - 48) * 10 + (buf[1] - 48); + if(count == 3) + val = (buf[0] - 48) * 100 + (buf[1] - 48) * 10 + (buf[2] - 48); + + if(val < 256) + pwm_dev->regs->ph1d = val * (PWM_FREQ / 256); + else + pwm_dev->regs->ph1d = PWM_FREQ; + + return count; +} +static DEVICE_ATTR(duty, S_IRUGO | S_IWUSR, duty_read, duty_write); + +static void create_sysfs_entries(struct device *dev) +{ + int status; + status = device_create_file(dev, &dev_attr_control); + status = device_create_file(dev, &dev_attr_duty); +} +static void remove_sysfs_entries(struct device *dev) +{ + device_remove_file(dev, &dev_attr_control); + device_remove_file(dev, &dev_attr_duty); +} + static int __init pwm_init(void) { int result; @@ -454,6 +541,8 @@ static int __init pwm_init(void) pwm_dev_array[j]->regs = (davinci_pwmregsovly) IO_ADDRESS(DAVINCI_PWM0_BASE + j * 0x400); + pwm_dev_array[j]->running = 0; + create_sysfs_entries(&pwm_device[j].dev); } } return 0; @@ -467,6 +556,7 @@ static void __exit pwm_exit(void) if (pwm_class != NULL) { size = pwm_device_count * pwm_minor_count; for (i = 0; i < size; i++) { + remove_sysfs_entries(&pwm_device[i].dev); platform_device_unregister(&pwm_device[i]); driver_unregister(&pwm_driver[i]); devno = MKDEV(pwm_major, pwm_minor_start + i); @@ -489,6 +579,7 @@ static void __exit pwm_exit(void) size = pwm_device_count * pwm_minor_count; unregister_chrdev_region(devno, size); } + } module_init(pwm_init); -- 1.5.6 _______________________________________________ Davinci-linux-open-source mailing list Davinci-linux-open-source@linux.davincidsp.com http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source