Import am335x usb driver file from FreeBSD.

This commit is contained in:
Sichen Zhao 2017-07-13 10:24:04 +08:00 committed by Sebastian Huber
parent 83574df474
commit bd3c01a126
15 changed files with 7444 additions and 0 deletions

View 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);

View 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);
}

View 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__ */

View 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);

View 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_ */

View 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);
}

View 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
View 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);

View 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_ */

View 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_ */

View 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 */

File diff suppressed because it is too large Load Diff

View 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
View 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
View 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 */