Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/broadcom Add drivers to access the clock manage...



details:   https://anonhg.NetBSD.org/src/rev/f7230394cc61
branches:  trunk
changeset: 341750:f7230394cc61
user:      mlelstv <mlelstv%NetBSD.org@localhost>
date:      Sat Nov 21 07:41:29 2015 +0000

description:
Add drivers to access the clock manager and pulse width modulator.

diffstat:

 sys/arch/arm/broadcom/bcm2835_cm.c   |  239 ++++++++++++++++++++++++
 sys/arch/arm/broadcom/bcm2835_cm.h   |  177 ++++++++++++++++++
 sys/arch/arm/broadcom/bcm2835_obio.c |   18 +-
 sys/arch/arm/broadcom/bcm2835_pwm.c  |  341 +++++++++++++++++++++++++++++++++++
 sys/arch/arm/broadcom/bcm2835_pwm.h  |  101 ++++++++++
 sys/arch/arm/broadcom/bcm2835reg.h   |    6 +-
 sys/arch/arm/broadcom/files.bcm2835  |   13 +-
 7 files changed, 891 insertions(+), 4 deletions(-)

diffs (truncated from 976 to 300 lines):

diff -r 2c252182f060 -r f7230394cc61 sys/arch/arm/broadcom/bcm2835_cm.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/broadcom/bcm2835_cm.c        Sat Nov 21 07:41:29 2015 +0000
@@ -0,0 +1,239 @@
+/*     $NetBSD: bcm2835_cm.c,v 1.1 2015/11/21 07:41:29 mlelstv Exp $ */
+
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Michael van Elst
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * Driver for BCM2835 Clock Manager
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: bcm2835_cm.c,v 1.1 2015/11/21 07:41:29 mlelstv Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+
+#include <arm/broadcom/bcm2835reg.h>
+#include <arm/broadcom/bcm_amba.h>
+
+#include <arm/broadcom/bcm2835_cm.h>
+
+struct bcm2835cm_softc {
+       device_t                sc_dev;
+
+       bus_space_tag_t         sc_iot;
+       bus_space_handle_t      sc_ioh;
+};
+
+#define CM_WRITE(sc, reg, val) \
+       bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
+#define CM_READ(sc, reg) \
+       bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))
+
+static int bcmcm_match(device_t, cfdata_t, void *);
+static void bcmcm_attach(device_t, device_t, void *);
+static int bcmcm_wait(struct bcm2835cm_softc *, int, int);
+
+CFATTACH_DECL_NEW(bcmcm_amba, sizeof(struct bcm2835cm_softc),
+    bcmcm_match, bcmcm_attach, NULL, NULL);
+
+/* ARGSUSED */
+static int
+bcmcm_match(device_t parent, cfdata_t match, void *aux)
+{
+       struct amba_attach_args *aaa = aux;
+
+       if (strcmp(aaa->aaa_name, "bcmcm") != 0)
+               return 0;
+
+       if (aaa->aaa_addr != BCM2835_CM_BASE)
+               return 0;
+
+       return 1;
+}
+
+static void
+bcmcm_attach(device_t parent, device_t self, void *aux)
+{
+       struct bcm2835cm_softc *sc = device_private(self);
+       struct amba_attach_args *aaa = aux;
+
+       aprint_naive("\n");
+       aprint_normal(": CM\n");
+
+       sc->sc_dev = self;
+       sc->sc_iot = aaa->aaa_iot;
+
+       if (bus_space_map(aaa->aaa_iot, aaa->aaa_addr, BCM2835_CM_SIZE, 0,
+           &sc->sc_ioh)) {
+               aprint_error_dev(sc->sc_dev, "unable to map device\n");
+               goto fail0;
+       }
+
+       /* Success!  */
+
+fail0: return;
+}
+
+static int
+bcmcm_wait(struct bcm2835cm_softc *sc, int ctlreg, int onoff)
+{
+       int i;
+       uint32_t r;
+
+       for (i=0; i<100; ++i) {
+               r = CM_READ(sc, ctlreg);
+               if (((r & CM_CTL_BUSY) != 0) == onoff)
+                       break;
+               delay(10);
+       }
+       if (i >= 100) {
+               device_printf(sc->sc_dev, "busy (addr=%#x)\n", ctlreg);
+               return EIO;
+       }
+
+       return 0;
+}
+
+int
+bcm_cm_set(enum bcm_cm_clock clk, uint32_t ctl, uint32_t div)
+{
+       struct bcm2835cm_softc *sc;
+       device_t dev;
+       int ctlreg, divreg;
+       uint32_t r;
+
+       dev = device_find_by_driver_unit("bcmcm", 0);
+       if (dev == NULL)
+               return ENXIO;
+       sc = device_private(dev);
+
+       switch (clk) {
+       case BCM_CM_GP0:
+               ctlreg = CM_GP0CTL;
+               divreg = CM_GP0DIV;
+               break;
+       case BCM_CM_GP1:
+               ctlreg = CM_GP1CTL;
+               divreg = CM_GP1DIV;
+               break;
+       case BCM_CM_GP2:
+               ctlreg = CM_GP2CTL;
+               divreg = CM_GP2DIV;
+               break;
+       case BCM_CM_PCM:
+               ctlreg = CM_PCMCTL;
+               divreg = CM_PCMDIV;
+               break;
+       case BCM_CM_PWM:
+               ctlreg = CM_PWMCTL;
+               divreg = CM_PWMDIV;
+               break;
+       default:
+               return EINVAL;
+       }
+
+       ctl &= ~CM_CTL_PASSWD;
+       ctl |= __SHIFTIN(CM_PASSWD, CM_CTL_PASSWD);
+       div &= ~CM_DIV_PASSWD;
+       div |= __SHIFTIN(CM_PASSWD, CM_DIV_PASSWD);
+
+       /* if clock is running, turn it off and wait for
+        * the cycle to end
+        */
+       r = CM_READ(sc, ctlreg);
+       if (r & CM_CTL_ENAB) {
+               r &= ~CM_CTL_PASSWD;
+               r |= __SHIFTIN(CM_PASSWD, CM_CTL_PASSWD);
+               r &= ~CM_CTL_ENAB;
+               CM_WRITE(sc, ctlreg, r);
+       }
+
+       bcmcm_wait(sc, ctlreg, 0);
+
+       /* configure new divider, mode, don't enable */
+       CM_WRITE(sc, divreg, div);
+       CM_WRITE(sc, ctlreg, ctl & ~CM_CTL_ENAB);
+
+       /* enable it */
+       if (ctl & CM_CTL_ENAB) {
+               CM_WRITE(sc, ctlreg, ctl);
+               return bcmcm_wait(sc, ctlreg, 1);
+       }
+
+       return 0;
+}
+
+int
+bcm_cm_get(enum bcm_cm_clock clk, uint32_t *ctlp, uint32_t *divp)
+{
+       struct bcm2835cm_softc *sc;
+       device_t dev;
+       int ctlreg, divreg;
+
+       dev = device_find_by_driver_unit("bcmcm", 0);
+       if (dev == NULL)
+               return ENXIO;
+       sc = device_private(dev);
+
+       switch (clk) {
+       case BCM_CM_GP0:
+               ctlreg = CM_GP0CTL;
+               divreg = CM_GP0DIV;
+               break;
+       case BCM_CM_GP1:
+               ctlreg = CM_GP1CTL;
+               divreg = CM_GP1DIV;
+               break;
+       case BCM_CM_GP2:
+               ctlreg = CM_GP2CTL;
+               divreg = CM_GP2DIV;
+               break;
+       case BCM_CM_PCM:
+               ctlreg = CM_PCMCTL;
+               divreg = CM_PCMDIV;
+               break;
+       case BCM_CM_PWM:
+               ctlreg = CM_PWMCTL;
+               divreg = CM_PWMDIV;
+               break;
+       default:
+               return EINVAL;
+       }
+
+       if (ctlp != NULL)
+               *ctlp = CM_READ(sc, ctlreg);
+       if (divp != NULL)
+               *divp = CM_READ(sc, divreg);
+
+       return 0;
+}
diff -r 2c252182f060 -r f7230394cc61 sys/arch/arm/broadcom/bcm2835_cm.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/broadcom/bcm2835_cm.h        Sat Nov 21 07:41:29 2015 +0000
@@ -0,0 +1,177 @@
+/* $NetBSD: */
+
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * 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 ``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 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.
+ */
+
+#ifndef BCM2835_CMREG_H
+#define BCM2835_CMREG_H
+
+#define CM_GP0CTL              0x70
+#define  CM_CTL_PASSWD         __BITS(24,31)
+#define  CM_CTL_MASH           __BITS(9,10)
+#define  CM_CTL_FLIP           __BIT(8)
+#define  CM_CTL_BUSY           __BIT(7)
+#define  CM_CTL_KILL           __BIT(5)
+#define  CM_CTL_ENAB           __BIT(4)
+#define  CM_CTL_SRC            __BIT(0,3)
+#define CM_GP0DIV              0x74
+#define  CM_DIV_PASSWD         __BITS(24,31)
+#define  CM_DIV_DIVI           __BITS(12,23)
+#define  CM_DIV_DIVF           __BITS(0,11)
+#define CM_GP1CTL              0x78
+#define CM_GP1DIV              0x7c
+#define CM_GP2CTL              0x80
+#define CM_GP2DIV              0x84
+
+#define CM_PCMCTL              0x98    /* PCM / I2S */
+#define CM_PCMDIV              0x9c
+#define CM_PWMCTL              0xa0
+#define CM_PWMDIV              0xa4
+



Home | Main Index | Thread Index | Old Index