1aef60d8cSIan Lepore /*- 2aef60d8cSIan Lepore * Copyright (c) 2013 Ian Lepore 3aef60d8cSIan Lepore * All rights reserved. 4aef60d8cSIan Lepore * 5aef60d8cSIan Lepore * Redistribution and use in source and binary forms, with or without 6aef60d8cSIan Lepore * modification, are permitted provided that the following conditions 7aef60d8cSIan Lepore * are met: 8aef60d8cSIan Lepore * 9aef60d8cSIan Lepore * 1. Redistributions of source code must retain the above copyright 10aef60d8cSIan Lepore * notice, this list of conditions and the following disclaimer. 11aef60d8cSIan Lepore * 2. Redistributions in binary form must reproduce the above copyright 12aef60d8cSIan Lepore * notice, this list of conditions and the following disclaimer in the 13aef60d8cSIan Lepore * documentation and/or other materials provided with the distribution. 14aef60d8cSIan Lepore * 15aef60d8cSIan Lepore * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16aef60d8cSIan Lepore * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17aef60d8cSIan Lepore * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18aef60d8cSIan Lepore * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19aef60d8cSIan Lepore * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20aef60d8cSIan Lepore * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21aef60d8cSIan Lepore * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22aef60d8cSIan Lepore * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23aef60d8cSIan Lepore * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24aef60d8cSIan Lepore * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25aef60d8cSIan Lepore */ 26aef60d8cSIan Lepore 27aef60d8cSIan Lepore #include "opt_platform.h" 28aef60d8cSIan Lepore 29aef60d8cSIan Lepore #include <sys/cdefs.h> 30aef60d8cSIan Lepore __FBSDID("$FreeBSD$"); 31aef60d8cSIan Lepore 32aef60d8cSIan Lepore #include <sys/param.h> 33aef60d8cSIan Lepore #include <sys/systm.h> 34aef60d8cSIan Lepore #include <sys/bus.h> 35aef60d8cSIan Lepore #include <sys/conf.h> 36aef60d8cSIan Lepore #include <sys/kernel.h> 37aef60d8cSIan Lepore #include <sys/sysctl.h> 38aef60d8cSIan Lepore #include <machine/bus.h> 39aef60d8cSIan Lepore 40aef60d8cSIan Lepore #include <arm/ti/ti_prcm.h> 41aef60d8cSIan Lepore 42aef60d8cSIan Lepore #include <dev/fdt/fdt_common.h> 43aef60d8cSIan Lepore #include <dev/ofw/ofw_bus.h> 44aef60d8cSIan Lepore #include <dev/ofw/ofw_bus_subr.h> 45aef60d8cSIan Lepore 46aef60d8cSIan Lepore #include <dev/uart/uart.h> 47aef60d8cSIan Lepore #include <dev/uart/uart_cpu.h> 48*3bb693afSIan Lepore #include <dev/uart/uart_cpu_fdt.h> 49aef60d8cSIan Lepore #include <dev/uart/uart_bus.h> 50aef60d8cSIan Lepore #include <dev/uart/uart_dev_ns8250.h> 51aef60d8cSIan Lepore 52aef60d8cSIan Lepore #include "uart_if.h" 53aef60d8cSIan Lepore 54aef60d8cSIan Lepore /* 55aef60d8cSIan Lepore * High-level UART interface. 56aef60d8cSIan Lepore */ 57aef60d8cSIan Lepore struct ti8250_softc { 58aef60d8cSIan Lepore struct ns8250_softc ns8250_base; 59aef60d8cSIan Lepore /*uint32_t mystuff;*/ 60aef60d8cSIan Lepore }; 61aef60d8cSIan Lepore 62aef60d8cSIan Lepore #define MDR1_REG 8 63aef60d8cSIan Lepore #define MDR1_MODE_UART 0 64aef60d8cSIan Lepore #define MDR1_MODE_DISABLE 7 65aef60d8cSIan Lepore #define SYSCC_REG 15 66aef60d8cSIan Lepore #define SYSCC_SOFTRESET (1 << 1) 67aef60d8cSIan Lepore #define SYSS_REG 16 68aef60d8cSIan Lepore #define SYSS_STATUS_RESETDONE (1 << 0) 69aef60d8cSIan Lepore 70aef60d8cSIan Lepore static int 71aef60d8cSIan Lepore ti8250_bus_probe(struct uart_softc *sc) 72aef60d8cSIan Lepore { 73aef60d8cSIan Lepore int status; 74aef60d8cSIan Lepore int devid; 75aef60d8cSIan Lepore clk_ident_t clkid; 76aef60d8cSIan Lepore pcell_t prop; 77aef60d8cSIan Lepore phandle_t node; 78aef60d8cSIan Lepore 79aef60d8cSIan Lepore /* 80aef60d8cSIan Lepore * Get the device id from FDT. If it's not there we can't turn on the 81aef60d8cSIan Lepore * right clocks, so bail, unless we're doing unit 0. We assume that's 82aef60d8cSIan Lepore * the serial console, whose clock isn't controllable anyway, and we 83aef60d8cSIan Lepore * sure don't want to break the console because of a config error. 84aef60d8cSIan Lepore */ 85aef60d8cSIan Lepore node = ofw_bus_get_node(sc->sc_dev); 86aef60d8cSIan Lepore if ((OF_getprop(node, "uart-device-id", &prop, sizeof(prop))) <= 0) { 87aef60d8cSIan Lepore device_printf(sc->sc_dev, 88aef60d8cSIan Lepore "missing uart-device-id attribute in FDT\n"); 89aef60d8cSIan Lepore if (device_get_unit(sc->sc_dev) != 0) 90aef60d8cSIan Lepore return (ENXIO); 91aef60d8cSIan Lepore devid = 0; 92aef60d8cSIan Lepore } else 93aef60d8cSIan Lepore devid = fdt32_to_cpu(prop); 94aef60d8cSIan Lepore 95aef60d8cSIan Lepore /* Enable clocks for this device. We can't continue if that fails. */ 96aef60d8cSIan Lepore clkid = UART0_CLK + devid; 97aef60d8cSIan Lepore if ((status = ti_prcm_clk_enable(clkid)) != 0) 98aef60d8cSIan Lepore return (status); 99aef60d8cSIan Lepore 100aef60d8cSIan Lepore /* 101aef60d8cSIan Lepore * Set the hardware to disabled mode, do a full device reset, then set 102aef60d8cSIan Lepore * it to uart mode. Most devices will be reset-and-disabled already, 103aef60d8cSIan Lepore * but you never know what a bootloader might have done. 104aef60d8cSIan Lepore */ 105aef60d8cSIan Lepore uart_setreg(&sc->sc_bas, MDR1_REG, MDR1_MODE_DISABLE); 106aef60d8cSIan Lepore uart_setreg(&sc->sc_bas, SYSCC_REG, SYSCC_SOFTRESET); 107aef60d8cSIan Lepore while (uart_getreg(&sc->sc_bas, SYSS_REG) & SYSS_STATUS_RESETDONE) 108aef60d8cSIan Lepore continue; 109aef60d8cSIan Lepore uart_setreg(&sc->sc_bas, MDR1_REG, MDR1_MODE_UART); 110aef60d8cSIan Lepore 111aef60d8cSIan Lepore status = ns8250_bus_probe(sc); 112aef60d8cSIan Lepore if (status == 0) 113aef60d8cSIan Lepore device_set_desc(sc->sc_dev, "TI UART (16550 compatible)"); 114aef60d8cSIan Lepore 115aef60d8cSIan Lepore return (status); 116aef60d8cSIan Lepore } 117aef60d8cSIan Lepore 118aef60d8cSIan Lepore static kobj_method_t ti8250_methods[] = { 119aef60d8cSIan Lepore KOBJMETHOD(uart_probe, ti8250_bus_probe), 120aef60d8cSIan Lepore 121aef60d8cSIan Lepore KOBJMETHOD(uart_attach, ns8250_bus_attach), 122aef60d8cSIan Lepore KOBJMETHOD(uart_detach, ns8250_bus_detach), 123aef60d8cSIan Lepore KOBJMETHOD(uart_flush, ns8250_bus_flush), 124aef60d8cSIan Lepore KOBJMETHOD(uart_getsig, ns8250_bus_getsig), 125aef60d8cSIan Lepore KOBJMETHOD(uart_ioctl, ns8250_bus_ioctl), 126aef60d8cSIan Lepore KOBJMETHOD(uart_ipend, ns8250_bus_ipend), 127aef60d8cSIan Lepore KOBJMETHOD(uart_param, ns8250_bus_param), 128aef60d8cSIan Lepore KOBJMETHOD(uart_receive, ns8250_bus_receive), 129aef60d8cSIan Lepore KOBJMETHOD(uart_setsig, ns8250_bus_setsig), 130aef60d8cSIan Lepore KOBJMETHOD(uart_transmit, ns8250_bus_transmit), 131aef60d8cSIan Lepore KOBJMETHOD_END 132aef60d8cSIan Lepore }; 133aef60d8cSIan Lepore 134*3bb693afSIan Lepore static struct uart_class uart_ti8250_class = { 135aef60d8cSIan Lepore "ti8250", 136aef60d8cSIan Lepore ti8250_methods, 137aef60d8cSIan Lepore sizeof(struct ti8250_softc), 138aef60d8cSIan Lepore .uc_ops = &uart_ns8250_ops, 139aef60d8cSIan Lepore .uc_range = 0x88, 140aef60d8cSIan Lepore .uc_rclk = 48000000 141aef60d8cSIan Lepore }; 142*3bb693afSIan Lepore static struct ofw_compat_data compat_data[] = { 143*3bb693afSIan Lepore {"ti,ns16550", (uintptr_t)&uart_ti8250_class}, 144*3bb693afSIan Lepore {NULL, (uintptr_t)NULL}, 145*3bb693afSIan Lepore }; 146*3bb693afSIan Lepore UART_FDT_CLASS_AND_DEVICE(compat_data); 147