From patchwork Wed Sep 8 10:16:55 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sugumar Natarajan X-Patchwork-Id: 163431 Received: from bear.ext.ti.com (bear.ext.ti.com [192.94.94.41]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o88AmkhW016090 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 8 Sep 2010 10:49:22 GMT Received: from dlep33.itg.ti.com ([157.170.170.112]) by bear.ext.ti.com (8.13.7/8.13.7) with ESMTP id o88AmkbD015724 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Wed, 8 Sep 2010 05:48:46 -0500 Received: from linux.omap.com (localhost [127.0.0.1]) by dlep33.itg.ti.com (8.13.7/8.13.7) with ESMTP id o88AmjXx026930 for ; Wed, 8 Sep 2010 05:48:45 -0500 (CDT) Received: from linux.omap.com (localhost [127.0.0.1]) by linux.omap.com (Postfix) with ESMTP id 57F4B8062B for ; Wed, 8 Sep 2010 05:48:44 -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 CDFCE80626 for ; Wed, 8 Sep 2010 05:48:34 -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 o88AmWS6005141 for ; Wed, 8 Sep 2010 05:48:33 -0500 (CDT) Received: from symphonyindia.ti.com (symphony-ftp [192.168.247.11]) by tidmzi-ftp.india.ext.ti.com (Postfix) with SMTP id 934733887A for ; Wed, 8 Sep 2010 16:18:29 +0530 (IST) Received: from localhost.localdomain ([192.168.247.76]) by symphonyindia.ti.com (8.13.1/8.12.10) with ESMTP id o88AfOn8029572; Wed, 8 Sep 2010 16:11:24 +0530 From: Sugumar Natarajan To: davinci-linux-open-source@linux.davincidsp.com Subject: [PATCH v2 2/2] davinci: da850: eCAP driver for PWM signal generation Date: Wed, 8 Sep 2010 15:46:55 +0530 Message-Id: <1283941015-22153-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+patchwork-davinci=patchwork.kernel.org@linux.davincidsp.com Errors-To: davinci-linux-open-source-bounces+patchwork-davinci=patchwork.kernel.org@linux.davincidsp.com X-Greylist: Sender succeeded STARTTLS authentication, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Wed, 08 Sep 2010 10:49:23 +0000 (UTC) diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 9aca60c..8192866 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,14 @@ config DAVINCI_RESET_CLOCKS probably do not want this option enabled until your device drivers work properly. +config DAVINCI_ECAP_PWM + bool "eCAP driver support for PWM control" + depends on ARCH_DAVINCI_DA8XX + depends on HAVE_PWM + default n + help + Say Y to select the eCAP module for PWM control. + 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..5127174 --- /dev/null +++ b/arch/arm/mach-davinci/ecap.c @@ -0,0 +1,155 @@ +/* + * 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_3_REG 0x10 +#define CAPTURE_4_REG 0x14 +#define CAPTURE_CTRL2_REG 0x2A + +#define ECAP_CTRL2_APWMPOLL BIT(10) +#define ECAP_CTRL2_MODESL BIT(9) +#define ECAP_CTRL2_SWSYNC BIT(8) +#define ECAP_CTRL2_SYNCO_SEL (BIT(7) | BIT(6)) +#define ECAP_CTRL2_SYNCI_EN BIT(5) +#define ECAP_CTRL2_TSCTRSTOP BIT(4) + +/* + * ecap_config_pwm - configures the eCAP Module for the PWM output with given + * period and duty cycle. + */ + +static void ecap_config_pwm(struct pwm_device *pwm, unsigned int period_cycles, + unsigned int duty_cycle) +{ + __raw_writew(ECAP_CTRL2_MODESL | ECAP_CTRL2_SYNCO_SEL | + ECAP_CTRL2_TSCTRSTOP, pwm->mmio_base + CAPTURE_CTRL2_REG); + __raw_writel(period_cycles, pwm->mmio_base + CAPTURE_3_REG); + + /* 100% duty cycle is obtained when the duty cycle value is one + * greater than period ie duty cycle = period + 1 + */ + if (duty_cycle == period_cycles) + duty_cycle = duty_cycle + 1; + + __raw_writel(duty_cycle, 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) { + 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) { + dev_err(&pdev->dev, "no memory resource defined\n"); + ret = -ENODEV; + goto err_free_clk; + } + + r = request_mem_region(r->start, resource_size(r), pdev->name); + if (!r) { + dev_err(&pdev->dev, "failed to request memory resource\n"); + ret = -EBUSY; + goto err_free_clk; + } + + pwm->mmio_base = ioremap(r->start, resource_size(r)); + if (!pwm->mmio_base) { + dev_err(&pdev->dev, "failed to ioremap() registers\n"); + ret = -ENODEV; + goto err_free_mem; + } + + clk_enable(pwm->clk); + pwm_add(pwm); + platform_set_drvdata(pdev, pwm); + return 0; + +err_free_mem: + release_mem_region(r->start, resource_size(r)); +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; + struct resource *r; + + pwm = platform_get_drvdata(pdev); + if (!pwm) + return -ENODEV; + + pwm_remove(pwm); + iounmap(pwm->mmio_base); + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(r->start, resource_size(r)); + 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 ba2720b..9778a15 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; };