mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH] Add pwm core support
@ 2012-01-31  9:36 Sascha Hauer
  2012-02-01  8:20 ` Robert Jarzmik
  2012-02-01 22:42 ` [PATCH] drivers/pwm: add PXA pulse width modulator controller Robert Jarzmik
  0 siblings, 2 replies; 19+ messages in thread
From: Sascha Hauer @ 2012-01-31  9:36 UTC (permalink / raw)
  To: barebox

This patch adds framework support for PWM (pulse width modulation)
devices.
A new pwm can be registered from a hardware driver using
pwmchip_add(). It can then be requested from a client driver using
pwm_request(). A string is used as a unique identifier for the
pwms. It should usually be initialized by the hardware drivers
using dev_name(dev). The client API is the same as currently
in the Linux Kernel.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---

This patch is currently compile tested only due to the lack of
client drivers.

 drivers/Kconfig      |    2 +
 drivers/Makefile     |    1 +
 drivers/pwm/Kconfig  |   12 ++++
 drivers/pwm/Makefile |    1 +
 drivers/pwm/core.c   |  163 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/pwm.h        |   63 +++++++++++++++++++
 6 files changed, 242 insertions(+), 0 deletions(-)
 create mode 100644 drivers/pwm/Kconfig
 create mode 100644 drivers/pwm/Makefile
 create mode 100644 drivers/pwm/core.c
 create mode 100644 include/pwm.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index c4e1517..52eedd9 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -15,4 +15,6 @@ source "drivers/mfd/Kconfig"
 source "drivers/led/Kconfig"
 source "drivers/eeprom/Kconfig"
 
+source "drivers/pwm/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 592c39e..380c2f1 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -13,3 +13,4 @@ obj-y	+= clk/
 obj-y	+= mfd/
 obj-$(CONFIG_LED) += led/
 obj-y	+= eeprom/
+obj-$(CONFIG_PWM) += pwm/
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..af30edf
--- /dev/null
+++ b/drivers/pwm/core.c
@@ -0,0 +1,163 @@
+/*
+ * 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 <common.h>
+#include <errno.h>
+#include <malloc.h>
+#include <pwm.h>
+#include <linux/list.h>
+
+struct pwm_device {
+	struct			pwm_chip *chip;
+	unsigned long		flags;
+#define FLAG_REQUESTED	0
+#define FLAG_ENABLED	1
+	struct list_head	node;
+};
+
+static LIST_HEAD(pwm_list);
+
+static struct pwm_device *_find_pwm(const char *devname)
+{
+	struct pwm_device *pwm;
+
+	list_for_each_entry(pwm, &pwm_list, node) {
+		if (!strcmp(pwm->chip->devname, devname))
+			return pwm;
+	}
+
+	return NULL;
+}
+
+/**
+ * pwmchip_add() - register a new pwm
+ * @chip: the pwm
+ *
+ * register a new pwm. pwm->devname must be initialized, usually
+ * from dev_name(dev) from the hardware driver.
+ */
+int pwmchip_add(struct pwm_chip *chip)
+{
+	struct pwm_device *pwm;
+	int ret = 0;
+
+	if (_find_pwm(chip->devname))
+		return -EBUSY;
+
+	pwm = xzalloc(sizeof(*pwm));
+	pwm->chip = chip;
+
+	list_add_tail(&pwm->node, &pwm_list);
+
+	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;
+
+	pwm = _find_pwm(chip->devname);
+	if (!pwm)
+		return -ENOENT;
+
+	if (test_bit(FLAG_REQUESTED, &pwm->flags))
+		return -EBUSY;
+
+	list_del(&pwm->node);
+
+	kfree(pwm);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pwmchip_remove);
+
+/*
+ * pwm_request - request a PWM device
+ */
+struct pwm_device *pwm_request(const char *devname)
+{
+	struct pwm_device *pwm;
+	int ret;
+
+	pwm = _find_pwm(devname);
+	if (!pwm)
+		return NULL;
+
+	if (test_bit(FLAG_REQUESTED, &pwm->flags))
+		return NULL;
+
+	if (pwm->chip->ops->request) {
+		ret = pwm->chip->ops->request(pwm->chip);
+		if (ret)
+			return NULL;
+	}
+
+	set_bit(FLAG_REQUESTED, &pwm->flags);
+
+	return pwm;
+}
+EXPORT_SYMBOL_GPL(pwm_request);
+
+/*
+ * pwm_free - free a PWM device
+ */
+void pwm_free(struct pwm_device *pwm)
+{
+	if (!test_and_clear_bit(FLAG_REQUESTED, &pwm->flags))
+		return;
+}
+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/pwm.h b/include/pwm.h
new file mode 100644
index 0000000..80f88b1
--- /dev/null
+++ b/include/pwm.h
@@ -0,0 +1,63 @@
+#ifndef __PWM_H
+#define __PWM_H
+
+struct pwm_device;
+
+/*
+ * pwm_request - request a PWM device
+ */
+struct pwm_device *pwm_request(const char *pwmname);
+
+/*
+ * pwm_free - free a PWM device
+ */
+void pwm_free(struct pwm_device *pwm);
+
+/*
+ * pwm_config - change a PWM device configuration
+ */
+int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns);
+
+/*
+ * pwm_enable - start a PWM output toggling
+ */
+int pwm_enable(struct pwm_device *pwm);
+
+/*
+ * pwm_disable - stop a PWM output toggling
+ */
+void pwm_disable(struct pwm_device *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 pwm_chip - abstract a PWM
+ * @devname: unique identifier for this pwm
+ * @ops: The callbacks for this PWM
+ */
+struct pwm_chip {
+	const char		*devname;
+	struct pwm_ops		*ops;
+};
+
+int pwmchip_add(struct pwm_chip *chip);
+int pwmchip_remove(struct pwm_chip *chip);
+
+#endif /* __PWM_H */
-- 
1.7.8.3


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] Add pwm core support
  2012-01-31  9:36 [PATCH] Add pwm core support Sascha Hauer
@ 2012-02-01  8:20 ` Robert Jarzmik
  2012-02-01 22:42 ` [PATCH] drivers/pwm: add PXA pulse width modulator controller Robert Jarzmik
  1 sibling, 0 replies; 19+ messages in thread
From: Robert Jarzmik @ 2012-02-01  8:20 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

Sascha Hauer <s.hauer@pengutronix.de> writes:

> This patch adds framework support for PWM (pulse width modulation)
> devices.
> A new pwm can be registered from a hardware driver using
> pwmchip_add(). It can then be requested from a client driver using
> pwm_request(). A string is used as a unique identifier for the
> pwms. It should usually be initialized by the hardware drivers
> using dev_name(dev). The client API is the same as currently
> in the Linux Kernel.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>
> This patch is currently compile tested only due to the lack of
> client drivers.
You can add my :
Tested-by: Robert Jarzmik <robert.jarzmik@free.fr>

And I'll post the pxa pwm driver which I developped on top on that framework
today, with which I'm pretty sure your core works, because my screen backlight
ignites :)

Cheers.

