diff options
-rw-r--r-- | sys/arm/sa11x0/files.sa11x0 | 6 | ||||
-rw-r--r-- | sys/arm/sa11x0/uart_bus_sa1110.c | 78 | ||||
-rw-r--r-- | sys/arm/sa11x0/uart_cpu_sa1110.c | 68 | ||||
-rw-r--r-- | sys/arm/sa11x0/uart_dev_sa1110.c | 307 | ||||
-rw-r--r-- | sys/arm/sa11x0/uart_dev_sa1110.h | 83 |
5 files changed, 539 insertions, 3 deletions
diff --git a/sys/arm/sa11x0/files.sa11x0 b/sys/arm/sa11x0/files.sa11x0 index a704f53..44c1f41 100644 --- a/sys/arm/sa11x0/files.sa11x0 +++ b/sys/arm/sa11x0/files.sa11x0 @@ -6,6 +6,6 @@ arm/sa11x0/sa11x0_io.c optional saip arm/sa11x0/sa11x0_io_asm.S optional saip arm/sa11x0/sa11x0_irq.S optional saip arm/sa11x0/sa11x0_irqhandler.c optional saip -dev/uart/uart_cpu_sa1110.c optional uart saip -dev/uart/uart_dev_sa1110.c optional uart saip -dev/uart/uart_bus_sa1110.c optional uart saip +arm/sa11x0/uart_cpu_sa1110.c optional uart saip +arm/sa11x0/uart_dev_sa1110.c optional uart saip +arm/sa11x0/uart_bus_sa1110.c optional uart saip diff --git a/sys/arm/sa11x0/uart_bus_sa1110.c b/sys/arm/sa11x0/uart_bus_sa1110.c new file mode 100644 index 0000000..6ff3add --- /dev/null +++ b/sys/arm/sa11x0/uart_bus_sa1110.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2004 Olivier Houchard. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <machine/bus.h> +#include <sys/rman.h> +#include <machine/resource.h> + +#include <dev/pci/pcivar.h> + +#include <dev/uart/uart.h> +#include <dev/uart/uart_bus.h> +#include <dev/uart/uart_cpu.h> +#include <arm/sa11x0/uart_dev_sa1110.h> + +#include "uart_if.h" + +static int uart_sa1110_probe(device_t dev); + +static device_method_t uart_sa1110_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, uart_sa1110_probe), + DEVMETHOD(device_attach, uart_bus_attach), + DEVMETHOD(device_detach, uart_bus_detach), + { 0, 0 } +}; + +static driver_t uart_sa1110_driver = { + uart_driver_name, + uart_sa1110_methods, + sizeof(struct uart_softc), +}; + +extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; +static int +uart_sa1110_probe(device_t dev) +{ + struct uart_softc *sc; + + sc = device_get_softc(dev); + sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs); + sc->sc_class = &uart_sa1110_class; + bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas)); + return(uart_bus_probe(dev, 0, 0, 0, 0)); + return (0); +} + + +DRIVER_MODULE(uart, saip, uart_sa1110_driver, uart_devclass, 0, 0); diff --git a/sys/arm/sa11x0/uart_cpu_sa1110.c b/sys/arm/sa11x0/uart_cpu_sa1110.c new file mode 100644 index 0000000..a8967cd --- /dev/null +++ b/sys/arm/sa11x0/uart_cpu_sa1110.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2003 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/cons.h> +#include <machine/bus.h> + +#include <dev/uart/uart.h> +#include <dev/uart/uart_cpu.h> + +#include <arm/sa11x0/sa11x0_var.h> + +bus_space_tag_t uart_bus_space_io; +bus_space_tag_t uart_bus_space_mem; +int +uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) +{ + return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0); +} + +extern int got_mmu; + +int +uart_cpu_getdev(int devtype, struct uart_devinfo *di) +{ + di->ops = uart_sa1110_ops; + di->bas.chan = 0; + di->bas.bst = &sa11x0_bs_tag; + di->bas.bsh = 0x80010000; + di->bas.regshft = 0; + di->bas.rclk = 0; + di->baudrate = 9600; + di->databits = 8; + di->stopbits = 1; + di->parity = UART_PARITY_NONE; + uart_bus_space_io = &sa11x0_bs_tag; + uart_bus_space_mem = NULL; + + return (0); +} diff --git a/sys/arm/sa11x0/uart_dev_sa1110.c b/sys/arm/sa11x0/uart_dev_sa1110.c new file mode 100644 index 0000000..0060252 --- /dev/null +++ b/sys/arm/sa11x0/uart_dev_sa1110.c @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2003 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/cons.h> +#include <sys/tty.h> +#include <machine/bus.h> + +#include <dev/uart/uart.h> +#include <dev/uart/uart_cpu.h> +#include <dev/uart/uart_bus.h> +#include <arm/sa11x0/uart_dev_sa1110.h> + +#include "uart_if.h" + +#define DEFAULT_RCLK 3686400 + +extern int got_mmu; + +/* + * Low-level UART interface. + */ +static int sa1110_probe(struct uart_bas *bas); +static void sa1110_init(struct uart_bas *bas, int, int, int, int); +static void sa1110_term(struct uart_bas *bas); +static void sa1110_putc(struct uart_bas *bas, int); +static int sa1110_poll(struct uart_bas *bas); +static int sa1110_getc(struct uart_bas *bas); + +int did_mmu = 0; + +extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; + +struct uart_ops uart_sa1110_ops = { + .probe = sa1110_probe, + .init = sa1110_init, + .term = sa1110_term, + .putc = sa1110_putc, + .poll = sa1110_poll, + .getc = sa1110_getc, +}; + +static int +sa1110_probe(struct uart_bas *bas) +{ + return (0); +} + +static void +sa1110_addr_change(struct uart_bas *bas) +{ + + bas->bsh = 0xd000d000; + did_mmu = 1; +} + +static void +sa1110_init(struct uart_bas *bas, int baudrate, int databits, int stopbits, + int parity) +{ + int brd; + + /* XXX: sigh. */ + if (!did_mmu && got_mmu) + sa1110_addr_change(bas); + if (bas->rclk == 0) + bas->rclk = DEFAULT_RCLK; + while (uart_getreg(bas, SACOM_SR1) & SR1_TBY); + uart_setreg(bas, SACOM_CR3, 0); + brd = SACOMSPEED(baudrate); + uart_setreg(bas, SACOM_CR1, brd >> 8); + uart_setreg(bas, SACOM_CR2, brd & 0xff); + uart_setreg(bas, SACOM_CR3, CR3_RXE | CR3_TXE); +} + +static void +sa1110_term(struct uart_bas *bas) +{ + /* XXX */ +} + +static void +sa1110_putc(struct uart_bas *bas, int c) +{ + /* XXX: sigh. */ + if (!did_mmu && got_mmu) + sa1110_addr_change(bas); + + while (!uart_getreg(bas, SACOM_SR1) & SR1_TNF); + uart_setreg(bas, SACOM_DR, c); +} + +static int +sa1110_poll(struct uart_bas *bas) +{ + /* XXX: sigh. */ + if (!did_mmu && got_mmu) + sa1110_addr_change(bas); + + if (!(uart_getreg(bas, SACOM_SR1) & SR1_RNE)) + return (-1); + return (uart_getreg(bas, SACOM_DR) & 0xff); +} + +static int +sa1110_getc(struct uart_bas *bas) +{ + int c; + /* XXX: sigh. */ + if (!did_mmu && got_mmu) + sa1110_addr_change(bas); + + while (!(uart_getreg(bas, SACOM_SR1) & SR1_RNE)) { + u_int32_t sr0; + + sr0 = uart_getreg(bas, SACOM_SR0); + if (ISSET(sr0, SR0_RBB)) + uart_setreg(bas, SACOM_SR0, SR0_RBB); + if (ISSET(sr0, SR0_REB)) + uart_setreg(bas, SACOM_SR0, SR0_REB); + } + c = uart_getreg(bas, SACOM_DR); + c &= 0xff; + return (c); +} + +static int sa1110_bus_probe(struct uart_softc *sc); +static int sa1110_bus_attach(struct uart_softc *sc); +static int sa1110_bus_flush(struct uart_softc *, int); +static int sa1110_bus_getsig(struct uart_softc *); +static int sa1110_bus_ioctl(struct uart_softc *, int, intptr_t); +static int sa1110_bus_ipend(struct uart_softc *); +static int sa1110_bus_param(struct uart_softc *, int, int, int, int); +static int sa1110_bus_receive(struct uart_softc *); +static int sa1110_bus_setsig(struct uart_softc *, int); +static int sa1110_bus_transmit(struct uart_softc *); + +static kobj_method_t sa1110_methods[] = { + KOBJMETHOD(uart_probe, sa1110_bus_probe), + KOBJMETHOD(uart_attach, sa1110_bus_attach), + KOBJMETHOD(uart_flush, sa1110_bus_flush), + KOBJMETHOD(uart_getsig, sa1110_bus_getsig), + KOBJMETHOD(uart_ioctl, sa1110_bus_ioctl), + KOBJMETHOD(uart_ipend, sa1110_bus_ipend), + KOBJMETHOD(uart_param, sa1110_bus_param), + KOBJMETHOD(uart_receive, sa1110_bus_receive), + KOBJMETHOD(uart_setsig, sa1110_bus_setsig), + KOBJMETHOD(uart_transmit, sa1110_bus_transmit), + + {0, 0 } +}; + +int +sa1110_bus_probe(struct uart_softc *sc) +{ + return (0); +} + +static int +sa1110_bus_attach(struct uart_softc *sc) +{ + bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas)); + + sc->sc_txfifosz = 3; + sc->sc_rxfifosz = 1; + sc->sc_hwiflow = 0; + uart_setreg(&sc->sc_bas, SACOM_CR3, CR3_RXE | CR3_TXE | CR3_RIE | CR3_TIE); + return (0); +} +static int +sa1110_bus_transmit(struct uart_softc *sc) +{ + int i; +#if 0 + int sr = uart_getreg(&sc->sc_bas, SACOM_SR0); + + while (!(uart_getreg(&sc->sc_bas, SACOM_CR3) & CR3_TIE)) + uart_setreg(&sc->sc_bas, SACOM_CR3, + uart_getreg(&sc->sc_bas, SACOM_CR3) | CR3_TIE); +#endif + + sc->sc_txbusy = 1; + uart_setreg(&sc->sc_bas, SACOM_CR3, uart_getreg(&sc->sc_bas, SACOM_CR3) + | CR3_TIE); + for (i = 0; i < sc->sc_txdatasz; i++) { + while (!uart_getreg(&sc->sc_bas, SACOM_SR1) & SR1_TNF); + + uart_setreg(&sc->sc_bas, SACOM_DR, sc->sc_txbuf[i]); + uart_barrier(&sc->sc_bas); + } +#if 0 + sr = uart_getreg(&sc->sc_bas, SACOM_SR0); +#endif + + return (0); +} +static int +sa1110_bus_setsig(struct uart_softc *sc, int sig) +{ + return (0); +} +static int +sa1110_bus_receive(struct uart_softc *sc) +{ + +#if 0 + while (!(uart_getreg(&sc->sc_bas, SACOM_SR1) & SR1_RNE)) { + u_int32_t sr0; + + sr0 = uart_getreg(&sc->sc_bas, SACOM_SR0); + if (ISSET(sr0, SR0_RBB)) + uart_setreg(&sc->sc_bas, SACOM_SR0, SR0_RBB); + if (ISSET(sr0, SR0_REB)) + uart_setreg(&sc->sc_bas, SACOM_SR0, SR0_REB); + } +#endif + + uart_setreg(&sc->sc_bas, SACOM_CR3, uart_getreg(&sc->sc_bas, SACOM_CR3) + | CR3_RIE); + uart_rx_put(sc, uart_getreg(&sc->sc_bas, SACOM_DR)); + return (0); +} +static int +sa1110_bus_param(struct uart_softc *sc, int baudrate, int databits, + int stopbits, int parity) +{ + int brd; + + if (baudrate > 0) { + brd = SACOMSPEED(baudrate); + uart_setreg(&sc->sc_bas, SACOM_CR1, brd >> 8); + uart_setreg(&sc->sc_bas, SACOM_CR2, brd & 0xff); + } + return (0); +} +static int +sa1110_bus_ipend(struct uart_softc *sc) +{ + int sr = uart_getreg(&sc->sc_bas, SACOM_SR0); + int ipend = 0; + int mask = CR3_RIE | CR3_TIE; + if (sr & 1) { + if (uart_getreg(&sc->sc_bas, SACOM_CR3) & CR3_TIE) + ipend |= UART_IPEND_TXIDLE; + mask &= ~CR3_TIE; + } + if (sr & 4) { + if (uart_getreg(&sc->sc_bas, SACOM_CR3) & CR3_RIE) + ipend |= UART_IPEND_RXREADY; + mask &= ~CR3_RIE; + } + uart_setreg(&sc->sc_bas, SACOM_CR3, CR3_RXE | mask); + return (ipend); +} +static int +sa1110_bus_flush(struct uart_softc *sc, int what) +{ + return (0); +} + +static int +sa1110_bus_getsig(struct uart_softc *sc) +{ + return (0); +} + +static int +sa1110_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) +{ + return (EINVAL); +} +struct uart_class uart_sa1110_class = { + "sa1110 class", + sa1110_methods, + 1, + .uc_range = 8, + .uc_rclk = 3686400 +}; diff --git a/sys/arm/sa11x0/uart_dev_sa1110.h b/sys/arm/sa11x0/uart_dev_sa1110.h new file mode 100644 index 0000000..cbed96d --- /dev/null +++ b/sys/arm/sa11x0/uart_dev_sa1110.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2003 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _DEV_UART_DEV_SA1110_H_ +#define _DEV_UART_DEV_SA1110_H_ + +#define SACOM_FREQ (3686400 / 16) +#define SACOMSPEED(b) (SACOM_FREQ / (b) - 1) + +/* UART control register 0 */ +#define SACOM_CR0 0x00 +#define CR0_PE 0x01 /* Parity enable */ +#define CR0_OES 0x02 /* Odd/even parity select */ +#define CR0_SBS 0x04 /* Stop bit select */ +#define CR0_DSS 0x08 /* Data size select */ +#define CR0_SCE 0x10 /* Sample clock enable */ +#define CR0_RCE 0x20 /* Receive clock edge enable */ +#define CR0_TCE 0x40 /* Transmit clock edge enable */ + +/* UART control register 1 and 2 - baud rate divisor */ +#define SACOM_CR1 0x04 +#define SACOM_CR2 0x08 + +/* UART control register 3 */ +#define SACOM_CR3 0x0C +#define CR3_RXE 0x01 /* Receiver enable */ +#define CR3_TXE 0x02 /* Transmitter enable */ +#define CR3_BRK 0x04 /* Break */ +#define CR3_RIE 0x08 /* Receive FIFO interrupt enable */ +#define CR3_TIE 0x10 /* Transmit FIFO interrupt enable */ +#define CR3_LBM 0x20 /* Loopback mode */ + +/* UART data register */ +#define SACOM_DR 0x14 +#define DR_PRE 0x100 /* Parity error */ +#define DR_FRE 0x200 /* Framing error */ +#define DR_ROR 0x400 /* Receiver overrun */ + +/* UART status register 0 */ +#define SACOM_SR0 0x1C +#define SR0_TFS 0x01 /* Transmit FIFO service request */ +#define SR0_RFS 0x02 /* Receive FIFO service request */ +#define SR0_RID 0x04 /* Receiver idle */ +#define SR0_RBB 0x08 /* Receiver begin of break */ +#define SR0_REB 0x10 /* Receiver end of break */ +#define SR0_EIF 0x20 /* Error in FIFO */ + +/* UART status register 1 */ +#define SACOM_SR1 0x20 +#define SR1_TBY 0x01 /* Transmitter busy */ +#define SR1_RNE 0x02 /* Receive FIFO not empty */ +#define SR1_TNF 0x04 /* Transmit FIFO not full */ +#define SR1_PRE 0x08 /* Parity error */ +#define SR1_FRE 0x10 /* Framing error */ +#define SR1_ROR 0x20 /* Receive FIFO overrun */ + +#define ISSET(a, b) ((a) & (b)) +#endif |