1aef60d8cSIan Lepore /*- 2*718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*718cf2ccSPedro F. Giffuni * 4aef60d8cSIan Lepore * Copyright (c) 2013 Ian Lepore 5aef60d8cSIan Lepore * All rights reserved. 6aef60d8cSIan Lepore * 7aef60d8cSIan Lepore * Redistribution and use in source and binary forms, with or without 8aef60d8cSIan Lepore * modification, are permitted provided that the following conditions 9aef60d8cSIan Lepore * are met: 10aef60d8cSIan Lepore * 11aef60d8cSIan Lepore * 1. Redistributions of source code must retain the above copyright 12aef60d8cSIan Lepore * notice, this list of conditions and the following disclaimer. 13aef60d8cSIan Lepore * 2. Redistributions in binary form must reproduce the above copyright 14aef60d8cSIan Lepore * notice, this list of conditions and the following disclaimer in the 15aef60d8cSIan Lepore * documentation and/or other materials provided with the distribution. 16aef60d8cSIan Lepore * 17aef60d8cSIan Lepore * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18aef60d8cSIan Lepore * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19aef60d8cSIan Lepore * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20aef60d8cSIan Lepore * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21aef60d8cSIan Lepore * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22aef60d8cSIan Lepore * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23aef60d8cSIan Lepore * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24aef60d8cSIan Lepore * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25aef60d8cSIan Lepore * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26aef60d8cSIan Lepore * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27aef60d8cSIan Lepore */ 28aef60d8cSIan Lepore 29aef60d8cSIan Lepore #include "opt_platform.h" 30aef60d8cSIan Lepore 31aef60d8cSIan Lepore #include <sys/cdefs.h> 32aef60d8cSIan Lepore __FBSDID("$FreeBSD$"); 33aef60d8cSIan Lepore 34aef60d8cSIan Lepore #include <sys/param.h> 35aef60d8cSIan Lepore #include <sys/systm.h> 36aef60d8cSIan Lepore #include <sys/bus.h> 37aef60d8cSIan Lepore #include <sys/conf.h> 38aef60d8cSIan Lepore #include <sys/kernel.h> 39aef60d8cSIan Lepore #include <sys/sysctl.h> 40aef60d8cSIan Lepore #include <machine/bus.h> 41aef60d8cSIan Lepore 42aef60d8cSIan Lepore #include <arm/ti/ti_prcm.h> 435b03aba6SOleksandr Tymoshenko #include <arm/ti/ti_hwmods.h> 44aef60d8cSIan Lepore 45aef60d8cSIan Lepore #include <dev/fdt/fdt_common.h> 46aef60d8cSIan Lepore #include <dev/ofw/ofw_bus.h> 47aef60d8cSIan Lepore #include <dev/ofw/ofw_bus_subr.h> 48aef60d8cSIan Lepore 49aef60d8cSIan Lepore #include <dev/uart/uart.h> 50aef60d8cSIan Lepore #include <dev/uart/uart_cpu.h> 513bb693afSIan Lepore #include <dev/uart/uart_cpu_fdt.h> 52aef60d8cSIan Lepore #include <dev/uart/uart_bus.h> 53aef60d8cSIan Lepore #include <dev/uart/uart_dev_ns8250.h> 54aef60d8cSIan Lepore 55aef60d8cSIan Lepore #include "uart_if.h" 56aef60d8cSIan Lepore 57aef60d8cSIan Lepore /* 58aef60d8cSIan Lepore * High-level UART interface. 59aef60d8cSIan Lepore */ 60aef60d8cSIan Lepore struct ti8250_softc { 61aef60d8cSIan Lepore struct ns8250_softc ns8250_base; 62aef60d8cSIan Lepore /*uint32_t mystuff;*/ 63aef60d8cSIan Lepore }; 64aef60d8cSIan Lepore 65aef60d8cSIan Lepore #define MDR1_REG 8 66aef60d8cSIan Lepore #define MDR1_MODE_UART 0 67aef60d8cSIan Lepore #define MDR1_MODE_DISABLE 7 68aef60d8cSIan Lepore #define SYSCC_REG 15 69aef60d8cSIan Lepore #define SYSCC_SOFTRESET (1 << 1) 70aef60d8cSIan Lepore #define SYSS_REG 16 71aef60d8cSIan Lepore #define SYSS_STATUS_RESETDONE (1 << 0) 72aef60d8cSIan Lepore 73aef60d8cSIan Lepore static int 74aef60d8cSIan Lepore ti8250_bus_probe(struct uart_softc *sc) 75aef60d8cSIan Lepore { 76aef60d8cSIan Lepore int status; 77aef60d8cSIan Lepore clk_ident_t clkid; 78aef60d8cSIan Lepore 79aef60d8cSIan Lepore /* Enable clocks for this device. We can't continue if that fails. */ 805b03aba6SOleksandr Tymoshenko clkid = ti_hwmods_get_clock(sc->sc_dev); 815b03aba6SOleksandr Tymoshenko if (clkid == INVALID_CLK_IDENT) { 825b03aba6SOleksandr Tymoshenko device_printf(sc->sc_dev, 835b03aba6SOleksandr Tymoshenko "failed to get clock based on hwmods\n"); 845b03aba6SOleksandr Tymoshenko clkid = UART1_CLK + device_get_unit(sc->sc_dev); 855b03aba6SOleksandr Tymoshenko } 86aef60d8cSIan Lepore if ((status = ti_prcm_clk_enable(clkid)) != 0) 87aef60d8cSIan Lepore return (status); 88aef60d8cSIan Lepore 89aef60d8cSIan Lepore /* 90aef60d8cSIan Lepore * Set the hardware to disabled mode, do a full device reset, then set 91aef60d8cSIan Lepore * it to uart mode. Most devices will be reset-and-disabled already, 92aef60d8cSIan Lepore * but you never know what a bootloader might have done. 93aef60d8cSIan Lepore */ 94aef60d8cSIan Lepore uart_setreg(&sc->sc_bas, MDR1_REG, MDR1_MODE_DISABLE); 95aef60d8cSIan Lepore uart_setreg(&sc->sc_bas, SYSCC_REG, SYSCC_SOFTRESET); 96aef60d8cSIan Lepore while (uart_getreg(&sc->sc_bas, SYSS_REG) & SYSS_STATUS_RESETDONE) 97aef60d8cSIan Lepore continue; 98aef60d8cSIan Lepore uart_setreg(&sc->sc_bas, MDR1_REG, MDR1_MODE_UART); 99aef60d8cSIan Lepore 100aef60d8cSIan Lepore status = ns8250_bus_probe(sc); 101aef60d8cSIan Lepore if (status == 0) 102aef60d8cSIan Lepore device_set_desc(sc->sc_dev, "TI UART (16550 compatible)"); 103aef60d8cSIan Lepore 104aef60d8cSIan Lepore return (status); 105aef60d8cSIan Lepore } 106aef60d8cSIan Lepore 107aef60d8cSIan Lepore static kobj_method_t ti8250_methods[] = { 108aef60d8cSIan Lepore KOBJMETHOD(uart_probe, ti8250_bus_probe), 109aef60d8cSIan Lepore 110aef60d8cSIan Lepore KOBJMETHOD(uart_attach, ns8250_bus_attach), 111aef60d8cSIan Lepore KOBJMETHOD(uart_detach, ns8250_bus_detach), 112aef60d8cSIan Lepore KOBJMETHOD(uart_flush, ns8250_bus_flush), 113aef60d8cSIan Lepore KOBJMETHOD(uart_getsig, ns8250_bus_getsig), 114aef60d8cSIan Lepore KOBJMETHOD(uart_ioctl, ns8250_bus_ioctl), 115aef60d8cSIan Lepore KOBJMETHOD(uart_ipend, ns8250_bus_ipend), 116aef60d8cSIan Lepore KOBJMETHOD(uart_param, ns8250_bus_param), 117aef60d8cSIan Lepore KOBJMETHOD(uart_receive, ns8250_bus_receive), 118aef60d8cSIan Lepore KOBJMETHOD(uart_setsig, ns8250_bus_setsig), 119aef60d8cSIan Lepore KOBJMETHOD(uart_transmit, ns8250_bus_transmit), 120aef60d8cSIan Lepore KOBJMETHOD_END 121aef60d8cSIan Lepore }; 122aef60d8cSIan Lepore 1233bb693afSIan Lepore static struct uart_class uart_ti8250_class = { 124aef60d8cSIan Lepore "ti8250", 125aef60d8cSIan Lepore ti8250_methods, 126aef60d8cSIan Lepore sizeof(struct ti8250_softc), 127aef60d8cSIan Lepore .uc_ops = &uart_ns8250_ops, 128aef60d8cSIan Lepore .uc_range = 0x88, 129405ada37SAndrew Turner .uc_rclk = 48000000, 1305b03aba6SOleksandr Tymoshenko .uc_rshift = 2 131aef60d8cSIan Lepore }; 1323bb693afSIan Lepore static struct ofw_compat_data compat_data[] = { 1333bb693afSIan Lepore {"ti,ns16550", (uintptr_t)&uart_ti8250_class}, 1345b03aba6SOleksandr Tymoshenko {"ti,omap3-uart", (uintptr_t)&uart_ti8250_class}, 1355b03aba6SOleksandr Tymoshenko {"ti,omap4-uart", (uintptr_t)&uart_ti8250_class}, 1363bb693afSIan Lepore {NULL, (uintptr_t)NULL}, 1373bb693afSIan Lepore }; 1383bb693afSIan Lepore UART_FDT_CLASS_AND_DEVICE(compat_data); 139