--
Robert

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH] drivers/pwm: add PXA pulse width modulator controller
  2012-01-31  9:36 [PATCH] Add pwm core support Sascha Hauer
  2012-02-01  8:20 ` Robert Jarzmik
@ 2012-02-01 22:42 ` Robert Jarzmik
  2012-02-03  9:52   ` Sascha Hauer
  1 sibling, 1 reply; 19+ messages in thread
From: Robert Jarzmik @ 2012-02-01 22:42 UTC (permalink / raw)
  To: barebox, s.hauer

Add PXA embedded pulse width modulator support. The PWM can
generate signals from 49.6kHz to 1.625MHz.
The driver is for pxa2xx family. The pxa3xx was not handled yet.

Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
---
 arch/arm/mach-pxa/Makefile                |    1 +
 arch/arm/mach-pxa/include/mach/clock.h    |    1 +
 arch/arm/mach-pxa/include/mach/regs-pwm.h |   20 ++++
 arch/arm/mach-pxa/speed-pxa27x.c          |    5 +
 drivers/pwm/Kconfig                       |    6 +
 drivers/pwm/Makefile                      |    1 +
 drivers/pwm/pxa_pwm.c                     |  163 +++++++++++++++++++++++++++++
 7 files changed, 197 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-pxa/include/mach/regs-pwm.h
 create mode 100644 drivers/pwm/pxa_pwm.c

diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index c01a9e0..6a02a54 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -1,6 +1,7 @@
 obj-y += clocksource.o
 obj-y += common.o
 obj-y += gpio.o
+obj-y += devices.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/regs-pwm.h b/arch/arm/mach-pxa/include/mach/regs-pwm.h
new file mode 100644
index 0000000..9fdcbb6
--- /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 PWM0slave	0x40B00010
+#define PWM1slave	0x40C00010
+
+#endif
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;
+}
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 93c1052..50c956a 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -8,5 +8,11 @@ menuconfig PWM
 	  If unsure, say N.
 
 if PWM
+config PWM_PXA
+	bool "PXA PWM Support"
+	default y if ARCH_PXA2XX
+	help
+	  This enables PWM support for Intel/Marvell PXA chips, such
+	  as the PXA25x, PXA27x.
 
 endif
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 3469c3d..c886bd5 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_PWM)		+= core.o
+obj-$(CONFIG_PWM_PXA)		+= pxa_pwm.o
\ No newline at end of file
diff --git a/drivers/pwm/pxa_pwm.c b/drivers/pwm/pxa_pwm.c
new file mode 100644
index 0000000..bb114aa
--- /dev/null
+++ b/drivers/pwm/pxa_pwm.c
@@ -0,0 +1,163 @@
+/*
+ * 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 <init.h>
+#include <errno.h>
+#include <io.h>
+#include <pwm.h>
+
+#include <mach/hardware.h>
+#include <mach/clock.h>
+#include <mach/pxa-regs.h>
+#include <mach/regs-pwm.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)
+
+#ifdef CONFIG_PWM
+
+static int pwm_get_pwm_idx(struct pwm_chip *chip)
+{
+	if (!strncmp(chip->devname, "pxa_pwm0", 8))
+		return 0;
+	else if (!strncmp(chip->devname, "pxa_pwm1", 8))
+		return 1;
+	else
+		return -EINVAL;
+}
+
+static void __iomem *pwm_bases[] = {
+	(void __iomem *)PWM0,
+	(void __iomem *)PWM1,
+	(void __iomem *)PWM0slave,
+	(void __iomem *)PWM1slave,
+};
+
+/*
+ * 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
+ */
+static int pxa_pwm_config(struct pwm_chip *chip, int duty_ns, int period_ns)
+{
+	int pwm_idx;
+	unsigned long long c;
+	unsigned long period_cycles, prescale, pv, dc;
+	void __iomem *iobase;
+
+	pwm_idx = pwm_get_pwm_idx(chip);
+	if (pwm_idx < 0 || period_ns == 0 || duty_ns > period_ns)
+		return -EINVAL;
+	iobase = pwm_bases[pwm_idx];
+
+	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;
+}
+
+static int pxa_pwm_enable(struct pwm_chip *chip)
+{
+	switch (pwm_get_pwm_idx(chip)) {
+	case 0:
+		CKEN |= CKEN_PWM0;
+		break;
+	case 1:
+		CKEN |= CKEN_PWM1;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void pxa_pwm_disable(struct pwm_chip *chip)
+{
+	switch (pwm_get_pwm_idx(chip)) {
+	case 0:
+		CKEN &= ~CKEN_PWM0;
+		break;
+	case 1:
+		CKEN &= ~CKEN_PWM1;
+		break;
+	default:
+		break;
+	}
+}
+
+static struct pwm_ops pxa_pwm_ops = {
+	.config = pxa_pwm_config,
+	.enable = pxa_pwm_enable,
+	.disable = pxa_pwm_disable,
+};
+
+#define DECLARE_PXA_PWM(name) \
+	static struct pwm_chip name = { \
+	.devname = #name, \
+	.ops = &pxa_pwm_ops, \
+}
+
+DECLARE_PXA_PWM(pxa_pwm0);
+DECLARE_PXA_PWM(pxa_pwm1);
+DECLARE_PXA_PWM(pxa_pwm0slave);
+DECLARE_PXA_PWM(pxa_pwm1slave);
+
+static int pxa_pwm_init(void)
+{
+	CKEN &= ~CKEN_PWM0 & ~CKEN_PWM1;
+	pwmchip_add(&pxa_pwm0);
+	pwmchip_add(&pxa_pwm1);
+	if (cpu_is_pxa27x()) {
+		pwmchip_add(&pxa_pwm0slave);
+		pwmchip_add(&pxa_pwm1slave);
+	}
+	return 0;
+}
+
+#else
+static int pxa_pwm_init(void)
+{
+	return 0;
+}
+#endif
+
+coredevice_initcall(pxa_pwm_init);
-- 
1.7.5.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] drivers/pwm: add PXA pulse width modulator controller
  2012-02-01 22:42 ` [PATCH] drivers/pwm: add PXA pulse width modulator controller Robert Jarzmik
@ 2012-02-03  9:52   ` Sascha Hauer
  2012-02-03 15:39     ` Robert Jarzmik
  0 siblings, 1 reply; 19+ messages in thread
From: Sascha Hauer @ 2012-02-03  9:52 UTC (permalink / raw)
  To: Robert Jarzmik; +Cc: barebox

Hi Robert,

On Wed, Feb 01, 2012 at 11:42:28PM +0100, Robert Jarzmik wrote:
> Add PXA embedded pulse width modulator support. The PWM can
> generate signals from 49.6kHz to 1.625MHz.
> The driver is for pxa2xx family. The pxa3xx was not handled yet.

Why not implement it as a regular driver? If we ever want to implement
a commandline control of the pwms via pwm0.dutyns=xx we'll need
a struct device.

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] 19+ messages in thread

* Re: [PATCH] drivers/pwm: add PXA pulse width modulator controller
  2012-02-03  9:52   ` Sascha Hauer
@ 2012-02-03 15:39     ` Robert Jarzmik
  2012-02-08 15:26       ` Robert Jarzmik
  0 siblings, 1 reply; 19+ messages in thread
From: Robert Jarzmik @ 2012-02-03 15:39 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

Sascha Hauer <s.hauer@pengutronix.de> writes:

> Hi Robert,
>
> Why not implement it as a regular driver? If we ever want to implement
> a commandline control of the pwms via pwm0.dutyns=xx we'll need
> a struct device.

This is because in my own case, I need pwm to be registered before other devices
are probed. The trouble (in my case) is that for drivers/video/pxa.c, I have the
following call path :
 - pxafb_probe()
   -> pxafb_enable_controller()
     -> pxafb_backlight_power()
       -> mioa701_lcd_backlight()
          => 	struct pwm_device *pwm0 = pwm_request("pxa_pwm0");
		pwm_enable(pwm0);
		pwm_config(pwm0, 2000 * 1024, 4000 * 1024);

I'm a bit afraid that the pxafb driver will be probed first, before pwm_pxa, and
therefore the backlight setting won't work. I haven't found a clean way to
specify this dependency.

Cheers.

-- 
Robert

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] drivers/pwm: add PXA pulse width modulator controller
  2012-02-03 15:39     ` Robert Jarzmik
