Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 27 May 2013 00:13:27 +0000 (UTC)
From:      Oleksandr Tymoshenko <gonzo@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r251017 - head/sys/arm/ti/am335x
Message-ID:  <201305270013.r4R0DRWA039741@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gonzo
Date: Mon May 27 00:13:27 2013
New Revision: 251017
URL: http://svnweb.freebsd.org/changeset/base/251017

Log:
  Add PWM module driver for AM335x. Only eCAS subsystem is supported
  
  Export function to configure eCAS submodule from another drivers.
  It's used to control LCD panel backlight on AM335x EVM.

Added:
  head/sys/arm/ti/am335x/am335x_pwm.c   (contents, props changed)
  head/sys/arm/ti/am335x/am335x_pwm.h   (contents, props changed)
Modified:
  head/sys/arm/ti/am335x/files.am335x

Added: head/sys/arm/ti/am335x/am335x_pwm.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/arm/ti/am335x/am335x_pwm.c	Mon May 27 00:13:27 2013	(r251017)
@@ -0,0 +1,285 @@
+/*-
+ * Copyright (c) 2013 Oleksandr Tymoshenko <gonzo@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/ti/ti_prcm.h>
+#include <arm/ti/ti_scm.h>
+
+#include "am335x_pwm.h"
+#include "am335x_scm.h"
+
+#define	PWM_LOCK(_sc)		mtx_lock(&(_sc)->sc_mtx)
+#define	PWM_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
+#define	PWM_LOCK_INIT(_sc)	mtx_init(&(_sc)->sc_mtx, \
+    device_get_nameunit(_sc->sc_dev), "am335x_pwm softc", MTX_DEF)
+#define	PWM_LOCK_DESTROY(_sc)	mtx_destroy(&(_sc)->sc_mtx);
+
+static struct resource_spec am335x_pwm_mem_spec[] = {
+	{ SYS_RES_MEMORY, 0, RF_ACTIVE }, /* PWMSS */
+	{ SYS_RES_MEMORY, 1, RF_ACTIVE }, /* eCAP */
+	{ SYS_RES_MEMORY, 2, RF_ACTIVE }, /* eQEP */
+	{ SYS_RES_MEMORY, 3, RF_ACTIVE }, /*ePWM */
+	{ -1, 0, 0 }
+};
+
+#define	PWMSS_READ4(_sc, reg)	bus_read_4((_sc)->sc_mem_res[0], reg);
+#define	PWMSS_WRITE4(_sc, reg, value)	\
+    bus_write_4((_sc)->sc_mem_res[0], reg, value);
+
+#define	ECAP_READ2(_sc, reg)	bus_read_2((_sc)->sc_mem_res[1], reg);
+#define	ECAP_WRITE2(_sc, reg, value)	\
+    bus_write_2((_sc)->sc_mem_res[1], reg, value);
+#define	ECAP_READ4(_sc, reg)	bus_read_4((_sc)->sc_mem_res[1], reg);
+#define	ECAP_WRITE4(_sc, reg, value)	\
+    bus_write_4((_sc)->sc_mem_res[1], reg, value);
+
+#define	EPWM_READ2(_sc, reg)	bus_read_2((_sc)->sc_mem_res[3], reg);
+#define	EPWM_WRITE2(_sc, reg, value)	\
+    bus_write_2((_sc)->sc_mem_res[3], reg, value);
+
+#define	PWMSS_IDVER		0x00
+#define	PWMSS_SYSCONFIG		0x04
+#define	PWMSS_CLKCONFIG		0x08
+#define		CLKCONFIG_EPWMCLK_EN	(1 << 8)
+#define	PWMSS_CLKSTATUS		0x0C
+
+#define	ECAP_TSCTR		0x00
+#define	ECAP_CAP1		0x08
+#define	ECAP_CAP2		0x0C
+#define	ECAP_CAP3		0x10
+#define	ECAP_CAP4		0x14
+#define	ECAP_ECCTL2		0x2A
+#define		ECCTL2_MODE_APWM		(1 << 9)
+#define		ECCTL2_SYNCO_SEL		(3 << 6)
+#define		ECCTL2_TSCTRSTOP_FREERUN	(1 << 4)
+
+#define	EPWM_TBCTL		0x00
+#define		TBCTL_PHDIR_UP		(1 << 13)
+#define		TBCTL_PHDIR_DOWN	(0 << 13)
+#define		TBCTL_CLKDIV(x)		((x) << 10)
+#define		TBCTL_HSPCLKDIV(x)	((x) << 7)
+#define		TBCTL_SYNCOSEL_DISABLED	(3 << 4)
+#define		TBCTL_PRDLD_SHADOW	(0 << 3)
+#define		TBCTL_PRDLD_IMMEDIATE	(0 << 3)
+#define		TBCTL_PHSEN_ENABLED	(1 << 2)
+#define		TBCTL_PHSEN_DISABLED	(0 << 2)
+#define	EPWM_TBSTS		0x02
+#define	EPWM_TBPHSHR		0x04
+#define	EPWM_TBPHS		0x06
+#define	EPWM_TBCNT		0x08
+#define	EPWM_TBPRD		0x0a
+/* Counter-compare */
+#define	EPWM_CMPCTL		0x0e
+#define		CMPCTL_SHDWBMODE_SHADOW		(1 << 6)
+#define		CMPCTL_SHDWBMODE_IMMEDIATE	(0 << 6)
+#define		CMPCTL_SHDWAMODE_SHADOW		(1 << 4)
+#define		CMPCTL_SHDWAMODE_IMMEDIATE	(0 << 4)
+#define		CMPCTL_LOADBMODE_ZERO		(0 << 2)
+#define		CMPCTL_LOADBMODE_PRD		(1 << 2)
+#define		CMPCTL_LOADBMODE_EITHER		(2 << 2)
+#define		CMPCTL_LOADBMODE_FREEZE		(3 << 2)
+#define		CMPCTL_LOADAMODE_ZERO		(0 << 0)
+#define		CMPCTL_LOADAMODE_PRD		(1 << 0)
+#define		CMPCTL_LOADAMODE_EITHER		(2 << 0)
+#define		CMPCTL_LOADAMODE_FREEZE		(3 << 0)
+#define	EPWM_CMPAHR		0x10
+#define	EPWM_CMPA		0x12
+#define	EPWM_CMPB		0x14
+/* CMPCTL_LOADAMODE_ZERO */
+#define	EPWM_AQCTLA		0x16
+#define	EPWM_AQCTLB		0x18
+#define		AQCTL_CAU_NONE		(0 << 0)
+#define		AQCTL_CAU_CLEAR		(1 << 0)
+#define		AQCTL_CAU_SET		(2 << 0)
+#define		AQCTL_CAU_TOGGLE	(3 << 0)
+#define		AQCTL_ZRO_NONE		(0 << 0)
+#define		AQCTL_ZRO_CLEAR		(1 << 0)
+#define		AQCTL_ZRO_SET		(2 << 0)
+#define		AQCTL_ZRO_TOGGLE	(3 << 0)
+#define	EPWM_AQSFRC		0x1a
+#define	EPWM_AQCSFRC		0x1c
+
+static device_probe_t am335x_pwm_probe;
+static device_attach_t am335x_pwm_attach;
+static device_detach_t am335x_pwm_detach;
+
+struct am335x_pwm_softc {
+	device_t		sc_dev;
+	struct mtx		sc_mtx;
+	struct resource		*sc_mem_res[4];
+	int			sc_id;
+};
+
+static device_method_t am335x_pwm_methods[] = {
+	DEVMETHOD(device_probe,		am335x_pwm_probe),
+	DEVMETHOD(device_attach,	am335x_pwm_attach),
+	DEVMETHOD(device_detach,	am335x_pwm_detach),
+
+	DEVMETHOD_END
+};
+
+static driver_t am335x_pwm_driver = {
+	"am335x_pwm",
+	am335x_pwm_methods,
+	sizeof(struct am335x_pwm_softc),
+};
+
+static devclass_t am335x_pwm_devclass;
+
+/*
+ * API function to set period/duty cycles for ECASx 
+ */
+int
+am335x_pwm_config_ecas(int unit, int period, int duty)
+{
+	device_t dev;
+	struct am335x_pwm_softc *sc;
+	uint16_t reg;
+
+	dev = devclass_get_device(am335x_pwm_devclass, unit);
+	if (dev == NULL)
+		return (ENXIO);
+
+	if (duty > period)
+		return (EINVAL);
+
+	if (period == 0)
+		return (EINVAL);
+
+	sc = device_get_softc(dev);
+	PWM_LOCK(sc);
+
+	reg = ECAP_READ2(sc, ECAP_ECCTL2);
+	reg |= ECCTL2_MODE_APWM | ECCTL2_TSCTRSTOP_FREERUN | ECCTL2_SYNCO_SEL;
+	ECAP_WRITE2(sc, ECAP_ECCTL2, reg);
+
+	/* CAP3 in APWM mode is APRD shadow register */
+	ECAP_WRITE4(sc, ECAP_CAP3, period - 1);
+
+	/* CAP4 in APWM mode is ACMP shadow register */
+	ECAP_WRITE4(sc, ECAP_CAP4, duty);
+	/* Restart counter */
+	ECAP_WRITE4(sc, ECAP_TSCTR, 0);
+
+	PWM_UNLOCK(sc);
+
+	return (0);
+}
+
+static int
+am335x_pwm_probe(device_t dev)
+{
+	if (!ofw_bus_is_compatible(dev, "ti,am335x-pwm"))
+		return (ENXIO);
+
+	device_set_desc(dev, "AM335x PWM");
+
+	return (BUS_PROBE_DEFAULT);
+}
+
+static int
+am335x_pwm_attach(device_t dev)
+{
+	struct am335x_pwm_softc *sc;
+	int err;
+	uint32_t reg;
+	phandle_t node;
+	pcell_t did;
+
+	sc = device_get_softc(dev);
+	sc->sc_dev = dev;
+	/* Get the PWM module id */
+	node = ofw_bus_get_node(dev);
+	if ((OF_getprop(node, "pwm-device-id", &did, sizeof(did))) <= 0) {
+		device_printf(dev, "missing pwm-device-id attribute in FDT\n");
+		return (ENXIO);
+	}
+	sc->sc_id = fdt32_to_cpu(did);
+
+	PWM_LOCK_INIT(sc);
+
+	err = bus_alloc_resources(dev, am335x_pwm_mem_spec,
+	    sc->sc_mem_res);
+	if (err) {
+		device_printf(dev, "cannot allocate memory resources\n");
+		goto fail;
+	}
+
+	ti_prcm_clk_enable(PWMSS0_CLK + sc->sc_id);
+	ti_scm_reg_read_4(SCM_PWMSS_CTRL, &reg);
+	reg |= (1 << sc->sc_id);
+	ti_scm_reg_write_4(SCM_PWMSS_CTRL, reg);
+
+	return (0);
+fail:
+	PWM_LOCK_DESTROY(sc);
+	if (sc->sc_mem_res[0])
+		bus_release_resources(dev, am335x_pwm_mem_spec,
+		    sc->sc_mem_res);
+
+	return(ENXIO);
+}
+
+static int
+am335x_pwm_detach(device_t dev)
+{
+	struct am335x_pwm_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	PWM_LOCK(sc);
+	if (sc->sc_mem_res[0])
+		bus_release_resources(dev, am335x_pwm_mem_spec,
+		    sc->sc_mem_res);
+	PWM_UNLOCK(sc);
+
+	PWM_LOCK_DESTROY(sc);
+
+	return (0);
+}
+
+DRIVER_MODULE(am335x_pwm, simplebus, am335x_pwm_driver, am335x_pwm_devclass, 0, 0);
+MODULE_VERSION(am335x_pwm, 1);
+MODULE_DEPEND(am335x_pwm, simplebus, 1, 1, 1);

