1245450Sganbold/*- 2263711Sganbold * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@freebsd.org> 3245450Sganbold * All rights reserved. 4245450Sganbold * 5245450Sganbold * Redistribution and use in source and binary forms, with or without 6245450Sganbold * modification, are permitted provided that the following conditions 7245450Sganbold * are met: 8245453Sganbold * 1. Redistributions of source code must retain the above copyright 9245453Sganbold * notice, this list of conditions and the following disclaimer. 10245453Sganbold * 2. Redistributions in binary form must reproduce the above copyright 11245453Sganbold * notice, this list of conditions and the following disclaimer in the 12245453Sganbold * documentation and/or other materials provided with the distribution. 13245450Sganbold * 14245450Sganbold * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15245450Sganbold * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16245450Sganbold * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17245454Sganbold * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18245450Sganbold * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19245450Sganbold * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20245450Sganbold * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21245450Sganbold * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22245450Sganbold * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23245450Sganbold * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24245450Sganbold * SUCH DAMAGE. 25245450Sganbold */ 26245450Sganbold 27245450Sganbold/* Simple UART console driver for Allwinner A10 */ 28245450Sganbold 29245450Sganbold#include <sys/cdefs.h> 30245450Sganbold__FBSDID("$FreeBSD: releng/11.0/sys/arm/allwinner/console.c 263711 2014-03-25 08:31:47Z ganbold $"); 31245450Sganbold 32245450Sganbold#include <sys/types.h> 33245450Sganbold#include <sys/param.h> 34245450Sganbold#include <sys/systm.h> 35245450Sganbold#include <sys/cons.h> 36245450Sganbold#include <sys/consio.h> 37245450Sganbold#include <sys/kernel.h> 38245450Sganbold 39245450Sganbold#ifndef A10_UART_BASE 40245450Sganbold#define A10_UART_BASE 0xe1c28000 /* UART0 */ 41245450Sganbold#endif 42245450Sganbold 43245500Sganbold#define REG_SHIFT 2 44245450Sganbold 45245500Sganbold#define UART_DLL 0 /* Out: Divisor Latch Low */ 46245500Sganbold#define UART_DLM 1 /* Out: Divisor Latch High */ 47245500Sganbold#define UART_FCR 2 /* Out: FIFO Control Register */ 48245500Sganbold#define UART_LCR 3 /* Out: Line Control Register */ 49245500Sganbold#define UART_MCR 4 /* Out: Modem Control Register */ 50245500Sganbold#define UART_LSR 5 /* In: Line Status Register */ 51245500Sganbold#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ 52245500Sganbold#define UART_LSR_DR 0x01 /* Receiver data ready */ 53245500Sganbold#define UART_MSR 6 /* In: Modem Status Register */ 54245500Sganbold#define UART_SCR 7 /* I/O: Scratch Register */ 55245450Sganbold 56245500Sganboldstatic uint32_t 57245500Sganbolduart_getreg(uint32_t *bas) 58245450Sganbold{ 59245500Sganbold return *((volatile uint32_t *)(bas)) & 0xff; 60245450Sganbold} 61245450Sganbold 62245450Sganboldstatic void 63245500Sganbolduart_setreg(uint32_t *bas, uint32_t val) 64245450Sganbold{ 65245500Sganbold *((volatile uint32_t *)(bas)) = val; 66245450Sganbold} 67245450Sganbold 68245450Sganboldstatic int 69245450Sganboldub_getc(void) 70245450Sganbold{ 71245500Sganbold while ((uart_getreg((uint32_t *)(A10_UART_BASE + 72245500Sganbold (UART_LSR << REG_SHIFT))) & UART_LSR_DR) == 0); 73245450Sganbold __asm __volatile("nop"); 74245450Sganbold 75245500Sganbold return (uart_getreg((uint32_t *)A10_UART_BASE) & 0xff); 76245450Sganbold} 77245450Sganbold 78245450Sganboldstatic void 79245450Sganboldub_putc(unsigned char c) 80245450Sganbold{ 81245450Sganbold if (c == '\n') 82245450Sganbold ub_putc('\r'); 83245450Sganbold 84245500Sganbold while ((uart_getreg((uint32_t *)(A10_UART_BASE + 85245500Sganbold (UART_LSR << REG_SHIFT))) & UART_LSR_THRE) == 0) 86245450Sganbold __asm __volatile("nop"); 87245450Sganbold 88245500Sganbold uart_setreg((uint32_t *)A10_UART_BASE, c); 89245450Sganbold} 90245450Sganbold 91245450Sganboldstatic cn_probe_t uart_cnprobe; 92245450Sganboldstatic cn_init_t uart_cninit; 93245450Sganboldstatic cn_term_t uart_cnterm; 94245450Sganboldstatic cn_getc_t uart_cngetc; 95245450Sganboldstatic cn_putc_t uart_cnputc; 96245450Sganboldstatic cn_grab_t uart_cngrab; 97245450Sganboldstatic cn_ungrab_t uart_cnungrab; 98245450Sganbold 99245450Sganboldstatic void 100245450Sganbolduart_cngrab(struct consdev *cp) 101245450Sganbold{ 102245450Sganbold} 103245450Sganbold 104245450Sganboldstatic void 105245450Sganbolduart_cnungrab(struct consdev *cp) 106245450Sganbold{ 107245450Sganbold} 108245450Sganbold 109245450Sganbold 110245450Sganboldstatic void 111245450Sganbolduart_cnprobe(struct consdev *cp) 112245450Sganbold{ 113245450Sganbold sprintf(cp->cn_name, "uart"); 114245450Sganbold cp->cn_pri = CN_NORMAL; 115245450Sganbold} 116245450Sganbold 117245450Sganboldstatic void 118245450Sganbolduart_cninit(struct consdev *cp) 119245450Sganbold{ 120245500Sganbold uart_setreg((uint32_t *)(A10_UART_BASE + 121245500Sganbold (UART_FCR << REG_SHIFT)), 0x06); 122245450Sganbold} 123245450Sganbold 124245450Sganboldvoid 125245450Sganbolduart_cnputc(struct consdev *cp, int c) 126245450Sganbold{ 127245450Sganbold ub_putc(c); 128245450Sganbold} 129245450Sganbold 130245450Sganboldint 131245450Sganbolduart_cngetc(struct consdev * cp) 132245450Sganbold{ 133245450Sganbold return ub_getc(); 134245450Sganbold} 135245450Sganbold 136245450Sganboldstatic void 137245450Sganbolduart_cnterm(struct consdev * cp) 138245450Sganbold{ 139245450Sganbold} 140245450Sganbold 141245450SganboldCONSOLE_DRIVER(uart); 142245450Sganbold 143