diff options
28 files changed, 4023 insertions, 9 deletions
diff --git a/sys/arm/broadcom/bcm2835/files.bcm2835 b/sys/arm/broadcom/bcm2835/files.bcm2835 index ca13964..e7356ae 100644 --- a/sys/arm/broadcom/bcm2835/files.bcm2835 +++ b/sys/arm/broadcom/bcm2835/files.bcm2835 @@ -14,7 +14,7 @@ arm/broadcom/bcm2835/bcm2835_systimer.c standard arm/broadcom/bcm2835/bcm2835_wdog.c standard arm/broadcom/bcm2835/bus_space.c optional fdt arm/broadcom/bcm2835/common.c optional fdt -arm/broadcom/bcm2835/dwc_otg_brcm.c optional dwcotg +dev/usb/controller/dwc_otg_fdt.c optional dwcotg arm/arm/bus_space_generic.c standard arm/arm/bus_space_asm_generic.S standard diff --git a/sys/arm/conf/COSMIC b/sys/arm/conf/COSMIC new file mode 100644 index 0000000..409895c --- /dev/null +++ b/sys/arm/conf/COSMIC @@ -0,0 +1,139 @@ +# Kernel configuration for Cosmic Board (Freescale Vybrid Family development board). +# +# For more information on this file, please read the config(5) manual page, +# and/or the handbook section on Kernel Configuration Files: +# +# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html +# +# The handbook is also available locally in /usr/share/doc/handbook +# if you've installed the doc distribution, otherwise always see the +# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the +# latest information. +# +# An exhaustive list of options and more detailed explanations of the +# device lines is also present in the ../../conf/NOTES and NOTES files. +# If you are in doubt as to the purpose or necessity of a line, check first +# in NOTES. +# +# $FreeBSD$ + +ident COSMIC + +include "../freescale/vybrid/std.vybrid" + +makeoptions MODULES_OVERRIDE="" +makeoptions WITHOUT_MODULES="ahc" + +makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols +makeoptions WERROR="-Werror" + +options HZ=100 ## +options SCHED_4BSD #4BSD scheduler +options INET #InterNETworking +options INET6 #IPv6 communications protocols +options FFS #Berkeley Fast Filesystem +options SOFTUPDATES +options UFS_ACL #Support for access control lists +options UFS_DIRHASH #Improve performance on big directories +options MSDOSFS #MSDOS Filesystem +options CD9660 #ISO 9660 Filesystem +options PROCFS #Process filesystem (requires PSEUDOFS) +options PSEUDOFS #Pseudo-filesystem framework +#options NANDFS #NAND Filesystem +options TMPFS +options COMPAT_43 #Compatible with BSD 4.3 [KEEP THIS!] +options SCSI_DELAY=5000 #Delay (in ms) before probing SCSI +options KTRACE +options SYSVSHM #SYSV-style shared memory +options SYSVMSG #SYSV-style message queues +options SYSVSEM #SYSV-style semaphores +options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions +options KBD_INSTALL_CDEV +options PREEMPTION +options FREEBSD_BOOT_LOADER +options VFP # vfp/neon + +# Debugging +makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols +options BREAK_TO_DEBUGGER +#options VERBOSE_SYSINIT #Enable verbose sysinit messages +options KDB +options DDB #Enable the kernel debugger +options INVARIANTS #Enable calls of extra sanity checking +options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS +#options WITNESS #Enable checks to detect deadlocks and cycles +#options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed +options DIAGNOSTIC + +# NFS support +options NFSCL #Network Filesystem Client +options NFSLOCKD #Network Lock Manager +options NFS_ROOT #NFS usable as /, requires NFSCLIENT + +# Uncomment this for NFS root +#options NFS_ROOT #NFS usable as /, requires NFSCL +#options BOOTP_NFSROOT +#options BOOTP_COMPAT +#options BOOTP +#options BOOTP_NFSV3 +#options BOOTP_WIRED_TO=ffec0 + +device mmc # mmc/sd bus +device mmcsd # mmc/sd flash cards +device sdhci # generic sdhci + +#options ROOTDEVNAME=\"nfs:10.5.0.1:/tftpboot/cosmic\" +#options ROOTDEVNAME=\"nandfs:/dev/gnand0s.root\" +options ROOTDEVNAME=\"ufs:/dev/da0\" + +#options SMP + +# Pseudo devices + +device loop +device random +device pty +device md +device gpio + +# USB support +device usb +options USB_DEBUG +#options USB_REQ_DEBUG +#options USB_VERBOSE +#device musb +device ehci +#device ohci + +device umass +device scbus # SCSI bus (required for SCSI) +device da # Direct Access (disks) +device pass + +# SATA +#device ata +#device atadisk +#device mvs + +device nand + +# Serial ports +device uart + +# I2C (TWSI) +#device iic +#device iicbus + +# Ethernet +device ether +device ffec + +# USB ethernet support, requires miibus +device miibus +device axe # ASIX Electronics USB Ethernet +device bpf # Berkeley packet filter + +#FDT +options FDT +options FDT_DTB_STATIC +makeoptions FDT_DTS_FILE=vybrid-cosmic.dts diff --git a/sys/arm/conf/DIGI-CCWMX53 b/sys/arm/conf/DIGI-CCWMX53 index 5aec9fe..8a44844 100644 --- a/sys/arm/conf/DIGI-CCWMX53 +++ b/sys/arm/conf/DIGI-CCWMX53 @@ -65,7 +65,7 @@ options VFP # vfp/neon #options BOOTP_COMPAT #options BOOTP_NFSROOT #options BOOTP_NFSV3 -#options BOOTP_WIRED_TO=ue0 +#options BOOTP_WIRED_TO=ffec0 #options ROOTDEVNAME=\"ufs:ada0s2a\" @@ -105,8 +105,12 @@ device ether # Ethernet support #device faith # IPv6-to-IPv4 relaying (translation) #device firmware # firmware assist module +# Ethernet +device ffec # Freescale Fast Ethernet Controller +device miibus # Standard mii bus + # Serial (COM) ports -#device uart # Multi-uart driver +device uart # Multi-uart driver options ALT_BREAK_TO_DEBUGGER device ata @@ -130,13 +134,13 @@ device cd # CD device pass # Passthrough device (direct SCSI access) # USB support -#options USB_DEBUG # enable debug msgs -#device ehci # OHCI USB interface -#device usb # USB Bus (required) -#device umass # Disks/Mass storage - Requires scbus and da -#device uhid # "Human Interface Devices" +options USB_DEBUG # enable debug msgs +device ehci # OHCI USB interface +device usb # USB Bus (required) +device umass # Disks/Mass storage - Requires scbus and da +device uhid # "Human Interface Devices" #device ukbd # Allow keyboard like HIDs to control console -#device ums +device ums # USB Ethernet, requires miibus #device miibus diff --git a/sys/arm/conf/RADXA b/sys/arm/conf/RADXA new file mode 100644 index 0000000..d62f155 --- /dev/null +++ b/sys/arm/conf/RADXA @@ -0,0 +1,119 @@ +# RADXA -- Custom configuration for the RADXA ARM development +# platform, check out http://www.radxa.com +# +# For more information on this file, please read the handbook section on +# Kernel Configuration Files: +# +# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html +# +# The handbook is also available locally in /usr/share/doc/handbook +# if you've installed the doc distribution, otherwise always see the +# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the +# latest information. +# +# An exhaustive list of options and more detailed explanations of the +# device lines is also present in the ../../conf/NOTES and NOTES files. +# If you are in doubt as to the purpose or necessity of a line, check first +# in NOTES. +# +# $FreeBSD$ + +ident RADXA + +include "../rockchip/std.rk30xx" + +makeoptions MODULES_OVERRIDE="" +makeoptions WITHOUT_MODULES="ahc" + +options HZ=100 +options SCHED_4BSD #4BSD scheduler +options INET #InterNETworking +options INET6 #IPv6 communications protocols +options FFS #Berkeley Fast Filesystem +options SOFTUPDATES #Enable FFS soft updates support +options UFS_ACL #Support for access control lists +options UFS_DIRHASH #Improve performance on big directories +options MSDOSFS #MSDOS Filesystem +options CD9660 #ISO 9660 Filesystem +options PROCFS #Process filesystem (requires PSEUDOFS) +options PSEUDOFS #Pseudo-filesystem framework +options COMPAT_43 #Compatible with BSD 4.3 [KEEP THIS!] +options SCSI_DELAY=5000 #Delay (in ms) before probing SCSI +options KTRACE #ktrace(1) support +options SYSVSHM #SYSV-style shared memory +options SYSVMSG #SYSV-style message queues +options SYSVSEM #SYSV-style semaphores +options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions +options KBD_INSTALL_CDEV # install a CDEV entry in /dev +options PREEMPTION +options FREEBSD_BOOT_LOADER +options VFP # vfp/neon + +# Debugging +makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols +options BREAK_TO_DEBUGGER +#options VERBOSE_SYSINIT #Enable verbose sysinit messages +options KDB +options DDB #Enable the kernel debugger +#options INVARIANTS #Enable calls of extra sanity checking +#options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS +options WITNESS #Enable checks to detect deadlocks and cycles +options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed +options DIAGNOSTIC + +# NFS support +#options NFSCL +#options NFSSERVER #Network Filesystem Server +#options NFSCLIENT #Network Filesystem Client + +# MMC/SD/SDIO card slot support +#device mmc # mmc/sd bus +#device mmcsd # mmc/sd flash cards + +# Boot device is 2nd slice on MMC/SD card +options ROOTDEVNAME=\"ufs:/dev/da0s2\" + +# Console and misc +device uart +device uart_ns8250 +device pty +device snp +device md +device random # Entropy device + +# I2C support +#device iicbus +#device iic + +# GPIO +device gpio + +device scbus # SCSI bus (required for SCSI) +device da # Direct Access (disks) +device pass + +# USB support +device usb +options USB_DEBUG +#options USB_REQ_DEBUG +#options USB_VERBOSE +device dwcotg #DWC OTG controller + +device umass + +# Ethernet +device loop +device ether +device mii +device smscphy +device bpf + +# USB ethernet support, requires miibus +device miibus +device udav + +# Flattened Device Tree +options FDT +options FDT_DTB_STATIC +makeoptions FDT_DTS_FILE=rk3188-radxa.dts + diff --git a/sys/arm/freescale/vybrid/files.vybrid b/sys/arm/freescale/vybrid/files.vybrid new file mode 100644 index 0000000..4f700d0 --- /dev/null +++ b/sys/arm/freescale/vybrid/files.vybrid @@ -0,0 +1,28 @@ +# $FreeBSD$ + +kern/kern_clocksource.c standard + +arm/arm/bus_space_generic.c standard +arm/arm/bus_space_asm_generic.S standard +arm/arm/cpufunc_asm_armv5.S standard +arm/arm/cpufunc_asm_arm10.S standard +arm/arm/cpufunc_asm_arm11.S standard +arm/arm/cpufunc_asm_armv7.S standard +arm/arm/irq_dispatch.S standard + +arm/arm/bus_space-v6.c standard +arm/arm/gic.c standard +arm/arm/mpcore_timer.c standard + +arm/freescale/vybrid/vf_machdep.c standard +arm/freescale/vybrid/vf_common.c standard +arm/freescale/vybrid/vf_ccm.c standard +arm/freescale/vybrid/vf_anadig.c standard +arm/freescale/vybrid/vf_iomuxc.c standard +arm/freescale/vybrid/vf_mscm.c standard +arm/freescale/vybrid/vf_src.c standard +arm/freescale/vybrid/vf_nfc.c optional nand +arm/freescale/vybrid/vf_ehci.c optional ehci +arm/freescale/vybrid/vf_gpio.c optional gpio +arm/freescale/vybrid/vf_uart.c optional uart +dev/ffec/if_ffec.c optional ffec diff --git a/sys/arm/freescale/vybrid/std.vybrid b/sys/arm/freescale/vybrid/std.vybrid new file mode 100644 index 0000000..92d5a46 --- /dev/null +++ b/sys/arm/freescale/vybrid/std.vybrid @@ -0,0 +1,20 @@ +# $FreeBSD$ + +makeoption ARM_LITTLE_ENDIAN + +cpu CPU_CORTEXA +machine arm armv6 + +options PHYSADDR=0x80000000 + +makeoptions KERNPHYSADDR=0x80100000 +options KERNPHYSADDR=0x80100000 + +makeoptions KERNVIRTADDR=0xc0100000 +options KERNVIRTADDR=0xc0100000 + +options STARTUP_PAGETABLE_ADDR=0x81000000 + +options ARM_L2_PIPT + +files "../freescale/vybrid/files.vybrid" diff --git a/sys/arm/freescale/vybrid/vf_anadig.c b/sys/arm/freescale/vybrid/vf_anadig.c new file mode 100644 index 0000000..afa860d --- /dev/null +++ b/sys/arm/freescale/vybrid/vf_anadig.c @@ -0,0 +1,214 @@ +/*- + * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.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 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. + */ + +/* + * Vybrid Family Analog components control digital interface (ANADIG) + * Chapter 11, Vybrid Reference Manual, Rev. 5, 07/2013 + */ + +#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 <dev/fdt/fdt_common.h> +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <machine/bus.h> +#include <machine/fdt.h> +#include <machine/cpu.h> +#include <machine/intr.h> + +#include <arm/freescale/vybrid/vf_common.h> + +#define ANADIG_PLL3_CTRL 0x010 /* PLL3 Control */ +#define ANADIG_PLL7_CTRL 0x020 /* PLL7 Control */ +#define ANADIG_PLL2_CTRL 0x030 /* PLL2 Control */ +#define ANADIG_PLL2_SS 0x040 /* PLL2 Spread Spectrum */ +#define ANADIG_PLL2_NUM 0x050 /* PLL2 Numerator */ +#define ANADIG_PLL2_DENOM 0x060 /* PLL2 Denominator */ +#define ANADIG_PLL4_CTRL 0x070 /* PLL4 Control */ +#define ANADIG_PLL4_NUM 0x080 /* PLL4 Numerator */ +#define ANADIG_PLL4_DENOM 0x090 /* PLL4 Denominator */ +#define ANADIG_PLL6_CTRL 0x0A0 /* PLL6 Control */ +#define ANADIG_PLL6_NUM 0x0B0 /* PLL6 Numerator */ +#define ANADIG_PLL6_DENOM 0x0C0 /* PLL6 Denominator */ +#define ANADIG_PLL5_CTRL 0x0E0 /* PLL5 Control */ +#define ANADIG_PLL3_PFD 0x0F0 /* PLL3 PFD */ +#define ANADIG_PLL2_PFD 0x100 /* PLL2 PFD */ +#define ANADIG_REG_1P1 0x110 /* Regulator 1P1 */ +#define ANADIG_REG_3P0 0x120 /* Regulator 3P0 */ +#define ANADIG_REG_2P5 0x130 /* Regulator 2P5 */ +#define ANADIG_ANA_MISC0 0x150 /* Analog Miscellaneous */ +#define ANADIG_ANA_MISC1 0x160 /* Analog Miscellaneous */ +#define ANADIG_ANADIG_DIGPROG 0x260 /* Digital Program */ +#define ANADIG_PLL1_CTRL 0x270 /* PLL1 Control */ +#define ANADIG_PLL1_SS 0x280 /* PLL1 Spread Spectrum */ +#define ANADIG_PLL1_NUM 0x290 /* PLL1 Numerator */ +#define ANADIG_PLL1_DENOM 0x2A0 /* PLL1 Denominator */ +#define ANADIG_PLL1_PFD 0x2B0 /* PLL1_PFD */ +#define ANADIG_PLL_LOCK 0x2C0 /* PLL Lock */ + +#define USB_VBUS_DETECT(n) (0x1A0 + 0x60 * n) +#define USB_CHRG_DETECT(n) (0x1B0 + 0x60 * n) +#define USB_VBUS_DETECT_STATUS(n) (0x1C0 + 0x60 * n) +#define USB_CHRG_DETECT_STATUS(n) (0x1D0 + 0x60 * n) +#define USB_LOOPBACK(n) (0x1E0 + 0x60 * n) +#define USB_MISC(n) (0x1F0 + 0x60 * n) + +#define ANADIG_PLL_LOCKED (1 << 31) +#define ENABLE_LINREG (1 << 0) +#define EN_CLK_TO_UTMI (1 << 30) + +#define CTRL_BYPASS (1 << 16) +#define CTRL_PWR (1 << 12) +#define CTRL_PLL_EN (1 << 13) +#define EN_USB_CLKS (1 << 6) + +struct anadig_softc { + struct resource *res[1]; + bus_space_tag_t bst; + bus_space_handle_t bsh; +}; + +static struct resource_spec anadig_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { -1, 0 } +}; + +static int +anadig_probe(device_t dev) +{ + + if (!ofw_bus_is_compatible(dev, "fsl,mvf600-anadig")) + return (ENXIO); + + device_set_desc(dev, "Vybrid Family ANADIG Unit"); + return (BUS_PROBE_DEFAULT); +} + +static int +enable_pll(struct anadig_softc *sc, int pll_ctrl) +{ + int reg; + + reg = READ4(sc, pll_ctrl); + reg &= ~(CTRL_BYPASS | CTRL_PWR); + if (pll_ctrl == ANADIG_PLL3_CTRL || pll_ctrl == ANADIG_PLL7_CTRL) { + /* It is USB PLL. Power bit logic is reversed */ + reg |= (CTRL_PWR | EN_USB_CLKS); + } + WRITE4(sc, pll_ctrl, reg); + + /* Wait for PLL lock */ + while (!(READ4(sc, pll_ctrl) & ANADIG_PLL_LOCKED)) + ; + + reg = READ4(sc, pll_ctrl); + reg |= (CTRL_PLL_EN); + WRITE4(sc, pll_ctrl, reg); + + return (0); +} + +static int +anadig_attach(device_t dev) +{ + struct anadig_softc *sc; + int reg; + + sc = device_get_softc(dev); + + if (bus_alloc_resources(dev, anadig_spec, sc->res)) { + device_printf(dev, "could not allocate resources\n"); + return (ENXIO); + } + + /* Memory interface */ + sc->bst = rman_get_bustag(sc->res[0]); + sc->bsh = rman_get_bushandle(sc->res[0]); + + /* Enable USB PLLs */ + enable_pll(sc, ANADIG_PLL3_CTRL); + enable_pll(sc, ANADIG_PLL7_CTRL); + + /* Enable other */ + enable_pll(sc, ANADIG_PLL1_CTRL); + enable_pll(sc, ANADIG_PLL2_CTRL); + enable_pll(sc, ANADIG_PLL4_CTRL); + enable_pll(sc, ANADIG_PLL5_CTRL); + enable_pll(sc, ANADIG_PLL6_CTRL); + + /* Enable USB voltage regulator */ + reg = READ4(sc, ANADIG_REG_3P0); + reg |= (ENABLE_LINREG); + WRITE4(sc, ANADIG_REG_3P0, reg); + + /* Give clocks to USB */ + reg = READ4(sc, USB_MISC(0)); + reg |= (EN_CLK_TO_UTMI); + WRITE4(sc, USB_MISC(0), reg); + + reg = READ4(sc, USB_MISC(1)); + reg |= (EN_CLK_TO_UTMI); + WRITE4(sc, USB_MISC(1), reg); + +#if 0 + printf("USB_ANALOG_USB_MISC(0) == 0x%08x\n", + READ4(sc, USB_ANALOG_USB_MISC(0))); + printf("USB_ANALOG_USB_MISC(1) == 0x%08x\n", + READ4(sc, USB_ANALOG_USB_MISC(1))); +#endif + + return (0); +} + +static device_method_t anadig_methods[] = { + DEVMETHOD(device_probe, anadig_probe), + DEVMETHOD(device_attach, anadig_attach), + { 0, 0 } +}; + +static driver_t anadig_driver = { + "anadig", + anadig_methods, + sizeof(struct anadig_softc), +}; + +static devclass_t anadig_devclass; + +DRIVER_MODULE(anadig, simplebus, anadig_driver, anadig_devclass, 0, 0); diff --git a/sys/arm/freescale/vybrid/vf_ccm.c b/sys/arm/freescale/vybrid/vf_ccm.c new file mode 100644 index 0000000..1410faa --- /dev/null +++ b/sys/arm/freescale/vybrid/vf_ccm.c @@ -0,0 +1,188 @@ +/*- + * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.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 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. + */ + +/* + * Vybrid Family Clock Controller Module (CCM) + * Chapter 10, Vybrid Reference Manual, Rev. 5, 07/2013 + */ + +#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 <dev/fdt/fdt_common.h> +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <machine/bus.h> +#include <machine/fdt.h> +#include <machine/cpu.h> +#include <machine/intr.h> + +#include <arm/freescale/vybrid/vf_common.h> + +#define CCM_CCR 0x00 /* Control Register */ +#define CCM_CSR 0x04 /* Status Register */ +#define CCM_CCSR 0x08 /* Clock Switcher Register */ +#define CCM_CACRR 0x0C /* ARM Clock Root Register */ +#define CCM_CSCMR1 0x10 /* Serial Clock Multiplexer Register 1 */ +#define CCM_CSCDR1 0x14 /* Serial Clock Divider Register 1 */ +#define CCM_CSCDR2 0x18 /* Serial Clock Divider Register 2 */ +#define CCM_CSCDR3 0x1C /* Serial Clock Divider Register 3 */ +#define CCM_CSCMR2 0x20 /* Serial Clock Multiplexer Register 2 */ +#define CCM_CTOR 0x28 /* Testing Observability Register */ +#define CCM_CLPCR 0x2C /* Low Power Control Register */ +#define CCM_CISR 0x30 /* Interrupt Status Register */ +#define CCM_CIMR 0x34 /* Interrupt Mask Register */ +#define CCM_CCOSR 0x38 /* Clock Output Source Register */ +#define CCM_CGPR 0x3C /* General Purpose Register */ + +#define CCM_CCGRN 12 +#define CCM_CCGR(n) (0x40 + (n * 0x04)) /* Clock Gating Register */ +#define CCM_CMEOR(n) (0x70 + (n * 0x70)) /* Module Enable Override Reg */ +#define CCM_CCPGR(n) (0x90 + (n * 0x04)) /* Platform Clock Gating Reg */ + +#define CCM_CPPDSR 0x88 /* PLL PFD Disable Status Register */ +#define CCM_CCOWR 0x8C /* CORE Wakeup Register */ + +#define PLL3_PFD4_EN (1 << 31) +#define PLL3_PFD3_EN (1 << 30) +#define PLL3_PFD2_EN (1 << 29) +#define PLL3_PFD1_EN (1 << 28) +#define PLL2_PFD4_EN (1 << 15) +#define PLL2_PFD3_EN (1 << 14) +#define PLL2_PFD2_EN (1 << 13) +#define PLL2_PFD1_EN (1 << 12) +#define PLL1_PFD4_EN (1 << 11) +#define PLL1_PFD3_EN (1 << 10) +#define PLL1_PFD2_EN (1 << 9) +#define PLL1_PFD1_EN (1 << 8) + +/* CCM_CCR */ +#define FIRC_EN (1 << 16) +#define FXOSC_EN (1 << 12) +#define FXOSC_RDY (1 << 5) + +/* CCM_CSCDR1 */ +#define ENET_TS_EN (1 << 23) +#define RMII_CLK_EN (1 << 24) + +struct ccm_softc { + struct resource *res[1]; + bus_space_tag_t bst; + bus_space_handle_t bsh; + device_t dev; +}; + +static struct resource_spec ccm_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { -1, 0 } +}; + +static int +ccm_probe(device_t dev) +{ + + if (!ofw_bus_is_compatible(dev, "fsl,mvf600-ccm")) + return (ENXIO); + + device_set_desc(dev, "Vybrid Family CCM Unit"); + return (BUS_PROBE_DEFAULT); +} + +static int +ccm_attach(device_t dev) +{ + struct ccm_softc *sc; + int reg; + int i; + + sc = device_get_softc(dev); + sc->dev = dev; + + if (bus_alloc_resources(dev, ccm_spec, sc->res)) { + device_printf(dev, "could not allocate resources\n"); + return (ENXIO); + } + + /* Memory interface */ + sc->bst = rman_get_bustag(sc->res[0]); + sc->bsh = rman_get_bushandle(sc->res[0]); + + /* Enable oscillator */ + reg = READ4(sc, CCM_CCR); + reg |= (FIRC_EN | FXOSC_EN); + WRITE4(sc, CCM_CCR, reg); + + /* Wait 10 times */ + for (i = 0; i < 10; i++) { + if (READ4(sc, CCM_CSR) & FXOSC_RDY) { + device_printf(sc->dev, "On board oscillator is ready.\n"); + break; + } + + cpufunc_nullop(); + } + + /* Clock is on during all modes, except stop mode. */ + for (i = 0; i < CCM_CCGRN; i++) { + WRITE4(sc, CCM_CCGR(i), 0xffffffff); + } + + /* Enable ENET clocks */ + reg = READ4(sc, CCM_CSCDR1); + reg |= (ENET_TS_EN | RMII_CLK_EN); + WRITE4(sc, CCM_CSCDR1, reg); + + return (0); +} + +static device_method_t ccm_methods[] = { + DEVMETHOD(device_probe, ccm_probe), + DEVMETHOD(device_attach, ccm_attach), + { 0, 0 } +}; + +static driver_t ccm_driver = { + "ccm", + ccm_methods, + sizeof(struct ccm_softc), +}; + +static devclass_t ccm_devclass; + +DRIVER_MODULE(ccm, simplebus, ccm_driver, ccm_devclass, 0, 0); diff --git a/sys/arm/freescale/vybrid/vf_common.c b/sys/arm/freescale/vybrid/vf_common.c new file mode 100644 index 0000000..ffec9a3 --- /dev/null +++ b/sys/arm/freescale/vybrid/vf_common.c @@ -0,0 +1,86 @@ +/*- + * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.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 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 <dev/fdt/fdt_common.h> +#include <dev/ofw/openfirm.h> + +#include <machine/bus.h> +#include <machine/fdt.h> + +#include <arm/freescale/vybrid/vf_src.h> + +void +cpu_reset(void) +{ + phandle_t src; + uint32_t addr, paddr; + bus_addr_t vaddr; + + if (src_swreset() == 0) + goto end; + + src = OF_finddevice("src"); + if ((src != 0) && (OF_getprop(src, "reg", &paddr, sizeof(paddr))) > 0) { + addr = fdt32_to_cpu(paddr); + if (bus_space_map(fdtbus_bs_tag, addr, 0x10, 0, &vaddr) == 0) { + bus_space_write_4(fdtbus_bs_tag, vaddr, 0x00, SW_RST); + } + } + +end: + while (1); +} + +struct fdt_fixup_entry fdt_fixup_table[] = { + { NULL, NULL } +}; + +static int +fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, + int *pol) +{ + + if (!fdt_is_compatible(node, "arm,gic")) + return (ENXIO); + + *interrupt = fdt32_to_cpu(intr[0]); + *trig = INTR_TRIGGER_CONFORM; + *pol = INTR_POLARITY_CONFORM; + return (0); +} + +fdt_pic_decode_t fdt_pic_table[] = { + &fdt_pic_decode_ic, + NULL +}; diff --git a/sys/arm/freescale/vybrid/vf_common.h b/sys/arm/freescale/vybrid/vf_common.h new file mode 100644 index 0000000..d11f000 --- /dev/null +++ b/sys/arm/freescale/vybrid/vf_common.h @@ -0,0 +1,40 @@ +/*- + * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.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 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$ + */ + +#define READ4(_sc, _reg) \ + bus_space_read_4(_sc->bst, _sc->bsh, _reg) +#define WRITE4(_sc, _reg, _val) \ + bus_space_write_4(_sc->bst, _sc->bsh, _reg, _val) +#define READ2(_sc, _reg) \ + bus_space_read_2(_sc->bst, _sc->bsh, _reg) +#define WRITE2(_sc, _reg, _val) \ + bus_space_write_2(_sc->bst, _sc->bsh, _reg, _val) +#define READ1(_sc, _reg) \ + bus_space_read_1(_sc->bst, _sc->bsh, _reg) +#define WRITE1(_sc, _reg, _val) \ + bus_space_write_1(_sc->bst, _sc->bsh, _reg, _val) diff --git a/sys/arm/freescale/vybrid/vf_ehci.c b/sys/arm/freescale/vybrid/vf_ehci.c new file mode 100644 index 0000000..76edb85 --- /dev/null +++ b/sys/arm/freescale/vybrid/vf_ehci.c @@ -0,0 +1,416 @@ +/*- + * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.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 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. + */ + +/* + * Vybrid Family Universal Serial Bus (USB) Controller + * Chapter 44-45, Vybrid Reference Manual, Rev. 5, 07/2013 + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include "opt_bus.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/condvar.h> +#include <sys/rman.h> +#include <sys/gpio.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_busdma.h> +#include <dev/usb/usb_process.h> +#include <dev/usb/usb_controller.h> +#include <dev/usb/usb_bus.h> +#include <dev/usb/controller/ehci.h> +#include <dev/usb/controller/ehcireg.h> + +#include <dev/fdt/fdt_common.h> + +#include <machine/bus.h> +#include <machine/resource.h> + +#include "gpio_if.h" +#include "opt_platform.h" + +#define ENUTMILEVEL3 (1 << 15) +#define ENUTMILEVEL2 (1 << 14) + +#define GPIO_USB_PWR 134 + +#define USB_ID 0x000 /* Identification register */ +#define USB_HWGENERAL 0x004 /* Hardware General */ +#define USB_HWHOST 0x008 /* Host Hardware Parameters */ +#define USB_HWDEVICE 0x00C /* Device Hardware Parameters */ +#define USB_HWTXBUF 0x010 /* TX Buffer Hardware Parameters */ +#define USB_HWRXBUF 0x014 /* RX Buffer Hardware Parameters */ +#define USB_HCSPARAMS 0x104 /* Host Controller Structural Parameters */ + +#define USBPHY_PWD 0x00 /* PHY Power-Down Register */ +#define USBPHY_PWD_SET 0x04 /* PHY Power-Down Register */ +#define USBPHY_PWD_CLR 0x08 /* PHY Power-Down Register */ +#define USBPHY_PWD_TOG 0x0C /* PHY Power-Down Register */ +#define USBPHY_TX 0x10 /* PHY Transmitter Control Register */ +#define USBPHY_RX 0x20 /* PHY Receiver Control Register */ +#define USBPHY_RX_SET 0x24 /* PHY Receiver Control Register */ +#define USBPHY_RX_CLR 0x28 /* PHY Receiver Control Register */ +#define USBPHY_RX_TOG 0x2C /* PHY Receiver Control Register */ +#define USBPHY_CTRL 0x30 /* PHY General Control Register */ +#define USBPHY_CTRL_SET 0x34 /* PHY General Control Register */ +#define USBPHY_CTRL_CLR 0x38 /* PHY General Control Register */ +#define USBPHY_CTRL_TOG 0x3C /* PHY General Control Register */ +#define USBPHY_STATUS 0x40 /* PHY Status Register */ +#define USBPHY_DEBUG 0x50 /* PHY Debug Register */ +#define USBPHY_DEBUG_SET 0x54 /* PHY Debug Register */ +#define USBPHY_DEBUG_CLR 0x58 /* PHY Debug Register */ +#define USBPHY_DEBUG_TOG 0x5C /* PHY Debug Register */ +#define USBPHY_DEBUG0_STATUS 0x60 /* UTMI Debug Status Register 0 */ +#define USBPHY_DEBUG1 0x70 /* UTMI Debug Status Register 1 */ +#define USBPHY_DEBUG1_SET 0x74 /* UTMI Debug Status Register 1 */ +#define USBPHY_DEBUG1_CLR 0x78 /* UTMI Debug Status Register 1 */ +#define USBPHY_DEBUG1_TOG 0x7C /* UTMI Debug Status Register 1 */ +#define USBPHY_VERSION 0x80 /* UTMI RTL Version */ +#define USBPHY_IP 0x90 /* PHY IP Block Register */ +#define USBPHY_IP_SET 0x94 /* PHY IP Block Register */ +#define USBPHY_IP_CLR 0x98 /* PHY IP Block Register */ +#define USBPHY_IP_TOG 0x9C /* PHY IP Block Register */ + +#define USBPHY_CTRL_SFTRST (1 << 31) +#define USBPHY_CTRL_CLKGATE (1 << 30) +#define USBPHY_DEBUG_CLKGATE (1 << 30) + +#define PHY_READ4(_sc, _reg) \ + bus_space_read_4(_sc->bst_phy, _sc->bsh_phy, _reg) +#define PHY_WRITE4(_sc, _reg, _val) \ + bus_space_write_4(_sc->bst_phy, _sc->bsh_phy, _reg, _val) + +#define USBC_READ4(_sc, _reg) \ + bus_space_read_4(_sc->bst_usbc, _sc->bsh_usbc, _reg) +#define USBC_WRITE4(_sc, _reg, _val) \ + bus_space_write_4(_sc->bst_usbc, _sc->bsh_usbc, _reg, _val) + +/* Forward declarations */ +static int vybrid_ehci_attach(device_t dev); +static int vybrid_ehci_detach(device_t dev); +static int vybrid_ehci_probe(device_t dev); + +struct vybrid_ehci_softc { + ehci_softc_t base; + device_t dev; + struct resource *res[6]; + bus_space_tag_t bst_phy; + bus_space_handle_t bsh_phy; + bus_space_tag_t bst_usbc; + bus_space_handle_t bsh_usbc; +}; + +static struct resource_spec vybrid_ehci_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { SYS_RES_MEMORY, 1, RF_ACTIVE }, + { SYS_RES_MEMORY, 2, RF_ACTIVE }, + { SYS_RES_IRQ, 0, RF_ACTIVE }, + { -1, 0 } +}; + +static device_method_t ehci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, vybrid_ehci_probe), + DEVMETHOD(device_attach, vybrid_ehci_attach), + DEVMETHOD(device_detach, vybrid_ehci_detach), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + + { 0, 0 } +}; + +/* kobj_class definition */ +static driver_t ehci_driver = { + "ehci", + ehci_methods, + sizeof(ehci_softc_t) +}; + +static devclass_t ehci_devclass; + +DRIVER_MODULE(ehci, simplebus, ehci_driver, ehci_devclass, 0, 0); +MODULE_DEPEND(ehci, usb, 1, 1, 1); + +/* + * Public methods + */ +static int +vybrid_ehci_probe(device_t dev) +{ + + if (ofw_bus_is_compatible(dev, "fsl,mvf600-usb-ehci") == 0) + return (ENXIO); + + device_set_desc(dev, "Vybrid Family integrated USB controller"); + return (BUS_PROBE_DEFAULT); +} + +static int +phy_init(struct vybrid_ehci_softc *esc) +{ + device_t sc_gpio_dev; + int reg; + + /* Reset phy */ + reg = PHY_READ4(esc, USBPHY_CTRL); + reg |= (USBPHY_CTRL_SFTRST); + PHY_WRITE4(esc, USBPHY_CTRL, reg); + + /* Minimum reset time */ + DELAY(10000); + + reg &= ~(USBPHY_CTRL_SFTRST | USBPHY_CTRL_CLKGATE); + PHY_WRITE4(esc, USBPHY_CTRL, reg); + + reg = (ENUTMILEVEL2 | ENUTMILEVEL3); + PHY_WRITE4(esc, USBPHY_CTRL_SET, reg); + + /* Get the GPIO device, we need this to give power to USB */ + sc_gpio_dev = devclass_get_device(devclass_find("gpio"), 0); + if (sc_gpio_dev == NULL) { + device_printf(esc->dev, "Error: failed to get the GPIO dev\n"); + return (1); + } + + /* Give power to USB */ + GPIO_PIN_SETFLAGS(sc_gpio_dev, GPIO_USB_PWR, GPIO_PIN_OUTPUT); + GPIO_PIN_SET(sc_gpio_dev, GPIO_USB_PWR, GPIO_PIN_HIGH); + + /* Power up PHY */ + PHY_WRITE4(esc, USBPHY_PWD, 0x00); + + /* Ungate clocks */ + reg = PHY_READ4(esc, USBPHY_DEBUG); + reg &= ~(USBPHY_DEBUG_CLKGATE); + PHY_WRITE4(esc, USBPHY_DEBUG, reg); + +#if 0 + printf("USBPHY_CTRL == 0x%08x\n", + PHY_READ4(esc, USBPHY_CTRL)); + printf("USBPHY_IP == 0x%08x\n", + PHY_READ4(esc, USBPHY_IP)); + printf("USBPHY_STATUS == 0x%08x\n", + PHY_READ4(esc, USBPHY_STATUS)); + printf("USBPHY_DEBUG == 0x%08x\n", + PHY_READ4(esc, USBPHY_DEBUG)); + printf("USBPHY_DEBUG0_STATUS == 0x%08x\n", + PHY_READ4(esc, USBPHY_DEBUG0_STATUS)); + printf("USBPHY_DEBUG1 == 0x%08x\n", + PHY_READ4(esc, USBPHY_DEBUG1)); +#endif + + return (0); +} + +static int +vybrid_ehci_attach(device_t dev) +{ + struct vybrid_ehci_softc *esc; + ehci_softc_t *sc; + bus_space_handle_t bsh; + int err; + int reg; + + esc = device_get_softc(dev); + esc->dev = dev; + + sc = &esc->base; + sc->sc_bus.parent = dev; + sc->sc_bus.devices = sc->sc_devices; + sc->sc_bus.devices_max = EHCI_MAX_DEVICES; + + if (bus_alloc_resources(dev, vybrid_ehci_spec, esc->res)) { + device_printf(dev, "could not allocate resources\n"); + return (ENXIO); + } + + /* EHCI registers */ + sc->sc_io_tag = rman_get_bustag(esc->res[0]); + bsh = rman_get_bushandle(esc->res[0]); + sc->sc_io_size = rman_get_size(esc->res[0]); + + esc->bst_usbc = rman_get_bustag(esc->res[1]); + esc->bsh_usbc = rman_get_bushandle(esc->res[1]); + + esc->bst_phy = rman_get_bustag(esc->res[2]); + esc->bsh_phy = rman_get_bushandle(esc->res[2]); + + /* get all DMA memory */ + if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(dev), + &ehci_iterate_hw_softc)) + return (ENXIO); + +#if 0 + printf("USBx_HCSPARAMS is 0x%08x\n", + bus_space_read_4(sc->sc_io_tag, bsh, USB_HCSPARAMS)); + printf("USB_ID == 0x%08x\n", + bus_space_read_4(sc->sc_io_tag, bsh, USB_ID)); + printf("USB_HWGENERAL == 0x%08x\n", + bus_space_read_4(sc->sc_io_tag, bsh, USB_HWGENERAL)); + printf("USB_HWHOST == 0x%08x\n", + bus_space_read_4(sc->sc_io_tag, bsh, USB_HWHOST)); + printf("USB_HWDEVICE == 0x%08x\n", + bus_space_read_4(sc->sc_io_tag, bsh, USB_HWDEVICE)); + printf("USB_HWTXBUF == 0x%08x\n", + bus_space_read_4(sc->sc_io_tag, bsh, USB_HWTXBUF)); + printf("USB_HWRXBUF == 0x%08x\n", + bus_space_read_4(sc->sc_io_tag, bsh, USB_HWRXBUF)); +#endif + + if (phy_init(esc)) { + device_printf(dev, "Could not setup PHY\n"); + return (1); + } + + /* + * Set handle to USB related registers subregion used by + * generic EHCI driver. + */ + err = bus_space_subregion(sc->sc_io_tag, bsh, 0x100, + sc->sc_io_size, &sc->sc_io_hdl); + if (err != 0) + return (ENXIO); + + /* Setup interrupt handler */ + err = bus_setup_intr(dev, esc->res[3], INTR_TYPE_BIO | INTR_MPSAFE, + NULL, (driver_intr_t *)ehci_interrupt, sc, + &sc->sc_intr_hdl); + if (err) { + device_printf(dev, "Could not setup irq, " + "%d\n", err); + return (1); + } + + /* Add USB device */ + sc->sc_bus.bdev = device_add_child(dev, "usbus", -1); + if (!sc->sc_bus.bdev) { + device_printf(dev, "Could not add USB device\n"); + err = bus_teardown_intr(dev, esc->res[5], + sc->sc_intr_hdl); + if (err) + device_printf(dev, "Could not tear down irq," + " %d\n", err); + return (1); + } + device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); + + strlcpy(sc->sc_vendor, "Freescale", sizeof(sc->sc_vendor)); + + /* Set host mode */ + reg = bus_space_read_4(sc->sc_io_tag, sc->sc_io_hdl, 0xA8); + reg |= 0x3; + bus_space_write_4(sc->sc_io_tag, sc->sc_io_hdl, 0xA8, reg); + + /* Set flags */ + sc->sc_flags |= EHCI_SCFLG_SETMODE | EHCI_SCFLG_NORESTERM; + + err = ehci_init(sc); + if (!err) { + sc->sc_flags |= EHCI_SCFLG_DONEINIT; + err = device_probe_and_attach(sc->sc_bus.bdev); + } else { + device_printf(dev, "USB init failed err=%d\n", err); + + device_delete_child(dev, sc->sc_bus.bdev); + sc->sc_bus.bdev = NULL; + + err = bus_teardown_intr(dev, esc->res[5], + sc->sc_intr_hdl); + if (err) + device_printf(dev, "Could not tear down irq," + " %d\n", err); + return (1); + } + return (0); +} + +static int +vybrid_ehci_detach(device_t dev) +{ + struct vybrid_ehci_softc *esc; + ehci_softc_t *sc; + int err; + + esc = device_get_softc(dev); + sc = &esc->base; + + if (sc->sc_flags & EHCI_SCFLG_DONEINIT) + return (0); + + /* + * only call ehci_detach() after ehci_init() + */ + if (sc->sc_flags & EHCI_SCFLG_DONEINIT) { + ehci_detach(sc); + sc->sc_flags &= ~EHCI_SCFLG_DONEINIT; + } + + /* + * Disable interrupts that might have been switched on in + * ehci_init. + */ + if (sc->sc_io_tag && sc->sc_io_hdl) + bus_space_write_4(sc->sc_io_tag, sc->sc_io_hdl, + EHCI_USBINTR, 0); + + if (esc->res[5] && sc->sc_intr_hdl) { + err = bus_teardown_intr(dev, esc->res[5], + sc->sc_intr_hdl); + if (err) { + device_printf(dev, "Could not tear down irq," + " %d\n", err); + return (err); + } + sc->sc_intr_hdl = NULL; + } + + if (sc->sc_bus.bdev) { + device_delete_child(dev, sc->sc_bus.bdev); + sc->sc_bus.bdev = NULL; + } + + /* During module unload there are lots of children leftover */ + device_delete_children(dev); + + bus_release_resources(dev, vybrid_ehci_spec, esc->res); + + return (0); +} diff --git a/sys/arm/freescale/vybrid/vf_gpio.c b/sys/arm/freescale/vybrid/vf_gpio.c new file mode 100644 index 0000000..8a7b9b1 --- /dev/null +++ b/sys/arm/freescale/vybrid/vf_gpio.c @@ -0,0 +1,403 @@ +/*- + * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.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 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. + */ + +/* + * Vybrid Family General-Purpose Input/Output (GPIO) + * Chapter 7, Vybrid Reference Manual, Rev. 5, 07/2013 + */ + +#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 <sys/mutex.h> +#include <sys/gpio.h> + +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <machine/bus.h> +#include <machine/fdt.h> +#include <machine/cpu.h> +#include <machine/intr.h> + +#include "gpio_if.h" + +#include <arm/freescale/vybrid/vf_common.h> + +#define GPIO_PDOR(n) (0x00 + 0x40 * (n >> 5)) +#define GPIO_PSOR(n) (0x04 + 0x40 * (n >> 5)) +#define GPIO_PCOR(n) (0x08 + 0x40 * (n >> 5)) +#define GPIO_PTOR(n) (0x0C + 0x40 * (n >> 5)) +#define GPIO_PDIR(n) (0x10 + 0x40 * (n >> 5)) + +#define GPIO_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) +#define GPIO_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) + +#define NPORTS 5 +#define NGPIO (NPORTS * 32) +#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT) + +/* + * GPIO interface + */ +static int vf_gpio_pin_max(device_t, int *); +static int vf_gpio_pin_getcaps(device_t, uint32_t, uint32_t *); +static int vf_gpio_pin_getname(device_t, uint32_t, char *); +static int vf_gpio_pin_getflags(device_t, uint32_t, uint32_t *); +static int vf_gpio_pin_setflags(device_t, uint32_t, uint32_t); +static int vf_gpio_pin_set(device_t, uint32_t, unsigned int); +static int vf_gpio_pin_get(device_t, uint32_t, unsigned int *); +static int vf_gpio_pin_toggle(device_t, uint32_t pin); + +struct vf_gpio_softc { + struct resource *res[6]; + bus_space_tag_t bst; + bus_space_handle_t bsh; + + struct mtx sc_mtx; + int gpio_npins; + struct gpio_pin gpio_pins[NGPIO]; + void *gpio_ih[NPORTS]; +}; + +struct vf_gpio_softc *gpio_sc; + +static struct resource_spec vf_gpio_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { SYS_RES_IRQ, 0, RF_ACTIVE }, + { SYS_RES_IRQ, 1, RF_ACTIVE }, + { SYS_RES_IRQ, 2, RF_ACTIVE }, + { SYS_RES_IRQ, 3, RF_ACTIVE }, + { SYS_RES_IRQ, 4, RF_ACTIVE }, + { -1, 0 } +}; + +static int +vf_gpio_intr(void *arg) +{ + struct vf_gpio_softc *sc; + sc = arg; + + /* TODO: interrupt handling */ + + return (FILTER_HANDLED); +} + + +static int +vf_gpio_probe(device_t dev) +{ + + if (!ofw_bus_is_compatible(dev, "fsl,mvf600-gpio")) + return (ENXIO); + + device_set_desc(dev, "Vybrid Family GPIO Unit"); + return (BUS_PROBE_DEFAULT); +} + +static int +vf_gpio_attach(device_t dev) +{ + struct vf_gpio_softc *sc; + int irq, i; + + sc = device_get_softc(dev); + mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); + + if (bus_alloc_resources(dev, vf_gpio_spec, sc->res)) { + device_printf(dev, "could not allocate resources\n"); + return (ENXIO); + } + + gpio_sc = sc; + + /* Memory interface */ + sc->bst = rman_get_bustag(sc->res[0]); + sc->bsh = rman_get_bushandle(sc->res[0]); + + sc->gpio_npins = NGPIO; + + for (irq = 0; irq < NPORTS; irq ++) { + if ((bus_setup_intr(dev, sc->res[1 + irq], INTR_TYPE_MISC, + vf_gpio_intr, NULL, sc, &sc->gpio_ih[irq]))) { + device_printf(dev, + "WARNING: unable to register interrupt handler\n"); + return (ENXIO); + } + } + + for (i = 0; i < sc->gpio_npins; i++) { + sc->gpio_pins[i].gp_pin = i; + sc->gpio_pins[i].gp_caps = DEFAULT_CAPS; + sc->gpio_pins[i].gp_flags = + (READ4(sc, GPIO_PDOR(i)) & (1 << (i % 32))) ? + GPIO_PIN_OUTPUT: GPIO_PIN_INPUT; + snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME, + "vf_gpio%d.%d", device_get_unit(dev), i); + } + + device_add_child(dev, "gpioc", device_get_unit(dev)); + device_add_child(dev, "gpiobus", device_get_unit(dev)); + + return (bus_generic_attach(dev)); +} + +static int +vf_gpio_pin_max(device_t dev, int *maxpin) +{ + + *maxpin = NGPIO - 1; + return (0); +} + +static int +vf_gpio_pin_getname(device_t dev, uint32_t pin, char *name) +{ + struct vf_gpio_softc *sc; + int i; + + sc = device_get_softc(dev); + for (i = 0; i < sc->gpio_npins; i++) { + if (sc->gpio_pins[i].gp_pin == pin) + break; + } + + if (i >= sc->gpio_npins) + return (EINVAL); + + GPIO_LOCK(sc); + memcpy(name, sc->gpio_pins[i].gp_name, GPIOMAXNAME); + GPIO_UNLOCK(sc); + + return (0); +} + +static int +vf_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) +{ + struct vf_gpio_softc *sc; + int i; + + sc = device_get_softc(dev); + for (i = 0; i < sc->gpio_npins; i++) { + if (sc->gpio_pins[i].gp_pin == pin) + break; + } + + if (i >= sc->gpio_npins) + return (EINVAL); + + GPIO_LOCK(sc); + *caps = sc->gpio_pins[i].gp_caps; + GPIO_UNLOCK(sc); + + return (0); +} + +static int +vf_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) +{ + struct vf_gpio_softc *sc; + int i; + + sc = device_get_softc(dev); + for (i = 0; i < sc->gpio_npins; i++) { + if (sc->gpio_pins[i].gp_pin == pin) + break; + } + + if (i >= sc->gpio_npins) + return (EINVAL); + + GPIO_LOCK(sc); + *flags = sc->gpio_pins[i].gp_flags; + GPIO_UNLOCK(sc); + + return (0); +} + +static int +vf_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) +{ + struct vf_gpio_softc *sc; + int i; + + sc = device_get_softc(dev); + for (i = 0; i < sc->gpio_npins; i++) { + if (sc->gpio_pins[i].gp_pin == pin) + break; + } + + if (i >= sc->gpio_npins) + return (EINVAL); + + GPIO_LOCK(sc); + *val = (READ4(sc, GPIO_PDOR(i)) & (1 << (i % 32))); + GPIO_UNLOCK(sc); + + return (0); +} + +static int +vf_gpio_pin_toggle(device_t dev, uint32_t pin) +{ + struct vf_gpio_softc *sc; + int i; + + sc = device_get_softc(dev); + for (i = 0; i < sc->gpio_npins; i++) { + if (sc->gpio_pins[i].gp_pin == pin) + break; + } + + if (i >= sc->gpio_npins) + return (EINVAL); + + GPIO_LOCK(sc); + WRITE4(sc, GPIO_PTOR(i), (1 << (i % 32))); + GPIO_UNLOCK(sc); + + return (0); +} + + +static void +vf_gpio_pin_configure(struct vf_gpio_softc *sc, struct gpio_pin *pin, + unsigned int flags) +{ + + GPIO_LOCK(sc); + + /* + * Manage input/output + */ + if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) { + pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT); + if (flags & GPIO_PIN_OUTPUT) { + pin->gp_flags |= GPIO_PIN_OUTPUT; + + } else { + pin->gp_flags |= GPIO_PIN_INPUT; + WRITE4(sc, GPIO_PCOR(pin->gp_pin), + (1 << (pin->gp_pin % 32))); + } + } + + GPIO_UNLOCK(sc); +} + + +static int +vf_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) +{ + struct vf_gpio_softc *sc; + int i; + + sc = device_get_softc(dev); + for (i = 0; i < sc->gpio_npins; i++) { + if (sc->gpio_pins[i].gp_pin == pin) + break; + } + + if (i >= sc->gpio_npins) + return (EINVAL); + + /* Check for unwanted flags. */ + if ((flags & sc->gpio_pins[i].gp_caps) != flags) + return (EINVAL); + + /* Can't mix input/output together */ + if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) == + (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) + return (EINVAL); + + vf_gpio_pin_configure(sc, &sc->gpio_pins[i], flags); + + return (0); +} + +static int +vf_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) +{ + struct vf_gpio_softc *sc; + int i; + + sc = device_get_softc(dev); + for (i = 0; i < sc->gpio_npins; i++) { + if (sc->gpio_pins[i].gp_pin == pin) + break; + } + + if (i >= sc->gpio_npins) + return (EINVAL); + + GPIO_LOCK(sc); + if (value) + WRITE4(sc, GPIO_PSOR(i), (1 << (i % 32))); + else + WRITE4(sc, GPIO_PCOR(i), (1 << (i % 32))); + GPIO_UNLOCK(sc); + + return (0); +} + +static device_method_t vf_gpio_methods[] = { + DEVMETHOD(device_probe, vf_gpio_probe), + DEVMETHOD(device_attach, vf_gpio_attach), + + /* GPIO protocol */ + DEVMETHOD(gpio_pin_max, vf_gpio_pin_max), + DEVMETHOD(gpio_pin_getname, vf_gpio_pin_getname), + DEVMETHOD(gpio_pin_getcaps, vf_gpio_pin_getcaps), + DEVMETHOD(gpio_pin_getflags, vf_gpio_pin_getflags), + DEVMETHOD(gpio_pin_get, vf_gpio_pin_get), + DEVMETHOD(gpio_pin_toggle, vf_gpio_pin_toggle), + DEVMETHOD(gpio_pin_setflags, vf_gpio_pin_setflags), + DEVMETHOD(gpio_pin_set, vf_gpio_pin_set), + { 0, 0 } +}; + +static driver_t vf_gpio_driver = { + "gpio", + vf_gpio_methods, + sizeof(struct vf_gpio_softc), +}; + +static devclass_t vf_gpio_devclass; + +DRIVER_MODULE(vf_gpio, simplebus, vf_gpio_driver, vf_gpio_devclass, 0, 0); diff --git a/sys/arm/freescale/vybrid/vf_iomuxc.c b/sys/arm/freescale/vybrid/vf_iomuxc.c new file mode 100644 index 0000000..08daf5e --- /dev/null +++ b/sys/arm/freescale/vybrid/vf_iomuxc.c @@ -0,0 +1,171 @@ +/*- + * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.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 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. + */ + +/* + * Vybrid Family Input/Output Multiplexer Controller (IOMUXC) + * Chapter 5, Vybrid Reference Manual, Rev. 5, 07/2013 + */ + +#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 <dev/fdt/fdt_common.h> +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <machine/bus.h> +#include <machine/fdt.h> +#include <machine/cpu.h> +#include <machine/intr.h> + +#include <arm/freescale/vybrid/vf_iomuxc.h> +#include <arm/freescale/vybrid/vf_common.h> + +#define IBE (1 << 0) /* Input Buffer Enable Field */ +#define OBE (1 << 1) /* Output Buffer Enable Field. */ +#define PUE (1 << 2) /* Pull / Keep Select Field. */ +#define PKE (1 << 3) /* Pull / Keep Enable Field. */ +#define PUS_MASK (3 << 4) /* Pull Up / Down Config Field. */ +#define DSE_MASK (7 << 6) /* Drive Strength Field. */ +#define HYS (1 << 9) /* Hysteresis Enable Field */ + +#define MUX_MODE_MASK 7 +#define MUX_MODE_SHIFT 20 +#define MUX_MODE_GPIO 0 +#define MUX_MODE_RMII 1 +#define MUX_MODE_RMII_CLKIN 2 +#define MUX_MODE_VBUS_EN_OTG 2 + +#define PUS_22_KOHM_PULL_UP (3 << 4) +#define DSE_25_OHM (6 << 6) + +#define NET0_PAD_START 45 +#define NET1_PAD_START 54 +#define NET_PAD_N 9 + +struct iomuxc_softc { + struct resource *tmr_res[1]; + bus_space_tag_t bst; + bus_space_handle_t bsh; + device_t dev; +}; + +static struct resource_spec iomuxc_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { -1, 0 } +}; + +static int +iomuxc_probe(device_t dev) +{ + + if (!ofw_bus_is_compatible(dev, "fsl,mvf600-iomuxc")) + return (ENXIO); + + device_set_desc(dev, "Vybrid Family IOMUXC Unit"); + return (BUS_PROBE_DEFAULT); +} + +static int +configure_pad(struct iomuxc_softc *sc, int pad, int mux_mode) +{ + int reg; + + reg = READ4(sc, pad); + reg &= ~(MUX_MODE_MASK << MUX_MODE_SHIFT); + reg |= (mux_mode << MUX_MODE_SHIFT); + WRITE4(sc, pad, reg); + + return (0); +} + +static int +iomuxc_attach(device_t dev) +{ + struct iomuxc_softc *sc; + int reg; + int i; + + sc = device_get_softc(dev); + sc->dev = dev; + + if (bus_alloc_resources(dev, iomuxc_spec, sc->tmr_res)) { + device_printf(dev, "could not allocate resources\n"); + return (ENXIO); + } + + /* Memory interface */ + sc->bst = rman_get_bustag(sc->tmr_res[0]); + sc->bsh = rman_get_bushandle(sc->tmr_res[0]); + + /* USB */ + configure_pad(sc, IOMUXC_PTA17, MUX_MODE_VBUS_EN_OTG); + reg = (PKE | PUE | PUS_22_KOHM_PULL_UP | DSE_25_OHM | OBE); + WRITE4(sc, IOMUXC_PTA7, reg); + + /* NET */ + configure_pad(sc, IOMUXC_PTA6, MUX_MODE_RMII_CLKIN); + + /* NET0 */ + for (i = NET0_PAD_START; i <= (NET0_PAD_START + NET_PAD_N); i++) { + configure_pad(sc, IOMUXC(i), MUX_MODE_RMII); + } + + /* NET1 */ + for (i = NET1_PAD_START; i <= (NET1_PAD_START + NET_PAD_N); i++) { + configure_pad(sc, IOMUXC(i), MUX_MODE_RMII); + } + + return (0); +} + +static device_method_t iomuxc_methods[] = { + DEVMETHOD(device_probe, iomuxc_probe), + DEVMETHOD(device_attach, iomuxc_attach), + { 0, 0 } +}; + +static driver_t iomuxc_driver = { + "iomuxc", + iomuxc_methods, + sizeof(struct iomuxc_softc), +}; + +static devclass_t iomuxc_devclass; + +DRIVER_MODULE(iomuxc, simplebus, iomuxc_driver, iomuxc_devclass, 0, 0); diff --git a/sys/arm/freescale/vybrid/vf_iomuxc.h b/sys/arm/freescale/vybrid/vf_iomuxc.h new file mode 100644 index 0000000..98b98b3 --- /dev/null +++ b/sys/arm/freescale/vybrid/vf_iomuxc.h @@ -0,0 +1,165 @@ +/*- + * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.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 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$ + */ + +#define IOMUXC(n) (n * 0x04) +#define IOMUXCN 135 +#define IOMUXC_PTA6 0x000 /* Software MUX Pad Control Register 0 */ +#define IOMUXC_PTA8 0x004 /* Software MUX Pad Control Register 1 */ +#define IOMUXC_PTA9 0x008 /* Software MUX Pad Control Register 2 */ +#define IOMUXC_PTA10 0x00C /* Software MUX Pad Control Register 3 */ +#define IOMUXC_PTA11 0x010 /* Software MUX Pad Control Register 4 */ +#define IOMUXC_PTA12 0x014 /* Software MUX Pad Control Register 5 */ +#define IOMUXC_PTA16 0x018 /* Software MUX Pad Control Register 6 */ +#define IOMUXC_PTA17 0x01C /* Software MUX Pad Control Register 7 */ +#define IOMUXC_PTA18 0x020 /* Software MUX Pad Control Register 8 */ +#define IOMUXC_PTA19 0x024 /* Software MUX Pad Control Register 9 */ +#define IOMUXC_PTA20 0x028 /* Software MUX Pad Control Register 10 */ +#define IOMUXC_PTA21 0x02C /* Software MUX Pad Control Register 11 */ +#define IOMUXC_PTA22 0x030 /* Software MUX Pad Control Register 12 */ +#define IOMUXC_PTA23 0x034 /* Software MUX Pad Control Register 13 */ +#define IOMUXC_PTA24 0x038 /* Software MUX Pad Control Register 14 */ +#define IOMUXC_PTA25 0x03C /* Software MUX Pad Control Register 15 */ +#define IOMUXC_PTA26 0x040 /* Software MUX Pad Control Register 16 */ +#define IOMUXC_PTA27 0x044 /* Software MUX Pad Control Register 17 */ +#define IOMUXC_PTA28 0x048 /* Software MUX Pad Control Register 18 */ +#define IOMUXC_PTA29 0x04C /* Software MUX Pad Control Register 19 */ +#define IOMUXC_PTA30 0x050 /* Software MUX Pad Control Register 20 */ +#define IOMUXC_PTA31 0x054 /* Software MUX Pad Control Register 21 */ +#define IOMUXC_PTB0 0x058 /* Software MUX Pad Control Register 22 */ +#define IOMUXC_PTB1 0x05C /* Software MUX Pad Control Register 23 */ +#define IOMUXC_PTB2 0x060 /* Software MUX Pad Control Register 24 */ +#define IOMUXC_PTB3 0x064 /* Software MUX Pad Control Register 25 */ +#define IOMUXC_PTB4 0x068 /* Software MUX Pad Control Register 26 */ +#define IOMUXC_PTB5 0x06C /* Software MUX Pad Control Register 27 */ +#define IOMUXC_PTB6 0x070 /* Software MUX Pad Control Register 28 */ +#define IOMUXC_PTB7 0x074 /* Software MUX Pad Control Register 29 */ +#define IOMUXC_PTB8 0x078 /* Software MUX Pad Control Register 30 */ +#define IOMUXC_PTB9 0x07C /* Software MUX Pad Control Register 31 */ +#define IOMUXC_PTB10 0x080 /* Software MUX Pad Control Register 32 */ +#define IOMUXC_PTB11 0x084 /* Software MUX Pad Control Register 33 */ +#define IOMUXC_PTB12 0x088 /* Software MUX Pad Control Register 34 */ +#define IOMUXC_PTB13 0x08C /* Software MUX Pad Control Register 35 */ +#define IOMUXC_PTB14 0x090 /* Software MUX Pad Control Register 36 */ +#define IOMUXC_PTB15 0x094 /* Software MUX Pad Control Register 37 */ +#define IOMUXC_PTB16 0x098 /* Software MUX Pad Control Register 38 */ +#define IOMUXC_PTB17 0x09C /* Software MUX Pad Control Register 39 */ +#define IOMUXC_PTB18 0x0A0 /* Software MUX Pad Control Register 40 */ +#define IOMUXC_PTB19 0x0A4 /* Software MUX Pad Control Register 41 */ +#define IOMUXC_PTB20 0x0A8 /* Software MUX Pad Control Register 42 */ +#define IOMUXC_PTB21 0x0AC /* Software MUX Pad Control Register 43 */ +#define IOMUXC_PTB22 0x0B0 /* Software MUX Pad Control Register 44 */ +#define IOMUXC_PTC0 0x0B4 /* Software MUX Pad Control Register 45 */ +#define IOMUXC_PTC1 0x0B8 /* Software MUX Pad Control Register 46 */ +#define IOMUXC_PTC2 0x0BC /* Software MUX Pad Control Register 47 */ +#define IOMUXC_PTC3 0x0C0 /* Software MUX Pad Control Register 48 */ +#define IOMUXC_PTC4 0x0C4 /* Software MUX Pad Control Register 49 */ +#define IOMUXC_PTC5 0x0C8 /* Software MUX Pad Control Register 50 */ +#define IOMUXC_PTC6 0x0CC /* Software MUX Pad Control Register 51 */ +#define IOMUXC_PTC7 0x0D0 /* Software MUX Pad Control Register 52 */ +#define IOMUXC_PTC8 0x0D4 /* Software MUX Pad Control Register 53 */ +#define IOMUXC_PTC9 0x0D8 /* Software MUX Pad Control Register 54 */ +#define IOMUXC_PTC10 0x0DC /* Software MUX Pad Control Register 55 */ +#define IOMUXC_PTC11 0x0E0 /* Software MUX Pad Control Register 56 */ +#define IOMUXC_PTC12 0x0E4 /* Software MUX Pad Control Register 57 */ +#define IOMUXC_PTC13 0x0E8 /* Software MUX Pad Control Register 58 */ +#define IOMUXC_PTC14 0x0EC /* Software MUX Pad Control Register 59 */ +#define IOMUXC_PTC15 0x0F0 /* Software MUX Pad Control Register 60 */ +#define IOMUXC_PTC16 0x0F4 /* Software MUX Pad Control Register 61 */ +#define IOMUXC_PTC17 0x0F8 /* Software MUX Pad Control Register 62 */ +#define IOMUXC_PTD31 0x0FC /* Software MUX Pad Control Register 63 */ +#define IOMUXC_PTD30 0x100 /* Software MUX Pad Control Register 64 */ +#define IOMUXC_PTD29 0x104 /* Software MUX Pad Control Register 65 */ +#define IOMUXC_PTD28 0x108 /* Software MUX Pad Control Register 66 */ +#define IOMUXC_PTD27 0x10C /* Software MUX Pad Control Register 67 */ +#define IOMUXC_PTD26 0x110 /* Software MUX Pad Control Register 68 */ +#define IOMUXC_PTD25 0x114 /* Software MUX Pad Control Register 69 */ +#define IOMUXC_PTD24 0x118 /* Software MUX Pad Control Register 70 */ +#define IOMUXC_PTD23 0x11C /* Software MUX Pad Control Register 71 */ +#define IOMUXC_PTD22 0x120 /* Software MUX Pad Control Register 72 */ +#define IOMUXC_PTD21 0x124 /* Software MUX Pad Control Register 73 */ +#define IOMUXC_PTD20 0x128 /* Software MUX Pad Control Register 74 */ +#define IOMUXC_PTD19 0x12C /* Software MUX Pad Control Register 75 */ +#define IOMUXC_PTD18 0x130 /* Software MUX Pad Control Register 76 */ +#define IOMUXC_PTD17 0x134 /* Software MUX Pad Control Register 77 */ +#define IOMUXC_PTD16 0x138 /* Software MUX Pad Control Register 78 */ +#define IOMUXC_PTD0 0x13C /* Software MUX Pad Control Register 79 */ +#define IOMUXC_PTD1 0x140 /* Software MUX Pad Control Register 80 */ +#define IOMUXC_PTD2 0x144 /* Software MUX Pad Control Register 81 */ +#define IOMUXC_PTD3 0x148 /* Software MUX Pad Control Register 82 */ +#define IOMUXC_PTD4 0x14C /* Software MUX Pad Control Register 83 */ +#define IOMUXC_PTD5 0x150 /* Software MUX Pad Control Register 84 */ +#define IOMUXC_PTD6 0x154 /* Software MUX Pad Control Register 85 */ +#define IOMUXC_PTD7 0x158 /* Software MUX Pad Control Register 86 */ +#define IOMUXC_PTD8 0x15C /* Software MUX Pad Control Register 87 */ +#define IOMUXC_PTD9 0x160 /* Software MUX Pad Control Register 88 */ +#define IOMUXC_PTD10 0x164 /* Software MUX Pad Control Register 89 */ +#define IOMUXC_PTD11 0x168 /* Software MUX Pad Control Register 90 */ +#define IOMUXC_PTD12 0x16C /* Software MUX Pad Control Register 91 */ +#define IOMUXC_PTD13 0x170 /* Software MUX Pad Control Register 92 */ +#define IOMUXC_PTB23 0x174 /* Software MUX Pad Control Register 93 */ +#define IOMUXC_PTB24 0x178 /* Software MUX Pad Control Register 94 */ +#define IOMUXC_PTB25 0x17C /* Software MUX Pad Control Register 95 */ +#define IOMUXC_PTB26 0x180 /* Software MUX Pad Control Register 96 */ +#define IOMUXC_PTB27 0x184 /* Software MUX Pad Control Register 97 */ +#define IOMUXC_PTB28 0x188 /* Software MUX Pad Control Register 98 */ +#define IOMUXC_PTC26 0x18C /* Software MUX Pad Control Register 99 */ +#define IOMUXC_PTC27 0x190 /* Software MUX Pad Control Register 100 */ +#define IOMUXC_PTC28 0x194 /* Software MUX Pad Control Register 101 */ +#define IOMUXC_PTC29 0x198 /* Software MUX Pad Control Register 102 */ +#define IOMUXC_PTC30 0x19C /* Software MUX Pad Control Register 103 */ +#define IOMUXC_PTC31 0x1A0 /* Software MUX Pad Control Register 104 */ +#define IOMUXC_PTE0 0x1A4 /* Software MUX Pad Control Register 105 */ +#define IOMUXC_PTE1 0x1A8 /* Software MUX Pad Control Register 106 */ +#define IOMUXC_PTE2 0x1AC /* Software MUX Pad Control Register 107 */ +#define IOMUXC_PTE3 0x1B0 /* Software MUX Pad Control Register 108 */ +#define IOMUXC_PTE4 0x1B4 /* Software MUX Pad Control Register 109 */ +#define IOMUXC_PTE5 0x1B8 /* Software MUX Pad Control Register 110 */ +#define IOMUXC_PTE6 0x1BC /* Software MUX Pad Control Register 111 */ +#define IOMUXC_PTE7 0x1C0 /* Software MUX Pad Control Register 112 */ +#define IOMUXC_PTE8 0x1C4 /* Software MUX Pad Control Register 113 */ +#define IOMUXC_PTE9 0x1C8 /* Software MUX Pad Control Register 114 */ +#define IOMUXC_PTE10 0x1CC /* Software MUX Pad Control Register 115 */ +#define IOMUXC_PTE11 0x1D0 /* Software MUX Pad Control Register 116 */ +#define IOMUXC_PTE12 0x1D4 /* Software MUX Pad Control Register 117 */ +#define IOMUXC_PTE13 0x1D8 /* Software MUX Pad Control Register 118 */ +#define IOMUXC_PTE14 0x1DC /* Software MUX Pad Control Register 119 */ +#define IOMUXC_PTE15 0x1E0 /* Software MUX Pad Control Register 120 */ +#define IOMUXC_PTE16 0x1E4 /* Software MUX Pad Control Register 121 */ +#define IOMUXC_PTE17 0x1E8 /* Software MUX Pad Control Register 122 */ +#define IOMUXC_PTE18 0x1EC /* Software MUX Pad Control Register 123 */ +#define IOMUXC_PTE19 0x1F0 /* Software MUX Pad Control Register 124 */ +#define IOMUXC_PTE20 0x1F4 /* Software MUX Pad Control Register 125 */ +#define IOMUXC_PTE21 0x1F8 /* Software MUX Pad Control Register 126 */ +#define IOMUXC_PTE22 0x1FC /* Software MUX Pad Control Register 127 */ +#define IOMUXC_PTE23 0x200 /* Software MUX Pad Control Register 128 */ +#define IOMUXC_PTE24 0x204 /* Software MUX Pad Control Register 129 */ +#define IOMUXC_PTE25 0x208 /* Software MUX Pad Control Register 130 */ +#define IOMUXC_PTE26 0x20C /* Software MUX Pad Control Register 131 */ +#define IOMUXC_PTE27 0x210 /* Software MUX Pad Control Register 132 */ +#define IOMUXC_PTE28 0x214 /* Software MUX Pad Control Register 133 */ +#define IOMUXC_PTA7 0x218 /* Software MUX Pad Control Register 134 */ diff --git a/sys/arm/freescale/vybrid/vf_machdep.c b/sys/arm/freescale/vybrid/vf_machdep.c new file mode 100644 index 0000000..29e7355 --- /dev/null +++ b/sys/arm/freescale/vybrid/vf_machdep.c @@ -0,0 +1,93 @@ +/*- + * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.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 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 "opt_ddb.h" +#include "opt_platform.h" + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#define _ARM32_BUS_DMA_PRIVATE +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> + +#include <vm/vm.h> + +#include <machine/armreg.h> +#include <machine/bus.h> +#include <machine/devmap.h> +#include <machine/machdep.h> + +#include <dev/fdt/fdt_common.h> + +vm_offset_t +initarm_lastaddr(void) +{ + + return (arm_devmap_lastaddr()); +} + +void +initarm_early_init(void) +{ + +} + +void +initarm_gpio_init(void) +{ + +} + +void +initarm_late_init(void) +{ + +} + +int +initarm_devmap_init(void) +{ + + arm_devmap_add_entry(0x40000000, 0x100000); + + return (0); +} + +struct arm32_dma_range * +bus_dma_get_range(void) +{ + + return (NULL); +} + +int +bus_dma_get_range_nb(void) +{ + + return (0); +} diff --git a/sys/arm/freescale/vybrid/vf_mscm.c b/sys/arm/freescale/vybrid/vf_mscm.c new file mode 100644 index 0000000..5741627 --- /dev/null +++ b/sys/arm/freescale/vybrid/vf_mscm.c @@ -0,0 +1,123 @@ +/*- + * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.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 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. + */ + +/* + * Vybrid Family Miscellaneous System Control Module (MSCM) + * Chapter 66, Vybrid Reference Manual, Rev. 5, 07/2013 + */ + +#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 <dev/fdt/fdt_common.h> +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <machine/bus.h> +#include <machine/fdt.h> +#include <machine/cpu.h> +#include <machine/intr.h> + +#include <arm/freescale/vybrid/vf_common.h> + +#define VF_NINT 112 /* Total number of interrupts */ + +/* Int Router Shared Peripheral Routing Control */ +#define MSCM_IRSPRC(n) (0x880 + 2 * n) + +struct mscm_softc { + struct resource *res[1]; + bus_space_tag_t bst; + bus_space_handle_t bsh; +}; + +static struct resource_spec mscm_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { -1, 0 } +}; + +static int +mscm_probe(device_t dev) +{ + + if (!ofw_bus_is_compatible(dev, "fsl,mvf600-mscm")) + return (ENXIO); + + device_set_desc(dev, "Vybrid Family Miscellaneous System Control Module"); + return (BUS_PROBE_DEFAULT); +} + +static int +mscm_attach(device_t dev) +{ + struct mscm_softc *sc; + int i; + + sc = device_get_softc(dev); + + if (bus_alloc_resources(dev, mscm_spec, sc->res)) { + device_printf(dev, "could not allocate resources\n"); + return (ENXIO); + } + + /* Memory interface */ + sc->bst = rman_get_bustag(sc->res[0]); + sc->bsh = rman_get_bushandle(sc->res[0]); + + /* Route all the interrupts to CP0 */ + for (i = 0; i < VF_NINT; i++) + WRITE2(sc, MSCM_IRSPRC(i), 1); + + return (0); +} + +static device_method_t mscm_methods[] = { + DEVMETHOD(device_probe, mscm_probe), + DEVMETHOD(device_attach, mscm_attach), + { 0, 0 } +}; + +static driver_t mscm_driver = { + "mscm", + mscm_methods, + sizeof(struct mscm_softc), +}; + +static devclass_t mscm_devclass; + +DRIVER_MODULE(mscm, simplebus, mscm_driver, mscm_devclass, 0, 0); diff --git a/sys/arm/freescale/vybrid/vf_nfc.c b/sys/arm/freescale/vybrid/vf_nfc.c new file mode 100644 index 0000000..8132200 --- /dev/null +++ b/sys/arm/freescale/vybrid/vf_nfc.c @@ -0,0 +1,524 @@ +/*- + * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.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 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. + */ + +/* + * Vybrid Family NAND Flash Controller (NFC) + * Chapter 31, Vybrid Reference Manual, Rev. 5, 07/2013 + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/malloc.h> +#include <sys/rman.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/time.h> + +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> +#include <dev/nand/nand.h> +#include <dev/nand/nandbus.h> + +#include <machine/bus.h> +#include <machine/fdt.h> + +#include "nfc_if.h" + +#include <arm/freescale/vybrid/vf_common.h> + +enum addr_type { + ADDR_NONE, + ADDR_ID, + ADDR_ROW, + ADDR_ROWCOL +}; + +struct fsl_nfc_fcm { + uint32_t addr_bits; + enum addr_type addr_type; + uint32_t col_addr_bits; + uint32_t row_addr_bits; + u_int read_ptr; + u_int addr_ptr; + u_int command; + u_int code; +}; + +struct vf_nand_softc { + struct nand_softc nand_dev; + bus_space_handle_t bsh; + bus_space_tag_t bst; + struct resource *res[2]; + struct fsl_nfc_fcm fcm; +}; + +static struct resource_spec nfc_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { SYS_RES_IRQ, 0, RF_ACTIVE }, + { -1, 0 } +}; + +static int vf_nand_attach(device_t); +static int vf_nand_probe(device_t); +static int vf_nand_send_command(device_t, uint8_t); +static int vf_nand_send_address(device_t, uint8_t); +static int vf_nand_start_command(device_t); +static uint8_t vf_nand_read_byte(device_t); +static void vf_nand_read_buf(device_t, void *, uint32_t); +static void vf_nand_write_buf(device_t, void *, uint32_t); +static int vf_nand_select_cs(device_t, uint8_t); +static int vf_nand_read_rnb(device_t); + +#define CMD_READ_PAGE 0x7EE0 +#define CMD_PROG_PAGE 0x7FC0 +#define CMD_PROG_PAGE_DMA 0xFFC8 +#define CMD_ERASE 0x4EC0 +#define CMD_READ_ID 0x4804 +#define CMD_READ_STATUS 0x4068 +#define CMD_RESET 0x4040 +#define CMD_RANDOM_IN 0x7140 +#define CMD_RANDOM_OUT 0x70E0 + +#define CMD_BYTE2_PROG_PAGE 0x10 +#define CMD_BYTE2_PAGE_READ 0x30 +#define CMD_BYTE2_ERASE 0xD0 + +#define NFC_CMD1 0x3F00 /* Flash command 1 */ +#define NFC_CMD2 0x3F04 /* Flash command 2 */ +#define NFC_CAR 0x3F08 /* Column address */ +#define NFC_RAR 0x3F0C /* Row address */ +#define NFC_RPT 0x3F10 /* Flash command repeat */ +#define NFC_RAI 0x3F14 /* Row address increment */ +#define NFC_SR1 0x3F18 /* Flash status 1 */ +#define NFC_SR2 0x3F1C /* Flash status 2 */ +#define NFC_DMA_CH1 0x3F20 /* DMA channel 1 address */ +#define NFC_DMACFG 0x3F24 /* DMA configuration */ +#define NFC_SWAP 0x3F28 /* Cach swap */ +#define NFC_SECSZ 0x3F2C /* Sector size */ +#define NFC_CFG 0x3F30 /* Flash configuration */ +#define NFC_DMA_CH2 0x3F34 /* DMA channel 2 address */ +#define NFC_ISR 0x3F38 /* Interrupt status */ + +#define ECCMODE_SHIFT 17 +#define AIAD_SHIFT 5 +#define AIBN_SHIFT 4 +#define PAGECOUNT_SHIFT 0 +#define BITWIDTH_SHIFT 7 +#define BITWIDTH8 0 +#define BITWIDTH16 1 +#define PAGECOUNT_MASK 0xf + +#define CMD2_BYTE1_SHIFT 24 +#define CMD2_CODE_SHIFT 8 +#define CMD2_BUFNO_SHIFT 1 +#define CMD2_START_SHIFT 0 + +static device_method_t vf_nand_methods[] = { + DEVMETHOD(device_probe, vf_nand_probe), + DEVMETHOD(device_attach, vf_nand_attach), + DEVMETHOD(nfc_start_command, vf_nand_start_command), + DEVMETHOD(nfc_send_command, vf_nand_send_command), + DEVMETHOD(nfc_send_address, vf_nand_send_address), + DEVMETHOD(nfc_read_byte, vf_nand_read_byte), + DEVMETHOD(nfc_read_buf, vf_nand_read_buf), + DEVMETHOD(nfc_write_buf, vf_nand_write_buf), + DEVMETHOD(nfc_select_cs, vf_nand_select_cs), + DEVMETHOD(nfc_read_rnb, vf_nand_read_rnb), + { 0, 0 }, +}; + +static driver_t vf_nand_driver = { + "nand", + vf_nand_methods, + sizeof(struct vf_nand_softc), +}; + +static devclass_t vf_nand_devclass; +DRIVER_MODULE(vf_nand, simplebus, vf_nand_driver, vf_nand_devclass, 0, 0); + +static int +vf_nand_probe(device_t dev) +{ + + if (!ofw_bus_is_compatible(dev, "fsl,mvf600-nand")) + return (ENXIO); + + device_set_desc(dev, "Vybrid Family NAND controller"); + return (BUS_PROBE_DEFAULT); +} + +static int +vf_nand_attach(device_t dev) +{ + struct vf_nand_softc *sc; + int err; + int reg; + + sc = device_get_softc(dev); + if (bus_alloc_resources(dev, nfc_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]); + + /* Size in bytes of one elementary transfer unit */ + WRITE4(sc, NFC_SECSZ, 2048); + + /* Flash mode width */ + reg = READ4(sc, NFC_CFG); + reg |= (BITWIDTH16 << BITWIDTH_SHIFT); + + /* No correction, ECC bypass */ + reg &= ~(0x7 << ECCMODE_SHIFT); + + /* Disable Auto-incrementing of flash row address */ + reg &= ~(0x1 << AIAD_SHIFT); + + /* Disable Auto-incrementing of buffer numbers */ + reg &= ~(0x1 << AIBN_SHIFT); + + /* + * Number of virtual pages (in one physical flash page) + * to be programmed or read, etc. + */ + reg &= ~(PAGECOUNT_MASK); + reg |= (1 << PAGECOUNT_SHIFT); + WRITE4(sc, NFC_CFG, reg); + + nand_init(&sc->nand_dev, dev, NAND_ECC_NONE, 0, 0, NULL, NULL); + err = nandbus_create(dev); + return (err); +} + +static int +vf_nand_start_command(device_t dev) +{ + struct vf_nand_softc *sc; + struct fsl_nfc_fcm *fcm; + int reg; + + sc = device_get_softc(dev); + fcm = &sc->fcm; + + nand_debug(NDBG_DRV,"vf_nand: start command %x", fcm->command); + + /* CMD2 */ + reg = READ4(sc, NFC_CMD2); + reg &= ~(0xff << CMD2_BYTE1_SHIFT); + reg |= (fcm->command << CMD2_BYTE1_SHIFT); + WRITE4(sc, NFC_CMD2, reg); + + /* CMD1 */ + if ((fcm->command == NAND_CMD_READ) || + (fcm->command == NAND_CMD_PROG) || + (fcm->command == NAND_CMD_ERASE)) { + reg = READ4(sc, NFC_CMD1); + reg &= ~(0xff << 24); + + if (fcm->command == NAND_CMD_READ) + reg |= (CMD_BYTE2_PAGE_READ << 24); + else if (fcm->command == NAND_CMD_PROG) + reg |= (CMD_BYTE2_PROG_PAGE << 24); + else if (fcm->command == NAND_CMD_ERASE) + reg |= (CMD_BYTE2_ERASE << 24); + + WRITE4(sc, NFC_CMD1, reg); + } + + /* We work with 1st buffer */ + reg = READ4(sc, NFC_CMD2); + reg &= ~(0xf << CMD2_BUFNO_SHIFT); + reg |= (0 << CMD2_BUFNO_SHIFT); + WRITE4(sc, NFC_CMD2, reg); + + /* Cmd CODE */ + reg = READ4(sc, NFC_CMD2); + reg &= ~(0xffff << CMD2_CODE_SHIFT); + reg |= (fcm->code << CMD2_CODE_SHIFT); + WRITE4(sc, NFC_CMD2, reg); + + /* Col */ + if (fcm->addr_type == ADDR_ROWCOL) { + reg = READ4(sc, NFC_CAR); + reg &= ~(0xffff); + reg |= fcm->col_addr_bits; + nand_debug(NDBG_DRV,"setting CAR to 0x%08x\n", reg); + WRITE4(sc, NFC_CAR, reg); + } + + /* Row */ + reg = READ4(sc, NFC_RAR); + reg &= ~(0xffffff); + if (fcm->addr_type == ADDR_ID) + reg |= fcm->addr_bits; + else + reg |= fcm->row_addr_bits; + WRITE4(sc, NFC_RAR, reg); + + /* Start */ + reg = READ4(sc, NFC_CMD2); + reg |= (1 << CMD2_START_SHIFT); + WRITE4(sc, NFC_CMD2, reg); + + /* Wait command completion */ + while (READ4(sc, NFC_CMD2) & (1 << CMD2_START_SHIFT)) + ; + + return (0); +} + +static int +vf_nand_send_command(device_t dev, uint8_t command) +{ + struct vf_nand_softc *sc; + struct fsl_nfc_fcm *fcm; + + nand_debug(NDBG_DRV,"vf_nand: send command %x", command); + + sc = device_get_softc(dev); + fcm = &sc->fcm; + + if ((command == NAND_CMD_READ_END) || + (command == NAND_CMD_PROG_END) || + (command == NAND_CMD_ERASE_END)) { + return (0); + } + + fcm->command = command; + + fcm->code = 0; + fcm->read_ptr = 0; + fcm->addr_type = 0; + fcm->addr_bits = 0; + + fcm->addr_ptr = 0; + fcm->col_addr_bits = 0; + fcm->row_addr_bits = 0; + + switch (command) { + case NAND_CMD_READ: + fcm->code = CMD_READ_PAGE; + fcm->addr_type = ADDR_ROWCOL; + break; + case NAND_CMD_PROG: + fcm->code = CMD_PROG_PAGE; + fcm->addr_type = ADDR_ROWCOL; + break; + case NAND_CMD_PROG_END: + break; + case NAND_CMD_ERASE_END: + break; + case NAND_CMD_RESET: + fcm->code = CMD_RESET; + break; + case NAND_CMD_READ_ID: + fcm->code = CMD_READ_ID; + fcm->addr_type = ADDR_ID; + break; + case NAND_CMD_READ_PARAMETER: + fcm->code = CMD_READ_PAGE; + fcm->addr_type = ADDR_ID; + break; + case NAND_CMD_STATUS: + fcm->code = CMD_READ_STATUS; + break; + case NAND_CMD_ERASE: + fcm->code = CMD_ERASE; + fcm->addr_type = ADDR_ROW; + break; + default: + nand_debug(NDBG_DRV, "unknown command %d\n", command); + return (1); + } + + return (0); +} + +static int +vf_nand_send_address(device_t dev, uint8_t addr) +{ + struct vf_nand_softc *sc; + struct fsl_nfc_fcm *fcm; + + nand_debug(NDBG_DRV,"vf_nand: send address %x", addr); + sc = device_get_softc(dev); + fcm = &sc->fcm; + + nand_debug(NDBG_DRV, "setting addr #%d to 0x%02x\n", fcm->addr_ptr, addr); + + if (fcm->addr_type == ADDR_ID) { + fcm->addr_bits = addr; + } else if (fcm->addr_type == ADDR_ROWCOL) { + + if (fcm->addr_ptr < 2) + fcm->col_addr_bits |= (addr << (fcm->addr_ptr * 8)); + else + fcm->row_addr_bits |= (addr << ((fcm->addr_ptr - 2) * 8)); + + } else if (fcm->addr_type == ADDR_ROW) + fcm->row_addr_bits |= (addr << (fcm->addr_ptr * 8)); + + fcm->addr_ptr += 1; + + return (0); +} + +static uint8_t +vf_nand_read_byte(device_t dev) +{ + struct vf_nand_softc *sc; + struct fsl_nfc_fcm *fcm; + uint8_t data; + int sr1, sr2; + int b; + + sc = device_get_softc(dev); + fcm = &sc->fcm; + + sr1 = READ4(sc, NFC_SR1); + sr2 = READ4(sc, NFC_SR2); + + data = 0; + if (fcm->addr_type == ADDR_ID) { + b = 32 - ((fcm->read_ptr + 1) * 8); + data = (sr1 >> b) & 0xff; + fcm->read_ptr++; + } else if (fcm->command == NAND_CMD_STATUS) { + data = sr2 & 0xff; + } + + nand_debug(NDBG_DRV,"vf_nand: read %x", data); + return (data); +} + +static void +vf_nand_read_buf(device_t dev, void* buf, uint32_t len) +{ + struct vf_nand_softc *sc; + struct fsl_nfc_fcm *fcm; + uint16_t *tmp; + uint8_t *b; + int i; + + b = (uint8_t*)buf; + sc = device_get_softc(dev); + fcm = &sc->fcm; + + nand_debug(NDBG_DRV, "vf_nand: read_buf len %d", len); + + if (fcm->command == NAND_CMD_READ_PARAMETER) { + tmp = malloc(len, M_DEVBUF, M_NOWAIT); + bus_read_region_2(sc->res[0], 0x0, tmp, len); + + for (i = 0; i < len; i += 2) { + b[i] = tmp[i+1]; + b[i+1] = tmp[i]; + } + + free(tmp, M_DEVBUF); + +#ifdef NAND_DEBUG + for (i = 0; i < len; i++) { + if (!(i % 16)) + printf("%s", i == 0 ? "vf_nand:\n" : "\n"); + printf(" %x", b[i]); + if (i == len - 1) + printf("\n"); + } +#endif + + } else { + + for (i = 0; i < len; i++) { + b[i] = READ1(sc, i); + +#ifdef NAND_DEBUG + if (!(i % 16)) + printf("%s", i == 0 ? "vf_nand:\n" : "\n"); + printf(" %x", b[i]); + if (i == len - 1) + printf("\n"); +#endif + } + + } +} + +static void +vf_nand_write_buf(device_t dev, void* buf, uint32_t len) +{ + struct vf_nand_softc *sc; + struct fsl_nfc_fcm *fcm; + uint8_t *b; + int i; + + b = (uint8_t*)buf; + sc = device_get_softc(dev); + fcm = &sc->fcm; + + nand_debug(NDBG_DRV,"vf_nand: write_buf len %d", len); + + for (i = 0; i < len; i++) { + WRITE1(sc, i, b[i]); + +#ifdef NAND_DEBUG + if (!(i % 16)) + printf("%s", i == 0 ? "vf_nand:\n" : "\n"); + printf(" %x", b[i]); + if (i == len - 1) + printf("\n"); +#endif + + } +} + +static int +vf_nand_select_cs(device_t dev, uint8_t cs) +{ + + if (cs > 0) + return (ENODEV); + + return (0); +} + +static int +vf_nand_read_rnb(device_t dev) +{ + + /* no-op */ + return (0); /* ready */ +} diff --git a/sys/arm/freescale/vybrid/vf_src.c b/sys/arm/freescale/vybrid/vf_src.c new file mode 100644 index 0000000..0fe6f3b --- /dev/null +++ b/sys/arm/freescale/vybrid/vf_src.c @@ -0,0 +1,147 @@ +/*- + * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.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 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. + */ + +/* + * Vybrid Family System Reset Controller (SRC) + * Chapter 18, Vybrid Reference Manual, Rev. 5, 07/2013 + */ + +#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 <dev/fdt/fdt_common.h> +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <machine/bus.h> +#include <machine/fdt.h> +#include <machine/cpu.h> +#include <machine/intr.h> + +#include <arm/freescale/vybrid/vf_src.h> +#include <arm/freescale/vybrid/vf_common.h> + +#define SRC_SCR 0x00 /* SRC Control Register */ +#define SRC_SBMR1 0x04 /* SRC Boot Mode Register 1 */ +#define SRC_SRSR 0x08 /* SRC Status Register */ +#define SRC_SECR 0x0C /* SRC_SECR */ +#define SRC_SICR 0x14 /* SRC Reset Interrupt Configuration Register */ +#define SRC_SIMR 0x18 /* SRC Interrupt Masking Register */ +#define SRC_SBMR2 0x1C /* SRC Boot Mode Register 2 */ +#define SRC_GPR0 0x20 /* General Purpose Register */ +#define SRC_GPR1 0x24 /* General Purpose Register */ +#define SRC_GPR2 0x28 /* General Purpose Register */ +#define SRC_GPR3 0x2C /* General Purpose Register */ +#define SRC_GPR4 0x30 /* General Purpose Register */ +#define SRC_MISC0 0x4C /* MISC0 */ +#define SRC_MISC1 0x50 /* MISC1 */ +#define SRC_MISC2 0x54 /* MISC2 */ +#define SRC_MISC3 0x58 /* MISC3 */ + +struct src_softc { + struct resource *res[1]; + bus_space_tag_t bst; + bus_space_handle_t bsh; +}; + +struct src_softc *src_sc; + +static struct resource_spec src_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { -1, 0 } +}; + +int +src_swreset(void) +{ + + if (src_sc == NULL) + return (1); + + WRITE4(src_sc, SRC_SCR, SW_RST); + + return (0); +} + +static int +src_probe(device_t dev) +{ + + if (!ofw_bus_is_compatible(dev, "fsl,mvf600-src")) + return (ENXIO); + + device_set_desc(dev, "Vybrid Family System Reset Controller"); + return (BUS_PROBE_DEFAULT); +} + +static int +src_attach(device_t dev) +{ + struct src_softc *sc; + + sc = device_get_softc(dev); + + if (bus_alloc_resources(dev, src_spec, sc->res)) { + device_printf(dev, "could not allocate resources\n"); + return (ENXIO); + } + + /* Memory interface */ + sc->bst = rman_get_bustag(sc->res[0]); + sc->bsh = rman_get_bushandle(sc->res[0]); + + src_sc = sc; + + return (0); +} + +static device_method_t src_methods[] = { + DEVMETHOD(device_probe, src_probe), + DEVMETHOD(device_attach, src_attach), + { 0, 0 } +}; + +static driver_t src_driver = { + "src", + src_methods, + sizeof(struct src_softc), +}; + +static devclass_t src_devclass; + +DRIVER_MODULE(src, simplebus, src_driver, src_devclass, 0, 0); diff --git a/sys/arm/freescale/vybrid/vf_src.h b/sys/arm/freescale/vybrid/vf_src.h new file mode 100644 index 0000000..8e50b05 --- /dev/null +++ b/sys/arm/freescale/vybrid/vf_src.h @@ -0,0 +1,30 @@ +/*- + * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.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 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$ + */ + +#define SW_RST (1 << 12) /* Software reset */ +int src_swreset(void); diff --git a/sys/arm/freescale/vybrid/vf_uart.c b/sys/arm/freescale/vybrid/vf_uart.c new file mode 100644 index 0000000..d181432 --- /dev/null +++ b/sys/arm/freescale/vybrid/vf_uart.c @@ -0,0 +1,509 @@ +/*- + * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.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 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. + */ + +/* + * Vybrid Family Universal Asynchronous Receiver/Transmitter + * Chapter 49, Vybrid Reference Manual, Rev. 5, 07/2013 + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include "opt_ddb.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/kdb.h> +#include <machine/bus.h> +#include <machine/fdt.h> + +#include <dev/uart/uart.h> +#include <dev/uart/uart_cpu.h> +#include <dev/uart/uart_bus.h> + +#include "uart_if.h" + +#define UART_BDH 0x00 /* Baud Rate Registers: High */ +#define UART_BDL 0x01 /* Baud Rate Registers: Low */ +#define UART_C1 0x02 /* Control Register 1 */ +#define UART_C2 0x03 /* Control Register 2 */ +#define UART_S1 0x04 /* Status Register 1 */ +#define UART_S2 0x05 /* Status Register 2 */ +#define UART_C3 0x06 /* Control Register 3 */ +#define UART_D 0x07 /* Data Register */ +#define UART_MA1 0x08 /* Match Address Registers 1 */ +#define UART_MA2 0x09 /* Match Address Registers 2 */ +#define UART_C4 0x0A /* Control Register 4 */ +#define UART_C5 0x0B /* Control Register 5 */ +#define UART_ED 0x0C /* Extended Data Register */ +#define UART_MODEM 0x0D /* Modem Register */ +#define UART_IR 0x0E /* Infrared Register */ +#define UART_PFIFO 0x10 /* FIFO Parameters */ +#define UART_CFIFO 0x11 /* FIFO Control Register */ +#define UART_SFIFO 0x12 /* FIFO Status Register */ +#define UART_TWFIFO 0x13 /* FIFO Transmit Watermark */ +#define UART_TCFIFO 0x14 /* FIFO Transmit Count */ +#define UART_RWFIFO 0x15 /* FIFO Receive Watermark */ +#define UART_RCFIFO 0x16 /* FIFO Receive Count */ +#define UART_C7816 0x18 /* 7816 Control Register */ +#define UART_IE7816 0x19 /* 7816 Interrupt Enable Register */ +#define UART_IS7816 0x1A /* 7816 Interrupt Status Register */ +#define UART_WP7816T0 0x1B /* 7816 Wait Parameter Register */ +#define UART_WP7816T1 0x1B /* 7816 Wait Parameter Register */ +#define UART_WN7816 0x1C /* 7816 Wait N Register */ +#define UART_WF7816 0x1D /* 7816 Wait FD Register */ +#define UART_ET7816 0x1E /* 7816 Error Threshold Register */ +#define UART_TL7816 0x1F /* 7816 Transmit Length Register */ +#define UART_C6 0x21 /* CEA709.1-B Control Register 6 */ +#define UART_PCTH 0x22 /* CEA709.1-B Packet Cycle Time Counter High */ +#define UART_PCTL 0x23 /* CEA709.1-B Packet Cycle Time Counter Low */ +#define UART_B1T 0x24 /* CEA709.1-B Beta1 Timer */ +#define UART_SDTH 0x25 /* CEA709.1-B Secondary Delay Timer High */ +#define UART_SDTL 0x26 /* CEA709.1-B Secondary Delay Timer Low */ +#define UART_PRE 0x27 /* CEA709.1-B Preamble */ +#define UART_TPL 0x28 /* CEA709.1-B Transmit Packet Length */ +#define UART_IE 0x29 /* CEA709.1-B Interrupt Enable Register */ +#define UART_WB 0x2A /* CEA709.1-B WBASE */ +#define UART_S3 0x2B /* CEA709.1-B Status Register */ +#define UART_S4 0x2C /* CEA709.1-B Status Register */ +#define UART_RPL 0x2D /* CEA709.1-B Received Packet Length */ +#define UART_RPREL 0x2E /* CEA709.1-B Received Preamble Length */ +#define UART_CPW 0x2F /* CEA709.1-B Collision Pulse Width */ +#define UART_RIDT 0x30 /* CEA709.1-B Receive Indeterminate Time */ +#define UART_TIDT 0x31 /* CEA709.1-B Transmit Indeterminate Time */ + +#define UART_C2_TE (1 << 3) /* Transmitter Enable */ +#define UART_C2_TIE (1 << 7) /* Transmitter Interrupt Enable */ +#define UART_C2_RE (1 << 2) /* Receiver Enable */ +#define UART_C2_RIE (1 << 5) /* Receiver Interrupt Enable */ +#define UART_S1_TDRE (1 << 7) /* Transmit Data Register Empty Flag */ +#define UART_S1_RDRF (1 << 5) /* Receive Data Register Full Flag */ +#define UART_S2_LBKDIF (1 << 7) /* LIN Break Detect Interrupt Flag */ + +#define UART_C4_BRFA 0x1f /* Baud Rate Fine Adjust */ +#define UART_BDH_SBR 0x1f /* UART Baud Rate Bits */ + +/* + * Low-level UART interface. + */ +static int vf_uart_probe(struct uart_bas *bas); +static void vf_uart_init(struct uart_bas *bas, int, int, int, int); +static void vf_uart_term(struct uart_bas *bas); +static void vf_uart_putc(struct uart_bas *bas, int); +static int vf_uart_rxready(struct uart_bas *bas); +static int vf_uart_getc(struct uart_bas *bas, struct mtx *); + +void uart_reinit(struct uart_softc *,int,int); + +static struct uart_ops uart_vybrid_ops = { + .probe = vf_uart_probe, + .init = vf_uart_init, + .term = vf_uart_term, + .putc = vf_uart_putc, + .rxready = vf_uart_rxready, + .getc = vf_uart_getc, +}; + +static int +vf_uart_probe(struct uart_bas *bas) +{ + + return (0); +} + +static void +vf_uart_init(struct uart_bas *bas, int baudrate, int databits, + int stopbits, int parity) +{ + +} + +static void +vf_uart_term(struct uart_bas *bas) +{ + +} + +static void +vf_uart_putc(struct uart_bas *bas, int c) +{ + + while (!(uart_getreg(bas, UART_S1) & UART_S1_TDRE)) + ; + + uart_setreg(bas, UART_D, c); +} + +static int +vf_uart_rxready(struct uart_bas *bas) +{ + int usr1; + + usr1 = uart_getreg(bas, UART_S1); + if (usr1 & UART_S1_RDRF) { + return (1); + } + + return (0); +} + +static int +vf_uart_getc(struct uart_bas *bas, struct mtx *hwmtx) +{ + int c; + + uart_lock(hwmtx); + + while (!(uart_getreg(bas, UART_S1) & UART_S1_RDRF)) + ; + + c = uart_getreg(bas, UART_D); + uart_unlock(hwmtx); + + return (c & 0xff); +} + +/* + * High-level UART interface. + */ +struct vf_uart_softc { + struct uart_softc base; +}; + +void +uart_reinit(struct uart_softc *sc, int clkspeed, int baud) +{ + struct uart_bas *bas; + int sbr; + int brfa; + int reg; + + bas = &sc->sc_bas; + if (!bas) { + printf("Error: cant reconfigure bas\n"); + return; + } + + uart_setreg(bas, UART_MODEM, 0x00); + + /* + * Disable transmitter and receiver + * for a while. + */ + reg = uart_getreg(bas, UART_C2); + reg &= ~(UART_C2_RE | UART_C2_TE); + uart_setreg(bas, UART_C2, 0x00); + + uart_setreg(bas, UART_C1, 0x00); + + sbr = (uint16_t) (clkspeed / (baud * 16)); + brfa = (clkspeed / baud) - (sbr * 16); + + reg = uart_getreg(bas, UART_BDH); + reg &= ~UART_BDH_SBR; + reg |= ((sbr & 0x1f00) >> 8); + uart_setreg(bas, UART_BDH, reg); + + reg = sbr & 0x00ff; + uart_setreg(bas, UART_BDL, reg); + + reg = uart_getreg(bas, UART_C4); + reg &= ~UART_C4_BRFA; + reg |= (brfa & UART_C4_BRFA); + uart_setreg(bas, UART_C4, reg); + + reg = uart_getreg(bas, UART_C2); + reg |= (UART_C2_RE | UART_C2_TE); + uart_setreg(bas, UART_C2, reg); + +} + +static int vf_uart_bus_attach(struct uart_softc *); +static int vf_uart_bus_detach(struct uart_softc *); +static int vf_uart_bus_flush(struct uart_softc *, int); +static int vf_uart_bus_getsig(struct uart_softc *); +static int vf_uart_bus_ioctl(struct uart_softc *, int, intptr_t); +static int vf_uart_bus_ipend(struct uart_softc *); +static int vf_uart_bus_param(struct uart_softc *, int, int, int, int); +static int vf_uart_bus_probe(struct uart_softc *); +static int vf_uart_bus_receive(struct uart_softc *); +static int vf_uart_bus_setsig(struct uart_softc *, int); +static int vf_uart_bus_transmit(struct uart_softc *); + +static kobj_method_t vf_uart_methods[] = { + KOBJMETHOD(uart_attach, vf_uart_bus_attach), + KOBJMETHOD(uart_detach, vf_uart_bus_detach), + KOBJMETHOD(uart_flush, vf_uart_bus_flush), + KOBJMETHOD(uart_getsig, vf_uart_bus_getsig), + KOBJMETHOD(uart_ioctl, vf_uart_bus_ioctl), + KOBJMETHOD(uart_ipend, vf_uart_bus_ipend), + KOBJMETHOD(uart_param, vf_uart_bus_param), + KOBJMETHOD(uart_probe, vf_uart_bus_probe), + KOBJMETHOD(uart_receive, vf_uart_bus_receive), + KOBJMETHOD(uart_setsig, vf_uart_bus_setsig), + KOBJMETHOD(uart_transmit, vf_uart_bus_transmit), + { 0, 0 } +}; + +struct uart_class uart_vybrid_class = { + "vybrid", + vf_uart_methods, + sizeof(struct vf_uart_softc), + .uc_ops = &uart_vybrid_ops, + .uc_range = 0x100, + .uc_rclk = 24000000 /* TODO: get value from CCM */ +}; + +static int +vf_uart_bus_attach(struct uart_softc *sc) +{ + struct uart_bas *bas; + int reg; + + bas = &sc->sc_bas; + + sc->sc_hwiflow = 0; + sc->sc_hwoflow = 0; + + uart_reinit(sc, 66000000, 115200); + + reg = uart_getreg(bas, UART_C2); + if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) { + reg &= ~UART_C2_RIE; + } else { + reg |= UART_C2_RIE; + } + uart_setreg(bas, UART_C2, reg); + + return (0); +} + +static int +vf_uart_bus_detach(struct uart_softc *sc) +{ + + /* TODO */ + return (0); +} + +static int +vf_uart_bus_flush(struct uart_softc *sc, int what) +{ + + /* TODO */ + return (0); +} + +static int +vf_uart_bus_getsig(struct uart_softc *sc) +{ + + /* TODO */ + return (0); +} + +static int +vf_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) +{ + struct uart_bas *bas; + int error; + + bas = &sc->sc_bas; + error = 0; + uart_lock(sc->sc_hwmtx); + switch (request) { + case UART_IOCTL_BREAK: + /* TODO */ + break; + case UART_IOCTL_BAUD: + /* TODO */ + *(int*)data = 115200; + break; + default: + error = EINVAL; + break; + } + uart_unlock(sc->sc_hwmtx); + + return (error); +} + +static int +vf_uart_bus_ipend(struct uart_softc *sc) +{ + struct uart_bas *bas; + int ipend; + uint32_t usr1, usr2; + int reg; + int sfifo; + + bas = &sc->sc_bas; + ipend = 0; + + uart_lock(sc->sc_hwmtx); + + usr1 = uart_getreg(bas, UART_S1); + usr2 = uart_getreg(bas, UART_S2); + sfifo = uart_getreg(bas, UART_SFIFO); + + /* ack usr2 */ + uart_setreg(bas, UART_S2, usr2); + + if (usr1 & UART_S1_TDRE) { + reg = uart_getreg(bas, UART_C2); + reg &= ~(UART_C2_TIE); + uart_setreg(bas, UART_C2, reg); + + if (sc->sc_txbusy != 0) { + ipend |= SER_INT_TXIDLE; + } + } + + if (usr1 & UART_S1_RDRF) { + reg = uart_getreg(bas, UART_C2); + reg &= ~(UART_C2_RIE); + uart_setreg(bas, UART_C2, reg); + + ipend |= SER_INT_RXREADY; + } + + if (usr2 & UART_S2_LBKDIF) { + ipend |= SER_INT_BREAK; + } + + uart_unlock(sc->sc_hwmtx); + + return (ipend); +} + +static int +vf_uart_bus_param(struct uart_softc *sc, int baudrate, int databits, + int stopbits, int parity) +{ + + uart_lock(sc->sc_hwmtx); + vf_uart_init(&sc->sc_bas, baudrate, databits, stopbits, parity); + uart_unlock(sc->sc_hwmtx); + + return (0); +} + +static int +vf_uart_bus_probe(struct uart_softc *sc) +{ + int error; + + error = vf_uart_probe(&sc->sc_bas); + if (error) + return (error); + + sc->sc_rxfifosz = 1; + sc->sc_txfifosz = 1; + + device_set_desc(sc->sc_dev, "Vybrid Family UART"); + return (0); +} + +static int +vf_uart_bus_receive(struct uart_softc *sc) +{ + struct uart_bas *bas; + int reg; + int c; + + bas = &sc->sc_bas; + uart_lock(sc->sc_hwmtx); + + /* Read FIFO */ + while (uart_getreg(bas, UART_S1) & UART_S1_RDRF) { + if (uart_rx_full(sc)) { + /* No space left in input buffer */ + sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN; + break; + } + + c = uart_getreg(bas, UART_D); + uart_rx_put(sc, c); + } + + /* Reenable Data Ready interrupt */ + reg = uart_getreg(bas, UART_C2); + reg |= (UART_C2_RIE); + uart_setreg(bas, UART_C2, reg); + + uart_unlock(sc->sc_hwmtx); + return (0); +} + +static int +vf_uart_bus_setsig(struct uart_softc *sc, int sig) +{ + struct uart_bas *bas; + int reg; + + /* TODO: implement (?) */ + + /* XXX workaround to have working console on mount prompt */ + /* Enable RX interrupt */ + bas = &sc->sc_bas; + if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) { + reg = uart_getreg(bas, UART_C2); + reg |= (UART_C2_RIE); + uart_setreg(bas, UART_C2, reg); + } + + return (0); +} + +static int +vf_uart_bus_transmit(struct uart_softc *sc) +{ + struct uart_bas *bas = &sc->sc_bas; + int i; + int reg; + + bas = &sc->sc_bas; + uart_lock(sc->sc_hwmtx); + + /* Fill TX FIFO */ + for (i = 0; i < sc->sc_txdatasz; i++) { + uart_setreg(bas, UART_D, sc->sc_txbuf[i] & 0xff); + uart_barrier(&sc->sc_bas); + } + + sc->sc_txbusy = 1; + + /* Call me when ready */ + reg = uart_getreg(bas, UART_C2); + reg |= (UART_C2_TIE); + uart_setreg(bas, UART_C2, reg); + + uart_unlock(sc->sc_hwmtx); + + return (0); +} diff --git a/sys/boot/fdt/dts/digi-ccwmx53.dts b/sys/boot/fdt/dts/digi-ccwmx53.dts index f89c0d0..898ffbb 100644 --- a/sys/boot/fdt/dts/digi-ccwmx53.dts +++ b/sys/boot/fdt/dts/digi-ccwmx53.dts @@ -101,6 +101,10 @@ }; }; aips@60000000 { + ethernet@63fec000 { + status = "okay"; + phy-mode = "rmii"; + }; i2c@63fc4000 { status = "okay"; }; diff --git a/sys/boot/fdt/dts/rk3188-radxa.dts b/sys/boot/fdt/dts/rk3188-radxa.dts new file mode 100644 index 0000000..7fc8ec5 --- /dev/null +++ b/sys/boot/fdt/dts/rk3188-radxa.dts @@ -0,0 +1,59 @@ +/*- + * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold@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 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$ + */ + +/dts-v1/; + +/include/ "rk3188.dtsi" + +/ { + model = "Radxa RadxaRock"; + + memory { + device_type = "memory"; + reg = < 0x60000000 0x80000000 >; /* 2GB RAM */ + }; + + aliases { + soc = &SOC; + }; + + SOC: rk3188 { + + uart2: serial@20064000 { + status = "okay"; + }; + + }; + + chosen { + bootargs = "-v"; + stdin = &uart2; + stdout = &uart2; + }; +}; + diff --git a/sys/boot/fdt/dts/rk3188.dtsi b/sys/boot/fdt/dts/rk3188.dtsi new file mode 100644 index 0000000..2efa678 --- /dev/null +++ b/sys/boot/fdt/dts/rk3188.dtsi @@ -0,0 +1,251 @@ +/*- + * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold@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 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$ + */ + +/ { + compatible = "rockchip,rk3188"; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + soc = &SOC; + }; + + SOC: rk3188 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges; + bus-frequency = <0>; + + GIC: interrupt-controller@1013d000 { + compatible = "arm,gic"; + reg = <0x1013d000 0x1000>, /* Distributor Registers */ + <0x1013c100 0x0100>; /* CPU Interface Registers */ + interrupt-controller; + #interrupt-cells = <1>; + }; + + pmu@20004000 { + compatible = "rockchip,rk30xx-pmu"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x20004000 0x100>; + }; + + grf@20008000 { + compatible = "rockchip,rk30xx-grf"; + #address-cells = <1>; + #size-cells = <1>; + reg = < 0x20008000 0x2000 >; + }; + + mp_tmr@1013c600 { + compatible = "arm,mpcore-timers"; + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = < 148500000 >; + reg = <0x1013c200 0x100>, /* Global Timer Regs */ + <0x1013c600 0x20>; /* Private Timer Regs */ + interrupts = < 27 29 >; + interrupt-parent = <&GIC>; + }; + + timer@20038000 { + compatible = "rockchip,rk30xx-timer"; + compatible = "rockchip,rk3188-dw-apb-timer-osc"; + reg = <0x20038000 0x20>; + interrupts = <76>; + clocks = <24000000>; + status = "disabled"; + }; + + timer@20038020 { + compatible = "rockchip,rk30xx-timer"; + reg = <0x20038020 0x20>; + interrupts = <77>; + clocks = <24000000>; + status = "disabled"; + }; + + timer@20038060 { + compatible = "rockchip,rk30xx-timer"; + reg = <0x20038060 0x20>; + interrupts = <91>; + clocks = <24000000>; + status = "disabled"; + }; + + timer@20038080 { + compatible = "rockchip,rk30xx-timer"; + reg = <0x20038080 0x20>; + interrupts = <92>; + clocks = <24000000>; + status = "disabled"; + }; + + timer@200380a0 { + compatible = "rockchip,rk30xx-timer"; + reg = <0x200380a0 0x20>; + interrupts = <96>; + clocks = <24000000>; + status = "disabled"; + }; + + watchdog@2004c000 { + compatible = "rockchip,rk30xx-wdt"; + reg = <0x2004c000 0x100>; + }; + + gpio0: gpio@2000a000 { + compatible = "rockchip,rk30xx-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x2000a000 0x100>; + interrupts = <86>; + interrupt-parent = <&GIC>; + }; + + gpio1: gpio@2003c000 { + compatible = "rockchip,rk30xx-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x2003c000 0x100>; + interrupts = <87>; + interrupt-parent = <&GIC>; + }; + + gpio2: gpio@2003e000 { + compatible = "rockchip,rk30xx-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x2003e000 0x100>; + interrupts = <88>; + interrupt-parent = <&GIC>; + }; + + gpio3: gpio@20080000 { + compatible = "rockchip,rk30xx-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x20080000 0x100>; + interrupts = <89>; + interrupt-parent = <&GIC>; + }; + + usb0: usb@10180000 { + compatible = "synopsys,designware-hs-otg2"; + reg = <0x10180000 0x40000>; + interrupts = <48>; + interrupt-parent = <&GIC>; + #address-cells = <1>; + #size-cells = <0>; + }; + + usb1: usb@101c0000 { + compatible = "synopsys,designware-hs-otg2"; + reg = <0x101c0000 0x40000>; + interrupts = < 49 >; + interrupt-parent = <&GIC>; + #address-cells = <1>; + #size-cells = <0>; + }; + + uart0: serial@10124000 { + compatible = "ns16550"; + reg = <0x10124000 0x400>; + reg-shift = <2>; + interrupts = <66>; + interrupt-parent = <&GIC>; + current-speed = <115200>; + clock-frequency = < 24000000 >; + busy-detect = <1>; + broken-txfifo = <1>; + status = "disabled"; + }; + + uart1: serial@10126000 { + compatible = "ns16550"; + reg = <0x10126000 0x400>; + reg-shift = <2>; + interrupts = <67>; + interrupt-parent = <&GIC>; + current-speed = <115200>; + clock-frequency = < 24000000 >; + busy-detect = <1>; + broken-txfifo = <1>; + status = "disabled"; + }; + + uart2: serial@20064000 { + compatible = "ns16550"; + reg = <0x20064000 0x400>; + reg-shift = <2>; + interrupts = <68>; + interrupt-parent = <&GIC>; + current-speed = <115200>; + clock-frequency = < 24000000 >; + busy-detect = <1>; + broken-txfifo = <1>; + status = "disabled"; + }; + + uart3: serial@20068000 { + compatible = "ns16550"; + reg = <0x20068000 0x400>; + reg-shift = <2>; + interrupts = <69>; + interrupt-parent = <&GIC>; + current-speed = <115200>; + clock-frequency = < 24000000 >; + busy-detect = <1>; + broken-txfifo = <1>; + status = "disabled"; + }; + + mmc@10214000 { + compatible = "rockchip,rk30xx-mmc"; + reg = <0x10214000 0x1000>; + interrupts = <55>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <24000000>; /* TODO: verify freq */ + status = "disabled"; + }; + + mmc@10218000 { + compatible = "rockchip,rk30xx-mmc"; + reg = <0x10218000 0x1000>; + interrupts = <56>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <24000000>; /* TODO: verify freq */ + status = "disabled"; + }; + }; +}; + diff --git a/sys/boot/fdt/dts/vybrid-cosmic.dts b/sys/boot/fdt/dts/vybrid-cosmic.dts new file mode 100644 index 0000000..79b49f7 --- /dev/null +++ b/sys/boot/fdt/dts/vybrid-cosmic.dts @@ -0,0 +1,56 @@ +/*- + * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.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 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$ + */ + +/dts-v1/; + +/include/ "vybrid.dtsi" + +/ { + model = "Cosmic Board"; + + memory { + device_type = "memory"; + reg = < 0x80000000 0x10000000 >; /* 256MB RAM */ + }; + + SOC: vybrid { + serial0: serial@40027000 { + status = "disabled"; + }; + + fec0: ethernet@400D0000 { + status = "disabled"; + }; + }; + + chosen { + bootargs = "-v"; + stdin = "serial1"; + stdout = "serial1"; + }; +}; diff --git a/sys/boot/fdt/dts/vybrid.dtsi b/sys/boot/fdt/dts/vybrid.dtsi new file mode 100644 index 0000000..004b1a1 --- /dev/null +++ b/sys/boot/fdt/dts/vybrid.dtsi @@ -0,0 +1,223 @@ +/*- + * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.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 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$ + */ + +/ { + model = "Freescale Vybrid Family"; + compatible = "freescale,vybrid", "fsl,vf"; + #address-cells = <1>; + #size-cells = <1>; + + interrupt-parent = <&GIC>; + + aliases { + soc = &SOC; + serial0 = &serial0; + serial1 = &serial1; + src = &SRC; + }; + + SOC: vybrid { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges; + bus-frequency = <0>; + + SRC: src@4006E000 { + compatible = "fsl,mvf600-src"; + reg = <0x4006E000 0x100>; + }; + + mscm@40001000 { + compatible = "fsl,mvf600-mscm"; + reg = <0x40001000 0x1000>; + }; + + GIC: interrupt-controller@01c81000 { + compatible = "arm,gic"; + reg = <0x40003000 0x1000>, /* Distributor Registers */ + <0x40002100 0x100>; /* CPU Interface Registers */ + interrupt-controller; + #interrupt-cells = <1>; + }; + + anadig@40050000 { + compatible = "fsl,mvf600-anadig"; + reg = <0x40050000 0x300>; + }; + + ccm@4006b000 { + compatible = "fsl,mvf600-ccm"; + reg = <0x4006b000 0x1000>; + }; + + mp_tmr@40002100 { + compatible = "arm,mpcore-timers"; + clock-frequency = <133000000>; + #address-cells = <1>; + #size-cells = <0>; + reg = < 0x40002200 0x100 >, /* Global Timer Registers */ + < 0x40002600 0x100 >; /* Private Timer Registers */ + interrupts = < 27 29 >; + interrupt-parent = < &GIC >; + }; + + pit@40037000 { + compatible = "fsl,mvf600-pit"; + reg = <0x40037000 0x1000>; + interrupts = < 71 >; + interrupt-parent = <&GIC>; + clock-frequency = < 24000000 >; + }; + + lptmr@40040000 { + compatible = "fsl,mvf600-lptmr"; + reg = <0x40040000 0x1000>; + interrupts = < 72 >; + interrupt-parent = <&GIC>; + clock-frequency = < 24000000 >; + }; + + iomuxc@40048000 { + compatible = "fsl,mvf600-iomuxc"; + reg = <0x40048000 0x1000>; + }; + + gpio@400FF000 { + compatible = "fsl,mvf600-gpio"; + reg = <0x400FF000 0x200>; + #gpio-cells = <3>; + gpio-controller; + interrupts = < 139 140 141 142 143 >; + interrupt-parent = <&GIC>; + + }; + + nand@400E0000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "fsl,mvf600-nand"; + reg = <0x400E0000 0x10000>; + interrupts = < 115 >; + interrupt-parent = <&GIC>; + + partition@40000 { + reg = <0x40000 0x200000>; /* 2MB */ + label = "u-boot"; + read-only; + }; + + partition@240000 { + reg = <0x240000 0x200000>; /* 2MB */ + label = "test"; + }; + + partition@440000 { + reg = <0x440000 0xa00000>; /* 10MB */ + label = "kernel"; + }; + + partition@e40000 { + reg = <0xe40000 0x1e000000>; /* 480MB */ + label = "root"; + }; + + }; + + sdhci0: sdhci@400B1000 { + compatible = "fsl,mvf600-sdhci"; + reg = <0x400B1000 0x1000>; + interrupts = < 59 >; + interrupt-parent = <&GIC>; + clock-frequency = <50000000>; + }; + + sdhci1: sdhci@400B2000 { + compatible = "fsl,mvf600-sdhci"; + reg = <0x400B2000 0x1000>; + interrupts = < 60 >; + interrupt-parent = <&GIC>; + clock-frequency = <50000000>; + }; + + serial0: serial@40027000 { + compatible = "fsl,mvf600-uart"; + reg = <0x40027000 0x1000>; + interrupts = <93>; + interrupt-parent = <&GIC>; + current-speed = <115200>; + clock-frequency = < 24000000 >; + }; + + serial1: serial@40028000 { + compatible = "fsl,mvf600-uart"; + reg = <0x40028000 0x1000>; + interrupts = <94>; + interrupt-parent = <&GIC>; + current-speed = <115200>; + clock-frequency = < 24000000 >; + }; + + usb@40034000 { + compatible = "fsl,mvf600-usb-ehci", "usb-ehci"; + reg = < 0x40034000 0x1000 >, /* ehci */ + < 0x40035000 0x1000 >, /* usbc */ + < 0x40050800 0x100 >; /* phy */ + interrupts = < 107 >; + interrupt-parent = <&GIC>; + }; + + usb@400b4000 { + compatible = "fsl,mvf600-usb-ehci", "usb-ehci"; + reg = < 0x400b4000 0x1000 >, /* ehci */ + < 0x400b5000 0x1000 >, /* usbc */ + < 0x40050C00 0x100 >; /* phy */ + interrupts = < 108 >; + interrupt-parent = <&GIC>; + }; + + fec0: ethernet@400D0000 { + compatible = "fsl,mvf600-fec"; + reg = <0x400D0000 0x1000>; + interrupts = < 110 >; + interrupt-parent = <&GIC>; + phy-mode = "rmii"; + phy-disable-preamble; + }; + + fec1: ethernet@400D1000 { + compatible = "fsl,mvf600-fec"; + reg = <0x400D1000 0x1000>; + interrupts = < 111 >; + interrupt-parent = <&GIC>; + phy-mode = "rmii"; + phy-disable-preamble; + }; + + }; +}; diff --git a/sys/dev/uart/uart.h b/sys/dev/uart/uart.h index 095d368..4874488 100644 --- a/sys/dev/uart/uart.h +++ b/sys/dev/uart/uart.h @@ -75,6 +75,7 @@ extern struct uart_class uart_lpc_class __attribute__((weak)); extern struct uart_class uart_pl011_class __attribute__((weak)); extern struct uart_class uart_cdnc_class __attribute__((weak)); extern struct uart_class uart_ti8250_class __attribute__((weak)); +extern struct uart_class uart_vybrid_class __attribute__((weak)); #ifdef FDT struct ofw_compat_data; diff --git a/sys/dev/uart/uart_bus_fdt.c b/sys/dev/uart/uart_bus_fdt.c index 5a0ebd7..a98c50a 100644 --- a/sys/dev/uart/uart_bus_fdt.c +++ b/sys/dev/uart/uart_bus_fdt.c @@ -80,6 +80,7 @@ static struct ofw_compat_data compat_data[] = { {"fsl,imx27-uart", (uintptr_t)&uart_imx_class}, {"fsl,imx25-uart", (uintptr_t)&uart_imx_class}, {"fsl,imx21-uart", (uintptr_t)&uart_imx_class}, + {"fsl,mvf600-uart", (uintptr_t)&uart_vybrid_class}, {"lpc,uart", (uintptr_t)&uart_lpc_class}, {"ti,ns16550", (uintptr_t)&uart_ti8250_class}, {"ns16550", (uintptr_t)&uart_ns8250_class}, diff --git a/sys/arm/broadcom/bcm2835/dwc_otg_brcm.c b/sys/dev/usb/controller/dwc_otg_fdt.c index ac7a18d..ac7a18d 100644 --- a/sys/arm/broadcom/bcm2835/dwc_otg_brcm.c +++ b/sys/dev/usb/controller/dwc_otg_fdt.c |