diff options
Diffstat (limited to 'sys')
35 files changed, 8732 insertions, 0 deletions
diff --git a/sys/arm/conf/EFIKA_MX b/sys/arm/conf/EFIKA_MX new file mode 100644 index 0000000..75e2943 --- /dev/null +++ b/sys/arm/conf/EFIKA_MX @@ -0,0 +1,177 @@ +# Kernel configuration for Efika MX Smarttop/Smartbook boards +# +# 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 EFIKA_MX + +include "../freescale/imx/std.imx" + +makeoptions WITHOUT_MODULES="ahc" + +makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols +#options DEBUG + +options SCHED_4BSD # 4BSD scheduler +#options PREEMPTION # Enable kernel thread preemption +options INET # InterNETworking +#options INET6 # IPv6 communications protocols +#options SCTP # Stream Control Transmission Protocol +options FFS # Berkeley Fast Filesystem +options SOFTUPDATES # Enable FFS soft updates support +options UFS_ACL # Support for access control lists +options UFS_DIRHASH # Improve performance on big directories +options UFS_GJOURNAL # Enable gjournal-based UFS journaling +#options MD_ROOT # MD is a potential root device +options NFSCL # New Network Filesystem Client +#options NFSD # New Network Filesystem Server +options NFSLOCKD # Network Lock Manager +options NFS_ROOT # NFS usable as /, requires NFSCL +options MSDOSFS # MSDOS Filesystem +options CD9660 # ISO 9660 Filesystem +#options PROCFS # Process filesystem (requires PSEUDOFS) +options PSEUDOFS # Pseudo-filesystem framework +options TMPFS # TMP Memory Filesystem +options GEOM_PART_GPT # GUID Partition Tables. +options GEOM_LABEL # Provides labelization +#options COMPAT_FREEBSD5 # Compatible with FreeBSD5 +#options COMPAT_FREEBSD6 # Compatible with FreeBSD6 +#options COMPAT_FREEBSD7 # Compatible with FreeBSD7 +options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI +options KTRACE # ktrace(1) support +options SYSVSHM # SYSV-style shared memory +options SYSVMSG # SYSV-style message queues +options SYSVSEM # SYSV-style semaphores +options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions +options INCLUDE_CONFIG_FILE # Include this file in kernel + +# required for netbooting +#options BOOTP +#options BOOTP_COMPAT +#options BOOTP_NFSROOT +#options BOOTP_NFSV3 +#options BOOTP_WIRED_TO=ue0 +# +options ROOTDEVNAME=\"ufs:ada0s2a\" + + +# kernel/memory size reduction +#options MUTEX_NOINLINE +#options NO_FFS_SNAPSHOT +#options NO_SWAPPING +#options NO_SYSCTL_DESCR +#options RWLOCK_NOINLINE + +# Debugging support. Always need this: +options KDB # Enable kernel debugger support. +# For minimum debugger support (stable branch) use: +#options KDB_TRACE # Print a stack trace for a panic. +# For full debugger support use this instead: +options DDB # Support DDB. +#options GDB # Support remote GDB. +options DEADLKRES # Enable the deadlock resolver +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 + +# The `bpf' device enables the Berkeley Packet Filter. +# Be aware of the administrative consequences of enabling this! +# Note that 'bpf' is required for DHCP. +device bpf # Berkeley packet filter + +# Pseudo devices. +device loop # Network loopback +device random # Entropy device +device ether # Ethernet support +#device vlan # 802.1Q VLAN support +#device tun # Packet tunnel. +#device md # Memory "disks" +#device gif # IPv6 and IPv4 tunneling +#device faith # IPv6-to-IPv4 relaying (translation) +#device firmware # firmware assist module + +# Serial (COM) ports +device uart # Multi-uart driver +options ALT_BREAK_TO_DEBUGGER + +device ata +device atapci # Only for helper functions +device imxata +options ATA_CAM +options ATA_STATIC_ID # Static device numbering + +device iomux # IO Multiplexor + +device gpio +device gpioled + +device fsliic +device iic +device iicbus + +# SCSI peripherals +device scbus # SCSI bus (required for SCSI) +device da # Direct Access (disks) +device cd # CD +device pass # Passthrough device (direct SCSI access) + +# USB support +#options USB_DEBUG # enable debug msgs +device ehci # OHCI USB interface +device usb # USB Bus (required) +device umass # Disks/Mass storage - Requires scbus and da +device uhid # "Human Interface Devices" +device u3g + +# USB Ethernet, requires miibus +device miibus +device aue # ADMtek USB Ethernet +device axe # ASIX Electronics USB Ethernet +device cdce # Generic USB over Ethernet +device cue # CATC USB Ethernet +device kue # Kawasaki LSI USB Ethernet +device rue # RealTek RTL8150 USB Ethernet +device udav # Davicom DM9601E USB + +# USB Wireless +device rum # Ralink Technology RT2501USB wireless NICs + +# Watchdog timer. +# WARNING: can't be disabled!!! +device imxwdt # Watchdog + +# Wireless NIC cards +device wlan # 802.11 support +device wlan_wep # 802.11 WEP support +device wlan_ccmp # 802.11 CCMP support +device wlan_tkip # 802.11 TKIP support +device wlan_amrr # AMRR transmit rate control algorithm + +# Flattened Device Tree +options FDT +options FDT_DTB_STATIC +makeoptions FDT_DTS_FILE=efikamx.dts + +# NOTE: serial console will be disabled if syscons enabled +# Uncomment following lines for framebuffer/syscons support +device sc +device kbdmux +options SC_DFLT_FONT # compile font in +makeoptions SC_DFLT_FONT=cp437 +device ukbd # Allow keyboard like HIDs to control console + +device ums diff --git a/sys/arm/freescale/imx/bus_space.c b/sys/arm/freescale/imx/bus_space.c new file mode 100644 index 0000000..6d92f45 --- /dev/null +++ b/sys/arm/freescale/imx/bus_space.c @@ -0,0 +1,130 @@ +/*- + * Copyright (C) 2012 FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Oleksandr Tymoshenko under sponsorship + * from the FreeBSD Foundation. + * Portions of this software were developed by Oleksandr Rybalko + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of MARVELL nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/malloc.h> + +#include <machine/bus.h> + +/* Prototypes for all the bus_space structure functions */ +bs_protos(generic); +bs_protos(generic_armv4); + +struct bus_space _base_tag = { + /* cookie */ + .bs_cookie = (void *) 0, + + /* mapping/unmapping */ + .bs_map = generic_bs_map, + .bs_unmap = generic_bs_unmap, + .bs_subregion = generic_bs_subregion, + + /* allocation/deallocation */ + .bs_alloc = generic_bs_alloc, + .bs_free = generic_bs_free, + + /* barrier */ + .bs_barrier = generic_bs_barrier, + + /* read (single) */ + .bs_r_1 = generic_bs_r_1, + .bs_r_2 = generic_armv4_bs_r_2, + .bs_r_4 = generic_bs_r_4, + .bs_r_8 = NULL, + + /* read multiple */ + .bs_rm_1 = generic_bs_rm_1, + .bs_rm_2 = generic_armv4_bs_rm_2, + .bs_rm_4 = generic_bs_rm_4, + .bs_rm_8 = NULL, + + /* read region */ + .bs_rr_1 = generic_bs_rr_1, + .bs_rr_2 = generic_armv4_bs_rr_2, + .bs_rr_4 = generic_bs_rr_4, + .bs_rr_8 = NULL, + + /* write (single) */ + .bs_w_1 = generic_bs_w_1, + .bs_w_2 = generic_armv4_bs_w_2, + .bs_w_4 = generic_bs_w_4, + .bs_w_8 = NULL, + + /* write multiple */ + .bs_wm_1 = generic_bs_wm_1, + .bs_wm_2 = generic_armv4_bs_wm_2, + .bs_wm_4 = generic_bs_wm_4, + .bs_wm_8 = NULL, + + /* write region */ + .bs_wr_1 = generic_bs_wr_1, + .bs_wr_2 = generic_armv4_bs_wr_2, + .bs_wr_4 = generic_bs_wr_4, + .bs_wr_8 = NULL, + + /* read multiple stream */ + .bs_rm_1_s = generic_bs_rm_1, + .bs_rm_2_s = generic_armv4_bs_rm_2, + .bs_rm_4_s = generic_bs_rm_4, + .bs_rm_8_s = NULL, + + /* write multiple stream */ + .bs_wm_1_s = generic_bs_wm_1, + .bs_wm_2_s = generic_armv4_bs_wm_2, + .bs_wm_4_s = generic_bs_wm_4, + .bs_wm_8_s = NULL, + + /* set multiple */ + /* XXX not implemented */ + + /* set region */ + .bs_sr_1 = NULL, + .bs_sr_2 = generic_armv4_bs_sr_2, + .bs_sr_4 = generic_bs_sr_4, + .bs_sr_8 = NULL, + + /* copy */ + .bs_c_1 = NULL, + .bs_c_2 = generic_armv4_bs_c_2, + .bs_c_4 = NULL, + .bs_c_8 = NULL, +}; + +bus_space_tag_t fdtbus_bs_tag = &_base_tag; diff --git a/sys/arm/freescale/imx/common.c b/sys/arm/freescale/imx/common.c new file mode 100644 index 0000000..cf0f974 --- /dev/null +++ b/sys/arm/freescale/imx/common.c @@ -0,0 +1,75 @@ +/*- + * Copyright (C) 2008-2011 MARVELL INTERNATIONAL LTD. + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * Developed by Semihalf. + * + * Portions of this software were developed by Oleksandr Rybalko + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of MARVELL nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "opt_global.h" + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/kdb.h> +#include <sys/reboot.h> + +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/openfirm.h> + +#include <machine/bus.h> +#include <machine/fdt.h> +#include <machine/vmparam.h> + +struct fdt_fixup_entry fdt_fixup_table[] = { + { NULL, NULL } +}; + +static int +fdt_intc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, + int *pol) +{ + + *interrupt = fdt32_to_cpu(intr[0]); + *trig = INTR_TRIGGER_CONFORM; + *pol = INTR_POLARITY_CONFORM; + + return (0); +} + +fdt_pic_decode_t fdt_pic_table[] = { + &fdt_intc_decode_ic, + NULL +}; diff --git a/sys/arm/freescale/imx/console.c b/sys/arm/freescale/imx/console.c new file mode 100644 index 0000000..c1b7dee --- /dev/null +++ b/sys/arm/freescale/imx/console.c @@ -0,0 +1,164 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Oleksandr Rybalko under sponsorship + * from the FreeBSD Foundation. + * + * 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. + */ + +/* Simple UART console driver for Freescale i.MX515 */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/cons.h> +#include <sys/consio.h> +#include <sys/kernel.h> + +/* Allow it to be predefined, to be able to use another UART for console */ +#ifndef IMX_UART_BASE +#define IMX_UART_BASE 0xe3fbc000 /* UART1 */ +#endif + +#define IMX_RXD (u_int32_t *)(IMX_UART_BASE + 0x00) +#define IMX_TXD (u_int32_t *)(IMX_UART_BASE + 0x40) + +#define IMX_UFCR (u_int32_t *)(IMX_UART_BASE + 0x90) +#define IMX_USR1 (u_int32_t *)(IMX_UART_BASE + 0x94) +#define IMX_USR1_TRDY (1 << 13) + +#define IMX_USR2 (u_int32_t *)(IMX_UART_BASE + 0x98) +#define IMX_USR2_RDR (1 << 0) +#define IMX_USR2_TXFE (1 << 14) +#define IMX_USR2_TXDC (1 << 3) + +#define IMX_UTS (u_int32_t *)(IMX_UART_BASE + 0xb4) +#define IMX_UTS_TXFULL (1 << 4) + +/* + * uart related funcs + */ +static u_int32_t +uart_getreg(u_int32_t *bas) +{ + + return *((volatile u_int32_t *)(bas)) & 0xff; +} + +static void +uart_setreg(u_int32_t *bas, u_int32_t val) +{ + + *((volatile u_int32_t *)(bas)) = (u_int32_t)val; +} + +static int +ub_tstc(void) +{ + + return ((uart_getreg(IMX_USR2) & IMX_USR2_RDR) ? 1 : 0); +} + +static int +ub_getc(void) +{ + + while (!ub_tstc()); + __asm __volatile("nop"); + + return (uart_getreg(IMX_RXD) & 0xff); +} + +static void +ub_putc(unsigned char c) +{ + + if (c == '\n') + ub_putc('\r'); + + while (uart_getreg(IMX_UTS) & IMX_UTS_TXFULL) + __asm __volatile("nop"); + + uart_setreg(IMX_TXD, c); +} + +static cn_probe_t uart_cnprobe; +static cn_init_t uart_cninit; +static cn_term_t uart_cnterm; +static cn_getc_t uart_cngetc; +static cn_putc_t uart_cnputc; +static cn_grab_t uart_cngrab; +static cn_ungrab_t uart_cnungrab; + +static void +uart_cngrab(struct consdev *cp) +{ + +} + +static void +uart_cnungrab(struct consdev *cp) +{ + +} + + +static void +uart_cnprobe(struct consdev *cp) +{ + + sprintf(cp->cn_name, "uart"); + cp->cn_pri = CN_NORMAL; +} + +static void +uart_cninit(struct consdev *cp) +{ + uart_setreg(IMX_UFCR, 0x00004210); +} + +void +uart_cnputc(struct consdev *cp, int c) +{ + + ub_putc(c); +} + +int +uart_cngetc(struct consdev * cp) +{ + + return ub_getc(); +} + +static void +uart_cnterm(struct consdev * cp) +{ + +} + +CONSOLE_DRIVER(uart); diff --git a/sys/arm/freescale/imx/i2c.c b/sys/arm/freescale/imx/i2c.c new file mode 100644 index 0000000..91e2083 --- /dev/null +++ b/sys/arm/freescale/imx/i2c.c @@ -0,0 +1,492 @@ +/*- + * Copyright (C) 2008-2009 Semihalf, Michal Hajduk + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by Oleksandr Rybalko + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#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/resource.h> + +#include <machine/bus.h> +#include <machine/resource.h> +#include <sys/rman.h> + +#include <sys/lock.h> +#include <sys/mutex.h> + +#include <dev/iicbus/iiconf.h> +#include <dev/iicbus/iicbus.h> +#include "iicbus_if.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> + +#define I2C_ADDR_REG 0x00 /* I2C slave address register */ +#define I2C_FDR_REG 0x04 /* I2C frequency divider register */ +#define I2C_CONTROL_REG 0x08 /* I2C control register */ +#define I2C_STATUS_REG 0x0C /* I2C status register */ +#define I2C_DATA_REG 0x10 /* I2C data register */ +#define I2C_DFSRR_REG 0x14 /* I2C Digital Filter Sampling rate */ + +#define I2CCR_MEN (1 << 7) /* Module enable */ +#define I2CCR_MSTA (1 << 5) /* Master/slave mode */ +#define I2CCR_MTX (1 << 4) /* Transmit/receive mode */ +#define I2CCR_TXAK (1 << 3) /* Transfer acknowledge */ +#define I2CCR_RSTA (1 << 2) /* Repeated START */ + +#define I2CSR_MCF (1 << 7) /* Data transfer */ +#define I2CSR_MASS (1 << 6) /* Addressed as a slave */ +#define I2CSR_MBB (1 << 5) /* Bus busy */ +#define I2CSR_MAL (1 << 4) /* Arbitration lost */ +#define I2CSR_SRW (1 << 2) /* Slave read/write */ +#define I2CSR_MIF (1 << 1) /* Module interrupt */ +#define I2CSR_RXAK (1 << 0) /* Received acknowledge */ + +#define I2C_BAUD_RATE_FAST 0x31 +#define I2C_BAUD_RATE_DEF 0x3F +#define I2C_DFSSR_DIV 0x10 + +#ifdef DEBUG +#define debugf(fmt, args...) do { printf("%s(): ", __func__); \ + printf(fmt,##args); } while (0) +#else +#define debugf(fmt, args...) +#endif + +struct i2c_softc { + device_t dev; + device_t iicbus; + struct resource *res; + struct mtx mutex; + int rid; + bus_space_handle_t bsh; + bus_space_tag_t bst; +}; + +static phandle_t i2c_get_node(device_t, device_t); +static int i2c_probe(device_t); +static int i2c_attach(device_t); + +static int i2c_repeated_start(device_t, u_char, int); +static int i2c_start(device_t, u_char, int); +static int i2c_stop(device_t); +static int i2c_reset(device_t, u_char, u_char, u_char *); +static int i2c_read(device_t, char *, int, int *, int, int); +static int i2c_write(device_t, const char *, int, int *, int); + +static device_method_t i2c_methods[] = { + DEVMETHOD(device_probe, i2c_probe), + DEVMETHOD(device_attach, i2c_attach), + + /* OFW methods */ + DEVMETHOD(ofw_bus_get_node, i2c_get_node), + + DEVMETHOD(iicbus_callback, iicbus_null_callback), + DEVMETHOD(iicbus_repeated_start, i2c_repeated_start), + DEVMETHOD(iicbus_start, i2c_start), + DEVMETHOD(iicbus_stop, i2c_stop), + DEVMETHOD(iicbus_reset, i2c_reset), + DEVMETHOD(iicbus_read, i2c_read), + DEVMETHOD(iicbus_write, i2c_write), + DEVMETHOD(iicbus_transfer, iicbus_transfer_gen), + + { 0, 0 } +}; + +static driver_t i2c_driver = { + "iichb", + i2c_methods, + sizeof(struct i2c_softc), +}; +static devclass_t i2c_devclass; + +DRIVER_MODULE(i2c, simplebus, i2c_driver, i2c_devclass, 0, 0); +DRIVER_MODULE(iicbus, i2c, iicbus_driver, iicbus_devclass, 0, 0); + +static phandle_t +i2c_get_node(device_t bus, device_t dev) +{ + /* + * Share controller node with iicbus device + */ + return ofw_bus_get_node(bus); +} + +static __inline void +i2c_write_reg(struct i2c_softc *sc, bus_size_t off, uint8_t val) +{ + + bus_space_write_1(sc->bst, sc->bsh, off, val); +} + +static __inline uint8_t +i2c_read_reg(struct i2c_softc *sc, bus_size_t off) +{ + + return (bus_space_read_1(sc->bst, sc->bsh, off)); +} + +static __inline void +i2c_flag_set(struct i2c_softc *sc, bus_size_t off, uint8_t mask) +{ + uint8_t status; + + status = i2c_read_reg(sc, off); + status |= mask; + i2c_write_reg(sc, off, status); +} + +/* Wait for transfer interrupt flag */ +static int +wait_for_iif(struct i2c_softc *sc) +{ + int retry; + + retry = 1000; + while (retry --) { + if (i2c_read_reg(sc, I2C_STATUS_REG) & I2CSR_MIF) + return (IIC_NOERR); + DELAY(10); + } + + return (IIC_ETIMEOUT); +} + +/* Wait for free bus */ +static int +wait_for_nibb(struct i2c_softc *sc) +{ + int retry; + + retry = 1000; + while (retry --) { + if ((i2c_read_reg(sc, I2C_STATUS_REG) & I2CSR_MBB) == 0) + return (IIC_NOERR); + DELAY(10); + } + + return (IIC_ETIMEOUT); +} + +/* Wait for transfer complete+interrupt flag */ +static int +wait_for_icf(struct i2c_softc *sc) +{ + int retry; + + retry = 1000; + while (retry --) { + + if ((i2c_read_reg(sc, I2C_STATUS_REG) & + (I2CSR_MCF|I2CSR_MIF)) == (I2CSR_MCF|I2CSR_MIF)) + return (IIC_NOERR); + DELAY(10); + } + + return (IIC_ETIMEOUT); +} + +static int +i2c_probe(device_t dev) +{ + struct i2c_softc *sc; + + if (!ofw_bus_is_compatible(dev, "fsl,imx-i2c")) + return (ENXIO); + + sc = device_get_softc(dev); + sc->rid = 0; + + sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid, + RF_ACTIVE); + if (sc->res == NULL) { + device_printf(dev, "could not allocate resources\n"); + return (ENXIO); + } + + sc->bst = rman_get_bustag(sc->res); + sc->bsh = rman_get_bushandle(sc->res); + + /* Enable I2C */ + i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN); + bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->res); + device_set_desc(dev, "I2C bus controller"); + + return (BUS_PROBE_DEFAULT); +} + +static int +i2c_attach(device_t dev) +{ + struct i2c_softc *sc; + + sc = device_get_softc(dev); + sc->dev = dev; + sc->rid = 0; + + mtx_init(&sc->mutex, device_get_nameunit(dev), "I2C", MTX_DEF); + + sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid, + RF_ACTIVE); + if (sc->res == NULL) { + device_printf(dev, "could not allocate resources"); + mtx_destroy(&sc->mutex); + return (ENXIO); + } + + sc->bst = rman_get_bustag(sc->res); + sc->bsh = rman_get_bushandle(sc->res); + + sc->iicbus = device_add_child(dev, "iicbus", -1); + if (sc->iicbus == NULL) { + device_printf(dev, "could not add iicbus child"); + mtx_destroy(&sc->mutex); + return (ENXIO); + } + + bus_generic_attach(dev); + return (IIC_NOERR); +} + +static int +i2c_repeated_start(device_t dev, u_char slave, int timeout) +{ + struct i2c_softc *sc; + int error; + + sc = device_get_softc(dev); + + mtx_lock(&sc->mutex); + + i2c_write_reg(sc, I2C_ADDR_REG, slave); + if ((i2c_read_reg(sc, I2C_STATUS_REG) & I2CSR_MBB) == 0) { + mtx_unlock(&sc->mutex); + return (IIC_EBUSBSY); + } + + /* Set repeated start condition */ + DELAY(10); + i2c_flag_set(sc, I2C_CONTROL_REG, I2CCR_RSTA); + DELAY(10); + /* Clear status */ + i2c_write_reg(sc, I2C_STATUS_REG, 0x0); + /* Write target address - LSB is R/W bit */ + i2c_write_reg(sc, I2C_DATA_REG, slave); + + error = wait_for_iif(sc); + + /* Clear status */ + i2c_write_reg(sc, I2C_STATUS_REG, 0x0); + + mtx_unlock(&sc->mutex); + + if (error) + return (error); + + return (IIC_NOERR); +} + +static int +i2c_start(device_t dev, u_char slave, int timeout) +{ + struct i2c_softc *sc; + int error; + + sc = device_get_softc(dev); + + mtx_lock(&sc->mutex); + i2c_write_reg(sc, I2C_ADDR_REG, slave); + if (i2c_read_reg(sc, I2C_STATUS_REG) & I2CSR_MBB) { + mtx_unlock(&sc->mutex); + return (IIC_EBUSBSY); + } + + /* Set start condition */ + i2c_write_reg(sc, I2C_CONTROL_REG, + I2CCR_MEN | I2CCR_MSTA | I2CCR_TXAK); + DELAY(100); + i2c_write_reg(sc, I2C_CONTROL_REG, + I2CCR_MEN | I2CCR_MSTA | I2CCR_MTX | I2CCR_TXAK); + /* Clear status */ + i2c_write_reg(sc, I2C_STATUS_REG, 0x0); + /* Write target address - LSB is R/W bit */ + i2c_write_reg(sc, I2C_DATA_REG, slave); + + error = wait_for_iif(sc); + + mtx_unlock(&sc->mutex); + if (error) + return (error); + + return (IIC_NOERR); +} + + +static int +i2c_stop(device_t dev) +{ + struct i2c_softc *sc; + + sc = device_get_softc(dev); + mtx_lock(&sc->mutex); + i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | I2CCR_TXAK); + DELAY(100); + /* Reset controller if bus still busy after STOP */ + if (wait_for_nibb(sc) == IIC_ETIMEOUT) { + i2c_write_reg(sc, I2C_CONTROL_REG, 0); + DELAY(1000); + i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | I2CCR_TXAK); + + i2c_write_reg(sc, I2C_STATUS_REG, 0x0); + } + mtx_unlock(&sc->mutex); + + return (IIC_NOERR); +} + +static int +i2c_reset(device_t dev, u_char speed, u_char addr, u_char *oldadr) +{ + struct i2c_softc *sc; + uint8_t baud_rate; + + sc = device_get_softc(dev); + + switch (speed) { + case IIC_FAST: + baud_rate = I2C_BAUD_RATE_FAST; + break; + case IIC_SLOW: + case IIC_UNKNOWN: + case IIC_FASTEST: + default: + baud_rate = I2C_BAUD_RATE_DEF; + break; + } + + mtx_lock(&sc->mutex); + i2c_write_reg(sc, I2C_CONTROL_REG, 0x0); + i2c_write_reg(sc, I2C_STATUS_REG, 0x0); + DELAY(1000); + + i2c_write_reg(sc, I2C_FDR_REG, 20); + i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN); + DELAY(1000); + i2c_write_reg(sc, I2C_STATUS_REG, 0x0); + mtx_unlock(&sc->mutex); + + return (IIC_NOERR); +} + +static int +i2c_read(device_t dev, char *buf, int len, int *read, int last, int delay) +{ + struct i2c_softc *sc; + int error, reg; + + sc = device_get_softc(dev); + *read = 0; + + mtx_lock(&sc->mutex); + + if (len) { + if (len == 1) + i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | + I2CCR_MSTA | I2CCR_TXAK); + + else + i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | + I2CCR_MSTA); + + /* dummy read */ + i2c_read_reg(sc, I2C_DATA_REG); + DELAY(1000); + } + + while (*read < len) { + error = wait_for_icf(sc); + if (error) { + mtx_unlock(&sc->mutex); + return (error); + } + i2c_write_reg(sc, I2C_STATUS_REG, 0x0); + if ((*read == len - 2) && last) { + /* NO ACK on last byte */ + i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | + I2CCR_MSTA | I2CCR_TXAK); + } + + if ((*read == len - 1) && last) { + /* Transfer done, remove master bit */ + i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | + I2CCR_TXAK); + } + + reg = i2c_read_reg(sc, I2C_DATA_REG); + *buf++ = reg; + (*read)++; + } + mtx_unlock(&sc->mutex); + + return (IIC_NOERR); +} + +static int +i2c_write(device_t dev, const char *buf, int len, int *sent, int timeout) +{ + struct i2c_softc *sc; + int error; + + sc = device_get_softc(dev); + *sent = 0; + + mtx_lock(&sc->mutex); + while (*sent < len) { + i2c_write_reg(sc, I2C_STATUS_REG, 0x0); + i2c_write_reg(sc, I2C_DATA_REG, *buf++); + + error = wait_for_iif(sc); + if (error) { + mtx_unlock(&sc->mutex); + return (error); + } + + (*sent)++; + } + mtx_unlock(&sc->mutex); + + return (IIC_NOERR); +} diff --git a/sys/arm/freescale/imx/imx.files b/sys/arm/freescale/imx/imx.files new file mode 100644 index 0000000..dd2a975 --- /dev/null +++ b/sys/arm/freescale/imx/imx.files @@ -0,0 +1,51 @@ +# $FreeBSD$ +arm/arm/bus_space_asm_generic.S standard +arm/arm/bus_space_generic.c standard +arm/arm/cpufunc_asm_armv5.S standard +arm/arm/cpufunc_asm_arm11.S standard +arm/arm/cpufunc_asm_armv7.S standard +arm/arm/irq_dispatch.S standard +kern/kern_clocksource.c standard + +# Init +arm/freescale/imx/imx_machdep.c standard +arm/freescale/imx/common.c standard +arm/freescale/imx/bus_space.c standard + +# Dummy serial console +#arm/freescale/imx/console.c standard + +# TrustZone Interrupt Controller +arm/freescale/imx/tzic.c standard + +# IOMUX - external pins multiplexor +arm/freescale/imx/imx51_iomux.c optional iomux + +# GPIO +arm/freescale/imx/imx51_gpio.c optional gpio + +# Generic Periodic Timer +arm/freescale/imx/imx_gpt.c standard + +# Clock Configuration Manager +arm/freescale/imx/imx51_ccm.c standard + +# i.MX5xx PATA controller +dev/ata/chipsets/ata-fsl.c optional imxata + +# UART driver +dev/uart/uart_dev_imx.c optional uart + +# USB join controller (1 OTG, 3 EHCI) +dev/usb/controller/ehci_imx.c optional ehci + +# Watchdog +arm/freescale/imx/imx_wdog.c optional imxwdt + +# i2c +arm/freescale/imx/i2c.c optional fsliic +dev/ofw/ofw_iicbus.c optional fsliic + +# IPU - Image Processing Unit (frame buffer also) +arm/freescale/imx/imx51_ipuv3.c optional sc + diff --git a/sys/arm/freescale/imx/imx51_ccm.c b/sys/arm/freescale/imx/imx51_ccm.c new file mode 100644 index 0000000..6093e2b --- /dev/null +++ b/sys/arm/freescale/imx/imx51_ccm.c @@ -0,0 +1,474 @@ +/* $NetBSD: imx51_ccm.c,v 1.1 2012/04/17 09:33:31 bsh Exp $ */ +/* + * Copyright (c) 2010, 2011, 2012 Genetec Corporation. All rights reserved. + * Written by Hashimoto Kenichi for Genetec Corporation. + * + * 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 GENETEC CORPORATION ``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 GENETEC CORPORATION + * 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. + */ + +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by Oleksandr Rybalko + * under sponsorship from the FreeBSD Foundation. + * + * 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. + */ + +/* + * Clock Controller Module (CCM) + */ + +#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 <machine/bus.h> +#include <machine/cpu.h> +#include <machine/intr.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 <arm/freescale/imx/imx51_ccmvar.h> +#include <arm/freescale/imx/imx51_ccmreg.h> +#include <arm/freescale/imx/imx51_dpllreg.h> + +#define IMXCCMDEBUG +#undef IMXCCMDEBUG + +#ifndef IMX51_OSC_FREQ +#define IMX51_OSC_FREQ (24 * 1000 * 1000) /* 24MHz */ +#endif + +#ifndef IMX51_CKIL_FREQ +#define IMX51_CKIL_FREQ 32768 +#endif + +struct imxccm_softc { + device_t sc_dev; + struct resource *res[7]; + u_int64_t pll_freq[IMX51_N_DPLLS]; +}; + +struct imxccm_softc *ccm_softc = NULL; + +static uint64_t imx51_get_pll_freq(u_int); + +static int imxccm_match(device_t); +static int imxccm_attach(device_t); + +static device_method_t imxccm_methods[] = { + DEVMETHOD(device_probe, imxccm_match), + DEVMETHOD(device_attach, imxccm_attach), + + DEVMETHOD_END +}; + +static driver_t imxccm_driver = { + "imxccm", + imxccm_methods, + sizeof(struct imxccm_softc), +}; + +static devclass_t imxccm_devclass; + +EARLY_DRIVER_MODULE(imxccm, simplebus, imxccm_driver, imxccm_devclass, 0, 0, + BUS_PASS_CPU); + +static struct resource_spec imxccm_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Global registers */ + { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* DPLLIP1 */ + { SYS_RES_MEMORY, 2, RF_ACTIVE }, /* DPLLIP2 */ + { SYS_RES_MEMORY, 3, RF_ACTIVE }, /* DPLLIP3 */ + { SYS_RES_IRQ, 0, RF_ACTIVE }, /* 71 */ + { SYS_RES_IRQ, 1, RF_ACTIVE }, /* 72 */ + { -1, 0 } +}; + +static int +imxccm_match(device_t dev) +{ + + if (!ofw_bus_is_compatible(dev, "fsl,imx51-ccm")) + return (ENXIO); + + device_set_desc(dev, "Freescale Clock Control Module"); + return (BUS_PROBE_DEFAULT); +} + +static int +imxccm_attach(device_t dev) +{ + struct imxccm_softc *sc; + + sc = device_get_softc(dev); + sc->sc_dev = dev; + + if (bus_alloc_resources(dev, imxccm_spec, sc->res)) { + device_printf(dev, "could not allocate resources\n"); + return (ENXIO); + } + + ccm_softc = sc; + + imx51_get_pll_freq(1); + imx51_get_pll_freq(2); + imx51_get_pll_freq(3); + + device_printf(dev, "PLL1=%lluMHz, PLL2=%lluMHz, PLL3=%lluMHz\n", + sc->pll_freq[0] / 1000000, + sc->pll_freq[1] / 1000000, + sc->pll_freq[2] / 1000000); + device_printf(dev, "CPU clock=%d, UART clock=%d\n", + imx51_get_clock(IMX51CLK_ARM_ROOT), + imx51_get_clock(IMX51CLK_UART_CLK_ROOT)); + device_printf(dev, + "mainbus clock=%d, ahb clock=%d ipg clock=%d perclk=%d\n", + imx51_get_clock(IMX51CLK_MAIN_BUS_CLK), + imx51_get_clock(IMX51CLK_AHB_CLK_ROOT), + imx51_get_clock(IMX51CLK_IPG_CLK_ROOT), + imx51_get_clock(IMX51CLK_PERCLK_ROOT)); + + + return (0); +} + +u_int +imx51_get_clock(enum imx51_clock clk) +{ + u_int freq; + u_int sel; + uint32_t cacrr; /* ARM clock root register */ + uint32_t ccsr; + uint32_t cscdr1; + uint32_t cscmr1; + uint32_t cbcdr; + uint32_t cbcmr; + uint32_t cdcr; + + if (ccm_softc == NULL) + return (0); + + switch (clk) { + case IMX51CLK_PLL1: + case IMX51CLK_PLL2: + case IMX51CLK_PLL3: + return ccm_softc->pll_freq[clk-IMX51CLK_PLL1]; + case IMX51CLK_PLL1SW: + ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR); + if ((ccsr & CCSR_PLL1_SW_CLK_SEL) == 0) + return ccm_softc->pll_freq[1-1]; + /* step clock */ + /* FALLTHROUGH */ + case IMX51CLK_PLL1STEP: + ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR); + switch ((ccsr & CCSR_STEP_SEL_MASK) >> CCSR_STEP_SEL_SHIFT) { + case 0: + return imx51_get_clock(IMX51CLK_LP_APM); + case 1: + return 0; /* XXX PLL bypass clock */ + case 2: + return ccm_softc->pll_freq[2-1] / + (1 + ((ccsr & CCSR_PLL2_DIV_PODF_MASK) >> + CCSR_PLL2_DIV_PODF_SHIFT)); + case 3: + return ccm_softc->pll_freq[3-1] / + (1 + ((ccsr & CCSR_PLL3_DIV_PODF_MASK) >> + CCSR_PLL3_DIV_PODF_SHIFT)); + } + /*NOTREACHED*/ + case IMX51CLK_PLL2SW: + ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR); + if ((ccsr & CCSR_PLL2_SW_CLK_SEL) == 0) + return imx51_get_clock(IMX51CLK_PLL2); + return 0; /* XXX PLL2 bypass clk */ + case IMX51CLK_PLL3SW: + ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR); + if ((ccsr & CCSR_PLL3_SW_CLK_SEL) == 0) + return imx51_get_clock(IMX51CLK_PLL3); + return 0; /* XXX PLL3 bypass clk */ + + case IMX51CLK_LP_APM: + ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR); + return (ccsr & CCSR_LP_APM) ? + imx51_get_clock(IMX51CLK_FPM) : IMX51_OSC_FREQ; + + case IMX51CLK_ARM_ROOT: + freq = imx51_get_clock(IMX51CLK_PLL1SW); + cacrr = bus_read_4(ccm_softc->res[0], CCMC_CACRR); + return freq / (cacrr + 1); + + /* ... */ + case IMX51CLK_MAIN_BUS_CLK_SRC: + cbcdr = bus_read_4(ccm_softc->res[0], CCMC_CBCDR); + if ((cbcdr & CBCDR_PERIPH_CLK_SEL) == 0) + freq = imx51_get_clock(IMX51CLK_PLL2SW); + else { + freq = 0; + cbcmr = bus_read_4(ccm_softc->res[0], CCMC_CBCMR); + switch ((cbcmr & CBCMR_PERIPH_APM_SEL_MASK) >> + CBCMR_PERIPH_APM_SEL_SHIFT) { + case 0: + freq = imx51_get_clock(IMX51CLK_PLL1SW); + break; + case 1: + freq = imx51_get_clock(IMX51CLK_PLL3SW); + break; + case 2: + freq = imx51_get_clock(IMX51CLK_LP_APM); + break; + case 3: + /* XXX: error */ + break; + } + } + return freq; + case IMX51CLK_MAIN_BUS_CLK: + freq = imx51_get_clock(IMX51CLK_MAIN_BUS_CLK_SRC); + cdcr = bus_read_4(ccm_softc->res[0], CCMC_CDCR); + return freq / (cdcr & CDCR_PERIPH_CLK_DVFS_PODF_MASK) >> + CDCR_PERIPH_CLK_DVFS_PODF_SHIFT; + case IMX51CLK_AHB_CLK_ROOT: + freq = imx51_get_clock(IMX51CLK_MAIN_BUS_CLK); + cbcdr = bus_read_4(ccm_softc->res[0], CCMC_CBCDR); + return freq / (1 + ((cbcdr & CBCDR_AHB_PODF_MASK) >> + CBCDR_AHB_PODF_SHIFT)); + case IMX51CLK_IPG_CLK_ROOT: + freq = imx51_get_clock(IMX51CLK_AHB_CLK_ROOT); + cbcdr = bus_read_4(ccm_softc->res[0], CCMC_CBCDR); + return freq / (1 + ((cbcdr & CBCDR_IPG_PODF_MASK) >> + CBCDR_IPG_PODF_SHIFT)); + + case IMX51CLK_PERCLK_ROOT: + cbcmr = bus_read_4(ccm_softc->res[0], CCMC_CBCMR); + if (cbcmr & CBCMR_PERCLK_IPG_SEL) + return imx51_get_clock(IMX51CLK_IPG_CLK_ROOT); + if (cbcmr & CBCMR_PERCLK_LP_APM_SEL) + freq = imx51_get_clock(IMX51CLK_LP_APM); + else + freq = imx51_get_clock(IMX51CLK_MAIN_BUS_CLK_SRC); + cbcdr = bus_read_4(ccm_softc->res[0], CCMC_CBCDR); + +#ifdef IMXCCMDEBUG + printf("cbcmr=%x cbcdr=%x\n", cbcmr, cbcdr); +#endif + + freq /= 1 + ((cbcdr & CBCDR_PERCLK_PRED1_MASK) >> + CBCDR_PERCLK_PRED1_SHIFT); + freq /= 1 + ((cbcdr & CBCDR_PERCLK_PRED2_MASK) >> + CBCDR_PERCLK_PRED2_SHIFT); + freq /= 1 + ((cbcdr & CBCDR_PERCLK_PODF_MASK) >> + CBCDR_PERCLK_PODF_SHIFT); + return freq; + case IMX51CLK_UART_CLK_ROOT: + cscdr1 = bus_read_4(ccm_softc->res[0], CCMC_CSCDR1); + cscmr1 = bus_read_4(ccm_softc->res[0], CCMC_CSCMR1); + +#ifdef IMXCCMDEBUG + printf("cscdr1=%x cscmr1=%x\n", cscdr1, cscmr1); +#endif + + sel = (cscmr1 & CSCMR1_UART_CLK_SEL_MASK) >> + CSCMR1_UART_CLK_SEL_SHIFT; + + freq = 0; /* shut up GCC */ + switch (sel) { + case 0: + case 1: + case 2: + freq = imx51_get_clock(IMX51CLK_PLL1SW + sel); + break; + case 3: + freq = imx51_get_clock(IMX51CLK_LP_APM); + break; + } + + return freq / (1 + ((cscdr1 & CSCDR1_UART_CLK_PRED_MASK) >> + CSCDR1_UART_CLK_PRED_SHIFT)) / + (1 + ((cscdr1 & CSCDR1_UART_CLK_PODF_MASK) >> + CSCDR1_UART_CLK_PODF_SHIFT)); + case IMX51CLK_IPU_HSP_CLK_ROOT: + freq = 0; + cbcmr = bus_read_4(ccm_softc->res[0], CCMC_CBCMR); + switch ((cbcmr & CBCMR_IPU_HSP_CLK_SEL_MASK) >> + CBCMR_IPU_HSP_CLK_SEL_SHIFT) { + case 0: + freq = imx51_get_clock(IMX51CLK_ARM_AXI_A_CLK); + break; + case 1: + freq = imx51_get_clock(IMX51CLK_ARM_AXI_B_CLK); + break; + case 2: + freq = imx51_get_clock( + IMX51CLK_EMI_SLOW_CLK_ROOT); + break; + case 3: + freq = imx51_get_clock(IMX51CLK_AHB_CLK_ROOT); + break; + } + return freq; + default: + device_printf(ccm_softc->sc_dev, + "clock %d: not supported yet\n", clk); + return 0; + } +} + + +static uint64_t +imx51_get_pll_freq(u_int pll_no) +{ + uint32_t dp_ctrl; + uint32_t dp_op; + uint32_t dp_mfd; + uint32_t dp_mfn; + uint32_t mfi; + int32_t mfn; + uint32_t mfd; + uint32_t pdf; + uint32_t ccr; + uint64_t freq = 0; + u_int ref = 0; + + KASSERT(1 <= pll_no && pll_no <= IMX51_N_DPLLS, ("Wrong PLL id")); + + dp_ctrl = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_CTL); + + if (dp_ctrl & DP_CTL_HFSM) { + dp_op = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_HFS_OP); + dp_mfd = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_HFS_MFD); + dp_mfn = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_HFS_MFN); + } else { + dp_op = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_OP); + dp_mfd = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_MFD); + dp_mfn = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_MFN); + } + + pdf = dp_op & DP_OP_PDF_MASK; + mfi = max(5, (dp_op & DP_OP_MFI_MASK) >> DP_OP_MFI_SHIFT); + mfd = dp_mfd; + if (dp_mfn & 0x04000000) + /* 27bit signed value */ + mfn = (uint32_t)(0xf8000000 | dp_mfn); + else + mfn = dp_mfn; + + switch (dp_ctrl & DP_CTL_REF_CLK_SEL_MASK) { + case DP_CTL_REF_CLK_SEL_COSC: + /* Internal Oscillator */ + /* TODO: get from FDT "fsl,imx-osc" */ + ref = 24000000; /* IMX51_OSC_FREQ */ + break; + case DP_CTL_REF_CLK_SEL_FPM: + ccr = bus_read_4(ccm_softc->res[0], CCMC_CCR); + if (ccr & CCR_FPM_MULT) + /* TODO: get from FDT "fsl,imx-ckil" */ + ref = 32768 * 1024; + else + /* TODO: get from FDT "fsl,imx-ckil" */ + ref = 32768 * 512; + break; + default: + ref = 0; + } + + if (dp_ctrl & DP_CTL_REF_CLK_DIV) + ref /= 2; + + ref *= 4; + freq = (int64_t)ref * mfi + (int64_t)ref * mfn / (mfd + 1); + freq /= pdf + 1; + + if (!(dp_ctrl & DP_CTL_DPDCK0_2_EN)) + freq /= 2; + +#ifdef IMXCCMDEBUG + printf("ref: %dKHz ", ref); + printf("dp_ctl: %08x ", dp_ctrl); + printf("pdf: %3d ", pdf); + printf("mfi: %3d ", mfi); + printf("mfd: %3d ", mfd); + printf("mfn: %3d ", mfn); + printf("pll: %d\n", (uint32_t)freq); +#endif + + ccm_softc->pll_freq[pll_no-1] = freq; + + return (freq); +} + +void +imx51_clk_gating(int clk_src, int mode) +{ + int field, group; + uint32_t reg; + + group = CCMR_CCGR_MODULE(clk_src); + field = clk_src % CCMR_CCGR_NSOURCE; + reg = bus_read_4(ccm_softc->res[0], CCMC_CCGR(group)); + reg &= ~(0x03 << field * 2); + reg |= (mode << field * 2); + bus_write_4(ccm_softc->res[0], CCMC_CCGR(group), reg); +} + +int +imx51_get_clk_gating(int clk_src) +{ + uint32_t reg; + + reg = bus_read_4(ccm_softc->res[0], + CCMC_CCGR(CCMR_CCGR_MODULE(clk_src))); + return ((reg >> (clk_src % CCMR_CCGR_NSOURCE) * 2) & 0x03); +} + diff --git a/sys/arm/freescale/imx/imx51_ccmreg.h b/sys/arm/freescale/imx/imx51_ccmreg.h new file mode 100644 index 0000000..d17b98a --- /dev/null +++ b/sys/arm/freescale/imx/imx51_ccmreg.h @@ -0,0 +1,250 @@ +/* $NetBSD: imx51_ccmreg.h,v 1.1 2012/04/17 09:33:31 bsh Exp $ */ +/* + * Copyright (c) 2011, 2012 Genetec Corporation. All rights reserved. + * Written by Hashimoto Kenichi for Genetec Corporation. + * + * 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 GENETEC CORPORATION ``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 GENETEC CORPORATION + * 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. + */ + +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by Oleksandr Rybalko + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _IMX51_CCMREG_H +#define _IMX51_CCMREG_H + +#include <sys/cdefs.h> + +/* register offset address */ + +#define CCMC_BASE 0x73fd4000 +#define CCMC_CCR 0x0000 +#define CCR_FPM_MULT 0x00001000 +#define CCMC_CCDR 0x0004 +#define CCMC_CSR 0x0008 +#define CCMC_CCSR 0x000c +#define CCSR_LP_APM 0x00000200 +#define CCSR_STEP_SEL_SHIFT 7 +#define CCSR_STEP_SEL_MASK 0x00000180 +#define CCSR_PLL2_DIV_PODF_SHIFT 5 +#define CCSR_PLL2_DIV_PODF_MASK 0x00000060 +#define CCSR_PLL3_DIV_PODF_SHIFT 3 +#define CCSR_PLL3_DIV_PODF_MASK 0x00000030 +#define CCSR_PLL1_SW_CLK_SEL 0x00000004 +#define CCSR_PLL2_SW_CLK_SEL 0x00000002 +#define CCSR_PLL3_SW_CLK_SEL 0x00000001 +#define CCMC_CACRR 0x0010 +#define CCMC_CBCDR 0x0014 +#define CBCDR_DDR_HIGH_FREQ_CLK_SEL 0x40000000 +#define CBCDR_DDR_CLK_PODF_SHIFT 27 +#define CBCDR_DDR_CLK_PODF_MASK 0x38000000 +#define CBCDR_EMI_CLK_SEL 0x04000000 +#define CBCDR_PERIPH_CLK_SEL 0x02000000 +#define CBCDR_EMI_SLOW_PODF_SHIFT 22 +#define CBCDR_EMI_SLOW_PODF_MASK 0x01c00000 +#define CBCDR_AXI_B_PODF_SHIFT 19 +#define CBCDR_AXI_B_PODF_MASK 0x00380000 +#define CBCDR_AXI_A_PODF_SHIFT 16 +#define CBCDR_AXI_A_PODF_MASK 0x1fff0000 +#define CBCDR_NFC_PODF_SHIFT 13 +#define CBCDR_NFC_PODF_MASK 0x00018000 +#define CBCDR_AHB_PODF_SHIFT 10 +#define CBCDR_AHB_PODF_MASK 0x00001c00 +#define CBCDR_IPG_PODF_SHIFT 8 +#define CBCDR_IPG_PODF_MASK 0x00000300 +#define CBCDR_PERCLK_PRED1_SHIFT 6 +#define CBCDR_PERCLK_PRED1_MASK 0x000000c0 +#define CBCDR_PERCLK_PRED2_SHIFT 3 +#define CBCDR_PERCLK_PRED2_MASK 0x00000038 +#define CBCDR_PERCLK_PODF_SHIFT 0 +#define CBCDR_PERCLK_PODF_MASK 0x00000007 +#define CCMC_CBCMR 0x0018 +#define CBCMR_PERIPH_APM_SEL_SHIFT 12 +#define CBCMR_PERIPH_APM_SEL_MASK 0x00003000 +#define CBCMR_IPU_HSP_CLK_SEL_SHIFT 6 +#define CBCMR_IPU_HSP_CLK_SEL_MASK 0x000000c0 +#define CBCMR_PERCLK_LP_APM_SEL 0x00000002 +#define CBCMR_PERCLK_IPG_SEL 0x00000001 +#define CCMC_CSCMR1 0x001c +#define CSCMR1_UART_CLK_SEL_SHIFT 24 +#define CSCMR1_UART_CLK_SEL_MASK 0x03000000 +#define CCMC_CSCMR2 0x0020 +#define CCMC_CSCDR1 0x0024 +#define CSCDR1_UART_CLK_PRED_SHIFT 3 +#define CSCDR1_UART_CLK_PRED_MASK 0x00000038 +#define CSCDR1_UART_CLK_PODF_SHIFT 0 +#define CSCDR1_UART_CLK_PODF_MASK 0x00000007 +#define CCMC_CS1CDR 0x0028 +#define CCMC_CS2CDR 0x002c +#define CCMC_CDCDR 0x0030 +#define CCMC_CSCDR2 0x0038 +#define CCMC_CSCDR3 0x003c +#define CCMC_CSCDR4 0x0040 +#define CCMC_CWDR 0x0044 +#define CCMC_CDHIPR 0x0048 +#define CCMC_CDCR 0x004c +#define CDCR_PERIPH_CLK_DVFS_PODF_SHIFT 0 +#define CDCR_PERIPH_CLK_DVFS_PODF_MASK 0x00000003 +#define CCMC_CTOR 0x0050 +#define CCMC_CLPCR 0x0054 +#define CCMC_CISR 0x0058 +#define CCMC_CIMR 0x005c +#define CCMC_CCOSR 0x0060 +#define CCMC_CGPR 0x0064 +#define CCMC_CCGR(n) (0x0068 + (n) * 4) +#define CCMC_CMEOR 0x0084 + +#define CCMC_SIZE 0x88 + +/* CCGR Clock Gate Register */ + +#define CCMR_CCGR_NSOURCE 16 +#define CCMR_CCGR_NGROUPS 7 +#define CCMR_CCGR_MODULE(clk) ((clk) / CCMR_CCGR_NSOURCE) +#define __CCGR_NUM(a, b) ((a) * 16 + (b)) + +#define CCGR_ARM_BUS_CLK __CCGR_NUM(0, 0) +#define CCGR_ARM_AXI_CLK __CCGR_NUM(0, 1) +#define CCGR_ARM_DEBUG_CLK __CCGR_NUM(0, 2) +#define CCGR_TZIC_CLK __CCGR_NUM(0, 3) +#define CCGR_DAP_CLK __CCGR_NUM(0, 4) +#define CCGR_TPIU_CLK __CCGR_NUM(0, 5) +#define CCGR_CTI2_CLK __CCGR_NUM(0, 6) +#define CCGR_CTI3_CLK __CCGR_NUM(0, 7) +#define CCGR_AHBMUX1_CLK __CCGR_NUM(0, 8) +#define CCGR_AHBMUX2_CLK __CCGR_NUM(0, 9) +#define CCGR_ROMCP_CLK __CCGR_NUM(0, 10) +#define CCGR_ROM_CLK __CCGR_NUM(0, 11) +#define CCGR_AIPS_TZ1_CLK __CCGR_NUM(0, 12) +#define CCGR_AIPS_TZ2_CLK __CCGR_NUM(0, 13) +#define CCGR_AHB_MAX_CLK __CCGR_NUM(0, 14) +#define CCGR_IIM_CLK __CCGR_NUM(0, 15) +#define CCGR_TMAX1_CLK __CCGR_NUM(1, 0) +#define CCGR_TMAX2_CLK __CCGR_NUM(1, 1) +#define CCGR_TMAX3_CLK __CCGR_NUM(1, 2) +#define CCGR_UART1_CLK __CCGR_NUM(1, 3) +#define CCGR_UART1_SERIAL_CLK __CCGR_NUM(1, 4) +#define CCGR_UART2_CLK __CCGR_NUM(1, 5) +#define CCGR_UART2_SERIAL_CLK __CCGR_NUM(1, 6) +#define CCGR_UART3_CLK __CCGR_NUM(1, 7) +#define CCGR_UART3_SERIAL_CLK __CCGR_NUM(1, 8) +#define CCGR_I2C1_SERIAL_CLK __CCGR_NUM(1, 9) +#define CCGR_I2C2_SERIAL_CLK __CCGR_NUM(1, 10) +#define CCGR_HSI2C_CLK __CCGR_NUM(1, 11) +#define CCGR_HSI2C_SERIAL_CLK __CCGR_NUM(1, 12) +#define CCGR_FIRI_CLK __CCGR_NUM(1, 13) +#define CCGR_FIRI_SERIAL_CLK __CCGR_NUM(1, 14) +#define CCGR_SCC_CLK __CCGR_NUM(1, 15) + +#define CCGR_USB_PHY_CLK __CCGR_NUM(2, 0) +#define CCGR_EPIT1_CLK __CCGR_NUM(2, 1) +#define CCGR_EPIT1_SERIAL_CLK __CCGR_NUM(2, 2) +#define CCGR_EPIT2_CLK __CCGR_NUM(2, 3) +#define CCGR_EPIT2_SERIAL_CLK __CCGR_NUM(2, 4) +#define CCGR_PWM1_CLK __CCGR_NUM(2, 5) +#define CCGR_PWM1_SERIAL_CLK __CCGR_NUM(2, 6) +#define CCGR_PWM2_CLK __CCGR_NUM(2, 7) +#define CCGR_PWM2_SERIAL_CLK __CCGR_NUM(2, 8) +#define CCGR_GPT_CLK __CCGR_NUM(2, 9) +#define CCGR_GPT_SERIAL_CLK __CCGR_NUM(2, 10) +#define CCGR_OWIRE_CLK __CCGR_NUM(2, 11) +#define CCGR_FEC_CLK __CCGR_NUM(2, 12) +#define CCGR_USBOH3_IPG_AHB_CLK __CCGR_NUM(2, 13) +#define CCGR_USBOH3_60M_CLK __CCGR_NUM(2, 14) +#define CCGR_TVE_CLK __CCGR_NUM(2, 15) + +#define CCGR_ESDHC1_CLK __CCGR_NUM(3, 0) +#define CCGR_ESDHC1_SERIAL_CLK __CCGR_NUM(3, 1) +#define CCGR_ESDHC2_CLK __CCGR_NUM(3, 2) +#define CCGR_ESDHC2_SERIAL_CLK __CCGR_NUM(3, 3) +#define CCGR_ESDHC3_CLK __CCGR_NUM(3, 4) +#define CCGR_ESDHC3_SERIAL_CLK __CCGR_NUM(3, 5) +#define CCGR_ESDHC4_CLK __CCGR_NUM(3, 6) +#define CCGR_ESDHC4_SERIAL_CLK __CCGR_NUM(3, 7) +#define CCGR_SSI1_CLK __CCGR_NUM(3, 8) +#define CCGR_SSI1_SERIAL_CLK __CCGR_NUM(3, 9) +#define CCGR_SSI2_CLK __CCGR_NUM(3, 10) +#define CCGR_SSI2_SERIAL_CLK __CCGR_NUM(3, 11) +#define CCGR_SSI3_CLK __CCGR_NUM(3, 12) +#define CCGR_SSI3_SERIAL_CLK __CCGR_NUM(3, 13) +#define CCGR_SSI_EXT1_CLK __CCGR_NUM(3, 14) +#define CCGR_SSI_EXT2_CLK __CCGR_NUM(3, 15) + +#define CCGR_PATA_CLK __CCGR_NUM(4, 0) +#define CCGR_SIM_CLK __CCGR_NUM(4, 1) +#define CCGR_SIM_SERIAL_CLK __CCGR_NUM(4, 2) +#define CCGR_SAHARA_CLK __CCGR_NUM(4, 3) +#define CCGR_RTIC_CLK __CCGR_NUM(4, 4) +#define CCGR_ECSPI1_CLK __CCGR_NUM(4, 5) +#define CCGR_ECSPI1_SERIAL_CLK __CCGR_NUM(4, 6) +#define CCGR_ECSPI2_CLK __CCGR_NUM(4, 7) +#define CCGR_ECSPI2_SERIAL_CLK __CCGR_NUM(4, 8) +#define CCGR_CSPI_CLK __CCGR_NUM(4, 9) +#define CCGR_SRTC_CLK __CCGR_NUM(4, 10) +#define CCGR_SDMA_CLK __CCGR_NUM(4, 11) + +#define CCGR_SPBA_CLK __CCGR_NUM(5, 0) +#define CCGR_GPU_CLK __CCGR_NUM(5, 1) +#define CCGR_GARB_CLK __CCGR_NUM(5, 2) +#define CCGR_VPU_CLK __CCGR_NUM(5, 3) +#define CCGR_VPU_SERIAL_CLK __CCGR_NUM(5, 4) +#define CCGR_IPU_CLK __CCGR_NUM(5, 5) +#define CCGR_EMI_GARB_CLK __CCGR_NUM(6, 0) +#define CCGR_IPU_DI0_CLK __CCGR_NUM(6, 1) +#define CCGR_IPU_DI1_CLK __CCGR_NUM(6, 2) +#define CCGR_GPU2D_CLK __CCGR_NUM(6, 3) +#define CCGR_SLIMBUS_CLK __CCGR_NUM(6, 4) +#define CCGR_SLIMBUS_SERIAL_CLK __CCGR_NUM(6, 5) + +#define CCGR_CLK_MODE_OFF 0 +#define CCGR_CLK_MODE_RUNMODE 1 +#define CCGR_CLK_MODE_ALWAYS 3 + +#endif /* _IMX51_CCMREG_H */ + diff --git a/sys/arm/freescale/imx/imx51_ccmvar.h b/sys/arm/freescale/imx/imx51_ccmvar.h new file mode 100644 index 0000000..9b798f1 --- /dev/null +++ b/sys/arm/freescale/imx/imx51_ccmvar.h @@ -0,0 +1,110 @@ +/* $NetBSD: imx51_ccmvar.h,v 1.1 2012/04/17 09:33:31 bsh Exp $ */ +/* + * Copyright (c) 2012 Genetec Corporation. All rights reserved. + * Written by Hashimoto Kenichi for Genetec Corporation. + * + * 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 GENETEC CORPORATION ``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 GENETEC CORPORATION + * 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. + */ + +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by Oleksandr Rybalko + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _ARM_IMX_IMX51_CCMVAR_H_ +#define _ARM_IMX_IMX51_CCMVAR_H_ + +enum imx51_clock { + IMX51CLK_FPM, + IMX51CLK_PLL1, + IMX51CLK_PLL2, + IMX51CLK_PLL3, + IMX51CLK_PLL1SW, + IMX51CLK_PLL2SW, + IMX51CLK_PLL3SW, + IMX51CLK_PLL1STEP, + IMX51CLK_LP_APM, + IMX51CLK_ARM_ROOT, + IMX51CLK_MAIN_BUS_CLK_SRC, /* XXX */ + IMX51CLK_MAIN_BUS_CLK, + IMX51CLK_EMI_SLOW_CLK_ROOT, + IMX51CLK_ENFC_CLK_ROOT, + IMX51CLK_AHB_CLK_ROOT, + IMX51CLK_IPG_CLK_ROOT, + IMX51CLK_PERCLK_ROOT, + IMX51CLK_DDR_CLK_ROOT, + IMX51CLK_ARM_AXI_CLK_ROOT, + IMX51CLK_ARM_AXI_A_CLK, + IMX51CLK_ARM_AXI_B_CLK, + IMX51CLK_IPU_HSP_CLK_ROOT, + IMX51CLK_CKIL_SYNC_CLK_ROOT, + IMX51CLK_USBOH3_CLK_ROOT, + IMX51CLK_ESDHC1_CLK_ROOT, + IMX51CLK_ESDHC2_CLK_ROOT, + IMX51CLK_ESDHC3_CLK_ROOT, + IMX51CLK_UART_CLK_ROOT, + IMX51CLK_SSI1_CLK_ROOT, + IMX51CLK_SSI2_CLK_ROOT, + IMX51CLK_SSI_EXT1_CLK_ROOT, + IMX51CLK_SSI_EXT2_CLK_ROOT, + IMX51CLK_USB_PHY_CLK_ROOT, + IMX51CLK_TVE_216_54_CLK_ROOT, + IMX51CLK_DI_CLK_ROOT, + IMX51CLK_SPDIF0_CLK_ROOT, + IMX51CLK_SPDIF1_CLK_ROOT, + IMX51CLK_CSPI_CLK_ROOT, + IMX51CLK_WRCK_CLK_ROOT, + IMX51CLK_LPSR_CLK_ROOT, + IMX51CLK_PGC_CLK_ROOT +}; + +u_int imx51_get_clock(enum imx51_clock); +void imx51_clk_gating(int, int); +int imx51_get_clk_gating(int); + +#endif /* _ARM_IMX_IMX51_CCMVAR_H_ */ diff --git a/sys/arm/freescale/imx/imx51_dpllreg.h b/sys/arm/freescale/imx/imx51_dpllreg.h new file mode 100644 index 0000000..06393da --- /dev/null +++ b/sys/arm/freescale/imx/imx51_dpllreg.h @@ -0,0 +1,105 @@ +/* $NetBSD: imx51_dpllreg.h,v 1.1 2012/04/17 09:33:31 bsh Exp $ */ +/* + * Copyright (c) 2012 Genetec Corporation. All rights reserved. + * Written by Hashimoto Kenichi for Genetec Corporation. + * + * 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 GENETEC CORPORATION ``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 GENETEC CORPORATION + * 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. + */ + +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by Oleksandr Rybalko + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _IMX51_DPLLREG_H +#define _IMX51_DPLLREG_H + +#include <sys/cdefs.h> + +/* register offset address */ + +#define IMX51_N_DPLLS 3 /* 1..3 */ + +#define DPLL_BASE(n) (0x83F80000 + (0x4000 * ((n)-1))) +#define DPLL_SIZE 0x100 + +#define DPLL_DP_CTL 0x0000 /* 0x1223 */ +#define DP_CTL_LRF 0x00000001 +#define DP_CTL_BRM 0x00000002 +#define DP_CTL_PLM 0x00000004 +#define DP_CTL_RCP 0x00000008 +#define DP_CTL_RST 0x00000010 +#define DP_CTL_UPEN 0x00000020 +#define DP_CTL_PRE 0x00000040 +#define DP_CTL_HFSM 0x00000080 +#define DP_CTL_REF_CLK_SEL_MASK 0x00000300 +#define DP_CTL_REF_CLK_SEL_COSC 0x00000200 +#define DP_CTL_REF_CLK_SEL_FPM 0x00000300 +#define DP_CTL_REF_CLK_DIV 0x00000400 +#define DP_CTL_DPDCK0_2_EN 0x00001000 +#define DP_CTL_HIGHCLK_EN DP_CTL_DPDCK0_2_EN +#define DP_CTL_MULCTRL 0x00002000 +#define DPLL_DP_CONFIG 0x0004 /* 2 */ +#define DPLL_DP_CONFIG_APEN 0x00000002 +#define DPLL_DP_CONFIG_LDREQ 0x00000001 +#define DPLL_DP_OP 0x0008 /* 0x80 */ +#define DP_OP_PDF_SHIFT 0 +#define DP_OP_PDF_MASK (0xf << DP_OP_PDF_SHIFT) +#define DP_OP_MFI_SHIFT 4 +#define DP_OP_MFI_MASK (0xf << DP_OP_MFI_SHIFT) +#define DPLL_DP_MFD 0x000C /* 2 */ +#define DPLL_DP_MFN 0x0010 /* 1 */ +#define DPLL_DP_MFNMINUS 0x0014 /* 0 */ +#define DPLL_DP_MFNPLUS 0x0018 /* 0 */ +#define DPLL_DP_HFS_OP 0x001C /* 0x80 */ +#define DPLL_DP_HFS_MFD 0x0020 /* 2 */ +#define DPLL_DP_HFS_MFN 0x0024 /* 1 */ +#define DPLL_DP_TOGC 0x0028 /* 0x20000 */ +#define DPLL_DP_DESTAT 0x002C /* 1 */ + +#endif /* _IMX51_DPLLREG_H */ diff --git a/sys/arm/freescale/imx/imx51_gpio.c b/sys/arm/freescale/imx/imx51_gpio.c new file mode 100644 index 0000000..d42a313 --- /dev/null +++ b/sys/arm/freescale/imx/imx51_gpio.c @@ -0,0 +1,481 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Oleksandr Rybalko under sponsorship + * from the FreeBSD Foundation. + * + * 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. + */ + +/* + * Freescale i.MX515 GPIO driver. + */ + +#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/rman.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/gpio.h> + +#include <machine/bus.h> +#include <machine/resource.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 "gpio_if.h" + +#define GPIO_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) +#define GPIO_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) +#define GPIO_LOCK_INIT(_sc) mtx_init(&_sc->sc_mtx, \ + device_get_nameunit(_sc->sc_dev), "imx_gpio", MTX_DEF) +#define GPIO_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx); +#define GPIO_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED); +#define GPIO_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED); + +#define WRITE4(_sc, _r, _v) \ + bus_space_write_4((_sc)->sc_iot, (_sc)->sc_ioh, (_r), (_v)) +#define READ4(_sc, _r) \ + bus_space_read_4((_sc)->sc_iot, (_sc)->sc_ioh, (_r)) +#define SET4(_sc, _r, _m) \ + WRITE4((_sc), (_r), READ4((_sc), (_r)) | (_m)) +#define CLEAR4(_sc, _r, _m) \ + WRITE4((_sc), (_r), READ4((_sc), (_r)) & ~(_m)) + +/* Registers definition for Freescale i.MX515 GPIO controller */ + +#define IMX_GPIO_DR_REG 0x000 /* Pin Data */ +#define IMX_GPIO_OE_REG 0x004 /* Set Pin Output */ +#define IMX_GPIO_PSR_REG 0x008 /* Pad Status */ +#define IMX_GPIO_ICR1_REG 0x00C /* Interrupt Configuration */ +#define IMX_GPIO_ICR2_REG 0x010 /* Interrupt Configuration */ +#define GPIO_ICR_COND_LOW 0 +#define GPIO_ICR_COND_HIGH 1 +#define GPIO_ICR_COND_RISE 2 +#define GPIO_ICR_COND_FALL 3 +#define IMX_GPIO_IMR_REG 0x014 /* Interrupt Mask Register */ +#define IMX_GPIO_ISR_REG 0x018 /* Interrupt Status Register */ +#define IMX_GPIO_EDGE_REG 0x01C /* Edge Detect Register */ + +#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT) +#define NGPIO 32 + +struct imx51_gpio_softc { + device_t dev; + struct mtx sc_mtx; + struct resource *sc_res[11]; /* 1 x mem, 2 x IRQ, 8 x IRQ */ + void *gpio_ih[11]; /* 1 ptr is not a big waste */ + int sc_l_irq; /* Last irq resource */ + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + int gpio_npins; + struct gpio_pin gpio_pins[NGPIO]; +}; + +static struct resource_spec imx_gpio_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { SYS_RES_IRQ, 0, RF_ACTIVE }, + { SYS_RES_IRQ, 1, RF_ACTIVE }, + { -1, 0 } +}; + +static struct resource_spec imx_gpio0irq_spec[] = { + { SYS_RES_IRQ, 2, RF_ACTIVE }, + { SYS_RES_IRQ, 3, RF_ACTIVE }, + { SYS_RES_IRQ, 4, RF_ACTIVE }, + { SYS_RES_IRQ, 5, RF_ACTIVE }, + { SYS_RES_IRQ, 6, RF_ACTIVE }, + { SYS_RES_IRQ, 7, RF_ACTIVE }, + { SYS_RES_IRQ, 8, RF_ACTIVE }, + { SYS_RES_IRQ, 9, RF_ACTIVE }, + { -1, 0 } +}; + +/* + * Helpers + */ +static void imx51_gpio_pin_configure(struct imx51_gpio_softc *, + struct gpio_pin *, uint32_t); + +/* + * Driver stuff + */ +static int imx51_gpio_probe(device_t); +static int imx51_gpio_attach(device_t); +static int imx51_gpio_detach(device_t); +static int imx51_gpio_intr(void *); + +/* + * GPIO interface + */ +static int imx51_gpio_pin_max(device_t, int *); +static int imx51_gpio_pin_getcaps(device_t, uint32_t, uint32_t *); +static int imx51_gpio_pin_getflags(device_t, uint32_t, uint32_t *); +static int imx51_gpio_pin_getname(device_t, uint32_t, char *); +static int imx51_gpio_pin_setflags(device_t, uint32_t, uint32_t); +static int imx51_gpio_pin_set(device_t, uint32_t, unsigned int); +static int imx51_gpio_pin_get(device_t, uint32_t, unsigned int *); +static int imx51_gpio_pin_toggle(device_t, uint32_t pin); + +static void +imx51_gpio_pin_configure(struct imx51_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; + SET4(sc, IMX_GPIO_OE_REG, (1 << pin->gp_pin)); + } + else { + pin->gp_flags |= GPIO_PIN_INPUT; + CLEAR4(sc, IMX_GPIO_OE_REG, (1 << pin->gp_pin)); + } + } + + GPIO_UNLOCK(sc); +} + +static int +imx51_gpio_pin_max(device_t dev, int *maxpin) +{ + + *maxpin = NGPIO - 1; + return (0); +} + +static int +imx51_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) +{ + struct imx51_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 +imx51_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) +{ + struct imx51_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 +imx51_gpio_pin_getname(device_t dev, uint32_t pin, char *name) +{ + struct imx51_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 +imx51_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) +{ + struct imx51_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); + + /* Filter out 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); + + imx51_gpio_pin_configure(sc, &sc->gpio_pins[i], flags); + + + return (0); +} + +static int +imx51_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) +{ + struct imx51_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) + SET4(sc, IMX_GPIO_DR_REG, (1 << i)); + else + CLEAR4(sc, IMX_GPIO_DR_REG, (1 << i)); + GPIO_UNLOCK(sc); + + return (0); +} + +static int +imx51_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) +{ + struct imx51_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, IMX_GPIO_DR_REG) >> i) & 1; + GPIO_UNLOCK(sc); + + return (0); +} + +static int +imx51_gpio_pin_toggle(device_t dev, uint32_t pin) +{ + struct imx51_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, IMX_GPIO_DR_REG, + (READ4(sc, IMX_GPIO_DR_REG) ^ (1 << i))); + GPIO_UNLOCK(sc); + + return (0); +} + +static int +imx51_gpio_intr(void *arg) +{ + struct imx51_gpio_softc *sc; + uint32_t input, value; + + sc = arg; + input = READ4(sc, IMX_GPIO_ISR_REG); + value = input & READ4(sc, IMX_GPIO_IMR_REG); + WRITE4(sc, IMX_GPIO_DR_REG, input); + + if (!value) + goto intr_done; + + /* TODO: interrupt handling */ + +intr_done: + return (FILTER_HANDLED); +} + +static int +imx51_gpio_probe(device_t dev) +{ + + if (ofw_bus_is_compatible(dev, "fsl,imx51-gpio")) { + device_set_desc(dev, "i.MX515 GPIO Controller"); + return (BUS_PROBE_DEFAULT); + } + + return (ENXIO); +} + +static int +imx51_gpio_attach(device_t dev) +{ + struct imx51_gpio_softc *sc; + int i, irq; + + sc = device_get_softc(dev); + mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); + + if (bus_alloc_resources(dev, imx_gpio_spec, sc->sc_res)) { + device_printf(dev, "could not allocate resources\n"); + return (ENXIO); + } + + sc->dev = dev; + sc->gpio_npins = NGPIO; + sc->sc_l_irq = 2; + sc->sc_iot = rman_get_bustag(sc->sc_res[0]); + sc->sc_ioh = rman_get_bushandle(sc->sc_res[0]); + + if (bus_alloc_resources(dev, imx_gpio0irq_spec, &sc->sc_res[3]) == 0) { + /* + * First GPIO unit able to serve +8 interrupts for 8 first + * pins. + */ + sc->sc_l_irq = 10; + } + + for (irq = 1; irq <= sc->sc_l_irq; irq ++) { + if ((bus_setup_intr(dev, sc->sc_res[irq], INTR_TYPE_MISC, + imx51_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, IMX_GPIO_OE_REG) & (1 << i)) ? GPIO_PIN_OUTPUT: + GPIO_PIN_INPUT; + snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME, + "imx_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 +imx51_gpio_detach(device_t dev) +{ + struct imx51_gpio_softc *sc; + + sc = device_get_softc(dev); + + KASSERT(mtx_initialized(&sc->sc_mtx), ("gpio mutex not initialized")); + + bus_generic_detach(dev); + + if (sc->sc_res[3]) + bus_release_resources(dev, imx_gpio0irq_spec, &sc->sc_res[3]); + + if (sc->sc_res[0]) + bus_release_resources(dev, imx_gpio_spec, sc->sc_res); + + mtx_destroy(&sc->sc_mtx); + + return(0); +} + +static device_method_t imx51_gpio_methods[] = { + DEVMETHOD(device_probe, imx51_gpio_probe), + DEVMETHOD(device_attach, imx51_gpio_attach), + DEVMETHOD(device_detach, imx51_gpio_detach), + + /* GPIO protocol */ + DEVMETHOD(gpio_pin_max, imx51_gpio_pin_max), + DEVMETHOD(gpio_pin_getname, imx51_gpio_pin_getname), + DEVMETHOD(gpio_pin_getflags, imx51_gpio_pin_getflags), + DEVMETHOD(gpio_pin_getcaps, imx51_gpio_pin_getcaps), + DEVMETHOD(gpio_pin_setflags, imx51_gpio_pin_setflags), + DEVMETHOD(gpio_pin_get, imx51_gpio_pin_get), + DEVMETHOD(gpio_pin_set, imx51_gpio_pin_set), + DEVMETHOD(gpio_pin_toggle, imx51_gpio_pin_toggle), + {0, 0}, +}; + +static driver_t imx51_gpio_driver = { + "gpio", + imx51_gpio_methods, + sizeof(struct imx51_gpio_softc), +}; +static devclass_t imx51_gpio_devclass; + +DRIVER_MODULE(imx51_gpio, simplebus, imx51_gpio_driver, imx51_gpio_devclass, + 0, 0); diff --git a/sys/arm/freescale/imx/imx51_iomux.c b/sys/arm/freescale/imx/imx51_iomux.c new file mode 100644 index 0000000..62f3509 --- /dev/null +++ b/sys/arm/freescale/imx/imx51_iomux.c @@ -0,0 +1,232 @@ +/* $NetBSD: imx51_iomux.c,v 1.3 2012/04/15 09:51:31 bsh Exp $ */ + +/* + * Copyright (c) 2009, 2010 Genetec Corporation. All rights reserved. + * Written by Hashimoto Kenichi for Genetec Corporation. + * + * 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 GENETEC CORPORATION ``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 GENETEC CORPORATION + * 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. + */ + +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by Oleksandr Rybalko + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/malloc.h> +#include <sys/rman.h> + +#include <machine/bus.h> +#include <machine/fdt.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 <arm/freescale/imx/imx51_iomuxvar.h> +#include <arm/freescale/imx/imx51_iomuxreg.h> + + +#define IOMUX_WRITE(_sc, _r, _v) \ + bus_write_4((_sc)->sc_res, (_r), (_v)) +#define IOMUX_READ(_sc, _r) \ + bus_read_4((_sc)->sc_res, (_r)) +#define IOMUX_SET(_sc, _r, _m) \ + IOMUX_WRITE((_sc), (_r), IOMUX_READ((_sc), (_r)) | (_m)) +#define IOMUX_CLEAR(_sc, _r, _m) \ + IOMUX_WRITE((_sc), (_r), IOMUX_READ((_sc), (_r)) & ~(_m)) + +struct iomux_softc { + struct resource *sc_res; + device_t sc_dev; +}; + +static int iomux_probe(device_t); +static int iomux_attach(device_t); + +static struct iomux_softc *iomuxsc = NULL; + +static struct resource_spec imx_iomux_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Global registers */ + { -1, 0 } +}; + +static int +iomux_probe(device_t dev) +{ + + if (!ofw_bus_is_compatible(dev, "fsl,imx51-iomux")) + return (ENXIO); + + device_set_desc(dev, "Freescale i.MX51 IO pins multiplexor"); + return (BUS_PROBE_DEFAULT); +} + +static int +iomux_attach(device_t dev) +{ + struct iomux_softc * sc; + + sc = device_get_softc(dev); + + if (bus_alloc_resources(dev, imx_iomux_spec, &sc->sc_res)) { + device_printf(dev, "could not allocate resources\n"); + return (ENXIO); + } + + iomuxsc = sc; + + /* + * XXX: place to fetch all info about pinmuxing from loader data + * (FDT blob) and apply. Loader (1st one) must care about + * device-to-device difference. + */ + + return (0); +} + +static void +iomux_set_function_sub(struct iomux_softc *sc, uint32_t pin, uint32_t fn) +{ + bus_size_t mux_ctl_reg = IOMUX_PIN_TO_MUX_ADDRESS(pin); + + if (mux_ctl_reg != IOMUX_MUX_NONE) + IOMUX_WRITE(sc, mux_ctl_reg, fn); +} + +void +iomux_set_function(unsigned int pin, unsigned int fn) +{ + + if (iomuxsc == NULL) + return; + iomux_set_function_sub(iomuxsc, pin, fn); +} + +static void +iomux_set_pad_sub(struct iomux_softc *sc, uint32_t pin, uint32_t config) +{ + bus_size_t pad_ctl_reg = IOMUX_PIN_TO_PAD_ADDRESS(pin); + + if (pad_ctl_reg != IOMUX_PAD_NONE) + IOMUX_WRITE(sc, pad_ctl_reg, config); +} + +void +iomux_set_pad(unsigned int pin, unsigned int config) +{ + + if (iomuxsc == NULL) + return; + iomux_set_pad_sub(iomuxsc, pin, config); +} + +#ifdef notyet +void +iomux_set_input(unsigned int input, unsigned int config) +{ + bus_size_t input_ctl_reg = input; + + bus_space_write_4(iomuxsc->iomux_memt, iomuxsc->iomux_memh, + input_ctl_reg, config); +} +#endif + +void +iomux_mux_config(const struct iomux_conf *conflist) +{ + int i; + + if (iomuxsc == NULL) + return; + for (i = 0; conflist[i].pin != IOMUX_CONF_EOT; i++) { + iomux_set_pad_sub(iomuxsc, conflist[i].pin, conflist[i].pad); + iomux_set_function_sub(iomuxsc, conflist[i].pin, + conflist[i].mux); + } +} + +#ifdef notyet +void +iomux_input_config(const struct iomux_input_conf *conflist) +{ + int i; + + if (iomuxsc == NULL) + return; + for (i = 0; conflist[i].inout != -1; i++) { + iomux_set_inout(iomuxsc, conflist[i].inout, + conflist[i].inout_mode); + } +} +#endif + +static device_method_t imx_iomux_methods[] = { + DEVMETHOD(device_probe, iomux_probe), + DEVMETHOD(device_attach, iomux_attach), + + DEVMETHOD_END +}; + +static driver_t imx_iomux_driver = { + "imx_iomux", + imx_iomux_methods, + sizeof(struct iomux_softc), +}; + +static devclass_t imx_iomux_devclass; + +EARLY_DRIVER_MODULE(imx_iomux, simplebus, imx_iomux_driver, + imx_iomux_devclass, 0, 0, BUS_PASS_BUS - 1); + diff --git a/sys/arm/freescale/imx/imx51_iomuxreg.h b/sys/arm/freescale/imx/imx51_iomuxreg.h new file mode 100644 index 0000000..f965b32 --- /dev/null +++ b/sys/arm/freescale/imx/imx51_iomuxreg.h @@ -0,0 +1,761 @@ +/* + * This file was generated automatically from PDF file by mkiomuxreg_imx51.rb + * + */ + +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by Oleksandr Rybalko + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _IMX51_IOMUXREG_H +#define _IMX51_IOMUXREG_H + +#define IOMUXC_MUX_CTL 0x001c /* multiplex control */ +#define IOMUX_CONFIG_SION (1 << 4) +#define IOMUX_CONFIG_ALT0 (0) +#define IOMUX_CONFIG_ALT1 (1) +#define IOMUX_CONFIG_ALT2 (2) +#define IOMUX_CONFIG_ALT3 (3) +#define IOMUX_CONFIG_ALT4 (4) +#define IOMUX_CONFIG_ALT5 (5) +#define IOMUX_CONFIG_ALT6 (6) +#define IOMUX_CONFIG_ALT7 (7) +#define IOMUXC_PAD_CTL 0x03f0 /* pad control */ +#define PAD_CTL_HVE (1 << 13) +#define PAD_CTL_DDR_INPUT (1 << 9) +#define PAD_CTL_HYS (1 << 8) +#define PAD_CTL_PKE (1 << 7) +#define PAD_CTL_PUE (1 << 6) +#define PAD_CTL_PULL (PAD_CTL_PKE|PAD_CTL_PUE) +#define PAD_CTL_KEEPER (PAD_CTL_PKE|0) +#define PAD_CTL_PUS_100K_PD (0x0 << 4) +#define PAD_CTL_PUS_47K_PU (0x1 << 4) +#define PAD_CTL_PUS_100K_PU (0x2 << 4) +#define PAD_CTL_PUS_22K_PU (0x3 << 4) +#define PAD_CTL_ODE (1 << 3) /* opendrain */ +#define PAD_CTL_DSE_LOW (0x0 << 1) +#define PAD_CTL_DSE_MID (0x1 << 1) +#define PAD_CTL_DSE_HIGH (0x2 << 1) +#define PAD_CTL_DSE_MAX (0x3 << 1) +#define PAD_CTL_SRE (1 << 0) +#define IOMUXC_INPUT_CTL 0x08c4 /* input control */ +#define INPUT_DAISY_0 0 +#define INPUT_DAISY_1 1 +#define INPUT_DAISY_2 2 +#define INPUT_DAISY_3 3 +#define INPUT_DAISY_4 4 +#define INPUT_DAISY_5 5 +#define INPUT_DAISY_6 6 +#define INPUT_DAISY_7 7 + +/* + * IOMUX index + */ +#define IOMUX_PIN_TO_MUX_ADDRESS(pin) (((pin) >> 16) & 0xffff) +#define IOMUX_PIN_TO_PAD_ADDRESS(pin) (((pin) >> 0) & 0xffff) + +#define IOMUX_PIN(mux_adr, pad_adr) \ + (((mux_adr) << 16) | (((pad_adr) << 0))) +#define IOMUX_MUX_NONE 0xffff +#define IOMUX_PAD_NONE 0xffff + +/* register offset address */ +#define IOMUXC_GPR0 0x0000 +#define IOMUXC_GPR1 0x0004 +#define IOMUXC_OBSERVE_MUX_0 0x0008 +#define IOMUXC_OBSERVE_MUX_1 0x000c +#define IOMUXC_OBSERVE_MUX_2 0x0010 +#define IOMUXC_OBSERVE_MUX_3 0x0014 +#define IOMUXC_OBSERVE_MUX_4 0x0018 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_DA0 0x001c +#define IOMUXC_SW_MUX_CTL_PAD_EIM_DA1 0x0020 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_DA2 0x0024 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_DA3 0x0028 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_DA4 0x002c +#define IOMUXC_SW_MUX_CTL_PAD_EIM_DA5 0x0030 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_DA6 0x0034 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_DA7 0x0038 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_DA8 0x003c +#define IOMUXC_SW_MUX_CTL_PAD_EIM_DA9 0x0040 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_DA10 0x0044 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_DA11 0x0048 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_DA12 0x004c +#define IOMUXC_SW_MUX_CTL_PAD_EIM_DA13 0x0050 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_DA14 0x0054 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_DA15 0x0058 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_D16 0x005c +#define IOMUXC_SW_MUX_CTL_PAD_EIM_D17 0x0060 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_D18 0x0064 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_D19 0x0068 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_D20 0x006c +#define IOMUXC_SW_MUX_CTL_PAD_EIM_D21 0x0070 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_D22 0x0074 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_D23 0x0078 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_D24 0x007c +#define IOMUXC_SW_MUX_CTL_PAD_EIM_D25 0x0080 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_D26 0x0084 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_D27 0x0088 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_D28 0x008c +#define IOMUXC_SW_MUX_CTL_PAD_EIM_D29 0x0090 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_D30 0x0094 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_D31 0x0098 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_A16 0x009c +#define IOMUXC_SW_MUX_CTL_PAD_EIM_A17 0x00a0 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_A18 0x00a4 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_A19 0x00a8 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_A20 0x00ac +#define IOMUXC_SW_MUX_CTL_PAD_EIM_A21 0x00b0 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_A22 0x00b4 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_A23 0x00b8 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_A24 0x00bc +#define IOMUXC_SW_MUX_CTL_PAD_EIM_A25 0x00c0 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_A26 0x00c4 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_A27 0x00c8 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_EB0 0x00cc +#define IOMUXC_SW_MUX_CTL_PAD_EIM_EB1 0x00d0 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_EB2 0x00d4 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_EB3 0x00d8 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_OE 0x00dc +#define IOMUXC_SW_MUX_CTL_PAD_EIM_CS0 0x00e0 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_CS1 0x00e4 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_CS2 0x00e8 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_CS3 0x00ec +#define IOMUXC_SW_MUX_CTL_PAD_EIM_CS4 0x00f0 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_CS5 0x00f4 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_DTACK 0x00f8 +#define IOMUXC_SW_MUX_CTL_PAD_EIM_LBA 0x00fc +#define IOMUXC_SW_MUX_CTL_PAD_EIM_CRE 0x0100 +#define IOMUXC_SW_MUX_CTL_PAD_DRAM_CS1 0x0104 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_WE_B 0x0108 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_RE_B 0x010c +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_ALE 0x0110 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_CLE 0x0114 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_WP_B 0x0118 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_RB0 0x011c +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_RB1 0x0120 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_RB2 0x0124 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_RB3 0x0128 +#define IOMUXC_SW_MUX_CTL_PAD_GPIO_NAND 0x012c +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_CS0 0x0130 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_CS1 0x0134 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_CS2 0x0138 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_CS3 0x013c +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_CS4 0x0140 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_CS5 0x0144 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_CS6 0x0148 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_CS7 0x014c +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_RDY_INT 0x0150 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_D15 0x0154 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_D14 0x0158 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_D13 0x015c +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_D12 0x0160 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_D11 0x0164 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_D10 0x0168 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_D9 0x016c +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_D8 0x0170 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_D7 0x0174 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_D6 0x0178 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_D5 0x017c +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_D4 0x0180 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_D3 0x0184 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_D2 0x0188 +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_D1 0x018c +#define IOMUXC_SW_MUX_CTL_PAD_NANDF_D0 0x0190 +#define IOMUXC_SW_MUX_CTL_PAD_CSI1_D8 0x0194 +#define IOMUXC_SW_MUX_CTL_PAD_CSI1_D9 0x0198 +#define IOMUXC_SW_MUX_CTL_PAD_CSI1_D10 0x019c +#define IOMUXC_SW_MUX_CTL_PAD_CSI1_D11 0x01a0 +#define IOMUXC_SW_MUX_CTL_PAD_CSI1_D12 0x01a4 +#define IOMUXC_SW_MUX_CTL_PAD_CSI1_D13 0x01a8 +#define IOMUXC_SW_MUX_CTL_PAD_CSI1_D14 0x01ac +#define IOMUXC_SW_MUX_CTL_PAD_CSI1_D15 0x01b0 +#define IOMUXC_SW_MUX_CTL_PAD_CSI1_D16 0x01b4 +#define IOMUXC_SW_MUX_CTL_PAD_CSI1_D17 0x01b8 +#define IOMUXC_SW_MUX_CTL_PAD_CSI1_D18 0x01bc +#define IOMUXC_SW_MUX_CTL_PAD_CSI1_D19 0x01c0 +#define IOMUXC_SW_MUX_CTL_PAD_CSI1_VSYNC 0x01c4 +#define IOMUXC_SW_MUX_CTL_PAD_CSI1_HSYNC 0x01c8 +#define IOMUXC_SW_MUX_CTL_PAD_CSI2_D12 0x01cc +#define IOMUXC_SW_MUX_CTL_PAD_CSI2_D13 0x01d0 +#define IOMUXC_SW_MUX_CTL_PAD_CSI2_D14 0x01d4 +#define IOMUXC_SW_MUX_CTL_PAD_CSI2_D15 0x01d8 +#define IOMUXC_SW_MUX_CTL_PAD_CSI2_D16 0x01dc +#define IOMUXC_SW_MUX_CTL_PAD_CSI2_D17 0x01e0 +#define IOMUXC_SW_MUX_CTL_PAD_CSI2_D18 0x01e4 +#define IOMUXC_SW_MUX_CTL_PAD_CSI2_D19 0x01e8 +#define IOMUXC_SW_MUX_CTL_PAD_CSI2_VSYNC 0x01ec +#define IOMUXC_SW_MUX_CTL_PAD_CSI2_HSYNC 0x01f0 +#define IOMUXC_SW_MUX_CTL_PAD_CSI2_PIXCLK 0x01f4 +#define IOMUXC_SW_MUX_CTL_PAD_I2C1_CLK 0x01f8 +#define IOMUXC_SW_MUX_CTL_PAD_I2C1_DAT 0x01fc +#define IOMUXC_SW_MUX_CTL_PAD_AUD3_BB_TXD 0x0200 +#define IOMUXC_SW_MUX_CTL_PAD_AUD3_BB_RXD 0x0204 +#define IOMUXC_SW_MUX_CTL_PAD_AUD3_BB_CK 0x0208 +#define IOMUXC_SW_MUX_CTL_PAD_AUD3_BB_FS 0x020c +#define IOMUXC_SW_MUX_CTL_PAD_CSPI1_MOSI 0x0210 +#define IOMUXC_SW_MUX_CTL_PAD_CSPI1_MISO 0x0214 +#define IOMUXC_SW_MUX_CTL_PAD_CSPI1_SS0 0x0218 +#define IOMUXC_SW_MUX_CTL_PAD_CSPI1_SS1 0x021c +#define IOMUXC_SW_MUX_CTL_PAD_CSPI1_RDY 0x0220 +#define IOMUXC_SW_MUX_CTL_PAD_CSPI1_SCLK 0x0224 +#define IOMUXC_SW_MUX_CTL_PAD_UART1_RXD 0x0228 +#define IOMUXC_SW_MUX_CTL_PAD_UART1_TXD 0x022c +#define IOMUXC_SW_MUX_CTL_PAD_UART1_RTS 0x0230 +#define IOMUXC_SW_MUX_CTL_PAD_UART1_CTS 0x0234 +#define IOMUXC_SW_MUX_CTL_PAD_UART2_RXD 0x0238 +#define IOMUXC_SW_MUX_CTL_PAD_UART2_TXD 0x023c +#define IOMUXC_SW_MUX_CTL_PAD_UART3_RXD 0x0240 +#define IOMUXC_SW_MUX_CTL_PAD_UART3_TXD 0x0244 +#define IOMUXC_SW_MUX_CTL_PAD_OWIRE_LINE 0x0248 +#define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW0 0x024c +#define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW1 0x0250 +#define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW2 0x0254 +#define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW3 0x0258 +#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL0 0x025c +#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL1 0x0260 +#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL2 0x0264 +#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL3 0x0268 +#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL4 0x026c +#define IOMUXC_SW_MUX_CTL_PAD_KEY_COL5 0x0270 +#define IOMUXC_SW_MUX_CTL_PAD_JTAG_DE_B 0x0274 +#define IOMUXC_SW_MUX_CTL_PAD_USBH1_CLK 0x0278 +#define IOMUXC_SW_MUX_CTL_PAD_USBH1_DIR 0x027c +#define IOMUXC_SW_MUX_CTL_PAD_USBH1_STP 0x0280 +#define IOMUXC_SW_MUX_CTL_PAD_USBH1_NXT 0x0284 +#define IOMUXC_SW_MUX_CTL_PAD_USBH1_DATA0 0x0288 +#define IOMUXC_SW_MUX_CTL_PAD_USBH1_DATA1 0x028c +#define IOMUXC_SW_MUX_CTL_PAD_USBH1_DATA2 0x0290 +#define IOMUXC_SW_MUX_CTL_PAD_USBH1_DATA3 0x0294 +#define IOMUXC_SW_MUX_CTL_PAD_USBH1_DATA4 0x0298 +#define IOMUXC_SW_MUX_CTL_PAD_USBH1_DATA5 0x029c +#define IOMUXC_SW_MUX_CTL_PAD_USBH1_DATA6 0x02a0 +#define IOMUXC_SW_MUX_CTL_PAD_USBH1_DATA7 0x02a4 +#define IOMUXC_SW_MUX_CTL_PAD_DI1_PIN11 0x02a8 +#define IOMUXC_SW_MUX_CTL_PAD_DI1_PIN12 0x02ac +#define IOMUXC_SW_MUX_CTL_PAD_DI1_PIN13 0x02b0 +#define IOMUXC_SW_MUX_CTL_PAD_DI1_D0_CS 0x02b4 +#define IOMUXC_SW_MUX_CTL_PAD_DI1_D1_CS 0x02b8 +#define IOMUXC_SW_MUX_CTL_PAD_DISPB2_SER_DIN 0x02bc +#define IOMUXC_SW_MUX_CTL_PAD_DISPB2_SER_DIO 0x02c0 +#define IOMUXC_SW_MUX_CTL_PAD_DISPB2_SER_CLK 0x02c4 +#define IOMUXC_SW_MUX_CTL_PAD_DISPB2_SER_RS 0x02c8 +#define IOMUXC_SW_MUX_CTL_PAD_DISP1_DAT0 0x02cc +#define IOMUXC_SW_MUX_CTL_PAD_DISP1_DAT1 0x02d0 +#define IOMUXC_SW_MUX_CTL_PAD_DISP1_DAT2 0x02d4 +#define IOMUXC_SW_MUX_CTL_PAD_DISP1_DAT3 0x02d8 +#define IOMUXC_SW_MUX_CTL_PAD_DISP1_DAT4 0x02dc +#define IOMUXC_SW_MUX_CTL_PAD_DISP1_DAT5 0x02e0 +#define IOMUXC_SW_MUX_CTL_PAD_DISP1_DAT6 0x02e4 +#define IOMUXC_SW_MUX_CTL_PAD_DISP1_DAT7 0x02e8 +#define IOMUXC_SW_MUX_CTL_PAD_DISP1_DAT8 0x02ec +#define IOMUXC_SW_MUX_CTL_PAD_DISP1_DAT9 0x02f0 +#define IOMUXC_SW_MUX_CTL_PAD_DISP1_DAT10 0x02f4 +#define IOMUXC_SW_MUX_CTL_PAD_DISP1_DAT11 0x02f8 +#define IOMUXC_SW_MUX_CTL_PAD_DISP1_DAT12 0x02fc +#define IOMUXC_SW_MUX_CTL_PAD_DISP1_DAT13 0x0300 +#define IOMUXC_SW_MUX_CTL_PAD_DISP1_DAT14 0x0304 +#define IOMUXC_SW_MUX_CTL_PAD_DISP1_DAT15 0x0308 +#define IOMUXC_SW_MUX_CTL_PAD_DISP1_DAT16 0x030c +#define IOMUXC_SW_MUX_CTL_PAD_DISP1_DAT17 0x0310 +#define IOMUXC_SW_MUX_CTL_PAD_DISP1_DAT18 0x0314 +#define IOMUXC_SW_MUX_CTL_PAD_DISP1_DAT19 0x0318 +#define IOMUXC_SW_MUX_CTL_PAD_DISP1_DAT20 0x031c +#define IOMUXC_SW_MUX_CTL_PAD_DISP1_DAT21 0x0320 +#define IOMUXC_SW_MUX_CTL_PAD_DISP1_DAT22 0x0324 +#define IOMUXC_SW_MUX_CTL_PAD_DISP1_DAT23 0x0328 +#define IOMUXC_SW_MUX_CTL_PAD_DI1_PIN3 0x032c +#define IOMUXC_SW_MUX_CTL_PAD_DI1_PIN2 0x0330 +#define IOMUXC_SW_MUX_CTL_PAD_DI_GP1 0x0334 +#define IOMUXC_SW_MUX_CTL_PAD_DI_GP2 0x0338 +#define IOMUXC_SW_MUX_CTL_PAD_DI_GP3 0x033c +#define IOMUXC_SW_MUX_CTL_PAD_DI2_PIN4 0x0340 +#define IOMUXC_SW_MUX_CTL_PAD_DI2_PIN2 0x0344 +#define IOMUXC_SW_MUX_CTL_PAD_DI2_PIN3 0x0348 +#define IOMUXC_SW_MUX_CTL_PAD_DI2_DISP_CLK 0x034c +#define IOMUXC_SW_MUX_CTL_PAD_DI_GP4 0x0350 +#define IOMUXC_SW_MUX_CTL_PAD_DISP2_DAT0 0x0354 +#define IOMUXC_SW_MUX_CTL_PAD_DISP2_DAT1 0x0358 +#define IOMUXC_SW_MUX_CTL_PAD_DISP2_DAT2 0x035c +#define IOMUXC_SW_MUX_CTL_PAD_DISP2_DAT3 0x0360 +#define IOMUXC_SW_MUX_CTL_PAD_DISP2_DAT4 0x0364 +#define IOMUXC_SW_MUX_CTL_PAD_DISP2_DAT5 0x0368 +#define IOMUXC_SW_MUX_CTL_PAD_DISP2_DAT6 0x036c +#define IOMUXC_SW_MUX_CTL_PAD_DISP2_DAT7 0x0370 +#define IOMUXC_SW_MUX_CTL_PAD_DISP2_DAT8 0x0374 +#define IOMUXC_SW_MUX_CTL_PAD_DISP2_DAT9 0x0378 +#define IOMUXC_SW_MUX_CTL_PAD_DISP2_DAT10 0x037c +#define IOMUXC_SW_MUX_CTL_PAD_DISP2_DAT11 0x0380 +#define IOMUXC_SW_MUX_CTL_PAD_DISP2_DAT12 0x0384 +#define IOMUXC_SW_MUX_CTL_PAD_DISP2_DAT13 0x0388 +#define IOMUXC_SW_MUX_CTL_PAD_DISP2_DAT14 0x038c +#define IOMUXC_SW_MUX_CTL_PAD_DISP2_DAT15 0x0390 +#define IOMUXC_SW_MUX_CTL_PAD_SD1_CMD 0x0394 +#define IOMUXC_SW_MUX_CTL_PAD_SD1_CLK 0x0398 +#define IOMUXC_SW_MUX_CTL_PAD_SD1_DATA0 0x039c +#define IOMUXC_SW_MUX_CTL_PAD_SD1_DATA1 0x03a0 +#define IOMUXC_SW_MUX_CTL_PAD_SD1_DATA2 0x03a4 +#define IOMUXC_SW_MUX_CTL_PAD_SD1_DATA3 0x03a8 +#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_0 0x03ac +#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_1 0x03b0 +#define IOMUXC_SW_MUX_CTL_PAD_SD2_CMD 0x03b4 +#define IOMUXC_SW_MUX_CTL_PAD_SD2_CLK 0x03b8 +#define IOMUXC_SW_MUX_CTL_PAD_SD2_DATA0 0x03bc +#define IOMUXC_SW_MUX_CTL_PAD_SD2_DATA1 0x03c0 +#define IOMUXC_SW_MUX_CTL_PAD_SD2_DATA2 0x03c4 +#define IOMUXC_SW_MUX_CTL_PAD_SD2_DATA3 0x03c8 +#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_2 0x03cc +#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_3 0x03d0 +#define IOMUXC_SW_MUX_CTL_PAD_PMIC_INT_REQ 0x03d4 +#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_4 0x03d8 +#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_5 0x03dc +#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_6 0x03e0 +#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_7 0x03e4 +#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_8 0x03e8 +#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_9 0x03ec +#define IOMUXC_SW_PAD_CTL_PAD_EIM_D16 0x03f0 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_D17 0x03f4 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_D18 0x03f8 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_D19 0x03fc +#define IOMUXC_SW_PAD_CTL_PAD_EIM_D20 0x0400 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_D21 0x0404 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_D22 0x0408 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_D23 0x040c +#define IOMUXC_SW_PAD_CTL_PAD_EIM_D24 0x0410 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_D25 0x0414 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_D26 0x0418 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_D27 0x041c +#define IOMUXC_SW_PAD_CTL_PAD_EIM_D28 0x0420 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_D29 0x0424 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_D30 0x0428 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_D31 0x042c +#define IOMUXC_SW_PAD_CTL_PAD_EIM_A16 0x0430 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_A17 0x0434 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_A18 0x0438 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_A19 0x043c +#define IOMUXC_SW_PAD_CTL_PAD_EIM_A20 0x0440 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_A21 0x0444 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_A22 0x0448 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_A23 0x044c +#define IOMUXC_SW_PAD_CTL_PAD_EIM_A24 0x0450 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_A25 0x0454 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_A26 0x0458 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_A27 0x045c +#define IOMUXC_SW_PAD_CTL_PAD_EIM_EB0 0x0460 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_EB1 0x0464 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_EB2 0x0468 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_EB3 0x046c +#define IOMUXC_SW_PAD_CTL_PAD_EIM_OE 0x0470 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_CS0 0x0474 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_CS1 0x0478 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_CS2 0x047c +#define IOMUXC_SW_PAD_CTL_PAD_EIM_CS3 0x0480 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_CS4 0x0484 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_CS5 0x0488 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_DTACK 0x048c +#define IOMUXC_SW_PAD_CTL_PAD_EIM_WAIT 0x0490 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_LBA 0x0494 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_BCLK 0x0498 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_RW 0x049c +#define IOMUXC_SW_PAD_CTL_PAD_EIM_CRE 0x04a0 +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_RAS 0x04a4 +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_CAS 0x04a8 +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDWE 0x04ac +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCKE0 0x04b0 +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCKE1 0x04b4 +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK 0x04b8 +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS0 0x04bc +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS1 0x04c0 +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS2 0x04c4 +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS3 0x04c8 +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_CS0 0x04cc +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_CS1 0x04d0 +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM0 0x04d4 +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM1 0x04d8 +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM2 0x04dc +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM3 0x04e0 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_WE_B 0x04e4 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_RE_B 0x04e8 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_ALE 0x04ec +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_CLE 0x04f0 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_WP_B 0x04f4 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_RB0 0x04f8 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_RB1 0x04fc +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_RB2 0x0500 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_RB3 0x0504 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_SDBA2 0x0508 +#define IOMUXC_SW_PAD_CTL_PAD_EIM_SDODT1 0x050c +#define IOMUXC_SW_PAD_CTL_PAD_EIM_SDODT0 0x0510 +#define IOMUXC_SW_PAD_CTL_PAD_GPIO_NAND 0x0514 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_CS0 0x0518 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_CS1 0x051c +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_CS2 0x0520 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_CS3 0x0524 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_CS4 0x0528 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_CS5 0x052c +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_CS6 0x0530 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_CS7 0x0534 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_RDY_INT 0x0538 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_D15 0x053c +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_D14 0x0540 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_D13 0x0544 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_D12 0x0548 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_D11 0x054c +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_D10 0x0550 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_D9 0x0554 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_D8 0x0558 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_D7 0x055c +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_D6 0x0560 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_D5 0x0564 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_D4 0x0568 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_D3 0x056c +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_D2 0x0570 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_D1 0x0574 +#define IOMUXC_SW_PAD_CTL_PAD_NANDF_D0 0x0578 +#define IOMUXC_SW_PAD_CTL_PAD_CSI1_D8 0x057c +#define IOMUXC_SW_PAD_CTL_PAD_CSI1_D9 0x0580 +#define IOMUXC_SW_PAD_CTL_PAD_CSI1_D10 0x0584 +#define IOMUXC_SW_PAD_CTL_PAD_CSI1_D11 0x0588 +#define IOMUXC_SW_PAD_CTL_PAD_CSI1_D12 0x058c +#define IOMUXC_SW_PAD_CTL_PAD_CSI1_D13 0x0590 +#define IOMUXC_SW_PAD_CTL_PAD_CSI1_D14 0x0594 +#define IOMUXC_SW_PAD_CTL_PAD_CSI1_D15 0x0598 +#define IOMUXC_SW_PAD_CTL_PAD_CSI1_D16 0x059c +#define IOMUXC_SW_PAD_CTL_PAD_CSI1_D17 0x05a0 +#define IOMUXC_SW_PAD_CTL_PAD_CSI1_D18 0x05a4 +#define IOMUXC_SW_PAD_CTL_PAD_CSI1_D19 0x05a8 +#define IOMUXC_SW_PAD_CTL_PAD_CSI1_VSYNC 0x05ac +#define IOMUXC_SW_PAD_CTL_PAD_CSI1_HSYNC 0x05b0 +#define IOMUXC_SW_PAD_CTL_PAD_CSI1_PIXCLK 0x05b4 +#define IOMUXC_SW_PAD_CTL_PAD_CSI1_MCLK 0x05b8 +#define IOMUXC_SW_PAD_CTL_PAD_CSI2_D12 0x05bc +#define IOMUXC_SW_PAD_CTL_PAD_CSI2_D13 0x05c0 +#define IOMUXC_SW_PAD_CTL_PAD_CSI2_D14 0x05c4 +#define IOMUXC_SW_PAD_CTL_PAD_CSI2_D15 0x05c8 +#define IOMUXC_SW_PAD_CTL_PAD_CSI2_D16 0x05cc +#define IOMUXC_SW_PAD_CTL_PAD_CSI2_D17 0x05d0 +#define IOMUXC_SW_PAD_CTL_PAD_CSI2_D18 0x05d4 +#define IOMUXC_SW_PAD_CTL_PAD_CSI2_D19 0x05d8 +#define IOMUXC_SW_PAD_CTL_PAD_CSI2_VSYNC 0x05dc +#define IOMUXC_SW_PAD_CTL_PAD_CSI2_HSYNC 0x05e0 +#define IOMUXC_SW_PAD_CTL_PAD_CSI2_PIXCLK 0x05e4 +#define IOMUXC_SW_PAD_CTL_PAD_I2C1_CLK 0x05e8 +#define IOMUXC_SW_PAD_CTL_PAD_I2C1_DAT 0x05ec +#define IOMUXC_SW_PAD_CTL_PAD_AUD3_BB_TXD 0x05f0 +#define IOMUXC_SW_PAD_CTL_PAD_AUD3_BB_RXD 0x05f4 +#define IOMUXC_SW_PAD_CTL_PAD_AUD3_BB_CK 0x05f8 +#define IOMUXC_SW_PAD_CTL_PAD_AUD3_BB_FS 0x05fc +#define IOMUXC_SW_PAD_CTL_PAD_CSPI1_MOSI 0x0600 +#define IOMUXC_SW_PAD_CTL_PAD_CSPI1_MISO 0x0604 +#define IOMUXC_SW_PAD_CTL_PAD_CSPI1_SS0 0x0608 +#define IOMUXC_SW_PAD_CTL_PAD_CSPI1_SS1 0x060c +#define IOMUXC_SW_PAD_CTL_PAD_CSPI1_RDY 0x0610 +#define IOMUXC_SW_PAD_CTL_PAD_CSPI1_SCLK 0x0614 +#define IOMUXC_SW_PAD_CTL_PAD_UART1_RXD 0x0618 +#define IOMUXC_SW_PAD_CTL_PAD_UART1_TXD 0x061c +#define IOMUXC_SW_PAD_CTL_PAD_UART1_RTS 0x0620 +#define IOMUXC_SW_PAD_CTL_PAD_UART1_CTS 0x0624 +#define IOMUXC_SW_PAD_CTL_PAD_UART2_RXD 0x0628 +#define IOMUXC_SW_PAD_CTL_PAD_UART2_TXD 0x062c +#define IOMUXC_SW_PAD_CTL_PAD_UART3_RXD 0x0630 +#define IOMUXC_SW_PAD_CTL_PAD_UART3_TXD 0x0634 +#define IOMUXC_SW_PAD_CTL_PAD_OWIRE_LINE 0x0638 +#define IOMUXC_SW_PAD_CTL_PAD_KEY_ROW0 0x063c +#define IOMUXC_SW_PAD_CTL_PAD_KEY_ROW1 0x0640 +#define IOMUXC_SW_PAD_CTL_PAD_KEY_ROW2 0x0644 +#define IOMUXC_SW_PAD_CTL_PAD_KEY_ROW3 0x0648 +#define IOMUXC_SW_PAD_CTL_PAD_KEY_COL0 0x064c +#define IOMUXC_SW_PAD_CTL_PAD_KEY_COL1 0x0650 +#define IOMUXC_SW_PAD_CTL_PAD_KEY_COL2 0x0654 +#define IOMUXC_SW_PAD_CTL_PAD_KEY_COL3 0x0658 +#define IOMUXC_SW_PAD_CTL_PAD_KEY_COL4 0x065c +#define IOMUXC_SW_PAD_CTL_PAD_KEY_COL5 0x0660 +#define IOMUXC_SW_PAD_CTL_PAD_JTAG_TCK 0x0664 +#define IOMUXC_SW_PAD_CTL_PAD_JTAG_TMS 0x0668 +#define IOMUXC_SW_PAD_CTL_PAD_JTAG_TDI 0x066c +#define IOMUXC_SW_PAD_CTL_PAD_JTAG_TRSTB 0x0670 +#define IOMUXC_SW_PAD_CTL_PAD_JTAG_MOD 0x0674 +#define IOMUXC_SW_PAD_CTL_PAD_USBH1_CLK 0x0678 +#define IOMUXC_SW_PAD_CTL_PAD_USBH1_DIR 0x067c +#define IOMUXC_SW_PAD_CTL_PAD_USBH1_STP 0x0680 +#define IOMUXC_SW_PAD_CTL_PAD_USBH1_NXT 0x0684 +#define IOMUXC_SW_PAD_CTL_PAD_USBH1_DATA0 0x0688 +#define IOMUXC_SW_PAD_CTL_PAD_USBH1_DATA1 0x068c +#define IOMUXC_SW_PAD_CTL_PAD_USBH1_DATA2 0x0690 +#define IOMUXC_SW_PAD_CTL_PAD_USBH1_DATA3 0x0694 +#define IOMUXC_SW_PAD_CTL_PAD_USBH1_DATA4 0x0698 +#define IOMUXC_SW_PAD_CTL_PAD_USBH1_DATA5 0x069c +#define IOMUXC_SW_PAD_CTL_PAD_USBH1_DATA6 0x06a0 +#define IOMUXC_SW_PAD_CTL_PAD_USBH1_DATA7 0x06a4 +#define IOMUXC_SW_PAD_CTL_PAD_DI1_PIN11 0x06a8 +#define IOMUXC_SW_PAD_CTL_PAD_DI1_PIN12 0x06ac +#define IOMUXC_SW_PAD_CTL_PAD_DI1_PIN13 0x06b0 +#define IOMUXC_SW_PAD_CTL_PAD_DI1_D0_CS 0x06b4 +#define IOMUXC_SW_PAD_CTL_PAD_DI1_D1_CS 0x06b8 +#define IOMUXC_SW_PAD_CTL_PAD_DISPB2_SER_DIN 0x06bc +#define IOMUXC_SW_PAD_CTL_PAD_DISPB2_SER_DIO 0x06c0 +#define IOMUXC_SW_PAD_CTL_PAD_DISPB2_SER_CLK 0x06c4 +#define IOMUXC_SW_PAD_CTL_PAD_DISPB2_SER_RS 0x06c8 +#define IOMUXC_SW_PAD_CTL_PAD_DISP1_DAT0 0x06cc +#define IOMUXC_SW_PAD_CTL_PAD_DISP1_DAT1 0x06d0 +#define IOMUXC_SW_PAD_CTL_PAD_DISP1_DAT2 0x06d4 +#define IOMUXC_SW_PAD_CTL_PAD_DISP1_DAT3 0x06d8 +#define IOMUXC_SW_PAD_CTL_PAD_DISP1_DAT4 0x06dc +#define IOMUXC_SW_PAD_CTL_PAD_DISP1_DAT5 0x06e0 +#define IOMUXC_SW_PAD_CTL_PAD_DISP1_DAT6 0x06e4 +#define IOMUXC_SW_PAD_CTL_PAD_DISP1_DAT7 0x06e8 +#define IOMUXC_SW_PAD_CTL_PAD_DISP1_DAT8 0x06ec +#define IOMUXC_SW_PAD_CTL_PAD_DISP1_DAT9 0x06f0 +#define IOMUXC_SW_PAD_CTL_PAD_DISP1_DAT10 0x06f4 +#define IOMUXC_SW_PAD_CTL_PAD_DISP1_DAT11 0x06f8 +#define IOMUXC_SW_PAD_CTL_PAD_DISP1_DAT12 0x06fc +#define IOMUXC_SW_PAD_CTL_PAD_DISP1_DAT13 0x0700 +#define IOMUXC_SW_PAD_CTL_PAD_DISP1_DAT14 0x0704 +#define IOMUXC_SW_PAD_CTL_PAD_DISP1_DAT15 0x0708 +#define IOMUXC_SW_PAD_CTL_PAD_DISP1_DAT16 0x070c +#define IOMUXC_SW_PAD_CTL_PAD_DISP1_DAT17 0x0710 +#define IOMUXC_SW_PAD_CTL_PAD_DISP1_DAT18 0x0714 +#define IOMUXC_SW_PAD_CTL_PAD_DISP1_DAT19 0x0718 +#define IOMUXC_SW_PAD_CTL_PAD_DISP1_DAT20 0x071c +#define IOMUXC_SW_PAD_CTL_PAD_DISP1_DAT21 0x0720 +#define IOMUXC_SW_PAD_CTL_PAD_DISP1_DAT22 0x0724 +#define IOMUXC_SW_PAD_CTL_PAD_DISP1_DAT23 0x0728 +#define IOMUXC_SW_PAD_CTL_PAD_DI1_PIN3 0x072c +#define IOMUXC_SW_PAD_CTL_PAD_DI1_DISP_CLK 0x0730 +#define IOMUXC_SW_PAD_CTL_PAD_DI1_PIN2 0x0734 +#define IOMUXC_SW_PAD_CTL_PAD_DI1_PIN15 0x0738 +#define IOMUXC_SW_PAD_CTL_PAD_DI_GP1 0x073c +#define IOMUXC_SW_PAD_CTL_PAD_DI_GP2 0x0740 +#define IOMUXC_SW_PAD_CTL_PAD_DI_GP3 0x0744 +#define IOMUXC_SW_PAD_CTL_PAD_DI2_PIN4 0x0748 +#define IOMUXC_SW_PAD_CTL_PAD_DI2_PIN2 0x074c +#define IOMUXC_SW_PAD_CTL_PAD_DI2_PIN3 0x0750 +#define IOMUXC_SW_PAD_CTL_PAD_DI2_DISP_CLK 0x0754 +#define IOMUXC_SW_PAD_CTL_PAD_DI_GP4 0x0758 +#define IOMUXC_SW_PAD_CTL_PAD_DISP2_DAT0 0x075c +#define IOMUXC_SW_PAD_CTL_PAD_DISP2_DAT1 0x0760 +#define IOMUXC_SW_PAD_CTL_PAD_DISP2_DAT2 0x0764 +#define IOMUXC_SW_PAD_CTL_PAD_DISP2_DAT3 0x0768 +#define IOMUXC_SW_PAD_CTL_PAD_DISP2_DAT4 0x076c +#define IOMUXC_SW_PAD_CTL_PAD_DISP2_DAT5 0x0770 +#define IOMUXC_SW_PAD_CTL_PAD_DISP2_DAT6 0x0774 +#define IOMUXC_SW_PAD_CTL_PAD_DISP2_DAT7 0x0778 +#define IOMUXC_SW_PAD_CTL_PAD_DISP2_DAT8 0x077c +#define IOMUXC_SW_PAD_CTL_PAD_DISP2_DAT9 0x0780 +#define IOMUXC_SW_PAD_CTL_PAD_DISP2_DAT10 0x0784 +#define IOMUXC_SW_PAD_CTL_PAD_DISP2_DAT11 0x0788 +#define IOMUXC_SW_PAD_CTL_PAD_DISP2_DAT12 0x078c +#define IOMUXC_SW_PAD_CTL_PAD_DISP2_DAT13 0x0790 +#define IOMUXC_SW_PAD_CTL_PAD_DISP2_DAT14 0x0794 +#define IOMUXC_SW_PAD_CTL_PAD_DISP2_DAT15 0x0798 +#define IOMUXC_SW_PAD_CTL_PAD_SD1_CMD 0x079c +#define IOMUXC_SW_PAD_CTL_PAD_SD1_CLK 0x07a0 +#define IOMUXC_SW_PAD_CTL_PAD_SD1_DATA0 0x07a4 +#define IOMUXC_SW_PAD_CTL_PAD_SD1_DATA1 0x07a8 +#define IOMUXC_SW_PAD_CTL_PAD_SD1_DATA2 0x07ac +#define IOMUXC_SW_PAD_CTL_PAD_SD1_DATA3 0x07b0 +#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_0 0x07b4 +#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_1 0x07b8 +#define IOMUXC_SW_PAD_CTL_PAD_SD2_CMD 0x07bc +#define IOMUXC_SW_PAD_CTL_PAD_SD2_CLK 0x07c0 +#define IOMUXC_SW_PAD_CTL_PAD_SD2_DATA0 0x07c4 +#define IOMUXC_SW_PAD_CTL_PAD_SD2_DATA1 0x07c8 +#define IOMUXC_SW_PAD_CTL_PAD_SD2_DATA2 0x07cc +#define IOMUXC_SW_PAD_CTL_PAD_SD2_DATA3 0x07d0 +#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_2 0x07d4 +#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_3 0x07d8 +#define IOMUXC_SW_PAD_CTL_PAD_RESET_IN_B 0x07dc +#define IOMUXC_SW_PAD_CTL_PAD_POR_B 0x07e0 +#define IOMUXC_SW_PAD_CTL_PAD_BOOT_MODE1 0x07e4 +#define IOMUXC_SW_PAD_CTL_PAD_BOOT_MODE0 0x07e8 +#define IOMUXC_SW_PAD_CTL_PAD_PMIC_RDY 0x07ec +#define IOMUXC_SW_PAD_CTL_PAD_CKIL 0x07f0 +#define IOMUXC_SW_PAD_CTL_PAD_PMIC_STBY_REQ 0x07f4 +#define IOMUXC_SW_PAD_CTL_PAD_PMIC_ON_REQ 0x07f8 +#define IOMUXC_SW_PAD_CTL_PAD_PMIC_INT_REQ 0x07fc +#define IOMUXC_SW_PAD_CTL_PAD_CLK_SS 0x0800 +#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_4 0x0804 +#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_5 0x0808 +#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_6 0x080c +#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_7 0x0810 +#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_8 0x0814 +#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_9 0x0818 +#define IOMUXC_SW_PAD_CTL_GRP_CSI2_PKE0 0x081c +#define IOMUXC_SW_PAD_CTL_GRP_DDRPKS 0x0820 +#define IOMUXC_SW_PAD_CTL_GRP_EIM_SR1 0x0824 +#define IOMUXC_SW_PAD_CTL_GRP_DISP2_PKE0 0x0828 +#define IOMUXC_SW_PAD_CTL_GRP_DRAM_B4 0x082c +#define IOMUXC_SW_PAD_CTL_GRP_INDDR 0x0830 +#define IOMUXC_SW_PAD_CTL_GRP_EIM_SR2 0x0834 +#define IOMUXC_SW_PAD_CTL_GRP_PKEDDR 0x0838 +#define IOMUXC_SW_PAD_CTL_GRP_DDR_A0 0x083c +#define IOMUXC_SW_PAD_CTL_GRP_EMI_PKE0 0x0840 +#define IOMUXC_SW_PAD_CTL_GRP_EIM_SR3 0x0844 +#define IOMUXC_SW_PAD_CTL_GRP_DDR_A1 0x0848 +#define IOMUXC_SW_PAD_CTL_GRP_DDRAPUS 0x084c +#define IOMUXC_SW_PAD_CTL_GRP_EIM_SR4 0x0850 +#define IOMUXC_SW_PAD_CTL_GRP_EMI_SR5 0x0854 +#define IOMUXC_SW_PAD_CTL_GRP_EMI_SR6 0x0858 +#define IOMUXC_SW_PAD_CTL_GRP_HYSDDR0 0x085c +#define IOMUXC_SW_PAD_CTL_GRP_CSI1_PKE0 0x0860 +#define IOMUXC_SW_PAD_CTL_GRP_HYSDDR1 0x0864 +#define IOMUXC_SW_PAD_CTL_GRP_DISP1_PKE0 0x0868 +#define IOMUXC_SW_PAD_CTL_GRP_HYSDDR2 0x086c +#define IOMUXC_SW_PAD_CTL_GRP_HVDDR 0x0870 +#define IOMUXC_SW_PAD_CTL_GRP_HYSDDR3 0x0874 +#define IOMUXC_SW_PAD_CTL_GRP_DRAM_SR_B0 0x0878 +#define IOMUXC_SW_PAD_CTL_GRP_DDRAPKS 0x087c +#define IOMUXC_SW_PAD_CTL_GRP_DRAM_SR_B1 0x0880 +#define IOMUXC_SW_PAD_CTL_GRP_DDRPUS 0x0884 +#define IOMUXC_SW_PAD_CTL_GRP_EIM_DS1 0x0888 +#define IOMUXC_SW_PAD_CTL_GRP_DRAM_SR_B2 0x088c +#define IOMUXC_SW_PAD_CTL_GRP_PKEADDR 0x0890 +#define IOMUXC_SW_PAD_CTL_GRP_EIM_DS2 0x0894 +#define IOMUXC_SW_PAD_CTL_GRP_EIM_DS3 0x0898 +#define IOMUXC_SW_PAD_CTL_GRP_DRAM_SR_B4 0x089c +#define IOMUXC_SW_PAD_CTL_GRP_INMODE1 0x08a0 +#define IOMUXC_SW_PAD_CTL_GRP_DRAM_B0 0x08a4 +#define IOMUXC_SW_PAD_CTL_GRP_EIM_DS4 0x08a8 +#define IOMUXC_SW_PAD_CTL_GRP_DRAM_B1 0x08ac +#define IOMUXC_SW_PAD_CTL_GRP_DDR_SR_A0 0x08b0 +#define IOMUXC_SW_PAD_CTL_GRP_EMI_DS5 0x08b4 +#define IOMUXC_SW_PAD_CTL_GRP_DRAM_B2 0x08b8 +#define IOMUXC_SW_PAD_CTL_GRP_DDR_SR_A1 0x08bc +#define IOMUXC_SW_PAD_CTL_GRP_EMI_DS6 0x08c0 +#define IOMUXC_AUDMUX_P4_INPUT_DA_AMX_SELECT_INPUT 0x08c4 +#define IOMUXC_AUDMUX_P4_INPUT_DB_AMX_SELECT_INPUT 0x08c8 +#define IOMUXC_AUDMUX_P4_INPUT_TXCLK_AMX_SELECT_INPUT 0x08cc +#define IOMUXC_AUDMUX_P4_INPUT_TXFS_AMX_SELECT_INPUT 0x08d0 +#define IOMUXC_AUDMUX_P5_INPUT_DA_AMX_SELECT_INPUT 0x08d4 +#define IOMUXC_AUDMUX_P5_INPUT_DB_AMX_SELECT_INPUT 0x08d8 +#define IOMUXC_AUDMUX_P5_INPUT_RXCLK_AMX_SELECT_INPUT 0x08dc +#define IOMUXC_AUDMUX_P5_INPUT_RXFS_AMX_SELECT_INPUT 0x08e0 +#define IOMUXC_AUDMUX_P5_INPUT_TXCLK_AMX_SELECT_INPUT 0x08e4 +#define IOMUXC_AUDMUX_P5_INPUT_TXFS_AMX_SELECT_INPUT 0x08e8 +#define IOMUXC_AUDMUX_P6_INPUT_DA_AMX_SELECT_INPUT 0x08ec +#define IOMUXC_AUDMUX_P6_INPUT_DB_AMX_SELECT_INPUT 0x08f0 +#define IOMUXC_AUDMUX_P6_INPUT_RXCLK_AMX_SELECT_INPUT 0x08f4 +#define IOMUXC_AUDMUX_P6_INPUT_RXFS_AMX_SELECT_INPUT 0x08f8 +#define IOMUXC_AUDMUX_P6_INPUT_TXCLK_AMX_SELECT_INPUT 0x08fc +#define IOMUXC_AUDMUX_P6_INPUT_TXFS_AMX_SELECT_INPUT 0x0900 +#define IOMUXC_CCM_IPP_DI0_CLK_SELECT_INPUT 0x0904 +#define IOMUXC_CCM_IPP_DI1_CLK_SELECT_INPUT 0x0908 +#define IOMUXC_CCM_PLL1_BYPASS_CLK_SELECT_INPUT 0x090c +#define IOMUXC_CCM_PLL2_BYPASS_CLK_SELECT_INPUT 0x0910 +#define IOMUXC_CSPI_IPP_CSPI_CLK_IN_SELECT_INPUT 0x0914 +#define IOMUXC_CSPI_IPP_IND_MISO_SELECT_INPUT 0x0918 +#define IOMUXC_CSPI_IPP_IND_MOSI_SELECT_INPUT 0x091c +#define IOMUXC_CSPI_IPP_IND_SS1_B_SELECT_INPUT 0x0920 +#define IOMUXC_CSPI_IPP_IND_SS2_B_SELECT_INPUT 0x0924 +#define IOMUXC_CSPI_IPP_IND_SS3_B_SELECT_INPUT 0x0928 +#define IOMUXC_DPLLIP1_L1T_TOG_EN_SELECT_INPUT 0x092c +#define IOMUXC_ECSPI2_IPP_IND_SS_B_1_SELECT_INPUT 0x0930 +#define IOMUXC_ECSPI2_IPP_IND_SS_B_3_SELECT_INPUT 0x0934 +#define IOMUXC_EMI_IPP_IND_RDY_INT_SELECT_INPUT 0x0938 +#define IOMUXC_ESDHC3_IPP_DAT0_IN_SELECT_INPUT 0x093c +#define IOMUXC_ESDHC3_IPP_DAT1_IN_SELECT_INPUT 0x0940 +#define IOMUXC_ESDHC3_IPP_DAT2_IN_SELECT_INPUT 0x0944 +#define IOMUXC_ESDHC3_IPP_DAT3_IN_SELECT_INPUT 0x0948 +#define IOMUXC_FEC_FEC_COL_SELECT_INPUT 0x094c +#define IOMUXC_FEC_FEC_CRS_SELECT_INPUT 0x0950 +#define IOMUXC_FEC_FEC_MDI_SELECT_INPUT 0x0954 +#define IOMUXC_FEC_FEC_RDATA_0_SELECT_INPUT 0x0958 +#define IOMUXC_FEC_FEC_RDATA_1_SELECT_INPUT 0x095c +#define IOMUXC_FEC_FEC_RDATA_2_SELECT_INPUT 0x0960 +#define IOMUXC_FEC_FEC_RDATA_3_SELECT_INPUT 0x0964 +#define IOMUXC_FEC_FEC_RX_CLK_SELECT_INPUT 0x0968 +#define IOMUXC_FEC_FEC_RX_DV_SELECT_INPUT 0x096c +#define IOMUXC_FEC_FEC_RX_ER_SELECT_INPUT 0x0970 +#define IOMUXC_FEC_FEC_TX_CLK_SELECT_INPUT 0x0974 +#define IOMUXC_GPIO3_IPP_IND_G_IN_1_SELECT_INPUT 0x0978 +#define IOMUXC_GPIO3_IPP_IND_G_IN_2_SELECT_INPUT 0x097c +#define IOMUXC_GPIO3_IPP_IND_G_IN_3_SELECT_INPUT 0x0980 +#define IOMUXC_GPIO3_IPP_IND_G_IN_4_SELECT_INPUT 0x0984 +#define IOMUXC_GPIO3_IPP_IND_G_IN_5_SELECT_INPUT 0x0988 +#define IOMUXC_GPIO3_IPP_IND_G_IN_6_SELECT_INPUT 0x098c +#define IOMUXC_GPIO3_IPP_IND_G_IN_7_SELECT_INPUT 0x0990 +#define IOMUXC_GPIO3_IPP_IND_G_IN_8_SELECT_INPUT 0x0994 +#define IOMUXC_GPIO3_IPP_IND_G_IN_12_SELECT_INPUT 0x0998 +#define IOMUXC_HSC_MIPI_MIX_PAR0_VSYNC_SELECT_INPUT 0x09a4 +#define IOMUXC_HSC_MIPI_MIX_PAR1_DI_WAIT_SELECT_INPUT 0x09a8 +#define IOMUXC_HSC_MIPI_MIX_PAR_SISG_TRIG_SELECT_INPUT 0x09ac +#define IOMUXC_I2C1_IPP_SCL_IN_SELECT_INPUT 0x09b0 +#define IOMUXC_I2C1_IPP_SDA_IN_SELECT_INPUT 0x09b4 +#define IOMUXC_I2C2_IPP_SCL_IN_SELECT_INPUT 0x09b8 +#define IOMUXC_I2C2_IPP_SDA_IN_SELECT_INPUT 0x09bc +#define IOMUXC_IPU_IPP_DI_0_IND_DISPB_SD_D_SELECT_INPUT 0x09c0 +#define IOMUXC_IPU_IPP_DI_1_IND_DISPB_SD_D_SELECT_INPUT 0x09c4 +#define IOMUXC_KPP_IPP_IND_COL_6_SELECT_INPUT 0x09c8 +#define IOMUXC_KPP_IPP_IND_COL_7_SELECT_INPUT 0x09cc +#define IOMUXC_KPP_IPP_IND_ROW_4_SELECT_INPUT 0x09d0 +#define IOMUXC_KPP_IPP_IND_ROW_5_SELECT_INPUT 0x09d4 +#define IOMUXC_KPP_IPP_IND_ROW_6_SELECT_INPUT 0x09d8 +#define IOMUXC_KPP_IPP_IND_ROW_7_SELECT_INPUT 0x09dc +#define IOMUXC_UART1_IPP_UART_RTS_B_SELECT_INPUT 0x09e0 +#define IOMUXC_UART1_IPP_UART_RXD_MUX_SELECT_INPUT 0x09e4 +#define IOMUXC_UART2_IPP_UART_RTS_B_SELECT_INPUT 0x09e8 +#define IOMUXC_UART2_IPP_UART_RXD_MUX_SELECT_INPUT 0x09ec +#define IOMUXC_UART3_IPP_UART_RTS_B_SELECT_INPUT 0x09f0 +#define IOMUXC_UART3_IPP_UART_RXD_MUX_SELECT_INPUT 0x09f4 +#define IOMUXC_USBOH3_IPP_IND_UH3_CLK_SELECT_INPUT 0x09f8 +#define IOMUXC_USBOH3_IPP_IND_UH3_DATA_0_SELECT_INPUT 0x09fc +#define IOMUXC_USBOH3_IPP_IND_UH3_DATA_1_SELECT_INPUT 0x0a00 +#define IOMUXC_USBOH3_IPP_IND_UH3_DATA_2_SELECT_INPUT 0x0a04 +#define IOMUXC_USBOH3_IPP_IND_UH3_DATA_3_SELECT_INPUT 0x0a08 +#define IOMUXC_USBOH3_IPP_IND_UH3_DATA_4_SELECT_INPUT 0x0a0c +#define IOMUXC_USBOH3_IPP_IND_UH3_DATA_5_SELECT_INPUT 0x0a10 +#define IOMUXC_USBOH3_IPP_IND_UH3_DATA_6_SELECT_INPUT 0x0a14 +#define IOMUXC_USBOH3_IPP_IND_UH3_DATA_7_SELECT_INPUT 0x0a18 +#define IOMUXC_USBOH3_IPP_IND_UH3_DIR_SELECT_INPUT 0x0a1c +#define IOMUXC_USBOH3_IPP_IND_UH3_NXT_SELECT_INPUT 0x0a20 +#define IOMUXC_USBOH3_IPP_IND_UH3_STP_SELECT_INPUT 0x0a24 + +/* MUX & PAD Control */ + +#define MUX_PIN(name) \ + IOMUX_PIN(IOMUXC_SW_MUX_CTL_PAD_##name, \ + IOMUXC_SW_PAD_CTL_PAD_##name) + +#define MUX_PIN_MUX(name) \ + IOMUX_PIN(IOMUXC_SW_MUX_CTL_PAD_##name, IOMUX_PAD_NONE) + +#define MUX_PIN_PAD(name) \ + IOMUX_PIN(IOMUX_MUX_NONE, IOMUXC_SW_PAD_CTL_PAD_##name) + +#define MUX_PIN_GRP(name) \ + IOMUX_PIN(IOMUX_MUX_NONE, IOMUXC_SW_PAD_CTL_GRP_##name) + +#define MUX_PIN_PATH(name) \ + IOMUX_PIN(IOMUXC_##name##_SELECT_INPUT, IOMUX_MUX_NONE) + +/* INPUT Control */ + +#define MUX_SELECT(name) (name##_SELECT_INPUT) + +#endif /* _IMX51_IOMUXREG_H */ diff --git a/sys/arm/freescale/imx/imx51_iomuxvar.h b/sys/arm/freescale/imx/imx51_iomuxvar.h new file mode 100644 index 0000000..908b705 --- /dev/null +++ b/sys/arm/freescale/imx/imx51_iomuxvar.h @@ -0,0 +1,45 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by Oleksandr Rybalko + * under sponsorship from the FreeBSD Foundation. + * + * 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$ + */ + +/* iomux utility functions */ +struct iomux_conf { + u_int pin; +#define IOMUX_CONF_EOT ((u_int)(-1)) + u_short mux; + u_short pad; +}; + +void iomux_set_function(u_int, u_int); +void iomux_set_pad(u_int, u_int); +#ifdef notyet +void iomux_set_input(u_int, u_int); +#endif +void iomux_mux_config(const struct iomux_conf *); diff --git a/sys/arm/freescale/imx/imx51_ipuv3.c b/sys/arm/freescale/imx/imx51_ipuv3.c new file mode 100644 index 0000000..0f2e6d4 --- /dev/null +++ b/sys/arm/freescale/imx/imx51_ipuv3.c @@ -0,0 +1,876 @@ +/*- + * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo@freebsd.org> + * All rights reserved. + * + * Portions of this software were developed by Oleksandr Rybalko + * under sponsorship from the FreeBSD Foundation. + * + * 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/bio.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/endian.h> +#include <sys/kernel.h> +#include <sys/kthread.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <sys/mutex.h> +#include <sys/queue.h> +#include <sys/resource.h> +#include <sys/rman.h> +#include <sys/time.h> +#include <sys/timetc.h> +#include <sys/fbio.h> +#include <sys/consio.h> + +#include <sys/kdb.h> + +#include <machine/bus.h> +#include <machine/cpu.h> +#include <machine/cpufunc.h> +#include <machine/resource.h> +#include <machine/frame.h> +#include <machine/intr.h> + +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <dev/fb/fbreg.h> +#include <dev/syscons/syscons.h> + +#include <arm/freescale/imx/imx51_ccmvar.h> + +#include <arm/freescale/imx/imx51_ipuv3reg.h> + +#define IMX51_IPU_HSP_CLOCK 665000000 +#define IPU3FB_FONT_HEIGHT 16 + +struct ipu3sc_softc { + device_t dev; + bus_addr_t pbase; + bus_addr_t vbase; + + bus_space_tag_t iot; + bus_space_handle_t ioh; + bus_space_handle_t cm_ioh; + bus_space_handle_t dp_ioh; + bus_space_handle_t di0_ioh; + bus_space_handle_t di1_ioh; + bus_space_handle_t dctmpl_ioh; + bus_space_handle_t dc_ioh; + bus_space_handle_t dmfc_ioh; + bus_space_handle_t idmac_ioh; + bus_space_handle_t cpmem_ioh; +}; + +struct video_adapter_softc { + /* Videoadpater part */ + video_adapter_t va; + + intptr_t fb_addr; + intptr_t fb_paddr; + unsigned int fb_size; + + int bpp; + int depth; + unsigned int height; + unsigned int width; + unsigned int stride; + + unsigned int xmargin; + unsigned int ymargin; + + unsigned char *font; + int initialized; +}; + +static struct ipu3sc_softc *ipu3sc_softc; +static struct video_adapter_softc va_softc; + +/* FIXME: not only 2 bytes color supported */ +static uint16_t colors[16] = { + 0x0000, /* black */ + 0x001f, /* blue */ + 0x07e0, /* green */ + 0x07ff, /* cyan */ + 0xf800, /* red */ + 0xf81f, /* magenta */ + 0x3800, /* brown */ + 0xc618, /* light grey */ + 0xc618, /* XXX: dark grey */ + 0x001f, /* XXX: light blue */ + 0x07e0, /* XXX: light green */ + 0x07ff, /* XXX: light cyan */ + 0xf800, /* XXX: light red */ + 0xf81f, /* XXX: light magenta */ + 0xffe0, /* yellow */ + 0xffff, /* white */ +}; +static uint32_t colors_24[16] = { + 0x000000,/* Black */ + 0x000080,/* Blue */ + 0x008000,/* Green */ + 0x008080,/* Cyan */ + 0x800000,/* Red */ + 0x800080,/* Magenta */ + 0xcc6600,/* brown */ + 0xC0C0C0,/* Silver */ + 0x808080,/* Gray */ + 0x0000FF,/* Light Blue */ + 0x00FF00,/* Light Green */ + 0x00FFFF,/* Light Cyan */ + 0xFF0000,/* Light Red */ + 0xFF00FF,/* Light Magenta */ + 0xFFFF00,/* Yellow */ + 0xFFFFFF,/* White */ + + +}; + +#define IPUV3_READ(ipuv3, module, reg) \ + bus_space_read_4((ipuv3)->iot, (ipuv3)->module##_ioh, (reg)) +#define IPUV3_WRITE(ipuv3, module, reg, val) \ + bus_space_write_4((ipuv3)->iot, (ipuv3)->module##_ioh, (reg), (val)) + +#define CPMEM_CHANNEL_OFFSET(_c) ((_c) * 0x40) +#define CPMEM_WORD_OFFSET(_w) ((_w) * 0x20) +#define CPMEM_DP_OFFSET(_d) ((_d) * 0x10000) +#define IMX_IPU_DP0 0 +#define IMX_IPU_DP1 1 +#define CPMEM_CHANNEL(_dp, _ch, _w) \ + (CPMEM_DP_OFFSET(_dp) + CPMEM_CHANNEL_OFFSET(_ch) + \ + CPMEM_WORD_OFFSET(_w)) +#define CPMEM_OFFSET(_dp, _ch, _w, _o) \ + (CPMEM_CHANNEL((_dp), (_ch), (_w)) + (_o)) + +#define IPUV3_DEBUG 100 + +#ifdef IPUV3_DEBUG +#define SUBMOD_DUMP_REG(_sc, _m, _l) \ + { \ + int i; \ + printf("*** " #_m " ***\n"); \ + for (i = 0; i <= (_l); i += 4) { \ + if ((i % 32) == 0) \ + printf("%04x: ", i & 0xffff); \ + printf("0x%08x%c", IPUV3_READ((_sc), _m, i), \ + ((i + 4) % 32)?' ':'\n'); \ + } \ + printf("\n"); \ + } +#endif + +#ifdef IPUV3_DEBUG +int ipuv3_debug = IPUV3_DEBUG; +#define DPRINTFN(n,x) if (ipuv3_debug>(n)) printf x; else +#else +#define DPRINTFN(n,x) +#endif + +static int ipu3_fb_probe(device_t); +static int ipu3_fb_attach(device_t); + +static int +ipu3_fb_malloc(struct ipu3sc_softc *sc, size_t size) +{ + + sc->vbase = (uint32_t)contigmalloc(size, M_DEVBUF, M_ZERO, 0, ~0, + PAGE_SIZE, 0); + sc->pbase = vtophys(sc->vbase); + + return (0); +} + +static void +ipu3_fb_init(void *arg) +{ + struct ipu3sc_softc *sc = arg; + struct video_adapter_softc *va_sc = &va_softc; + uint64_t w0sh96; + uint32_t w1sh96; + + /* FW W0[137:125] - 96 = [41:29] */ + /* FH W0[149:138] - 96 = [53:42] */ + w0sh96 = IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 0, 16)); + w0sh96 <<= 32; + w0sh96 |= IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 0, 12)); + + va_sc->width = ((w0sh96 >> 29) & 0x1fff) + 1; + va_sc->height = ((w0sh96 >> 42) & 0x0fff) + 1; + + /* SLY W1[115:102] - 96 = [19:6] */ + w1sh96 = IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 12)); + va_sc->stride = ((w1sh96 >> 6) & 0x3fff) + 1; + + printf("%dx%d [%d]\n", va_sc->width, va_sc->height, va_sc->stride); + va_sc->fb_size = va_sc->height * va_sc->stride; + + ipu3_fb_malloc(sc, va_sc->fb_size); + + /* DP1 + config_ch_23 + word_2 */ + IPUV3_WRITE(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 0), + ((sc->pbase >> 3) | ((sc->pbase >> 3) << 29)) & 0xffffffff); + + IPUV3_WRITE(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 4), + ((sc->pbase >> 3) >> 3) & 0xffffffff); + + va_sc->fb_addr = (intptr_t)sc->vbase; + va_sc->fb_paddr = (intptr_t)sc->pbase; + va_sc->bpp = va_sc->stride / va_sc->width; + va_sc->depth = va_sc->bpp * 8; +} + +static int +ipu3_fb_probe(device_t dev) +{ + int error; + + if (!ofw_bus_is_compatible(dev, "fsl,ipu3")) + return (ENXIO); + + device_set_desc(dev, "i.MX515 Image Processing Unit (FB)"); + + error = sc_probe_unit(device_get_unit(dev), + device_get_flags(dev) | SC_AUTODETECT_KBD); + + if (error != 0) + return (error); + + return (BUS_PROBE_DEFAULT); +} + +static int +ipu3_fb_attach(device_t dev) +{ + struct ipu3sc_softc *sc = device_get_softc(dev); + bus_space_tag_t iot; + bus_space_handle_t ioh; + int err; + + if (ipu3sc_softc) + return (ENXIO); + + ipu3sc_softc = sc; + + device_printf(dev, "\tclock gate status is %d\n", + imx51_get_clk_gating(IMX51CLK_IPU_HSP_CLK_ROOT)); + + sc->dev = dev; + + err = (sc_attach_unit(device_get_unit(dev), + device_get_flags(dev) | SC_AUTODETECT_KBD)); + + if (err) { + device_printf(dev, "failed to attach syscons\n"); + goto fail; + } + + sc = device_get_softc(dev); + sc->iot = iot = fdtbus_bs_tag; + + device_printf(sc->dev, ": i.MX51 IPUV3 controller\n"); + + /* map controller registers */ + err = bus_space_map(iot, IPU_CM_BASE, IPU_CM_SIZE, 0, &ioh); + if (err) + goto fail_retarn_cm; + sc->cm_ioh = ioh; + + /* map Display Multi FIFO Controller registers */ + err = bus_space_map(iot, IPU_DMFC_BASE, IPU_DMFC_SIZE, 0, &ioh); + if (err) + goto fail_retarn_dmfc; + sc->dmfc_ioh = ioh; + + /* map Display Interface 0 registers */ + err = bus_space_map(iot, IPU_DI0_BASE, IPU_DI0_SIZE, 0, &ioh); + if (err) + goto fail_retarn_di0; + sc->di0_ioh = ioh; + + /* map Display Interface 1 registers */ + err = bus_space_map(iot, IPU_DI1_BASE, IPU_DI0_SIZE, 0, &ioh); + if (err) + goto fail_retarn_di1; + sc->di1_ioh = ioh; + + /* map Display Processor registers */ + err = bus_space_map(iot, IPU_DP_BASE, IPU_DP_SIZE, 0, &ioh); + if (err) + goto fail_retarn_dp; + sc->dp_ioh = ioh; + + /* map Display Controller registers */ + err = bus_space_map(iot, IPU_DC_BASE, IPU_DC_SIZE, 0, &ioh); + if (err) + goto fail_retarn_dc; + sc->dc_ioh = ioh; + + /* map Image DMA Controller registers */ + err = bus_space_map(iot, IPU_IDMAC_BASE, IPU_IDMAC_SIZE, 0, &ioh); + if (err) + goto fail_retarn_idmac; + sc->idmac_ioh = ioh; + + /* map CPMEM registers */ + err = bus_space_map(iot, IPU_CPMEM_BASE, IPU_CPMEM_SIZE, 0, &ioh); + if (err) + goto fail_retarn_cpmem; + sc->cpmem_ioh = ioh; + + /* map DCTEMPL registers */ + err = bus_space_map(iot, IPU_DCTMPL_BASE, IPU_DCTMPL_SIZE, 0, &ioh); + if (err) + goto fail_retarn_dctmpl; + sc->dctmpl_ioh = ioh; + +#ifdef notyet + sc->ih = imx51_ipuv3_intr_establish(IMX51_INT_IPUV3, IPL_BIO, + ipuv3intr, sc); + if (sc->ih == NULL) { + device_printf(sc->dev, + "unable to establish interrupt at irq %d\n", + IMX51_INT_IPUV3); + return (ENXIO); + } +#endif + + /* + * We have to wait until interrupts are enabled. + * Mailbox relies on it to get data from VideoCore + */ + ipu3_fb_init(sc); + + return (0); + +fail: + return (ENXIO); +fail_retarn_dctmpl: + bus_space_unmap(sc->iot, sc->cpmem_ioh, IPU_CPMEM_SIZE); +fail_retarn_cpmem: + bus_space_unmap(sc->iot, sc->idmac_ioh, IPU_IDMAC_SIZE); +fail_retarn_idmac: + bus_space_unmap(sc->iot, sc->dc_ioh, IPU_DC_SIZE); +fail_retarn_dp: + bus_space_unmap(sc->iot, sc->dp_ioh, IPU_DP_SIZE); +fail_retarn_dc: + bus_space_unmap(sc->iot, sc->di1_ioh, IPU_DI1_SIZE); +fail_retarn_di1: + bus_space_unmap(sc->iot, sc->di0_ioh, IPU_DI0_SIZE); +fail_retarn_di0: + bus_space_unmap(sc->iot, sc->dmfc_ioh, IPU_DMFC_SIZE); +fail_retarn_dmfc: + bus_space_unmap(sc->iot, sc->dc_ioh, IPU_CM_SIZE); +fail_retarn_cm: + device_printf(sc->dev, + "failed to map registers (errno=%d)\n", err); + return (err); +} + +static device_method_t ipu3_fb_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ipu3_fb_probe), + DEVMETHOD(device_attach, ipu3_fb_attach), + + { 0, 0 } +}; + +static devclass_t ipu3_fb_devclass; + +static driver_t ipu3_fb_driver = { + "fb", + ipu3_fb_methods, + sizeof(struct ipu3sc_softc), +}; + +DRIVER_MODULE(ipu3fb, simplebus, ipu3_fb_driver, ipu3_fb_devclass, 0, 0); + +/* + * Video driver routines and glue. + */ +static int ipu3fb_configure(int); +static vi_probe_t ipu3fb_probe; +static vi_init_t ipu3fb_init; +static vi_get_info_t ipu3fb_get_info; +static vi_query_mode_t ipu3fb_query_mode; +static vi_set_mode_t ipu3fb_set_mode; +static vi_save_font_t ipu3fb_save_font; +static vi_load_font_t ipu3fb_load_font; +static vi_show_font_t ipu3fb_show_font; +static vi_save_palette_t ipu3fb_save_palette; +static vi_load_palette_t ipu3fb_load_palette; +static vi_set_border_t ipu3fb_set_border; +static vi_save_state_t ipu3fb_save_state; +static vi_load_state_t ipu3fb_load_state; +static vi_set_win_org_t ipu3fb_set_win_org; +static vi_read_hw_cursor_t ipu3fb_read_hw_cursor; +static vi_set_hw_cursor_t ipu3fb_set_hw_cursor; +static vi_set_hw_cursor_shape_t ipu3fb_set_hw_cursor_shape; +static vi_blank_display_t ipu3fb_blank_display; +static vi_mmap_t ipu3fb_mmap; +static vi_ioctl_t ipu3fb_ioctl; +static vi_clear_t ipu3fb_clear; +static vi_fill_rect_t ipu3fb_fill_rect; +static vi_bitblt_t ipu3fb_bitblt; +static vi_diag_t ipu3fb_diag; +static vi_save_cursor_palette_t ipu3fb_save_cursor_palette; +static vi_load_cursor_palette_t ipu3fb_load_cursor_palette; +static vi_copy_t ipu3fb_copy; +static vi_putp_t ipu3fb_putp; +static vi_putc_t ipu3fb_putc; +static vi_puts_t ipu3fb_puts; +static vi_putm_t ipu3fb_putm; + +static video_switch_t ipu3fbvidsw = { + .probe = ipu3fb_probe, + .init = ipu3fb_init, + .get_info = ipu3fb_get_info, + .query_mode = ipu3fb_query_mode, + .set_mode = ipu3fb_set_mode, + .save_font = ipu3fb_save_font, + .load_font = ipu3fb_load_font, + .show_font = ipu3fb_show_font, + .save_palette = ipu3fb_save_palette, + .load_palette = ipu3fb_load_palette, + .set_border = ipu3fb_set_border, + .save_state = ipu3fb_save_state, + .load_state = ipu3fb_load_state, + .set_win_org = ipu3fb_set_win_org, + .read_hw_cursor = ipu3fb_read_hw_cursor, + .set_hw_cursor = ipu3fb_set_hw_cursor, + .set_hw_cursor_shape = ipu3fb_set_hw_cursor_shape, + .blank_display = ipu3fb_blank_display, + .mmap = ipu3fb_mmap, + .ioctl = ipu3fb_ioctl, + .clear = ipu3fb_clear, + .fill_rect = ipu3fb_fill_rect, + .bitblt = ipu3fb_bitblt, + .diag = ipu3fb_diag, + .save_cursor_palette = ipu3fb_save_cursor_palette, + .load_cursor_palette = ipu3fb_load_cursor_palette, + .copy = ipu3fb_copy, + .putp = ipu3fb_putp, + .putc = ipu3fb_putc, + .puts = ipu3fb_puts, + .putm = ipu3fb_putm, +}; + +VIDEO_DRIVER(ipu3fb, ipu3fbvidsw, ipu3fb_configure); + +extern sc_rndr_sw_t txtrndrsw; +RENDERER(ipu3fb, 0, txtrndrsw, gfb_set); +RENDERER_MODULE(ipu3fb, gfb_set); + +static uint16_t ipu3fb_static_window[ROW*COL]; +extern u_char dflt_font_16[]; + +static int +ipu3fb_configure(int flags) +{ + struct video_adapter_softc *sc; + + sc = &va_softc; + + if (sc->initialized) + return 0; + + sc->width = 640; + sc->height = 480; + sc->bpp = 2; + sc->stride = sc->width * sc->bpp; + + ipu3fb_init(0, &sc->va, 0); + + sc->initialized = 1; + + return (0); +} + +static int +ipu3fb_probe(int unit, video_adapter_t **adp, void *arg, int flags) +{ + + return (0); +} + +static int +ipu3fb_init(int unit, video_adapter_t *adp, int flags) +{ + struct video_adapter_softc *sc; + video_info_t *vi; + + sc = (struct video_adapter_softc *)adp; + vi = &adp->va_info; + + vid_init_struct(adp, "ipu3fb", -1, unit); + + sc->font = dflt_font_16; + vi->vi_cheight = IPU3FB_FONT_HEIGHT; + vi->vi_cwidth = 8; + vi->vi_width = sc->width/8; + vi->vi_height = sc->height/vi->vi_cheight; + + /* + * Clamp width/height to syscons maximums + */ + if (vi->vi_width > COL) + vi->vi_width = COL; + if (vi->vi_height > ROW) + vi->vi_height = ROW; + + sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; + sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2; + + adp->va_window = (vm_offset_t) ipu3fb_static_window; + adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */; + adp->va_line_width = sc->stride; + adp->va_buffer_size = sc->fb_size; + + vid_register(&sc->va); + + return (0); +} + +static int +ipu3fb_get_info(video_adapter_t *adp, int mode, video_info_t *info) +{ + + bcopy(&adp->va_info, info, sizeof(*info)); + return (0); +} + +static int +ipu3fb_query_mode(video_adapter_t *adp, video_info_t *info) +{ + + return (0); +} + +static int +ipu3fb_set_mode(video_adapter_t *adp, int mode) +{ + + return (0); +} + +static int +ipu3fb_save_font(video_adapter_t *adp, int page, int size, int width, + u_char *data, int c, int count) +{ + + return (0); +} + +static int +ipu3fb_load_font(video_adapter_t *adp, int page, int size, int width, + u_char *data, int c, int count) +{ + struct video_adapter_softc *sc; + + sc = (struct video_adapter_softc *)adp; + sc->font = data; + + return (0); +} + +static int +ipu3fb_show_font(video_adapter_t *adp, int page) +{ + + return (0); +} + +static int +ipu3fb_save_palette(video_adapter_t *adp, u_char *palette) +{ + + return (0); +} + +static int +ipu3fb_load_palette(video_adapter_t *adp, u_char *palette) +{ + + return (0); +} + +static int +ipu3fb_set_border(video_adapter_t *adp, int border) +{ + + return (ipu3fb_blank_display(adp, border)); +} + +static int +ipu3fb_save_state(video_adapter_t *adp, void *p, size_t size) +{ + + return (0); +} + +static int +ipu3fb_load_state(video_adapter_t *adp, void *p) +{ + + return (0); +} + +static int +ipu3fb_set_win_org(video_adapter_t *adp, off_t offset) +{ + + return (0); +} + +static int +ipu3fb_read_hw_cursor(video_adapter_t *adp, int *col, int *row) +{ + + *col = *row = 0; + return (0); +} + +static int +ipu3fb_set_hw_cursor(video_adapter_t *adp, int col, int row) +{ + + return (0); +} + +static int +ipu3fb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, + int celsize, int blink) +{ + + return (0); +} + +static int +ipu3fb_blank_display(video_adapter_t *adp, int mode) +{ + + return (0); +} + +static int +ipu3fb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, + int prot, vm_memattr_t *memattr) +{ + struct video_adapter_softc *sc; + + sc = (struct video_adapter_softc *)adp; + + /* + * This might be a legacy VGA mem request: if so, just point it at the + * framebuffer, since it shouldn't be touched + */ + if (offset < sc->stride * sc->height) { + *paddr = sc->fb_paddr + offset; + return (0); + } + + return (EINVAL); +} + +static int +ipu3fb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) +{ + struct video_adapter_softc *sc; + struct fbtype *fb; + + sc = (struct video_adapter_softc *)adp; + + switch (cmd) { + case FBIOGTYPE: + fb = (struct fbtype *)data; + fb->fb_type = FBTYPE_PCIMISC; + fb->fb_height = sc->height; + fb->fb_width = sc->width; + fb->fb_depth = sc->depth; + if (sc->depth <= 1 || sc->depth > 8) + fb->fb_cmsize = 0; + else + fb->fb_cmsize = 1 << sc->depth; + fb->fb_size = sc->fb_size; + break; + case FBIOSCURSOR: + return (ENODEV); + default: + return (fb_commonioctl(adp, cmd, data)); + } + + return (0); +} + +static int +ipu3fb_clear(video_adapter_t *adp) +{ + + return (ipu3fb_blank_display(adp, 0)); +} + +static int +ipu3fb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) +{ + + return (0); +} + +static int +ipu3fb_bitblt(video_adapter_t *adp, ...) +{ + + return (0); +} + +static int +ipu3fb_diag(video_adapter_t *adp, int level) +{ + + return (0); +} + +static int +ipu3fb_save_cursor_palette(video_adapter_t *adp, u_char *palette) +{ + + return (0); +} + +static int +ipu3fb_load_cursor_palette(video_adapter_t *adp, u_char *palette) +{ + + return (0); +} + +static int +ipu3fb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) +{ + + return (0); +} + +static int +ipu3fb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, + int size, int bpp, int bit_ltor, int byte_ltor) +{ + + return (0); +} + +static int +ipu3fb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) +{ + struct video_adapter_softc *sc; + int col, row, bpp; + int b, i, j, k; + uint8_t *addr; + u_char *p; + uint32_t fg, bg, color; + + sc = (struct video_adapter_softc *)adp; + bpp = sc->bpp; + + if (sc->fb_addr == 0) + return (0); + row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; + col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; + p = sc->font + c * IPU3FB_FONT_HEIGHT; + addr = (uint8_t *)sc->fb_addr + + (row + sc->ymargin) * (sc->stride) + + bpp * (col + sc->xmargin); + + if (bpp == 2) { + bg = colors[(a >> 4) & 0x0f]; + fg = colors[a & 0x0f]; + } else if (bpp == 3) { + bg = colors_24[(a >> 4) & 0x0f]; + fg = colors_24[a & 0x0f]; + } else { + return (ENXIO); + } + + for (i = 0; i < IPU3FB_FONT_HEIGHT; i++) { + for (j = 0, k = 7; j < 8; j++, k--) { + if ((p[i] & (1 << k)) == 0) + color = bg; + else + color = fg; + /* FIXME: BPP maybe different */ + for (b = 0; b < bpp; b ++) + addr[bpp * j + b] = + (color >> (b << 3)) & 0xff; + } + + addr += (sc->stride); + } + + return (0); +} + +static int +ipu3fb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len) +{ + int i; + + for (i = 0; i < len; i++) + ipu3fb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8); + + return (0); +} + +static int +ipu3fb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, + uint32_t pixel_mask, int size, int width) +{ + + return (0); +} + +/* + * Define a stub keyboard driver in case one hasn't been + * compiled into the kernel + */ +#include <sys/kbio.h> +#include <dev/kbd/kbdreg.h> + +static int dummy_kbd_configure(int flags); + +keyboard_switch_t ipu3dummysw; + +static int +dummy_kbd_configure(int flags) +{ + + return (0); +} +KEYBOARD_DRIVER(ipu3dummy, ipu3dummysw, dummy_kbd_configure); diff --git a/sys/arm/freescale/imx/imx51_ipuv3reg.h b/sys/arm/freescale/imx/imx51_ipuv3reg.h new file mode 100644 index 0000000..bdfb4dd --- /dev/null +++ b/sys/arm/freescale/imx/imx51_ipuv3reg.h @@ -0,0 +1,919 @@ +/* $NetBSD: imx51_ipuv3reg.h,v 1.1 2012/04/17 10:19:57 bsh Exp $ */ +/* + * Copyright (c) 2011, 2012 Genetec Corporation. All rights reserved. + * Written by Hashimoto Kenichi for Genetec Corporation. + * + * 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 GENETEC CORPORATION ``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 GENETEC CORPORATION + * 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. + */ + +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by Oleksandr Rybalko + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _ARM_IMX_IMX51_IPUV3REG_H +#define _ARM_IMX_IMX51_IPUV3REG_H + +/* register offset address */ + +/* + * CM + * Control Module + */ +#define IPU_CM_CONF 0x00000000 +#define CM_CONF_CSI_SEL 0x80000000 +#define CM_CONF_IC_INPUT 0x40000000 +#define CM_CONF_CSI1_DATA_SOURCE 0x20000000 +#define CM_CONF_CSI0_DATA_SOURCE 0x10000000 +#define CM_CONF_VDI_DMFC_SYNC 0x08000000 +#define CM_CONF_IC_DMFC_SYNC 0x04000000 +#define CM_CONF_IC_DMFC_SEL 0x02000000 +#define CM_CONF_ISP_DOUBLE_FLOW 0x01000000 +#define CM_CONF_IDMAC_DISABLE 0x00400000 +#define CM_CONF_IPU_DIAGBUS_ON 0x00200000 +#define CM_CONF_IPU_DIAGBUS_MODE 0x001f0000 +#define CM_CONF_VDI_EN 0x00001000 +#define CM_CONF_SISG_EN 0x00000800 +#define CM_CONF_DMFC_EN 0x00000400 +#define CM_CONF_DC_EN 0x00000200 +#define CM_CONF_SMFC_EN 0x00000100 +#define CM_CONF_DI1_EN 0x00000080 +#define CM_CONF_DI0_EN 0x00000040 +#define CM_CONF_DP_EN 0x00000020 +#define CM_CONF_ISP_EN 0x00000010 +#define CM_CONF_IRT_EN 0x00000008 +#define CM_CONF_IC_EN 0x00000004 +#define CM_CONF_CSI1_EN 0x00000002 +#define CM_CONF_CSI0_EN 0x00000001 +#define IPU_SISG_CTRL0 0x00000004 +#define IPU_SISG_CTRL1 0x00000008 +#define IPU_CM_INT_CTRL_1 0x0000003c +#define IPU_CM_INT_CTRL_2 0x00000040 +#define IPU_CM_INT_CTRL_3 0x00000044 +#define IPU_CM_INT_CTRL_4 0x00000048 +#define IPU_CM_INT_CTRL_5 0x0000004c +#define IPU_CM_INT_CTRL_6 0x00000050 +#define IPU_CM_INT_CTRL_7 0x00000054 +#define IPU_CM_INT_CTRL_8 0x00000058 +#define IPU_CM_INT_CTRL_9 0x0000005c +#define IPU_CM_INT_CTRL_10 0x00000060 +#define IPU_CM_INT_CTRL_11 0x00000064 +#define IPU_CM_INT_CTRL_12 0x00000068 +#define IPU_CM_INT_CTRL_13 0x0000006c +#define IPU_CM_INT_CTRL_14 0x00000070 +#define IPU_CM_INT_CTRL_15 0x00000074 +#define IPU_CM_SDMA_EVENT_1 0x00000078 +#define IPU_CM_SDMA_EVENT_2 0x0000007c +#define IPU_CM_SDMA_EVENT_3 0x00000080 +#define IPU_CM_SDMA_EVENT_4 0x00000084 +#define IPU_CM_SDMA_EVENT_7 0x00000088 +#define IPU_CM_SDMA_EVENT_8 0x0000008c +#define IPU_CM_SDMA_EVENT_11 0x00000090 +#define IPU_CM_SDMA_EVENT_12 0x00000094 +#define IPU_CM_SDMA_EVENT_13 0x00000098 +#define IPU_CM_SDMA_EVENT_14 0x0000009c +#define IPU_CM_SRM_PRI1 0x000000a0 +#define IPU_CM_SRM_PRI2 0x000000a4 +#define IPU_CM_FS_PROC_FLOW1 0x000000a8 +#define IPU_CM_FS_PROC_FLOW2 0x000000ac +#define IPU_CM_FS_PROC_FLOW3 0x000000b0 +#define IPU_CM_FS_DISP_FLOW1 0x000000b4 +#define IPU_CM_FS_DISP_FLOW2 0x000000b8 +#define IPU_CM_SKIP 0x000000bc +#define IPU_CM_DISP_ALT_CONF 0x000000c0 +#define IPU_CM_DISP_GEN 0x000000c4 +#define CM_DISP_GEN_DI0_COUNTER_RELEASE 0x01000000 +#define CM_DISP_GEN_DI1_COUNTER_RELEASE 0x00800000 +#define CM_DISP_GEN_MCU_MAX_BURST_STOP 0x00400000 +#define CM_DISP_GEN_MCU_T_SHIFT 18 +#define CM_DISP_GEN_MCU_T(n) ((n) << CM_DISP_GEN_MCU_T_SHIFT) +#define IPU_CM_DISP_ALT1 0x000000c8 +#define IPU_CM_DISP_ALT2 0x000000cc +#define IPU_CM_DISP_ALT3 0x000000d0 +#define IPU_CM_DISP_ALT4 0x000000d4 +#define IPU_CM_SNOOP 0x000000d8 +#define IPU_CM_MEM_RST 0x000000dc +#define CM_MEM_START 0x80000000 +#define CM_MEM_EN 0x007fffff +#define IPU_CM_PM 0x000000e0 +#define IPU_CM_GPR 0x000000e4 +#define CM_GPR_IPU_CH_BUF1_RDY1_CLR 0x80000000 +#define CM_GPR_IPU_CH_BUF1_RDY0_CLR 0x40000000 +#define CM_GPR_IPU_CH_BUF0_RDY1_CLR 0x20000000 +#define CM_GPR_IPU_CH_BUF0_RDY0_CLR 0x10000000 +#define CM_GPR_IPU_ALT_CH_BUF1_RDY1_CLR 0x08000000 +#define CM_GPR_IPU_ALT_CH_BUF1_RDY0_CLR 0x04000000 +#define CM_GPR_IPU_ALT_CH_BUF0_RDY1_CLR 0x02000000 +#define CM_GPR_IPU_ALT_CH_BUF0_RDY0_CLR 0x01000000 +#define CM_GPR_IPU_DI1_CLK_CHANGE_ACK_DIS 0x00800000 +#define CM_GPR_IPU_DI0_CLK_CHANGE_ACK_DIS 0x00400000 +#define CM_GPR_IPU_CH_BUF2_RDY1_CLR 0x00200000 +#define CM_GPR_IPU_CH_BUF2_RDY0_CLR 0x00100000 +#define CM_GPR_IPU_GP(n) __BIT((n)) +#define IPU_CM_CH_DB_MODE_SEL_0 0x00000150 +#define IPU_CM_CH_DB_MODE_SEL_1 0x00000154 +#define IPU_CM_ALT_CH_DB_MODE_SEL_0 0x00000168 +#define IPU_CM_ALT_CH_DB_MODE_SEL_1 0x0000016c +#define IPU_CM_CH_TRB_MODE_SEL_0 0x00000178 +#define IPU_CM_CH_TRB_MODE_SEL_1 0x0000017c +#define IPU_CM_INT_STAT_1 0x00000200 +#define IPU_CM_INT_STAT_2 0x00000204 +#define IPU_CM_INT_STAT_3 0x00000208 +#define IPU_CM_INT_STAT_4 0x0000020c +#define IPU_CM_INT_STAT_5 0x00000210 +#define IPU_CM_INT_STAT_6 0x00000214 +#define IPU_CM_INT_STAT_7 0x00000218 +#define IPU_CM_INT_STAT_8 0x0000021c +#define IPU_CM_INT_STAT_9 0x00000220 +#define IPU_CM_INT_STAT_10 0x00000224 +#define IPU_CM_INT_STAT_11 0x00000228 +#define IPU_CM_INT_STAT_12 0x0000022c +#define IPU_CM_INT_STAT_13 0x00000230 +#define IPU_CM_INT_STAT_14 0x00000234 +#define IPU_CM_INT_STAT_15 0x00000238 +#define IPU_CM_CUR_BUF_0 0x0000023c +#define IPU_CM_CUR_BUF_1 0x00000240 +#define IPU_CM_ALT_CUR_BUF_0 0x00000244 +#define IPU_CM_ALT_CUR_BUF_1 0x00000248 +#define IPU_CM_SRM_STAT 0x0000024c +#define IPU_CM_PROC_TASKS_STAT 0x00000250 +#define IPU_CM_DISP_TASKS_STAT 0x00000254 +#define IPU_CM_TRIPLE_CUR_BUF_0 0x00000258 +#define IPU_CM_TRIPLE_CUR_BUF_1 0x0000025c +#define IPU_CM_TRIPLE_CUR_BUF_2 0x00000260 +#define IPU_CM_TRIPLE_CUR_BUF_3 0x00000264 +#define IPU_CM_CH_BUF0_RDY0 0x00000268 +#define IPU_CM_CH_BUF0_RDY1 0x0000026c +#define IPU_CM_CH_BUF1_RDY0 0x00000270 +#define IPU_CM_CH_BUF1_RDY1 0x00000274 +#define IPU_CM_ALT_CH_BUF0_RDY0 0x00000278 +#define IPU_CM_ALT_CH_BUF0_RDY1 0x0000027c +#define IPU_CM_ALT_CH_BUF1_RDY0 0x00000280 +#define IPU_CM_ALT_CH_BUF1_RDY1 0x00000284 +#define IPU_CM_CH_BUF2_RDY0 0x00000288 +#define IPU_CM_CH_BUF2_RDY1 0x0000028c + +/* + * IDMAC + * Image DMA Controller + */ +#define IPU_IDMAC_CONF 0x00000000 +#define IPU_IDMAC_CH_EN_1 0x00000004 +#define IPU_IDMAC_CH_EN_2 0x00000008 +#define IPU_IDMAC_SEP_ALPHA 0x0000000c +#define IPU_IDMAC_ALT_SEP_ALPHA 0x00000010 +#define IPU_IDMAC_CH_PRI_1 0x00000014 +#define IPU_IDMAC_CH_PRI_2 0x00000018 +#define IPU_IDMAC_WM_EN_1 0x0000001c +#define IPU_IDMAC_WM_EN_2 0x00000020 +#define IPU_IDMAC_LOCK_EN_1 0x00000024 +#define IPU_IDMAC_LOCK_EN_2 0x00000028 +#define IPU_IDMAC_SUB_ADDR_0 0x0000002c +#define IPU_IDMAC_SUB_ADDR_1 0x00000030 +#define IPU_IDMAC_SUB_ADDR_2 0x00000034 +#define IPU_IDMAC_SUB_ADDR_3 0x00000038 +#define IPU_IDMAC_SUB_ADDR_4 0x0000003c +#define IPU_IDMAC_BNDM_EN_1 0x00000040 +#define IPU_IDMAC_BNDM_EN_2 0x00000044 +#define IPU_IDMAC_SC_CORD 0x00000048 +#define IPU_IDMAC_SC_CORD1 0x0000004c +#define IPU_IDMAC_CH_BUSY_1 0x00000100 +#define IPU_IDMAC_CH_BUSY_2 0x00000104 + +#define CH_PANNEL_BG 23 +#define CH_PANNEL_FG 27 + +/* + * DP + * Display Port + */ +#define IPU_DP_DEBUG_CNT 0x000000bc +#define IPU_DP_DEBUG_STAT 0x000000c0 + +/* + * IC + * Image Converter + */ +#define IPU_IC_CONF 0x00000000 +#define IPU_IC_PRP_ENC_RSC 0x00000004 +#define IPU_IC_PRP_VF_RSC 0x00000008 +#define IPU_IC_PP_RSC 0x0000000c +#define IPU_IC_CMBP_1 0x00000010 +#define IPU_IC_CMBP_2 0x00000014 +#define IPU_IC_IDMAC_1 0x00000018 +#define IPU_IC_IDMAC_2 0x0000001c +#define IPU_IC_IDMAC_3 0x00000020 +#define IPU_IC_IDMAC_4 0x00000024 + +/* + * CSI + * Camera Sensor Interface + */ +#define IPU_CSI0_SENS_CONF 0x00000000 +#define IPU_CSI0_SENS_FRM_SIZE 0x00000004 +#define IPU_CSI0_ACT_FRM_SIZE 0x00000008 +#define IPU_CSI0_OUT_FRM_CTRL 0x0000000c +#define IPU_CSI0_TST_CTRL 0x00000010 +#define IPU_CSI0_CCIR_CODE_1 0x00000014 +#define IPU_CSI0_CCIR_CODE_2 0x00000018 +#define IPU_CSI0_CCIR_CODE_3 0x0000001c +#define IPU_CSI0_DI 0x00000020 +#define IPU_CSI0_SKIP 0x00000024 +#define IPU_CSI0_CPD_CTRL 0x00000028 +#define IPU_CSI0_CPD_OFFSET1 0x000000ec +#define IPU_CSI0_CPD_OFFSET2 0x000000f0 + +#define IPU_CSI1_SENS_CONF 0x00000000 +#define IPU_CSI1_SENS_FRM_SIZE 0x00000004 +#define IPU_CSI1_ACT_FRM_SIZE 0x00000008 +#define IPU_CSI1_OUT_FRM_CTRL 0x0000000c +#define IPU_CSI1_TST_CTRL 0x00000010 +#define IPU_CSI1_CCIR_CODE_1 0x00000014 +#define IPU_CSI1_CCIR_CODE_2 0x00000018 +#define IPU_CSI1_CCIR_CODE_3 0x0000001c +#define IPU_CSI1_DI 0x00000020 +#define IPU_CSI1_SKIP 0x00000024 +#define IPU_CSI1_CPD_CTRL 0x00000028 +#define IPU_CSI1_CPD_OFFSET1 0x000000ec +#define IPU_CSI1_CPD_OFFSET2 0x000000f0 + +/* + * DI + * Display Interface + */ +#define IPU_DI_GENERAL 0x00000000 +#define DI_GENERAL_DISP_Y_SEL 0x70000000 +#define DI_GENERAL_CLOCK_STOP_MODE 0x0f000000 +#define DI_GENERAL_DISP_CLOCK_INIT 0x00800000 +#define DI_GENERAL_MASK_SEL 0x00400000 +#define DI_GENERAL_VSYNC_EXT 0x00200000 +#define DI_GENERAL_CLK_EXT 0x00100000 +#define DI_GENERAL_WATCHDOG_MODE 0x000c0000 +#define DI_GENERAL_POLARITY_DISP_CLK 0x00020000 +#define DI_GENERAL_SYNC_COUNT_SEL 0x0000f000 +#define DI_GENERAL_ERR_TREATMENT 0x00000800 +#define DI_GENERAL_ERM_VSYNC_SEL 0x00000400 +#define DI_GENERAL_POLARITY_CS(n) (1 << ((n) + 8)) +#define DI_GENERAL_POLARITY(n) (1 << ((n) - 1)) + +#define IPU_DI_BS_CLKGEN0 0x00000004 +#define DI_BS_CLKGEN0_OFFSET_SHIFT 16 +#define IPU_DI_BS_CLKGEN1 0x00000008 +#define DI_BS_CLKGEN1_DOWN_SHIFT 16 +#define DI_BS_CLKGEN1_UP_SHIFT 0 +#define IPU_DI_SW_GEN0(n) (0x0000000c + ((n) - 1) * 4) +#define DI_SW_GEN0_RUN_VAL 0x7ff80000 +#define DI_SW_GEN0_RUN_RESOL 0x00070000 +#define DI_SW_GEN0_OFFSET_VAL 0x00007ff8 +#define DI_SW_GEN0_OFFSET_RESOL 0x00000007 +#define __DI_SW_GEN0(run_val, run_resol, offset_val, offset_resol) \ + (((run_val) << 19) | ((run_resol) << 16) | \ + ((offset_val) << 3) | (offset_resol)) +#define IPU_DI_SW_GEN1(n) (0x00000030 + ((n) - 1) * 4) +#define DI_SW_GEN1_CNT_POL_GEN_EN 0x60000000 +#define DI_SW_GEN1_CNT_AUTO_RELOAD 0x10000000 +#define DI_SW_GEN1_CNT_CLR_SEL 0x0e000000 +#define DI_SW_GEN1_CNT_DOWN 0x01ff0000 +#define DI_SW_GEN1_CNT_POL_TRIG_SEL 0x00007000 +#define DI_SW_GEN1_CNT_POL_CLR_SEL 0x00000e00 +#define DI_SW_GEN1_CNT_UP 0x000001ff +#define __DI_SW_GEN1(pol_gen_en, auto_reload, clr_sel, down, pol_trig_sel, pol_clr_sel, up) \ + (((pol_gen_en) << 29) | ((auto_reload) << 28) | \ + ((clr_sel) << 25) | \ + ((down) << 16) | ((pol_trig_sel) << 12) | \ + ((pol_clr_sel) << 9) | (up)) +#define IPU_DI_SYNC_AS_GEN 0x00000054 +#define DI_SYNC_AS_GEN_SYNC_START_EN 0x10000000 +#define DI_SYNC_AS_GEN_VSYNC_SEL 0x0000e000 +#define DI_SYNC_AS_GEN_VSYNC_SEL_SHIFT 13 +#define DI_SYNC_AS_GEN_SYNC_STAR 0x00000fff +#define IPU_DI_DW_GEN(n) (0x00000058 + (n) * 4) +#define DI_DW_GEN_ACCESS_SIZE_SHIFT 24 +#define DI_DW_GEN_COMPONNENT_SIZE_SHIFT 16 +#define DI_DW_GEN_PIN_SHIFT(n) (((n) - 11) * 2) +#define DI_DW_GEN_PIN(n) __BITS(DI_DW_GEN_PIN_SHIFT(n) + 1, \ + DI_DW_GEN_PIN_SHIFT(n)) +#define IPU_DI_DW_SET(n, m) (0x00000088 + (n) * 4 + (m) * 0x30) +#define DI_DW_SET_DOWN_SHIFT 16 +#define DI_DW_SET_UP_SHIFT 0 +#define IPU_DI_STP_REP(n) (0x00000148 + ((n - 1) / 2) * 4) +#define DI_STP_REP_SHIFT(n) (((n - 1) % 2) * 16) +#define DI_STP_REP_MASK(n) (0x00000fff << DI_STP_REP_SHIFT((n))) +#define IPU_DI_SER_CONF 0x0000015c +#define IPU_DI_SSC 0x00000160 +#define IPU_DI_POL 0x00000164 +#define DI_POL_DRDY_POLARITY_17 0x00000040 +#define DI_POL_DRDY_POLARITY_16 0x00000020 +#define DI_POL_DRDY_POLARITY_15 0x00000010 +#define DI_POL_DRDY_POLARITY_14 0x00000008 +#define DI_POL_DRDY_POLARITY_13 0x00000004 +#define DI_POL_DRDY_POLARITY_12 0x00000002 +#define DI_POL_DRDY_POLARITY_11 0x00000001 +#define IPU_DI_AW0 0x00000168 +#define IPU_DI_AW1 0x0000016c +#define IPU_DI_SCR_CONF 0x00000170 +#define IPU_DI_STAT 0x00000174 + +/* + * SMFC + * Sensor Multi FIFO Controller + */ +#define IPU_SMFC_MAP 0x00000000 +#define IPU_SMFC_WMC 0x00000004 +#define IPU_SMFC_BS 0x00000008 + +/* + * DC + * Display Controller + */ +#define IPU_DC_READ_CH_CONF 0x00000000 +#define IPU_DC_READ_CH_ADDR 0x00000004 + +#define IPU_DC_RL0_CH_0 0x00000008 +#define IPU_DC_RL1_CH_0 0x0000000c +#define IPU_DC_RL2_CH_0 0x00000010 +#define IPU_DC_RL3_CH_0 0x00000014 +#define IPU_DC_RL4_CH_0 0x00000018 +#define IPU_DC_WR_CH_CONF_1 0x0000001c +#define IPU_DC_WR_CH_ADDR_1 0x00000020 +#define IPU_DC_RL0_CH_1 0x00000024 +#define IPU_DC_RL1_CH_1 0x00000028 +#define IPU_DC_RL2_CH_1 0x0000002c +#define IPU_DC_RL3_CH_1 0x00000030 +#define IPU_DC_RL4_CH_1 0x00000034 +#define IPU_DC_WR_CH_CONF_2 0x00000038 +#define IPU_DC_WR_CH_ADDR_2 0x0000003c +#define IPU_DC_RL0_CH_2 0x00000040 +#define IPU_DC_RL1_CH_2 0x00000044 +#define IPU_DC_RL2_CH_2 0x00000048 +#define IPU_DC_RL3_CH_2 0x0000004c +#define IPU_DC_RL4_CH_2 0x00000050 +#define IPU_DC_CMD_CH_CONF_3 0x00000054 +#define IPU_DC_CMD_CH_CONF_4 0x00000058 +#define IPU_DC_WR_CH_CONF_5 0x0000005c +#define IPU_DC_WR_CH_ADDR_5 0x00000060 +#define IPU_DC_RL0_CH_5 0x00000064 +#define IPU_DC_RL1_CH_5 0x00000068 +#define IPU_DC_RL2_CH_5 0x0000006c +#define IPU_DC_RL3_CH_5 0x00000070 +#define IPU_DC_RL4_CH_5 0x00000074 +#define IPU_DC_WR_CH_CONF_6 0x00000078 +#define IPU_DC_WR_CH_ADDR_6 0x0000007c +#define IPU_DC_RL0_CH_6 0x00000080 +#define IPU_DC_RL1_CH_6 0x00000084 +#define IPU_DC_RL2_CH_6 0x00000088 +#define IPU_DC_RL3_CH_6 0x0000008c +#define IPU_DC_RL4_CH_6 0x00000090 +#define IPU_DC_WR_CH_CONF1_8 0x00000094 +#define IPU_DC_WR_CH_CONF2_8 0x00000098 +#define IPU_DC_RL1_CH_8 0x0000009c +#define IPU_DC_RL2_CH_8 0x000000a0 +#define IPU_DC_RL3_CH_8 0x000000a4 +#define IPU_DC_RL4_CH_8 0x000000a8 +#define IPU_DC_RL5_CH_8 0x000000ac +#define IPU_DC_RL6_CH_8 0x000000b0 +#define IPU_DC_WR_CH_CONF1_9 0x000000b4 +#define IPU_DC_WR_CH_CONF2_9 0x000000b8 +#define IPU_DC_RL1_CH_9 0x000000bc +#define IPU_DC_RL2_CH_9 0x000000c0 +#define IPU_DC_RL3_CH_9 0x000000c4 +#define IPU_DC_RL4_CH_9 0x000000c8 +#define IPU_DC_RL5_CH_9 0x000000cc +#define IPU_DC_RL6_CH_9 0x000000d0 + +#define IPU_DC_RL(chan_base, evt) ((chan_base) + (evt / 2) *0x4) +#define DC_RL_CH_0 IPU_DC_RL0_CH_0 +#define DC_RL_CH_1 IPU_DC_RL0_CH_1 +#define DC_RL_CH_2 IPU_DC_RL0_CH_2 +#define DC_RL_CH_5 IPU_DC_RL0_CH_5 +#define DC_RL_CH_6 IPU_DC_RL0_CH_6 +#define DC_RL_CH_8 IPU_DC_RL0_CH_8 + +#define DC_RL_EVT_NF 0 +#define DC_RL_EVT_NL 1 +#define DC_RL_EVT_EOF 2 +#define DC_RL_EVT_NFIELD 3 +#define DC_RL_EVT_EOL 4 +#define DC_RL_EVT_EOFIELD 5 +#define DC_RL_EVT_NEW_ADDR 6 +#define DC_RL_EVT_NEW_CHAN 7 +#define DC_RL_EVT_NEW_DATA 8 + +#define IPU_DC_GEN 0x000000d4 +#define IPU_DC_DISP_CONF1_0 0x000000d8 +#define IPU_DC_DISP_CONF1_1 0x000000dc +#define IPU_DC_DISP_CONF1_2 0x000000e0 +#define IPU_DC_DISP_CONF1_3 0x000000e4 +#define IPU_DC_DISP_CONF2_0 0x000000e8 +#define IPU_DC_DISP_CONF2_1 0x000000ec +#define IPU_DC_DISP_CONF2_2 0x000000f0 +#define IPU_DC_DISP_CONF2_3 0x000000f4 +#define IPU_DC_DI0_CONF_1 0x000000f8 +#define IPU_DC_DI0_CONF_2 0x000000fc +#define IPU_DC_DI1_CONF_1 0x00000100 +#define IPU_DC_DI1_CONF_2 0x00000104 + +#define IPU_DC_MAP_CONF_PNTR(n) (0x00000108 + (n) * 4) +#define IPU_DC_MAP_CONF_0 0x00000108 +#define IPU_DC_MAP_CONF_1 0x0000010c +#define IPU_DC_MAP_CONF_2 0x00000110 +#define IPU_DC_MAP_CONF_3 0x00000114 +#define IPU_DC_MAP_CONF_4 0x00000118 +#define IPU_DC_MAP_CONF_5 0x0000011c +#define IPU_DC_MAP_CONF_6 0x00000120 +#define IPU_DC_MAP_CONF_7 0x00000124 +#define IPU_DC_MAP_CONF_8 0x00000128 +#define IPU_DC_MAP_CONF_9 0x0000012c +#define IPU_DC_MAP_CONF_10 0x00000130 +#define IPU_DC_MAP_CONF_11 0x00000134 +#define IPU_DC_MAP_CONF_12 0x00000138 +#define IPU_DC_MAP_CONF_13 0x0000013c +#define IPU_DC_MAP_CONF_14 0x00000140 + +#define IPU_DC_MAP_CONF_MASK(n) (0x00000144 + (n) * 4) +#define IPU_DC_MAP_CONF_15 0x00000144 +#define IPU_DC_MAP_CONF_16 0x00000148 +#define IPU_DC_MAP_CONF_17 0x0000014c +#define IPU_DC_MAP_CONF_18 0x00000150 +#define IPU_DC_MAP_CONF_19 0x00000154 +#define IPU_DC_MAP_CONF_20 0x00000158 +#define IPU_DC_MAP_CONF_21 0x0000015c +#define IPU_DC_MAP_CONF_22 0x00000160 +#define IPU_DC_MAP_CONF_23 0x00000164 +#define IPU_DC_MAP_CONF_24 0x00000168 +#define IPU_DC_MAP_CONF_25 0x0000016c +#define IPU_DC_MAP_CONF_26 0x00000170 + +#define IPU_DC_UGDE(m, n) (0x00000174 + (m) * 0x10 + (n) +4) +#define IPU_DC_UGDE0_0 0x00000174 +#define IPU_DC_UGDE0_1 0x00000178 +#define IPU_DC_UGDE0_2 0x0000017c +#define IPU_DC_UGDE0_3 0x00000180 +#define IPU_DC_UGDE1_0 0x00000184 +#define IPU_DC_UGDE1_1 0x00000188 +#define IPU_DC_UGDE1_2 0x0000018c +#define IPU_DC_UGDE1_3 0x00000190 +#define IPU_DC_UGDE2_0 0x00000194 +#define IPU_DC_UGDE2_1 0x00000198 +#define IPU_DC_UGDE2_2 0x0000019c +#define IPU_DC_UGDE2_3 0x000001a0 +#define IPU_DC_UGDE3_0 0x000001a4 +#define IPU_DC_UGDE3_1 0x000001a8 +#define IPU_DC_UGDE3_2 0x000001ac +#define IPU_DC_UGDE3_3 0x000001b0 +#define IPU_DC_LLA0 0x000001b4 +#define IPU_DC_LLA1 0x000001b8 +#define IPU_DC_R_LLA0 0x000001bc +#define IPU_DC_R_LLA1 0x000001c0 +#define IPU_DC_WR_CH_ADDR_5_ALT 0x000001c4 +#define IPU_DC_STAT 0x000001c8 + +/* + * DMFC + * Display Multi FIFO Controller + */ +#define IPU_DMFC_RD_CHAN 0x00000000 +#define DMFC_RD_CHAN_PPW_C 0x03000000 +#define DMFC_RD_CHAN_WM_DR_0 0x00e00000 +#define DMFC_RD_CHAN_WM_SET_0 0x001c0000 +#define DMFC_RD_CHAN_WM_EN_0 0x00020000 +#define DMFC_RD_CHAN_BURST_SIZE_0 0x000000c0 +#define IPU_DMFC_WR_CHAN 0x00000004 +#define DMFC_WR_CHAN_BUSRT_SIZE_2C 0xc0000000 +#define DMFC_WR_CHAN_FIFO_SIZE_2C 0x38000000 +#define DMFC_WR_CHAN_ST_ADDR_2C 0x07000000 +#define DMFC_WR_CHAN_BURST_SIZE_1C 0x00c00000 +#define DMFC_WR_CHAN_FIFO_SIZE_1C 0x00380000 +#define DMFC_WR_CHAN_ST_ADDR_1C 0x00070000 +#define DMFC_WR_CHAN_BURST_SIZE_2 0x0000c000 +#define DMFC_WR_CHAN_FIFO_SIZE_2 0x00003800 +#define DMFC_WR_CHAN_ST_ADDR_2 0x00000700 +#define DMFC_WR_CHAN_BURST_SIZE_1 0x000000c0 +#define DMFC_WR_CHAN_FIFO_SIZE_1 0x00000038 +#define DMFC_WR_CHAN_ST_ADDR_1 0x00000007 +#define IPU_DMFC_WR_CHAN_DEF 0x00000008 +#define DMFC_WR_CHAN_DEF_WM_CLR_2C 0xe0000000 +#define DMFC_WR_CHAN_DEF_WM_SET_2C 0x1c000000 +#define DMFC_WR_CHAN_DEF_WM_EN_2C 0x02000000 +#define DMFC_WR_CHAN_DEF_WM_CLR_1C 0x00e00000 +#define DMFC_WR_CHAN_DEF_WM_SET_1C 0x001c0000 +#define DMFC_WR_CHAN_DEF_WM_EN_1C 0x00020000 +#define DMFC_WR_CHAN_DEF_WM_CLR_2 0x0000e000 +#define DMFC_WR_CHAN_DEF_WM_SET_2 0x00001c00 +#define DMFC_WR_CHAN_DEF_WM_EN_2 0x00000200 +#define DMFC_WR_CHAN_DEF_WM_CLR_1 0x000000e0 +#define DMFC_WR_CHAN_DEF_WM_SET_1 0x0000000c +#define DMFC_WR_CHAN_DEF_WM_EN_1 0x00000002 +#define IPU_DMFC_DP_CHAN 0x0000000c +#define DMFC_DP_CHAN_BUSRT_SIZE_6F 0xc0000000 +#define DMFC_DP_CHAN_FIFO_SIZE_6F 0x38000000 +#define DMFC_DP_CHAN_ST_ADDR_6F 0x07000000 +#define DMFC_DP_CHAN_BURST_SIZE_6B 0x00c00000 +#define DMFC_DP_CHAN_FIFO_SIZE_6B 0x00380000 +#define DMFC_DP_CHAN_ST_ADDR_6B 0x00070000 +#define DMFC_DP_CHAN_BURST_SIZE_5F 0x0000c000 +#define DMFC_DP_CHAN_FIFO_SIZE_5F 0x00003800 +#define DMFC_DP_CHAN_ST_ADDR_5F 0x00000700 +#define DMFC_DP_CHAN_BURST_SIZE_5B 0x000000c0 +#define DMFC_DP_CHAN_FIFO_SIZE_5B 0x00000038 +#define DMFC_DP_CHAN_ST_ADDR_5B 0x00000007 +#define IPU_DMFC_DP_CHAN_DEF 0x00000010 +#define DMFC_DP_CHAN_DEF_WM_CLR_6F 0xe0000000 +#define DMFC_DP_CHAN_DEF_WM_SET_6F 0x1c000000 +#define DMFC_DP_CHAN_DEF_WM_EN_6F 0x02000000 +#define DMFC_DP_CHAN_DEF_WM_CLR_6B 0x00e00000 +#define DMFC_DP_CHAN_DEF_WM_SET_6B 0x001c0000 +#define DMFC_DP_CHAN_DEF_WM_EN_6B 0x00020000 +#define DMFC_DP_CHAN_DEF_WM_CLR_5F 0x0000e000 +#define DMFC_DP_CHAN_DEF_WM_SET_5F 0x00001c00 +#define DMFC_DP_CHAN_DEF_WM_EN_5F 0x00000200 +#define DMFC_DP_CHAN_DEF_WM_CLR_5B 0x000000e0 +#define DMFC_DP_CHAN_DEF_WM_SET_5B 0x0000001c +#define DMFC_DP_CHAN_DEF_WM_EN_5B 0x00000002 +#define IPU_DMFC_GENERAL1 0x00000014 +#define DMFC_GENERAL1_WAIT4EOT_9 0x01000000 +#define DMFC_GENERAL1_WAIT4EOT_6F 0x00800000 +#define DMFC_GENERAL1_WAIT4EOT_6B 0x00400000 +#define DMFC_GENERAL1_WAIT4EOT_5F 0x00200000 +#define DMFC_GENERAL1_WAIT4EOT_5B 0x00100000 +#define DMFC_GENERAL1_WAIT4EOT_4 0x00080000 +#define DMFC_GENERAL1_WAIT4EOT_3 0x00040000 +#define DMFC_GENERAL1_WAIT4EOT_2 0x00020000 +#define DMFC_GENERAL1_WAIT4EOT_1 0x00010000 +#define DMFC_GENERAL1_WM_CLR_9 0x0000e000 +#define DMFC_GENERAL1_WM_SET_9 0x00001c00 +#define DMFC_GENERAL1_BURST_SIZE_9 0x00000060 +#define DMFC_GENERAL1_DCDP_SYNC_PR 0x00000003 +#define DCDP_SYNC_PR_FORBIDDEN 0 +#define DCDP_SYNC_PR_DC_DP 1 +#define DCDP_SYNC_PR_DP_DC 2 +#define DCDP_SYNC_PR_ROUNDROBIN 3 +#define IPU_DMFC_GENERAL2 0x00000018 +#define DMFC_GENERAL2_FRAME_HEIGHT_RD 0x1fff0000 +#define DMFC_GENERAL2_FRAME_WIDTH_RD 0x00001fff +#define IPU_DMFC_IC_CTRL 0x0000001c +#define DMFC_IC_CTRL_IC_FRAME_HEIGHT_RD 0xfff80000 +#define DMFC_IC_CTRL_IC_FRAME_WIDTH_RD 0x0007ffc0 +#define DMFC_IC_CTRL_IC_PPW_C 0x00000030 +#define DMFC_IC_CTRL_IC_IN_PORT 0x00000007 +#define IC_IN_PORT_CH28 0 +#define IC_IN_PORT_CH41 1 +#define IC_IN_PORT_DISABLE 2 +#define IC_IN_PORT_CH23 4 +#define IC_IN_PORT_CH27 5 +#define IC_IN_PORT_CH24 6 +#define IC_IN_PORT_CH29 7 +#define IPU_DMFC_WR_CHAN_ALT 0x00000020 +#define IPU_DMFC_WR_CHAN_DEF_ALT 0x00000024 +#define IPU_DMFC_DP_CHAN_ALT 0x00000028 +#define IPU_DMFC_DP_CHAN_DEF_ALT 0x0000002c +#define DMFC_DP_CHAN_DEF_ALT_WM_CLR_6F_ALT 0xe0000000 +#define DMFC_DP_CHAN_DEF_ALT_WM_SET_6F_ALT 0x1c000000 +#define DMFC_DP_CHAN_DEF_ALT_WM_EN_6F_ALT 0x02000000 +#define DMFC_DP_CHAN_DEF_ALT_WM_CLR_6B_ALT 0x00e00000 +#define DMFC_DP_CHAN_DEF_ALT_WM_SET_6B_ALT 0x001c0000 +#define DMFC_DP_CHAN_DEF_ALT_WM_EN_6B_ALT 0x00020000 +#define DMFC_DP_CHAN_DEF_ALT_WM_CLR_5B_ALT 0x000000e0 +#define DMFC_DP_CHAN_DEF_ALT_WM_SET_5B_ALT 0x0000001c +#define DMFC_DP_CHAN_DEF_ALT_WM_EN_5B_ALT 0x00000002 +#define IPU_DMFC_GENERAL1_ALT 0x00000030 +#define DMFC_GENERAL1_ALT_WAIT4EOT_6F_ALT 0x00800000 +#define DMFC_GENERAL1_ALT_WAIT4EOT_6B_ALT 0x00400000 +#define DMFC_GENERAL1_ALT_WAIT4EOT_5B_ALT 0x00100000 +#define DMFC_GENERAL1_ALT_WAIT4EOT_2_ALT 0x00020000 +#define IPU_DMFC_STAT 0x00000034 +#define DMFC_STAT_IC_BUFFER_EMPTY 0x02000000 +#define DMFC_STAT_IC_BUFFER_FULL 0x01000000 +#define DMFC_STAT_FIFO_EMPTY(n) __BIT(12 + (n)) +#define DMFC_STAT_FIFO_FULL(n) __BIT((n)) + +/* + * VCI + * Video De Interkacing Module + */ +#define IPU_VDI_FSIZE 0x00000000 +#define IPU_VDI_C 0x00000004 + +/* + * DP + * Display Processor + */ +#define IPU_DP_COM_CONF_SYNC 0x00000000 +#define DP_FG_EN_SYNC 0x00000001 +#define DP_DP_GWAM_SYNC 0x00000004 +#define IPU_DP_GRAPH_WIND_CTRL_SYNC 0x00000004 +#define IPU_DP_FG_POS_SYNC 0x00000008 +#define IPU_DP_CUR_POS_SYNC 0x0000000c +#define IPU_DP_CUR_MAP_SYNC 0x00000010 +#define IPU_DP_CSC_SYNC_0 0x00000054 +#define IPU_DP_CSC_SYNC_1 0x00000058 +#define IPU_DP_CUR_POS_ALT 0x0000005c +#define IPU_DP_COM_CONF_ASYNC0 0x00000060 +#define IPU_DP_GRAPH_WIND_CTRL_ASYNC0 0x00000064 +#define IPU_DP_FG_POS_ASYNC0 0x00000068 +#define IPU_DP_CUR_POS_ASYNC0 0x0000006c +#define IPU_DP_CUR_MAP_ASYNC0 0x00000070 +#define IPU_DP_CSC_ASYNC0_0 0x000000b4 +#define IPU_DP_CSC_ASYNC0_1 0x000000b8 +#define IPU_DP_COM_CONF_ASYNC1 0x000000bc +#define IPU_DP_GRAPH_WIND_CTRL_ASYNC1 0x000000c0 +#define IPU_DP_FG_POS_ASYNC1 0x000000c4 +#define IPU_DP_CUR_POS_ASYNC1 0x000000c8 +#define IPU_DP_CUR_MAP_ASYNC1 0x000000cc +#define IPU_DP_CSC_ASYNC1_0 0x00000110 +#define IPU_DP_CSC_ASYNC1_1 0x00000114 + +/* IDMA parameter */ + /* + * non-Interleaved parameter + * + * param 0: XV W0[ 9: 0] + * YV W0[18:10] + * XB W0[31:19] + * param 1: YB W0[43:32] + * NSB W0[44] + * CF W0[45] + * UBO W0[61:46] + * param 2: UBO W0[67:62] + * VBO W0[89:68] + * IOX W0[93:90] + * RDRW W0[94] + * Reserved W0[95] + * param 3: Reserved W0[112:96] + * S0 W0[113] + * BNDM W0[116:114] + * BM W0[118:117] + * ROT W0[119] + * HF W0[120] + * VF W0[121] + * THF W0[122] + * CAP W0[123] + * CAE W0[124] + * FW W0[127:125] + * param 4: FW W0[137:128] + * FH W0[149:138] + * param 5: EBA0 W1[28:0] + * EBA1 W1[31:29] + * param 6: EBA1 W1[57:32] + * ILO W1[63:58] + * param 7: ILO W1[77:64] + * NPB W1[84:78] + * PFS W1[88:85] + * ALU W1[89] + * ALBM W1[92:90] + * ID W1[94:93] + * TH W1[95] + * param 8: TH W1[101:96] + * SLY W1[115:102] + * WID3 W1[127:125] + * param 9: SLUV W1[141:128] + * CRE W1[149] + * + * Interleaved parameter + * + * param 0: XV W0[ 9: 0] + * YV W0[18:10] + * XB W0[31:19] + * param 1: YB W0[43:32] + * NSB W0[44] + * CF W0[45] + * SX W0[57:46] + * SY W0[61:58] + * param 2: SY W0[68:62] + * NS W0[78:69] + * SDX W0[85:79] + * SM W0[95:86] + * param 3: SCC W0[96] + * SCE W0[97] + * SDY W0[104:98] + * SDRX W0[105] + * SDRY W0[106] + * BPP W0[109:107] + * DEC_SEL W0[111:110] + * DIM W0[112] + * SO W0[113] + * BNDM W0[116:114] + * BM W0[118:117] + * ROT W0[119] + * HF W0[120] + * VF W0[121] + * THF W0[122] + * CAP W0[123] + * CAE W0[124] + * FW W0[127:125] + * param 4: FW W0[137:128] + * FH W0[149:138] + * param 5: EBA0 W1[28:0] + * EBA1 W1[31:29] + * param 6: EBA1 W1[57:32] + * ILO W1[63:58] + * param 7: ILO W1[77:64] + * NPB W1[84:78] + * PFS W1[88:85] + * ALU W1[89] + * ALBM W1[92:90] + * ID W1[94:93] + * TH W1[95] + * param 8: TH W1[101:96] + * SL W1[115:102] + * WID0 W1[118:116] + * WID1 W1[121:119] + * WID2 W1[124:122] + * WID3 W1[127:125] + * param 9: OFS0 W1[132:128] + * OFS1 W1[137:133] + * OFS2 W1[142:138] + * OFS3 W1[147:143] + * SXYS W1[148] + * CRE W1[149] + * DEC_SEL2 W1[150] + */ + +#define __IDMA_PARAM(word, shift, size) \ + ((((word) & 0xff) << 16) | (((shift) & 0xff) << 8) | ((size) & 0xff)) + +/* non-Interleaved parameter */ +/* W0 */ +#define IDMAC_Ch_PARAM_XV __IDMA_PARAM(0, 0, 10) +#define IDMAC_Ch_PARAM_YV __IDMA_PARAM(0, 10, 9) +#define IDMAC_Ch_PARAM_XB __IDMA_PARAM(0, 19, 13) +#define IDMAC_Ch_PARAM_YB __IDMA_PARAM(0, 32, 12) +#define IDMAC_Ch_PARAM_NSB __IDMA_PARAM(0, 44, 1) +#define IDMAC_Ch_PARAM_CF __IDMA_PARAM(0, 45, 1) +#define IDMAC_Ch_PARAM_UBO __IDMA_PARAM(0, 46, 22) +#define IDMAC_Ch_PARAM_VBO __IDMA_PARAM(0, 68, 22) +#define IDMAC_Ch_PARAM_IOX __IDMA_PARAM(0, 90, 4) +#define IDMAC_Ch_PARAM_RDRW __IDMA_PARAM(0, 94, 1) +#define IDMAC_Ch_PARAM_S0 __IDMA_PARAM(0,113, 1) +#define IDMAC_Ch_PARAM_BNDM __IDMA_PARAM(0,114, 3) +#define IDMAC_Ch_PARAM_BM __IDMA_PARAM(0,117, 2) +#define IDMAC_Ch_PARAM_ROT __IDMA_PARAM(0,119, 1) +#define IDMAC_Ch_PARAM_HF __IDMA_PARAM(0,120, 1) +#define IDMAC_Ch_PARAM_VF __IDMA_PARAM(0,121, 1) +#define IDMAC_Ch_PARAM_THF __IDMA_PARAM(0,122, 1) +#define IDMAC_Ch_PARAM_CAP __IDMA_PARAM(0,123, 1) +#define IDMAC_Ch_PARAM_CAE __IDMA_PARAM(0,124, 1) +#define IDMAC_Ch_PARAM_FW __IDMA_PARAM(0,125, 13) +#define IDMAC_Ch_PARAM_FH __IDMA_PARAM(0,138, 12) +/* W1 */ +#define IDMAC_Ch_PARAM_EBA0 __IDMA_PARAM(1, 0, 29) +#define IDMAC_Ch_PARAM_EBA1 __IDMA_PARAM(1, 29, 29) +#define IDMAC_Ch_PARAM_ILO __IDMA_PARAM(1, 58, 20) +#define IDMAC_Ch_PARAM_NPB __IDMA_PARAM(1, 78, 7) +#define IDMAC_Ch_PARAM_PFS __IDMA_PARAM(1, 85, 4) +#define IDMAC_Ch_PARAM_ALU __IDMA_PARAM(1, 89, 1) +#define IDMAC_Ch_PARAM_ALBM __IDMA_PARAM(1, 90, 3) +#define IDMAC_Ch_PARAM_ID __IDMA_PARAM(1, 93, 2) +#define IDMAC_Ch_PARAM_TH __IDMA_PARAM(1, 95, 7) +#define IDMAC_Ch_PARAM_SL __IDMA_PARAM(1,102, 14) +#define IDMAC_Ch_PARAM_WID3 __IDMA_PARAM(1,125, 3) +#define IDMAC_Ch_PARAM_SLUV __IDMA_PARAM(1,128, 14) +#define IDMAC_Ch_PARAM_CRE __IDMA_PARAM(1,149, 1) + +/* Interleaved parameter */ +/* W0 */ +#define IDMAC_Ch_PARAM_XV __IDMA_PARAM(0, 0, 10) +#define IDMAC_Ch_PARAM_YV __IDMA_PARAM(0, 10, 9) +#define IDMAC_Ch_PARAM_XB __IDMA_PARAM(0, 19, 13) +#define IDMAC_Ch_PARAM_YB __IDMA_PARAM(0, 32, 12) +#define IDMAC_Ch_PARAM_NSB __IDMA_PARAM(0, 44, 1) +#define IDMAC_Ch_PARAM_CF __IDMA_PARAM(0, 45, 1) +#define IDMAC_Ch_PARAM_SX __IDMA_PARAM(0, 46, 12) +#define IDMAC_Ch_PARAM_SY __IDMA_PARAM(0, 58, 11) +#define IDMAC_Ch_PARAM_NS __IDMA_PARAM(0, 69, 10) +#define IDMAC_Ch_PARAM_SDX __IDMA_PARAM(0, 79, 7) +#define IDMAC_Ch_PARAM_SM __IDMA_PARAM(0, 86, 10) +#define IDMAC_Ch_PARAM_SCC __IDMA_PARAM(0, 96, 1) +#define IDMAC_Ch_PARAM_SCE __IDMA_PARAM(0, 97, 1) +#define IDMAC_Ch_PARAM_SDY __IDMA_PARAM(0, 98, 7) +#define IDMAC_Ch_PARAM_SDRX __IDMA_PARAM(0,105, 1) +#define IDMAC_Ch_PARAM_SDRY __IDMA_PARAM(0,106, 1) +#define IDMAC_Ch_PARAM_BPP __IDMA_PARAM(0,107, 3) +#define IDMAC_Ch_PARAM_DEC_SEL __IDMA_PARAM(0,110, 2) +#define IDMAC_Ch_PARAM_DIM __IDMA_PARAM(0,112, 1) +#define IDMAC_Ch_PARAM_SO __IDMA_PARAM(0,113, 1) +#define IDMAC_Ch_PARAM_BNDM __IDMA_PARAM(0,114, 3) +#define IDMAC_Ch_PARAM_BM __IDMA_PARAM(0,117, 2) +#define IDMAC_Ch_PARAM_ROT __IDMA_PARAM(0,119, 1) +#define IDMAC_Ch_PARAM_HF __IDMA_PARAM(0,120, 1) +#define IDMAC_Ch_PARAM_VF __IDMA_PARAM(0,121, 1) +#define IDMAC_Ch_PARAM_THF __IDMA_PARAM(0,122, 1) +#define IDMAC_Ch_PARAM_CAP __IDMA_PARAM(0,123, 1) +#define IDMAC_Ch_PARAM_CAE __IDMA_PARAM(0,124, 1) +#define IDMAC_Ch_PARAM_FW __IDMA_PARAM(0,125, 13) +#define IDMAC_Ch_PARAM_FH __IDMA_PARAM(0,138, 12) +/* W1 */ +#define IDMAC_Ch_PARAM_EBA0 __IDMA_PARAM(1, 0, 29) +#define IDMAC_Ch_PARAM_EBA1 __IDMA_PARAM(1, 29, 29) +#define IDMAC_Ch_PARAM_ILO __IDMA_PARAM(1, 58, 20) +#define IDMAC_Ch_PARAM_NPB __IDMA_PARAM(1, 78, 7) +#define IDMAC_Ch_PARAM_PFS __IDMA_PARAM(1, 85, 4) +#define IDMAC_Ch_PARAM_ALU __IDMA_PARAM(1, 89, 1) +#define IDMAC_Ch_PARAM_ALBM __IDMA_PARAM(1, 90, 3) +#define IDMAC_Ch_PARAM_ID __IDMA_PARAM(1, 93, 2) +#define IDMAC_Ch_PARAM_TH __IDMA_PARAM(1, 95, 7) +#define IDMAC_Ch_PARAM_SL __IDMA_PARAM(1,102, 14) +#define IDMAC_Ch_PARAM_WID0 __IDMA_PARAM(1,116, 3) +#define IDMAC_Ch_PARAM_WID1 __IDMA_PARAM(1,119, 3) +#define IDMAC_Ch_PARAM_WID2 __IDMA_PARAM(1,122, 3) +#define IDMAC_Ch_PARAM_WID3 __IDMA_PARAM(1,125, 3) +#define IDMAC_Ch_PARAM_OFS0 __IDMA_PARAM(1,128, 5) +#define IDMAC_Ch_PARAM_OFS1 __IDMA_PARAM(1,133, 5) +#define IDMAC_Ch_PARAM_OFS2 __IDMA_PARAM(1,138, 5) +#define IDMAC_Ch_PARAM_OFS3 __IDMA_PARAM(1,143, 5) +#define IDMAC_Ch_PARAM_SXYS __IDMA_PARAM(1,148, 1) +#define IDMAC_Ch_PARAM_CRE __IDMA_PARAM(1,149, 1) +#define IDMAC_Ch_PARAM_DEC_SEL2 __IDMA_PARAM(1,150, 1) + +/* XXX Temp */ +#define GPUMEM_BASE 0x20000000 +#define GPUMEM_SIZE 0x20000 + +#define GPU_BASE 0x30000000 +#define GPU_SIZE 0x10000000 + +/* Image Prossasing Unit */ +#define IPU_BASE 0x40000000 +#define IPU_CM_BASE (IPU_BASE + 0x1e000000) +#define IPU_CM_SIZE 0x8000 +#define IPU_IDMAC_BASE (IPU_BASE + 0x1e008000) +#define IPU_IDMAC_SIZE 0x8000 +#define IPU_DP_BASE (IPU_BASE + 0x1e018000) +#define IPU_DP_SIZE 0x8000 +#define IPU_IC_BASE (IPU_BASE + 0x1e020000) +#define IPU_IC_SIZE 0x8000 +#define IPU_IRT_BASE (IPU_BASE + 0x1e028000) +#define IPU_IRT_SIZE 0x8000 +#define IPU_CSI0_BASE (IPU_BASE + 0x1e030000) +#define IPU_CSI0_SIZE 0x8000 +#define IPU_CSI1_BASE (IPU_BASE + 0x1e038000) +#define IPU_CSI1_SIZE 0x8000 +#define IPU_DI0_BASE (IPU_BASE + 0x1e040000) +#define IPU_DI0_SIZE 0x8000 +#define IPU_DI1_BASE (IPU_BASE + 0x1e048000) +#define IPU_DI1_SIZE 0x8000 +#define IPU_SMFC_BASE (IPU_BASE + 0x1e050000) +#define IPU_SMFC_SIZE 0x8000 +#define IPU_DC_BASE (IPU_BASE + 0x1e058000) +#define IPU_DC_SIZE 0x8000 +#define IPU_DMFC_BASE (IPU_BASE + 0x1e060000) +#define IPU_DMFC_SIZE 0x8000 +#define IPU_VDI_BASE (IPU_BASE + 0x1e068000) +#define IPU_VDI_SIZE 0x8000 +#define IPU_CPMEM_BASE (IPU_BASE + 0x1f000000) +#define IPU_CPMEM_SIZE 0x20000 +#define IPU_LUT_BASE (IPU_BASE + 0x1f020000) +#define IPU_LUT_SIZE 0x20000 +#define IPU_SRM_BASE (IPU_BASE + 0x1f040000) +#define IPU_SRM_SIZE 0x20000 +#define IPU_TPM_BASE (IPU_BASE + 0x1f060000) +#define IPU_TPM_SIZE 0x20000 +#define IPU_DCTMPL_BASE (IPU_BASE + 0x1f080000) +#define IPU_DCTMPL_SIZE 0x20000 + +#endif /* _ARM_IMX_IMX51_IPUV3REG_H */ diff --git a/sys/arm/freescale/imx/imx51_sdmareg.h b/sys/arm/freescale/imx/imx51_sdmareg.h new file mode 100644 index 0000000..cc9cacb --- /dev/null +++ b/sys/arm/freescale/imx/imx51_sdmareg.h @@ -0,0 +1,142 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Oleksandr Rybalko under sponsorship + * from the FreeBSD Foundation. + * + * 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$ + */ + +/* Internal Registers definition for Freescale i.MX515 SDMA Core */ + +/* SDMA Core Instruction Memory Space */ +#define SDMA_IBUS_ROM_ADDR_BASE 0x0000 +#define SDMA_IBUS_ROM_ADDR_SIZE 0x07ff +#define SDMA_IBUS_RAM_ADDR_BASE 0x1000 +#define SDMA_IBUS_RAM_ADDR_SIZE 0x1fff + +/* SDMA Core Internal Registers */ +#define SDMA_MC0PTR 0x7000 /* AP (MCU) Channel 0 Pointer R */ + +#define SDMA_CCPTR 0x7002 /* Current Channel Pointer R */ +#define SDMA_ECTL_CCPTR_MASK 0x0000ffff +#define SDMA_ECTL_CCPTR_SHIFT 0 + +#define SDMA_CCR 0x7003 /* Current Channel Register R */ +#define SDMA_ECTL_CCR_MASK 0x0000001f +#define SDMA_ECTL_CCR_SHIFT 0 + +#define SDMA_NCR 0x7004 /* Highest Pending Channel Register R */ +#define SDMA_ECTL_NCR_MASK 0x0000001f +#define SDMA_ECTL_NCR_SHIFT 0 + +#define SDMA_EVENTS 0x7005 /* External DMA Requests Mirror R */ + +#define SDMA_CCPRI 0x7006 /* Current Channel Priority R */ +#define SDMA_ECTL_CCPRI_MASK 0x00000007 +#define SDMA_ECTL_CCPRI_SHIFT 0 + +#define SDMA_NCPRI 0x7007 /* Next Channel Priority R */ +#define SDMA_ECTL_NCPRI_MASK 0x00000007 +#define SDMA_ECTL_NCPRI_SHIFT 0 + +#define SDMA_ECOUNT 0x7009 /* OnCE Event Cell Counter R/W */ +#define SDMA_ECTL_ECOUNT_MASK 0x0000ffff +#define SDMA_ECTL_ECOUNT_SHIFT 0 + +#define SDMA_ECTL 0x700A /* OnCE Event Cell Control Register R/W */ +#define SDMA_ECTL_EN (1 << 13) +#define SDMA_ECTL_CNT (1 << 12) +#define SDMA_ECTL_ECTC_MASK 0x00000c00 +#define SDMA_ECTL_ECTC_SHIFT 10 +#define SDMA_ECTL_DTC_MASK 0x00000300 +#define SDMA_ECTL_DTC_SHIFT 8 +#define SDMA_ECTL_ATC_MASK 0x000000c0 +#define SDMA_ECTL_ATC_SHIFT 6 +#define SDMA_ECTL_ABTC_MASK 0x00000030 +#define SDMA_ECTL_ABTC_SHIFT 4 +#define SDMA_ECTL_AATC_MASK 0x0000000c +#define SDMA_ECTL_AATC_SHIFT 2 +#define SDMA_ECTL_ATS_MASK 0x00000003 +#define SDMA_ECTL_ATS_SHIFT 0 + +#define SDMA_EAA 0x700B /* OnCE Event Address Register A R/W */ +#define SDMA_ECTL_EAA_MASK 0x0000ffff +#define SDMA_ECTL_EAA_SHIFT 0 + +#define SDMA_EAB 0x700C /* OnCE Event Cell Address Register B R/W */ +#define SDMA_ECTL_EAB_MASK 0x0000ffff +#define SDMA_ECTL_EAB_SHIFT 0 + +#define SDMA_EAM 0x700D /* OnCE Event Cell Address Mask R/W */ +#define SDMA_ECTL_EAM_MASK 0x0000ffff +#define SDMA_ECTL_EAM_SHIFT 0 + +#define SDMA_ED 0x700E /* OnCE Event Cell Data Register R/W */ +#define SDMA_EDM 0x700F /* OnCE Event Cell Data Mask R/W */ +#define SDMA_RTB 0x7018 /* OnCE Real-Time Buffer R/W */ + +#define SDMA_TB 0x7019 /* OnCE Trace Buffer R */ +#define SDMA_TB_TBF (1 << 28) +#define SDMA_TB_TADDR_MASK 0x0fffc000 +#define SDMA_TB_TADDR_SHIFT 14 +#define SDMA_TB_CHFADDR_MASK 0x00003fff +#define SDMA_TB_CHFADDR_SHIFT 0 + +#define SDMA_OSTAT 0x701A /* OnCE Status R */ +#define SDMA_OSTAT_PST_MASK 0x0000f000 +#define SDMA_OSTAT_PST_SHIFT 12 +#define SDMA_OSTAT_RCV (1 << 11) +#define SDMA_OSTAT_EDR (1 << 10) +#define SDMA_OSTAT_ODR (1 << 9) +#define SDMA_OSTAT_SWB (1 << 8) +#define SDMA_OSTAT_MST (1 << 7) +#define SDMA_OSTAT_ECDR_MASK 0x00000007 +#define SDMA_OSTAT_ECDR_SHIFT 0 + +#define SDMA_MCHN0ADDR 0x701C /* Channel 0 Boot Address R */ +#define SDMA_MCHN0ADDR_SMS_Z (1 << 14) +#define SDMA_MCHN0ADDR_CHN0ADDR_MASK 0x00003fff +#define SDMA_MCHN0ADDR_CHN0ADDR_SHIFT 0 + +#define SDMA_MODE 0x701D /* Mode Status Register R */ +#define SDMA_MODE_DSPCtrl (1 << 3) +#define SDMA_MODE_AP_END (1 << 0) + +#define SDMA_LOCK 0x701E /* Lock Status Register R */ +#define SDMA_LOCK_LOCK (1 << 0) + +#define SDMA_EVENTS2 0x701F /* External DMA Requests Mirror #2 R */ + +#define SDMA_HE 0x7020 /* AP Enable Register R */ +#define SDMA_PRIV 0x7022 /* Current Channel BP Privilege Register R */ +#define SDMA_PRIV_BPPRIV (1 << 0) +#define SDMA_PRF_CNT 0x7023 /* Profile Free Running Register R/W */ +#define SDMA_PRF_CNT_SEL_MASK 0xc0000000 +#define SDMA_PRF_CNT_SEL_SHIFT 30 +#define SDMA_PRF_CNT_EN (1 << 29) +#define SDMA_PRF_CNT_OFL (1 << 22) +#define SDMA_PRF_CNT_COUNTER_MASK 0x003fffff +#define SDMA_PRF_CNT_COUNTER_SHIFT 0 diff --git a/sys/arm/freescale/imx/imx51_ssireg.h b/sys/arm/freescale/imx/imx51_ssireg.h new file mode 100644 index 0000000..1a5b5b3 --- /dev/null +++ b/sys/arm/freescale/imx/imx51_ssireg.h @@ -0,0 +1,180 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Oleksandr Rybalko under sponsorship + * from the FreeBSD Foundation. + * + * 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$ + */ + +/* Registers definition for Freescale i.MX515 Synchronous Serial Interface */ + +#define IMX51_SSI_STX0_REG 0x0000 /* SSI TX Data Register 0 */ +#define IMX51_SSI_STX1_REG 0x0004 /* SSI TX Data Register 1 */ +#define IMX51_SSI_SRX0_REG 0x0008 /* SSI RX Data Register 0 */ +#define IMX51_SSI_SRX1_REG 0x000C /* SSI RX Data Register 1 */ +#define IMX51_SSI_SCR_REG 0x0010 /* SSI Control Register */ +#define SSI_SCR_RFR_CLK_DIS (1 << 11) /* RX FC Disable */ +#define SSI_SCR_TFR_CLK_DIS (1 << 10) /* TX FC Disable */ +#define SSI_SCR_CLK_IST (1 << 9) /* Clock Idle */ +#define SSI_SCR_TCH_EN (1 << 8) /* 2Chan Enable */ +#define SSI_SCR_SYS_CLK_EN (1 << 7) /* System Clock En */ +#define SSI_SCR_MODE_NORMAL (0 << 5) +#define SSI_SCR_MODE_I2S_MASTER (1 << 5) +#define SSI_SCR_MODE_I2S_SLAVE (2 << 5) +#define SSI_SCR_MODE_MASK (3 << 5) +#define SSI_SCR_SYN (1 << 4) /* Sync Mode */ +#define SSI_SCR_NET (1 << 3) /* Network Mode */ +#define SSI_SCR_RE (1 << 2) /* RX Enable */ +#define SSI_SCR_TE (1 << 1) /* TX Enable */ +#define SSI_SCR_SSIEN (1 << 0) /* SSI Enable */ + +#define IMX51_SSI_SISR_REG 0x0014 /* SSI Interrupt Status Register */ +#define SSI_SISR_RFRC (1 << 24) /* RX Frame Complete */ +#define SSI_SIR_TFRC (1 << 23) /* TX Frame Complete */ +#define SSI_SIR_CMDAU (1 << 18) /* Command Address Updated */ +#define SSI_SIR_CMDDU (1 << 17) /* Command Data Updated */ +#define SSI_SIR_RXT (1 << 16) /* RX Tag Updated */ +#define SSI_SIR_RDR1 (1 << 15) /* RX Data Ready 1 */ +#define SSI_SIR_RDR0 (1 << 14) /* RX Data Ready 0 */ +#define SSI_SIR_TDE1 (1 << 13) /* TX Data Reg Empty 1 */ +#define SSI_SIR_TDE0 (1 << 12) /* TX Data Reg Empty 0 */ +#define SSI_SIR_ROE1 (1 << 11) /* RXer Overrun Error 1 */ +#define SSI_SIR_ROE0 (1 << 10) /* RXer Overrun Error 0 */ +#define SSI_SIR_TUE1 (1 << 9) /* TXer Underrun Error 1 */ +#define SSI_SIR_TUE0 (1 << 8) /* TXer Underrun Error 0 */ +#define SSI_SIR_TFS (1 << 7) /* TX Frame Sync */ +#define SSI_SIR_RFS (1 << 6) /* RX Frame Sync */ +#define SSI_SIR_TLS (1 << 5) /* TX Last Time Slot */ +#define SSI_SIR_RLS (1 << 4) /* RX Last Time Slot */ +#define SSI_SIR_RFF1 (1 << 3) /* RX FIFO Full 1 */ +#define SSI_SIR_RFF0 (1 << 2) /* RX FIFO Full 0 */ +#define SSI_SIR_TFE1 (1 << 1) /* TX FIFO Empty 1 */ +#define SSI_SIR_TFE0 (1 << 0) /* TX FIFO Empty 0 */ + +#define IMX51_SSI_SIER_REG 0x0018 /* SSI Interrupt Enable Register */ +/* 24-23 Enable Bit (See SISR) */ +#define SSI_SIER_RDMAE (1 << 22) /* RX DMA Enable */ +#define SSI_SIER_RIE (1 << 21) /* RX Interrupt Enable */ +#define SSI_SIER_TDMAE (1 << 20) /* TX DMA Enable */ +#define SSI_SIER_TIE (1 << 19) /* TX Interrupt Enable */ +/* 18-0 Enable Bits (See SISR) */ + +#define IMX51_SSI_STCR_REG 0x001C /* SSI TX Configuration Register */ +#define SSI_STCR_TXBIT0 (1 << 9) /* TX Bit 0 */ +#define SSI_STCR_TFEN1 (1 << 8) /* TX FIFO Enable 1 */ +#define SSI_STCR_TFEN0 (1 << 7) /* TX FIFO Enable 0 */ +#define SSI_STCR_TFDIR (1 << 6) /* TX Frame Direction */ +#define SSI_STCR_TXDIR (1 << 5) /* TX Clock Direction */ +#define SSI_STCR_TSHFD (1 << 4) /* TX Shift Direction */ +#define SSI_STCR_TSCKP (1 << 3) /* TX Clock Polarity */ +#define SSI_STCR_TFSI (1 << 2) /* TX Frame Sync Invert */ +#define SSI_STCR_TFSL (1 << 1) /* TX Frame Sync Length */ +#define SSI_STCR_TEFS (1 << 0) /* TX Early Frame Sync */ + +#define IMX51_SSI_SRCR_REG 0x0020 /* SSI RX Configuration Register */ +#define SSI_SRCR_RXEXT (1 << 10) /* RX Data Extension */ +#define SSI_SRCR_RXBIT0 (1 << 9) /* RX Bit 0 */ +#define SSI_SRCR_RFEN1 (1 << 8) /* RX FIFO Enable 1 */ +#define SSI_SRCR_RFEN0 (1 << 7) /* RX FIFO Enable 0 */ +#define SSI_SRCR_RFDIR (1 << 6) /* RX Frame Direction */ +#define SSI_SRCR_RXDIR (1 << 5) /* RX Clock Direction */ +#define SSI_SRCR_RSHFD (1 << 4) /* RX Shift Direction */ +#define SSI_SRCR_RSCKP (1 << 3) /* RX Clock Polarity */ +#define SSI_SRCR_RFSI (1 << 2) /* RX Frame Sync Invert */ +#define SSI_SRCR_RFSL (1 << 1) /* RX Frame Sync Length */ +#define SSI_SRCR_REFS (1 << 0) /* RX Early Frame Sync */ + +#define IMX51_SSI_STCCR_REG 0x0024 /* TX Clock Control */ +#define IMX51_SSI_SRCCR_REG 0x0028 /* RX Clock Control */ +#define SSI_SXCCR_DIV2 (1 << 18) /* Divide By 2 */ +#define SSI_SXCCR_PSR (1 << 17) /* Prescaler Range */ +#define SSI_SXCCR_WL_MASK 0x0001e000 +#define SSI_SXCCR_WL_SHIFT 13 /* Word Length Control */ +#define SSI_SXCCR_DC_MASK 0x00001f00 +#define SSI_SXCCR_DC_SHIFT 8 /* Frame Rate Divider */ +#define SSI_SXCCR_PM_MASK 0x000000ff +#define SSI_SXCCR_PM_SHIFT 0 /* Prescaler Modulus */ + +#define IMX51_SSI_SFCSR_REG 0x002C /* SSI FIFO Control/Status Register */ +#define SSI_SFCSR_RFCNT1_MASK 0xf0000000 +#define SSI_SFCSR_RFCNT1_SHIFT 28 /* RX FIFO Counter 1 */ +#define SSI_SFCSR_TFCNT1_MASK 0x0f000000 +#define SSI_SFCSR_TFCNT1_SHIFT 24 /* TX FIFO Counter 1 */ +#define SSI_SFCSR_RFWM1_MASK 0x00f00000 +#define SSI_SFCSR_RFWM1_SHIFT 20 /* RX FIFO Full WaterMark 1 */ +#define SSI_SFCSR_TFWM1_MASK 0x000f0000 +#define SSI_SFCSR_TFWM1_SHIFT 16 /* TX FIFO Empty WaterMark 1 */ +#define SSI_SFCSR_RFCNT0_MASK 0x0000f000 +#define SSI_SFCSR_RFCNT0_SHIFT 12 /* RX FIFO Counter 0 */ +#define SSI_SFCSR_TFCNT0_MASK 0x00000f00 +#define SSI_SFCSR_TFCNT0_SHIFT 8 /* TX FIFO Counter 0 */ +#define SSI_SFCSR_RFWM0_MASK 0x000000f0 +#define SSI_SFCSR_RFWM0_SHIFT 4 /* RX FIFO Full WaterMark 0 */ +#define SSI_SFCSR_TFWM0_MASK 0x0000000f +#define SSI_SFCSR_TFWM0_SHIFT 0 /* TX FIFO Empty WaterMark 0 */ + +#define IMX51_SSI_STR_REG 0x0030 /* SSI Test Register1 */ +#define SSI_STR_TEST (1 << 15) /* Test Mode */ +#define SSI_STR_RCK2TCK (1 << 14) /* RX<->TX Clock Loop Back */ +#define SSI_STR_RFS2TFS (1 << 13) /* RX<->TX Frame Loop Back */ +#define SSI_STR_RXSTATE_MASK 0x00001f00 +#define SSI_STR_RXSTATE_SHIFT 8 /* RXer State Machine Status */ +#define SSI_STR_TXD2RXD (1 << 7) /* TX<->RX Data Loop Back */ +#define SSI_STR_TCK2RCK (1 << 6) /* TX<->RX Clock Loop Back */ +#define SSI_STR_TFS2RFS (1 << 5) /* TX<->RX Frame Loop Back */ +#define SSI_STR_TXSTATE_MASK 0x0000001f +#define SSI_STR_TXSTATE_SHIFT 0 /* TXer State Machine Status */ + +#define IMX51_SSI_SOR_REG 0x0034 /* SSI Option Register2 */ +#define SSI_SOR_CLKOFF (1 << 6) /* Clock Off */ +#define SSI_SOR_RX_CLR (1 << 5) /* RXer Clear */ +#define SSI_SOR_TX_CLR (1 << 4) /* TXer Clear */ +#define SSI_SOR_INIT (1 << 3) /* Initialize */ +#define SSI_SOR_WAIT_MASK 0x00000006 +#define SSI_SOR_INIT_SHIFT 1 /* Wait */ +#define SSI_SOR_SYNRST (1 << 0) /* Frame Sync Reset */ + +#define IMX51_SSI_SACNT_REG 0x0038 /* SSI AC97 Control Register */ +#define SSI_SACNT_FRDIV_MASK 0x000007e0 +#define SSI_SACNT_FRDIV_SHIFT 5 /* Frame Rate Divider */ +#define SSI_SACNT_WR (1 << 4) /* Write Command */ +#define SSI_SACNT_RD (1 << 3) /* Read Command */ +#define SSI_SACNT_TIF (1 << 2) /* Tag in FIFO */ +#define SSI_SACNT_FV (1 << 1) /* Fixed/Variable Operation */ +#define SSI_SACNT_AC97EN (1 << 0) /* AC97 Mode Enable */ + +#define IMX51_SSI_SACADD_REG 0x003C /* SSI AC97 Command Address Register */ +#define SSI_SACADD_MASK 0x0007ffff +#define IMX51_SSI_SACDAT_REG 0x0040 /* SSI AC97 Command Data Register */ +#define SSI_SACDAT_MASK 0x000fffff +#define IMX51_SSI_SATAG_REG 0x0044 /* SSI AC97 Tag Register */ +#define SSI_SATAG_MASK 0x0000ffff +#define IMX51_SSI_STMSK_REG 0x0048 /* SSI TX Time Slot Mask Register */ +#define IMX51_SSI_SRMSK_REG 0x004C /* SSI RX Time Slot Mask Register */ +#define IMX51_SSI_SACCST_REG 0x0050 /* SSI AC97 Channel Status Register */ +#define IMX51_SSI_SACCEN_REG 0x0054 /* SSI AC97 Channel Enable Register */ +#define IMX51_SSI_SACCDIS_REG 0x0058 /* SSI AC97 Channel Disable Register */ +#define SSI_SAC_MASK 0x000003ff /* SACCST,SACCEN,SACCDIS */ diff --git a/sys/arm/freescale/imx/imx51_tzicreg.h b/sys/arm/freescale/imx/imx51_tzicreg.h new file mode 100644 index 0000000..d8eed64 --- /dev/null +++ b/sys/arm/freescale/imx/imx51_tzicreg.h @@ -0,0 +1,85 @@ +/* $NetBSD: imx51_tzicreg.h,v 1.1 2010/11/13 07:11:03 bsh Exp $ */ +/* + * Copyright (c) 2010 Genetec Corporation. All rights reserved. + * Written by Hashimoto Kenichi for Genetec Corporation. + * + * 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 GENETEC CORPORATION ``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 GENETEC CORPORATION + * 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. + */ + +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by Oleksandr Rybalko + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _IMX51_TZICREG_H_ +#define _IMX51_TZICRREG_H_ + +#include <sys/cdefs.h> + +#define TZIC_SIZE 0x4000 +#define TZIC_INTCNTL 0x0000 +#define INTCNTL_NSEN_MASK 0x80000000 +#define INTCNTL_NSEN 0x00010000 +#define INTCNTL_EN 0x00000001 +#define TZIC_INTTYPE 0x0004 +#define TZIC_PRIOMASK 0x000c +#define TZIC_SYNCCTRL 0x0010 +#define TZIC_DSMINT 0x0014 +#define TZIC_INTSEC(n) (0x0080 + 0x04 * (n)) +#define TZIC_ENSET(n) (0x0100 + 0x04 * (n)) +#define TZIC_ENCLEAR(n) (0x0180 + 0x04 * (n)) +#define TZIC_SRCSET(n) (0x0200 + 0x04 * (n)) +#define TZIC_SRCCLAR(n) (0x0280 + 0x04 * (n)) +#define TZIC_PRIORITY(n) (0x0400 + 0x04 * (n)) +#define TZIC_PND(n) (0x0d00 + 0x04 * (n)) +#define TZIC_HIPND(n) (0x0d80 + 0x04 * (n)) +#define TZIC_WAKEUP(n) (0x0e00 + 0x04 * (n)) +#define TZIC_SWINT 0x0f00 + +#define TZIC_INTNUM 128 +#endif /* _IMX51_TZICRREG_H_ */ diff --git a/sys/arm/freescale/imx/imx_gpt.c b/sys/arm/freescale/imx/imx_gpt.c new file mode 100644 index 0000000..6e12d00 --- /dev/null +++ b/sys/arm/freescale/imx/imx_gpt.c @@ -0,0 +1,370 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Oleksandr Rybalko under sponsorship + * from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/malloc.h> +#include <sys/rman.h> +#include <sys/timeet.h> +#include <sys/timetc.h> +#include <sys/watchdog.h> +#include <machine/bus.h> +#include <machine/cpu.h> +#include <machine/frame.h> +#include <machine/intr.h> + +#include <machine/fdt.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 <arm/freescale/imx/imx_gptvar.h> +#include <arm/freescale/imx/imx_gptreg.h> + +#include <sys/kdb.h> +#include <arm/freescale/imx/imx51_ccmvar.h> + +#define MIN_PERIOD 100LLU + +#define WRITE4(_sc, _r, _v) \ + bus_space_write_4((_sc)->sc_iot, (_sc)->sc_ioh, (_r), (_v)) +#define READ4(_sc, _r) \ + bus_space_read_4((_sc)->sc_iot, (_sc)->sc_ioh, (_r)) +#define SET4(_sc, _r, _m) \ + WRITE4((_sc), (_r), READ4((_sc), (_r)) | (_m)) +#define CLEAR4(_sc, _r, _m) \ + WRITE4((_sc), (_r), READ4((_sc), (_r)) & ~(_m)) + +static u_int imx_gpt_get_timecount(struct timecounter *); +static int imx_gpt_timer_start(struct eventtimer *, sbintime_t, + sbintime_t); +static int imx_gpt_timer_stop(struct eventtimer *); + +static int imx_gpt_intr(void *); +static int imx_gpt_probe(device_t); +static int imx_gpt_attach(device_t); + +static struct timecounter imx_gpt_timecounter = { + .tc_name = "i.MX GPT Timecounter", + .tc_get_timecount = imx_gpt_get_timecount, + .tc_counter_mask = ~0u, + .tc_frequency = 0, + .tc_quality = 500, +}; + +struct imx_gpt_softc *imx_gpt_sc = NULL; +static volatile int imx_gpt_delay_count = 300; + +static struct resource_spec imx_gpt_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { SYS_RES_IRQ, 0, RF_ACTIVE }, + { -1, 0 } +}; + +static int +imx_gpt_probe(device_t dev) +{ + + if (!ofw_bus_is_compatible(dev, "fsl,imx51-gpt")) + return (ENXIO); + + device_set_desc(dev, "Freescale i.MXxxx GPT timer"); + return (BUS_PROBE_DEFAULT); +} + +static int +imx_gpt_attach(device_t dev) +{ + struct imx_gpt_softc *sc; + int err; + + sc = device_get_softc(dev); + + if (bus_alloc_resources(dev, imx_gpt_spec, sc->res)) { + device_printf(dev, "could not allocate resources\n"); + return (ENXIO); + } + + sc->sc_dev = dev; + sc->sc_clksrc = GPT_CR_CLKSRC_IPG; + sc->sc_iot = rman_get_bustag(sc->res[0]); + sc->sc_ioh = rman_get_bushandle(sc->res[0]); + + switch (sc->sc_clksrc) { + case GPT_CR_CLKSRC_NONE: + device_printf(dev, "can't run timer without clock source\n"); + return (EINVAL); + case GPT_CR_CLKSRC_EXT: + device_printf(dev, "Not implemented. Geve me the way to get " + "external clock source frequency\n"); + return (EINVAL); + case GPT_CR_CLKSRC_32K: + sc->clkfreq = 32768; + break; + case GPT_CR_CLKSRC_IPG_HIGH: + sc->clkfreq = imx51_get_clock(IMX51CLK_IPG_CLK_ROOT) * 2; + break; + default: + sc->clkfreq = imx51_get_clock(IMX51CLK_IPG_CLK_ROOT); + } + device_printf(dev, "Run on %dKHz clock.\n", sc->clkfreq / 1000); + + /* Reset */ + WRITE4(sc, IMX_GPT_CR, GPT_CR_SWR); + /* Enable and setup counters */ + WRITE4(sc, IMX_GPT_CR, + GPT_CR_CLKSRC_IPG | /* Use IPG clock */ + GPT_CR_FRR | /* Just count (FreeRunner mode) */ + GPT_CR_STOPEN | /* Run in STOP mode */ + GPT_CR_WAITEN | /* Run in WAIT mode */ + GPT_CR_DBGEN); /* Run in DEBUG mode */ + + /* Disable interrupts */ + WRITE4(sc, IMX_GPT_IR, 0); + + /* Tick every 10us */ + /* XXX: must be calculated from clock source frequency */ + WRITE4(sc, IMX_GPT_PR, 665); + /* Use 100 KHz */ + sc->clkfreq = 100000; + + /* Setup and enable the timer interrupt */ + err = bus_setup_intr(dev, sc->res[1], INTR_TYPE_CLK, imx_gpt_intr, + NULL, sc, &sc->sc_ih); + if (err != 0) { + bus_release_resources(dev, imx_gpt_spec, sc->res); + device_printf(dev, "Unable to setup the clock irq handler, " + "err = %d\n", err); + return (ENXIO); + } + + sc->et.et_name = "i.MXxxx GPT Eventtimer"; + sc->et.et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERIODIC; + sc->et.et_quality = 1000; + sc->et.et_frequency = sc->clkfreq; + sc->et.et_min_period = (MIN_PERIOD << 32) / sc->et.et_frequency; + sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency; + sc->et.et_start = imx_gpt_timer_start; + sc->et.et_stop = imx_gpt_timer_stop; + sc->et.et_priv = sc; + et_register(&sc->et); + + /* Disable interrupts */ + WRITE4(sc, IMX_GPT_IR, 0); + /* ACK any panding interrupts */ + WRITE4(sc, IMX_GPT_SR, (GPT_IR_ROV << 1) - 1); + + if (device_get_unit(dev) == 0) + imx_gpt_sc = sc; + + imx_gpt_timecounter.tc_frequency = sc->clkfreq; + tc_init(&imx_gpt_timecounter); + + printf("clock: hz=%d stathz = %d\n", hz, stathz); + + device_printf(sc->sc_dev, "timer clock frequency %d\n", sc->clkfreq); + + imx_gpt_delay_count = imx51_get_clock(IMX51CLK_ARM_ROOT) / 4000000; + + SET4(sc, IMX_GPT_CR, GPT_CR_EN); + + return (0); +} + +static int +imx_gpt_timer_start(struct eventtimer *et, sbintime_t first, sbintime_t period) +{ + struct imx_gpt_softc *sc; + uint32_t ticks; + + sc = (struct imx_gpt_softc *)et->et_priv; + + if (period != 0) { + sc->sc_period = ((uint32_t)et->et_frequency * period) >> 32; + /* Set expected value */ + WRITE4(sc, IMX_GPT_OCR2, READ4(sc, IMX_GPT_CNT) + sc->sc_period); + /* Enable compare register 2 Interrupt */ + SET4(sc, IMX_GPT_IR, GPT_IR_OF2); + } else if (first != 0) { + ticks = ((uint32_t)et->et_frequency * first) >> 32; + + /* + * TODO: setupt second compare reg with time which will save + * us in case correct one lost, f.e. if period to short and + * setup done later than counter reach target value. + */ + /* Do not disturb, otherwise event will be lost */ + spinlock_enter(); + /* Set expected value */ + WRITE4(sc, IMX_GPT_OCR1, READ4(sc, IMX_GPT_CNT) + ticks); + /* Enable compare register 1 Interrupt */ + SET4(sc, IMX_GPT_IR, GPT_IR_OF1); + /* Now everybody can relax */ + spinlock_exit(); + + return (0); + } + + return (EINVAL); +} + +static int +imx_gpt_timer_stop(struct eventtimer *et) +{ + struct imx_gpt_softc *sc; + + sc = (struct imx_gpt_softc *)et->et_priv; + + /* Disable OF2 Interrupt */ + CLEAR4(sc, IMX_GPT_IR, GPT_IR_OF2); + WRITE4(sc, IMX_GPT_SR, GPT_IR_OF2); + sc->sc_period = 0; + + return (0); +} + +int +imx_gpt_get_timerfreq(struct imx_gpt_softc *sc) +{ + + return (sc->clkfreq); +} + +void +cpu_initclocks(void) +{ + + if (!imx_gpt_sc) { + panic("%s: driver has not been initialized!", __func__); + } + + cpu_initclocks_bsp(); + + /* Switch to DELAY using counter */ + imx_gpt_delay_count = 0; + device_printf(imx_gpt_sc->sc_dev, + "switch DELAY to use H/W counter\n"); +} + +static int +imx_gpt_intr(void *arg) +{ + struct imx_gpt_softc *sc; + uint32_t status; + + sc = (struct imx_gpt_softc *)arg; + + /* Sometime we not get staus bit when interrupt arrive. Cache? */ + while (!(status = READ4(sc, IMX_GPT_SR))) + ; + + if (status & GPT_IR_OF1) { + if (sc->et.et_active) { + sc->et.et_event_cb(&sc->et, sc->et.et_arg); + } + } + if (status & GPT_IR_OF2) { + if (sc->et.et_active) { + sc->et.et_event_cb(&sc->et, sc->et.et_arg); + /* Set expected value */ + WRITE4(sc, IMX_GPT_OCR2, READ4(sc, IMX_GPT_CNT) + + sc->sc_period); + } + } + + /* ACK */ + WRITE4(sc, IMX_GPT_SR, status); + + return (FILTER_HANDLED); +} + +u_int +imx_gpt_get_timecount(struct timecounter *tc) +{ + + if (imx_gpt_sc == NULL) + return (0); + + return (READ4(imx_gpt_sc, IMX_GPT_CNT)); +} + +static device_method_t imx_gpt_methods[] = { + DEVMETHOD(device_probe, imx_gpt_probe), + DEVMETHOD(device_attach, imx_gpt_attach), + + DEVMETHOD_END +}; + +static driver_t imx_gpt_driver = { + "imx_gpt", + imx_gpt_methods, + sizeof(struct imx_gpt_softc), +}; + +static devclass_t imx_gpt_devclass; + +EARLY_DRIVER_MODULE(imx_gpt, simplebus, imx_gpt_driver, imx_gpt_devclass, 0, + 0, BUS_PASS_TIMER); + +void +DELAY(int usec) +{ + int32_t counts; + uint32_t last; + + /* + * Check the timers are setup, if not just use a for loop for the + * meantime. + */ + if (imx_gpt_delay_count) { + for (; usec > 0; usec--) + for (counts = imx_gpt_delay_count; counts > 0; + counts--) + /* Prevent optimizing out the loop */ + cpufunc_nullop(); + return; + } + + /* At least 1 count */ + usec = MAX(1, usec / 100); + + last = READ4(imx_gpt_sc, IMX_GPT_CNT) + usec; + while (READ4(imx_gpt_sc, IMX_GPT_CNT) < last) { + /* Prevent optimizing out the loop */ + cpufunc_nullop(); + } + /* TODO: use interrupt on OCR2 */ +} diff --git a/sys/arm/freescale/imx/imx_gptreg.h b/sys/arm/freescale/imx/imx_gptreg.h new file mode 100644 index 0000000..cdee630 --- /dev/null +++ b/sys/arm/freescale/imx/imx_gptreg.h @@ -0,0 +1,96 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Oleksandr Rybalko under sponsorship + * from the FreeBSD Foundation. + * + * 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$ + */ + +/* Registers definition for Freescale i.MX515 Generic Periodic Timer */ + +#define IMX_GPT_CR 0x0000 /* Control Register R/W */ +#define GPT_CR_FO3 (1 << 31) +#define GPT_CR_FO2 (1 << 30) +#define GPT_CR_FO1 (1 << 29) +#define GPT_CR_OM3_SHIFT 26 +#define GPT_CR_OM3_MASK 0x1c000000 +#define GPT_CR_OM2_SHIFT 23 +#define GPT_CR_OM2_MASK 0x03800000 +#define GPT_CR_OM1_SHIFT 20 +#define GPT_CR_OM1_MASK 0x00700000 +#define GPT_CR_OMX_NONE 0 +#define GPT_CR_OMX_TOGGLE 1 +#define GPT_CR_OMX_CLEAR 2 +#define GPT_CR_OMX_SET 3 +#define GPT_CR_OMX_PULSE 4 /* Run CLKSRC on output pin */ +#define GPT_CR_IM2_SHIFT 18 +#define GPT_CR_IM2_MASK 0x000c0000 +#define GPT_CR_IM1_SHIFT 16 +#define GPT_CR_IM1_MASK 0x00030000 +#define GPT_CR_IMX_NONE 0 +#define GPT_CR_IMX_REDGE 1 +#define GPT_CR_IMX_FEDGE 2 +#define GPT_CR_IMX_BOTH 3 +#define GPT_CR_SWR (1 << 15) +#define GPT_CR_FRR (1 << 9) +#define GPT_CR_CLKSRC_NONE 0x00000000 +#define GPT_CR_CLKSRC_IPG 0x00000040 +#define GPT_CR_CLKSRC_IPG_HIGH 0x00000080 +#define GPT_CR_CLKSRC_EXT 0x000000c0 +#define GPT_CR_CLKSRC_32K 0x00000100 +#define GPT_CR_STOPEN (1 << 5) +#define GPT_CR_WAITEN (1 << 3) +#define GPT_CR_DBGEN (1 << 2) +#define GPT_CR_ENMOD (1 << 1) +#define GPT_CR_EN (1 << 0) + +#define IMX_GPT_PR 0x0004 /* Prescaler Register R/W */ +#define GPT_PR_VALUE_SHIFT 0 +#define GPT_PR_VALUE_MASK 0x00000fff + +/* Same map for SR and IR */ +#define IMX_GPT_SR 0x0008 /* Status Register R/W */ +#define IMX_GPT_IR 0x000c /* Interrupt Register R/W */ +#define GPT_IR_ROV (1 << 5) +#define GPT_IR_IF2 (1 << 4) +#define GPT_IR_IF1 (1 << 3) +#define GPT_IR_OF3 (1 << 2) +#define GPT_IR_OF2 (1 << 1) +#define GPT_IR_OF1 (1 << 0) +#define GPT_IR_ALL \ + (GPT_IR_ROV | \ + GPT_IR_IF2 | \ + GPT_IR_IF1 | \ + GPT_IR_OF3 | \ + GPT_IR_OF2 | \ + GPT_IR_OF1) + +#define IMX_GPT_OCR1 0x0010 /* Output Compare Register 1 R/W */ +#define IMX_GPT_OCR2 0x0014 /* Output Compare Register 2 R/W */ +#define IMX_GPT_OCR3 0x0018 /* Output Compare Register 3 R/W */ +#define IMX_GPT_ICR1 0x001c /* Input capture Register 1 RO */ +#define IMX_GPT_ICR2 0x0020 /* Input capture Register 2 RO */ +#define IMX_GPT_CNT 0x0024 /* Counter Register RO */ diff --git a/sys/arm/freescale/imx/imx_gptvar.h b/sys/arm/freescale/imx/imx_gptvar.h new file mode 100644 index 0000000..7004e05 --- /dev/null +++ b/sys/arm/freescale/imx/imx_gptvar.h @@ -0,0 +1,50 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Oleksandr Rybalko under sponsorship + * from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _IMXGPTVAR_H +#define _IMXGPTVAR_H + +struct imx_gpt_softc { + device_t sc_dev; + struct resource *res[2]; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + void *sc_ih; /* interrupt handler */ + uint32_t sc_period; + uint32_t sc_clksrc; + uint32_t clkfreq; + struct eventtimer et; +}; + +extern struct imx_gpt_softc *imx_gpt_sc; + +int imx_gpt_get_timerfreq(struct imx_gpt_softc *); +#endif /* _IMXGPTVAR_H */ diff --git a/sys/arm/freescale/imx/imx_machdep.c b/sys/arm/freescale/imx/imx_machdep.c new file mode 100644 index 0000000..03d0383 --- /dev/null +++ b/sys/arm/freescale/imx/imx_machdep.c @@ -0,0 +1,142 @@ +/*- + * Copyright (c) 1994-1998 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * + * This code is derived from software written for Brini by Mark Brinicombe + * Portions of this software were developed by Oleksandr Rybalko + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Brini. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. + * + * from: FreeBSD: //depot/projects/arm/src/sys/arm/at91/kb920x_machdep.c, rev 45 + */ + +#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 <sys/reboot.h> + +#include <vm/vm.h> +#include <vm/pmap.h> + +#include <machine/bus.h> +#include <machine/frame.h> /* For trapframe_t, used in <machine/machdep.h> */ +#include <machine/machdep.h> +#include <machine/pmap.h> + +#include <dev/fdt/fdt_common.h> + +#define IMX51_DEV_VIRT_BASE 0xe0000000 +vm_offset_t +initarm_lastaddr(void) +{ + + boothowto |= RB_VERBOSE|RB_MULTIPLE; + bootverbose = 1; + + if (fdt_immr_addr(IMX51_DEV_VIRT_BASE) != 0) + while (1); + + /* Platform-specific initialisation */ + return (fdt_immr_va - ARM_NOCACHE_KVA_SIZE); +} + +/* + * Set initial values of GPIO output ports + */ +void +initarm_gpio_init(void) +{ + +} + +void +initarm_late_init(void) +{ + +} + +#define FDT_DEVMAP_MAX 2 +static struct pmap_devmap fdt_devmap[FDT_DEVMAP_MAX] = { + { 0, 0, 0, 0, 0, }, + { 0, 0, 0, 0, 0, } +}; + +/* + * Construct pmap_devmap[] with DT-derived config data. + */ +int +platform_devmap_init(void) +{ + + /* + * Map segment where UART1 and UART2 located. + */ + fdt_devmap[0].pd_va = IMX51_DEV_VIRT_BASE + 0x03f00000; + fdt_devmap[0].pd_pa = 0x73f00000; + fdt_devmap[0].pd_size = 0x00100000; + fdt_devmap[0].pd_prot = VM_PROT_READ | VM_PROT_WRITE; + fdt_devmap[0].pd_cache = PTE_NOCACHE; + + pmap_devmap_bootstrap_table = &fdt_devmap[0]; + return (0); +} + +struct arm32_dma_range * +bus_dma_get_range(void) +{ + + return (NULL); +} + +int +bus_dma_get_range_nb(void) +{ + + return (0); +} + +void +cpu_reset(void) +{ + + printf("Reset ...\n"); + /* Clear n_reset flag */ + *((volatile u_int16_t *)(IMX51_DEV_VIRT_BASE + 0x03f98000)) = + (u_int16_t)0; + while (1); +} diff --git a/sys/arm/freescale/imx/imx_wdog.c b/sys/arm/freescale/imx/imx_wdog.c new file mode 100644 index 0000000..c8c9fda --- /dev/null +++ b/sys/arm/freescale/imx/imx_wdog.c @@ -0,0 +1,163 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Oleksandr Rybalko under sponsorship + * from the FreeBSD Foundation. + * + * 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/kernel.h> +#include <sys/module.h> +#include <sys/time.h> +#include <sys/bus.h> +#include <sys/resource.h> +#include <sys/rman.h> +#include <sys/watchdog.h> + +#include <machine/bus.h> +#include <machine/intr.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/fdt.h> + +#include <arm/freescale/imx/imx_wdogreg.h> + +struct imx_wdog_softc { + struct mtx sc_mtx; + device_t sc_dev; + bus_space_tag_t sc_bst; + bus_space_handle_t sc_bsh; + struct resource *sc_res[2]; + uint32_t sc_timeout; +}; + +static struct resource_spec imx_wdog_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { SYS_RES_IRQ, 0, RF_ACTIVE }, + { -1, 0 } +}; + +static void imx_watchdog(void *, u_int, int *); +static int imx_wdog_probe(device_t); +static int imx_wdog_attach(device_t); + +static device_method_t imx_wdog_methods[] = { + DEVMETHOD(device_probe, imx_wdog_probe), + DEVMETHOD(device_attach, imx_wdog_attach), + DEVMETHOD_END +}; + +static driver_t imx_wdog_driver = { + "imx_wdog", + imx_wdog_methods, + sizeof(struct imx_wdog_softc), +}; +static devclass_t imx_wdog_devclass; +DRIVER_MODULE(imx_wdog, simplebus, imx_wdog_driver, imx_wdog_devclass, 0, 0); + + +static void +imx_watchdog(void *arg, u_int cmd, int *error) +{ + struct imx_wdog_softc *sc; + uint16_t reg; + int timeout; + + sc = arg; + mtx_lock(&sc->sc_mtx); + + /* Refresh counter, since we feels good */ + WRITE(sc, WDOG_SR_REG, WDOG_SR_STEP1); + WRITE(sc, WDOG_SR_REG, WDOG_SR_STEP2); + + /* We don't require precession, so "-10" (/1024) is ok */ + timeout = (1 << ((cmd & WD_INTERVAL) - 10)) / 1000000; + if (timeout > 1 && timeout < 128) { + if (timeout != sc->sc_timeout) { + device_printf(sc->sc_dev, + "WARNING: watchdog can't be disabled!!!"); + sc->sc_timeout = timeout; + reg = READ(sc, WDOG_CR_REG); + reg &= ~WDOG_CR_WT_MASK; + reg |= (timeout << (WDOG_CR_WT_SHIFT + 1)) & + WDOG_CR_WT_MASK; + WRITE(sc, WDOG_CR_REG, reg); + /* Refresh counter */ + WRITE(sc, WDOG_SR_REG, WDOG_SR_STEP1); + WRITE(sc, WDOG_SR_REG, WDOG_SR_STEP2); + *error = 0; + } else { + *error = EOPNOTSUPP; + } + } else { + device_printf(sc->sc_dev, "Can not be disabled.\n"); + *error = EOPNOTSUPP; + } + mtx_unlock(&sc->sc_mtx); + +} + +static int +imx_wdog_probe(device_t dev) +{ + + if (!ofw_bus_is_compatible(dev, "fsl,imx51-wdt")) + return (ENXIO); + + device_set_desc(dev, "Freescale i.MX5xx Watchdog Timer"); + return (0); +} + +static int +imx_wdog_attach(device_t dev) +{ + struct imx_wdog_softc *sc; + + sc = device_get_softc(dev); + sc->sc_dev = dev; + + if (bus_alloc_resources(dev, imx_wdog_spec, sc->sc_res)) { + device_printf(dev, "could not allocate resources\n"); + return (ENXIO); + } + + mtx_init(&sc->sc_mtx, device_get_nameunit(dev), "imx_wdt", MTX_DEF); + + sc->sc_dev = dev; + sc->sc_bst = rman_get_bustag(sc->sc_res[0]); + sc->sc_bsh = rman_get_bushandle(sc->sc_res[0]); + + /* TODO: handle interrupt */ + + EVENTHANDLER_REGISTER(watchdog_list, imx_watchdog, sc, 0); + return (0); +} diff --git a/sys/arm/freescale/imx/imx_wdogreg.h b/sys/arm/freescale/imx/imx_wdogreg.h new file mode 100644 index 0000000..0decd69 --- /dev/null +++ b/sys/arm/freescale/imx/imx_wdogreg.h @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Oleksandr Rybalko under sponsorship + * from the FreeBSD Foundation. + * + * 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 WDOG_CLK_FREQ 32768 + +#define WDOG_CR_REG 0x00 /* Control Register */ +#define WDOG_CR_WT_MASK 0xff00 /* Count of 0.5 sec */ +#define WDOG_CR_WT_SHIFT 8 +#define WDOG_CR_WDW (1 << 7) /* Suspend WDog */ +#define WDOG_CR_WDA (1 << 5) /* Don't touch ipp_wdog */ +#define WDOG_CR_SRS (1 << 4) /* Don't touch sys_reset */ +#define WDOG_CR_WDT (1 << 3) /* Assert ipp_wdog on tout */ +#define WDOG_CR_WDE (1 << 2) /* WDog Enable */ +#define WDOG_CR_WDBG (1 << 1) /* Suspend when DBG mode */ +#define WDOG_CR_WDZST (1 << 0) /* Suspend when LP mode */ + +#define WDOG_SR_REG 0x02 /* Service Register */ +#define WDOG_SR_STEP1 0x5555 +#define WDOG_SR_STEP2 0xaaaa + +#define WDOG_RSR_REG 0x04 /* Reset Status Register */ +#define WDOG_RSR_TOUT (1 << 1) /* Due WDog timeout reset */ +#define WDOG_RSR_SFTW (1 << 0) /* Due Soft reset */ + +#define WDOG_ICR_REG 0x06 /* Interrupt Control Register */ +#define WDOG_ICR_WIE (1 << 15) /* Enable Interrupt */ +#define WDOG_ICR_WTIS (1 << 14) /* Interrupt has occurred */ +#define WDOG_ICR_WTCT_MASK 0x00ff +#define WDOG_ICR_WTCT_SHIFT 0 /* Interrupt hold time */ + +#define WDOG_MCR_REG 0x08 /* Miscellaneous Control Register */ +#define WDOG_MCR_PDE (1 << 0) + +#define READ(_sc, _r) \ + bus_space_read_2((_sc)->sc_bst, (_sc)->sc_bsh, (_r)) +#define WRITE(_sc, _r, _v) \ + bus_space_write_2((_sc)->sc_bst, (_sc)->sc_bsh, (_r), (_v)) diff --git a/sys/arm/freescale/imx/std.imx b/sys/arm/freescale/imx/std.imx new file mode 100644 index 0000000..60903f6 --- /dev/null +++ b/sys/arm/freescale/imx/std.imx @@ -0,0 +1,15 @@ +# $FreeBSD$ +machine arm armv6 +cpu CPU_CORTEXA +makeoptions ARM_LITTLE_ENDIAN +options ARM_L2_PIPT + +options KERNVIRTADDR=0xc0100000 +makeoptions KERNVIRTADDR=0xc0100000 +options KERNPHYSADDR=0x90100000 +makeoptions KERNPHYSADDR=0x90100000 +options PHYSADDR=0x90000000 +options STARTUP_PAGETABLE_ADDR=0x91000000 + +files "../freescale/imx/imx.files" + diff --git a/sys/arm/freescale/imx/tzic.c b/sys/arm/freescale/imx/tzic.c new file mode 100644 index 0000000..9b7ecec --- /dev/null +++ b/sys/arm/freescale/imx/tzic.c @@ -0,0 +1,187 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Oleksandr Rybalko under sponsorship + * from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/ktr.h> +#include <sys/module.h> +#include <sys/rman.h> +#include <sys/pcpu.h> +#include <sys/proc.h> +#include <sys/cpuset.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <machine/bus.h> +#include <machine/intr.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 <arm/freescale/imx/imx51_tzicreg.h> + +struct tzic_softc { + struct resource * tzic_res[3]; + bus_space_tag_t tzic_bst; + bus_space_handle_t tzic_bsh; + uint8_t ver; +}; + +static struct resource_spec tzic_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { -1, 0 } +}; + +static struct tzic_softc *tzic_sc = NULL; + +#define tzic_read_4(reg) \ + bus_space_read_4(tzic_sc->tzic_bst, tzic_sc->tzic_bsh, reg) +#define tzic_write_4(reg, val) \ + bus_space_write_4(tzic_sc->tzic_bst, tzic_sc->tzic_bsh, reg, val) + +static void tzic_post_filter(void *); + +static int +tzic_probe(device_t dev) +{ + if (ofw_bus_is_compatible(dev, "fsl,tzic")) { + device_set_desc(dev, "TrustZone Interrupt Controller"); + return (BUS_PROBE_DEFAULT); + } + return (ENXIO); +} + +static int +tzic_attach(device_t dev) +{ + struct tzic_softc *sc = device_get_softc(dev); + int i; + uint32_t reg; + + if (tzic_sc) + return (ENXIO); + + if (bus_alloc_resources(dev, tzic_spec, sc->tzic_res)) { + device_printf(dev, "could not allocate resources\n"); + return (ENXIO); + } + + arm_post_filter = tzic_post_filter; + + /* Distributor Interface */ + sc->tzic_bst = rman_get_bustag(sc->tzic_res[0]); + sc->tzic_bsh = rman_get_bushandle(sc->tzic_res[0]); + + tzic_sc = sc; + + reg = tzic_read_4(TZIC_INTCNTL); + tzic_write_4(TZIC_INTCNTL, INTCNTL_NSEN_MASK|INTCNTL_NSEN|INTCNTL_EN); + reg = tzic_read_4(TZIC_INTCNTL); + tzic_write_4(TZIC_PRIOMASK, 0x1f); + reg = tzic_read_4(TZIC_PRIOMASK); + + tzic_write_4(TZIC_SYNCCTRL, 0x02); + reg = tzic_read_4(TZIC_SYNCCTRL); + + /* route all interrupts to IRQ. secure interrupts are for FIQ */ + for (i = 0; i < 4; i++) + tzic_write_4(TZIC_INTSEC(i), 0xffffffff); + + /* disable all interrupts */ + for (i = 0; i < 4; i++) + tzic_write_4(TZIC_ENCLEAR(i), 0xffffffff); + + return (0); +} + +static device_method_t tzic_methods[] = { + DEVMETHOD(device_probe, tzic_probe), + DEVMETHOD(device_attach, tzic_attach), + { 0, 0 } +}; + +static driver_t tzic_driver = { + "tzic", + tzic_methods, + sizeof(struct tzic_softc), +}; + +static devclass_t tzic_devclass; + +/* + * Memory space of controller located outside of device range, so let him to + * attach not only to simplebus, but fdtbus also. + */ +EARLY_DRIVER_MODULE(tzic, fdtbus, tzic_driver, tzic_devclass, 0, 0, + BUS_PASS_INTERRUPT); +EARLY_DRIVER_MODULE(tzic, simplebus, tzic_driver, tzic_devclass, 0, 0, + BUS_PASS_INTERRUPT); + +static void +tzic_post_filter(void *arg) +{ + +} + +int +arm_get_next_irq(int last_irq) +{ + uint32_t pending; + int i, b; + + for (i = 0; i < 4; i++) { + pending = tzic_read_4(TZIC_PND(i)); + for (b = 0; b < 32; b++) + if (pending & (1 << b)) { + return (i * 32 + b); + } + } + + return (-1); +} + +void +arm_mask_irq(uintptr_t nb) +{ + + tzic_write_4(TZIC_ENCLEAR(nb / 32), (1UL <<(nb % 32))); +} + +void +arm_unmask_irq(uintptr_t nb) +{ + + tzic_write_4(TZIC_ENSET(nb / 32), (1UL <<(nb % 32))); +} diff --git a/sys/boot/fdt/dts/efikamx.dts b/sys/boot/fdt/dts/efikamx.dts new file mode 100644 index 0000000..120d1f4 --- /dev/null +++ b/sys/boot/fdt/dts/efikamx.dts @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Semihalf under sponsorship from + * the FreeBSD Foundation. + * + * 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. + * + * Freescale i.MX515 Device Tree Source. + * + * $FreeBSD$ + */ + +/dts-v1/; +/include/ "imx51x.dtsi" + +/ { + model = "Genesi Efika MX"; + compatible = "genesi,imx51-efikamx"; + + memory { + /* RAM 512M */ + reg = <0x90000000 0x20000000>; + }; + + localbus@5e000000 { + ipu3@5e000000 { + status = "okay"; + }; + }; + + soc@70000000 { + aips@70000000 { + spba@70000000 { + esdhc@70004000 { + clock-frequency = <216000000>; + status = "okay"; + }; + esdhc@70008000 { + clock-frequency = <216000000>; + status = "okay"; + }; + SSI2: ssi@70014000 { + status = "okay"; + }; + }; + timer@73fa0000 { + status = "okay"; + }; + + /* UART1, console */ + UART1: serial@73fbc000 { + status = "okay"; + clock-frequency = <3000000>; /* XXX */ + }; + + clock@73fd4000 { + status = "okay"; + }; + gpio@73f84000 { + status = "okay"; + }; + gpio@73f88000 { + status = "okay"; + }; + gpio@73f8c000 { + status = "okay"; + }; + gpio@73f90000 { + status = "okay"; + }; + wdog@73f98000 { + status = "okay"; + }; + }; + aips@80000000 { + i2c@83fc4000 { + status = "okay"; + }; + i2c@83fc8000 { + status = "okay"; + }; + audmux@83fd4000 { + status = "okay"; + }; + ide@83fe0000 { + status = "okay"; + }; + }; + }; + + aliases { + UART1 = &UART1; + SSI2 = &SSI2; + }; + + chosen { + bootargs = "-v"; + stdin = "UART1"; + stdout = "UART1"; + }; +}; diff --git a/sys/boot/fdt/dts/imx51x.dtsi b/sys/boot/fdt/dts/imx51x.dtsi new file mode 100644 index 0000000..19f281e --- /dev/null +++ b/sys/boot/fdt/dts/imx51x.dtsi @@ -0,0 +1,590 @@ +/* + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Semihalf under sponsorship from + * the FreeBSD Foundation. + * + * 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. + * + * Freescale i.MX515 Device Tree Source. + * + * $FreeBSD$ + */ + +/ { + #address-cells = <1>; + #size-cells = <1>; + + aliases { + soc = &SOC; + }; + + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "ARM,MCIMX515"; + reg = <0x0>; + d-cache-line-size = <32>; + i-cache-line-size = <32>; + d-cache-size = <0x8000>; + i-cache-size = <0x8000>; + /* TODO: describe L2 cache also */ + timebase-frequency = <0>; + bus-frequency = <0>; + clock-frequency = <0>; + }; + }; + + localbus@e0000000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + + /* This reflects CPU decode windows setup. */ + ranges; + + tzic: tz-interrupt-controller@e0000000 { + compatible = "fsl,imx51-tzic", "fsl,tzic"; + interrupt-controller; + #interrupt-cells = <1>; + reg = <0xe0000000 0x00004000>; + }; + /* + * 60000000 60000FFF 4K Debug ROM + * 60001000 60001FFF 4K ETB + * 60002000 60002FFF 4K ETM + * 60003000 60003FFF 4K TPIU + * 60004000 60004FFF 4K CTI0 + * 60005000 60005FFF 4K CTI1 + * 60006000 60006FFF 4K CTI2 + * 60007000 60007FFF 4K CTI3 + * 60008000 60008FFF 4K Cortex Debug Unit + * + * E0000000 E0003FFF 0x4000 TZIC + */ + }; + + SOC: soc@70000000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&tzic>; + ranges = <0x70000000 0x70000000 0x14000000>; + + aips@70000000 { /* AIPS1 */ + compatible = "fsl,aips-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&tzic>; + ranges; + + /* Required by many devices, so better to stay first */ + /* 73FD4000 0x4000 CCM */ + clock@73fd4000 { + compatible = "fsl,imx51-ccm"; + /* 83F80000 0x4000 DPLLIP1 */ + /* 83F84000 0x4000 DPLLIP2 */ + /* 83F88000 0x4000 DPLLIP3 */ + reg = <0x73fd4000 0x4000 + 0x83F80000 0x4000 + 0x83F84000 0x4000 + 0x83F88000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <71 72>; + status = "disabled"; + }; + + /* + * GPIO modules moved up - to have it attached for + * drivers which rely on GPIO + */ + /* 73F84000 0x4000 GPIO1 */ + gpio1: gpio@73f84000 { + compatible = "fsl,imx51-gpio", "fsl,imx31-gpio"; + reg = <0x73f84000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <50 51 42 43 44 45 46 47 48 49>; + /* TODO: use <> also */ + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + /* 73F88000 0x4000 GPIO2 */ + gpio2: gpio@73f88000 { + compatible = "fsl,imx51-gpio", "fsl,imx31-gpio"; + reg = <0x73f88000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <52 53>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + /* 73F8C000 0x4000 GPIO3 */ + gpio3: gpio@73f8c000 { + compatible = "fsl,imx51-gpio", "fsl,imx31-gpio"; + reg = <0x73f8c000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <54 55>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + /* 73F90000 0x4000 GPIO4 */ + gpio4: gpio@73f90000 { + compatible = "fsl,imx51-gpio", "fsl,imx31-gpio"; + reg = <0x73f90000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <56 57>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + spba@70000000 { + compatible = "fsl,spba-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&tzic>; + ranges; + + /* 70004000 0x4000 ESDHC 1 */ + esdhc@70004000 { + compatible = "fsl,imx51-esdhc"; + reg = <0x70004000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <1>; + status = "disabled"; + }; + + /* 70008000 0x4000 ESDHC 2 */ + esdhc@70008000 { + compatible = "fsl,imx51-esdhc"; + reg = <0x70008000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <2>; + status = "disabled"; + }; + + /* 7000C000 0x4000 UART 3 */ + uart3: serial@7000c000 { + compatible = "fsl,imx51-uart", "fsl,imx-uart"; + reg = <0x7000c000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <33>; + status = "disabled"; + }; + + /* 70010000 0x4000 eCSPI1 */ + ecspi@70010000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx51-ecspi"; + reg = <0x70010000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <36>; + status = "disabled"; + }; + + /* 70014000 0x4000 SSI2 irq30 */ + SSI2: ssi@70014000 { + compatible = "fsl,imx51-ssi"; + reg = <0x70014000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <30>; + status = "disabled"; + }; + + /* 70020000 0x4000 ESDHC 3 */ + esdhc@70020000 { + compatible = "fsl,imx51-esdhc"; + reg = <0x70020000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <3>; + status = "disabled"; + }; + + /* 70024000 0x4000 ESDHC 4 */ + esdhc@70024000 { + compatible = "fsl,imx51-esdhc"; + reg = <0x70024000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <4>; + status = "disabled"; + }; + + /* 70028000 0x4000 SPDIF */ + /* 91 SPDIF */ + + /* 70030000 0x4000 PATA (PORT UDMA) irq70 */ + + /* 70034000 0x4000 SLM */ + /* 70038000 0x4000 HSI2C */ /* 64 HS-I2C */ + /* 7003C000 0x4000 SPBA */ + }; + + /* 73F80000 0x4000 USBOH3 */ + /* irq14 USBOH3 USB Host 1 */ + /* irq16 USBOH3 USB Host 2 */ + /* irq17 USBOH3 USB Host 3 */ + /* irq18 USBOH3 USB OTG */ + usb1: usb@73F80000 { + compatible = "fsl,usb-4core"; + reg = <0x73f80000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <18 14 16 17>; + }; + + /* 73F98000 0x4000 WDOG1 */ + wdog@73f98000 { + compatible = "fsl,imx51-wdt", "fsl,imx21-wdt"; + reg = <0x73f98000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <58>; + status = "disabled"; + }; + + /* 73F9C000 0x4000 WDOG2 (TZ) */ + wdog@73f9c000 { + compatible = "fsl,imx51-wdt", "fsl,imx21-wdt"; + reg = <0x73f9c000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <59>; + status = "disabled"; + }; + + /* 73F94000 0x4000 KPP */ + keyboard@73f94000 { + compatible = "fsl,imx51-kpp"; + reg = <0x73f94000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <60>; + status = "disabled"; + }; + + /* 73FA0000 0x4000 GPT */ + timer@73fa0000 { + compatible = "fsl,imx51-gpt"; + reg = <0x73fa0000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <39>; + status = "disabled"; + }; + + /* 73FA4000 0x4000 SRTC */ + + rtc@73fa4000 { + compatible = "fsl,imx51-srtc"; + reg = <0x73fa4000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <24 25>; + status = "disabled"; + }; + + /* 73FA8000 0x4000 IOMUXC */ + iomux@73fa8000 { + compatible = "fsl,imx51-iomux"; + reg = <0x73fa8000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <7>; + }; + + /* 73FAC000 0x4000 EPIT1 */ + epit1: timer@73fac000 { + compatible = "fsl,imx51-epit"; + reg = <0x73fac000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <40>; + status = "disabled"; + }; + + /* 73FB0000 0x4000 EPIT2 */ + epit2: timer@73fb0000 { + compatible = "fsl,imx51-epit"; + reg = <0x73fb0000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <41>; + status = "disabled"; + }; + + /* 73FB4000 0x4000 PWM1 */ + pwm@73fb4000 { + compatible = "fsl,imx51-pwm"; + reg = <0x73fb4000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <61>; + status = "disabled"; + }; + + /* 73FB8000 0x4000 PWM2 */ + pwm@73fb8000 { + compatible = "fsl,imx51-pwm"; + reg = <0x73fb8000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <94>; + status = "disabled"; + }; + + /* 73FBC000 0x4000 UART 1 */ + uart1: serial@73fbc000 { + compatible = "fsl,imx51-uart", "fsl,imx-uart"; + reg = <0x73fbc000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <31>; + status = "disabled"; + }; + + /* 73FC0000 0x4000 UART 2 */ + uart2: serial@73fc0000 { + compatible = "fsl,imx51-uart", "fsl,imx-uart"; + reg = <0x73fc0000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <32>; + status = "disabled"; + }; + + /* 73FC4000 0x4000 USBOH3 */ + /* NOTYET + usb@73fc4000 { + compatible = "fsl,imx51-otg"; + reg = <0x73fc4000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <>; + status = "disabled"; + }; + */ + /* 73FD0000 0x4000 SRC */ + reset@73fd0000 { + compatible = "fsl,imx51-src"; + reg = <0x73fd0000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <75>; + status = "disabled"; + }; + /* 73FD8000 0x4000 GPC */ + power@73fd8000 { + compatible = "fsl,imx51-gpc"; + reg = <0x73fd8000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <73 74>; + status = "disabled"; + }; + + }; + + aips@80000000 { /* AIPS2 */ + compatible = "fsl,aips-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&tzic>; + ranges; + + /* 83F94000 0x4000 AHBMAX */ + /* 83F98000 0x4000 IIM */ + /* + * 69 IIM Interrupt request to the processor. + * Indicates to the processor that program or + * explicit. + */ + /* 83F9C000 0x4000 CSU */ + /* + * 27 CSU Interrupt Request 1. Indicates to the + * processor that one or more alarm inputs were. + */ + + /* 83FA0000 0x4000 TIGERP_PLATFORM_NE_32K_256K */ + /* irq76 Neon Monitor Interrupt */ + /* irq77 Performance Unit Interrupt */ + /* irq78 CTI IRQ */ + /* irq79 Debug Interrupt, Cross-Trigger Interface 1 */ + /* irq80 Debug Interrupt, Cross-Trigger Interface 1 */ + /* irq89 Debug Interrupt, Cross-Trigger Interface 2 */ + /* irq98 Debug Interrupt, Cross-Trigger Interface 3 */ + + /* 83FA4000 0x4000 OWIRE irq88 */ + /* 83FA8000 0x4000 FIRI irq93 */ + /* 83FAC000 0x4000 eCSPI2 */ + ecspi@83fac000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx51-ecspi"; + reg = <0x83fac000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <37>; + status = "disabled"; + }; + + /* 83FB0000 0x4000 SDMA */ + sdma@83fb0000 { + compatible = "fsl,imx51-sdma", "fsl,imx35-sdma"; + reg = <0x83fb0000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <6>; + }; + + /* 83FB4000 0x4000 SCC */ + /* 21 SCC Security Monitor High Priority Interrupt. */ + /* 22 SCC Secure (TrustZone) Interrupt. */ + /* 23 SCC Regular (Non-Secure) Interrupt. */ + + /* 83FB8000 0x4000 ROMCP */ + /* 83FBC000 0x4000 RTIC */ + /* + * 26 RTIC RTIC (Trust Zone) Interrupt Request. + * Indicates that the RTIC has completed hashing the + */ + + /* 83FC0000 0x4000 CSPI */ + cspi@83fc0000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx51-cspi", "fsl,imx35-cspi"; + reg = <0x83fc0000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <38>; + status = "disabled"; + }; + + /* 83FC4000 0x4000 I2C2 */ + i2c@83fc4000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx51-i2c", "fsl,imx1-i2c", "fsl,imx-i2c"; + reg = <0x83fc4000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <63>; + status = "disabled"; + }; + + /* 83FC8000 0x4000 I2C1 */ + i2c@83fc8000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx51-i2c", "fsl,imx1-i2c", "fsl,imx-i2c"; + reg = <0x83fc8000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <62>; + status = "disabled"; + }; + + /* 83FCC000 0x4000 SSI1 */ + /* 29 SSI1 SSI-1 Interrupt Request */ + SSI1: ssi@83fcc000 { + compatible = "fsl,imx51-ssi"; + reg = <0x83fcc000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <29>; + status = "disabled"; + }; + + /* 83FD0000 0x4000 AUDMUX */ + audmux@83fd4000 { + compatible = "fsl,imx51-audmux"; + reg = <0x83fd4000 0x4000>; + status = "disabled"; + }; + + /* 83FD8000 0x4000 EMI1 */ + /* 8 EMI (NFC) */ + /* 15 EMI */ + /* 97 EMI Boot sequence completed interrupt */ + /* + * 101 EMI Indicates all pages have been transferred + * to NFC during an auto program operation. + */ + + /* 83FE0000 0x4000 PATA (PORT PIO) */ + /* 70 PATA Parallel ATA host controller interrupt */ + ide@83fe0000 { + compatible = "fsl,imx51-ata"; + reg = <0x83fe0000 0x4000>; + interrupt-parent = <&tzic>; + interrupts = <70>; + status = "disabled"; + }; + + /* 83FE4000 0x4000 SIM */ + /* 67 SIM intr composed of oef, xte, sdi1, and sdi0 */ + /* 68 SIM intr composed of tc, etc, tfe, and rdrf */ + + /* 83FE8000 0x4000 SSI3 */ + /* 96 SSI3 SSI-3 Interrupt Request */ + SSI3: ssi@83fe8000 { + compatible = "fsl,imx51-ssi"; + reg = <0x83fe8000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <96>; + status = "disabled"; + }; + + /* 83FEC000 0x4000 FEC */ + ethernet@83fec000 { + compatible = "fsl,imx51-fec"; + reg = <0x83fec000 0x4000>; + interrupt-parent = <&tzic>; interrupts = <87>; + status = "disabled"; + }; + + /* 83FF0000 0x4000 TVE */ + /* 92 TVE */ + /* 83FF4000 0x4000 VPU */ + /* 9 VPU */ + /* 100 VPU Idle interrupt from VPU */ + + /* 83FF8000 0x4000 SAHARA Lite */ + /* 19 SAHARA SAHARA host 0 (TrustZone) Intr Lite */ + /* 20 SAHARA SAHARA host 1 (non-TrustZone) Intr Lite */ + }; + }; + + localbus@5e000000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + + ranges; + + vga: ipu3@5e000000 { + compatible = "fsl,ipu3"; + reg = < + 0x5e000000 0x08000 /* CM */ + 0x5e008000 0x08000 /* IDMAC */ + 0x5e018000 0x08000 /* DP */ + 0x5e020000 0x08000 /* IC */ + 0x5e028000 0x08000 /* IRT */ + 0x5e030000 0x08000 /* CSI0 */ + 0x5e038000 0x08000 /* CSI1 */ + 0x5e040000 0x08000 /* DI0 */ + 0x5e048000 0x08000 /* DI1 */ + 0x5e050000 0x08000 /* SMFC */ + 0x5e058000 0x08000 /* DC */ + 0x5e060000 0x08000 /* DMFC */ + 0x5e068000 0x08000 /* VDI */ + 0x5f000000 0x20000 /* CPMEM */ + 0x5f020000 0x20000 /* LUT */ + 0x5f040000 0x20000 /* SRM */ + 0x5f060000 0x20000 /* TPM */ + 0x5f080000 0x20000 /* DCTMPL */ + >; + interrupt-parent = <&tzic>; + interrupts = < + 10 /* IPUEX Error */ + 11 /* IPUEX Sync */ + >; + status = "disabled"; + }; + }; +}; + +/* + +TODO: Not mapped interrupts + +5 DAP +84 GPU2D (OpenVG) general interrupt +85 GPU2D (OpenVG) busy signal (for S/W power gating feasibility) +12 GPU3D +102 GPU3D Idle interrupt from GPU3D (for S/W power gating) +90 SJC +*/ diff --git a/sys/dev/ata/chipsets/ata-fsl.c b/sys/dev/ata/chipsets/ata-fsl.c new file mode 100644 index 0000000..5e5a686 --- /dev/null +++ b/sys/dev/ata/chipsets/ata-fsl.c @@ -0,0 +1,238 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Oleksandr Rybalko under sponsorship + * from the FreeBSD Foundation. + * + * 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 "opt_ata.h" +#include <sys/param.h> +#include <sys/module.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/ata.h> +#include <sys/bus.h> +#include <sys/endian.h> +#include <sys/malloc.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/sema.h> +#include <sys/taskqueue.h> +#include <vm/uma.h> +#include <machine/stdarg.h> +#include <machine/resource.h> +#include <machine/bus.h> +#include <sys/rman.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcireg.h> +#include <dev/ata/ata-all.h> +#include <dev/ata/ata-pci.h> +#include <ata_if.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/fdt.h> + +/* local prototypes */ +static int imx_ata_ch_attach(device_t dev); +static int imx_ata_setmode(device_t dev, int target, int mode); + +static int +imx_ata_probe(device_t dev) +{ + struct ata_pci_controller *ctrl; + + if (!ofw_bus_is_compatible(dev, "fsl,imx51-ata")) + return (ENXIO); + + ctrl = device_get_softc(dev); + + device_set_desc(dev, "Freescale Integrated PATA Controller"); + return (BUS_PROBE_DEFAULT); +} + +static void +imx_ata_intr(void *data) +{ + struct ata_pci_controller *ctrl = data; + + bus_write_2(ctrl->r_res1, 0x28, bus_read_2(ctrl->r_res1, 0x28)); + ctrl->interrupt[0].function(ctrl->interrupt[0].argument); +} + +static int +imx_ata_attach(device_t dev) +{ + struct ata_pci_controller *ctrl; + device_t child; + int unit; + + ctrl = device_get_softc(dev); + /* do chipset specific setups only needed once */ + ctrl->legacy = ata_legacy(dev); + ctrl->channels = 1; + ctrl->ichannels = -1; + ctrl->ch_attach = ata_pci_ch_attach; + ctrl->ch_detach = ata_pci_ch_detach; + ctrl->dev = dev; + + ctrl->r_type1 = SYS_RES_MEMORY; + ctrl->r_rid1 = 0; + ctrl->r_res1 = bus_alloc_resource_any(dev, ctrl->r_type1, + &ctrl->r_rid1, RF_ACTIVE); + + if (ata_setup_interrupt(dev, imx_ata_intr)) { + device_printf(dev, "failed to setup interrupt\n"); + return ENXIO; + } + + ctrl->channels = 1; + + ctrl->ch_attach = imx_ata_ch_attach; + ctrl->setmode = imx_ata_setmode; + + /* attach all channels on this controller */ + unit = 0; + child = device_add_child(dev, "ata", ((unit == 0) && ctrl->legacy) ? + unit : devclass_find_free_unit(ata_devclass, 2)); + if (child == NULL) + device_printf(dev, "failed to add ata child device\n"); + else + device_set_ivars(child, (void *)(intptr_t)unit); + + bus_generic_attach(dev); + return 0; +} + +static int +imx_ata_ch_attach(device_t dev) +{ + struct ata_pci_controller *ctrl; + struct ata_channel *ch; + int i; + + ctrl = device_get_softc(device_get_parent(dev)); + ch = device_get_softc(dev); + for (i = ATA_DATA; i < ATA_MAX_RES; i++) + ch->r_io[i].res = ctrl->r_res1; + + bus_write_2(ctrl->r_res1, 0x24, 0x80); + DELAY(100); + bus_write_2(ctrl->r_res1, 0x24, 0xc0); + DELAY(100); + + + /* Write TIME_OFF/ON/1/2W */ + bus_write_1(ctrl->r_res1, 0x00, 3); + bus_write_1(ctrl->r_res1, 0x01, 3); + bus_write_1(ctrl->r_res1, 0x02, (25 + 15) / 15); + bus_write_1(ctrl->r_res1, 0x03, (70 + 15) / 15); + + /* Write TIME_2R/AX/RDX/4 */ + bus_write_1(ctrl->r_res1, 0x04, (70 + 15) / 15); + bus_write_1(ctrl->r_res1, 0x05, (50 + 15) / 15 + 2); + bus_write_1(ctrl->r_res1, 0x06, 1); + bus_write_1(ctrl->r_res1, 0x07, (10 + 15) / 15); + + /* Write TIME_9 ; the rest of timing registers is irrelevant for PIO */ + bus_write_1(ctrl->r_res1, 0x08, (10 + 15) / 15); + + bus_write_2(ctrl->r_res1, 0x24, 0xc1); + DELAY(30000); + + /* setup ATA registers */ + ch->r_io[ATA_DATA ].offset = 0xa0; + ch->r_io[ATA_FEATURE].offset = 0xa4; + ch->r_io[ATA_ERROR ].offset = 0xa4; + ch->r_io[ATA_COUNT ].offset = 0xa8; + ch->r_io[ATA_SECTOR ].offset = 0xac; + ch->r_io[ATA_CYL_LSB].offset = 0xb0; + ch->r_io[ATA_CYL_MSB].offset = 0xb4; + ch->r_io[ATA_DRIVE ].offset = 0xb8; + ch->r_io[ATA_COMMAND].offset = 0xbc; + + ch->r_io[ATA_STATUS ].offset = 0xbc; + ch->r_io[ATA_ALTSTAT].offset = 0xd8; + ch->r_io[ATA_CONTROL].offset = 0xd8; + + ata_pci_hw(dev); + + ch->flags |= ATA_NO_SLAVE; + ch->flags |= ATA_USE_16BIT; + ch->flags |= ATA_CHECKS_CABLE; + ch->flags |= ATA_KNOWN_PRESENCE; + + /* Clear pending interrupts. */ + bus_write_2(ctrl->r_res1, 0x28, 0xf8); + /* Enable all, but Idle interrupts. */ + bus_write_2(ctrl->r_res1, 0x2c, 0x88); + + return 0; +} + +static int +imx_ata_setmode(device_t dev, int target, int mode) +{ + + return (min(mode, ATA_PIO4)); +} + +static device_method_t imx_ata_methods[] = { + DEVMETHOD(device_probe, imx_ata_probe), + DEVMETHOD(device_attach, imx_ata_attach), + DEVMETHOD(device_detach, ata_pci_detach), + DEVMETHOD(device_suspend, ata_pci_suspend), + DEVMETHOD(device_resume, ata_pci_resume), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(bus_read_ivar, ata_pci_read_ivar), + DEVMETHOD(bus_write_ivar, ata_pci_write_ivar), + DEVMETHOD(bus_alloc_resource, ata_pci_alloc_resource), + DEVMETHOD(bus_release_resource, ata_pci_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, ata_pci_setup_intr), + DEVMETHOD(bus_teardown_intr, ata_pci_teardown_intr), + DEVMETHOD(pci_read_config, ata_pci_read_config), + DEVMETHOD(pci_write_config, ata_pci_write_config), + DEVMETHOD(bus_print_child, ata_pci_print_child), + DEVMETHOD(bus_child_location_str, ata_pci_child_location_str), + DEVMETHOD_END +}; +static driver_t imx_ata_driver = { + "atapci", + imx_ata_methods, + sizeof(struct ata_pci_controller) +}; +DRIVER_MODULE(imx_ata, simplebus, imx_ata_driver, ata_pci_devclass, NULL, + NULL); +MODULE_VERSION(imx_ata, 1); +MODULE_DEPEND(imx_ata, ata, 1, 1, 1); +MODULE_DEPEND(imx_ata, atapci, 1, 1, 1); diff --git a/sys/dev/uart/uart.h b/sys/dev/uart/uart.h index 7647188..5229747 100644 --- a/sys/dev/uart/uart.h +++ b/sys/dev/uart/uart.h @@ -64,6 +64,7 @@ struct uart_bas { */ struct uart_class; +extern struct uart_class uart_imx_class __attribute__((weak)); extern struct uart_class uart_ns8250_class __attribute__((weak)); extern struct uart_class uart_quicc_class __attribute__((weak)); extern struct uart_class uart_sab82532_class __attribute__((weak)); diff --git a/sys/dev/uart/uart_bus_fdt.c b/sys/dev/uart/uart_bus_fdt.c index b55329e..cd4f71c 100644 --- a/sys/dev/uart/uart_bus_fdt.c +++ b/sys/dev/uart/uart_bus_fdt.c @@ -105,6 +105,8 @@ uart_fdt_probe(device_t dev) sc->sc_class = &uart_ns8250_class; else if (ofw_bus_is_compatible(dev, "lpc,uart")) sc->sc_class = &uart_lpc_class; + else if (ofw_bus_is_compatible(dev, "fsl,imx-uart")) + sc->sc_class = &uart_imx_class; else if (ofw_bus_is_compatible(dev, "arm,pl011")) sc->sc_class = &uart_pl011_class; else @@ -184,6 +186,8 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) /* * Finalize configuration. */ + if (fdt_is_compatible(node, "fsl,imx-uart")) + class = &uart_imx_class; if (fdt_is_compatible(node, "quicc")) class = &uart_quicc_class; if (fdt_is_compatible(node, "lpc")) diff --git a/sys/dev/uart/uart_dev_imx.c b/sys/dev/uart/uart_dev_imx.c new file mode 100644 index 0000000..81fe163 --- /dev/null +++ b/sys/dev/uart/uart_dev_imx.c @@ -0,0 +1,436 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Oleksandr Rybalko under sponsorship + * from the FreeBSD Foundation. + * + * 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 "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 <dev/uart/uart_dev_imx5xx.h> + +#include "uart_if.h" +/* + * Low-level UART interface. + */ +static int imx_uart_probe(struct uart_bas *bas); +static void imx_uart_init(struct uart_bas *bas, int, int, int, int); +static void imx_uart_term(struct uart_bas *bas); +static void imx_uart_putc(struct uart_bas *bas, int); +static int imx_uart_rxready(struct uart_bas *bas); +static int imx_uart_getc(struct uart_bas *bas, struct mtx *); + +static struct uart_ops uart_imx_uart_ops = { + .probe = imx_uart_probe, + .init = imx_uart_init, + .term = imx_uart_term, + .putc = imx_uart_putc, + .rxready = imx_uart_rxready, + .getc = imx_uart_getc, +}; + +static int +imx_uart_probe(struct uart_bas *bas) +{ + + return (0); +} + +static void +imx_uart_init(struct uart_bas *bas, int baudrate, int databits, + int stopbits, int parity) +{ + +} + +static void +imx_uart_term(struct uart_bas *bas) +{ + +} + +static void +imx_uart_putc(struct uart_bas *bas, int c) +{ + + while (!(IS(bas, USR2, TXFE))) + ; + SETREG(bas, REG(UTXD), c); +} + +static int +imx_uart_rxready(struct uart_bas *bas) +{ + + return ((IS(bas, USR2, RDR)) ? 1 : 0); +} + +static int +imx_uart_getc(struct uart_bas *bas, struct mtx *hwmtx) +{ + int c; + + uart_lock(hwmtx); + while (!(IS(bas, USR2, RDR))) + ; + + c = GETREG(bas, REG(URXD)); + uart_unlock(hwmtx); +#if defined(KDB) + if (c & FLD(URXD, BRK)) { + if (kdb_break()) + return (0); + } +#endif + return (c & 0xff); +} + +/* + * High-level UART interface. + */ +struct imx_uart_softc { + struct uart_softc base; +}; + +static int imx_uart_bus_attach(struct uart_softc *); +static int imx_uart_bus_detach(struct uart_softc *); +static int imx_uart_bus_flush(struct uart_softc *, int); +static int imx_uart_bus_getsig(struct uart_softc *); +static int imx_uart_bus_ioctl(struct uart_softc *, int, intptr_t); +static int imx_uart_bus_ipend(struct uart_softc *); +static int imx_uart_bus_param(struct uart_softc *, int, int, int, int); +static int imx_uart_bus_probe(struct uart_softc *); +static int imx_uart_bus_receive(struct uart_softc *); +static int imx_uart_bus_setsig(struct uart_softc *, int); +static int imx_uart_bus_transmit(struct uart_softc *); + +static kobj_method_t imx_uart_methods[] = { + KOBJMETHOD(uart_attach, imx_uart_bus_attach), + KOBJMETHOD(uart_detach, imx_uart_bus_detach), + KOBJMETHOD(uart_flush, imx_uart_bus_flush), + KOBJMETHOD(uart_getsig, imx_uart_bus_getsig), + KOBJMETHOD(uart_ioctl, imx_uart_bus_ioctl), + KOBJMETHOD(uart_ipend, imx_uart_bus_ipend), + KOBJMETHOD(uart_param, imx_uart_bus_param), + KOBJMETHOD(uart_probe, imx_uart_bus_probe), + KOBJMETHOD(uart_receive, imx_uart_bus_receive), + KOBJMETHOD(uart_setsig, imx_uart_bus_setsig), + KOBJMETHOD(uart_transmit, imx_uart_bus_transmit), + { 0, 0 } +}; + +struct uart_class uart_imx_class = { + "imx", + imx_uart_methods, + sizeof(struct imx_uart_softc), + .uc_ops = &uart_imx_uart_ops, + .uc_range = 0x100, + .uc_rclk = 24000000 /* TODO: get value from CCM */ +}; + +#define SIGCHG(c, i, s, d) \ + if (c) { \ + i |= (i & s) ? s : s | d; \ + } else { \ + i = (i & s) ? (i & ~s) | d : i; \ + } + +static int +imx_uart_bus_attach(struct uart_softc *sc) +{ + struct uart_bas *bas; + struct uart_devinfo *di; + + bas = &sc->sc_bas; + if (sc->sc_sysdev != NULL) { + di = sc->sc_sysdev; + imx_uart_init(bas, di->baudrate, di->databits, di->stopbits, + di->parity); + } else { + imx_uart_init(bas, 115200, 8, 1, 0); + } + + sc->sc_rxfifosz = 1; + sc->sc_txfifosz = 1; + + (void)imx_uart_bus_getsig(sc); + + /* XXX workaround to have working console on manut prompt */ + if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE){ + DIS(bas, UCR4, DREN); + } else { + ENA(bas, UCR4, DREN); + } + DIS(bas, UCR1, RRDYEN); + DIS(bas, UCR1, IDEN); + DIS(bas, UCR3, RXDSEN); + DIS(bas, UCR2, ATEN); + DIS(bas, UCR1, TXMPTYEN); + DIS(bas, UCR1, TRDYEN); + DIS(bas, UCR4, TCEN); + DIS(bas, UCR4, OREN); + ENA(bas, UCR4, BKEN); + DIS(bas, UCR4, WKEN); + DIS(bas, UCR1, ADEN); + DIS(bas, UCR3, ACIEN); + DIS(bas, UCR2, ESCI); + DIS(bas, UCR4, ENIRI); + DIS(bas, UCR3, AIRINTEN); + DIS(bas, UCR3, AWAKEN); + DIS(bas, UCR3, FRAERREN); + DIS(bas, UCR3, PARERREN); + DIS(bas, UCR1, RTSDEN); + DIS(bas, UCR2, RTSEN); + DIS(bas, UCR3, DTREN); + DIS(bas, UCR3, RI); + DIS(bas, UCR3, DCD); + DIS(bas, UCR3, DTRDEN); + + /* ACK all interrupts */ + SETREG(bas, REG(USR1), 0xffff); + SETREG(bas, REG(USR2), 0xffff); + return (0); +} + +static int +imx_uart_bus_detach(struct uart_softc *sc) +{ + + SETREG(&sc->sc_bas, REG(UCR4), 0); + + return (0); +} + +static int +imx_uart_bus_flush(struct uart_softc *sc, int what) +{ + + /* TODO */ + return (0); +} + +static int +imx_uart_bus_getsig(struct uart_softc *sc) +{ + uint32_t new, old, sig; + uint8_t bes; + + do { + old = sc->sc_hwsig; + sig = old; + uart_lock(sc->sc_hwmtx); + bes = GETREG(&sc->sc_bas, REG(USR2)); + uart_unlock(sc->sc_hwmtx); + /* XXX: chip can show delta */ + SIGCHG(bes & FLD(USR2, DCDIN), sig, SER_DCD, SER_DDCD); + new = sig & ~SER_MASK_DELTA; + } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); + + return (sig); +} + +static int +imx_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 +imx_uart_bus_ipend(struct uart_softc *sc) +{ + struct uart_bas *bas; + int ipend; + uint32_t usr1, usr2; + uint32_t ucr1, ucr4; + + bas = &sc->sc_bas; + ipend = 0; + + uart_lock(sc->sc_hwmtx); + + /* Read pending interrupts */ + usr1 = GETREG(bas, REG(USR1)); + usr2 = GETREG(bas, REG(USR2)); + /* ACK interrupts */ + SETREG(bas, REG(USR1), usr1); + SETREG(bas, REG(USR2), usr2); + + ucr1 = GETREG(bas, REG(UCR1)); + ucr4 = GETREG(bas, REG(UCR4)); + + if ((usr2 & FLD(USR2, TXFE)) && (ucr1 & FLD(UCR1, TXMPTYEN))) { + DIS(bas, UCR1, TXMPTYEN); + /* Continue TXing */ + ipend |= SER_INT_TXIDLE; + } + if ((usr2 & FLD(USR2, RDR)) && (ucr4 & FLD(UCR4, DREN))) { + DIS(bas, UCR4, DREN); + /* Wow, new char on input */ + ipend |= SER_INT_RXREADY; + } + if ((usr2 & FLD(USR2, BRCD)) && (ucr4 & FLD(UCR4, BKEN))) + ipend |= SER_INT_BREAK; + + uart_unlock(sc->sc_hwmtx); + + return (ipend); +} + +static int +imx_uart_bus_param(struct uart_softc *sc, int baudrate, int databits, + int stopbits, int parity) +{ + + uart_lock(sc->sc_hwmtx); + imx_uart_init(&sc->sc_bas, baudrate, databits, stopbits, parity); + uart_unlock(sc->sc_hwmtx); + return (0); +} + +static int +imx_uart_bus_probe(struct uart_softc *sc) +{ + int error; + + error = imx_uart_probe(&sc->sc_bas); + if (error) + return (error); + + device_set_desc(sc->sc_dev, "imx_uart"); + return (0); +} + +static int +imx_uart_bus_receive(struct uart_softc *sc) +{ + struct uart_bas *bas; + int xc, out; + + bas = &sc->sc_bas; + uart_lock(sc->sc_hwmtx); + + /* Read while we have anything in FIFO */ + while (IS(bas, USR2, RDR)) { + if (uart_rx_full(sc)) { + /* No space left in input buffer */ + sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN; + break; + } + out = 0; + xc = GETREG(bas, REG(URXD)); + + /* We have valid char */ + if (xc & FLD(URXD, CHARRDY)) + out = xc & 0x000000ff; + + if (xc & FLD(URXD, FRMERR)) + out |= UART_STAT_FRAMERR; + if (xc & FLD(URXD, PRERR)) + out |= UART_STAT_PARERR; + if (xc & FLD(URXD, OVRRUN)) + out |= UART_STAT_OVERRUN; + if (xc & FLD(URXD, BRK)) + out |= UART_STAT_BREAK; + + uart_rx_put(sc, out); + } + /* Reenable Data Ready interrupt */ + ENA(bas, UCR4, DREN); + + uart_unlock(sc->sc_hwmtx); + return (0); +} + +static int +imx_uart_bus_setsig(struct uart_softc *sc, int sig) +{ + + /* TODO: implement (?) */ + + /* XXX workaround to have working console on mount prompt */ + /* Enable RX interrupt */ + if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) + if (!IS(&sc->sc_bas, UCR4, DREN)) + ENA(&sc->sc_bas, UCR4, DREN); + return (0); +} + +static int +imx_uart_bus_transmit(struct uart_softc *sc) +{ + struct uart_bas *bas = &sc->sc_bas; + int i; + + bas = &sc->sc_bas; + uart_lock(sc->sc_hwmtx); + + /* Fill TX FIFO */ + for (i = 0; i < sc->sc_txdatasz; i++) { + SETREG(bas, REG(UTXD), sc->sc_txbuf[i] & 0xff); + } + + sc->sc_txbusy = 1; + /* Call me when ready */ + ENA(bas, UCR1, TXMPTYEN); + + uart_unlock(sc->sc_hwmtx); + + return (0); +} diff --git a/sys/dev/uart/uart_dev_imx5xx.h b/sys/dev/uart/uart_dev_imx5xx.h new file mode 100644 index 0000000..ac24a3f --- /dev/null +++ b/sys/dev/uart/uart_dev_imx5xx.h @@ -0,0 +1,222 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Oleksandr Rybalko under sponsorship + * from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _UART_DEV_IMX5XX_H +#define _UART_DEV_IMX5XX_H + +#define IMXUART_URXD_REG 0x0000 /* UART Receiver Register */ +#define IMXUART_URXD_CHARRDY (1 << 15) +#define IMXUART_URXD_ERR (1 << 14) +#define IMXUART_URXD_OVRRUN (1 << 13) +#define IMXUART_URXD_FRMERR (1 << 12) +#define IMXUART_URXD_BRK (1 << 11) +#define IMXUART_URXD_PRERR (1 << 10) +#define IMXUART_URXD_RX_DATA_MASK 0xff + +#define IMXUART_UTXD_REG 0x0040 /* UART Transmitter Register */ +#define IMXUART_UTXD_TX_DATA_MASK 0xff + +#define IMXUART_UCR1_REG 0x0080 /* UART Control Register 1 */ +#define IMXUART_UCR1_ADEN (1 << 15) +#define IMXUART_UCR1_ADBR (1 << 14) +#define IMXUART_UCR1_TRDYEN (1 << 13) +#define IMXUART_UCR1_IDEN (1 << 12) +#define IMXUART_UCR1_ICD_MASK (3 << 10) +#define IMXUART_UCR1_ICD_IDLE4 (0 << 10) +#define IMXUART_UCR1_ICD_IDLE8 (1 << 10) +#define IMXUART_UCR1_ICD_IDLE16 (2 << 10) +#define IMXUART_UCR1_ICD_IDLE32 (3 << 10) +#define IMXUART_UCR1_RRDYEN (1 << 9) +#define IMXUART_UCR1_RXDMAEN (1 << 8) +#define IMXUART_UCR1_IREN (1 << 7) +#define IMXUART_UCR1_TXMPTYEN (1 << 6) +#define IMXUART_UCR1_RTSDEN (1 << 5) +#define IMXUART_UCR1_SNDBRK (1 << 4) +#define IMXUART_UCR1_TXDMAEN (1 << 3) +#define IMXUART_UCR1_ATDMAEN (1 << 2) +#define IMXUART_UCR1_DOZE (1 << 1) +#define IMXUART_UCR1_UARTEN (1 << 0) + +#define IMXUART_UCR2_REG 0x0084 /* UART Control Register 2 */ +#define IMXUART_UCR2_ESCI (1 << 15) +#define IMXUART_UCR2_IRTS (1 << 14) +#define IMXUART_UCR2_CTSC (1 << 13) +#define IMXUART_UCR2_CTS (1 << 12) +#define IMXUART_UCR2_ESCEN (1 << 11) +#define IMXUART_UCR2_RTEC_MASK (3 << 9) +#define IMXUART_UCR2_RTEC_REDGE (0 << 9) +#define IMXUART_UCR2_RTEC_FEDGE (1 << 9) +#define IMXUART_UCR2_RTEC_EDGE (2 << 9) +#define IMXUART_UCR2_PREN (1 << 8) +#define IMXUART_UCR2_PROE (1 << 7) +#define IMXUART_UCR2_STPB (1 << 6) +#define IMXUART_UCR2_WS (1 << 5) +#define IMXUART_UCR2_RTSEN (1 << 4) +#define IMXUART_UCR2_ATEN (1 << 3) +#define IMXUART_UCR2_TXEN (1 << 2) +#define IMXUART_UCR2_RXEN (1 << 1) +#define IMXUART_UCR2_N_SRST (1 << 0) + +#define IMXUART_UCR3_REG 0x0088 /* UART Control Register 3 */ +#define IMXUART_UCR3_DPEC_MASK (3 << 14) +#define IMXUART_UCR3_DPEC_REDGE (0 << 14) +#define IMXUART_UCR3_DPEC_FEDGE (1 << 14) +#define IMXUART_UCR3_DPEC_EDGE (2 << 14) +#define IMXUART_UCR3_DTREN (1 << 13) +#define IMXUART_UCR3_PARERREN (1 << 12) +#define IMXUART_UCR3_FRAERREN (1 << 11) +#define IMXUART_UCR3_DSR (1 << 10) +#define IMXUART_UCR3_DCD (1 << 9) +#define IMXUART_UCR3_RI (1 << 8) +#define IMXUART_UCR3_ADNIMP (1 << 7) +#define IMXUART_UCR3_RXDSEN (1 << 6) +#define IMXUART_UCR3_AIRINTEN (1 << 5) +#define IMXUART_UCR3_AWAKEN (1 << 4) +#define IMXUART_UCR3_DTRDEN (1 << 3) +#define IMXUART_UCR3_RXDMUXSEL (1 << 2) +#define IMXUART_UCR3_INVT (1 << 1) +#define IMXUART_UCR3_ACIEN (1 << 0) + +#define IMXUART_UCR4_REG 0x008c /* UART Control Register 4 */ +#define IMXUART_UCR4_CTSTL_MASK (0x3f << 10) +#define IMXUART_UCR4_CTSTL_SHIFT 10 +#define IMXUART_UCR4_INVR (1 << 9) +#define IMXUART_UCR4_ENIRI (1 << 8) +#define IMXUART_UCR4_WKEN (1 << 7) +#define IMXUART_UCR4_IDDMAEN (1 << 6) +#define IMXUART_UCR4_IRSC (1 << 5) +#define IMXUART_UCR4_LPBYP (1 << 4) +#define IMXUART_UCR4_TCEN (1 << 3) +#define IMXUART_UCR4_BKEN (1 << 2) +#define IMXUART_UCR4_OREN (1 << 1) +#define IMXUART_UCR4_DREN (1 << 0) + +#define IMXUART_UFCR_REG 0x0090 /* UART FIFO Control Register */ +#define IMXUART_UFCR_TXTL_MASK (0x3f << 10) +#define IMXUART_UFCR_TXTL_SHIFT 10 +#define IMXUART_UFCR_RFDIV_MASK (0x07 << 7) +#define IMXUART_UFCR_RFDIV_SHIFT 7 +#define IMXUART_UFCR_RFDIV_SHIFT 7 +#define IMXUART_UFCR_RFDIV_DIV6 (0 << 7) +#define IMXUART_UFCR_RFDIV_DIV5 (1 << 7) +#define IMXUART_UFCR_RFDIV_DIV4 (2 << 7) +#define IMXUART_UFCR_RFDIV_DIV3 (3 << 7) +#define IMXUART_UFCR_RFDIV_DIV2 (4 << 7) +#define IMXUART_UFCR_RFDIV_DIV1 (5 << 7) +#define IMXUART_UFCR_RFDIV_DIV7 (6 << 7) +#define IMXUART_UFCR_DCEDTE (1 << 6) +#define IMXUART_UFCR_RXTL_MASK 0x0000003f +#define IMXUART_UFCR_RXTL_SHIFT 0 + +#define IMXUART_USR1_REG 0x0094 /* UART Status Register 1 */ +#define IMXUART_USR1_PARITYERR (1 << 15) +#define IMXUART_USR1_RTSS (1 << 14) +#define IMXUART_USR1_TRDY (1 << 13) +#define IMXUART_USR1_RTSD (1 << 12) +#define IMXUART_USR1_ESCF (1 << 11) +#define IMXUART_USR1_FRAMERR (1 << 10) +#define IMXUART_USR1_RRDY (1 << 9) +#define IMXUART_USR1_AGTIM (1 << 8) +#define IMXUART_USR1_DTRD (1 << 7) +#define IMXUART_USR1_RXDS (1 << 6) +#define IMXUART_USR1_AIRINT (1 << 5) +#define IMXUART_USR1_AWAKE (1 << 4) +/* 6040 5008 XXX */ + +#define IMXUART_USR2_REG 0x0098 /* UART Status Register 2 */ +#define IMXUART_USR2_ADET (1 << 15) +#define IMXUART_USR2_TXFE (1 << 14) +#define IMXUART_USR2_DTRF (1 << 13) +#define IMXUART_USR2_IDLE (1 << 12) +#define IMXUART_USR2_ACST (1 << 11) +#define IMXUART_USR2_RIDELT (1 << 10) +#define IMXUART_USR2_RIIN (1 << 9) +#define IMXUART_USR2_IRINT (1 << 8) +#define IMXUART_USR2_WAKE (1 << 7) +#define IMXUART_USR2_DCDDELT (1 << 6) +#define IMXUART_USR2_DCDIN (1 << 5) +#define IMXUART_USR2_RTSF (1 << 4) +#define IMXUART_USR2_TXDC (1 << 3) +#define IMXUART_USR2_BRCD (1 << 2) +#define IMXUART_USR2_ORE (1 << 1) +#define IMXUART_USR2_RDR (1 << 0) + +#define IMXUART_UESC_REG 0x009c /* UART Escape Character Register */ +#define IMXUART_UESC_ESC_CHAR_MASK 0x000000ff + +#define IMXUART_UTIM_REG 0x00a0 /* UART Escape Timer Register */ +#define IMXUART_UTIM_TIM_MASK 0x00000fff + +#define IMXUART_UBIR_REG 0x00a4 /* UART BRM Incremental Register */ +#define IMXUART_UBIR_INC_MASK 0x0000ffff + +#define IMXUART_UBMR_REG 0x00a8 /* UART BRM Modulator Register */ +#define IMXUART_UBMR_MOD_MASK 0x0000ffff + +#define IMXUART_UBRC_REG 0x00ac /* UART Baud Rate Count Register */ +#define IMXUART_UBRC_BCNT_MASK 0x0000ffff + +#define IMXUART_ONEMS_REG 0x00b0 /* UART One Millisecond Register */ +#define IMXUART_ONEMS_ONEMS_MASK 0x00ffffff + +#define IMXUART_UTS_REG 0x00b4 /* UART Test Register */ +#define IMXUART_UTS_FRCPERR (1 << 13) +#define IMXUART_UTS_LOOP (1 << 12) +#define IMXUART_UTS_DBGEN (1 << 11) +#define IMXUART_UTS_LOOPIR (1 << 10) +#define IMXUART_UTS_RXDBG (1 << 9) +#define IMXUART_UTS_TXEMPTY (1 << 6) +#define IMXUART_UTS_RXEMPTY (1 << 5) +#define IMXUART_UTS_TXFULL (1 << 4) +#define IMXUART_UTS_RXFULL (1 << 3) +#define IMXUART_UTS_SOFTRST (1 << 0) + +#define REG(_r) IMXUART_ ## _r ## _REG +#define FLD(_r, _v) IMXUART_ ## _r ## _ ## _v + +#define GETREG(bas, reg) \ + bus_space_read_4((bas)->bst, (bas)->bsh, (reg)) +#define SETREG(bas, reg, value) \ + bus_space_write_4((bas)->bst, (bas)->bsh, (reg), (value)) + +#define CLR(_bas, _r, _b) \ + SETREG((_bas), (_r), GETREG((_bas), (_r)) & ~(_b)) +#define SET(_bas, _r, _b) \ + SETREG((_bas), (_r), GETREG((_bas), (_r)) | (_b)) +#define IS_SET(_bas, _r, _b) \ + ((GETREG((_bas), (_r)) & (_b)) ? 1 : 0) + +#define ENA(_bas, _r, _b) SET((_bas), REG(_r), FLD(_r, _b)) +#define DIS(_bas, _r, _b) CLR((_bas), REG(_r), FLD(_r, _b)) +#define IS(_bas, _r, _b) IS_SET((_bas), REG(_r), FLD(_r, _b)) + + +#endif /* _UART_DEV_IMX5XX_H */ diff --git a/sys/dev/usb/controller/ehci_imx.c b/sys/dev/usb/controller/ehci_imx.c new file mode 100644 index 0000000..e9f148c --- /dev/null +++ b/sys/dev/usb/controller/ehci_imx.c @@ -0,0 +1,282 @@ +/*- + * Copyright (c) 2010-2012 Semihalf + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by Oleksandr Rybalko + * under sponsorship from the FreeBSD Foundation. + * + * 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 "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 <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 <machine/bus.h> +#include <machine/resource.h> + +#include "opt_platform.h" + +#define FSL_EHCI_COUNT 4 +#define FSL_EHCI_REG_OFF 0x100 +#define FSL_EHCI_REG_SIZE 0x100 +#define FSL_EHCI_REG_STEP 0x200 + +struct imx_ehci_softc { + ehci_softc_t ehci[FSL_EHCI_COUNT]; + /* MEM + 4 interrupts */ + struct resource *sc_res[1 + FSL_EHCI_COUNT]; +}; + +/* i.MX515 have 4 EHCI inside USB core */ +/* TODO: we can get number of EHCIs by IRQ allocation */ +static struct resource_spec imx_ehci_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 }, + /* RF_OPTIONAL will allow to use driver for systems with 3 EHCIs */ + { SYS_RES_IRQ, 3, RF_ACTIVE | RF_OPTIONAL }, + { -1, 0 } +}; + +/* Forward declarations */ +static int fsl_ehci_attach(device_t self); +static int fsl_ehci_detach(device_t self); +static int fsl_ehci_probe(device_t self); + +static device_method_t ehci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, fsl_ehci_probe), + DEVMETHOD(device_attach, fsl_ehci_attach), + DEVMETHOD(device_detach, fsl_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(struct imx_ehci_softc) +}; + +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 +fsl_ehci_probe(device_t dev) +{ + + if (ofw_bus_is_compatible(dev, "fsl,usb-4core") == 0) + return (ENXIO); + + device_set_desc(dev, "Freescale integrated USB controller"); + + return (BUS_PROBE_DEFAULT); +} + +static int +fsl_ehci_attach(device_t self) +{ + struct imx_ehci_softc *sc; + bus_space_tag_t iot; + ehci_softc_t *esc; + int err, i, rid; + + sc = device_get_softc(self); + rid = 0; + + /* Allocate io resource for EHCI */ + if (bus_alloc_resources(self, imx_ehci_spec, sc->sc_res)) { + device_printf(self, "could not allocate resources\n"); + return (ENXIO); + } + iot = rman_get_bustag(sc->sc_res[0]); + + /* TODO: Power/clock enable */ + /* TODO: basic init */ + + for (i = 0; i < FSL_EHCI_COUNT; i ++) { + /* No interrupt - no driver */ + if (sc->sc_res[1 + i] == NULL) + continue; + + esc = &sc->ehci[i]; + esc->sc_io_tag = iot; + esc->sc_bus.parent = self; + esc->sc_bus.devices = esc->sc_devices; + esc->sc_bus.devices_max = EHCI_MAX_DEVICES; + + if (usb_bus_mem_alloc_all(&esc->sc_bus, USB_GET_DMA_TAG(self), + &ehci_iterate_hw_softc)) + continue; + + /* + * Set handle to USB related registers subregion used by + * generic EHCI driver. + */ + err = bus_space_subregion(iot, + rman_get_bushandle(sc->sc_res[0]), + FSL_EHCI_REG_OFF + (i * FSL_EHCI_REG_STEP), + FSL_EHCI_REG_SIZE, &esc->sc_io_hdl); + if (err != 0) + continue; + + /* Setup interrupt handler */ + err = bus_setup_intr(self, sc->sc_res[1 + i], INTR_TYPE_BIO, + NULL, (driver_intr_t *)ehci_interrupt, esc, + &esc->sc_intr_hdl); + if (err) { + device_printf(self, "Could not setup irq, " + "for EHCI%d %d\n", i, err); + continue; + } + + /* Add USB device */ + esc->sc_bus.bdev = device_add_child(self, "usbus", -1); + if (!esc->sc_bus.bdev) { + device_printf(self, "Could not add USB device\n"); + err = bus_teardown_intr(self, esc->sc_irq_res, + esc->sc_intr_hdl); + if (err) + device_printf(self, "Could not tear down irq," + " %d\n", err); + continue; + } + device_set_ivars(esc->sc_bus.bdev, &esc->sc_bus); + + esc->sc_id_vendor = 0x1234; + strlcpy(esc->sc_vendor, "Freescale", sizeof(esc->sc_vendor)); + + /* Set flags */ + esc->sc_flags |= EHCI_SCFLG_DONTRESET | EHCI_SCFLG_NORESTERM; + + err = ehci_init(esc); + if (!err) { + esc->sc_flags |= EHCI_SCFLG_DONEINIT; + err = device_probe_and_attach(esc->sc_bus.bdev); + } else { + device_printf(self, "USB init failed err=%d\n", err); + + device_delete_child(self, esc->sc_bus.bdev); + esc->sc_bus.bdev = NULL; + + err = bus_teardown_intr(self, esc->sc_irq_res, + esc->sc_intr_hdl); + if (err) + device_printf(self, "Could not tear down irq," + " %d\n", err); + + continue; + } + } + return (0); +} + +static int +fsl_ehci_detach(device_t self) +{ + struct imx_ehci_softc *sc; + ehci_softc_t *esc; + int err, i; + + sc = device_get_softc(self); + + for (i = 0; i < FSL_EHCI_COUNT; i ++) { + esc = &sc->ehci[i]; + if (esc->sc_flags & EHCI_SCFLG_DONEINIT) + continue; + /* + * only call ehci_detach() after ehci_init() + */ + if (esc->sc_flags & EHCI_SCFLG_DONEINIT) { + ehci_detach(esc); + esc->sc_flags &= ~EHCI_SCFLG_DONEINIT; + } + + /* + * Disable interrupts that might have been switched on in + * ehci_init. + */ + if (esc->sc_io_tag && esc->sc_io_hdl) + bus_space_write_4(esc->sc_io_tag, esc->sc_io_hdl, + EHCI_USBINTR, 0); + + if (esc->sc_irq_res && esc->sc_intr_hdl) { + err = bus_teardown_intr(self, esc->sc_irq_res, + esc->sc_intr_hdl); + if (err) { + device_printf(self, "Could not tear down irq," + " %d\n", err); + return (err); + } + esc->sc_intr_hdl = NULL; + } + + if (esc->sc_bus.bdev) { + device_delete_child(self, esc->sc_bus.bdev); + esc->sc_bus.bdev = NULL; + } + } + + /* During module unload there are lots of children leftover */ + device_delete_children(self); + + if (sc->sc_res[0]) + bus_release_resources(self, imx_ehci_spec, sc->sc_res); + + return (0); +} |