coreboot/src/lib/uart8250mem.c
<<
>>
Prefs
   1/*
   2 * This file is part of the coreboot project.
   3 *
   4 * Copyright (C) 2003 Eric Biederman
   5 * Copyright (C) 2006-2010 coresystems GmbH
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; version 2 of the License.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  19 */
  20
  21#include <arch/io.h>
  22#include <uart8250.h>
  23#include <pc80/mc146818rtc.h>
  24#if CONFIG_USE_OPTION_TABLE
  25#include "option_table.h"
  26#endif
  27#if !defined(__SMM__) && !defined(__PRE_RAM__)
  28#include <device/device.h>
  29#endif
  30
  31/* Should support 8250, 16450, 16550, 16550A type UARTs */
  32
  33static inline int uart8250_mem_can_tx_byte(unsigned base_port)
  34{
  35        return read8(base_port + UART_LSR) & UART_MSR_DSR;
  36}
  37
  38static inline void uart8250_mem_wait_to_tx_byte(unsigned base_port)
  39{
  40        while(!uart8250_mem_can_tx_byte(base_port))
  41                ;
  42}
  43
  44static inline void uart8250_mem_wait_until_sent(unsigned base_port)
  45{
  46        while(!(read8(base_port + UART_LSR) & UART_LSR_TEMT))
  47                ;
  48}
  49
  50void uart8250_mem_tx_byte(unsigned base_port, unsigned char data)
  51{
  52        uart8250_mem_wait_to_tx_byte(base_port);
  53        write8(base_port + UART_TBR, data);
  54        /* Make certain the data clears the FIFOs */
  55        uart8250_mem_wait_until_sent(base_port);
  56}
  57
  58int uart8250_mem_can_rx_byte(unsigned base_port)
  59{
  60        return read8(base_port + UART_LSR) & UART_LSR_DR;
  61}
  62
  63unsigned char uart8250_mem_rx_byte(unsigned base_port)
  64{
  65        while(!uart8250_mem_can_rx_byte(base_port))
  66                ;
  67        return read8(base_port + UART_RBR);
  68}
  69
  70void uart8250_mem_init(unsigned base_port, unsigned divisor)
  71{
  72        /* Disable interrupts */
  73        write8(base_port + UART_IER, 0x0);
  74        /* Enable FIFOs */
  75        write8(base_port + UART_FCR, UART_FCR_FIFO_EN);
  76
  77        /* Assert DTR and RTS so the other end is happy */
  78        write8(base_port + UART_MCR, UART_MCR_DTR | UART_MCR_RTS);
  79
  80        /* DLAB on */
  81        write8(base_port + UART_LCR, UART_LCR_DLAB | CONFIG_TTYS0_LCS);
  82
  83        /* Set Baud Rate Divisor. 12 ==> 115200 Baud */
  84        write8(base_port + UART_DLL, divisor & 0xFF);
  85        write8(base_port + UART_DLM, (divisor >> 8) & 0xFF);
  86
  87        /* Set to 3 for 8N1 */
  88        write8(base_port + UART_LCR, CONFIG_TTYS0_LCS);
  89}
  90
  91u32 uart_mem_init(void)
  92{
  93        unsigned uart_baud = CONFIG_TTYS0_BAUD;
  94        u32 uart_bar = 0;
  95        unsigned div;
  96
  97        /* find out the correct baud rate */
  98#if !defined(__SMM__) && CONFIG_USE_OPTION_TABLE
  99        static const unsigned baud[8] = { 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200 };
 100        unsigned b_index = 0;
 101#if defined(__PRE_RAM__)
 102        b_index = read_option(CMOS_VSTART_baud_rate, CMOS_VLEN_baud_rate, 0);
 103        b_index &= 7;
 104        uart_baud = baud[b_index];
 105#else
 106        if (get_option(&b_index, "baud_rate") == 0) {
 107                uart_baud = baud[b_index];
 108        }
 109#endif
 110#endif
 111
 112        /* Now find the UART base address and calculate the divisor */
 113#if CONFIG_DRIVERS_OXFORD_OXPCIE
 114
 115#if defined(MORE_TESTING) && !defined(__SMM__) && !defined(__PRE_RAM__)
 116        device_t dev = dev_find_device(0x1415, 0xc158, NULL);
 117
 118        if (dev) {
 119                struct resource *res = find_resource(dev, 0x10);
 120        
 121                if (res) {
 122                        uart_bar = res->base + 0x1000; // for 1st UART
 123                        // uart_bar = res->base + 0x2000; // for 2nd UART
 124                }
 125        }
 126
 127        if (!uart_bar)
 128#endif
 129        uart_bar = CONFIG_OXFORD_OXPCIE_BASE_ADDRESS + 0x1000; // 1st UART
 130        // uart_bar = CONFIG_OXFORD_OXPCIE_BASE_ADDRESS + 0x2000; // 2nd UART
 131        
 132        div = 4000000 / uart_baud;
 133#endif
 134
 135        if (uart_bar)
 136                uart8250_mem_init(uart_bar, div);
 137
 138        return uart_bar;
 139}
 140
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.