@ 2012-02-08 15:26       ` Robert Jarzmik
  2012-02-09  8:10         ` Sascha Hauer
  0 siblings, 1 reply; 19+ messages in thread
From: Robert Jarzmik @ 2012-02-08 15:26 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

Robert Jarzmik <robert.jarzmik@free.fr> writes:

> Sascha Hauer <s.hauer@pengutronix.de> writes:
>
>> Hi Robert,
>>
>> Why not implement it as a regular driver? If we ever want to implement
>> a commandline control of the pwms via pwm0.dutyns=xx we'll need
>> a struct device.
>
> This is because in my own case, I need pwm to be registered before other devices
> are probed. The trouble (in my case) is that for drivers/video/pxa.c, I have the
> following call path :
>  - pxafb_probe()
>    -> pxafb_enable_controller()
>      -> pxafb_backlight_power()
>        -> mioa701_lcd_backlight()
>           => 	struct pwm_device *pwm0 = pwm_request("pxa_pwm0");
> 		pwm_enable(pwm0);
> 		pwm_config(pwm0, 2000 * 1024, 4000 * 1024);
>
> I'm a bit afraid that the pxafb driver will be probed first, before pwm_pxa, and
> therefore the backlight setting won't work. I haven't found a clean way to
> specify this dependency.

Sascha, ping ?

Do you have a way to specify the dependency, and do you want me to adapt the
driver ?

Cheers.

--
Robert

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] drivers/pwm: add PXA pulse width modulator controller
  2012-02-08 15:26       ` Robert Jarzmik
@ 2012-02-09  8:10         ` Sascha Hauer
  2012-02-09 11:50           ` Robert Jarzmik
  0 siblings, 1 reply; 19+ messages in thread
From: Sascha Hauer @ 2012-02-09  8:10 UTC (permalink / raw)
  To: Robert Jarzmik; +Cc: barebox

On Wed, Feb 08, 2012 at 04:26:21PM +0100, Robert Jarzmik wrote:
> Robert Jarzmik <robert.jarzmik@free.fr> writes:
> 
> > Sascha Hauer <s.hauer@pengutronix.de> writes:
> >
> >> Hi Robert,
> >>
> >> Why not implement it as a regular driver? If we ever want to implement
> >> a commandline control of the pwms via pwm0.dutyns=xx we'll need
> >> a struct device.
> >
> > This is because in my own case, I need pwm to be registered before other devices
> > are probed. The trouble (in my case) is that for drivers/video/pxa.c, I have the
> > following call path :
> >  - pxafb_probe()
> >    -> pxafb_enable_controller()
> >      -> pxafb_backlight_power()
> >        -> mioa701_lcd_backlight()
> >           => 	struct pwm_device *pwm0 = pwm_request("pxa_pwm0");
> > 		pwm_enable(pwm0);
> > 		pwm_config(pwm0, 2000 * 1024, 4000 * 1024);
> >
> > I'm a bit afraid that the pxafb driver will be probed first, before pwm_pxa, and
> > therefore the backlight setting won't work. I haven't found a clean way to
> > specify this dependency.
> 
> Sascha, ping ?
> 
> Do you have a way to specify the dependency, and do you want me to adapt the
> driver ?

Sorry, I wanted to think about this issue and appearently forgot about
it.
So the moment has come we have the same problems as in the kernel: we
can't express the dependencies between devices. For your case I think
we can get around the problem once more.

Experience shows that the framebuffer shouldn't be enabled on
initialization time. If it does you end up with a framebuffer showing
a blank screen in the best case. Instead the framebuffer should be
enabled explicitely once there is an image on the screen which looks
much nicer to the user. That said the following should be removed from
the pxafb driver:

	if (pdata->enable_on_load)
		info->fbops->fb_enable(info);

Are you ok with that?

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] 19+ messages in thread

* Re: [PATCH] drivers/pwm: add PXA pulse width modulator controller
  2012-02-09  8:10         ` Sascha Hauer
@ 2012-02-09 11:50           ` Robert Jarzmik
  2012-02-09 13:44             ` Sascha Hauer
  2012-02-14 12:58             ` [PATCH V2 1/2] " Robert Jarzmik
  0 siblings, 2 replies; 19+ messages in thread
From: Robert Jarzmik @ 2012-02-09 11:50 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

Sascha Hauer <s.hauer@pengutronix.de> writes:
> Experience shows that the framebuffer shouldn't be enabled on
> initialization time. If it does you end up with a framebuffer showing
> a blank screen in the best case. Instead the framebuffer should be
> enabled explicitely once there is an image on the screen which looks
> much nicer to the user. That said the following should be removed from
> the pxafb driver:
>
> 	if (pdata->enable_on_load)
> 		info->fbops->fb_enable(info);
>
> Are you ok with that?
For the pxafb, yes agreed.

I still see a small issue with the PWM API.
When I register the pxa-pwm driver, I have :
 pxa_pwm_probe(struct device_d *dev)
   -> base = dev_request_mem_region(dev, 0);
   -> pxa_pwm = xzalloc(...)
   -> pxa_pwm->name = drv_name(...)
   -> pxa_pwm->ops = &pxa_pwm_ops,
   -> pwmchip_add(pxa_pwm)

As you can see, the "base" is lost, and I have no way to store it in the
pwm_chip structure.

Shouldn't the pwm_chip structure have a priv pointer ?

Cheers.

--
Robert

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] drivers/pwm: add PXA pulse width modulator controller
  2012-02-09 11:50           ` Robert Jarzmik
@ 2012-02-09 13:44             ` Sascha Hauer
  2012-02-09 14:30               ` Robert Jarzmik
  2012-02-14 12:58             ` [PATCH V2 1/2] " Robert Jarzmik
  1 sibling, 1 reply; 19+ messages in thread
From: Sascha Hauer @ 2012-02-09 13:44 UTC (permalink / raw)
  To: Robert Jarzmik; +Cc: barebox

On Thu, Feb 09, 2012 at 12:50:17PM +0100, Robert Jarzmik wrote:
> Sascha Hauer <s.hauer@pengutronix.de> writes:
> > Experience shows that the framebuffer shouldn't be enabled on
> > initialization time. If it does you end up with a framebuffer showing
> > a blank screen in the best case. Instead the framebuffer should be
> > enabled explicitely once there is an image on the screen which looks
> > much nicer to the user. That said the following should be removed from
> > the pxafb driver:
> >
> > 	if (pdata->enable_on_load)
> > 		info->fbops->fb_enable(info);
> >
> > Are you ok with that?
> For the pxafb, yes agreed.
> 
> I still see a small issue with the PWM API.
> When I register the pxa-pwm driver, I have :
>  pxa_pwm_probe(struct device_d *dev)
>    -> base = dev_request_mem_region(dev, 0);
>    -> pxa_pwm = xzalloc(...)
>    -> pxa_pwm->name = drv_name(...)
>    -> pxa_pwm->ops = &pxa_pwm_ops,
>    -> pwmchip_add(pxa_pwm)
> 
> As you can see, the "base" is lost, and I have no way to store it in the
> pwm_chip structure.
> 
> Shouldn't the pwm_chip structure have a priv pointer ?

The intention was to put a struct pwm_chip into a struct pxa_pwm_chip
and use container_of.

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] 19+ messages in thread

* Re: [PATCH] drivers/pwm: add PXA pulse width modulator controller
  2012-02-09 13:44             ` Sascha Hauer
