1*a29b35ddSAndrew Turner /*- 2*a29b35ddSAndrew Turner * Copyright (c) 2012, 2013 The FreeBSD Foundation 3*a29b35ddSAndrew Turner * All rights reserved. 4*a29b35ddSAndrew Turner * 5*a29b35ddSAndrew Turner * This software was developed by Oleksandr Rybalko under sponsorship 6*a29b35ddSAndrew Turner * from the FreeBSD Foundation. 7*a29b35ddSAndrew Turner * 8*a29b35ddSAndrew Turner * Redistribution and use in source and binary forms, with or without 9*a29b35ddSAndrew Turner * modification, are permitted provided that the following conditions 10*a29b35ddSAndrew Turner * are met: 11*a29b35ddSAndrew Turner * 1. Redistributions of source code must retain the above copyright 12*a29b35ddSAndrew Turner * notice, this list of conditions and the following disclaimer. 13*a29b35ddSAndrew Turner * 2. Redistributions in binary form must reproduce the above copyright 14*a29b35ddSAndrew Turner * notice, this list of conditions and the following disclaimer in the 15*a29b35ddSAndrew Turner * documentation and/or other materials provided with the distribution. 16*a29b35ddSAndrew Turner * 17*a29b35ddSAndrew Turner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18*a29b35ddSAndrew Turner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19*a29b35ddSAndrew Turner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20*a29b35ddSAndrew Turner * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21*a29b35ddSAndrew Turner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22*a29b35ddSAndrew Turner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23*a29b35ddSAndrew Turner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24*a29b35ddSAndrew Turner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25*a29b35ddSAndrew Turner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26*a29b35ddSAndrew Turner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27*a29b35ddSAndrew Turner * SUCH DAMAGE. 28*a29b35ddSAndrew Turner */ 29*a29b35ddSAndrew Turner 30*a29b35ddSAndrew Turner /* Simple UART console driver for Freescale i.MX515 */ 31*a29b35ddSAndrew Turner 32*a29b35ddSAndrew Turner #include <sys/cdefs.h> 33*a29b35ddSAndrew Turner __FBSDID("$FreeBSD$"); 34*a29b35ddSAndrew Turner 35*a29b35ddSAndrew Turner #include <sys/types.h> 36*a29b35ddSAndrew Turner #include <sys/param.h> 37*a29b35ddSAndrew Turner #include <sys/systm.h> 38*a29b35ddSAndrew Turner #include <sys/cons.h> 39*a29b35ddSAndrew Turner #include <sys/consio.h> 40*a29b35ddSAndrew Turner #include <sys/kernel.h> 41*a29b35ddSAndrew Turner 42*a29b35ddSAndrew Turner /* Allow it to be predefined, to be able to use another UART for console */ 43*a29b35ddSAndrew Turner #ifndef IMX_UART_BASE 44*a29b35ddSAndrew Turner #define IMX_UART_BASE 0xe3fbc000 /* imx51 UART1 */ 45*a29b35ddSAndrew Turner #endif 46*a29b35ddSAndrew Turner 47*a29b35ddSAndrew Turner #define IMX_RXD 0x00 48*a29b35ddSAndrew Turner #define IMX_TXD 0x40 49*a29b35ddSAndrew Turner 50*a29b35ddSAndrew Turner #define IMX_UFCR 0x90 51*a29b35ddSAndrew Turner #define IMX_USR1 0x94 52*a29b35ddSAndrew Turner #define IMX_USR1_TRDY (1 << 13) 53*a29b35ddSAndrew Turner 54*a29b35ddSAndrew Turner #define IMX_USR2 0x98 55*a29b35ddSAndrew Turner #define IMX_USR2_RDR (1 << 0) 56*a29b35ddSAndrew Turner #define IMX_USR2_TXFE (1 << 14) 57*a29b35ddSAndrew Turner #define IMX_USR2_TXDC (1 << 3) 58*a29b35ddSAndrew Turner 59*a29b35ddSAndrew Turner #define IMX_UTS 0xb4 60*a29b35ddSAndrew Turner #define IMX_UTS_TXFULL (1 << 4) 61*a29b35ddSAndrew Turner 62*a29b35ddSAndrew Turner /* 63*a29b35ddSAndrew Turner * The base address of the uart registers. 64*a29b35ddSAndrew Turner * 65*a29b35ddSAndrew Turner * This is global so that it can be changed on the fly from the outside. For 66*a29b35ddSAndrew Turner * example, set imx_uart_base=physaddr and then call cninit() as the first two 67*a29b35ddSAndrew Turner * lines of initarm() and enjoy printf() availability through the tricky bits of 68*a29b35ddSAndrew Turner * startup. After initarm() switches from physical to virtual addressing, just 69*a29b35ddSAndrew Turner * set imx_uart_base=virtaddr and printf keeps working. 70*a29b35ddSAndrew Turner */ 71*a29b35ddSAndrew Turner uint32_t imx_uart_base = IMX_UART_BASE; 72*a29b35ddSAndrew Turner 73*a29b35ddSAndrew Turner /* 74*a29b35ddSAndrew Turner * uart related funcs 75*a29b35ddSAndrew Turner */ 76*a29b35ddSAndrew Turner static uint32_t 77*a29b35ddSAndrew Turner ub_getreg(uint32_t off) 78*a29b35ddSAndrew Turner { 79*a29b35ddSAndrew Turner 80*a29b35ddSAndrew Turner return *((volatile uint32_t *)(imx_uart_base + off)); 81*a29b35ddSAndrew Turner } 82*a29b35ddSAndrew Turner 83*a29b35ddSAndrew Turner static void 84*a29b35ddSAndrew Turner ub_setreg(uint32_t off, uint32_t val) 85*a29b35ddSAndrew Turner { 86*a29b35ddSAndrew Turner 87*a29b35ddSAndrew Turner *((volatile uint32_t *)(imx_uart_base + off)) = val; 88*a29b35ddSAndrew Turner } 89*a29b35ddSAndrew Turner 90*a29b35ddSAndrew Turner static int 91*a29b35ddSAndrew Turner ub_tstc(void) 92*a29b35ddSAndrew Turner { 93*a29b35ddSAndrew Turner 94*a29b35ddSAndrew Turner return ((ub_getreg(IMX_USR2) & IMX_USR2_RDR) ? 1 : 0); 95*a29b35ddSAndrew Turner } 96*a29b35ddSAndrew Turner 97*a29b35ddSAndrew Turner static int 98*a29b35ddSAndrew Turner ub_getc(void) 99*a29b35ddSAndrew Turner { 100*a29b35ddSAndrew Turner 101*a29b35ddSAndrew Turner while (!ub_tstc()); 102*a29b35ddSAndrew Turner __asm __volatile("nop"); 103*a29b35ddSAndrew Turner 104*a29b35ddSAndrew Turner return (ub_getreg(IMX_RXD) & 0xff); 105*a29b35ddSAndrew Turner } 106*a29b35ddSAndrew Turner 107*a29b35ddSAndrew Turner static void 108*a29b35ddSAndrew Turner ub_putc(unsigned char c) 109*a29b35ddSAndrew Turner { 110*a29b35ddSAndrew Turner 111*a29b35ddSAndrew Turner if (c == '\n') 112*a29b35ddSAndrew Turner ub_putc('\r'); 113*a29b35ddSAndrew Turner 114*a29b35ddSAndrew Turner while (ub_getreg(IMX_UTS) & IMX_UTS_TXFULL) 115*a29b35ddSAndrew Turner __asm __volatile("nop"); 116*a29b35ddSAndrew Turner 117*a29b35ddSAndrew Turner ub_setreg(IMX_TXD, c); 118*a29b35ddSAndrew Turner } 119*a29b35ddSAndrew Turner 120*a29b35ddSAndrew Turner static cn_probe_t uart_cnprobe; 121*a29b35ddSAndrew Turner static cn_init_t uart_cninit; 122*a29b35ddSAndrew Turner static cn_term_t uart_cnterm; 123*a29b35ddSAndrew Turner static cn_getc_t uart_cngetc; 124*a29b35ddSAndrew Turner static cn_putc_t uart_cnputc; 125*a29b35ddSAndrew Turner static cn_grab_t uart_cngrab; 126*a29b35ddSAndrew Turner static cn_ungrab_t uart_cnungrab; 127*a29b35ddSAndrew Turner 128*a29b35ddSAndrew Turner static void 129*a29b35ddSAndrew Turner uart_cngrab(struct consdev *cp) 130*a29b35ddSAndrew Turner { 131*a29b35ddSAndrew Turner 132*a29b35ddSAndrew Turner } 133*a29b35ddSAndrew Turner 134*a29b35ddSAndrew Turner static void 135*a29b35ddSAndrew Turner uart_cnungrab(struct consdev *cp) 136*a29b35ddSAndrew Turner { 137*a29b35ddSAndrew Turner 138*a29b35ddSAndrew Turner } 139*a29b35ddSAndrew Turner 140*a29b35ddSAndrew Turner 141*a29b35ddSAndrew Turner static void 142*a29b35ddSAndrew Turner uart_cnprobe(struct consdev *cp) 143*a29b35ddSAndrew Turner { 144*a29b35ddSAndrew Turner 145*a29b35ddSAndrew Turner sprintf(cp->cn_name, "uart"); 146*a29b35ddSAndrew Turner cp->cn_pri = CN_NORMAL; 147*a29b35ddSAndrew Turner } 148*a29b35ddSAndrew Turner 149*a29b35ddSAndrew Turner static void 150*a29b35ddSAndrew Turner uart_cninit(struct consdev *cp) 151*a29b35ddSAndrew Turner { 152*a29b35ddSAndrew Turner 153*a29b35ddSAndrew Turner /* Init fifo trigger levels to 32 bytes, refclock div to 2. */ 154*a29b35ddSAndrew Turner ub_setreg(IMX_UFCR, 0x00004210); 155*a29b35ddSAndrew Turner } 156*a29b35ddSAndrew Turner 157*a29b35ddSAndrew Turner static void 158*a29b35ddSAndrew Turner uart_cnputc(struct consdev *cp, int c) 159*a29b35ddSAndrew Turner { 160*a29b35ddSAndrew Turner 161*a29b35ddSAndrew Turner ub_putc(c); 162*a29b35ddSAndrew Turner } 163*a29b35ddSAndrew Turner 164*a29b35ddSAndrew Turner static int 165*a29b35ddSAndrew Turner uart_cngetc(struct consdev * cp) 166*a29b35ddSAndrew Turner { 167*a29b35ddSAndrew Turner 168*a29b35ddSAndrew Turner return ub_getc(); 169*a29b35ddSAndrew Turner } 170*a29b35ddSAndrew Turner 171*a29b35ddSAndrew Turner static void 172*a29b35ddSAndrew Turner uart_cnterm(struct consdev * cp) 173*a29b35ddSAndrew Turner { 174*a29b35ddSAndrew Turner 175*a29b35ddSAndrew Turner } 176*a29b35ddSAndrew Turner 177*a29b35ddSAndrew Turner CONSOLE_DRIVER(uart); 178