From patchwork Tue Sep 7 06:38:04 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sugumar Natarajan X-Patchwork-Id: 160001 Received: from devils.ext.ti.com (devils.ext.ti.com [198.47.26.153]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o877BgqP005586 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 7 Sep 2010 07:12:18 GMT Received: from dlep35.itg.ti.com ([157.170.170.118]) by devils.ext.ti.com (8.13.7/8.13.7) with ESMTP id o8779R1d022729 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Tue, 7 Sep 2010 02:09:27 -0500 Received: from linux.omap.com (localhost [127.0.0.1]) by dlep35.itg.ti.com (8.13.7/8.13.7) with ESMTP id o8779R0D022857; Tue, 7 Sep 2010 02:09:27 -0500 (CDT) Received: from linux.omap.com (localhost [127.0.0.1]) by linux.omap.com (Postfix) with ESMTP id 14CFA80627; Tue, 7 Sep 2010 02:09:27 -0500 (CDT) X-Original-To: davinci-linux-open-source@linux.davincidsp.com Delivered-To: davinci-linux-open-source@linux.davincidsp.com Received: from dflp53.itg.ti.com (dflp53.itg.ti.com [128.247.5.6]) by linux.omap.com (Postfix) with ESMTP id A5EE380626 for ; Tue, 7 Sep 2010 02:09:25 -0500 (CDT) Received: from tidmzi-ftp.india.ext.ti.com (localhost [127.0.0.1]) by dflp53.itg.ti.com (8.13.8/8.13.8) with SMTP id o8779NGP010207 for ; Tue, 7 Sep 2010 02:09:24 -0500 (CDT) Received: from symphonyindia.ti.com (symphony-ftp [192.168.247.11]) by tidmzi-ftp.india.ext.ti.com (Postfix) with SMTP id C06833887A for ; Tue, 7 Sep 2010 12:39:20 +0530 (IST) Received: from localhost.localdomain ([192.168.247.76]) by symphonyindia.ti.com (8.13.1/8.12.10) with ESMTP id o8772EBU008915; Tue, 7 Sep 2010 12:32:14 +0530 From: Sugumar Natarajan To: davinci-linux-open-source@linux.davincidsp.com Subject: [PATCH 2/2] DA850/OMAPL138: eCAP driver support for PWM signal generation Date: Tue, 7 Sep 2010 12:08:04 +0530 Message-Id: <1283841484-27121-1-git-send-email-sugumar@ti.com> X-Mailer: git-send-email 1.5.6 X-BeenThere: davinci-linux-open-source@linux.davincidsp.com X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: davinci-linux-open-source-bounces@linux.davincidsp.com Errors-To: davinci-linux-open-source-bounces@linux.davincidsp.com X-Greylist: Sender succeeded STARTTLS authentication, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Tue, 07 Sep 2010 07:12:18 +0000 (UTC) diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 9aca60c..3e821b4 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -40,6 +40,7 @@ config ARCH_DAVINCI_DA850 select CP_INTC select ARCH_DAVINCI_DA8XX select ARCH_HAS_CPUFREQ + select HAVE_PWM config ARCH_DAVINCI_DA8XX select CPU_ARM926T @@ -230,6 +231,12 @@ config DAVINCI_RESET_CLOCKS probably do not want this option enabled until your device drivers work properly. +config DAVINCI_ECAP_PWM + bool + depends on ARCH_DAVINCI_DA8XX + depends on HAVE_PWM + default y + endmenu endif diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 90ca821..90bd88e 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -42,3 +42,6 @@ obj-$(CONFIG_SUSPEND) += pm.o sleep.o # Generic PWM control support obj-$(CONFIG_HAVE_PWM) += davinci_pwm.o + +# eCAP driver support for PWM +obj-$(CONFIG_DAVINCI_ECAP_PWM) += ecap.o diff --git a/arch/arm/mach-davinci/ecap.c b/arch/arm/mach-davinci/ecap.c new file mode 100644 index 0000000..7032009 --- /dev/null +++ b/arch/arm/mach-davinci/ecap.c @@ -0,0 +1,131 @@ +/* + * DA850/OMAP-L138 eCAP driver for PWM output generation + * + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CAPTURE_1_REG 0x8 +#define CAPTURE_2_REG 0xC +#define CAPTURE_3_REG 0x10 +#define CAPTURE_4_REG 0x14 +#define CAPTURE_CTRL2_REG 0x2A +#define PWM_CONFIG 0x290 + +/* + * ecap_config_pwm - configures the eCAP Module for the PWM output with given + * period and duty cycle. + * + * Maximum brightness is obtained when the duty cycle value is one greater than + * period ie duty cycle >= period + 1 + * + */ + +static void ecap_config_pwm(struct pwm_device *pwm, unsigned int period_cycles, + unsigned int duty_cycle) +{ + __raw_writew(PWM_CONFIG, pwm->mmio_base + CAPTURE_CTRL2_REG); + __raw_writel(period_cycles, pwm->mmio_base + CAPTURE_3_REG); + __raw_writel(duty_cycle + 1, pwm->mmio_base + CAPTURE_4_REG); +} + +static int __devinit ecap_probe(struct platform_device *pdev) +{ + struct pwm_device *pwm = NULL; + struct resource *r; + int ret = 0; + + pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL); + if (pwm == NULL) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + pwm->clk = clk_get(&pdev->dev, "ecap"); + if (IS_ERR(pwm->clk)) { + ret = PTR_ERR(pwm->clk); + goto err_free; + } + + pwm->pwm_id = pdev->id; + pwm->pdev = pdev; + pwm->pwm_config_device = ecap_config_pwm; + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (r == NULL) { + dev_err(&pdev->dev, "no memory resource defined\n"); + ret = -ENODEV; + goto err_free_clk; + } + + pwm->mmio_base = ioremap(r->start, resource_size(r)); + if (pwm->mmio_base == NULL) { + dev_err(&pdev->dev, "failed to ioremap() registers\n"); + ret = -ENODEV; + goto err_free_clk; + } + + clk_enable(pwm->clk); + add_pwm(pwm); + platform_set_drvdata(pdev, pwm); + return 0; + +err_free_clk: + clk_put(pwm->clk); +err_free: + kfree(pwm); + return ret; +} + +static int __devexit ecap_remove(struct platform_device *pdev) +{ + struct pwm_device *pwm; + + pwm = platform_get_drvdata(pdev); + remove_pwm(pwm); + iounmap(pwm->mmio_base); + clk_put(pwm->clk); + kfree(pwm); + return 0; +} + +static struct platform_driver ecap_driver = { + .driver = { + .name = "ecap", + .owner = THIS_MODULE, + }, + .probe = ecap_probe, + .remove = __devexit_p(ecap_remove), +}; + +static int __init ecap_init(void) +{ + return platform_driver_register(&ecap_driver); +} + +static void __exit ecap_exit(void) +{ + platform_driver_unregister(&ecap_driver); +} + +module_init(ecap_init); +module_exit(ecap_exit); + +MODULE_LICENSE("GPL v2"); diff --git a/arch/arm/mach-davinci/include/mach/davinci_pwm.h b/arch/arm/mach-davinci/include/mach/davinci_pwm.h index b89e823..9f66ae7 100644 --- a/arch/arm/mach-davinci/include/mach/davinci_pwm.h +++ b/arch/arm/mach-davinci/include/mach/davinci_pwm.h @@ -22,6 +22,7 @@ struct pwm_device { unsigned int period, unsigned int dutycycle); const char *label; struct clk *clk; + void __iomem *mmio_base; unsigned int use_count; unsigned int pwm_id; };