@ 2012-02-09 14:30               ` Robert Jarzmik
  0 siblings, 0 replies; 19+ messages in thread
From: Robert Jarzmik @ 2012-02-09 14:30 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

Sascha Hauer <s.hauer@pengutronix.de> writes:

> The intention was to put a struct pwm_chip into a struct pxa_pwm_chip
> and use container_of.

Ah ok, I understand now.
I will submit a V2 of my patch soon.

Cheers.

-- 
Robert

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH V2 1/2] drivers/pwm: add PXA pulse width modulator controller
  2012-02-09 11:50           ` Robert Jarzmik
  2012-02-09 13:44             ` Sascha Hauer
@ 2012-02-14 12:58             ` Robert Jarzmik
  2012-02-14 12:58               ` [PATCH V2 2/2] drivers/video: remove pxafb enable on load Robert Jarzmik
  2012-02-15  8:32               ` [PATCH V2 1/2] drivers/pwm: add PXA pulse width modulator controller Sascha Hauer
  1 sibling, 2 replies; 19+ messages in thread
From: Robert Jarzmik @ 2012-02-14 12:58 UTC (permalink / raw)
  To: barebox

Add PXA embedded pulse width modulator support. The PWM can
generate signals from 49.6kHz to 1.625MHz.
The driver is for pxa2xx family. The pxa3xx was not handled yet.

Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
---
 arch/arm/mach-pxa/Makefile                |    1 +
 arch/arm/mach-pxa/devices.c               |    5 +
 arch/arm/mach-pxa/include/mach/clock.h    |    1 +
 arch/arm/mach-pxa/include/mach/devices.h  |    2 +-
 arch/arm/mach-pxa/include/mach/regs-pwm.h |   20 +++
 arch/arm/mach-pxa/speed-pxa27x.c          |    5 +
 drivers/pwm/Kconfig                       |    6 +
 drivers/pwm/Makefile                      |    1 +
 drivers/pwm/pxa_pwm.c                     |  219 +++++++++++++++++++++++++++++
 9 files changed, 259 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-pxa/include/mach/regs-pwm.h
 create mode 100644 drivers/pwm/pxa_pwm.c

diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index c01a9e0..6a02a54 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -1,6 +1,7 @@
 obj-y += clocksource.o
 obj-y += common.o
 obj-y += gpio.o
+obj-y += devices.o
 
 obj-$(CONFIG_ARCH_PXA2XX) += mfp-pxa2xx.o
 obj-$(CONFIG_ARCH_PXA27X) += speed-pxa27x.o
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index 1a396f1..b6ac0ba 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -47,3 +47,8 @@ struct device_d *pxa_add_mmc(void *base, int id, void *pdata)
 {
 	return pxa_add_device("pxa-mmc", id, base, 0x1000, pdata);
 }
+
+struct device_d *pxa_add_pwm(void *base, int id)
+{
+	return pxa_add_device("pxa_pwm", id, base, 0x10, NULL);
+}
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/devices.h b/arch/arm/mach-pxa/include/mach/devices.h
index e205b7c..8390153 100644
--- a/arch/arm/mach-pxa/include/mach/devices.h
+++ b/arch/arm/mach-pxa/include/mach/devices.h
@@ -23,4 +23,4 @@ struct device_d *pxa_add_i2c(void *base, int id,
 struct device_d *pxa_add_uart(void *base, int id);
 struct device_d *pxa_add_fb(void *base, struct pxafb_platform_data *pdata);
 struct device_d *pxa_add_mmc(void *base, int id, void *pdata);
-
+struct device_d *pxa_add_pwm(void *base, int id);
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..9fdcbb6
--- /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 PWM0slave	0x40B00010
+#define PWM1slave	0x40C00010
+
+#endif
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;
+}
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 93c1052..50c956a 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -8,5 +8,11 @@ menuconfig PWM
 	  If unsure, say N.
 
 if PWM
