mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-07-22 23:45:41 +08:00
Import am335x usb driver file from FreeBSD.
This commit is contained in:
parent
83574df474
commit
bd3c01a126
421
freebsd/sys/arm/ti/am335x/am335x_musb.c
Normal file
421
freebsd/sys/arm/ti/am335x/am335x_musb.c
Normal file
@ -0,0 +1,421 @@
|
|||||||
|
#include <machine/rtems-bsd-kernel-space.h>
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2013 Oleksandr Tymoshenko <gonzo@freebsd.org>
|
||||||
|
*
|
||||||
|
* 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/stdint.h>
|
||||||
|
#include <sys/stddef.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/queue.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/systm.h>
|
||||||
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
#include <sys/module.h>
|
||||||
|
#include <sys/lock.h>
|
||||||
|
#include <sys/mutex.h>
|
||||||
|
#include <sys/condvar.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <sys/sx.h>
|
||||||
|
#include <rtems/bsd/sys/unistd.h>
|
||||||
|
#include <sys/callout.h>
|
||||||
|
#include <sys/malloc.h>
|
||||||
|
#include <sys/priv.h>
|
||||||
|
|
||||||
|
#include <dev/ofw/openfirm.h>
|
||||||
|
#include <dev/ofw/ofw_bus.h>
|
||||||
|
#include <dev/ofw/ofw_bus_subr.h>
|
||||||
|
|
||||||
|
#include <dev/usb/usb.h>
|
||||||
|
#include <dev/usb/usbdi.h>
|
||||||
|
|
||||||
|
#include <dev/usb/usb_core.h>
|
||||||
|
#include <dev/usb/usb_busdma.h>
|
||||||
|
#include <dev/usb/usb_process.h>
|
||||||
|
#include <dev/usb/usb_util.h>
|
||||||
|
|
||||||
|
#define USB_DEBUG_VAR usbssdebug
|
||||||
|
|
||||||
|
#include <dev/usb/usb_controller.h>
|
||||||
|
#include <dev/usb/usb_bus.h>
|
||||||
|
#include <dev/usb/controller/musb_otg.h>
|
||||||
|
#include <dev/usb/usb_debug.h>
|
||||||
|
|
||||||
|
#include <sys/rman.h>
|
||||||
|
|
||||||
|
#include <arm/ti/ti_prcm.h>
|
||||||
|
#include <arm/ti/ti_scm.h>
|
||||||
|
#include <arm/ti/am335x/am335x_scm.h>
|
||||||
|
|
||||||
|
#define USBCTRL_REV 0x00
|
||||||
|
#define USBCTRL_CTRL 0x14
|
||||||
|
#define USBCTRL_STAT 0x18
|
||||||
|
#define USBCTRL_IRQ_STAT0 0x30
|
||||||
|
#define IRQ_STAT0_RXSHIFT 16
|
||||||
|
#define IRQ_STAT0_TXSHIFT 0
|
||||||
|
#define USBCTRL_IRQ_STAT1 0x34
|
||||||
|
#define IRQ_STAT1_DRVVBUS (1 << 8)
|
||||||
|
#define USBCTRL_INTEN_SET0 0x38
|
||||||
|
#define USBCTRL_INTEN_SET1 0x3C
|
||||||
|
#define USBCTRL_INTEN_USB_ALL 0x1ff
|
||||||
|
#define USBCTRL_INTEN_USB_SOF (1 << 3)
|
||||||
|
#define USBCTRL_INTEN_CLR0 0x40
|
||||||
|
#define USBCTRL_INTEN_CLR1 0x44
|
||||||
|
#define USBCTRL_UTMI 0xE0
|
||||||
|
#define USBCTRL_UTMI_FSDATAEXT (1 << 1)
|
||||||
|
#define USBCTRL_MODE 0xE8
|
||||||
|
#define USBCTRL_MODE_IDDIG (1 << 8)
|
||||||
|
#define USBCTRL_MODE_IDDIGMUX (1 << 7)
|
||||||
|
|
||||||
|
/* USBSS resource + 2 MUSB ports */
|
||||||
|
|
||||||
|
#define RES_USBCORE 0
|
||||||
|
#define RES_USBCTRL 1
|
||||||
|
|
||||||
|
#define USB_WRITE4(sc, idx, reg, val) do { \
|
||||||
|
bus_write_4((sc)->sc_mem_res[idx], (reg), (val)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define USB_READ4(sc, idx, reg) bus_read_4((sc)->sc_mem_res[idx], (reg))
|
||||||
|
|
||||||
|
#define USBCTRL_WRITE4(sc, reg, val) \
|
||||||
|
USB_WRITE4((sc), RES_USBCTRL, (reg), (val))
|
||||||
|
#define USBCTRL_READ4(sc, reg) \
|
||||||
|
USB_READ4((sc), RES_USBCTRL, (reg))
|
||||||
|
|
||||||
|
static struct resource_spec am335x_musbotg_mem_spec[] = {
|
||||||
|
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
|
||||||
|
{ SYS_RES_MEMORY, 1, RF_ACTIVE },
|
||||||
|
{ -1, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef USB_DEBUG
|
||||||
|
static int usbssdebug = 0;
|
||||||
|
|
||||||
|
static SYSCTL_NODE(_hw_usb, OID_AUTO, am335x_usbss, CTLFLAG_RW, 0, "AM335x USBSS");
|
||||||
|
SYSCTL_INT(_hw_usb_am335x_usbss, OID_AUTO, debug, CTLFLAG_RW,
|
||||||
|
&usbssdebug, 0, "Debug level");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static device_probe_t musbotg_probe;
|
||||||
|
static device_attach_t musbotg_attach;
|
||||||
|
static device_detach_t musbotg_detach;
|
||||||
|
|
||||||
|
struct musbotg_super_softc {
|
||||||
|
struct musbotg_softc sc_otg;
|
||||||
|
struct resource *sc_mem_res[2];
|
||||||
|
int sc_irq_rid;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
musbotg_vbus_poll(struct musbotg_super_softc *sc)
|
||||||
|
{
|
||||||
|
uint32_t stat;
|
||||||
|
|
||||||
|
if (sc->sc_otg.sc_mode == MUSB2_DEVICE_MODE)
|
||||||
|
musbotg_vbus_interrupt(&sc->sc_otg, 1);
|
||||||
|
else {
|
||||||
|
stat = USBCTRL_READ4(sc, USBCTRL_STAT);
|
||||||
|
musbotg_vbus_interrupt(&sc->sc_otg, stat & 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Arg to musbotg_clocks_on and musbot_clocks_off is
|
||||||
|
* a uint32_t * pointing to the SCM register offset.
|
||||||
|
*/
|
||||||
|
static uint32_t USB_CTRL[] = {SCM_USB_CTRL0, SCM_USB_CTRL1};
|
||||||
|
|
||||||
|
static void
|
||||||
|
musbotg_clocks_on(void *arg)
|
||||||
|
{
|
||||||
|
struct musbotg_softc *sc;
|
||||||
|
uint32_t c, reg;
|
||||||
|
|
||||||
|
sc = arg;
|
||||||
|
reg = USB_CTRL[sc->sc_id];
|
||||||
|
|
||||||
|
ti_scm_reg_read_4(reg, &c);
|
||||||
|
c &= ~3; /* Enable power */
|
||||||
|
c |= 1 << 19; /* VBUS detect enable */
|
||||||
|
c |= 1 << 20; /* Session end enable */
|
||||||
|
ti_scm_reg_write_4(reg, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
musbotg_clocks_off(void *arg)
|
||||||
|
{
|
||||||
|
struct musbotg_softc *sc;
|
||||||
|
uint32_t c, reg;
|
||||||
|
|
||||||
|
sc = arg;
|
||||||
|
reg = USB_CTRL[sc->sc_id];
|
||||||
|
|
||||||
|
/* Disable power to PHY */
|
||||||
|
ti_scm_reg_read_4(reg, &c);
|
||||||
|
ti_scm_reg_write_4(reg, c | 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
musbotg_ep_int_set(struct musbotg_softc *sc, int ep, int on)
|
||||||
|
{
|
||||||
|
struct musbotg_super_softc *ssc = sc->sc_platform_data;
|
||||||
|
uint32_t epmask;
|
||||||
|
|
||||||
|
epmask = ((1 << ep) << IRQ_STAT0_RXSHIFT);
|
||||||
|
epmask |= ((1 << ep) << IRQ_STAT0_TXSHIFT);
|
||||||
|
if (on)
|
||||||
|
USBCTRL_WRITE4(ssc, USBCTRL_INTEN_SET0, epmask);
|
||||||
|
else
|
||||||
|
USBCTRL_WRITE4(ssc, USBCTRL_INTEN_CLR0, epmask);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
musbotg_wrapper_interrupt(void *arg)
|
||||||
|
{
|
||||||
|
struct musbotg_softc *sc = arg;
|
||||||
|
struct musbotg_super_softc *ssc = sc->sc_platform_data;
|
||||||
|
uint32_t stat, stat0, stat1;
|
||||||
|
|
||||||
|
stat = USBCTRL_READ4(ssc, USBCTRL_STAT);
|
||||||
|
stat0 = USBCTRL_READ4(ssc, USBCTRL_IRQ_STAT0);
|
||||||
|
stat1 = USBCTRL_READ4(ssc, USBCTRL_IRQ_STAT1);
|
||||||
|
if (stat0)
|
||||||
|
USBCTRL_WRITE4(ssc, USBCTRL_IRQ_STAT0, stat0);
|
||||||
|
if (stat1)
|
||||||
|
USBCTRL_WRITE4(ssc, USBCTRL_IRQ_STAT1, stat1);
|
||||||
|
|
||||||
|
DPRINTFN(4, "port%d: stat0=%08x stat1=%08x, stat=%08x\n",
|
||||||
|
sc->sc_id, stat0, stat1, stat);
|
||||||
|
|
||||||
|
if (stat1 & IRQ_STAT1_DRVVBUS)
|
||||||
|
musbotg_vbus_interrupt(sc, stat & 1);
|
||||||
|
|
||||||
|
musbotg_interrupt(arg, ((stat0 >> 16) & 0xffff),
|
||||||
|
stat0 & 0xffff, stat1 & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
musbotg_probe(device_t dev)
|
||||||
|
{
|
||||||
|
if (!ofw_bus_status_okay(dev))
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
|
if (!ofw_bus_is_compatible(dev, "ti,musb-am33xx"))
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
|
device_set_desc(dev, "TI AM33xx integrated USB OTG controller");
|
||||||
|
|
||||||
|
return (BUS_PROBE_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
musbotg_attach(device_t dev)
|
||||||
|
{
|
||||||
|
struct musbotg_super_softc *sc = device_get_softc(dev);
|
||||||
|
char mode[16];
|
||||||
|
int err;
|
||||||
|
uint32_t reg;
|
||||||
|
|
||||||
|
sc->sc_otg.sc_id = device_get_unit(dev);
|
||||||
|
|
||||||
|
/* Request the memory resources */
|
||||||
|
err = bus_alloc_resources(dev, am335x_musbotg_mem_spec,
|
||||||
|
sc->sc_mem_res);
|
||||||
|
if (err) {
|
||||||
|
device_printf(dev,
|
||||||
|
"Error: could not allocate mem resources\n");
|
||||||
|
return (ENXIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Request the IRQ resources */
|
||||||
|
sc->sc_otg.sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
|
||||||
|
&sc->sc_irq_rid, RF_ACTIVE);
|
||||||
|
if (sc->sc_otg.sc_irq_res == NULL) {
|
||||||
|
device_printf(dev,
|
||||||
|
"Error: could not allocate irq resources\n");
|
||||||
|
return (ENXIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* setup MUSB OTG USB controller interface softc */
|
||||||
|
sc->sc_otg.sc_clocks_on = &musbotg_clocks_on;
|
||||||
|
sc->sc_otg.sc_clocks_off = &musbotg_clocks_off;
|
||||||
|
sc->sc_otg.sc_clocks_arg = &sc->sc_otg;
|
||||||
|
|
||||||
|
sc->sc_otg.sc_ep_int_set = musbotg_ep_int_set;
|
||||||
|
|
||||||
|
/* initialise some bus fields */
|
||||||
|
sc->sc_otg.sc_bus.parent = dev;
|
||||||
|
sc->sc_otg.sc_bus.devices = sc->sc_otg.sc_devices;
|
||||||
|
sc->sc_otg.sc_bus.devices_max = MUSB2_MAX_DEVICES;
|
||||||
|
sc->sc_otg.sc_bus.dma_bits = 32;
|
||||||
|
|
||||||
|
/* get all DMA memory */
|
||||||
|
if (usb_bus_mem_alloc_all(&sc->sc_otg.sc_bus,
|
||||||
|
USB_GET_DMA_TAG(dev), NULL)) {
|
||||||
|
device_printf(dev,
|
||||||
|
"Failed allocate bus mem for musb\n");
|
||||||
|
return (ENOMEM);
|
||||||
|
}
|
||||||
|
sc->sc_otg.sc_io_res = sc->sc_mem_res[RES_USBCORE];
|
||||||
|
sc->sc_otg.sc_io_tag =
|
||||||
|
rman_get_bustag(sc->sc_otg.sc_io_res);
|
||||||
|
sc->sc_otg.sc_io_hdl =
|
||||||
|
rman_get_bushandle(sc->sc_otg.sc_io_res);
|
||||||
|
sc->sc_otg.sc_io_size =
|
||||||
|
rman_get_size(sc->sc_otg.sc_io_res);
|
||||||
|
|
||||||
|
sc->sc_otg.sc_bus.bdev = device_add_child(dev, "usbus", -1);
|
||||||
|
if (!(sc->sc_otg.sc_bus.bdev)) {
|
||||||
|
device_printf(dev, "No busdev for musb\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
device_set_ivars(sc->sc_otg.sc_bus.bdev,
|
||||||
|
&sc->sc_otg.sc_bus);
|
||||||
|
|
||||||
|
err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res,
|
||||||
|
INTR_TYPE_BIO | INTR_MPSAFE,
|
||||||
|
NULL, (driver_intr_t *)musbotg_wrapper_interrupt,
|
||||||
|
&sc->sc_otg, &sc->sc_otg.sc_intr_hdl);
|
||||||
|
if (err) {
|
||||||
|
sc->sc_otg.sc_intr_hdl = NULL;
|
||||||
|
device_printf(dev,
|
||||||
|
"Failed to setup interrupt for musb\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
sc->sc_otg.sc_platform_data = sc;
|
||||||
|
if (OF_getprop(ofw_bus_get_node(dev), "dr_mode", mode,
|
||||||
|
sizeof(mode)) > 0) {
|
||||||
|
if (strcasecmp(mode, "host") == 0)
|
||||||
|
sc->sc_otg.sc_mode = MUSB2_HOST_MODE;
|
||||||
|
else
|
||||||
|
sc->sc_otg.sc_mode = MUSB2_DEVICE_MODE;
|
||||||
|
} else {
|
||||||
|
/* Beaglebone defaults: USB0 device, USB1 HOST. */
|
||||||
|
if (sc->sc_otg.sc_id == 0)
|
||||||
|
sc->sc_otg.sc_mode = MUSB2_DEVICE_MODE;
|
||||||
|
else
|
||||||
|
sc->sc_otg.sc_mode = MUSB2_HOST_MODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* software-controlled function
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (sc->sc_otg.sc_mode == MUSB2_HOST_MODE) {
|
||||||
|
reg = USBCTRL_READ4(sc, USBCTRL_MODE);
|
||||||
|
reg |= USBCTRL_MODE_IDDIGMUX;
|
||||||
|
reg &= ~USBCTRL_MODE_IDDIG;
|
||||||
|
USBCTRL_WRITE4(sc, USBCTRL_MODE, reg);
|
||||||
|
USBCTRL_WRITE4(sc, USBCTRL_UTMI,
|
||||||
|
USBCTRL_UTMI_FSDATAEXT);
|
||||||
|
} else {
|
||||||
|
reg = USBCTRL_READ4(sc, USBCTRL_MODE);
|
||||||
|
reg |= USBCTRL_MODE_IDDIGMUX;
|
||||||
|
reg |= USBCTRL_MODE_IDDIG;
|
||||||
|
USBCTRL_WRITE4(sc, USBCTRL_MODE, reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
reg = USBCTRL_INTEN_USB_ALL & ~USBCTRL_INTEN_USB_SOF;
|
||||||
|
USBCTRL_WRITE4(sc, USBCTRL_INTEN_SET1, reg);
|
||||||
|
USBCTRL_WRITE4(sc, USBCTRL_INTEN_CLR0, 0xffffffff);
|
||||||
|
|
||||||
|
err = musbotg_init(&sc->sc_otg);
|
||||||
|
if (!err)
|
||||||
|
err = device_probe_and_attach(sc->sc_otg.sc_bus.bdev);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
/* poll VBUS one time */
|
||||||
|
musbotg_vbus_poll(sc);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
error:
|
||||||
|
musbotg_detach(dev);
|
||||||
|
return (ENXIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
musbotg_detach(device_t dev)
|
||||||
|
{
|
||||||
|
struct musbotg_super_softc *sc = device_get_softc(dev);
|
||||||
|
int err;
|
||||||
|
|
||||||
|
/* during module unload there are lots of children leftover */
|
||||||
|
device_delete_children(dev);
|
||||||
|
|
||||||
|
if (sc->sc_otg.sc_irq_res && sc->sc_otg.sc_intr_hdl) {
|
||||||
|
/*
|
||||||
|
* only call musbotg_uninit() after musbotg_init()
|
||||||
|
*/
|
||||||
|
musbotg_uninit(&sc->sc_otg);
|
||||||
|
|
||||||
|
err = bus_teardown_intr(dev, sc->sc_otg.sc_irq_res,
|
||||||
|
sc->sc_otg.sc_intr_hdl);
|
||||||
|
sc->sc_otg.sc_intr_hdl = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_bus_mem_free_all(&sc->sc_otg.sc_bus, NULL);
|
||||||
|
|
||||||
|
/* Free resources if any */
|
||||||
|
if (sc->sc_mem_res[0])
|
||||||
|
bus_release_resources(dev, am335x_musbotg_mem_spec,
|
||||||
|
sc->sc_mem_res);
|
||||||
|
|
||||||
|
if (sc->sc_otg.sc_irq_res)
|
||||||
|
bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irq_rid,
|
||||||
|
sc->sc_otg.sc_irq_res);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static device_method_t musbotg_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, musbotg_probe),
|
||||||
|
DEVMETHOD(device_attach, musbotg_attach),
|
||||||
|
DEVMETHOD(device_detach, musbotg_detach),
|
||||||
|
DEVMETHOD(device_suspend, bus_generic_suspend),
|
||||||
|
DEVMETHOD(device_resume, bus_generic_resume),
|
||||||
|
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
||||||
|
|
||||||
|
DEVMETHOD_END
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t musbotg_driver = {
|
||||||
|
.name = "musbotg",
|
||||||
|
.methods = musbotg_methods,
|
||||||
|
.size = sizeof(struct musbotg_super_softc),
|
||||||
|
};
|
||||||
|
|
||||||
|
static devclass_t musbotg_devclass;
|
||||||
|
|
||||||
|
DRIVER_MODULE(musbotg, usbss, musbotg_driver, musbotg_devclass, 0, 0);
|
||||||
|
MODULE_DEPEND(musbotg, usbss, 1, 1, 1);
|
857
freebsd/sys/arm/ti/am335x/am335x_prcm.c
Normal file
857
freebsd/sys/arm/ti/am335x/am335x_prcm.c
Normal file
@ -0,0 +1,857 @@
|
|||||||
|
#include <machine/rtems-bsd-kernel-space.h>
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2012 Damjan Marion <dmarion@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/bus.h>
|
||||||
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/module.h>
|
||||||
|
#include <sys/malloc.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
#include <sys/timeet.h>
|
||||||
|
#include <sys/timetc.h>
|
||||||
|
#include <sys/watchdog.h>
|
||||||
|
#include <machine/bus.h>
|
||||||
|
#include <machine/cpu.h>
|
||||||
|
#include <machine/intr.h>
|
||||||
|
|
||||||
|
#include <arm/ti/tivar.h>
|
||||||
|
#include <arm/ti/ti_scm.h>
|
||||||
|
#include <arm/ti/ti_prcm.h>
|
||||||
|
|
||||||
|
#include <dev/ofw/openfirm.h>
|
||||||
|
#include <dev/ofw/ofw_bus.h>
|
||||||
|
#include <dev/ofw/ofw_bus_subr.h>
|
||||||
|
|
||||||
|
#include <machine/bus.h>
|
||||||
|
|
||||||
|
#include "am335x_scm.h"
|
||||||
|
|
||||||
|
#define CM_PER 0
|
||||||
|
#define CM_PER_L4LS_CLKSTCTRL (CM_PER + 0x000)
|
||||||
|
#define CM_PER_L3S_CLKSTCTRL (CM_PER + 0x004)
|
||||||
|
#define CM_PER_L3_CLKSTCTRL (CM_PER + 0x00C)
|
||||||
|
#define CM_PER_CPGMAC0_CLKCTRL (CM_PER + 0x014)
|
||||||
|
#define CM_PER_LCDC_CLKCTRL (CM_PER + 0x018)
|
||||||
|
#define CM_PER_USB0_CLKCTRL (CM_PER + 0x01C)
|
||||||
|
#define CM_PER_TPTC0_CLKCTRL (CM_PER + 0x024)
|
||||||
|
#define CM_PER_UART5_CLKCTRL (CM_PER + 0x038)
|
||||||
|
#define CM_PER_MMC0_CLKCTRL (CM_PER + 0x03C)
|
||||||
|
#define CM_PER_I2C2_CLKCTRL (CM_PER + 0x044)
|
||||||
|
#define CM_PER_I2C1_CLKCTRL (CM_PER + 0x048)
|
||||||
|
#define CM_PER_SPI0_CLKCTRL (CM_PER + 0x04C)
|
||||||
|
#define CM_PER_SPI1_CLKCTRL (CM_PER + 0x050)
|
||||||
|
#define CM_PER_UART1_CLKCTRL (CM_PER + 0x06C)
|
||||||
|
#define CM_PER_UART2_CLKCTRL (CM_PER + 0x070)
|
||||||
|
#define CM_PER_UART3_CLKCTRL (CM_PER + 0x074)
|
||||||
|
#define CM_PER_UART4_CLKCTRL (CM_PER + 0x078)
|
||||||
|
#define CM_PER_TIMER7_CLKCTRL (CM_PER + 0x07C)
|
||||||
|
#define CM_PER_TIMER2_CLKCTRL (CM_PER + 0x080)
|
||||||
|
#define CM_PER_TIMER3_CLKCTRL (CM_PER + 0x084)
|
||||||
|
#define CM_PER_TIMER4_CLKCTRL (CM_PER + 0x088)
|
||||||
|
#define CM_PER_GPIO1_CLKCTRL (CM_PER + 0x0AC)
|
||||||
|
#define CM_PER_GPIO2_CLKCTRL (CM_PER + 0x0B0)
|
||||||
|
#define CM_PER_GPIO3_CLKCTRL (CM_PER + 0x0B4)
|
||||||
|
#define CM_PER_TPCC_CLKCTRL (CM_PER + 0x0BC)
|
||||||
|
#define CM_PER_EPWMSS1_CLKCTRL (CM_PER + 0x0CC)
|
||||||
|
#define CM_PER_EPWMSS0_CLKCTRL (CM_PER + 0x0D4)
|
||||||
|
#define CM_PER_EPWMSS2_CLKCTRL (CM_PER + 0x0D8)
|
||||||
|
#define CM_PER_L3_INSTR_CLKCTRL (CM_PER + 0x0DC)
|
||||||
|
#define CM_PER_L3_CLKCTRL (CM_PER + 0x0E0)
|
||||||
|
#define CM_PER_PRUSS_CLKCTRL (CM_PER + 0x0E8)
|
||||||
|
#define CM_PER_TIMER5_CLKCTRL (CM_PER + 0x0EC)
|
||||||
|
#define CM_PER_TIMER6_CLKCTRL (CM_PER + 0x0F0)
|
||||||
|
#define CM_PER_MMC1_CLKCTRL (CM_PER + 0x0F4)
|
||||||
|
#define CM_PER_MMC2_CLKCTRL (CM_PER + 0x0F8)
|
||||||
|
#define CM_PER_TPTC1_CLKCTRL (CM_PER + 0x0FC)
|
||||||
|
#define CM_PER_TPTC2_CLKCTRL (CM_PER + 0x100)
|
||||||
|
#define CM_PER_SPINLOCK0_CLKCTRL (CM_PER + 0x10C)
|
||||||
|
#define CM_PER_MAILBOX0_CLKCTRL (CM_PER + 0x110)
|
||||||
|
#define CM_PER_OCPWP_L3_CLKSTCTRL (CM_PER + 0x12C)
|
||||||
|
#define CM_PER_OCPWP_CLKCTRL (CM_PER + 0x130)
|
||||||
|
#define CM_PER_CPSW_CLKSTCTRL (CM_PER + 0x144)
|
||||||
|
#define CM_PER_PRUSS_CLKSTCTRL (CM_PER + 0x140)
|
||||||
|
|
||||||
|
#define CM_WKUP 0x400
|
||||||
|
#define CM_WKUP_CLKSTCTRL (CM_WKUP + 0x000)
|
||||||
|
#define CM_WKUP_CONTROL_CLKCTRL (CM_WKUP + 0x004)
|
||||||
|
#define CM_WKUP_GPIO0_CLKCTRL (CM_WKUP + 0x008)
|
||||||
|
#define CM_WKUP_CM_L3_AON_CLKSTCTRL (CM_WKUP + 0x01C)
|
||||||
|
#define CM_WKUP_CM_CLKSEL_DPLL_MPU (CM_WKUP + 0x02C)
|
||||||
|
#define CM_WKUP_CM_IDLEST_DPLL_DISP (CM_WKUP + 0x048)
|
||||||
|
#define CM_WKUP_CM_CLKSEL_DPLL_DISP (CM_WKUP + 0x054)
|
||||||
|
#define CM_WKUP_CM_CLKDCOLDO_DPLL_PER (CM_WKUP + 0x07C)
|
||||||
|
#define CM_WKUP_CM_CLKMODE_DPLL_DISP (CM_WKUP + 0x098)
|
||||||
|
#define CM_WKUP_I2C0_CLKCTRL (CM_WKUP + 0x0B8)
|
||||||
|
#define CM_WKUP_ADC_TSC_CLKCTRL (CM_WKUP + 0x0BC)
|
||||||
|
|
||||||
|
#define CM_DPLL 0x500
|
||||||
|
#define CLKSEL_TIMER7_CLK (CM_DPLL + 0x004)
|
||||||
|
#define CLKSEL_TIMER2_CLK (CM_DPLL + 0x008)
|
||||||
|
#define CLKSEL_TIMER3_CLK (CM_DPLL + 0x00C)
|
||||||
|
#define CLKSEL_TIMER4_CLK (CM_DPLL + 0x010)
|
||||||
|
#define CLKSEL_TIMER5_CLK (CM_DPLL + 0x018)
|
||||||
|
#define CLKSEL_TIMER6_CLK (CM_DPLL + 0x01C)
|
||||||
|
#define CLKSEL_PRUSS_OCP_CLK (CM_DPLL + 0x030)
|
||||||
|
|
||||||
|
#define CM_RTC 0x800
|
||||||
|
#define CM_RTC_RTC_CLKCTRL (CM_RTC + 0x000)
|
||||||
|
#define CM_RTC_CLKSTCTRL (CM_RTC + 0x004)
|
||||||
|
|
||||||
|
#define PRM_PER 0xC00
|
||||||
|
#define PRM_PER_RSTCTRL (PRM_PER + 0x00)
|
||||||
|
|
||||||
|
#define PRM_DEVICE_OFFSET 0xF00
|
||||||
|
#define PRM_RSTCTRL (PRM_DEVICE_OFFSET + 0x00)
|
||||||
|
|
||||||
|
struct am335x_prcm_softc {
|
||||||
|
struct resource * res[2];
|
||||||
|
bus_space_tag_t bst;
|
||||||
|
bus_space_handle_t bsh;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct resource_spec am335x_prcm_spec[] = {
|
||||||
|
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
|
||||||
|
{ -1, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct am335x_prcm_softc *am335x_prcm_sc = NULL;
|
||||||
|
|
||||||
|
static int am335x_clk_noop_activate(struct ti_clock_dev *clkdev);
|
||||||
|
static int am335x_clk_generic_activate(struct ti_clock_dev *clkdev);
|
||||||
|
static int am335x_clk_gpio_activate(struct ti_clock_dev *clkdev);
|
||||||
|
static int am335x_clk_noop_deactivate(struct ti_clock_dev *clkdev);
|
||||||
|
static int am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev);
|
||||||
|
static int am335x_clk_noop_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
|
||||||
|
static int am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
|
||||||
|
static int am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
|
||||||
|
static int am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
|
||||||
|
static int am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
|
||||||
|
static int am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
|
||||||
|
static int am335x_clk_set_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int freq);
|
||||||
|
static void am335x_prcm_reset(void);
|
||||||
|
static int am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev);
|
||||||
|
static int am335x_clk_musb0_activate(struct ti_clock_dev *clkdev);
|
||||||
|
static int am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev);
|
||||||
|
static int am335x_clk_pruss_activate(struct ti_clock_dev *clkdev);
|
||||||
|
|
||||||
|
#define AM335X_NOOP_CLOCK_DEV(i) \
|
||||||
|
{ .id = (i), \
|
||||||
|
.clk_activate = am335x_clk_noop_activate, \
|
||||||
|
.clk_deactivate = am335x_clk_noop_deactivate, \
|
||||||
|
.clk_set_source = am335x_clk_noop_set_source, \
|
||||||
|
.clk_accessible = NULL, \
|
||||||
|
.clk_get_source_freq = NULL, \
|
||||||
|
.clk_set_source_freq = NULL \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define AM335X_GENERIC_CLOCK_DEV(i) \
|
||||||
|
{ .id = (i), \
|
||||||
|
.clk_activate = am335x_clk_generic_activate, \
|
||||||
|
.clk_deactivate = am335x_clk_generic_deactivate, \
|
||||||
|
.clk_set_source = am335x_clk_generic_set_source, \
|
||||||
|
.clk_accessible = NULL, \
|
||||||
|
.clk_get_source_freq = NULL, \
|
||||||
|
.clk_set_source_freq = NULL \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define AM335X_GPIO_CLOCK_DEV(i) \
|
||||||
|
{ .id = (i), \
|
||||||
|
.clk_activate = am335x_clk_gpio_activate, \
|
||||||
|
.clk_deactivate = am335x_clk_generic_deactivate, \
|
||||||
|
.clk_set_source = am335x_clk_generic_set_source, \
|
||||||
|
.clk_accessible = NULL, \
|
||||||
|
.clk_get_source_freq = NULL, \
|
||||||
|
.clk_set_source_freq = NULL \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define AM335X_MMCHS_CLOCK_DEV(i) \
|
||||||
|
{ .id = (i), \
|
||||||
|
.clk_activate = am335x_clk_generic_activate, \
|
||||||
|
.clk_deactivate = am335x_clk_generic_deactivate, \
|
||||||
|
.clk_set_source = am335x_clk_generic_set_source, \
|
||||||
|
.clk_accessible = NULL, \
|
||||||
|
.clk_get_source_freq = am335x_clk_hsmmc_get_source_freq, \
|
||||||
|
.clk_set_source_freq = NULL \
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ti_clock_dev ti_am335x_clk_devmap[] = {
|
||||||
|
/* System clocks */
|
||||||
|
{ .id = SYS_CLK,
|
||||||
|
.clk_activate = NULL,
|
||||||
|
.clk_deactivate = NULL,
|
||||||
|
.clk_set_source = NULL,
|
||||||
|
.clk_accessible = NULL,
|
||||||
|
.clk_get_source_freq = am335x_clk_get_sysclk_freq,
|
||||||
|
.clk_set_source_freq = NULL,
|
||||||
|
},
|
||||||
|
/* MPU (ARM) core clocks */
|
||||||
|
{ .id = MPU_CLK,
|
||||||
|
.clk_activate = NULL,
|
||||||
|
.clk_deactivate = NULL,
|
||||||
|
.clk_set_source = NULL,
|
||||||
|
.clk_accessible = NULL,
|
||||||
|
.clk_get_source_freq = am335x_clk_get_arm_fclk_freq,
|
||||||
|
.clk_set_source_freq = NULL,
|
||||||
|
},
|
||||||
|
/* CPSW Ethernet Switch core clocks */
|
||||||
|
{ .id = CPSW_CLK,
|
||||||
|
.clk_activate = am335x_clk_cpsw_activate,
|
||||||
|
.clk_deactivate = NULL,
|
||||||
|
.clk_set_source = NULL,
|
||||||
|
.clk_accessible = NULL,
|
||||||
|
.clk_get_source_freq = NULL,
|
||||||
|
.clk_set_source_freq = NULL,
|
||||||
|
},
|
||||||
|
|
||||||
|
/* Mentor USB HS controller core clocks */
|
||||||
|
{ .id = MUSB0_CLK,
|
||||||
|
.clk_activate = am335x_clk_musb0_activate,
|
||||||
|
.clk_deactivate = NULL,
|
||||||
|
.clk_set_source = NULL,
|
||||||
|
.clk_accessible = NULL,
|
||||||
|
.clk_get_source_freq = NULL,
|
||||||
|
.clk_set_source_freq = NULL,
|
||||||
|
},
|
||||||
|
|
||||||
|
/* LCD controller clocks */
|
||||||
|
{ .id = LCDC_CLK,
|
||||||
|
.clk_activate = am335x_clk_lcdc_activate,
|
||||||
|
.clk_deactivate = NULL,
|
||||||
|
.clk_set_source = NULL,
|
||||||
|
.clk_accessible = NULL,
|
||||||
|
.clk_get_source_freq = am335x_clk_get_arm_disp_freq,
|
||||||
|
.clk_set_source_freq = am335x_clk_set_arm_disp_freq,
|
||||||
|
},
|
||||||
|
|
||||||
|
/* UART */
|
||||||
|
AM335X_NOOP_CLOCK_DEV(UART1_CLK),
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(UART2_CLK),
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(UART3_CLK),
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(UART4_CLK),
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(UART5_CLK),
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(UART6_CLK),
|
||||||
|
|
||||||
|
/* DMTimer */
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(TIMER2_CLK),
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(TIMER3_CLK),
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(TIMER4_CLK),
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(TIMER5_CLK),
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(TIMER6_CLK),
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(TIMER7_CLK),
|
||||||
|
|
||||||
|
/* GPIO, we use hwmods as reference, not units in spec */
|
||||||
|
AM335X_GPIO_CLOCK_DEV(GPIO1_CLK),
|
||||||
|
AM335X_GPIO_CLOCK_DEV(GPIO2_CLK),
|
||||||
|
AM335X_GPIO_CLOCK_DEV(GPIO3_CLK),
|
||||||
|
AM335X_GPIO_CLOCK_DEV(GPIO4_CLK),
|
||||||
|
|
||||||
|
/* I2C we use hwmods as reference, not units in spec */
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(I2C1_CLK),
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(I2C2_CLK),
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(I2C3_CLK),
|
||||||
|
|
||||||
|
/* McSPI we use hwmods as reference, not units in spec */
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(SPI0_CLK),
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(SPI1_CLK),
|
||||||
|
|
||||||
|
/* TSC_ADC */
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(TSC_ADC_CLK),
|
||||||
|
|
||||||
|
/* EDMA */
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(EDMA_TPCC_CLK),
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC0_CLK),
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC1_CLK),
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC2_CLK),
|
||||||
|
|
||||||
|
/* MMCHS */
|
||||||
|
AM335X_MMCHS_CLOCK_DEV(MMC1_CLK),
|
||||||
|
AM335X_MMCHS_CLOCK_DEV(MMC2_CLK),
|
||||||
|
AM335X_MMCHS_CLOCK_DEV(MMC3_CLK),
|
||||||
|
|
||||||
|
/* PWMSS */
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(PWMSS0_CLK),
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(PWMSS1_CLK),
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(PWMSS2_CLK),
|
||||||
|
|
||||||
|
/* System Mailbox clock */
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(MAILBOX0_CLK),
|
||||||
|
|
||||||
|
/* SPINLOCK */
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(SPINLOCK0_CLK),
|
||||||
|
|
||||||
|
/* PRU-ICSS */
|
||||||
|
{ .id = PRUSS_CLK,
|
||||||
|
.clk_activate = am335x_clk_pruss_activate,
|
||||||
|
.clk_deactivate = NULL,
|
||||||
|
.clk_set_source = NULL,
|
||||||
|
.clk_accessible = NULL,
|
||||||
|
.clk_get_source_freq = NULL,
|
||||||
|
.clk_set_source_freq = NULL,
|
||||||
|
},
|
||||||
|
|
||||||
|
/* RTC */
|
||||||
|
AM335X_GENERIC_CLOCK_DEV(RTC_CLK),
|
||||||
|
|
||||||
|
{ INVALID_CLK_IDENT, NULL, NULL, NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct am335x_clk_details {
|
||||||
|
clk_ident_t id;
|
||||||
|
uint32_t clkctrl_reg;
|
||||||
|
uint32_t clksel_reg;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define _CLK_DETAIL(i, c, s) \
|
||||||
|
{ .id = (i), \
|
||||||
|
.clkctrl_reg = (c), \
|
||||||
|
.clksel_reg = (s), \
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct am335x_clk_details g_am335x_clk_details[] = {
|
||||||
|
|
||||||
|
/* UART. UART0 clock not controllable. */
|
||||||
|
_CLK_DETAIL(UART1_CLK, 0, 0),
|
||||||
|
_CLK_DETAIL(UART2_CLK, CM_PER_UART1_CLKCTRL, 0),
|
||||||
|
_CLK_DETAIL(UART3_CLK, CM_PER_UART2_CLKCTRL, 0),
|
||||||
|
_CLK_DETAIL(UART4_CLK, CM_PER_UART3_CLKCTRL, 0),
|
||||||
|
_CLK_DETAIL(UART5_CLK, CM_PER_UART4_CLKCTRL, 0),
|
||||||
|
_CLK_DETAIL(UART6_CLK, CM_PER_UART5_CLKCTRL, 0),
|
||||||
|
|
||||||
|
/* DMTimer modules */
|
||||||
|
_CLK_DETAIL(TIMER2_CLK, CM_PER_TIMER2_CLKCTRL, CLKSEL_TIMER2_CLK),
|
||||||
|
_CLK_DETAIL(TIMER3_CLK, CM_PER_TIMER3_CLKCTRL, CLKSEL_TIMER3_CLK),
|
||||||
|
_CLK_DETAIL(TIMER4_CLK, CM_PER_TIMER4_CLKCTRL, CLKSEL_TIMER4_CLK),
|
||||||
|
_CLK_DETAIL(TIMER5_CLK, CM_PER_TIMER5_CLKCTRL, CLKSEL_TIMER5_CLK),
|
||||||
|
_CLK_DETAIL(TIMER6_CLK, CM_PER_TIMER6_CLKCTRL, CLKSEL_TIMER6_CLK),
|
||||||
|
_CLK_DETAIL(TIMER7_CLK, CM_PER_TIMER7_CLKCTRL, CLKSEL_TIMER7_CLK),
|
||||||
|
|
||||||
|
/* GPIO modules, hwmods start with gpio1 */
|
||||||
|
_CLK_DETAIL(GPIO1_CLK, CM_WKUP_GPIO0_CLKCTRL, 0),
|
||||||
|
_CLK_DETAIL(GPIO2_CLK, CM_PER_GPIO1_CLKCTRL, 0),
|
||||||
|
_CLK_DETAIL(GPIO3_CLK, CM_PER_GPIO2_CLKCTRL, 0),
|
||||||
|
_CLK_DETAIL(GPIO4_CLK, CM_PER_GPIO3_CLKCTRL, 0),
|
||||||
|
|
||||||
|
/* I2C modules, hwmods start with i2c1 */
|
||||||
|
_CLK_DETAIL(I2C1_CLK, CM_WKUP_I2C0_CLKCTRL, 0),
|
||||||
|
_CLK_DETAIL(I2C2_CLK, CM_PER_I2C1_CLKCTRL, 0),
|
||||||
|
_CLK_DETAIL(I2C3_CLK, CM_PER_I2C2_CLKCTRL, 0),
|
||||||
|
|
||||||
|
/* McSPI modules, hwmods start with spi0 */
|
||||||
|
_CLK_DETAIL(SPI0_CLK, CM_PER_SPI0_CLKCTRL, 0),
|
||||||
|
_CLK_DETAIL(SPI1_CLK, CM_PER_SPI1_CLKCTRL, 0),
|
||||||
|
|
||||||
|
/* TSC_ADC module */
|
||||||
|
_CLK_DETAIL(TSC_ADC_CLK, CM_WKUP_ADC_TSC_CLKCTRL, 0),
|
||||||
|
|
||||||
|
/* EDMA modules */
|
||||||
|
_CLK_DETAIL(EDMA_TPCC_CLK, CM_PER_TPCC_CLKCTRL, 0),
|
||||||
|
_CLK_DETAIL(EDMA_TPTC0_CLK, CM_PER_TPTC0_CLKCTRL, 0),
|
||||||
|
_CLK_DETAIL(EDMA_TPTC1_CLK, CM_PER_TPTC1_CLKCTRL, 0),
|
||||||
|
_CLK_DETAIL(EDMA_TPTC2_CLK, CM_PER_TPTC2_CLKCTRL, 0),
|
||||||
|
|
||||||
|
/* MMCHS modules, hwmods start with mmc1*/
|
||||||
|
_CLK_DETAIL(MMC1_CLK, CM_PER_MMC0_CLKCTRL, 0),
|
||||||
|
_CLK_DETAIL(MMC2_CLK, CM_PER_MMC1_CLKCTRL, 0),
|
||||||
|
_CLK_DETAIL(MMC3_CLK, CM_PER_MMC1_CLKCTRL, 0),
|
||||||
|
|
||||||
|
/* PWMSS modules */
|
||||||
|
_CLK_DETAIL(PWMSS0_CLK, CM_PER_EPWMSS0_CLKCTRL, 0),
|
||||||
|
_CLK_DETAIL(PWMSS1_CLK, CM_PER_EPWMSS1_CLKCTRL, 0),
|
||||||
|
_CLK_DETAIL(PWMSS2_CLK, CM_PER_EPWMSS2_CLKCTRL, 0),
|
||||||
|
|
||||||
|
_CLK_DETAIL(MAILBOX0_CLK, CM_PER_MAILBOX0_CLKCTRL, 0),
|
||||||
|
_CLK_DETAIL(SPINLOCK0_CLK, CM_PER_SPINLOCK0_CLKCTRL, 0),
|
||||||
|
|
||||||
|
/* RTC module */
|
||||||
|
_CLK_DETAIL(RTC_CLK, CM_RTC_RTC_CLKCTRL, 0),
|
||||||
|
|
||||||
|
{ INVALID_CLK_IDENT, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Read/Write macros */
|
||||||
|
#define prcm_read_4(reg) \
|
||||||
|
bus_space_read_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg)
|
||||||
|
#define prcm_write_4(reg, val) \
|
||||||
|
bus_space_write_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg, val)
|
||||||
|
|
||||||
|
void am335x_prcm_setup_dmtimer(int);
|
||||||
|
|
||||||
|
static int
|
||||||
|
am335x_prcm_probe(device_t dev)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!ofw_bus_status_okay(dev))
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
|
if (ofw_bus_is_compatible(dev, "ti,am3-prcm")) {
|
||||||
|
device_set_desc(dev, "AM335x Power and Clock Management");
|
||||||
|
return(BUS_PROBE_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ENXIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
am335x_prcm_attach(device_t dev)
|
||||||
|
{
|
||||||
|
struct am335x_prcm_softc *sc = device_get_softc(dev);
|
||||||
|
unsigned int sysclk, fclk;
|
||||||
|
|
||||||
|
if (am335x_prcm_sc)
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
|
if (bus_alloc_resources(dev, am335x_prcm_spec, sc->res)) {
|
||||||
|
device_printf(dev, "could not allocate resources\n");
|
||||||
|
return (ENXIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
sc->bst = rman_get_bustag(sc->res[0]);
|
||||||
|
sc->bsh = rman_get_bushandle(sc->res[0]);
|
||||||
|
|
||||||
|
am335x_prcm_sc = sc;
|
||||||
|
ti_cpu_reset = am335x_prcm_reset;
|
||||||
|
|
||||||
|
if (am335x_clk_get_sysclk_freq(NULL, &sysclk) != 0)
|
||||||
|
sysclk = 0;
|
||||||
|
if (am335x_clk_get_arm_fclk_freq(NULL, &fclk) != 0)
|
||||||
|
fclk = 0;
|
||||||
|
if (sysclk && fclk)
|
||||||
|
device_printf(dev, "Clocks: System %u.%01u MHz, CPU %u MHz\n",
|
||||||
|
sysclk/1000000, (sysclk % 1000000)/100000, fclk/1000000);
|
||||||
|
else
|
||||||
|
device_printf(dev, "can't read frequencies yet (SCM device not ready?)\n");
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static device_method_t am335x_prcm_methods[] = {
|
||||||
|
DEVMETHOD(device_probe, am335x_prcm_probe),
|
||||||
|
DEVMETHOD(device_attach, am335x_prcm_attach),
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t am335x_prcm_driver = {
|
||||||
|
"am335x_prcm",
|
||||||
|
am335x_prcm_methods,
|
||||||
|
sizeof(struct am335x_prcm_softc),
|
||||||
|
};
|
||||||
|
|
||||||
|
static devclass_t am335x_prcm_devclass;
|
||||||
|
|
||||||
|
DRIVER_MODULE(am335x_prcm, simplebus, am335x_prcm_driver,
|
||||||
|
am335x_prcm_devclass, 0, 0);
|
||||||
|
MODULE_VERSION(am335x_prcm, 1);
|
||||||
|
MODULE_DEPEND(am335x_prcm, ti_scm, 1, 1, 1);
|
||||||
|
|
||||||
|
static struct am335x_clk_details*
|
||||||
|
am335x_clk_details(clk_ident_t id)
|
||||||
|
{
|
||||||
|
struct am335x_clk_details *walker;
|
||||||
|
|
||||||
|
for (walker = g_am335x_clk_details; walker->id != INVALID_CLK_IDENT; walker++) {
|
||||||
|
if (id == walker->id)
|
||||||
|
return (walker);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
am335x_clk_noop_activate(struct ti_clock_dev *clkdev)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
am335x_clk_generic_activate(struct ti_clock_dev *clkdev)
|
||||||
|
{
|
||||||
|
struct am335x_prcm_softc *sc = am335x_prcm_sc;
|
||||||
|
struct am335x_clk_details* clk_details;
|
||||||
|
|
||||||
|
if (sc == NULL)
|
||||||
|
return ENXIO;
|
||||||
|
|
||||||
|
clk_details = am335x_clk_details(clkdev->id);
|
||||||
|
|
||||||
|
if (clk_details == NULL)
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
|
/* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */
|
||||||
|
prcm_write_4(clk_details->clkctrl_reg, 2);
|
||||||
|
while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 2)
|
||||||
|
DELAY(10);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
am335x_clk_gpio_activate(struct ti_clock_dev *clkdev)
|
||||||
|
{
|
||||||
|
struct am335x_prcm_softc *sc = am335x_prcm_sc;
|
||||||
|
struct am335x_clk_details* clk_details;
|
||||||
|
|
||||||
|
if (sc == NULL)
|
||||||
|
return ENXIO;
|
||||||
|
|
||||||
|
clk_details = am335x_clk_details(clkdev->id);
|
||||||
|
|
||||||
|
if (clk_details == NULL)
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
|
/* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */
|
||||||
|
/* set *_CLKCTRL register OPTFCLKEN_GPIO_1_G DBCLK[18] to FCLK_EN(1) */
|
||||||
|
prcm_write_4(clk_details->clkctrl_reg, 2 | (1 << 18));
|
||||||
|
while ((prcm_read_4(clk_details->clkctrl_reg) &
|
||||||
|
(3 | (1 << 18) )) != (2 | (1 << 18)))
|
||||||
|
DELAY(10);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
am335x_clk_noop_deactivate(struct ti_clock_dev *clkdev)
|
||||||
|
{
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev)
|
||||||
|
{
|
||||||
|
struct am335x_prcm_softc *sc = am335x_prcm_sc;
|
||||||
|
struct am335x_clk_details* clk_details;
|
||||||
|
|
||||||
|
if (sc == NULL)
|
||||||
|
return ENXIO;
|
||||||
|
|
||||||
|
clk_details = am335x_clk_details(clkdev->id);
|
||||||
|
|
||||||
|
if (clk_details == NULL)
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
|
/* set *_CLKCTRL register MODULEMODE[1:0] to disable(0) */
|
||||||
|
prcm_write_4(clk_details->clkctrl_reg, 0);
|
||||||
|
while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 0)
|
||||||
|
DELAY(10);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
am335x_clk_noop_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc)
|
||||||
|
{
|
||||||
|
struct am335x_prcm_softc *sc = am335x_prcm_sc;
|
||||||
|
struct am335x_clk_details* clk_details;
|
||||||
|
uint32_t reg;
|
||||||
|
|
||||||
|
if (sc == NULL)
|
||||||
|
return ENXIO;
|
||||||
|
|
||||||
|
clk_details = am335x_clk_details(clkdev->id);
|
||||||
|
|
||||||
|
if (clk_details == NULL)
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
|
switch (clksrc) {
|
||||||
|
case EXT_CLK:
|
||||||
|
reg = 0; /* SEL2: TCLKIN clock */
|
||||||
|
break;
|
||||||
|
case SYSCLK_CLK:
|
||||||
|
reg = 1; /* SEL1: CLK_M_OSC clock */
|
||||||
|
break;
|
||||||
|
case F32KHZ_CLK:
|
||||||
|
reg = 2; /* SEL3: CLK_32KHZ clock */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return (ENXIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
prcm_write_4(clk_details->clksel_reg, reg);
|
||||||
|
while ((prcm_read_4(clk_details->clksel_reg) & 0x3) != reg)
|
||||||
|
DELAY(10);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
|
||||||
|
{
|
||||||
|
*freq = 96000000;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
|
||||||
|
{
|
||||||
|
uint32_t ctrl_status;
|
||||||
|
|
||||||
|
/* Read the input clock freq from the control module. */
|
||||||
|
if (ti_scm_reg_read_4(SCM_CTRL_STATUS, &ctrl_status))
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
|
switch ((ctrl_status>>22) & 0x3) {
|
||||||
|
case 0x0:
|
||||||
|
/* 19.2Mhz */
|
||||||
|
*freq = 19200000;
|
||||||
|
break;
|
||||||
|
case 0x1:
|
||||||
|
/* 24Mhz */
|
||||||
|
*freq = 24000000;
|
||||||
|
break;
|
||||||
|
case 0x2:
|
||||||
|
/* 25Mhz */
|
||||||
|
*freq = 25000000;
|
||||||
|
break;
|
||||||
|
case 0x3:
|
||||||
|
/* 26Mhz */
|
||||||
|
*freq = 26000000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DPLL_BYP_CLKSEL(reg) ((reg>>23) & 1)
|
||||||
|
#define DPLL_DIV(reg) ((reg & 0x7f)+1)
|
||||||
|
#define DPLL_MULT(reg) ((reg>>8) & 0x7FF)
|
||||||
|
#define DPLL_MAX_MUL 0x800
|
||||||
|
#define DPLL_MAX_DIV 0x80
|
||||||
|
|
||||||
|
static int
|
||||||
|
am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
|
||||||
|
{
|
||||||
|
uint32_t reg;
|
||||||
|
uint32_t sysclk;
|
||||||
|
|
||||||
|
reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_MPU);
|
||||||
|
|
||||||
|
/*Check if we are running in bypass */
|
||||||
|
if (DPLL_BYP_CLKSEL(reg))
|
||||||
|
return ENXIO;
|
||||||
|
|
||||||
|
am335x_clk_get_sysclk_freq(NULL, &sysclk);
|
||||||
|
*freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg));
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
|
||||||
|
{
|
||||||
|
uint32_t reg;
|
||||||
|
uint32_t sysclk;
|
||||||
|
|
||||||
|
reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_DISP);
|
||||||
|
|
||||||
|
/*Check if we are running in bypass */
|
||||||
|
if (DPLL_BYP_CLKSEL(reg))
|
||||||
|
return ENXIO;
|
||||||
|
|
||||||
|
am335x_clk_get_sysclk_freq(NULL, &sysclk);
|
||||||
|
*freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg));
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
am335x_clk_set_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int freq)
|
||||||
|
{
|
||||||
|
uint32_t sysclk;
|
||||||
|
uint32_t mul, div;
|
||||||
|
uint32_t i, j;
|
||||||
|
unsigned int delta, min_delta;
|
||||||
|
|
||||||
|
am335x_clk_get_sysclk_freq(NULL, &sysclk);
|
||||||
|
|
||||||
|
/* Bypass mode */
|
||||||
|
prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x4);
|
||||||
|
|
||||||
|
/* Make sure it's in bypass mode */
|
||||||
|
while (!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP)
|
||||||
|
& (1 << 8)))
|
||||||
|
DELAY(10);
|
||||||
|
|
||||||
|
/* Dumb and non-optimal implementation */
|
||||||
|
min_delta = freq;
|
||||||
|
for (i = 1; i < DPLL_MAX_MUL; i++) {
|
||||||
|
for (j = 1; j < DPLL_MAX_DIV; j++) {
|
||||||
|
delta = abs(freq - i*(sysclk/j));
|
||||||
|
if (delta < min_delta) {
|
||||||
|
mul = i;
|
||||||
|
div = j;
|
||||||
|
min_delta = delta;
|
||||||
|
}
|
||||||
|
if (min_delta == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prcm_write_4(CM_WKUP_CM_CLKSEL_DPLL_DISP, (mul << 8) | (div - 1));
|
||||||
|
|
||||||
|
/* Locked mode */
|
||||||
|
prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x7);
|
||||||
|
|
||||||
|
int timeout = 10000;
|
||||||
|
while ((!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP)
|
||||||
|
& (1 << 0))) && timeout--)
|
||||||
|
DELAY(10);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
am335x_prcm_reset(void)
|
||||||
|
{
|
||||||
|
prcm_write_4(PRM_RSTCTRL, (1<<1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev)
|
||||||
|
{
|
||||||
|
struct am335x_prcm_softc *sc = am335x_prcm_sc;
|
||||||
|
|
||||||
|
if (sc == NULL)
|
||||||
|
return ENXIO;
|
||||||
|
|
||||||
|
/* set MODULENAME to ENABLE */
|
||||||
|
prcm_write_4(CM_PER_CPGMAC0_CLKCTRL, 2);
|
||||||
|
|
||||||
|
/* wait for IDLEST to become Func(0) */
|
||||||
|
while(prcm_read_4(CM_PER_CPGMAC0_CLKCTRL) & (3<<16));
|
||||||
|
|
||||||
|
/*set CLKTRCTRL to SW_WKUP(2) */
|
||||||
|
prcm_write_4(CM_PER_CPSW_CLKSTCTRL, 2);
|
||||||
|
|
||||||
|
/* wait for 125 MHz OCP clock to become active */
|
||||||
|
while((prcm_read_4(CM_PER_CPSW_CLKSTCTRL) & (1<<4)) == 0);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
am335x_clk_musb0_activate(struct ti_clock_dev *clkdev)
|
||||||
|
{
|
||||||
|
struct am335x_prcm_softc *sc = am335x_prcm_sc;
|
||||||
|
|
||||||
|
if (sc == NULL)
|
||||||
|
return ENXIO;
|
||||||
|
|
||||||
|
/* set ST_DPLL_CLKDCOLDO(9) to CLK_GATED(1) */
|
||||||
|
/* set DPLL_CLKDCOLDO_GATE_CTRL(8) to CLK_ENABLE(1)*/
|
||||||
|
prcm_write_4(CM_WKUP_CM_CLKDCOLDO_DPLL_PER, 0x300);
|
||||||
|
|
||||||
|
/*set MODULEMODE to ENABLE(2) */
|
||||||
|
prcm_write_4(CM_PER_USB0_CLKCTRL, 2);
|
||||||
|
|
||||||
|
/* wait for MODULEMODE to become ENABLE(2) */
|
||||||
|
while ((prcm_read_4(CM_PER_USB0_CLKCTRL) & 0x3) != 2)
|
||||||
|
DELAY(10);
|
||||||
|
|
||||||
|
/* wait for IDLEST to become Func(0) */
|
||||||
|
while(prcm_read_4(CM_PER_USB0_CLKCTRL) & (3<<16))
|
||||||
|
DELAY(10);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev)
|
||||||
|
{
|
||||||
|
struct am335x_prcm_softc *sc = am335x_prcm_sc;
|
||||||
|
|
||||||
|
if (sc == NULL)
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For now set frequency to 2*VGA_PIXEL_CLOCK
|
||||||
|
*/
|
||||||
|
am335x_clk_set_arm_disp_freq(clkdev, 25175000*2);
|
||||||
|
|
||||||
|
/*set MODULEMODE to ENABLE(2) */
|
||||||
|
prcm_write_4(CM_PER_LCDC_CLKCTRL, 2);
|
||||||
|
|
||||||
|
/* wait for MODULEMODE to become ENABLE(2) */
|
||||||
|
while ((prcm_read_4(CM_PER_LCDC_CLKCTRL) & 0x3) != 2)
|
||||||
|
DELAY(10);
|
||||||
|
|
||||||
|
/* wait for IDLEST to become Func(0) */
|
||||||
|
while(prcm_read_4(CM_PER_LCDC_CLKCTRL) & (3<<16))
|
||||||
|
DELAY(10);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
am335x_clk_pruss_activate(struct ti_clock_dev *clkdev)
|
||||||
|
{
|
||||||
|
struct am335x_prcm_softc *sc = am335x_prcm_sc;
|
||||||
|
|
||||||
|
if (sc == NULL)
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
|
/* Set MODULEMODE to ENABLE(2) */
|
||||||
|
prcm_write_4(CM_PER_PRUSS_CLKCTRL, 2);
|
||||||
|
|
||||||
|
/* Wait for MODULEMODE to become ENABLE(2) */
|
||||||
|
while ((prcm_read_4(CM_PER_PRUSS_CLKCTRL) & 0x3) != 2)
|
||||||
|
DELAY(10);
|
||||||
|
|
||||||
|
/* Set CLKTRCTRL to SW_WKUP(2) */
|
||||||
|
prcm_write_4(CM_PER_PRUSS_CLKSTCTRL, 2);
|
||||||
|
|
||||||
|
/* Wait for the 200 MHz OCP clock to become active */
|
||||||
|
while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<4)) == 0)
|
||||||
|
DELAY(10);
|
||||||
|
|
||||||
|
/* Wait for the 200 MHz IEP clock to become active */
|
||||||
|
while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<5)) == 0)
|
||||||
|
DELAY(10);
|
||||||
|
|
||||||
|
/* Wait for the 192 MHz UART clock to become active */
|
||||||
|
while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<6)) == 0)
|
||||||
|
DELAY(10);
|
||||||
|
|
||||||
|
/* Select L3F as OCP clock */
|
||||||
|
prcm_write_4(CLKSEL_PRUSS_OCP_CLK, 0);
|
||||||
|
while ((prcm_read_4(CLKSEL_PRUSS_OCP_CLK) & 0x3) != 0)
|
||||||
|
DELAY(10);
|
||||||
|
|
||||||
|
/* Clear the RESET bit */
|
||||||
|
prcm_write_4(PRM_PER_RSTCTRL, prcm_read_4(PRM_PER_RSTCTRL) & ~2);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
49
freebsd/sys/arm/ti/am335x/am335x_scm.h
Normal file
49
freebsd/sys/arm/ti/am335x/am335x_scm.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2012 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_SCM_H__
|
||||||
|
#define __AM335X_SCM_H__
|
||||||
|
|
||||||
|
/* AM335x-specific registers for control module (scm) */
|
||||||
|
#define SCM_CTRL_STATUS 0x40
|
||||||
|
#define SCM_BGAP_CTRL 0x448
|
||||||
|
#define SCM_BGAP_TEMP_MASK 0xff
|
||||||
|
#define SCM_BGAP_TEMP_SHIFT 8
|
||||||
|
#define SCM_BGAP_BGOFF (1 << 6)
|
||||||
|
#define SCM_BGAP_SOC (1 << 4)
|
||||||
|
#define SCM_BGAP_CLRZ (1 << 3)
|
||||||
|
#define SCM_BGAP_CONTCONV (1 << 2)
|
||||||
|
#define SCM_BGAP_EOCZ (1 << 1)
|
||||||
|
#define SCM_USB_CTRL0 0x620
|
||||||
|
#define SCM_USB_STS0 0x624
|
||||||
|
#define SCM_USB_CTRL1 0x628
|
||||||
|
#define SCM_USB_STS1 0x62C
|
||||||
|
#define SCM_MAC_ID0_LO 0x630
|
||||||
|
#define SCM_MAC_ID0_HI 0x634
|
||||||
|
#define SCM_PWMSS_CTRL 0x664
|
||||||
|
|
||||||
|
#endif /* __AM335X_SCM_H__ */
|
226
freebsd/sys/arm/ti/am335x/am335x_usbss.c
Normal file
226
freebsd/sys/arm/ti/am335x/am335x_usbss.c
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
#include <machine/rtems-bsd-kernel-space.h>
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2013 Oleksandr Tymoshenko <gonzo@freebsd.org>
|
||||||
|
*
|
||||||
|
* 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/stdint.h>
|
||||||
|
#include <sys/stddef.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/queue.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/systm.h>
|
||||||
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/bus.h>
|
||||||
|
#include <sys/module.h>
|
||||||
|
#include <sys/lock.h>
|
||||||
|
#include <sys/mutex.h>
|
||||||
|
#include <sys/condvar.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <sys/sx.h>
|
||||||
|
#include <rtems/bsd/sys/unistd.h>
|
||||||
|
#include <sys/callout.h>
|
||||||
|
#include <sys/malloc.h>
|
||||||
|
#include <sys/priv.h>
|
||||||
|
|
||||||
|
#include <dev/fdt/simplebus.h>
|
||||||
|
#include <dev/ofw/openfirm.h>
|
||||||
|
#include <dev/ofw/ofw_bus.h>
|
||||||
|
#include <dev/ofw/ofw_bus_subr.h>
|
||||||
|
|
||||||
|
#include <dev/usb/usb.h>
|
||||||
|
#include <dev/usb/usbdi.h>
|
||||||
|
|
||||||
|
#include <dev/usb/usb_core.h>
|
||||||
|
#include <dev/usb/usb_busdma.h>
|
||||||
|
#include <dev/usb/usb_process.h>
|
||||||
|
#include <dev/usb/usb_util.h>
|
||||||
|
|
||||||
|
#include <dev/usb/usb_controller.h>
|
||||||
|
#include <dev/usb/usb_bus.h>
|
||||||
|
#include <dev/usb/controller/musb_otg.h>
|
||||||
|
#include <dev/usb/usb_debug.h>
|
||||||
|
|
||||||
|
#include <sys/rman.h>
|
||||||
|
|
||||||
|
#include <arm/ti/ti_prcm.h>
|
||||||
|
#include <arm/ti/ti_scm.h>
|
||||||
|
#include <arm/ti/am335x/am335x_scm.h>
|
||||||
|
|
||||||
|
#define AM335X_USB_PORTS 2
|
||||||
|
|
||||||
|
#define USBSS_REVREG 0x00
|
||||||
|
#define USBSS_SYSCONFIG 0x10
|
||||||
|
#define USBSS_SYSCONFIG_SRESET 1
|
||||||
|
|
||||||
|
#define USBCTRL_REV 0x00
|
||||||
|
#define USBCTRL_CTRL 0x14
|
||||||
|
#define USBCTRL_STAT 0x18
|
||||||
|
#define USBCTRL_IRQ_STAT0 0x30
|
||||||
|
#define IRQ_STAT0_RXSHIFT 16
|
||||||
|
#define IRQ_STAT0_TXSHIFT 0
|
||||||
|
#define USBCTRL_IRQ_STAT1 0x34
|
||||||
|
#define IRQ_STAT1_DRVVBUS (1 << 8)
|
||||||
|
#define USBCTRL_INTEN_SET0 0x38
|
||||||
|
#define USBCTRL_INTEN_SET1 0x3C
|
||||||
|
#define USBCTRL_INTEN_USB_ALL 0x1ff
|
||||||
|
#define USBCTRL_INTEN_USB_SOF (1 << 3)
|
||||||
|
#define USBCTRL_INTEN_CLR0 0x40
|
||||||
|
#define USBCTRL_INTEN_CLR1 0x44
|
||||||
|
#define USBCTRL_UTMI 0xE0
|
||||||
|
#define USBCTRL_UTMI_FSDATAEXT (1 << 1)
|
||||||
|
#define USBCTRL_MODE 0xE8
|
||||||
|
#define USBCTRL_MODE_IDDIG (1 << 8)
|
||||||
|
#define USBCTRL_MODE_IDDIGMUX (1 << 7)
|
||||||
|
|
||||||
|
#define USBSS_WRITE4(sc, reg, val) \
|
||||||
|
bus_write_4((sc)->sc_mem_res, (reg), (val))
|
||||||
|
#define USBSS_READ4(sc, reg) \
|
||||||
|
bus_read_4((sc)->sc_mem_res, (reg))
|
||||||
|
|
||||||
|
static device_probe_t usbss_probe;
|
||||||
|
static device_attach_t usbss_attach;
|
||||||
|
static device_detach_t usbss_detach;
|
||||||
|
|
||||||
|
struct usbss_softc {
|
||||||
|
struct simplebus_softc simplebus_sc;
|
||||||
|
struct resource *sc_mem_res;
|
||||||
|
int sc_mem_rid;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
usbss_probe(device_t dev)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!ofw_bus_status_okay(dev))
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
|
if (!ofw_bus_is_compatible(dev, "ti,am33xx-usb"))
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
|
device_set_desc(dev, "TI AM33xx integrated USB OTG controller");
|
||||||
|
|
||||||
|
return (BUS_PROBE_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
usbss_attach(device_t dev)
|
||||||
|
{
|
||||||
|
struct usbss_softc *sc = device_get_softc(dev);
|
||||||
|
int i;
|
||||||
|
uint32_t rev;
|
||||||
|
phandle_t node;
|
||||||
|
|
||||||
|
/* Request the memory resources */
|
||||||
|
sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
|
||||||
|
&sc->sc_mem_rid, RF_ACTIVE);
|
||||||
|
if (sc->sc_mem_res == NULL) {
|
||||||
|
device_printf(dev,
|
||||||
|
"Error: could not allocate mem resources\n");
|
||||||
|
return (ENXIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable device clocks. */
|
||||||
|
ti_prcm_clk_enable(MUSB0_CLK);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset USBSS, USB0 and USB1.
|
||||||
|
* The registers of USB subsystem must not be accessed while the
|
||||||
|
* reset pulse is active (200ns).
|
||||||
|
*/
|
||||||
|
USBSS_WRITE4(sc, USBSS_SYSCONFIG, USBSS_SYSCONFIG_SRESET);
|
||||||
|
DELAY(100);
|
||||||
|
i = 10;
|
||||||
|
while (USBSS_READ4(sc, USBSS_SYSCONFIG) & USBSS_SYSCONFIG_SRESET) {
|
||||||
|
DELAY(100);
|
||||||
|
if (i-- == 0) {
|
||||||
|
device_printf(dev, "reset timeout.\n");
|
||||||
|
return (ENXIO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read the module revision. */
|
||||||
|
rev = USBSS_READ4(sc, USBSS_REVREG);
|
||||||
|
device_printf(dev, "TI AM335X USBSS v%d.%d.%d\n",
|
||||||
|
(rev >> 8) & 7, (rev >> 6) & 3, rev & 63);
|
||||||
|
|
||||||
|
node = ofw_bus_get_node(dev);
|
||||||
|
|
||||||
|
if (node == -1) {
|
||||||
|
usbss_detach(dev);
|
||||||
|
return (ENXIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
simplebus_init(dev, node);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allow devices to identify.
|
||||||
|
*/
|
||||||
|
bus_generic_probe(dev);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now walk the OFW tree and attach top-level devices.
|
||||||
|
*/
|
||||||
|
for (node = OF_child(node); node > 0; node = OF_peer(node))
|
||||||
|
simplebus_add_device(dev, node, 0, NULL, -1, NULL);
|
||||||
|
|
||||||
|
return (bus_generic_attach(dev));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
usbss_detach(device_t dev)
|
||||||
|
{
|
||||||
|
struct usbss_softc *sc = device_get_softc(dev);
|
||||||
|
|
||||||
|
/* Free resources if any */
|
||||||
|
if (sc->sc_mem_res)
|
||||||
|
bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mem_rid,
|
||||||
|
sc->sc_mem_res);
|
||||||
|
|
||||||
|
/* during module unload there are lots of children leftover */
|
||||||
|
device_delete_children(dev);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static device_method_t usbss_methods[] = {
|
||||||
|
/* Device interface */
|
||||||
|
DEVMETHOD(device_probe, usbss_probe),
|
||||||
|
DEVMETHOD(device_attach, usbss_attach),
|
||||||
|
DEVMETHOD(device_detach, usbss_detach),
|
||||||
|
DEVMETHOD(device_suspend, bus_generic_suspend),
|
||||||
|
DEVMETHOD(device_resume, bus_generic_resume),
|
||||||
|
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
||||||
|
|
||||||
|
DEVMETHOD_END
|
||||||
|
};
|
||||||
|
|
||||||
|
DEFINE_CLASS_1(usbss, usbss_driver, usbss_methods,
|
||||||
|
sizeof(struct usbss_softc), simplebus_driver);
|
||||||
|
static devclass_t usbss_devclass;
|
||||||
|
DRIVER_MODULE(usbss, simplebus, usbss_driver, usbss_devclass, 0, 0);
|
||||||
|
MODULE_DEPEND(usbss, usb, 1, 1, 1);
|
83
freebsd/sys/arm/ti/ti_cpuid.h
Normal file
83
freebsd/sys/arm/ti/ti_cpuid.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2011
|
||||||
|
* Ben Gray <ben.r.gray@gmail.com>.
|
||||||
|
* 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 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 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 _TI_CPUID_H_
|
||||||
|
#define _TI_CPUID_H_
|
||||||
|
|
||||||
|
#define OMAP_MAKEREV(d, a, b, c) \
|
||||||
|
(uint32_t)(((d) << 16) | (((a) & 0xf) << 8) | (((b) & 0xf) << 4) | ((c) & 0xf))
|
||||||
|
|
||||||
|
#define OMAP_REV_DEVICE(x) (((x) >> 16) & 0xffff)
|
||||||
|
#define OMAP_REV_MAJOR(x) (((x) >> 8) & 0xf)
|
||||||
|
#define OMAP_REV_MINOR(x) (((x) >> 4) & 0xf)
|
||||||
|
#define OMAP_REV_MINOR_MINOR(x) (((x) >> 0) & 0xf)
|
||||||
|
|
||||||
|
#define OMAP3350_DEV 0x3530
|
||||||
|
#define OMAP3350_REV_ES1_0 OMAP_MAKEREV(OMAP3350_DEV, 1, 0, 0)
|
||||||
|
#define OMAP3530_REV_ES2_0 OMAP_MAKEREV(OMAP3350_DEV, 2, 0, 0)
|
||||||
|
#define OMAP3530_REV_ES2_1 OMAP_MAKEREV(OMAP3350_DEV, 2, 1, 0)
|
||||||
|
#define OMAP3530_REV_ES3_0 OMAP_MAKEREV(OMAP3350_DEV, 3, 0, 0)
|
||||||
|
#define OMAP3530_REV_ES3_1 OMAP_MAKEREV(OMAP3350_DEV, 3, 1, 0)
|
||||||
|
#define OMAP3530_REV_ES3_1_2 OMAP_MAKEREV(OMAP3350_DEV, 3, 1, 2)
|
||||||
|
|
||||||
|
#define OMAP4430_DEV 0x4430
|
||||||
|
#define OMAP4430_REV_ES1_0 OMAP_MAKEREV(OMAP4430_DEV, 1, 0, 0)
|
||||||
|
#define OMAP4430_REV_ES2_0 OMAP_MAKEREV(OMAP4430_DEV, 2, 0, 0)
|
||||||
|
#define OMAP4430_REV_ES2_1 OMAP_MAKEREV(OMAP4430_DEV, 2, 1, 0)
|
||||||
|
#define OMAP4430_REV_ES2_2 OMAP_MAKEREV(OMAP4430_DEV, 2, 2, 0)
|
||||||
|
#define OMAP4430_REV_ES2_3 OMAP_MAKEREV(OMAP4430_DEV, 2, 3, 0)
|
||||||
|
#define OMAP4430_REV_UNKNOWN OMAP_MAKEREV(OMAP4430_DEV, 9, 9, 9)
|
||||||
|
|
||||||
|
#define OMAP4460_DEV 0x4460
|
||||||
|
#define OMAP4460_REV_ES1_0 OMAP_MAKEREV(OMAP4460_DEV, 1, 0, 0)
|
||||||
|
#define OMAP4460_REV_ES1_1 OMAP_MAKEREV(OMAP4460_DEV, 1, 1, 0)
|
||||||
|
#define OMAP4460_REV_UNKNOWN OMAP_MAKEREV(OMAP4460_DEV, 9, 9, 9)
|
||||||
|
|
||||||
|
#define OMAP4470_DEV 0x4470
|
||||||
|
#define OMAP4470_REV_ES1_0 OMAP_MAKEREV(OMAP4470_DEV, 1, 0, 0)
|
||||||
|
#define OMAP4470_REV_UNKNOWN OMAP_MAKEREV(OMAP4470_DEV, 9, 9, 9)
|
||||||
|
|
||||||
|
#define OMAP_UNKNOWN_DEV OMAP_MAKEREV(0x9999, 9, 9, 9)
|
||||||
|
|
||||||
|
#define AM335X_DEVREV(x) ((x) >> 28)
|
||||||
|
|
||||||
|
#define CHIP_OMAP_4 0
|
||||||
|
#define CHIP_AM335X 1
|
||||||
|
|
||||||
|
extern int _ti_chip;
|
||||||
|
|
||||||
|
static __inline int ti_chip(void)
|
||||||
|
{
|
||||||
|
KASSERT(_ti_chip != -1, ("Can't determine TI Chip"));
|
||||||
|
return _ti_chip;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ti_revision(void);
|
||||||
|
|
||||||
|
#endif /* _TI_CPUID_H_ */
|
357
freebsd/sys/arm/ti/ti_prcm.c
Normal file
357
freebsd/sys/arm/ti/ti_prcm.c
Normal file
@ -0,0 +1,357 @@
|
|||||||
|
#include <machine/rtems-bsd-kernel-space.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010
|
||||||
|
* Ben Gray <ben.r.gray@gmail.com>.
|
||||||
|
* 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.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by Ben Gray.
|
||||||
|
* 4. The name of the company nor the name of the author may be used to
|
||||||
|
* endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BEN GRAY ``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 BEN GRAY 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Power, Reset and Clock Management Module
|
||||||
|
*
|
||||||
|
* This is a very simple driver wrapper around the PRCM set of registers in
|
||||||
|
* the OMAP3 chip. It allows you to turn on and off things like the functional
|
||||||
|
* and interface clocks to the various on-chip modules.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#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 <rtems/bsd/sys/resource.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
#include <sys/lock.h>
|
||||||
|
#include <sys/mutex.h>
|
||||||
|
|
||||||
|
#include <machine/bus.h>
|
||||||
|
#include <machine/resource.h>
|
||||||
|
#include <machine/intr.h>
|
||||||
|
|
||||||
|
#include <arm/ti/ti_cpuid.h>
|
||||||
|
#include <arm/ti/ti_prcm.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ti_*_clk_devmap - Array of clock devices, should be defined one per SoC
|
||||||
|
*
|
||||||
|
* This array is typically defined in one of the targeted *_prcm_clk.c
|
||||||
|
* files and is specific to the given SoC platform. Each entry in the array
|
||||||
|
* corresponds to an individual clock device.
|
||||||
|
*/
|
||||||
|
extern struct ti_clock_dev ti_omap4_clk_devmap[];
|
||||||
|
extern struct ti_clock_dev ti_am335x_clk_devmap[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ti_prcm_clk_dev - returns a pointer to the clock device with given id
|
||||||
|
* @clk: the ID of the clock device to get
|
||||||
|
*
|
||||||
|
* Simply iterates through the clk_devmap global array and returns a pointer
|
||||||
|
* to the clock device if found.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* The pointer to the clock device on success, on failure NULL is returned.
|
||||||
|
*/
|
||||||
|
static struct ti_clock_dev *
|
||||||
|
ti_prcm_clk_dev(clk_ident_t clk)
|
||||||
|
{
|
||||||
|
struct ti_clock_dev *clk_dev;
|
||||||
|
|
||||||
|
/* Find the clock within the devmap - it's a bit inefficent having a for
|
||||||
|
* loop for this, but this function should only called when a driver is
|
||||||
|
* being activated so IMHO not a big issue.
|
||||||
|
*/
|
||||||
|
clk_dev = NULL;
|
||||||
|
switch(ti_chip()) {
|
||||||
|
#ifdef SOC_OMAP4
|
||||||
|
case CHIP_OMAP_4:
|
||||||
|
clk_dev = &(ti_omap4_clk_devmap[0]);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef SOC_TI_AM335X
|
||||||
|
case CHIP_AM335X:
|
||||||
|
clk_dev = &(ti_am335x_clk_devmap[0]);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (clk_dev == NULL)
|
||||||
|
panic("No clock devmap found");
|
||||||
|
while (clk_dev->id != INVALID_CLK_IDENT) {
|
||||||
|
if (clk_dev->id == clk) {
|
||||||
|
return (clk_dev);
|
||||||
|
}
|
||||||
|
clk_dev++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sanity check we managed to find the clock */
|
||||||
|
printf("ti_prcm: Failed to find clock device (%d)\n", clk);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ti_prcm_clk_valid - enables a clock for a particular module
|
||||||
|
* @clk: identifier for the module to enable, see ti_prcm.h for a list
|
||||||
|
* of possible modules.
|
||||||
|
* Example: OMAP3_MODULE_MMC1_ICLK or OMAP3_MODULE_GPTIMER10_FCLK.
|
||||||
|
*
|
||||||
|
* This function can enable either a functional or interface clock.
|
||||||
|
*
|
||||||
|
* The real work done to enable the clock is really done in the callback
|
||||||
|
* function associated with the clock, this function is simply a wrapper
|
||||||
|
* around that.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* Internally locks the driver context.
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* Returns 0 on success or positive error code on failure.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
ti_prcm_clk_valid(clk_ident_t clk)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (ti_prcm_clk_dev(clk) == NULL)
|
||||||
|
ret = EINVAL;
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ti_prcm_clk_enable - enables a clock for a particular module
|
||||||
|
* @clk: identifier for the module to enable, see ti_prcm.h for a list
|
||||||
|
* of possible modules.
|
||||||
|
* Example: OMAP3_MODULE_MMC1_ICLK or OMAP3_MODULE_GPTIMER10_FCLK.
|
||||||
|
*
|
||||||
|
* This function can enable either a functional or interface clock.
|
||||||
|
*
|
||||||
|
* The real work done to enable the clock is really done in the callback
|
||||||
|
* function associated with the clock, this function is simply a wrapper
|
||||||
|
* around that.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* Internally locks the driver context.
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* Returns 0 on success or positive error code on failure.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
ti_prcm_clk_enable(clk_ident_t clk)
|
||||||
|
{
|
||||||
|
struct ti_clock_dev *clk_dev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Find the clock within the devmap - it's a bit inefficent having a for
|
||||||
|
* loop for this, but this function should only called when a driver is
|
||||||
|
* being activated so IMHO not a big issue.
|
||||||
|
*/
|
||||||
|
clk_dev = ti_prcm_clk_dev(clk);
|
||||||
|
|
||||||
|
/* Sanity check we managed to find the clock */
|
||||||
|
if (clk_dev == NULL)
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
/* Activate the clock */
|
||||||
|
if (clk_dev->clk_activate)
|
||||||
|
ret = clk_dev->clk_activate(clk_dev);
|
||||||
|
else
|
||||||
|
ret = EINVAL;
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ti_prcm_clk_disable - disables a clock for a particular module
|
||||||
|
* @clk: identifier for the module to enable, see ti_prcm.h for a list
|
||||||
|
* of possible modules.
|
||||||
|
* Example: OMAP3_MODULE_MMC1_ICLK or OMAP3_MODULE_GPTIMER10_FCLK.
|
||||||
|
*
|
||||||
|
* This function can enable either a functional or interface clock.
|
||||||
|
*
|
||||||
|
* The real work done to enable the clock is really done in the callback
|
||||||
|
* function associated with the clock, this function is simply a wrapper
|
||||||
|
* around that.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* Internally locks the driver context.
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* Returns 0 on success or positive error code on failure.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
ti_prcm_clk_disable(clk_ident_t clk)
|
||||||
|
{
|
||||||
|
struct ti_clock_dev *clk_dev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Find the clock within the devmap - it's a bit inefficent having a for
|
||||||
|
* loop for this, but this function should only called when a driver is
|
||||||
|
* being activated so IMHO not a big issue.
|
||||||
|
*/
|
||||||
|
clk_dev = ti_prcm_clk_dev(clk);
|
||||||
|
|
||||||
|
/* Sanity check we managed to find the clock */
|
||||||
|
if (clk_dev == NULL)
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
/* Activate the clock */
|
||||||
|
if (clk_dev->clk_deactivate)
|
||||||
|
ret = clk_dev->clk_deactivate(clk_dev);
|
||||||
|
else
|
||||||
|
ret = EINVAL;
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ti_prcm_clk_set_source - sets the source
|
||||||
|
* @clk: identifier for the module to enable, see ti_prcm.h for a list
|
||||||
|
* of possible modules.
|
||||||
|
* Example: OMAP3_MODULE_MMC1_ICLK or OMAP3_MODULE_GPTIMER10_FCLK.
|
||||||
|
*
|
||||||
|
* This function can enable either a functional or interface clock.
|
||||||
|
*
|
||||||
|
* The real work done to enable the clock is really done in the callback
|
||||||
|
* function associated with the clock, this function is simply a wrapper
|
||||||
|
* around that.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* Internally locks the driver context.
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* Returns 0 on success or positive error code on failure.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
ti_prcm_clk_set_source(clk_ident_t clk, clk_src_t clksrc)
|
||||||
|
{
|
||||||
|
struct ti_clock_dev *clk_dev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Find the clock within the devmap - it's a bit inefficent having a for
|
||||||
|
* loop for this, but this function should only called when a driver is
|
||||||
|
* being activated so IMHO not a big issue.
|
||||||
|
*/
|
||||||
|
clk_dev = ti_prcm_clk_dev(clk);
|
||||||
|
|
||||||
|
/* Sanity check we managed to find the clock */
|
||||||
|
if (clk_dev == NULL)
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
/* Activate the clock */
|
||||||
|
if (clk_dev->clk_set_source)
|
||||||
|
ret = clk_dev->clk_set_source(clk_dev, clksrc);
|
||||||
|
else
|
||||||
|
ret = EINVAL;
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ti_prcm_clk_get_source_freq - gets the source clock frequency
|
||||||
|
* @clk: identifier for the module to enable, see ti_prcm.h for a list
|
||||||
|
* of possible modules.
|
||||||
|
* @freq: pointer to an integer that upon return will contain the src freq
|
||||||
|
*
|
||||||
|
* This function returns the frequency of the source clock.
|
||||||
|
*
|
||||||
|
* The real work done to enable the clock is really done in the callback
|
||||||
|
* function associated with the clock, this function is simply a wrapper
|
||||||
|
* around that.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* Internally locks the driver context.
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* Returns 0 on success or positive error code on failure.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
ti_prcm_clk_get_source_freq(clk_ident_t clk, unsigned int *freq)
|
||||||
|
{
|
||||||
|
struct ti_clock_dev *clk_dev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Find the clock within the devmap - it's a bit inefficent having a for
|
||||||
|
* loop for this, but this function should only called when a driver is
|
||||||
|
* being activated so IMHO not a big issue.
|
||||||
|
*/
|
||||||
|
clk_dev = ti_prcm_clk_dev(clk);
|
||||||
|
|
||||||
|
/* Sanity check we managed to find the clock */
|
||||||
|
if (clk_dev == NULL)
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
/* Get the source frequency of the clock */
|
||||||
|
if (clk_dev->clk_get_source_freq)
|
||||||
|
ret = clk_dev->clk_get_source_freq(clk_dev, freq);
|
||||||
|
else
|
||||||
|
ret = EINVAL;
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ti_prcm_clk_set_source_freq - sets the source clock frequency as close to freq as possible
|
||||||
|
* @clk: identifier for the module to enable, see ti_prcm.h for a list
|
||||||
|
* of possible modules.
|
||||||
|
* @freq: requested freq
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* Internally locks the driver context.
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* Returns 0 on success or positive error code on failure.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
ti_prcm_clk_set_source_freq(clk_ident_t clk, unsigned int freq)
|
||||||
|
{
|
||||||
|
struct ti_clock_dev *clk_dev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
clk_dev = ti_prcm_clk_dev(clk);
|
||||||
|
|
||||||
|
/* Sanity check we managed to find the clock */
|
||||||
|
if (clk_dev == NULL)
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
/* Get the source frequency of the clock */
|
||||||
|
if (clk_dev->clk_set_source_freq)
|
||||||
|
ret = clk_dev->clk_set_source_freq(clk_dev, freq);
|
||||||
|
else
|
||||||
|
ret = EINVAL;
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
207
freebsd/sys/arm/ti/ti_prcm.h
Normal file
207
freebsd/sys/arm/ti/ti_prcm.h
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2010
|
||||||
|
* Ben Gray <ben.r.gray@gmail.com>.
|
||||||
|
* 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.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by Ben Gray.
|
||||||
|
* 4. The name of the company nor the name of the author may be used to
|
||||||
|
* endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BEN GRAY ``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 BEN GRAY 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$
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Texas Instruments - OMAP3xxx series processors
|
||||||
|
*
|
||||||
|
* Reference:
|
||||||
|
* OMAP35x Applications Processor
|
||||||
|
* Technical Reference Manual
|
||||||
|
* (omap35xx_techref.pdf)
|
||||||
|
*/
|
||||||
|
#ifndef _TI_PRCM_H_
|
||||||
|
#define _TI_PRCM_H_
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
|
||||||
|
INVALID_CLK_IDENT = 0,
|
||||||
|
|
||||||
|
/* System clocks, typically you can only call ti_prcm_clk_get_source_freq()
|
||||||
|
* on these clocks as they are enabled by default.
|
||||||
|
*/
|
||||||
|
SYS_CLK = 1,
|
||||||
|
|
||||||
|
/* The MPU (ARM) core clock */
|
||||||
|
MPU_CLK = 20,
|
||||||
|
|
||||||
|
/* MMC modules */
|
||||||
|
MMC1_CLK = 100,
|
||||||
|
MMC2_CLK,
|
||||||
|
MMC3_CLK,
|
||||||
|
MMC4_CLK,
|
||||||
|
MMC5_CLK,
|
||||||
|
MMC6_CLK,
|
||||||
|
|
||||||
|
/* I2C modules */
|
||||||
|
I2C1_CLK = 200,
|
||||||
|
I2C2_CLK,
|
||||||
|
I2C3_CLK,
|
||||||
|
I2C4_CLK,
|
||||||
|
I2C5_CLK,
|
||||||
|
|
||||||
|
/* USB module(s) */
|
||||||
|
USBTLL_CLK = 300,
|
||||||
|
USBHSHOST_CLK,
|
||||||
|
USBFSHOST_CLK,
|
||||||
|
USBP1_PHY_CLK,
|
||||||
|
USBP2_PHY_CLK,
|
||||||
|
USBP1_UTMI_CLK,
|
||||||
|
USBP2_UTMI_CLK,
|
||||||
|
USBP1_HSIC_CLK,
|
||||||
|
USBP2_HSIC_CLK,
|
||||||
|
|
||||||
|
/* UART modules */
|
||||||
|
UART1_CLK = 400,
|
||||||
|
UART2_CLK,
|
||||||
|
UART3_CLK,
|
||||||
|
UART4_CLK,
|
||||||
|
UART5_CLK,
|
||||||
|
UART6_CLK,
|
||||||
|
UART7_CLK,
|
||||||
|
UART8_CLK,
|
||||||
|
UART9_CLK,
|
||||||
|
|
||||||
|
/* General purpose timer modules */
|
||||||
|
TIMER1_CLK = 500,
|
||||||
|
TIMER2_CLK,
|
||||||
|
TIMER3_CLK,
|
||||||
|
TIMER4_CLK,
|
||||||
|
TIMER5_CLK,
|
||||||
|
TIMER6_CLK,
|
||||||
|
TIMER7_CLK,
|
||||||
|
TIMER8_CLK,
|
||||||
|
TIMER9_CLK,
|
||||||
|
TIMER10_CLK,
|
||||||
|
TIMER11_CLK,
|
||||||
|
TIMER12_CLK,
|
||||||
|
|
||||||
|
/* McBSP module(s) */
|
||||||
|
MCBSP1_CLK = 600,
|
||||||
|
MCBSP2_CLK,
|
||||||
|
MCBSP3_CLK,
|
||||||
|
MCBSP4_CLK,
|
||||||
|
MCBSP5_CLK,
|
||||||
|
|
||||||
|
/* General purpose I/O modules */
|
||||||
|
GPIO1_CLK = 700,
|
||||||
|
GPIO2_CLK,
|
||||||
|
GPIO3_CLK,
|
||||||
|
GPIO4_CLK,
|
||||||
|
GPIO5_CLK,
|
||||||
|
GPIO6_CLK,
|
||||||
|
GPIO7_CLK,
|
||||||
|
|
||||||
|
/* sDMA module */
|
||||||
|
SDMA_CLK = 800,
|
||||||
|
|
||||||
|
/* CPSW modules */
|
||||||
|
CPSW_CLK = 1000,
|
||||||
|
|
||||||
|
/* Mentor USB modules */
|
||||||
|
MUSB0_CLK = 1100,
|
||||||
|
|
||||||
|
/* EDMA module */
|
||||||
|
EDMA_TPCC_CLK = 1200,
|
||||||
|
EDMA_TPTC0_CLK,
|
||||||
|
EDMA_TPTC1_CLK,
|
||||||
|
EDMA_TPTC2_CLK,
|
||||||
|
|
||||||
|
/* LCD controller module */
|
||||||
|
LCDC_CLK = 1300,
|
||||||
|
|
||||||
|
/* PWM modules */
|
||||||
|
PWMSS0_CLK = 1400,
|
||||||
|
PWMSS1_CLK,
|
||||||
|
PWMSS2_CLK,
|
||||||
|
|
||||||
|
/* Mailbox modules */
|
||||||
|
MAILBOX0_CLK = 1500,
|
||||||
|
|
||||||
|
/* Spinlock modules */
|
||||||
|
SPINLOCK0_CLK = 1600,
|
||||||
|
|
||||||
|
PRUSS_CLK = 1700,
|
||||||
|
|
||||||
|
TSC_ADC_CLK = 1800,
|
||||||
|
|
||||||
|
/* RTC module */
|
||||||
|
RTC_CLK = 1900,
|
||||||
|
|
||||||
|
/* McSPI */
|
||||||
|
SPI0_CLK = 2000,
|
||||||
|
SPI1_CLK,
|
||||||
|
} clk_ident_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
SYSCLK_CLK, /* System clock */
|
||||||
|
EXT_CLK,
|
||||||
|
|
||||||
|
F32KHZ_CLK, /* 32KHz clock */
|
||||||
|
F48MHZ_CLK, /* 48MHz clock */
|
||||||
|
F64MHZ_CLK, /* 64MHz clock */
|
||||||
|
F96MHZ_CLK, /* 96MHz clock */
|
||||||
|
|
||||||
|
} clk_src_t;
|
||||||
|
|
||||||
|
struct ti_clock_dev {
|
||||||
|
/* The profile of the timer */
|
||||||
|
clk_ident_t id;
|
||||||
|
|
||||||
|
/* A bunch of callbacks associated with the clock device */
|
||||||
|
int (*clk_activate)(struct ti_clock_dev *clkdev);
|
||||||
|
int (*clk_deactivate)(struct ti_clock_dev *clkdev);
|
||||||
|
int (*clk_set_source)(struct ti_clock_dev *clkdev,
|
||||||
|
clk_src_t clksrc);
|
||||||
|
int (*clk_accessible)(struct ti_clock_dev *clkdev);
|
||||||
|
int (*clk_set_source_freq)(struct ti_clock_dev *clkdev,
|
||||||
|
unsigned int freq);
|
||||||
|
int (*clk_get_source_freq)(struct ti_clock_dev *clkdev,
|
||||||
|
unsigned int *freq);
|
||||||
|
};
|
||||||
|
|
||||||
|
int ti_prcm_clk_valid(clk_ident_t clk);
|
||||||
|
int ti_prcm_clk_enable(clk_ident_t clk);
|
||||||
|
int ti_prcm_clk_disable(clk_ident_t clk);
|
||||||
|
int ti_prcm_clk_accessible(clk_ident_t clk);
|
||||||
|
int ti_prcm_clk_disable_autoidle(clk_ident_t clk);
|
||||||
|
int ti_prcm_clk_set_source(clk_ident_t clk, clk_src_t clksrc);
|
||||||
|
int ti_prcm_clk_set_source_freq(clk_ident_t clk, unsigned int freq);
|
||||||
|
int ti_prcm_clk_get_source_freq(clk_ident_t clk, unsigned int *freq);
|
||||||
|
void ti_prcm_reset(void);
|
||||||
|
|
||||||
|
#endif /* _TI_PRCM_H_ */
|
176
freebsd/sys/arm/ti/ti_scm.c
Normal file
176
freebsd/sys/arm/ti/ti_scm.c
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
#include <machine/rtems-bsd-kernel-space.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010
|
||||||
|
* Ben Gray <ben.r.gray@gmail.com>.
|
||||||
|
* 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.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by Ben Gray.
|
||||||
|
* 4. The name of the company nor the name of the author may be used to
|
||||||
|
* endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BEN GRAY ``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 BEN GRAY 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SCM - System Control Module
|
||||||
|
*
|
||||||
|
* Hopefully in the end this module will contain a bunch of utility functions
|
||||||
|
* for configuring and querying the general system control registers, but for
|
||||||
|
* now it only does pin(pad) multiplexing.
|
||||||
|
*
|
||||||
|
* This is different from the GPIO module in that it is used to configure the
|
||||||
|
* pins between modules not just GPIO input/output.
|
||||||
|
*
|
||||||
|
* This file contains the generic top level driver, however it relies on chip
|
||||||
|
* specific settings and therefore expects an array of ti_scm_padconf structs
|
||||||
|
* call ti_padconf_devmap to be located somewhere in the kernel.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#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 <rtems/bsd/sys/resource.h>
|
||||||
|
#include <sys/rman.h>
|
||||||
|
#include <sys/lock.h>
|
||||||
|
#include <sys/mutex.h>
|
||||||
|
|
||||||
|
#include <machine/bus.h>
|
||||||
|
#include <machine/resource.h>
|
||||||
|
|
||||||
|
#include <dev/ofw/openfirm.h>
|
||||||
|
#include <dev/ofw/ofw_bus.h>
|
||||||
|
#include <dev/ofw/ofw_bus_subr.h>
|
||||||
|
#include <dev/fdt/fdt_pinctrl.h>
|
||||||
|
|
||||||
|
#include "ti_scm.h"
|
||||||
|
|
||||||
|
static struct resource_spec ti_scm_res_spec[] = {
|
||||||
|
{ SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Control memory window */
|
||||||
|
{ -1, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct ti_scm_softc *ti_scm_sc;
|
||||||
|
|
||||||
|
#define ti_scm_read_4(sc, reg) \
|
||||||
|
bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
|
||||||
|
#define ti_scm_write_4(sc, reg, val) \
|
||||||
|
bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Device part of OMAP SCM driver
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
ti_scm_probe(device_t dev)
|
||||||
|
{
|
||||||
|
if (!ofw_bus_status_okay(dev))
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
|
if (!ofw_bus_is_compatible(dev, "syscon"))
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
|
if (ti_scm_sc) {
|
||||||
|
return (EEXIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
device_set_desc(dev, "TI Control Module");
|
||||||
|
return (BUS_PROBE_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ti_scm_attach - attaches the timer to the simplebus
|
||||||
|
* @dev: new device
|
||||||
|
*
|
||||||
|
* Reserves memory and interrupt resources, stores the softc structure
|
||||||
|
* globally and registers both the timecount and eventtimer objects.
|
||||||
|
*
|
||||||
|
* RETURNS
|
||||||
|
* Zero on success or ENXIO if an error occuried.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
ti_scm_attach(device_t dev)
|
||||||
|
{
|
||||||
|
struct ti_scm_softc *sc = device_get_softc(dev);
|
||||||
|
|
||||||
|
sc->sc_dev = dev;
|
||||||
|
|
||||||
|
if (bus_alloc_resources(dev, ti_scm_res_spec, sc->sc_res)) {
|
||||||
|
device_printf(dev, "could not allocate resources\n");
|
||||||
|
return (ENXIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Global timer interface */
|
||||||
|
sc->sc_bst = rman_get_bustag(sc->sc_res[0]);
|
||||||
|
sc->sc_bsh = rman_get_bushandle(sc->sc_res[0]);
|
||||||
|
|
||||||
|
ti_scm_sc = sc;
|
||||||
|
|
||||||
|
/* Attach platform extensions, if any. */
|
||||||
|
bus_generic_probe(dev);
|
||||||
|
|
||||||
|
return (bus_generic_attach(dev));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ti_scm_reg_read_4(uint32_t reg, uint32_t *val)
|
||||||
|
{
|
||||||
|
if (!ti_scm_sc)
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
|
*val = ti_scm_read_4(ti_scm_sc, reg);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ti_scm_reg_write_4(uint32_t reg, uint32_t val)
|
||||||
|
{
|
||||||
|
if (!ti_scm_sc)
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
|
ti_scm_write_4(ti_scm_sc, reg, val);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static device_method_t ti_scm_methods[] = {
|
||||||
|
DEVMETHOD(device_probe, ti_scm_probe),
|
||||||
|
DEVMETHOD(device_attach, ti_scm_attach),
|
||||||
|
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static driver_t ti_scm_driver = {
|
||||||
|
"ti_scm",
|
||||||
|
ti_scm_methods,
|
||||||
|
sizeof(struct ti_scm_softc),
|
||||||
|
};
|
||||||
|
|
||||||
|
static devclass_t ti_scm_devclass;
|
||||||
|
|
||||||
|
EARLY_DRIVER_MODULE(ti_scm, simplebus, ti_scm_driver, ti_scm_devclass, 0, 0,
|
||||||
|
BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
|
56
freebsd/sys/arm/ti/ti_scm.h
Normal file
56
freebsd/sys/arm/ti/ti_scm.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2010
|
||||||
|
* Ben Gray <ben.r.gray@gmail.com>.
|
||||||
|
* 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.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by Ben Gray.
|
||||||
|
* 4. The name of the company nor the name of the author may be used to
|
||||||
|
* endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BEN GRAY ``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 BEN GRAY 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$
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functions to configure the PIN multiplexing on the chip.
|
||||||
|
*
|
||||||
|
* This is different from the GPIO module in that it is used to configure the
|
||||||
|
* pins between modules not just GPIO input output.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _TI_SCM_H_
|
||||||
|
#define _TI_SCM_H_
|
||||||
|
|
||||||
|
struct ti_scm_softc {
|
||||||
|
device_t sc_dev;
|
||||||
|
struct resource * sc_res[4];
|
||||||
|
bus_space_tag_t sc_bst;
|
||||||
|
bus_space_handle_t sc_bsh;
|
||||||
|
};
|
||||||
|
|
||||||
|
int ti_scm_reg_read_4(uint32_t reg, uint32_t *val);
|
||||||
|
int ti_scm_reg_write_4(uint32_t reg, uint32_t val);
|
||||||
|
|
||||||
|
#endif /* _TI_SCM_H_ */
|
41
freebsd/sys/arm/ti/tivar.h
Normal file
41
freebsd/sys/arm/ti/tivar.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2010
|
||||||
|
* Ben Gray <ben.r.gray@gmail.com>.
|
||||||
|
* 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.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by Ben Gray.
|
||||||
|
* 4. The name of the company nor the name of the author may be used to
|
||||||
|
* endorse or promote products derived from this software without specific
|
||||||
|
* prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BEN GRAY ``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 BEN GRAY 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 _TIVAR_H_
|
||||||
|
#define _TIVAR_H_
|
||||||
|
|
||||||
|
/* board-dependent reset function implementation */
|
||||||
|
extern void (*ti_cpu_reset)(void);
|
||||||
|
|
||||||
|
#endif /* _TIVAR_H_ */
|
58
freebsd/sys/dev/fdt/fdt_pinctrl.h
Normal file
58
freebsd/sys/dev/fdt/fdt_pinctrl.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2014 Ian Lepore <ian@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 ``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.
|
||||||
|
*
|
||||||
|
* $FreeBSD$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DEV_FDT_PINCTRL_H
|
||||||
|
#define DEV_FDT_PINCTRL_H
|
||||||
|
|
||||||
|
#include <rtems/bsd/local/fdt_pinctrl_if.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Configure pins by name or index. This looks up the pinctrl-N property in
|
||||||
|
* client's fdt data by index or name, and passes each handle in it to the
|
||||||
|
* pinctrl driver for configuration.
|
||||||
|
*/
|
||||||
|
int fdt_pinctrl_configure(device_t client, u_int index);
|
||||||
|
int fdt_pinctrl_configure_by_name(device_t client, const char * name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register a pinctrl driver so that it can be used by other devices which call
|
||||||
|
* fdt_pinctrl_configure(). The pinprop argument is the name of a property that
|
||||||
|
* identifies each descendent of the pinctrl node which is a pin configuration
|
||||||
|
* node whose xref phandle can be passed to FDT_PINCTRL_CONFIGURE(). If this is
|
||||||
|
* NULL, every descendant node is registered.
|
||||||
|
*/
|
||||||
|
int fdt_pinctrl_register(device_t pinctrl, const char *pinprop);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Walk the device tree and configure pins for each enabled device whose
|
||||||
|
* pinctrl-0 property contains references to nodes which are children of the
|
||||||
|
* given pinctrl device. This helper routine is for use by pinctrl drivers.
|
||||||
|
*/
|
||||||
|
int fdt_pinctrl_configure_tree(device_t pinctrl);
|
||||||
|
|
||||||
|
#endif /* DEV_FDT_PINCTRL_H */
|
||||||
|
|
4257
freebsd/sys/dev/usb/controller/musb_otg.c
Normal file
4257
freebsd/sys/dev/usb/controller/musb_otg.c
Normal file
File diff suppressed because it is too large
Load Diff
435
freebsd/sys/dev/usb/controller/musb_otg.h
Normal file
435
freebsd/sys/dev/usb/controller/musb_otg.h
Normal file
@ -0,0 +1,435 @@
|
|||||||
|
/* $FreeBSD$ */
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2008 Hans Petter Selasky. 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This header file defines the registers of the Mentor Graphics USB OnTheGo
|
||||||
|
* Inventra chip.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _MUSB2_OTG_H_
|
||||||
|
#define _MUSB2_OTG_H_
|
||||||
|
|
||||||
|
#define MUSB2_MAX_DEVICES USB_MAX_DEVICES
|
||||||
|
|
||||||
|
/* Common registers */
|
||||||
|
|
||||||
|
#define MUSB2_REG_FADDR 0x0000 /* function address register */
|
||||||
|
#define MUSB2_MASK_FADDR 0x7F
|
||||||
|
|
||||||
|
#define MUSB2_REG_POWER 0x0001 /* power register */
|
||||||
|
#define MUSB2_MASK_SUSPM_ENA 0x01
|
||||||
|
#define MUSB2_MASK_SUSPMODE 0x02
|
||||||
|
#define MUSB2_MASK_RESUME 0x04
|
||||||
|
#define MUSB2_MASK_RESET 0x08
|
||||||
|
#define MUSB2_MASK_HSMODE 0x10
|
||||||
|
#define MUSB2_MASK_HSENAB 0x20
|
||||||
|
#define MUSB2_MASK_SOFTC 0x40
|
||||||
|
#define MUSB2_MASK_ISOUPD 0x80
|
||||||
|
|
||||||
|
/* Endpoint interrupt handling */
|
||||||
|
|
||||||
|
#define MUSB2_REG_INTTX 0x0002 /* transmit interrupt register */
|
||||||
|
#define MUSB2_REG_INTRX 0x0004 /* receive interrupt register */
|
||||||
|
#define MUSB2_REG_INTTXE 0x0006 /* transmit interrupt enable register */
|
||||||
|
#define MUSB2_REG_INTRXE 0x0008 /* receive interrupt enable register */
|
||||||
|
#define MUSB2_MASK_EPINT(epn) (1 << (epn)) /* epn = [0..15] */
|
||||||
|
|
||||||
|
/* Common interrupt handling */
|
||||||
|
|
||||||
|
#define MUSB2_REG_INTUSB 0x000A /* USB interrupt register */
|
||||||
|
#define MUSB2_MASK_ISUSP 0x01
|
||||||
|
#define MUSB2_MASK_IRESUME 0x02
|
||||||
|
#define MUSB2_MASK_IRESET 0x04
|
||||||
|
#define MUSB2_MASK_IBABBLE 0x04
|
||||||
|
#define MUSB2_MASK_ISOF 0x08
|
||||||
|
#define MUSB2_MASK_ICONN 0x10
|
||||||
|
#define MUSB2_MASK_IDISC 0x20
|
||||||
|
#define MUSB2_MASK_ISESSRQ 0x40
|
||||||
|
#define MUSB2_MASK_IVBUSERR 0x80
|
||||||
|
|
||||||
|
#define MUSB2_REG_INTUSBE 0x000B /* USB interrupt enable register */
|
||||||
|
#define MUSB2_REG_FRAME 0x000C /* USB frame register */
|
||||||
|
#define MUSB2_MASK_FRAME 0x3FF /* 0..1023 */
|
||||||
|
|
||||||
|
#define MUSB2_REG_EPINDEX 0x000E /* endpoint index register */
|
||||||
|
#define MUSB2_MASK_EPINDEX 0x0F
|
||||||
|
|
||||||
|
#define MUSB2_REG_TESTMODE 0x000F /* test mode register */
|
||||||
|
#define MUSB2_MASK_TSE0_NAK 0x01
|
||||||
|
#define MUSB2_MASK_TJ 0x02
|
||||||
|
#define MUSB2_MASK_TK 0x04
|
||||||
|
#define MUSB2_MASK_TPACKET 0x08
|
||||||
|
#define MUSB2_MASK_TFORCE_HS 0x10
|
||||||
|
#define MUSB2_MASK_TFORCE_LS 0x20
|
||||||
|
#define MUSB2_MASK_TFIFO_ACC 0x40
|
||||||
|
#define MUSB2_MASK_TFORCE_HC 0x80
|
||||||
|
|
||||||
|
#define MUSB2_REG_INDEXED_CSR 0x0010 /* EP control status register offset */
|
||||||
|
|
||||||
|
#define MUSB2_REG_TXMAXP (0x0000 + MUSB2_REG_INDEXED_CSR)
|
||||||
|
#define MUSB2_REG_RXMAXP (0x0004 + MUSB2_REG_INDEXED_CSR)
|
||||||
|
#define MUSB2_MASK_PKTSIZE 0x03FF /* in bytes, should be even */
|
||||||
|
#define MUSB2_MASK_PKTMULT 0xFC00 /* HS packet multiplier: 0..2 */
|
||||||
|
|
||||||
|
#define MUSB2_REG_TXCSRL (0x0002 + MUSB2_REG_INDEXED_CSR)
|
||||||
|
#define MUSB2_MASK_CSRL_TXPKTRDY 0x01
|
||||||
|
#define MUSB2_MASK_CSRL_TXFIFONEMPTY 0x02
|
||||||
|
#define MUSB2_MASK_CSRL_TXUNDERRUN 0x04 /* Device Mode */
|
||||||
|
#define MUSB2_MASK_CSRL_TXERROR 0x04 /* Host Mode */
|
||||||
|
#define MUSB2_MASK_CSRL_TXFFLUSH 0x08
|
||||||
|
#define MUSB2_MASK_CSRL_TXSENDSTALL 0x10/* Device Mode */
|
||||||
|
#define MUSB2_MASK_CSRL_TXSETUPPKT 0x10 /* Host Mode */
|
||||||
|
#define MUSB2_MASK_CSRL_TXSENTSTALL 0x20/* Device Mode */
|
||||||
|
#define MUSB2_MASK_CSRL_TXSTALLED 0x20 /* Host Mode */
|
||||||
|
#define MUSB2_MASK_CSRL_TXDT_CLR 0x40
|
||||||
|
#define MUSB2_MASK_CSRL_TXINCOMP 0x80 /* Device mode */
|
||||||
|
#define MUSB2_MASK_CSRL_TXNAKTO 0x80 /* Host mode */
|
||||||
|
|
||||||
|
/* Device Side Mode */
|
||||||
|
#define MUSB2_MASK_CSR0L_RXPKTRDY 0x01
|
||||||
|
#define MUSB2_MASK_CSR0L_TXPKTRDY 0x02
|
||||||
|
#define MUSB2_MASK_CSR0L_SENTSTALL 0x04
|
||||||
|
#define MUSB2_MASK_CSR0L_DATAEND 0x08
|
||||||
|
#define MUSB2_MASK_CSR0L_SETUPEND 0x10
|
||||||
|
#define MUSB2_MASK_CSR0L_SENDSTALL 0x20
|
||||||
|
#define MUSB2_MASK_CSR0L_RXPKTRDY_CLR 0x40
|
||||||
|
#define MUSB2_MASK_CSR0L_SETUPEND_CLR 0x80
|
||||||
|
|
||||||
|
/* Host Side Mode */
|
||||||
|
#define MUSB2_MASK_CSR0L_TXFIFONEMPTY 0x02
|
||||||
|
#define MUSB2_MASK_CSR0L_RXSTALL 0x04
|
||||||
|
#define MUSB2_MASK_CSR0L_SETUPPKT 0x08
|
||||||
|
#define MUSB2_MASK_CSR0L_ERROR 0x10
|
||||||
|
#define MUSB2_MASK_CSR0L_REQPKT 0x20
|
||||||
|
#define MUSB2_MASK_CSR0L_STATUSPKT 0x40
|
||||||
|
#define MUSB2_MASK_CSR0L_NAKTIMO 0x80
|
||||||
|
|
||||||
|
#define MUSB2_REG_TXCSRH (0x0003 + MUSB2_REG_INDEXED_CSR)
|
||||||
|
#define MUSB2_MASK_CSRH_TXDT_VAL 0x01 /* Host Mode */
|
||||||
|
#define MUSB2_MASK_CSRH_TXDT_WREN 0x02 /* Host Mode */
|
||||||
|
#define MUSB2_MASK_CSRH_TXDMAREQMODE 0x04
|
||||||
|
#define MUSB2_MASK_CSRH_TXDT_SWITCH 0x08
|
||||||
|
#define MUSB2_MASK_CSRH_TXDMAREQENA 0x10
|
||||||
|
#define MUSB2_MASK_CSRH_RXMODE 0x00
|
||||||
|
#define MUSB2_MASK_CSRH_TXMODE 0x20
|
||||||
|
#define MUSB2_MASK_CSRH_TXISO 0x40 /* Device Mode */
|
||||||
|
#define MUSB2_MASK_CSRH_TXAUTOSET 0x80
|
||||||
|
|
||||||
|
#define MUSB2_MASK_CSR0H_FFLUSH 0x01 /* Device Side flush FIFO */
|
||||||
|
#define MUSB2_MASK_CSR0H_DT 0x02 /* Host Side data toggle */
|
||||||
|
#define MUSB2_MASK_CSR0H_DT_WREN 0x04 /* Host Side */
|
||||||
|
#define MUSB2_MASK_CSR0H_PING_DIS 0x08 /* Host Side */
|
||||||
|
|
||||||
|
#define MUSB2_REG_RXCSRL (0x0006 + MUSB2_REG_INDEXED_CSR)
|
||||||
|
#define MUSB2_MASK_CSRL_RXPKTRDY 0x01
|
||||||
|
#define MUSB2_MASK_CSRL_RXFIFOFULL 0x02
|
||||||
|
#define MUSB2_MASK_CSRL_RXOVERRUN 0x04 /* Device Mode */
|
||||||
|
#define MUSB2_MASK_CSRL_RXERROR 0x04 /* Host Mode */
|
||||||
|
#define MUSB2_MASK_CSRL_RXDATAERR 0x08 /* Device Mode */
|
||||||
|
#define MUSB2_MASK_CSRL_RXNAKTO 0x08 /* Host Mode */
|
||||||
|
#define MUSB2_MASK_CSRL_RXFFLUSH 0x10
|
||||||
|
#define MUSB2_MASK_CSRL_RXSENDSTALL 0x20/* Device Mode */
|
||||||
|
#define MUSB2_MASK_CSRL_RXREQPKT 0x20 /* Host Mode */
|
||||||
|
#define MUSB2_MASK_CSRL_RXSENTSTALL 0x40/* Device Mode */
|
||||||
|
#define MUSB2_MASK_CSRL_RXSTALL 0x40 /* Host Mode */
|
||||||
|
#define MUSB2_MASK_CSRL_RXDT_CLR 0x80
|
||||||
|
|
||||||
|
#define MUSB2_REG_RXCSRH (0x0007 + MUSB2_REG_INDEXED_CSR)
|
||||||
|
#define MUSB2_MASK_CSRH_RXINCOMP 0x01
|
||||||
|
#define MUSB2_MASK_CSRH_RXDT_VAL 0x02 /* Host Mode */
|
||||||
|
#define MUSB2_MASK_CSRH_RXDT_WREN 0x04 /* Host Mode */
|
||||||
|
#define MUSB2_MASK_CSRH_RXDMAREQMODE 0x08
|
||||||
|
#define MUSB2_MASK_CSRH_RXNYET 0x10
|
||||||
|
#define MUSB2_MASK_CSRH_RXDMAREQENA 0x20
|
||||||
|
#define MUSB2_MASK_CSRH_RXISO 0x40 /* Device Mode */
|
||||||
|
#define MUSB2_MASK_CSRH_RXAUTOREQ 0x40 /* Host Mode */
|
||||||
|
#define MUSB2_MASK_CSRH_RXAUTOCLEAR 0x80
|
||||||
|
|
||||||
|
#define MUSB2_REG_RXCOUNT (0x0008 + MUSB2_REG_INDEXED_CSR)
|
||||||
|
#define MUSB2_MASK_RXCOUNT 0xFFFF
|
||||||
|
|
||||||
|
#define MUSB2_REG_TXTI (0x000A + MUSB2_REG_INDEXED_CSR)
|
||||||
|
#define MUSB2_REG_RXTI (0x000C + MUSB2_REG_INDEXED_CSR)
|
||||||
|
|
||||||
|
/* Host Mode */
|
||||||
|
#define MUSB2_MASK_TI_SPEED 0xC0
|
||||||
|
#define MUSB2_MASK_TI_SPEED_LO 0xC0
|
||||||
|
#define MUSB2_MASK_TI_SPEED_FS 0x80
|
||||||
|
#define MUSB2_MASK_TI_SPEED_HS 0x40
|
||||||
|
#define MUSB2_MASK_TI_PROTO_CTRL 0x00
|
||||||
|
#define MUSB2_MASK_TI_PROTO_ISOC 0x10
|
||||||
|
#define MUSB2_MASK_TI_PROTO_BULK 0x20
|
||||||
|
#define MUSB2_MASK_TI_PROTO_INTR 0x30
|
||||||
|
#define MUSB2_MASK_TI_EP_NUM 0x0F
|
||||||
|
|
||||||
|
#define MUSB2_REG_TXNAKLIMIT (0x000B /* EPN=0 */ + MUSB2_REG_INDEXED_CSR)
|
||||||
|
#define MUSB2_REG_RXNAKLIMIT (0x000D /* EPN=0 */ + MUSB2_REG_INDEXED_CSR)
|
||||||
|
#define MUSB2_MASK_NAKLIMIT 0xFF
|
||||||
|
|
||||||
|
#define MUSB2_REG_FSIZE (0x000F + MUSB2_REG_INDEXED_CSR)
|
||||||
|
#define MUSB2_MASK_RX_FSIZE 0xF0 /* 3..13, 2**n bytes */
|
||||||
|
#define MUSB2_MASK_TX_FSIZE 0x0F /* 3..13, 2**n bytes */
|
||||||
|
|
||||||
|
#define MUSB2_REG_EPFIFO(n) (0x0020 + (4*(n)))
|
||||||
|
|
||||||
|
#define MUSB2_REG_CONFDATA (0x000F + MUSB2_REG_INDEXED_CSR) /* EPN=0 */
|
||||||
|
#define MUSB2_MASK_CD_UTMI_DW 0x01
|
||||||
|
#define MUSB2_MASK_CD_SOFTCONE 0x02
|
||||||
|
#define MUSB2_MASK_CD_DYNFIFOSZ 0x04
|
||||||
|
#define MUSB2_MASK_CD_HBTXE 0x08
|
||||||
|
#define MUSB2_MASK_CD_HBRXE 0x10
|
||||||
|
#define MUSB2_MASK_CD_BIGEND 0x20
|
||||||
|
#define MUSB2_MASK_CD_MPTXE 0x40
|
||||||
|
#define MUSB2_MASK_CD_MPRXE 0x80
|
||||||
|
|
||||||
|
/* Various registers */
|
||||||
|
|
||||||
|
#define MUSB2_REG_DEVCTL 0x0060
|
||||||
|
#define MUSB2_MASK_SESS 0x01
|
||||||
|
#define MUSB2_MASK_HOSTREQ 0x02
|
||||||
|
#define MUSB2_MASK_HOSTMD 0x04
|
||||||
|
#define MUSB2_MASK_VBUS0 0x08
|
||||||
|
#define MUSB2_MASK_VBUS1 0x10
|
||||||
|
#define MUSB2_MASK_LSDEV 0x20
|
||||||
|
#define MUSB2_MASK_FSDEV 0x40
|
||||||
|
#define MUSB2_MASK_BDEV 0x80
|
||||||
|
|
||||||
|
#define MUSB2_REG_MISC 0x0061
|
||||||
|
#define MUSB2_MASK_RXEDMA 0x01
|
||||||
|
#define MUSB2_MASK_TXEDMA 0x02
|
||||||
|
|
||||||
|
#define MUSB2_REG_TXFIFOSZ 0x0062
|
||||||
|
#define MUSB2_REG_RXFIFOSZ 0x0063
|
||||||
|
#define MUSB2_MASK_FIFODB 0x10 /* set if double buffering, r/w */
|
||||||
|
#define MUSB2_MASK_FIFOSZ 0x0F
|
||||||
|
#define MUSB2_VAL_FIFOSZ_8 0
|
||||||
|
#define MUSB2_VAL_FIFOSZ_16 1
|
||||||
|
#define MUSB2_VAL_FIFOSZ_32 2
|
||||||
|
#define MUSB2_VAL_FIFOSZ_64 3
|
||||||
|
#define MUSB2_VAL_FIFOSZ_128 4
|
||||||
|
#define MUSB2_VAL_FIFOSZ_256 5
|
||||||
|
#define MUSB2_VAL_FIFOSZ_512 6
|
||||||
|
#define MUSB2_VAL_FIFOSZ_1024 7
|
||||||
|
#define MUSB2_VAL_FIFOSZ_2048 8
|
||||||
|
#define MUSB2_VAL_FIFOSZ_4096 9
|
||||||
|
|
||||||
|
#define MUSB2_REG_TXFIFOADD 0x0064
|
||||||
|
#define MUSB2_REG_RXFIFOADD 0x0066
|
||||||
|
#define MUSB2_MASK_FIFOADD 0xFFF /* unit is 8-bytes */
|
||||||
|
|
||||||
|
#define MUSB2_REG_VSTATUS 0x0068
|
||||||
|
#define MUSB2_REG_VCONTROL 0x0068
|
||||||
|
#define MUSB2_REG_HWVERS 0x006C
|
||||||
|
#define MUSB2_REG_ULPI_BASE 0x0070
|
||||||
|
|
||||||
|
#define MUSB2_REG_EPINFO 0x0078
|
||||||
|
#define MUSB2_MASK_NRXEP 0xF0
|
||||||
|
#define MUSB2_MASK_NTXEP 0x0F
|
||||||
|
|
||||||
|
#define MUSB2_REG_RAMINFO 0x0079
|
||||||
|
#define MUSB2_REG_LINKINFO 0x007A
|
||||||
|
|
||||||
|
#define MUSB2_REG_VPLEN 0x007B
|
||||||
|
#define MUSB2_MASK_VPLEN 0xFF
|
||||||
|
|
||||||
|
#define MUSB2_REG_HS_EOF1 0x007C
|
||||||
|
#define MUSB2_REG_FS_EOF1 0x007D
|
||||||
|
#define MUSB2_REG_LS_EOF1 0x007E
|
||||||
|
#define MUSB2_REG_SOFT_RST 0x007F
|
||||||
|
#define MUSB2_MASK_SRST 0x01
|
||||||
|
#define MUSB2_MASK_SRSTX 0x02
|
||||||
|
|
||||||
|
#define MUSB2_REG_RQPKTCOUNT(n) (0x0300 + (4*(n))
|
||||||
|
#define MUSB2_REG_RXDBDIS 0x0340
|
||||||
|
#define MUSB2_REG_TXDBDIS 0x0342
|
||||||
|
#define MUSB2_MASK_DB(n) (1 << (n)) /* disable double buffer, n = [0..15] */
|
||||||
|
|
||||||
|
#define MUSB2_REG_CHIRPTO 0x0344
|
||||||
|
#define MUSB2_REG_HSRESUM 0x0346
|
||||||
|
|
||||||
|
/* Host Mode only registers */
|
||||||
|
|
||||||
|
#define MUSB2_REG_TXFADDR(n) (0x0080 + (8*(n)))
|
||||||
|
#define MUSB2_REG_TXHADDR(n) (0x0082 + (8*(n)))
|
||||||
|
#define MUSB2_REG_TXHUBPORT(n) (0x0083 + (8*(n)))
|
||||||
|
#define MUSB2_REG_RXFADDR(n) (0x0084 + (8*(n)))
|
||||||
|
#define MUSB2_REG_RXHADDR(n) (0x0086 + (8*(n)))
|
||||||
|
#define MUSB2_REG_RXHUBPORT(n) (0x0087 + (8*(n)))
|
||||||
|
|
||||||
|
#define MUSB2_EP_MAX 16 /* maximum number of endpoints */
|
||||||
|
|
||||||
|
#define MUSB2_DEVICE_MODE 0
|
||||||
|
#define MUSB2_HOST_MODE 1
|
||||||
|
|
||||||
|
#define MUSB2_READ_2(sc, reg) \
|
||||||
|
bus_space_read_2((sc)->sc_io_tag, (sc)->sc_io_hdl, reg)
|
||||||
|
|
||||||
|
#define MUSB2_WRITE_2(sc, reg, data) \
|
||||||
|
bus_space_write_2((sc)->sc_io_tag, (sc)->sc_io_hdl, reg, data)
|
||||||
|
|
||||||
|
#define MUSB2_READ_1(sc, reg) \
|
||||||
|
bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, reg)
|
||||||
|
|
||||||
|
#define MUSB2_WRITE_1(sc, reg, data) \
|
||||||
|
bus_space_write_1((sc)->sc_io_tag, (sc)->sc_io_hdl, reg, data)
|
||||||
|
|
||||||
|
struct musbotg_td;
|
||||||
|
struct musbotg_softc;
|
||||||
|
|
||||||
|
typedef uint8_t (musbotg_cmd_t)(struct musbotg_td *td);
|
||||||
|
|
||||||
|
struct musbotg_dma {
|
||||||
|
struct musbotg_softc *sc;
|
||||||
|
uint32_t dma_chan;
|
||||||
|
uint8_t busy:1;
|
||||||
|
uint8_t complete:1;
|
||||||
|
uint8_t error:1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct musbotg_td {
|
||||||
|
struct musbotg_td *obj_next;
|
||||||
|
musbotg_cmd_t *func;
|
||||||
|
struct usb_page_cache *pc;
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t remainder;
|
||||||
|
uint16_t max_frame_size; /* packet_size * mult */
|
||||||
|
uint16_t reg_max_packet;
|
||||||
|
uint8_t ep_no;
|
||||||
|
uint8_t transfer_type;
|
||||||
|
uint8_t error:1;
|
||||||
|
uint8_t alt_next:1;
|
||||||
|
uint8_t short_pkt:1;
|
||||||
|
uint8_t support_multi_buffer:1;
|
||||||
|
uint8_t did_stall:1;
|
||||||
|
uint8_t dma_enabled:1;
|
||||||
|
uint8_t transaction_started:1;
|
||||||
|
uint8_t dev_addr;
|
||||||
|
uint8_t toggle;
|
||||||
|
int8_t channel;
|
||||||
|
uint8_t haddr;
|
||||||
|
uint8_t hport;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct musbotg_std_temp {
|
||||||
|
musbotg_cmd_t *func;
|
||||||
|
struct usb_page_cache *pc;
|
||||||
|
struct musbotg_td *td;
|
||||||
|
struct musbotg_td *td_next;
|
||||||
|
uint32_t len;
|
||||||
|
uint32_t offset;
|
||||||
|
uint16_t max_frame_size;
|
||||||
|
uint8_t short_pkt;
|
||||||
|
/*
|
||||||
|
* short_pkt = 0: transfer should be short terminated
|
||||||
|
* short_pkt = 1: transfer should not be short terminated
|
||||||
|
*/
|
||||||
|
uint8_t setup_alt_next;
|
||||||
|
uint8_t did_stall;
|
||||||
|
uint8_t dev_addr;
|
||||||
|
int8_t channel;
|
||||||
|
uint8_t haddr;
|
||||||
|
uint8_t hport;
|
||||||
|
uint8_t transfer_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct musbotg_config_desc {
|
||||||
|
struct usb_config_descriptor confd;
|
||||||
|
struct usb_interface_descriptor ifcd;
|
||||||
|
struct usb_endpoint_descriptor endpd;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
union musbotg_hub_temp {
|
||||||
|
uWord wValue;
|
||||||
|
struct usb_port_status ps;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct musbotg_flags {
|
||||||
|
uint8_t change_connect:1;
|
||||||
|
uint8_t change_suspend:1;
|
||||||
|
uint8_t change_reset:1;
|
||||||
|
uint8_t change_over_current:1;
|
||||||
|
uint8_t change_enabled:1;
|
||||||
|
uint8_t status_suspend:1; /* set if suspended */
|
||||||
|
uint8_t status_vbus:1; /* set if present */
|
||||||
|
uint8_t status_bus_reset:1; /* set if reset complete */
|
||||||
|
uint8_t status_high_speed:1; /* set if High Speed is selected */
|
||||||
|
uint8_t remote_wakeup:1;
|
||||||
|
uint8_t self_powered:1;
|
||||||
|
uint8_t clocks_off:1;
|
||||||
|
uint8_t port_powered:1;
|
||||||
|
uint8_t port_enabled:1;
|
||||||
|
uint8_t port_over_current:1;
|
||||||
|
uint8_t d_pulled_up:1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct musbotg_softc {
|
||||||
|
struct usb_bus sc_bus;
|
||||||
|
union musbotg_hub_temp sc_hub_temp;
|
||||||
|
struct usb_hw_ep_profile sc_hw_ep_profile[MUSB2_EP_MAX];
|
||||||
|
|
||||||
|
struct usb_device *sc_devices[MUSB2_MAX_DEVICES];
|
||||||
|
struct resource *sc_io_res;
|
||||||
|
struct resource *sc_irq_res;
|
||||||
|
void *sc_intr_hdl;
|
||||||
|
bus_size_t sc_io_size;
|
||||||
|
bus_space_tag_t sc_io_tag;
|
||||||
|
bus_space_handle_t sc_io_hdl;
|
||||||
|
|
||||||
|
void (*sc_clocks_on) (void *arg);
|
||||||
|
void (*sc_clocks_off) (void *arg);
|
||||||
|
void (*sc_ep_int_set) (struct musbotg_softc *sc, int ep, int on);
|
||||||
|
void *sc_clocks_arg;
|
||||||
|
|
||||||
|
uint32_t sc_bounce_buf[(1024 * 3) / 4]; /* bounce buffer */
|
||||||
|
|
||||||
|
uint8_t sc_ep_max; /* maximum number of RX and TX
|
||||||
|
* endpoints supported */
|
||||||
|
uint8_t sc_rt_addr; /* root HUB address */
|
||||||
|
uint8_t sc_dv_addr; /* device address */
|
||||||
|
uint8_t sc_conf; /* root HUB config */
|
||||||
|
uint8_t sc_ep0_busy; /* set if ep0 is busy */
|
||||||
|
uint8_t sc_ep0_cmd; /* pending commands */
|
||||||
|
uint8_t sc_conf_data; /* copy of hardware register */
|
||||||
|
|
||||||
|
uint8_t sc_hub_idata[1];
|
||||||
|
uint16_t sc_channel_mask; /* 16 endpoints */
|
||||||
|
|
||||||
|
struct musbotg_flags sc_flags;
|
||||||
|
uint8_t sc_id;
|
||||||
|
uint8_t sc_mode;
|
||||||
|
void *sc_platform_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* prototypes */
|
||||||
|
|
||||||
|
usb_error_t musbotg_init(struct musbotg_softc *sc);
|
||||||
|
void musbotg_uninit(struct musbotg_softc *sc);
|
||||||
|
void musbotg_interrupt(struct musbotg_softc *sc,
|
||||||
|
uint16_t rxstat, uint16_t txstat, uint8_t stat);
|
||||||
|
void musbotg_vbus_interrupt(struct musbotg_softc *sc, uint8_t is_on);
|
||||||
|
void musbotg_connect_interrupt(struct musbotg_softc *sc);
|
||||||
|
|
||||||
|
#endif /* _MUSB2_OTG_H_ */
|
106
freebsd/sys/sys/timeet.h
Normal file
106
freebsd/sys/sys/timeet.h
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2010-2013 Alexander Motin <mav@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,
|
||||||
|
* without modification, immediately at the beginning of the file.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* $FreeBSD$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SYS_TIMEEC_H_
|
||||||
|
#define _SYS_TIMEEC_H_
|
||||||
|
|
||||||
|
#ifndef _KERNEL
|
||||||
|
#error "no user-serviceable parts inside"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/lock.h>
|
||||||
|
#include <sys/mutex.h>
|
||||||
|
#include <sys/queue.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* `struct eventtimer' is the interface between the hardware which implements
|
||||||
|
* a event timer and the MI code which uses this to receive time events.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct eventtimer;
|
||||||
|
typedef int et_start_t(struct eventtimer *et,
|
||||||
|
sbintime_t first, sbintime_t period);
|
||||||
|
typedef int et_stop_t(struct eventtimer *et);
|
||||||
|
typedef void et_event_cb_t(struct eventtimer *et, void *arg);
|
||||||
|
typedef int et_deregister_cb_t(struct eventtimer *et, void *arg);
|
||||||
|
|
||||||
|
struct eventtimer {
|
||||||
|
SLIST_ENTRY(eventtimer) et_all;
|
||||||
|
/* Pointer to the next event timer. */
|
||||||
|
const char *et_name;
|
||||||
|
/* Name of the event timer. */
|
||||||
|
int et_flags;
|
||||||
|
/* Set of capabilities flags: */
|
||||||
|
#define ET_FLAGS_PERIODIC 1
|
||||||
|
#define ET_FLAGS_ONESHOT 2
|
||||||
|
#define ET_FLAGS_PERCPU 4
|
||||||
|
#define ET_FLAGS_C3STOP 8
|
||||||
|
#define ET_FLAGS_POW2DIV 16
|
||||||
|
int et_quality;
|
||||||
|
/*
|
||||||
|
* Used to determine if this timecounter is better than
|
||||||
|
* another timecounter. Higher means better.
|
||||||
|
*/
|
||||||
|
int et_active;
|
||||||
|
u_int64_t et_frequency;
|
||||||
|
/* Base frequency in Hz. */
|
||||||
|
sbintime_t et_min_period;
|
||||||
|
sbintime_t et_max_period;
|
||||||
|
et_start_t *et_start;
|
||||||
|
et_stop_t *et_stop;
|
||||||
|
et_event_cb_t *et_event_cb;
|
||||||
|
et_deregister_cb_t *et_deregister_cb;
|
||||||
|
void *et_arg;
|
||||||
|
void *et_priv;
|
||||||
|
struct sysctl_oid *et_sysctl;
|
||||||
|
/* Pointer to the event timer's private parts. */
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct mtx et_eventtimers_mtx;
|
||||||
|
#define ET_LOCK() mtx_lock(&et_eventtimers_mtx)
|
||||||
|
#define ET_UNLOCK() mtx_unlock(&et_eventtimers_mtx)
|
||||||
|
|
||||||
|
/* Driver API */
|
||||||
|
int et_register(struct eventtimer *et);
|
||||||
|
int et_deregister(struct eventtimer *et);
|
||||||
|
void et_change_frequency(struct eventtimer *et, uint64_t newfreq);
|
||||||
|
/* Consumer API */
|
||||||
|
struct eventtimer *et_find(const char *name, int check, int want);
|
||||||
|
int et_init(struct eventtimer *et, et_event_cb_t *event,
|
||||||
|
et_deregister_cb_t *deregister, void *arg);
|
||||||
|
int et_start(struct eventtimer *et, sbintime_t first, sbintime_t period);
|
||||||
|
int et_stop(struct eventtimer *et);
|
||||||
|
int et_ban(struct eventtimer *et);
|
||||||
|
int et_free(struct eventtimer *et);
|
||||||
|
|
||||||
|
#ifdef SYSCTL_DECL
|
||||||
|
SYSCTL_DECL(_kern_eventtimer);
|
||||||
|
#endif
|
||||||
|
#endif /* !_SYS_TIMETC_H_ */
|
||||||
|
|
115
freebsd/sys/sys/watchdog.h
Normal file
115
freebsd/sys/sys/watchdog.h
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2003 Poul-Henning Kamp
|
||||||
|
* Copyright (c) 2013 iXsystems.com,
|
||||||
|
* author: Alfred Perlstein <alfred@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 _SYS_WATCHDOG_H
|
||||||
|
#define _SYS_WATCHDOG_H
|
||||||
|
|
||||||
|
#include <sys/ioccom.h>
|
||||||
|
|
||||||
|
#define _PATH_WATCHDOG "fido"
|
||||||
|
|
||||||
|
#define WDIOCPATPAT _IOW('W', 42, u_int) /* pat the watchdog */
|
||||||
|
#define WDIOC_SETTIMEOUT _IOW('W', 43, int) /* set/reset the timer */
|
||||||
|
#define WDIOC_GETTIMEOUT _IOR('W', 44, int) /* get total timeout */
|
||||||
|
#define WDIOC_GETTIMELEFT _IOR('W', 45, int) /* get time left */
|
||||||
|
#define WDIOC_GETPRETIMEOUT _IOR('W', 46, int) /* get the pre-timeout */
|
||||||
|
#define WDIOC_SETPRETIMEOUT _IOW('W', 47, int) /* set the pre-timeout */
|
||||||
|
/* set the action when a pre-timeout occurs see: WD_SOFT_* */
|
||||||
|
#define WDIOC_SETPRETIMEOUTACT _IOW('W', 48, int)
|
||||||
|
|
||||||
|
/* use software watchdog instead of hardware */
|
||||||
|
#define WDIOC_SETSOFT _IOW('W', 49, int)
|
||||||
|
#define WDIOC_SETSOFTTIMEOUTACT _IOW('W', 50, int)
|
||||||
|
|
||||||
|
#define WD_ACTIVE 0x8000000
|
||||||
|
/*
|
||||||
|
* Watchdog reset, timeout set to value in WD_INTERVAL field.
|
||||||
|
* The kernel will arm the watchdog and unless the userland
|
||||||
|
* program calls WDIOCPATPAT again before the timer expires
|
||||||
|
* the system will reinitialize.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define WD_PASSIVE 0x0400000
|
||||||
|
/*
|
||||||
|
* Set the watchdog in passive mode.
|
||||||
|
* The kernel will chose an appropriate timeout duration and
|
||||||
|
* periodically reset the timer provided everything looks all
|
||||||
|
* right to the kernel.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define WD_LASTVAL 0x0200000
|
||||||
|
/*
|
||||||
|
* Use the already last used timeout value.
|
||||||
|
* The kernel will use as timeout the last valid timeout provided.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define WD_INTERVAL 0x00000ff
|
||||||
|
/*
|
||||||
|
* Mask for duration bits.
|
||||||
|
* The watchdog will have a nominal patience of 2^N * nanoseconds.
|
||||||
|
* Example: N == 30 gives a patience of 2^30 nanoseconds ~= 1 second.
|
||||||
|
* NB: Expect variance in the +/- 10-20% range.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Handy macros for humans not used to power of two nanoseconds */
|
||||||
|
#define WD_TO_NEVER 0
|
||||||
|
#define WD_TO_1MS 20
|
||||||
|
#define WD_TO_125MS 27
|
||||||
|
#define WD_TO_250MS 28
|
||||||
|
#define WD_TO_500MS 29
|
||||||
|
#define WD_TO_1SEC 30
|
||||||
|
#define WD_TO_2SEC 31
|
||||||
|
#define WD_TO_4SEC 32
|
||||||
|
#define WD_TO_8SEC 33
|
||||||
|
#define WD_TO_16SEC 34
|
||||||
|
#define WD_TO_32SEC 35
|
||||||
|
#define WD_TO_64SEC 36
|
||||||
|
#define WD_TO_128SEC 37
|
||||||
|
|
||||||
|
/* action on pre-timeout trigger */
|
||||||
|
#define WD_SOFT_PANIC 0x01 /* panic */
|
||||||
|
#define WD_SOFT_DDB 0x02 /* enter debugger */
|
||||||
|
#define WD_SOFT_LOG 0x04 /* log(9) */
|
||||||
|
#define WD_SOFT_PRINTF 0x08 /* printf(9) */
|
||||||
|
#define WD_SOFT_MASK 0x0f /* all of the above */
|
||||||
|
|
||||||
|
#ifdef _KERNEL
|
||||||
|
|
||||||
|
#include <sys/eventhandler.h>
|
||||||
|
|
||||||
|
typedef void (*watchdog_fn)(void *, u_int, int *);
|
||||||
|
|
||||||
|
EVENTHANDLER_DECLARE(watchdog_list, watchdog_fn);
|
||||||
|
|
||||||
|
u_int wdog_kern_last_timeout(void);
|
||||||
|
int wdog_kern_pat(u_int utim);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _SYS_WATCHDOG_H */
|
Loading…
x
Reference in New Issue
Block a user