Added: head/sys/arm/ti/am335x/am335x_pwm.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/arm/ti/am335x/am335x_pwm.h	Mon May 27 00:13:27 2013	(r251017)
@@ -0,0 +1,33 @@
+/*-
+ * Copyright (c) 2013 Oleksandr Tymoshenko <gonzo@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef __AM335X_PWM_H__
+#define __AM335X_PWM_H__
+
+int am335x_pwm_config_ecas(int unit, int period, int duty);
+
+#endif /* __AM335X_PWM_H__ */

Modified: head/sys/arm/ti/am335x/files.am335x
==============================================================================
--- head/sys/arm/ti/am335x/files.am335x	Mon May 27 00:09:04 2013	(r251016)
+++ head/sys/arm/ti/am335x/files.am335x	Mon May 27 00:13:27 2013	(r251017)
@@ -4,6 +4,7 @@ arm/ti/aintc.c				standard
 arm/ti/am335x/am335x_prcm.c		standard
 arm/ti/am335x/am335x_dmtimer.c		standard
 arm/ti/am335x/am335x_scm_padconf.c	standard
+arm/ti/am335x/am335x_pwm.c		standard	
 arm/ti/ti_edma3.c			standard
 arm/ti/ti_mmchs.c			optional	mmc
 arm/ti/cpsw/if_cpsw.c			optional	cpsw



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201305270013.r4R0DRWA039741>