+config PWM_PXA
+	bool "PXA PWM Support"
+	default y if ARCH_PXA2XX
+	help
+	  This enables PWM support for Intel/Marvell PXA chips, such
+	  as the PXA25x, PXA27x.
 
 endif
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 3469c3d..c886bd5 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_PWM)		+= core.o
+obj-$(CONFIG_PWM_PXA)		+= pxa_pwm.o
\ No newline at end of file
diff --git a/drivers/pwm/pxa_pwm.c b/drivers/pwm/pxa_pwm.c
new file mode 100644
index 0000000..f52d675
--- /dev/null
+++ b/drivers/pwm/pxa_pwm.c
@@ -0,0 +1,219 @@
+/*
+ * 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 <init.h>
+#include <errno.h>
+#include <io.h>
+#include <pwm.h>
+
+#include <mach/hardware.h>
+#include <mach/clock.h>
+#include <mach/pxa-regs.h>
+#include <mach/regs-pwm.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)
+
+struct pxa_pwm_chip {
+	struct pwm_chip chip;
+	void __iomem *iobase;
+	int id;
+	int duty_ns;
+	int period_ns;
+};
+
+static struct pxa_pwm_chip *to_pxa_pwm_chip(struct pwm_chip *chip)
+{
+	return container_of(chip, struct pxa_pwm_chip, chip);
+}
+
+/*
+ * 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
+ */
+static int pxa_pwm_config(struct pwm_chip *chip, int duty_ns, int period_ns)
+{
+	unsigned long long c;
+	unsigned long period_cycles, prescale, pv, dc;
+	struct pxa_pwm_chip *pxa_pwm = to_pxa_pwm_chip(chip);
+
+	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;
+
+	pxa_pwm->duty_ns = duty_ns;
+	pxa_pwm->period_ns = period_ns;
+
+	/* NOTE: the clock to PWM has to be enabled first
+	 * before writing to the registers
+	 */
+	__raw_writel(prescale, pxa_pwm->iobase + PWMCR);
+	__raw_writel(dc, pxa_pwm->iobase + PWMDCR);
+	__raw_writel(pv, pxa_pwm->iobase + PWMPCR);
+
+	return 0;
+}
+
+static int pxa_pwm_enable(struct pwm_chip *chip)
+{
+	struct pxa_pwm_chip *pxa_pwm = to_pxa_pwm_chip(chip);
+
+	switch (pxa_pwm->id) {
+	case 0:
+	case 2:
+		CKEN |= CKEN_PWM0;
+		break;
+	case 1:
+	case 3:
+		CKEN |= CKEN_PWM1;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void pxa_pwm_disable(struct pwm_chip *chip)
+{
+	struct pxa_pwm_chip *pxa_pwm = to_pxa_pwm_chip(chip);
+
+	switch (pxa_pwm->id) {
+	case 0:
+	case 2:
+		CKEN &= ~CKEN_PWM0;
+		break;
+	case 1:
+	case 3:
+		CKEN &= ~CKEN_PWM1;
+		break;
+	default:
+		break;
+	}
+}
+
+static struct pwm_ops pxa_pwm_ops = {
+	.config = pxa_pwm_config,
+	.enable = pxa_pwm_enable,
+	.disable = pxa_pwm_disable,
+};
+
+static int set_period_ns(struct device_d *dev, struct param_d *p, const char *val)
+{
+	struct pxa_pwm_chip *pxa_pwm = dev->priv;
+	int period_ns;
+
+	if (!val)
+		return dev_param_set_generic(dev, p, NULL);
+
+	period_ns = simple_strtoul(val, NULL, 0);
+	pxa_pwm_config(&pxa_pwm->chip, pxa_pwm->duty_ns, period_ns);
+	return dev_param_set_generic(dev, p, val);
+}
+
+static int set_duty_ns(struct device_d *dev, struct param_d *p, const char *val)
+{
+	struct pxa_pwm_chip *pxa_pwm = dev->priv;
+	int duty_ns;
+
+	if (!val)
+		return dev_param_set_generic(dev, p, NULL);
+
+	duty_ns = simple_strtoul(val, NULL, 0);
+	pxa_pwm_config(&pxa_pwm->chip, duty_ns, pxa_pwm->period_ns);
+	return dev_param_set_generic(dev, p, val);
+}
+
+static int set_enable(struct device_d *dev, struct param_d *p, const char *val)
+{
+	struct pxa_pwm_chip *pxa_pwm = dev->priv;
+	int enable;
+
+	if (!val)
+		return dev_param_set_generic(dev, p, NULL);
+
+	enable = !!simple_strtoul(val, NULL, 0);
+	if (enable)
+		pxa_pwm_enable(&pxa_pwm->chip);
+	else
+		pxa_pwm_disable(&pxa_pwm->chip);
+	return dev_param_set_generic(dev, p, enable ? "1" : "0");
+}
+
+static int __init pxa_pwm_register_vars(struct device_d *dev,
+					struct pxa_pwm_chip *pxa_pwm)
+{
+	int ret;
+
+	ret = dev_add_param(dev, "duty_ns", set_duty_ns, NULL, 0);
+	if (!ret)
+		ret = dev_add_param(dev, "period_ns", set_period_ns, NULL, 0);
+	if (!ret)
+		ret = dev_add_param(dev, "enable", set_enable, NULL, 0);
+	if (!ret)
+		ret = dev_set_param(dev, "enable", 0);
+	return ret;
+}
+
+static int pxa_pwm_probe(struct device_d *dev)
+{
+	struct pxa_pwm_chip *chip;
+	int ret;
+
+	chip = xzalloc(sizeof(*chip));
+	chip->chip.devname = asprintf("%s", dev_name(dev));
+	chip->chip.ops = &pxa_pwm_ops;
+	chip->iobase = dev_request_mem_region(dev, 0);
+	chip->id = dev->id;
+	dev->priv = chip;
+
+	ret = pwmchip_add(&chip->chip);
+	if (!ret)
+		ret = pxa_pwm_register_vars(dev, chip);
+	return ret;
+}
+
+static struct driver_d pxa_pwm_driver = {
+	.name  = "pxa_pwm",
+	.probe = pxa_pwm_probe,
+};
+
+static int __init pxa_pwm_init_driver(void)
+{
+	CKEN &= ~CKEN_PWM0 & ~CKEN_PWM1;
+	register_driver(&pxa_pwm_driver);
+	return 0;
+}
+
+device_initcall(pxa_pwm_init_driver);
-- 
1.7.5.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH V2 2/2] drivers/video: remove pxafb enable on load
  2012-02-14 12:58             ` [PATCH V2 1/2] " Robert Jarzmik
@ 2012-02-14 12:58               ` Robert Jarzmik
  2012-02-15  8:32               ` [PATCH V2 1/2] drivers/pwm: add PXA pulse width modulator controller Sascha Hauer
  1 sibling, 0 replies; 19+ messages in thread
From: Robert Jarzmik @ 2012-02-14 12:58 UTC (permalink / raw)
  To: barebox

As pxafb can rely on a PWM to control backlight, and because
driver dependencies are hard to deal with, remove automatic
enable of PXAFB on probe.

The user should in its environment do a :
 - fb0.enable=1

This way, the PWM has been probed and is ready to work, and
the pxafb backlight control works.

Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
---
 arch/arm/mach-pxa/include/mach/pxafb.h |    1 -
 drivers/video/pxa.c                    |    3 ---
 2 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-pxa/include/mach/pxafb.h b/arch/arm/mach-pxa/include/mach/pxafb.h
index 1730fbf..23cbea9 100644
--- a/arch/arm/mach-pxa/include/mach/pxafb.h
+++ b/arch/arm/mach-pxa/include/mach/pxafb.h
@@ -64,7 +64,6 @@ struct pxafb_videomode {
 struct pxafb_platform_data {
 	struct pxafb_videomode	*mode;
 	unsigned int		lcd_conn;
-	int			enable_on_load;
 
 	/** force a memory area to be used, else NULL for dynamic allocation */
 	void			*framebuffer;
diff --git a/drivers/video/pxa.c b/drivers/video/pxa.c
index ddd7087..900ae80 100644
--- a/drivers/video/pxa.c
+++ b/drivers/video/pxa.c
@@ -538,9 +538,6 @@ static int pxafb_probe(struct device_d *dev)
 		return ret;
 	}
 
-	if (pdata->enable_on_load)
-		info->fbops->fb_enable(info);
-
 	return 0;
 }
 
-- 
1.7.5.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH V2 1/2] drivers/pwm: add PXA pulse width modulator controller
  2012-02-14 12:58             ` [PATCH V2 1/2] " Robert Jarzmik
  2012-02-14 12:58               ` [PATCH V2 2/2] drivers/video: remove pxafb enable on load Robert Jarzmik
@ 2012-02-15  8:32               ` Sascha Hauer
  2012-02-15 11:22                 ` Robert Jarzmik
  2012-02-15 15:21                 ` Robert Jarzmik
  1 sibling, 2 replies; 19+ messages in thread
From: Sascha Hauer @ 2012-02-15  8:32 UTC (permalink / raw)
  To: Robert Jarzmik; +Cc: barebox

Hi Robert,

On Tue, Feb 14, 2012 at 01:58:13PM +0100, Robert Jarzmik wrote:
> Add PXA embedded pulse width modulator support. The PWM can
> generate signals from 49.6kHz to 1.625MHz.
> The driver is for pxa2xx family. The pxa3xx was not handled yet.
> 
> Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
> ---
>  arch/arm/mach-pxa/Makefile                |    1 +
>  arch/arm/mach-pxa/devices.c               |    5 +
>  arch/arm/mach-pxa/include/mach/clock.h    |    1 +
>  arch/arm/mach-pxa/include/mach/devices.h  |    2 +-
>  arch/arm/mach-pxa/include/mach/regs-pwm.h |   20 +++
>  arch/arm/mach-pxa/speed-pxa27x.c          |    5 +
>  drivers/pwm/Kconfig                       |    6 +
>  drivers/pwm/Makefile                      |    1 +
>  drivers/pwm/pxa_pwm.c                     |  219 +++++++++++++++++++++++++++++
>  9 files changed, 259 insertions(+), 1 deletions(-)
>  create mode 100644 arch/arm/mach-pxa/include/mach/regs-pwm.h
>  create mode 100644 drivers/pwm/pxa_pwm.c
> 
> +
> +static int __init pxa_pwm_register_vars(struct device_d *dev,
> +					struct pxa_pwm_chip *pxa_pwm)
> +{
> +	int ret;
> +
> +	ret = dev_add_param(dev, "duty_ns", set_duty_ns, NULL, 0);
> +	if (!ret)
> +		ret = dev_add_param(dev, "period_ns", set_period_ns, NULL, 0);
> +	if (!ret)
> +		ret = dev_add_param(dev, "enable", set_enable, NULL, 0);
> +	if (!ret)
> +		ret = dev_set_param(dev, "enable", 0);
> +	return ret;
> +}

Nice to make the pwms accessible from the command line, but shouldn't
this be in the core? From what I see all we have to do is to add
duty_ns and period_ns to struct pwm_chip.

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] 19+ messages in thread

