* [PATCH] drivers/mtd: fix mtdraw write support @ 2012-01-26 19:55 Robert Jarzmik 2012-01-26 19:55 ` [PATCH] drivers/mtd: fix docg3 " Robert Jarzmik ` (3 more replies) 0 siblings, 4 replies; 8+ messages in thread From: Robert Jarzmik @ 2012-01-26 19:55 UTC (permalink / raw) To: barebox When unaligned writes are used, typically doing a cp file /dev/mtdraw0.foo, the alignement correction code was incorrectly handling such cases, and didn't return the expected number of written bytes. This was tested on a 528 block size. Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr> --- This fix applies to branch master and next. --- drivers/mtd/mtdraw.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/mtdraw.c b/drivers/mtd/mtdraw.c index b1cce3d..7abe235 100644 --- a/drivers/mtd/mtdraw.c +++ b/drivers/mtd/mtdraw.c @@ -191,8 +191,9 @@ static ssize_t mtdraw_write(struct cdev *cdev, const void *buf, size_t count, } if (mtdraw->write_fill == bsz) { - ret = mtdraw_blkwrite(mtd, mtdraw->writebuf, mtdraw->write_ofs); - retlen += ret; + numpage = mtdraw->write_ofs / (mtd->writesize + mtd->oobsize); + ret = mtdraw_blkwrite(mtd, mtdraw->writebuf, + mtd->writesize * numpage); mtdraw->write_fill = 0; } @@ -208,6 +209,7 @@ static ssize_t mtdraw_write(struct cdev *cdev, const void *buf, size_t count, if (ret >= 0 && count) { mtdraw->write_ofs = offset - mtdraw->write_fill; mtdraw_fillbuf(mtdraw, buf + retlen, count); + retlen += count; } if (ret < 0) { -- 1.7.5.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH] drivers/mtd: fix docg3 write support 2012-01-26 19:55 [PATCH] drivers/mtd: fix mtdraw write support Robert Jarzmik @ 2012-01-26 19:55 ` Robert Jarzmik 2012-01-26 19:55 ` [PATCH] arm/mach-pxa: add standard LCD panel GPIO settings Robert Jarzmik ` (2 subsequent siblings) 3 siblings, 0 replies; 8+ messages in thread From: Robert Jarzmik @ 2012-01-26 19:55 UTC (permalink / raw) To: barebox Fix typo error in MTD_WRITE defines. Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr> --- This fix applies to branches master and next. --- drivers/mtd/devices/docg3.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c index f7e33dc..88d707c 100644 --- a/drivers/mtd/devices/docg3.c +++ b/drivers/mtd/devices/docg3.c @@ -614,7 +614,7 @@ static int doc_block_isbad(struct mtd_info *mtd, loff_t from) return !is_good; } -#ifdef MTD_WRITE +#ifdef CONFIG_MTD_WRITE static int doc_guess_autoecc(struct mtd_oob_ops *ops) { int autoecc; @@ -1065,7 +1065,7 @@ static void __init doc_set_driver_info(int chip_id, struct mtd_info *mtd) mtd->read = doc_read; mtd->read_oob = doc_read_oob; mtd->block_isbad = doc_block_isbad; -#ifdef MTD_WRITE +#ifdef CONFIG_MTD_WRITE mtd->erase = doc_erase; mtd->write = doc_write; mtd->write_oob = doc_write_oob; -- 1.7.5.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH] arm/mach-pxa: add standard LCD panel GPIO settings 2012-01-26 19:55 [PATCH] drivers/mtd: fix mtdraw write support Robert Jarzmik 2012-01-26 19:55 ` [PATCH] drivers/mtd: fix docg3 " Robert Jarzmik @ 2012-01-26 19:55 ` Robert Jarzmik 2012-01-26 19:55 ` [PATCH] arm/mach-pxa: add CCCR bits definitions Robert Jarzmik 2012-01-26 19:55 ` [PATCH] arm/mach-pxa: add pulse width modulator controller Robert Jarzmik 3 siblings, 0 replies; 8+ messages in thread From: Robert Jarzmik @ 2012-01-26 19:55 UTC (permalink / raw) To: barebox Add standard GPIO routings for LCD panels, taken from linux kernel. Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr> --- arch/arm/mach-pxa/include/mach/mfp-pxa27x.h | 32 +++++++++++++++++++++++++++ 1 files changed, 32 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h index 6543c05..f6a27a2 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h @@ -434,5 +434,37 @@ #define GPIO112_nMSINS MFP_CFG_IN(GPIO112, AF2) #define GPIO32_MSSCLK MFP_CFG_OUT(GPIO32, AF1, DRIVE_LOW) +/* commonly used pin configurations */ +#define GPIOxx_LCD_16BPP \ + GPIO58_LCD_LDD_0, \ + GPIO59_LCD_LDD_1, \ + GPIO60_LCD_LDD_2, \ + GPIO61_LCD_LDD_3, \ + GPIO62_LCD_LDD_4, \ + GPIO63_LCD_LDD_5, \ + GPIO64_LCD_LDD_6, \ + GPIO65_LCD_LDD_7, \ + GPIO66_LCD_LDD_8, \ + GPIO67_LCD_LDD_9, \ + GPIO68_LCD_LDD_10, \ + GPIO69_LCD_LDD_11, \ + GPIO70_LCD_LDD_12, \ + GPIO71_LCD_LDD_13, \ + GPIO72_LCD_LDD_14, \ + GPIO73_LCD_LDD_15 + +#define GPIOxx_LCD_DSTN_16BPP \ + GPIOxx_LCD_16BPP, \ + GPIO74_LCD_FCLK, \ + GPIO75_LCD_LCLK, \ + GPIO76_LCD_PCLK + +#define GPIOxx_LCD_TFT_16BPP \ + GPIOxx_LCD_16BPP, \ + GPIO74_LCD_FCLK, \ + GPIO75_LCD_LCLK, \ + GPIO76_LCD_PCLK, \ + GPIO77_LCD_BIAS + extern int keypad_set_wake(unsigned int on); #endif /* __ASM_ARCH_MFP_PXA27X_H */ -- 1.7.5.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH] arm/mach-pxa: add CCCR bits definitions 2012-01-26 19:55 [PATCH] drivers/mtd: fix mtdraw write support Robert Jarzmik 2012-01-26 19:55 ` [PATCH] drivers/mtd: fix docg3 " Robert Jarzmik 2012-01-26 19:55 ` [PATCH] arm/mach-pxa: add standard LCD panel GPIO settings Robert Jarzmik @ 2012-01-26 19:55 ` Robert Jarzmik 2012-01-26 19:55 ` [PATCH] arm/mach-pxa: add pulse width modulator controller Robert Jarzmik 3 siblings, 0 replies; 8+ messages in thread From: Robert Jarzmik @ 2012-01-26 19:55 UTC (permalink / raw) To: barebox Add CCCR bits definition for PXA SoC, so that the bootloader can setup a stable core clock frequency, which is not the initial reset clock, as required by Intel's PXA27x Processor family developer's guide, chapter 3.5.5, table 3.7 (clock frequencies). Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr> --- arch/arm/mach-pxa/include/mach/pxa2xx-regs.h | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h b/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h index 4762d8a..b43648e 100644 --- a/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h +++ b/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h @@ -222,6 +222,11 @@ #define CCCR_N_MASK 0x0380 /* Run Mode Frequency to Turbo Mode Frequency Multiplier */ #define CCCR_M_MASK 0x0060 /* Memory Frequency to Run Mode Frequency Multiplier */ #define CCCR_L_MASK 0x001f /* Crystal Frequency to Memory Frequency Multiplier */ +#define CCCR_CPDIS (1 << 31) +#define CCCR_PPDIS (1 << 30) +#define CCCR_LCD26 (1 << 27) +#define CCCR_PLL_EARLY (1 << 26) +#define CCCR_A (1 << 25) #define CKEN_AC97CONF (1 << 31) /* AC97 Controller Configuration */ #define CKEN_CAMERA (1 << 24) /* Camera Interface Clock Enable */ -- 1.7.5.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH] arm/mach-pxa: add pulse width modulator controller 2012-01-26 19:55 [PATCH] drivers/mtd: fix mtdraw write support Robert Jarzmik ` (2 preceding siblings ...) 2012-01-26 19:55 ` [PATCH] arm/mach-pxa: add CCCR bits definitions Robert Jarzmik @ 2012-01-26 19:55 ` Robert Jarzmik 2012-01-27 11:42 ` Sascha Hauer 3 siblings, 1 reply; 8+ messages in thread From: Robert Jarzmik @ 2012-01-26 19:55 UTC (permalink / raw) To: barebox Add PXA embedded pulse width modulator support. The PWM can generate signals from 49.6kHz to 1.625MHz. Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr> --- arch/arm/mach-pxa/Makefile | 2 + arch/arm/mach-pxa/include/mach/clock.h | 1 + arch/arm/mach-pxa/include/mach/pwm.h | 23 ++++++++ arch/arm/mach-pxa/include/mach/regs-pwm.h | 20 +++++++ arch/arm/mach-pxa/pwm.c | 80 +++++++++++++++++++++++++++++ arch/arm/mach-pxa/speed-pxa27x.c | 5 ++ 6 files changed, 131 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-pxa/include/mach/pwm.h create mode 100644 arch/arm/mach-pxa/include/mach/regs-pwm.h create mode 100644 arch/arm/mach-pxa/pwm.c diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index c01a9e0..461b2fe 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -1,6 +1,8 @@ obj-y += clocksource.o obj-y += common.o obj-y += gpio.o +obj-y += devices.o +obj-y += pwm.o obj-$(CONFIG_ARCH_PXA2XX) += mfp-pxa2xx.o obj-$(CONFIG_ARCH_PXA27X) += speed-pxa27x.o diff --git a/arch/arm/mach-pxa/include/mach/clock.h b/arch/arm/mach-pxa/include/mach/clock.h index c53432f..f86152f 100644 --- a/arch/arm/mach-pxa/include/mach/clock.h +++ b/arch/arm/mach-pxa/include/mach/clock.h @@ -14,5 +14,6 @@ unsigned long pxa_get_uartclk(void); unsigned long pxa_get_mmcclk(void); unsigned long pxa_get_lcdclk(void); +unsigned long pxa_get_pwmclk(void); #endif /* !__MACH_CLOCK_H */ diff --git a/arch/arm/mach-pxa/include/mach/pwm.h b/arch/arm/mach-pxa/include/mach/pwm.h new file mode 100644 index 0000000..03c4f04 --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/pwm.h @@ -0,0 +1,23 @@ +/* + * (C) 2011 Robert Jarzmik <robert.jarzmik@free.fr> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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; either version 2 of + * the License, or (at your option) any later version. + * + * 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. + * + */ + +#include <mach/regs-pwm.h> + +int pwm_config(void __iomem *iobase, int duty_ns, int period_ns); +int pwm_enable(void __iomem *iobase); +void pwm_disable(void __iomem *iobase); diff --git a/arch/arm/mach-pxa/include/mach/regs-pwm.h b/arch/arm/mach-pxa/include/mach/regs-pwm.h new file mode 100644 index 0000000..cef6dcd --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/regs-pwm.h @@ -0,0 +1,20 @@ +/* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __ASM_MACH_REGS_PWM_H +#define __ASM_MACH_REGS_PWM_H + +#include <mach/hardware.h> + +/* + * Pulse modulator registers + */ +#define PWM0 0x40B00000 +#define PWM1 0x40C00000 +#define PWM2 0x40B00010 +#define PWM3 0x40C00010 + +#endif diff --git a/arch/arm/mach-pxa/pwm.c b/arch/arm/mach-pxa/pwm.c new file mode 100644 index 0000000..3750e35 --- /dev/null +++ b/arch/arm/mach-pxa/pwm.c @@ -0,0 +1,80 @@ +/* + * simple driver for PWM (Pulse Width Modulator) controller + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 2008-02-13 initial version + * eric miao <eric.miao@marvell.com> + * 2012 Robert Jarzmik <robert.jarzmik@free.fr> + */ + +#include <common.h> +#include <errno.h> +#include <io.h> + +#include <mach/clock.h> +#include <mach/pxa-regs.h> +#include <asm-generic/div64.h> +#include <linux/compiler.h> + +/* PWM registers and bits definitions */ +#define PWMCR (0x00) +#define PWMDCR (0x04) +#define PWMPCR (0x08) + +#define PWMCR_SD (1 << 6) +#define PWMDCR_FD (1 << 10) + +/* + * period_ns = 10^9 * (PRESCALE + 1) * (PV + 1) / PWM_CLK_RATE + * duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE + * PWM_CLK_RATE = 13 MHz + */ +int pwm_config(void __iomem *iobase, int duty_ns, int period_ns) +{ + unsigned long long c; + unsigned long period_cycles, prescale, pv, dc; + + if (iobase == NULL || period_ns == 0 || duty_ns > period_ns) + return -EINVAL; + + c = pxa_get_pwmclk(); + c = c * period_ns; + do_div(c, 1000000000); + period_cycles = c; + + if (period_cycles < 1) + period_cycles = 1; + prescale = (period_cycles - 1) / 1024; + pv = period_cycles / (prescale + 1) - 1; + + if (prescale > 63) + return -EINVAL; + + if (duty_ns == period_ns) + dc = PWMDCR_FD; + else + dc = (pv + 1) * duty_ns / period_ns; + + /* NOTE: the clock to PWM has to be enabled first + * before writing to the registers + */ + __raw_writel(prescale, iobase + PWMCR); + __raw_writel(dc, iobase + PWMDCR); + __raw_writel(pv, iobase + PWMPCR); + + return 0; +} + +int pwm_enable(void __iomem *iobase) +{ + CKEN |= CKEN_PWM1 | CKEN_PWM0; + return 0; +} + +void pwm_disable(void __iomem *iobase) +{ + CKEN &= ~CKEN_PWM1 & ~CKEN_PWM0; +} diff --git a/arch/arm/mach-pxa/speed-pxa27x.c b/arch/arm/mach-pxa/speed-pxa27x.c index 534eb1d..1de034c 100644 --- a/arch/arm/mach-pxa/speed-pxa27x.c +++ b/arch/arm/mach-pxa/speed-pxa27x.c @@ -47,3 +47,8 @@ unsigned long pxa_get_lcdclk(void) { return pxa_get_lcdclk_10khz() * 10000; } + +unsigned long pxa_get_pwmclk(void) +{ + return BASE_CLK; +} -- 1.7.5.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] arm/mach-pxa: add pulse width modulator controller 2012-01-26 19:55 ` [PATCH] arm/mach-pxa: add pulse width modulator controller Robert Jarzmik @ 2012-01-27 11:42 ` Sascha Hauer 2012-01-27 16:07 ` Robert Jarzmik 0 siblings, 1 reply; 8+ messages in thread From: Sascha Hauer @ 2012-01-27 11:42 UTC (permalink / raw) To: Robert Jarzmik; +Cc: barebox On Thu, Jan 26, 2012 at 08:55:28PM +0100, Robert Jarzmik wrote: > Add PXA embedded pulse width modulator support. The PWM can > generate signals from 49.6kHz to 1.625MHz. > > Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr> > --- [...] > + > + /* NOTE: the clock to PWM has to be enabled first > + * before writing to the registers > + */ Does this mean that pwm_enable() has to be called prior to pxm_config()? I think we should rather have a real pwm API. The following Kernel patch could be easily adopted and the overhead is acceptable I think. The problem is that once we let PXA implement pwm functions we cannot support other pwms in the same binary. On i.MX for example we have dedicated PWM controllers which most people use, but some others use a pwm internal to the framebuffer controller. Sascha 8<--------------------------------------------------- PWM: add pwm framework support This patch adds framework support for PWM (pulse width modulation) devices. The is a barebone PWM API already in the kernel under include/linux/pwm.h, but it does not allow for multiple drivers as each of them implements the pwm_*() functions. There are other PWM framework patches around from Bill Gatliff. Unlike his framework this one does not change the existing API for PWMs so that this framework can act as a drop in replacement for the existing API. Why another framework? Several people argue that there should not be another framework for PWMs but they should be integrated into one of the existing frameworks like led or hwmon. Unlike these frameworks the PWM framework is agnostic to the purpose of the PWM. In fact, a PWM can drive a LED, but this makes the LED framework a user of a PWM, like already done in leds-pwm.c. The gpio framework also is not suitable for PWMs. Every gpio could be turned into a PWM using timer based toggling, but on the other hand not every PWM hardware device can be turned into a gpio due to the lack of hardware capabilities. This patch does not try to improve the PWM API yet, this could be done in subsequent patches. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Acked-by: Kurt Van Dijck <kurt.van.dijck@eia.be> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Reviewed-by: Matthias Kaehlcke <matthias@kaehlcke.net> --- Documentation/pwm.txt | 56 +++++++++++++ MAINTAINERS | 6 ++ drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/pwm/Kconfig | 12 +++ drivers/pwm/Makefile | 1 + drivers/pwm/core.c | 220 +++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/pwm.h | 37 ++++++++ 8 files changed, 335 insertions(+), 0 deletions(-) create mode 100644 Documentation/pwm.txt create mode 100644 drivers/pwm/Kconfig create mode 100644 drivers/pwm/Makefile create mode 100644 drivers/pwm/core.c diff --git a/Documentation/pwm.txt b/Documentation/pwm.txt new file mode 100644 index 0000000..c7c5cb1 --- /dev/null +++ b/Documentation/pwm.txt @@ -0,0 +1,56 @@ +Pulse Width Modulation (PWM) interface + +This provides an overview about the Linux PWM interface + +PWMs are commonly used for controlling LEDs, fans or vibrators in +cell phones. PWMs with a fixed purpose have no need implementing +the Linux PWM API (although they could). However, PWMs are often +found as discrete devices on SoCs which have no fixed purpose. It's +up to the board designer to connect them to LEDs or fans. To provide +this kind of flexibility the generic PWM API exists. + +Identifying PWMs +---------------- + +PWMs are identified by unique ids throughout the system. A platform +should call pwmchip_reserve() during init time to reserve the id range +for internal PWMs so that users have a fixed id to refer to specific +PWMs. + +Using PWMs +---------- + +A PWM can be requested using pwm_request() and freed after usage with +pwm_free(). After being requested a PWM has to be configured using + +int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns); + +To start/stop toggling the PWM output use pwm_enable()/pwm_disable(). + +Implementing a PWM driver +------------------------- + +Currently there are two ways to implement pwm drivers. Traditionally +there only has been the barebone API meaning that each driver has +to implement the pwm_*() functions itself. This means that it's impossible +to have multiple PWM drivers in the system. For this reason it's mandatory +for new drivers to use the generic PWM framework. +A new PWM device can be added using pwmchip_add() and removed again with +pwmchip_remove(). pwmchip_add() takes a filled in struct pwm_chip as +argument which provides the ops and the pwm id to the framework. + +Locking +------- + +The PWM core list manipulations are protected by a mutex, so pwm_request() +and pwm_free() may not be called from an atomic context. Currently the +PWM core does not enforce any locking to pwm_enable(), pwm_disable() and +pwm_config(), so the calling context is currently driver specific. This +is an issue derived from the former barebone API and should be fixed soon. + +Helpers +------- + +Currently a PWM can only be configured with period_ns and duty_ns. For several +use cases freq_hz and duty_percent might be better. Instead of calculating +this in your driver please consider adding appropriate helpers to the framework. diff --git a/MAINTAINERS b/MAINTAINERS index 6185d05..d7bc359 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5187,6 +5187,12 @@ S: Maintained F: Documentation/video4linux/README.pvrusb2 F: drivers/media/video/pvrusb2/ +PPWM core +M: Sascha Hauer <s.hauer@pengutronix.de> +L: linux-kernel@vger.kernel.org +S: Maintained +F: drivers/pwm/ + PXA2xx/PXA3xx SUPPORT M: Eric Miao <eric.y.miao@gmail.com> M: Russell King <linux@arm.linux.org.uk> diff --git a/drivers/Kconfig b/drivers/Kconfig index 95b9e7e..9895125 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -130,4 +130,6 @@ source "drivers/iommu/Kconfig" source "drivers/virt/Kconfig" +source "drivers/pwm/Kconfig" + endmenu diff --git a/drivers/Makefile b/drivers/Makefile index 7fa433a..0581600 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -6,6 +6,7 @@ # obj-y += gpio/ +obj-y += pwm/ obj-$(CONFIG_PCI) += pci/ obj-$(CONFIG_PARISC) += parisc/ obj-$(CONFIG_RAPIDIO) += rapidio/ diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig new file mode 100644 index 0000000..93c1052 --- /dev/null +++ b/drivers/pwm/Kconfig @@ -0,0 +1,12 @@ +menuconfig PWM + bool "PWM Support" + help + This enables PWM support through the generic PWM framework. + You only need to enable this, if you also want to enable + one or more of the PWM drivers below. + + If unsure, say N. + +if PWM + +endif diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile new file mode 100644 index 0000000..3469c3d --- /dev/null +++ b/drivers/pwm/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_PWM) += core.o diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c new file mode 100644 index 0000000..71de479 --- /dev/null +++ b/drivers/pwm/core.c @@ -0,0 +1,220 @@ +/* + * Generic pwmlib implementation + * + * Copyright (C) 2011 Sascha Hauer <s.hauer@pengutronix.de> + * + * 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; either version 2, or (at your option) + * any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <linux/module.h> +#include <linux/pwm.h> +#include <linux/list.h> +#include <linux/mutex.h> +#include <linux/err.h> +#include <linux/slab.h> +#include <linux/device.h> + +struct pwm_device { + struct pwm_chip *chip; + const char *label; + unsigned long flags; +#define FLAG_REQUESTED 0 +#define FLAG_ENABLED 1 + struct list_head node; +}; + +static LIST_HEAD(pwm_list); + +static DEFINE_MUTEX(pwm_lock); + +static struct pwm_device *_find_pwm(int pwm_id) +{ + struct pwm_device *pwm; + + list_for_each_entry(pwm, &pwm_list, node) { + if (pwm->chip->pwm_id == pwm_id) + return pwm; + } + + return NULL; +} + +/** + * pwmchip_add() - register a new pwm + * @chip: the pwm + * + * register a new pwm. pwm->pwm_id must be initialized. if pwm_id < 0 then + * a dynamically assigned id will be used, otherwise the id specified, + */ +int pwmchip_add(struct pwm_chip *chip) +{ + struct pwm_device *pwm; + int ret = 0; + + pwm = kzalloc(sizeof(*pwm), GFP_KERNEL); + if (!pwm) + return -ENOMEM; + + pwm->chip = chip; + + mutex_lock(&pwm_lock); + + if (chip->pwm_id >= 0 && _find_pwm(chip->pwm_id)) { + ret = -EBUSY; + goto out; + } + + list_add_tail(&pwm->node, &pwm_list); +out: + mutex_unlock(&pwm_lock); + + if (ret) + kfree(pwm); + + return ret; +} +EXPORT_SYMBOL_GPL(pwmchip_add); + +/** + * pwmchip_remove() - remove a pwm + * @chip: the pwm + * + * remove a pwm. This function may return busy if the pwm is still requested. + */ +int pwmchip_remove(struct pwm_chip *chip) +{ + struct pwm_device *pwm; + int ret = 0; + + mutex_lock(&pwm_lock); + + pwm = _find_pwm(chip->pwm_id); + if (!pwm) { + ret = -ENOENT; + goto out; + } + + if (test_bit(FLAG_REQUESTED, &pwm->flags)) { + ret = -EBUSY; + goto out; + } + + list_del(&pwm->node); + + kfree(pwm); +out: + mutex_unlock(&pwm_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(pwmchip_remove); + +/* + * pwm_request - request a PWM device + */ +struct pwm_device *pwm_request(int pwm_id, const char *label) +{ + struct pwm_device *pwm; + int ret; + + mutex_lock(&pwm_lock); + + pwm = _find_pwm(pwm_id); + if (!pwm) { + pwm = ERR_PTR(-ENOENT); + goto out; + } + + if (test_bit(FLAG_REQUESTED, &pwm->flags)) { + pwm = ERR_PTR(-EBUSY); + goto out; + } + + if (!try_module_get(pwm->chip->ops->owner)) { + pwm = ERR_PTR(-ENODEV); + goto out; + } + + if (pwm->chip->ops->request) { + ret = pwm->chip->ops->request(pwm->chip); + if (ret) { + pwm = ERR_PTR(ret); + goto out_put; + } + } + + pwm->label = label; + set_bit(FLAG_REQUESTED, &pwm->flags); + + goto out; + +out_put: + module_put(pwm->chip->ops->owner); +out: + mutex_unlock(&pwm_lock); + + return pwm; +} +EXPORT_SYMBOL_GPL(pwm_request); + +/* + * pwm_free - free a PWM device + */ +void pwm_free(struct pwm_device *pwm) +{ + mutex_lock(&pwm_lock); + + if (!test_and_clear_bit(FLAG_REQUESTED, &pwm->flags)) { + pr_warning("PWM device already freed\n"); + goto out; + } + + pwm->label = NULL; + + module_put(pwm->chip->ops->owner); +out: + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL_GPL(pwm_free); + +/* + * pwm_config - change a PWM device configuration + */ +int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) +{ + return pwm->chip->ops->config(pwm->chip, duty_ns, period_ns); +} +EXPORT_SYMBOL_GPL(pwm_config); + +/* + * pwm_enable - start a PWM output toggling + */ +int pwm_enable(struct pwm_device *pwm) +{ + if (!test_and_set_bit(FLAG_ENABLED, &pwm->flags)) + return pwm->chip->ops->enable(pwm->chip); + + return 0; +} +EXPORT_SYMBOL_GPL(pwm_enable); + +/* + * pwm_disable - stop a PWM output toggling + */ +void pwm_disable(struct pwm_device *pwm) +{ + if (test_and_clear_bit(FLAG_ENABLED, &pwm->flags)) + pwm->chip->ops->disable(pwm->chip); +} +EXPORT_SYMBOL_GPL(pwm_disable); diff --git a/include/linux/pwm.h b/include/linux/pwm.h index 7c77575..df9681b 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -28,4 +28,41 @@ int pwm_enable(struct pwm_device *pwm); */ void pwm_disable(struct pwm_device *pwm); +#ifdef CONFIG_PWM +struct pwm_chip; + +/** + * struct pwm_ops - PWM operations + * @request: optional hook for requesting a PWM + * @free: optional hook for freeing a PWM + * @config: configure duty cycles and period length for this PWM + * @enable: enable PWM output toggling + * @disable: disable PWM output toggling + */ +struct pwm_ops { + int (*request)(struct pwm_chip *chip); + void (*free)(struct pwm_chip *chip); + int (*config)(struct pwm_chip *chip, int duty_ns, + int period_ns); + int (*enable)(struct pwm_chip *chip); + void (*disable)(struct pwm_chip *chip); + struct module *owner; +}; + +/** + * struct pwm_chip - abstract a PWM + * @label: for diagnostics + * @owner: helps prevent removal of modules exporting active PWMs + * @ops: The callbacks for this PWM + */ +struct pwm_chip { + int pwm_id; + const char *label; + struct pwm_ops *ops; +}; + +int pwmchip_add(struct pwm_chip *chip); +int pwmchip_remove(struct pwm_chip *chip); +#endif + #endif /* __LINUX_PWM_H */ -- 1.7.8.3 -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] arm/mach-pxa: add pulse width modulator controller 2012-01-27 11:42 ` Sascha Hauer @ 2012-01-27 16:07 ` Robert Jarzmik 2012-01-31 9:37 ` Sascha Hauer 0 siblings, 1 reply; 8+ messages in thread From: Robert Jarzmik @ 2012-01-27 16:07 UTC (permalink / raw) To: Sascha Hauer; +Cc: barebox Sascha Hauer <s.hauer@pengutronix.de> writes: > On Thu, Jan 26, 2012 at 08:55:28PM +0100, Robert Jarzmik wrote: >> Add PXA embedded pulse width modulator support. The PWM can >> generate signals from 49.6kHz to 1.625MHz. >> >> Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr> >> --- > > [...] > >> + >> + /* NOTE: the clock to PWM has to be enabled first >> + * before writing to the registers >> + */ > > Does this mean that pwm_enable() has to be called prior to pxm_config()? Yes. > I think we should rather have a real pwm API. So do I. > The following Kernel patch could be easily adopted and the overhead is > acceptable I think. Would you adapt it or do you want me to do it ? > The problem is that once we let PXA implement pwm functions we cannot support > other pwms in the same binary. On i.MX for example we have dedicated PWM > controllers which most people use, but some others use a pwm internal to the > framebuffer controller. True. That's a good reason to have your framework implemented. I don't think the rework of my patch on top of the framework will take me a lot of time. Cheers. -- Robert _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] arm/mach-pxa: add pulse width modulator controller 2012-01-27 16:07 ` Robert Jarzmik @ 2012-01-31 9:37 ` Sascha Hauer 0 siblings, 0 replies; 8+ messages in thread From: Sascha Hauer @ 2012-01-31 9:37 UTC (permalink / raw) To: Robert Jarzmik; +Cc: barebox On Fri, Jan 27, 2012 at 05:07:04PM +0100, Robert Jarzmik wrote: > Sascha Hauer <s.hauer@pengutronix.de> writes: > > > On Thu, Jan 26, 2012 at 08:55:28PM +0100, Robert Jarzmik wrote: > >> Add PXA embedded pulse width modulator support. The PWM can > >> generate signals from 49.6kHz to 1.625MHz. > >> > >> Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr> > >> --- > > > > [...] > > > >> + > >> + /* NOTE: the clock to PWM has to be enabled first > >> + * before writing to the registers > >> + */ > > > > Does this mean that pwm_enable() has to be called prior to pxm_config()? > Yes. > > > I think we should rather have a real pwm API. > So do I. > > > The following Kernel patch could be easily adopted and the overhead is > > acceptable I think. > Would you adapt it or do you want me to do it ? I just sent a patch, compile tested only. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2012-01-31 9:37 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2012-01-26 19:55 [PATCH] drivers/mtd: fix mtdraw write support Robert Jarzmik 2012-01-26 19:55 ` [PATCH] drivers/mtd: fix docg3 " Robert Jarzmik 2012-01-26 19:55 ` [PATCH] arm/mach-pxa: add standard LCD panel GPIO settings Robert Jarzmik 2012-01-26 19:55 ` [PATCH] arm/mach-pxa: add CCCR bits definitions Robert Jarzmik 2012-01-26 19:55 ` [PATCH] arm/mach-pxa: add pulse width modulator controller Robert Jarzmik 2012-01-27 11:42 ` Sascha Hauer 2012-01-27 16:07 ` Robert Jarzmik 2012-01-31 9:37 ` Sascha Hauer
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox