Add support for Freescale Vybrid Family VF600 heterogeneous
ARM Cortex-A5/M4 SoC (M4 core is not used in this work). Support includes device drivers for: - NAND Flash Controller (NFC) - USB Enhanced Host Controller Interface (EHCI) - General-Purpose Input/Output (GPIO) - Universal Asynchronous Receiver/Transmitter (UART) Also supported: - Generic Interrupt Controller (GIC) - MPCore timer - ffec ethernet driver Reviewed by: ray Approved by: cognet (mentor)
This commit is contained in:
parent
63b9ae948d
commit
5c263f43ef
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=258057
139
sys/arm/conf/COSMIC
Normal file
139
sys/arm/conf/COSMIC
Normal file
@ -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
|
28
sys/arm/freescale/vybrid/files.vybrid
Normal file
28
sys/arm/freescale/vybrid/files.vybrid
Normal file
@ -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
|
20
sys/arm/freescale/vybrid/std.vybrid
Normal file
20
sys/arm/freescale/vybrid/std.vybrid
Normal file
@ -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"
|
214
sys/arm/freescale/vybrid/vf_anadig.c
Normal file
214
sys/arm/freescale/vybrid/vf_anadig.c
Normal file
@ -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);
|
188
sys/arm/freescale/vybrid/vf_ccm.c
Normal file
188
sys/arm/freescale/vybrid/vf_ccm.c
Normal file
@ -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);
|
86
sys/arm/freescale/vybrid/vf_common.c
Normal file
86
sys/arm/freescale/vybrid/vf_common.c
Normal file
@ -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
|
||||
};
|
40
sys/arm/freescale/vybrid/vf_common.h
Normal file
40
sys/arm/freescale/vybrid/vf_common.h
Normal file
@ -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)
|
416
sys/arm/freescale/vybrid/vf_ehci.c
Normal file
416
sys/arm/freescale/vybrid/vf_ehci.c
Normal file
@ -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);
|
||||
}
|
403
sys/arm/freescale/vybrid/vf_gpio.c
Normal file
403
sys/arm/freescale/vybrid/vf_gpio.c
Normal file
@ -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);
|
171
sys/arm/freescale/vybrid/vf_iomuxc.c
Normal file
171
sys/arm/freescale/vybrid/vf_iomuxc.c
Normal file
@ -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);
|
165
sys/arm/freescale/vybrid/vf_iomuxc.h
Normal file
165
sys/arm/freescale/vybrid/vf_iomuxc.h
Normal file
@ -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 */
|
93
sys/arm/freescale/vybrid/vf_machdep.c
Normal file
93
sys/arm/freescale/vybrid/vf_machdep.c
Normal file
@ -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);
|
||||
}
|
123
sys/arm/freescale/vybrid/vf_mscm.c
Normal file
123
sys/arm/freescale/vybrid/vf_mscm.c
Normal file
@ -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);
|
524
sys/arm/freescale/vybrid/vf_nfc.c
Normal file
524
sys/arm/freescale/vybrid/vf_nfc.c
Normal file
@ -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 */
|
||||
}
|
147
sys/arm/freescale/vybrid/vf_src.c
Normal file
147
sys/arm/freescale/vybrid/vf_src.c
Normal file
@ -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);
|
30
sys/arm/freescale/vybrid/vf_src.h
Normal file
30
sys/arm/freescale/vybrid/vf_src.h
Normal file
@ -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);
|
509
sys/arm/freescale/vybrid/vf_uart.c
Normal file
509
sys/arm/freescale/vybrid/vf_uart.c
Normal file
@ -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);
|
||||
}
|
56
sys/boot/fdt/dts/vybrid-cosmic.dts
Normal file
56
sys/boot/fdt/dts/vybrid-cosmic.dts
Normal file
@ -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";
|
||||
};
|
||||
};
|
223
sys/boot/fdt/dts/vybrid.dtsi
Normal file
223
sys/boot/fdt/dts/vybrid.dtsi
Normal file
@ -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;
|
||||
};
|
||||
|
||||
};
|
||||
};
|
@ -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;
|
||||
|
@ -81,6 +81,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},
|
||||
|
Loading…
Reference in New Issue
Block a user