* Re: [PATCH V2 1/2] drivers/pwm: add PXA pulse width modulator controller
  2012-02-15  8:32               ` [PATCH V2 1/2] drivers/pwm: add PXA pulse width modulator controller Sascha Hauer
@ 2012-02-15 11:22                 ` Robert Jarzmik
  2012-02-15 15:21                 ` Robert Jarzmik
  1 sibling, 0 replies; 19+ messages in thread
From: Robert Jarzmik @ 2012-02-15 11:22 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

Sascha Hauer <s.hauer@pengutronix.de> writes:

> Hi Robert,
>
> Nice to make the pwms accessible from the command line, but shouldn't
> this be in the core? From what I see all we have to do is to add
> duty_ns and period_ns to struct pwm_chip.
>

Ah yes, I didn't think about it :)
I will send V3, with duty_ns, period_ns and enable transfered to pwm core.

Cheers.

-- 
Robert

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH V2 1/2] drivers/pwm: add PXA pulse width modulator controller
  2012-02-15  8:32               ` [PATCH V2 1/2] drivers/pwm: add PXA pulse width modulator controller Sascha Hauer
  2012-02-15 11:22                 ` Robert Jarzmik
@ 2012-02-15 15:21                 ` Robert Jarzmik
  2012-02-16  7:40                   ` Sascha Hauer
  1 sibling, 1 reply; 19+ messages in thread
From: Robert Jarzmik @ 2012-02-15 15:21 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

Sascha Hauer <s.hauer@pengutronix.de> writes:

> Hi Robert,
> Nice to make the pwms accessible from the command line, but shouldn't
> this be in the core? From what I see all we have to do is to add
> duty_ns and period_ns to struct pwm_chip.

I thought it over twice.

If the set_duty_ns(), set_period_ns() and set_enable() are transfered to the
core, I'll have to link the device and pwm_chip :
 - expand pwmadd_chip() : should be expanded with the "struct device_d *dev"
parameter
 - provide a way to link *dev with *pwm_chip
   => either store device_d pointer into pwm_device structure, and go through the
   list of all PWMs at each set_X() calls
   => or use dev->priv (bad idea since the driver, ie. pxa_pwm wants to do that)

This way, calling set_X(struct device_d *dev, ...) will find pwm_chip pointer
from dev, and call the approriate pwm_config(), ...

So it's a bit more that adding duty_ns and period_ns to struct pwm_chip. Is this
what you want ?

Cheers.

-- 
Robert

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH V2 1/2] drivers/pwm: add PXA pulse width modulator controller
  2012-02-15 15:21                 ` Robert Jarzmik
@ 2012-02-16  7:40                   ` Sascha Hauer
  2012-02-16 18:23                     ` [PATCH V3 1/3] drivers/pwm: add duty_ns and period_ns to core pwm chip Robert Jarzmik
  0 siblings, 1 reply; 19+ messages in thread
From: Sascha Hauer @ 2012-02-16  7:40 UTC (permalink / raw)
  To: Robert Jarzmik; +Cc: barebox

On Wed, Feb 15, 2012 at 04:21:13PM +0100, Robert Jarzmik wrote:
> Sascha Hauer <s.hauer@pengutronix.de> writes:
> 
> > Hi Robert,
> > Nice to make the pwms accessible from the command line, but shouldn't
> > this be in the core? From what I see all we have to do is to add
> > duty_ns and period_ns to struct pwm_chip.
> 
> I thought it over twice.
> 
> If the set_duty_ns(), set_period_ns() and set_enable() are transfered to the
> core, I'll have to link the device and pwm_chip :
>  - expand pwmadd_chip() : should be expanded with the "struct device_d *dev"
> parameter
>  - provide a way to link *dev with *pwm_chip
>    => either store device_d pointer into pwm_device structure, and go through the
>    list of all PWMs at each set_X() calls
>    => or use dev->priv (bad idea since the driver, ie. pxa_pwm wants to do that)
> 
> This way, calling set_X(struct device_d *dev, ...) will find pwm_chip pointer
> from dev, and call the approriate pwm_config(), ...
> 
> So it's a bit more that adding duty_ns and period_ns to struct pwm_chip. Is this
> what you want ?

Oh, yes, you are right. You have to add a struct device_d * to struct
pwm_chip.

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] 19+ messages in thread

* [PATCH V3 1/3] drivers/pwm: add duty_ns and period_ns to core pwm chip
  2012-02-16  7:40                   ` Sascha Hauer
@ 2012-02-16 18:23                     ` Robert Jarzmik
  2012-02-16 18:23                       ` [PATCH V3 2/3] drivers/pwm: add PXA pulse width modulator controller Robert Jarzmik
  2012-02-16 18:23                       ` [PATCH V3 3/3] drivers/video: remove pxafb enable on load Robert Jarzmik
  0 siblings, 2 replies; 19+ messages in thread
From: Robert Jarzmik @ 2012-02-16 18:23 UTC (permalink / raw)
  To: barebox

Add variables to control the duty_ns and period_ns of PWM
chips. When these variables are set, a call to either
pwm_enable() or pwm_config() is performed to enforce the
setup values.

Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
---
 drivers/pwm/core.c |   76 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 include/pwm.h      |    7 ++++-
 2 files changed, 81 insertions(+), 2 deletions(-)

diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index af30edf..5895584 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -29,10 +29,23 @@ struct pwm_device {
 #define FLAG_REQUESTED	0
 #define FLAG_ENABLED	1
 	struct list_head	node;
+	struct device_d		*dev;
 };
 
 static LIST_HEAD(pwm_list);
 
+static struct pwm_device *dev_to_pwm(struct device_d *dev)
+{
+	struct pwm_device *pwm;
+
+	list_for_each_entry(pwm, &pwm_list, node) {
+		if (pwm->dev == dev)
+			return pwm;
+	}
+
+	return NULL;
+}
+
 static struct pwm_device *_find_pwm(const char *devname)
 {
 	struct pwm_device *pwm;
@@ -45,6 +58,63 @@ static struct pwm_device *_find_pwm(const char *devname)
 	return NULL;
 }
 
