From owner-svn-src-head@FreeBSD.ORG Sat Apr 27 22:38:31 2013 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 3ACE1A24; Sat, 27 Apr 2013 22:38:31 +0000 (UTC) (envelope-from wkoszek@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 1D8D91DAA; Sat, 27 Apr 2013 22:38:31 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.6/8.14.6) with ESMTP id r3RMcVNX097439; Sat, 27 Apr 2013 22:38:31 GMT (envelope-from wkoszek@svn.freebsd.org) Received: (from wkoszek@localhost) by svn.freebsd.org (8.14.6/8.14.5/Submit) id r3RMcTCm097428; Sat, 27 Apr 2013 22:38:29 GMT (envelope-from wkoszek@svn.freebsd.org) Message-Id: <201304272238.r3RMcTCm097428@svn.freebsd.org> From: "Wojciech A. Koszek" Date: Sat, 27 Apr 2013 22:38:29 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r249997 - in head/sys: arm/conf arm/xilinx arm/xilinx/zedboard boot/fdt/dts dev/cadence dev/sdhci X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 27 Apr 2013 22:38:31 -0000 Author: wkoszek Date: Sat Apr 27 22:38:29 2013 New Revision: 249997 URL: http://svnweb.freebsd.org/changeset/base/249997 Log: Add Xilinx Zynq ARM/FPGA SoC support to FreeBSD/arm port. Submitted by: Thomas Skibo Reviewed by: wkoszek, freebsd-arm@ (no objections raised) Added: head/sys/arm/conf/ZEDBOARD (contents, props changed) head/sys/arm/xilinx/ head/sys/arm/xilinx/files.zynq7 (contents, props changed) head/sys/arm/xilinx/std.zynq7 (contents, props changed) head/sys/arm/xilinx/uart_dev_cdnc.c (contents, props changed) head/sys/arm/xilinx/zedboard/ head/sys/arm/xilinx/zedboard/files.zedboard (contents, props changed) head/sys/arm/xilinx/zedboard/std.zedboard (contents, props changed) head/sys/arm/xilinx/zy7_bus_space.c (contents, props changed) head/sys/arm/xilinx/zy7_devcfg.c (contents, props changed) head/sys/arm/xilinx/zy7_ehci.c (contents, props changed) head/sys/arm/xilinx/zy7_gpio.c (contents, props changed) head/sys/arm/xilinx/zy7_l2cache.c (contents, props changed) head/sys/arm/xilinx/zy7_machdep.c (contents, props changed) head/sys/arm/xilinx/zy7_reg.h (contents, props changed) head/sys/arm/xilinx/zy7_slcr.c (contents, props changed) head/sys/arm/xilinx/zy7_slcr.h (contents, props changed) head/sys/boot/fdt/dts/zedboard.dts (contents, props changed) head/sys/dev/cadence/ head/sys/dev/cadence/if_cgem.c (contents, props changed) head/sys/dev/cadence/if_cgem_hw.h (contents, props changed) head/sys/dev/sdhci/sdhci_fdt.c (contents, props changed) Added: head/sys/arm/conf/ZEDBOARD ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/arm/conf/ZEDBOARD Sat Apr 27 22:38:29 2013 (r249997) @@ -0,0 +1,98 @@ +# ZEDBOARD -- Custom configuration for the Xilinx Zynq-7000 based +# ZedBoard (www.zedboard.org) +# +# For more information on this file, please read the handbook section on +# Kernel Configuration Files: +# +# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html +# +# The handbook is also available locally in /usr/share/doc/handbook +# if you've installed the doc distribution, otherwise always see the +# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the +# latest information. +# +# An exhaustive list of options and more detailed explanations of the +# device lines is also present in the ../../conf/NOTES and NOTES files. +# If you are in doubt as to the purpose or necessity of a line, check first +# in NOTES. +# +# $FreeBSD$ + +ident ZEDBOARD + +include "../xilinx/zedboard/std.zedboard" + +makeoptions MODULES_OVERRIDE="" +makeoptions WITHOUT_MODULES="ahc" + +options SCHED_4BSD #4BSD scheduler +options INET #InterNETworking +options INET6 #IPv6 communications protocols +options FFS #Berkeley Fast Filesystem +options SOFTUPDATES #Enable FFS soft updates support +options UFS_ACL #Support for access control lists +options UFS_DIRHASH #Improve performance on big directories +# options ROOTDEVNAME=\"ufs:mmcsd0s2a\" + +options NFSCL #Network Filesystem Client +# options NFSSD #Network Filesystem Server +# options NFSLOCKD #Network Lock Manager +# options NFS_ROOT #NFS usable as /, requires NFSCL +# options BOOTP_NFSROOT +# options BOOTP + +options MSDOSFS #MSDOS Filesystem +options CD9660 #ISO 9660 Filesystem +options PROCFS #Process filesystem (requires PSEUDOFS) +options PSEUDOFS #Pseudo-filesystem framework +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 FREEBSD_BOOT_LOADER + +# Debugging +makeoptions DEBUG=-g +options DDB +options KDB +# options BREAK_TO_DEBUGGER + +# options INVARIANTS #Enable calls of extra sanity checking +# options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS +# options WITNESS #Enable checks to detect deadlocks and cycles +# options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed + +device loop +device random +device ether +device if_cgem # Zynq-7000 gig ethernet device +device mii +device pty +device uart +device gpio + +device md +device mmc # mmc/sd bus +device mmcsd # mmc/sd flash cards +device sdhci # generic sdhci +device bpf # Berkeley packet filter + +# USB support +device usb +options USB_DEBUG +#options USB_REQ_DEBUG +#options USB_VERBOSE +device ehci +device umass +device scbus # SCSI bus (required for SCSI) +device da # Direct Access (disks) +device axe # USB-Ethernet + + +# Flattened Device Tree +options FDT +# options FDT_DTB_STATIC +# makeoptions FDT_DTS_FILE=zedboard.dts + Added: head/sys/arm/xilinx/files.zynq7 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/arm/xilinx/files.zynq7 Sat Apr 27 22:38:29 2013 (r249997) @@ -0,0 +1,31 @@ +# +# files.zynq7 +# +# $FreeBSD$ + +kern/kern_clocksource.c standard + +arm/arm/bus_space_generic.c standard +arm/arm/bus_space_asm_generic.S standard +arm/arm/cpufunc_asm_armv5.S standard +arm/arm/cpufunc_asm_arm10.S standard +arm/arm/cpufunc_asm_arm11.S standard +arm/arm/cpufunc_asm_armv7.S standard +arm/arm/irq_dispatch.S standard + +arm/arm/gic.c standard +arm/arm/mpcore_timer.c standard +arm/arm/pl310.c standard + +arm/xilinx/zy7_machdep.c standard +arm/xilinx/zy7_l2cache.c standard +arm/xilinx/zy7_bus_space.c standard +arm/xilinx/zy7_slcr.c standard +arm/xilinx/zy7_devcfg.c standard + +dev/cadence/if_cgem.c optional if_cgem +dev/sdhci/sdhci_fdt.c optional sdhci +arm/xilinx/zy7_ehci.c optional ehci +arm/xilinx/uart_dev_cdnc.c optional uart +arm/xilinx/zy7_gpio.c optional gpio + Added: head/sys/arm/xilinx/std.zynq7 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/arm/xilinx/std.zynq7 Sat Apr 27 22:38:29 2013 (r249997) @@ -0,0 +1,23 @@ +# +# std.zynq7 - Generic configuration for Xilinx Zynq-7000 PS. +# +# $FreeBSD$ + +cpu CPU_CORTEXA +machine arm armv6 + +files "../xilinx/files.zynq7" + +# Physical memory starts at 0x00000000. We assume images are loaded at +# 0x00100000, e.g. from u-boot with 'fatload mmc 0 0x100000 kernel.bin' +# +# +options PHYSADDR=0x00000000 +options KERNPHYSADDR=0x00100000 +makeoptions KERNPHYSADDR=0x00100000 +options KERNVIRTADDR=0xc0100000 # Used in ldscript.arm +makeoptions KERNVIRTADDR=0xc0100000 + +options STARTUP_PAGETABLE_ADDR=0x000f0000 +options ARM_L2_PIPT + Added: head/sys/arm/xilinx/uart_dev_cdnc.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/arm/xilinx/uart_dev_cdnc.c Sat Apr 27 22:38:29 2013 (r249997) @@ -0,0 +1,684 @@ +/*- + * Copyright (c) 2005 M. Warner Losh + * Copyright (c) 2005 Olivier Houchard + * Copyright (c) 2012 Thomas Skibo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* A driver for the Cadence AMBA UART as used by the Xilinx Zynq-7000. + * + * Reference: Zynq-7000 All Programmable SoC Technical Reference Manual. + * (v1.4) November 16, 2012. Xilinx doc UG585. UART is covered in Ch. 19 + * and register definitions are in appendix B.33. + */ + + +#include +__FBSDID("$FreeBSD$"); + +#include "opt_global.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "uart_if.h" + +#define UART_FIFO_SIZE 64 + +#define RD4(bas, reg) \ + bus_space_read_4((bas)->bst, (bas)->bsh, uart_regofs((bas), (reg))) +#define WR4(bas, reg, value) \ + bus_space_write_4((bas)->bst, (bas)->bsh, uart_regofs((bas), (reg)), \ + (value)) + +/* Register definitions for Cadence UART Controller. + */ +#define CDNC_UART_CTRL_REG 0x00 /* Control Register. */ +#define CDNC_UART_CTRL_REG_STOPBRK (1<<8) +#define CDNC_UART_CTRL_REG_STARTBRK (1<<7) +#define CDNC_UART_CTRL_REG_TORST (1<<6) +#define CDNC_UART_CTRL_REG_TX_DIS (1<<5) +#define CDNC_UART_CTRL_REG_TX_EN (1<<4) +#define CDNC_UART_CTRL_REG_RX_DIS (1<<3) +#define CDNC_UART_CTRL_REG_RX_EN (1<<2) +#define CDNC_UART_CTRL_REG_TXRST (1<<1) +#define CDNC_UART_CTRL_REG_RXRST (1<<0) + +#define CDNC_UART_MODE_REG 0x04 /* Mode Register. */ +#define CDNC_UART_MODE_REG_CHMOD_R_LOOP (3<<8) /* [9:8] - channel mode */ +#define CDNC_UART_MODE_REG_CHMOD_L_LOOP (2<<8) +#define CDNC_UART_MODE_REG_CHMOD_AUTECHO (1<<8) +#define CDNC_UART_MODE_REG_STOP2 (2<<6) /* [7:6] - stop bits */ +#define CDNC_UART_MODE_REG_PAR_NONE (4<<3) /* [5:3] - parity type */ +#define CDNC_UART_MODE_REG_PAR_MARK (3<<3) +#define CDNC_UART_MODE_REG_PAR_SPACE (2<<3) +#define CDNC_UART_MODE_REG_PAR_ODD (1<<3) +#define CDNC_UART_MODE_REG_PAR_EVEN (0<<3) +#define CDNC_UART_MODE_REG_6BIT (3<<1) /* [2:1] - character len */ +#define CDNC_UART_MODE_REG_7BIT (2<<1) +#define CDNC_UART_MODE_REG_8BIT (0<<1) +#define CDNC_UART_MODE_REG_CLKSEL (1<<0) + +#define CDNC_UART_IEN_REG 0x08 /* Interrupt registers. */ +#define CDNC_UART_IDIS_REG 0x0C +#define CDNC_UART_IMASK_REG 0x10 +#define CDNC_UART_ISTAT_REG 0x14 +#define CDNC_UART_INT_TXOVR (1<<12) +#define CDNC_UART_INT_TXNRLYFUL (1<<11) /* tx "nearly" full */ +#define CDNC_UART_INT_TXTRIG (1<<10) +#define CDNC_UART_INT_DMSI (1<<9) /* delta modem status */ +#define CDNC_UART_INT_RXTMOUT (1<<8) +#define CDNC_UART_INT_PARITY (1<<7) +#define CDNC_UART_INT_FRAMING (1<<6) +#define CDNC_UART_INT_RXOVR (1<<5) +#define CDNC_UART_INT_TXFULL (1<<4) +#define CDNC_UART_INT_TXEMPTY (1<<3) +#define CDNC_UART_INT_RXFULL (1<<2) +#define CDNC_UART_INT_RXEMPTY (1<<1) +#define CDNC_UART_INT_RXTRIG (1<<0) +#define CDNC_UART_INT_ALL 0x1FFF + +#define CDNC_UART_BAUDGEN_REG 0x18 +#define CDNC_UART_RX_TIMEO_REG 0x1C +#define CDNC_UART_RX_WATER_REG 0x20 + +#define CDNC_UART_MODEM_CTRL_REG 0x24 +#define CDNC_UART_MODEM_CTRL_REG_FCM (1<<5) /* automatic flow control */ +#define CDNC_UART_MODEM_CTRL_REG_RTS (1<<1) +#define CDNC_UART_MODEM_CTRL_REG_DTR (1<<0) + +#define CDNC_UART_MODEM_STAT_REG 0x28 +#define CDNC_UART_MODEM_STAT_REG_FCMS (1<<8) /* flow control mode (rw) */ +#define CDNC_UART_MODEM_STAT_REG_DCD (1<<7) +#define CDNC_UART_MODEM_STAT_REG_RI (1<<6) +#define CDNC_UART_MODEM_STAT_REG_DSR (1<<5) +#define CDNC_UART_MODEM_STAT_REG_CTS (1<<4) +#define CDNC_UART_MODEM_STAT_REG_DDCD (1<<3) /* change in DCD (w1tc) */ +#define CDNC_UART_MODEM_STAT_REG_TERI (1<<2) /* trail edge ring (w1tc) */ +#define CDNC_UART_MODEM_STAT_REG_DDSR (1<<1) /* change in DSR (w1tc) */ +#define CDNC_UART_MODEM_STAT_REG_DCTS (1<<0) /* change in CTS (w1tc) */ + +#define CDNC_UART_CHAN_STAT_REG 0x2C /* Channel status register. */ +#define CDNC_UART_CHAN_STAT_REG_TXNRLYFUL (1<<14) /* tx "nearly" full */ +#define CDNC_UART_CHAN_STAT_REG_TXTRIG (1<<13) +#define CDNC_UART_CHAN_STAT_REG_FDELT (1<<12) +#define CDNC_UART_CHAN_STAT_REG_TXACTIVE (1<<11) +#define CDNC_UART_CHAN_STAT_REG_RXACTIVE (1<<10) +#define CDNC_UART_CHAN_STAT_REG_TXFULL (1<<4) +#define CDNC_UART_CHAN_STAT_REG_TXEMPTY (1<<3) +#define CDNC_UART_CHAN_STAT_REG_RXEMPTY (1<<1) +#define CDNC_UART_CHAN_STAT_REG_RXTRIG (1<<0) + +#define CDNC_UART_FIFO 0x30 /* Data FIFO (tx and rx) */ +#define CDNC_UART_BAUDDIV_REG 0x34 +#define CDNC_UART_FLOWDEL_REG 0x38 +#define CDNC_UART_TX_WATER_REG 0x44 + + +/* + * Low-level UART interface. + */ +static int cdnc_uart_probe(struct uart_bas *bas); +static void cdnc_uart_init(struct uart_bas *bas, int, int, int, int); +static void cdnc_uart_term(struct uart_bas *bas); +static void cdnc_uart_putc(struct uart_bas *bas, int); +static int cdnc_uart_rxready(struct uart_bas *bas); +static int cdnc_uart_getc(struct uart_bas *bas, struct mtx *mtx); + +extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; + +static struct uart_ops cdnc_uart_ops = { + .probe = cdnc_uart_probe, + .init = cdnc_uart_init, + .term = cdnc_uart_term, + .putc = cdnc_uart_putc, + .rxready = cdnc_uart_rxready, + .getc = cdnc_uart_getc, +}; + +#define SIGCHG(c, i, s, d) \ + if (c) { \ + i |= (i & s) ? s : s | d; \ + } else { \ + i = (i & s) ? (i & ~s) | d : i; \ + } + +static int +cdnc_uart_probe(struct uart_bas *bas) +{ + + return (0); +} + +static int +cdnc_uart_set_baud(struct uart_bas *bas, int baudrate) +{ + uint32_t baudgen, bauddiv; + uint32_t best_bauddiv, best_baudgen, best_error; + uint32_t baud_out, err; + + best_bauddiv = 0; + best_baudgen = 0; + best_error = ~0; + + /* Try all possible bauddiv values and pick best match. */ + for (bauddiv = 4; bauddiv <= 255; bauddiv++) { + baudgen = (bas->rclk + (baudrate * (bauddiv + 1)) / 2) / + (baudrate * (bauddiv + 1)); + if (baudgen < 1 || baudgen > 0xffff) + continue; + + baud_out = bas->rclk / (baudgen * (bauddiv + 1)); + err = baud_out > baudrate ? + baud_out - baudrate : baudrate - baud_out; + + if (err < best_error) { + best_error = err; + best_bauddiv = bauddiv; + best_baudgen = baudgen; + } + } + + if (best_bauddiv > 0) { + WR4(bas, CDNC_UART_BAUDDIV_REG, best_bauddiv); + WR4(bas, CDNC_UART_BAUDGEN_REG, best_baudgen); + return (0); + } else + return (-1); /* out of range */ +} + +static int +cdnc_uart_set_params(struct uart_bas *bas, int baudrate, int databits, + int stopbits, int parity) +{ + uint32_t mode_reg_value = 0; + + switch (databits) { + case 6: + mode_reg_value |= CDNC_UART_MODE_REG_6BIT; + break; + case 7: + mode_reg_value |= CDNC_UART_MODE_REG_7BIT; + break; + case 8: + default: + mode_reg_value |= CDNC_UART_MODE_REG_8BIT; + break; + } + + if (stopbits == 2) + mode_reg_value |= CDNC_UART_MODE_REG_STOP2; + + switch (parity) { + case UART_PARITY_MARK: + mode_reg_value |= CDNC_UART_MODE_REG_PAR_MARK; + break; + case UART_PARITY_SPACE: + mode_reg_value |= CDNC_UART_MODE_REG_PAR_SPACE; + break; + case UART_PARITY_ODD: + mode_reg_value |= CDNC_UART_MODE_REG_PAR_ODD; + break; + case UART_PARITY_EVEN: + mode_reg_value |= CDNC_UART_MODE_REG_PAR_EVEN; + break; + case UART_PARITY_NONE: + default: + mode_reg_value |= CDNC_UART_MODE_REG_PAR_NONE; + break; + } + + WR4(bas, CDNC_UART_MODE_REG, mode_reg_value); + + if (baudrate > 0 && cdnc_uart_set_baud(bas, baudrate) < 0) + return (EINVAL); + + return(0); +} + +static void +cdnc_uart_hw_init(struct uart_bas *bas) +{ + + /* Reset RX and TX. */ + WR4(bas, CDNC_UART_CTRL_REG, + CDNC_UART_CTRL_REG_RXRST | CDNC_UART_CTRL_REG_TXRST); + + /* Interrupts all off. */ + WR4(bas, CDNC_UART_IDIS_REG, CDNC_UART_INT_ALL); + WR4(bas, CDNC_UART_ISTAT_REG, CDNC_UART_INT_ALL); + + /* Clear delta bits. */ + WR4(bas, CDNC_UART_MODEM_STAT_REG, + CDNC_UART_MODEM_STAT_REG_DDCD | CDNC_UART_MODEM_STAT_REG_TERI | + CDNC_UART_MODEM_STAT_REG_DDSR | CDNC_UART_MODEM_STAT_REG_DCTS); + + /* RX FIFO water level, stale timeout */ + WR4(bas, CDNC_UART_RX_WATER_REG, UART_FIFO_SIZE/2); + WR4(bas, CDNC_UART_RX_TIMEO_REG, 10); + + /* TX FIFO water level (not used.) */ + WR4(bas, CDNC_UART_TX_WATER_REG, UART_FIFO_SIZE/2); + + /* Bring RX and TX online. */ + WR4(bas, CDNC_UART_CTRL_REG, + CDNC_UART_CTRL_REG_RX_EN | CDNC_UART_CTRL_REG_TX_EN | + CDNC_UART_CTRL_REG_TORST | CDNC_UART_CTRL_REG_STOPBRK); + + /* Set DTR and RTS. */ + WR4(bas, CDNC_UART_MODEM_CTRL_REG, CDNC_UART_MODEM_CTRL_REG_DTR | + CDNC_UART_MODEM_CTRL_REG_RTS); +} + +/* + * Initialize this device for use as a console. + */ +static void +cdnc_uart_init(struct uart_bas *bas, int baudrate, int databits, int stopbits, + int parity) +{ + + /* Initialize hardware. */ + cdnc_uart_hw_init(bas); + + /* Set baudrate, parameters. */ + (void)cdnc_uart_set_params(bas, baudrate, databits, stopbits, parity); +} + +/* + * Free resources now that we're no longer the console. This appears to + * be never called, and I'm unsure quite what to do if I am called. + */ +static void +cdnc_uart_term(struct uart_bas *bas) +{ + + /* XXX */ +} + +/* + * Put a character of console output (so we do it here polling rather than + * interrutp driven). + */ +static void +cdnc_uart_putc(struct uart_bas *bas, int c) +{ + + /* Wait for room. */ + while ((RD4(bas,CDNC_UART_CHAN_STAT_REG) & + CDNC_UART_CHAN_STAT_REG_TXFULL) != 0) + ; + + WR4(bas, CDNC_UART_FIFO, c); + + while ((RD4(bas,CDNC_UART_CHAN_STAT_REG) & + CDNC_UART_CHAN_STAT_REG_TXEMPTY) == 0) + ; +} + +/* + * Check for a character available. + */ +static int +cdnc_uart_rxready(struct uart_bas *bas) +{ + + return ((RD4(bas, CDNC_UART_CHAN_STAT_REG) & + CDNC_UART_CHAN_STAT_REG_RXEMPTY) == 0); +} + +/* + * Block waiting for a character. + */ +static int +cdnc_uart_getc(struct uart_bas *bas, struct mtx *mtx) +{ + int c; + + uart_lock(mtx); + + while ((RD4(bas, CDNC_UART_CHAN_STAT_REG) & + CDNC_UART_CHAN_STAT_REG_RXEMPTY) != 0) { + uart_unlock(mtx); + DELAY(4); + uart_lock(mtx); + } + + c = RD4(bas, CDNC_UART_FIFO); + + uart_unlock(mtx); + + c &= 0xff; + return (c); +} + +/*****************************************************************************/ +/* + * High-level UART interface. + */ + +static int cdnc_uart_bus_probe(struct uart_softc *sc); +static int cdnc_uart_bus_attach(struct uart_softc *sc); +static int cdnc_uart_bus_flush(struct uart_softc *, int); +static int cdnc_uart_bus_getsig(struct uart_softc *); +static int cdnc_uart_bus_ioctl(struct uart_softc *, int, intptr_t); +static int cdnc_uart_bus_ipend(struct uart_softc *); +static int cdnc_uart_bus_param(struct uart_softc *, int, int, int, int); +static int cdnc_uart_bus_receive(struct uart_softc *); +static int cdnc_uart_bus_setsig(struct uart_softc *, int); +static int cdnc_uart_bus_transmit(struct uart_softc *); + +static kobj_method_t cdnc_uart_bus_methods[] = { + KOBJMETHOD(uart_probe, cdnc_uart_bus_probe), + KOBJMETHOD(uart_attach, cdnc_uart_bus_attach), + KOBJMETHOD(uart_flush, cdnc_uart_bus_flush), + KOBJMETHOD(uart_getsig, cdnc_uart_bus_getsig), + KOBJMETHOD(uart_ioctl, cdnc_uart_bus_ioctl), + KOBJMETHOD(uart_ipend, cdnc_uart_bus_ipend), + KOBJMETHOD(uart_param, cdnc_uart_bus_param), + KOBJMETHOD(uart_receive, cdnc_uart_bus_receive), + KOBJMETHOD(uart_setsig, cdnc_uart_bus_setsig), + KOBJMETHOD(uart_transmit, cdnc_uart_bus_transmit), + + KOBJMETHOD_END +}; + +int +cdnc_uart_bus_probe(struct uart_softc *sc) +{ + + sc->sc_txfifosz = UART_FIFO_SIZE; + sc->sc_rxfifosz = UART_FIFO_SIZE; + sc->sc_hwiflow = 0; + sc->sc_hwoflow = 0; + + device_set_desc(sc->sc_dev, "Cadence UART"); + + return (0); +} + +static int +cdnc_uart_bus_attach(struct uart_softc *sc) +{ + struct uart_bas *bas = &sc->sc_bas; + struct uart_devinfo *di; + + if (sc->sc_sysdev != NULL) { + di = sc->sc_sysdev; + (void)cdnc_uart_set_params(bas, di->baudrate, di->databits, + di->stopbits, di->parity); + } else + cdnc_uart_hw_init(bas); + + (void)cdnc_uart_bus_getsig(sc); + + /* Enable interrupts. */ + WR4(bas, CDNC_UART_IEN_REG, + CDNC_UART_INT_RXTRIG | CDNC_UART_INT_RXTMOUT | + CDNC_UART_INT_TXOVR | CDNC_UART_INT_RXOVR | + CDNC_UART_INT_DMSI); + + return (0); +} + +static int +cdnc_uart_bus_transmit(struct uart_softc *sc) +{ + int i; + struct uart_bas *bas = &sc->sc_bas; + + uart_lock(sc->sc_hwmtx); + + /* Clear sticky TXEMPTY status bit. */ + WR4(bas, CDNC_UART_ISTAT_REG, CDNC_UART_INT_TXEMPTY); + + for (i = 0; i < sc->sc_txdatasz; i++) + WR4(bas, CDNC_UART_FIFO, sc->sc_txbuf[i]); + + /* Enable TX empty interrupt. */ + WR4(bas, CDNC_UART_IEN_REG, CDNC_UART_INT_TXEMPTY); + sc->sc_txbusy = 1; + + uart_unlock(sc->sc_hwmtx); + + return (0); +} + +static int +cdnc_uart_bus_setsig(struct uart_softc *sc, int sig) +{ + struct uart_bas *bas = &sc->sc_bas; + uint32_t new, old, modem_ctrl; + + do { + old = sc->sc_hwsig; + new = old; + if (sig & SER_DDTR) { + SIGCHG(sig & SER_DTR, new, SER_DTR, SER_DDTR); + } + if (sig & SER_DRTS) { + SIGCHG(sig & SER_RTS, new, SER_RTS, SER_DRTS); + } + } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); + uart_lock(sc->sc_hwmtx); + modem_ctrl = RD4(bas, CDNC_UART_MODEM_CTRL_REG) & + ~(CDNC_UART_MODEM_CTRL_REG_DTR | CDNC_UART_MODEM_CTRL_REG_RTS); + if ((new & SER_DTR) != 0) + modem_ctrl |= CDNC_UART_MODEM_CTRL_REG_DTR; + if ((new & SER_RTS) != 0) + modem_ctrl |= CDNC_UART_MODEM_CTRL_REG_RTS; + WR4(bas, CDNC_UART_MODEM_CTRL_REG, modem_ctrl); + + uart_unlock(sc->sc_hwmtx); + return (0); +} + +static int +cdnc_uart_bus_receive(struct uart_softc *sc) +{ + struct uart_bas *bas = &sc->sc_bas; + uint32_t status; + int c, c_status = 0; + + uart_lock(sc->sc_hwmtx); + + /* Check for parity or framing errors and clear the status bits. */ + status = RD4(bas, CDNC_UART_ISTAT_REG); + if ((status & (CDNC_UART_INT_FRAMING | CDNC_UART_INT_PARITY)) != 0) { + WR4(bas, CDNC_UART_ISTAT_REG, + status & (CDNC_UART_INT_FRAMING | CDNC_UART_INT_PARITY)); + if ((status & CDNC_UART_INT_PARITY) != 0) + c_status |= UART_STAT_PARERR; + if ((status & CDNC_UART_INT_FRAMING) != 0) + c_status |= UART_STAT_FRAMERR; + } + + while ((RD4(bas, CDNC_UART_CHAN_STAT_REG) & + CDNC_UART_CHAN_STAT_REG_RXEMPTY) == 0) { + c = RD4(bas, CDNC_UART_FIFO) & 0xff; +#ifdef KDB + /* Detect break and drop into debugger. */ + if (c == 0 && (c_status & UART_STAT_FRAMERR) != 0 && + sc->sc_sysdev != NULL && + sc->sc_sysdev->type == UART_DEV_CONSOLE) { + kdb_break(); + WR4(bas, CDNC_UART_ISTAT_REG, CDNC_UART_INT_FRAMING); + } +#endif + uart_rx_put(sc, c | c_status); + } + + uart_unlock(sc->sc_hwmtx); + + return (0); +} + +static int +cdnc_uart_bus_param(struct uart_softc *sc, int baudrate, int databits, + int stopbits, int parity) +{ + + return (cdnc_uart_set_params(&sc->sc_bas, baudrate, + databits, stopbits, parity)); +} + +static int +cdnc_uart_bus_ipend(struct uart_softc *sc) +{ + int ipend = 0; + struct uart_bas *bas = &sc->sc_bas; + uint32_t istatus; + + uart_lock(sc->sc_hwmtx); + + istatus = RD4(bas, CDNC_UART_ISTAT_REG); + + /* Clear interrupt bits. */ + WR4(bas, CDNC_UART_ISTAT_REG, istatus & + (CDNC_UART_INT_RXTRIG | CDNC_UART_INT_RXTMOUT | + CDNC_UART_INT_TXOVR | CDNC_UART_INT_RXOVR | + CDNC_UART_INT_TXEMPTY | CDNC_UART_INT_DMSI)); + + /* Receive data. */ + if ((istatus & (CDNC_UART_INT_RXTRIG | CDNC_UART_INT_RXTMOUT)) != 0) + ipend |= SER_INT_RXREADY; + + /* Transmit fifo empty. */ + if (sc->sc_txbusy && (istatus & CDNC_UART_INT_TXEMPTY) != 0) { + /* disable txempty interrupt. */ + WR4(bas, CDNC_UART_IDIS_REG, CDNC_UART_INT_TXEMPTY); + ipend |= SER_INT_TXIDLE; + } + + /* TX Overflow. */ + if ((istatus & CDNC_UART_INT_TXOVR) != 0) + ipend |= SER_INT_OVERRUN; + + /* RX Overflow. */ + if ((istatus & CDNC_UART_INT_RXOVR) != 0) + ipend |= SER_INT_OVERRUN; + + /* Modem signal change. */ + if ((istatus & CDNC_UART_INT_DMSI) != 0) { + WR4(bas, CDNC_UART_MODEM_STAT_REG, + CDNC_UART_MODEM_STAT_REG_DDCD | + CDNC_UART_MODEM_STAT_REG_TERI | + CDNC_UART_MODEM_STAT_REG_DDSR | + CDNC_UART_MODEM_STAT_REG_DCTS); + ipend |= SER_INT_SIGCHG; + } + + uart_unlock(sc->sc_hwmtx); + return (ipend); +} + +static int +cdnc_uart_bus_flush(struct uart_softc *sc, int what) +{ + + return (0); +} + +static int +cdnc_uart_bus_getsig(struct uart_softc *sc) +{ + struct uart_bas *bas = &sc->sc_bas; + uint32_t new, old, sig; + uint8_t modem_status; + + do { + old = sc->sc_hwsig; + sig = old; + uart_lock(sc->sc_hwmtx); + modem_status = RD4(bas, CDNC_UART_MODEM_STAT_REG); + uart_unlock(sc->sc_hwmtx); + SIGCHG(modem_status & CDNC_UART_MODEM_STAT_REG_DSR, + sig, SER_DSR, SER_DDSR); + SIGCHG(modem_status & CDNC_UART_MODEM_STAT_REG_CTS, + sig, SER_CTS, SER_DCTS); + SIGCHG(modem_status & CDNC_UART_MODEM_STAT_REG_DCD, + sig, SER_DCD, SER_DDCD); + SIGCHG(modem_status & CDNC_UART_MODEM_STAT_REG_RI, + sig, SER_RI, SER_DRI); + new = sig & ~SER_MASK_DELTA; + } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); + return (sig); +} + +static int +cdnc_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) +{ + struct uart_bas *bas = &sc->sc_bas; + uint32_t uart_ctrl, modem_ctrl; + int error = 0; + + uart_lock(sc->sc_hwmtx); + + switch (request) { + case UART_IOCTL_BREAK: + uart_ctrl = RD4(bas, CDNC_UART_CTRL_REG); + if (data) { + uart_ctrl |= CDNC_UART_CTRL_REG_STARTBRK; + uart_ctrl &= ~CDNC_UART_CTRL_REG_STOPBRK; + } else { + uart_ctrl |= CDNC_UART_CTRL_REG_STOPBRK; + uart_ctrl &= ~CDNC_UART_CTRL_REG_STARTBRK; + } + WR4(bas, CDNC_UART_CTRL_REG, uart_ctrl); + break; + case UART_IOCTL_IFLOW: + modem_ctrl = RD4(bas, CDNC_UART_MODEM_CTRL_REG); + if (data) + modem_ctrl |= CDNC_UART_MODEM_CTRL_REG_RTS; + else + modem_ctrl &= ~CDNC_UART_MODEM_CTRL_REG_RTS; + WR4(bas, CDNC_UART_MODEM_CTRL_REG, modem_ctrl); + break; + default: + error = EINVAL; + break; + } + + uart_unlock(sc->sc_hwmtx); + + return (error); +} + +struct uart_class uart_cdnc_class = { + "cdnc_uart", + cdnc_uart_bus_methods, + sizeof(struct uart_softc), + .uc_ops = &cdnc_uart_ops, + .uc_range = 8 +}; Added: head/sys/arm/xilinx/zedboard/files.zedboard ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/arm/xilinx/zedboard/files.zedboard Sat Apr 27 22:38:29 2013 (r249997) @@ -0,0 +1,9 @@ +# +# files.zedboard +# +# $FreeBSD$ + +# We'll need board specific files once we start implementing drivers +# for Zedboard PL peripherals such as HDMI, VGA, or Audio Codecs. For +# now, nothing is needed. +# Added: head/sys/arm/xilinx/zedboard/std.zedboard ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/arm/xilinx/zedboard/std.zedboard Sat Apr 27 22:38:29 2013 (r249997) @@ -0,0 +1,8 @@ +# +# std.zedboard +# +# $FreeBSD$ + +include "../xilinx/std.zynq7" +files "../xilinx/zedboard/files.zedboard" + Added: head/sys/arm/xilinx/zy7_bus_space.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/arm/xilinx/zy7_bus_space.c Sat Apr 27 22:38:29 2013 (r249997) @@ -0,0 +1,113 @@ +/*- + * Copyright (C) 2012 FreeBSD Foundation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include + +/* 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, + + /* 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; Added: head/sys/arm/xilinx/zy7_devcfg.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/arm/xilinx/zy7_devcfg.c Sat Apr 27 22:38:29 2013 (r249997) @@ -0,0 +1,650 @@ +/*- + * Copyright (C) 2013, Thomas Skibo. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***