+static int set_period_ns(struct device_d *dev, struct param_d *p,
+			 const char *val)
+{
+	struct pwm_device *pwm = dev_to_pwm(dev);
+	int period_ns;
+
+	if (!val)
+		return dev_param_set_generic(dev, p, NULL);
+
+	period_ns = simple_strtoul(val, NULL, 0);
+	pwm_config(pwm, pwm->chip->duty_ns, period_ns);
+	return dev_param_set_generic(dev, p, val);
+}
+
+static int set_duty_ns(struct device_d *dev, struct param_d *p, const char *val)
+{
+	struct pwm_device *pwm = dev_to_pwm(dev);
+	int duty_ns;
+
+	if (!val)
+		return dev_param_set_generic(dev, p, NULL);
+
+	duty_ns = simple_strtoul(val, NULL, 0);
+	pwm_config(pwm, duty_ns, pwm->chip->period_ns);
+	return dev_param_set_generic(dev, p, val);
+}
+
+static int set_enable(struct device_d *dev, struct param_d *p, const char *val)
+{
+	struct pwm_device *pwm = dev_to_pwm(dev);
+	int enable;
+
+	if (!val)
+		return dev_param_set_generic(dev, p, NULL);
+
+	enable = !!simple_strtoul(val, NULL, 0);
+	if (enable)
+		pwm_enable(pwm);
+	else
+		pwm_disable(pwm);
+	return dev_param_set_generic(dev, p, enable ? "1" : "0");
+}
+
+static int pwm_register_vars(struct device_d *dev)
+{
+	int ret;
+
+	ret = dev_add_param(dev, "duty_ns", set_duty_ns, NULL, 0);
+	if (!ret)
+		ret = dev_add_param(dev, "period_ns", set_period_ns, NULL, 0);
+	if (!ret)
+		ret = dev_add_param(dev, "enable", set_enable, NULL, 0);
+	if (!ret)
+		ret = dev_set_param(dev, "enable", 0);
+	return ret;
+}
+
 /**
  * pwmchip_add() - register a new pwm
  * @chip: the pwm
@@ -52,7 +122,7 @@ static struct pwm_device *_find_pwm(const char *devname)
  * register a new pwm. pwm->devname must be initialized, usually
  * from dev_name(dev) from the hardware driver.
  */
-int pwmchip_add(struct pwm_chip *chip)
+int pwmchip_add(struct pwm_chip *chip, struct device_d *dev)
 {
 	struct pwm_device *pwm;
 	int ret = 0;
@@ -62,8 +132,10 @@ int pwmchip_add(struct pwm_chip *chip)
 
 	pwm = xzalloc(sizeof(*pwm));
 	pwm->chip = chip;
+	pwm->dev = dev;
 
 	list_add_tail(&pwm->node, &pwm_list);
+	pwm_register_vars(dev);
 
 	return ret;
 }
@@ -136,6 +208,8 @@ EXPORT_SYMBOL_GPL(pwm_free);
  */
 int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
 {
+	pwm->chip->duty_ns = duty_ns;
+	pwm->chip->period_ns = period_ns;
 	return pwm->chip->ops->config(pwm->chip, duty_ns, period_ns);
 }
 EXPORT_SYMBOL_GPL(pwm_config);
diff --git a/include/pwm.h b/include/pwm.h
index 80f88b1..bdc2fdd 100644
--- a/include/pwm.h
+++ b/include/pwm.h
@@ -2,6 +2,7 @@
 #define __PWM_H
 
 struct pwm_device;
+struct device_d;
 
 /*
  * pwm_request - request a PWM device
@@ -51,13 +52,17 @@ struct pwm_ops {
  * struct pwm_chip - abstract a PWM
  * @devname: unique identifier for this pwm
  * @ops: The callbacks for this PWM
+ * @duty_ns: The duty cycle of the PWM, in nano-seconds
+ * @period_ns: The period of the PWM, in nano-seconds
  */
 struct pwm_chip {
 	const char		*devname;
 	struct pwm_ops		*ops;
+	int			duty_ns;
+	int			period_ns;
 };
 
-int pwmchip_add(struct pwm_chip *chip);
+int pwmchip_add(struct pwm_chip *chip, struct device_d *dev);
 int pwmchip_remove(struct pwm_chip *chip);
 
 #endif /* __PWM_H */
-- 
1.7.5.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH V3 2/3] drivers/pwm: add PXA pulse width modulator controller
  2012-02-16 18:23                     ` [PATCH V3 1/3] drivers/pwm: add duty_ns and period_ns to core pwm chip Robert Jarzmik
@ 2012-02-16 18:23                       ` Robert Jarzmik
  2012-02-16 18:23                       ` [PATCH V3 3/3] drivers/video: remove pxafb enable on load Robert Jarzmik
  1 sibling, 0 replies; 19+ messages in thread
From: Robert Jarzmik @ 2012-02-16 18:23 UTC (permalink / raw)
  To: barebox

Add PXA embedded pulse width modulator support. The PWM can
generate signals from 49.6kHz to 1.625MHz.
The driver is for pxa2xx family. The pxa3xx was not handled yet.

Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
---
 arch/arm/mach-pxa/Makefile                |    1 +
 arch/arm/mach-pxa/devices.c               |    5 +
 arch/arm/mach-pxa/include/mach/clock.h    |    1 +
 arch/arm/mach-pxa/include/mach/devices.h  |    2 +-
 arch/arm/mach-pxa/include/mach/regs-pwm.h |   20 ++++
 arch/arm/mach-pxa/speed-pxa27x.c          |    5 +
 drivers/pwm/Kconfig                       |    6 +
 drivers/pwm/Makefile                      |    1 +
 drivers/pwm/pxa_pwm.c                     |  157 +++++++++++++++++++++++++++++
 9 files changed, 197 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-pxa/include/mach/regs-pwm.h
 create mode 100644 drivers/pwm/pxa_pwm.c

diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index c01a9e0..6a02a54 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -1,6 +1,7 @@
 obj-y += clocksource.o
 obj-y += common.o
 obj-y += gpio.o
+obj-y += devices.o
 
 obj-$(CONFIG_ARCH_PXA2XX) += mfp-pxa2xx.o
 obj-$(CONFIG_ARCH_PXA27X) += speed-pxa27x.o
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index 1a396f1..b6ac0ba 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -47,3 +47,8 @@ struct device_d *pxa_add_mmc(void *base, int id, void *pdata)
 {
 	return pxa_add_device("pxa-mmc", id, base, 0x1000, pdata);
 }
+
+struct device_d *pxa_add_pwm(void *base, int id)
+{
+	return pxa_add_device("pxa_pwm", id, base, 0x10, NULL);
+}
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/devices.h b/arch/arm/mach-pxa/include/mach/devices.h
index e205b7c..8390153 100644
--- a/arch/arm/mach-pxa/include/mach/devices.h
+++ b/arch/arm/mach-pxa/include/mach/devices.h
@@ -23,4 +23,4 @@ struct device_d *pxa_add_i2c(void *base, int id,
 struct device_d *pxa_add_uart(void *base, int id);
 struct device_d *pxa_add_fb(void *base, struct pxafb_platform_data *pdata);
 struct device_d *pxa_add_mmc(void *base, int id, void *pdata);
-
+struct device_d *pxa_add_pwm(void *base, int id);
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..9fdcbb6
--- /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 PWM0slave	0x40B00010
+#define PWM1slave	0x40C00010
+
+#endif
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;
+}
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 93c1052..50c956a 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -8,5 +8,11 @@ menuconfig PWM
 	  If unsure, say N.
 
 if PWM
+config PWM_PXA
+	bool "PXA PWM Support"
+	default y if ARCH_PXA2XX
+	help
+	  This enables PWM support for Intel/Marvell PXA chips, such
+	  as the PXA25x, PXA27x.
 
 endif
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 3469c3d..c886bd5 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_PWM)		+= core.o
+obj-$(CONFIG_PWM_PXA)		+= pxa_pwm.o
\ No newline at end of file
diff --git a/drivers/pwm/pxa_pwm.c b/drivers/pwm/pxa_pwm.c
new file mode 100644
index 0000000..cf1f96a
--- /dev/null
+++ b/drivers/pwm/pxa_pwm.c
@@ -0,0 +1,157 @@
+/*
+ * 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 <init.h>
+#include <errno.h>
+#include <io.h>
+#include <pwm.h>
+
+#include <mach/hardware.h>
+#include <mach/clock.h>
+#include <mach/pxa-regs.h>
+#include <mach/regs-pwm.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)
+
+struct pxa_pwm_chip {
+	struct pwm_chip chip;
+	void __iomem *iobase;
+	int id;
+	int duty_ns;
+	int period_ns;
+};
+
+static struct pxa_pwm_chip *to_pxa_pwm_chip(struct pwm_chip *chip)
+{
+	return container_of(chip, struct pxa_pwm_chip, chip);
+}
+
+/*
+ * 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
+ */
+static int pxa_pwm_config(struct pwm_chip *chip, int duty_ns, int period_ns)
+{
+	unsigned long long c;
+	unsigned long period_cycles, prescale, pv, dc;
+	struct pxa_pwm_chip *pxa_pwm = to_pxa_pwm_chip(chip);
+
+	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;
+
+	pxa_pwm->duty_ns = duty_ns;
+	pxa_pwm->period_ns = period_ns;
+
+	/* NOTE: the clock to PWM has to be enabled first
+	 * before writing to the registers
+	 */
+	__raw_writel(prescale, pxa_pwm->iobase + PWMCR);
+	__raw_writel(dc, pxa_pwm->iobase + PWMDCR);
+	__raw_writel(pv, pxa_pwm->iobase + PWMPCR);
+
+	return 0;
+}
+
+static int pxa_pwm_enable(struct pwm_chip *chip)
+{
+	struct pxa_pwm_chip *pxa_pwm = to_pxa_pwm_chip(chip);
+
+	switch (pxa_pwm->id) {
+	case 0:
+	case 2:
+		CKEN |= CKEN_PWM0;
+		break;
+	case 1:
+	case 3:
+		CKEN |= CKEN_PWM1;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void pxa_pwm_disable(struct pwm_chip *chip)
+{
+	struct pxa_pwm_chip *pxa_pwm = to_pxa_pwm_chip(chip);
+
+	switch (pxa_pwm->id) {
+	case 0:
+	case 2:
+		CKEN &= ~CKEN_PWM0;
+		break;
+	case 1:
+	case 3:
+		CKEN &= ~CKEN_PWM1;
+		break;
+	default:
+		break;
+	}
+}
+
+static struct pwm_ops pxa_pwm_ops = {
+	.config = pxa_pwm_config,
+	.enable = pxa_pwm_enable,
+	.disable = pxa_pwm_disable,
+};
+
+static int pxa_pwm_probe(struct device_d *dev)
+{
+	struct pxa_pwm_chip *chip;
+
+	chip = xzalloc(sizeof(*chip));
+	chip->chip.devname = asprintf("%s", dev_name(dev));
+	chip->chip.ops = &pxa_pwm_ops;
+	chip->iobase = dev_request_mem_region(dev, 0);
+	chip->id = dev->id;
+	dev->priv = chip;
+
+	return pwmchip_add(&chip->chip, dev);
+}
+
+static struct driver_d pxa_pwm_driver = {
+	.name  = "pxa_pwm",
+	.probe = pxa_pwm_probe,
+};
+
+static int __init pxa_pwm_init_driver(void)
+{
+	CKEN &= ~CKEN_PWM0 & ~CKEN_PWM1;
+	register_driver(&pxa_pwm_driver);
+	return 0;
+}
+
+device_initcall(pxa_pwm_init_driver);
-- 
1.7.5.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH V3 3/3] drivers/video: remove pxafb enable on load
  2012-02-16 18:23                     ` [PATCH V3 1/3] drivers/pwm: add duty_ns and period_ns to core pwm chip Robert Jarzmik
  2012-02-16 18:23                       ` [PATCH V3 2/3] drivers/pwm: add PXA pulse width modulator controller Robert Jarzmik
@ 2012-02-16 18:23                       ` Robert Jarzmik
  1 sibling, 0 replies; 19+ messages in thread
From: Robert Jarzmik @ 2012-02-16 18:23 UTC (permalink / raw)
  To: barebox

As pxafb can rely on a PWM to control backlight, and because
driver dependencies are hard to deal with, remove automatic
enable of PXAFB on probe.

The user should in its environment do a :
 - fb0.enable=1

This way, the PWM has been probed and is ready to work, and
the pxafb backlight control works.

Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
---
 arch/arm/mach-pxa/include/mach/pxafb.h |    1 -
 drivers/video/pxa.c                    |    3 ---
 2 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-pxa/include/mach/pxafb.h b/arch/arm/mach-pxa/include/mach/pxafb.h
index 1730fbf..23cbea9 100644
--- a/arch/arm/mach-pxa/include/mach/pxafb.h
+++ b/arch/arm/mach-pxa/include/mach/pxafb.h
@@ -64,7 +64,6 @@ struct pxafb_videomode {
 struct pxafb_platform_data {
 	struct pxafb_videomode	*mode;
 	unsigned int		lcd_conn;
-	int			enable_on_load;
 
 	/** force a memory area to be used, else NULL for dynamic allocation */
 	void			*framebuffer;
diff --git a/drivers/video/pxa.c b/drivers/video/pxa.c
index ddd7087..900ae80 100644
--- a/drivers/video/pxa.c
+++ b/drivers/video/pxa.c
@@ -538,9 +538,6 @@ static int pxafb_probe(struct device_d *dev)
 		return ret;
 	}
 
-	if (pdata->enable_on_load)
-		info->fbops->fb_enable(info);
-
 	return 0;
 }
 
-- 
1.7.5.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2012-02-16 18:24 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-01-31  9:36 [PATCH] Add pwm core support Sascha Hauer
2012-02-01  8:20 ` Robert Jarzmik
2012-02-01 22:42 ` [PATCH] drivers/pwm: add PXA pulse width modulator controller Robert Jarzmik
2012-02-03  9:52   ` Sascha Hauer
2012-02-03 15:39     ` Robert Jarzmik
2012-02-08 15:26       ` Robert Jarzmik
2012-02-09  8:10         ` Sascha Hauer
2012-02-09 11:50           ` Robert Jarzmik
2012-02-09 13:44             ` Sascha Hauer
2012-02-09 14:30               ` Robert Jarzmik
2012-02-14 12:58             ` [PATCH V2 1/2] " Robert Jarzmik
2012-02-14 12:58               ` [PATCH V2 2/2] drivers/video: remove pxafb enable on load Robert Jarzmik
2012-02-15  8:32               ` [PATCH V2 1/2] drivers/pwm: add PXA pulse width modulator controller Sascha Hauer
2012-02-15 11:22                 ` Robert Jarzmik
2012-02-15 15:21                 ` Robert Jarzmik
2012-02-16  7:40                   ` Sascha Hauer
2012-02-16 18:23                     ` [PATCH V3 1/3] drivers/pwm: add duty_ns and period_ns to core pwm chip Robert Jarzmik
2012-02-16 18:23                       ` [PATCH V3 2/3] drivers/pwm: add PXA pulse width modulator controller Robert Jarzmik
2012-02-16 18:23                       ` [PATCH V3 3/3] drivers/video: remove pxafb enable on load Robert Jarzmik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox