summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
authorKyösti Mälkki <kyosti.malkki@gmail.com>2014-02-17 19:37:52 +0200
committerKyösti Mälkki <kyosti.malkki@gmail.com>2014-03-04 15:22:08 +0100
commit3ee1668ab4fbf75b256ac8eef4273b1ea445c998 (patch)
tree59f35a43b85c5da6a0d9d38aba7f391971cbc980 /src/drivers
parentc76b3d6cca4a6135e5a7d7f3c2d9aa5128ef23f0 (diff)
uart8250: Fix and unify baudrate divisor calculation
Divisor is a function of requested baudrate, platform-specific reference clock and amount of oversampling done on the UART reference. Calculate this parameter with divisor rounded to nearest integer. When building without option_table or when there is no entry for baud_rate, CONFIG_TTYS0_BAUD is used for default baudrate. For OxPCIe use of 4 MHz for reference was arbitrary giving correct divisor for 115200 but somewhat inaccurate for lower baudrates. Actual hardware is 62500000 with 16 times oversampling. FIXME: Field for baudrate in lb_tables is still incorrect. Change-Id: I68539738469af780fadd3392263dd9b3d5964d2d Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com> Reviewed-on: http://review.coreboot.org/5229 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/oxford/oxpcie/oxpcie_early.c10
-rw-r--r--src/drivers/uart/Makefile.inc6
-rw-r--r--src/drivers/uart/util.c48
3 files changed, 63 insertions, 1 deletions
diff --git a/src/drivers/oxford/oxpcie/oxpcie_early.c b/src/drivers/oxford/oxpcie/oxpcie_early.c
index d04e9d4df0..4f6f9649f5 100644
--- a/src/drivers/oxford/oxpcie/oxpcie_early.c
+++ b/src/drivers/oxford/oxpcie/oxpcie_early.c
@@ -21,6 +21,7 @@
#include <arch/io.h>
#include <arch/early_variables.h>
#include <delay.h>
+#include <uart.h>
#include <uart8250.h>
#include <device/pci_def.h>
@@ -116,7 +117,14 @@ void oxford_init(void)
/* Now the UART initialization */
u32 uart0_base = CONFIG_OXFORD_OXPCIE_BASE_ADDRESS + 0x1000;
- uart8250_mem_init(uart0_base, (4000000 / CONFIG_TTYS0_BAUD));
+ unsigned int div = uart_baudrate_divisor(default_baudrate(),
+ uart_platform_refclk(), 16);
+ uart8250_mem_init(uart0_base, div);
}
#endif
+
+unsigned int uart_platform_refclk(void)
+{
+ return 62500000;
+}
diff --git a/src/drivers/uart/Makefile.inc b/src/drivers/uart/Makefile.inc
new file mode 100644
index 0000000000..c797d4b44d
--- /dev/null
+++ b/src/drivers/uart/Makefile.inc
@@ -0,0 +1,6 @@
+ifeq ($(CONFIG_CONSOLE_SERIAL),y)
+romstage-y += util.c
+ramstage-y += util.c
+bootblock-y += util.c
+smm-y += util.c
+endif
diff --git a/src/drivers/uart/util.c b/src/drivers/uart/util.c
new file mode 100644
index 0000000000..c577048fb5
--- /dev/null
+++ b/src/drivers/uart/util.c
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <uart.h>
+#if CONFIG_USE_OPTION_TABLE
+#include <pc80/mc146818rtc.h>
+#include "option_table.h"
+#endif
+
+unsigned int default_baudrate(void)
+{
+#if !defined(__SMM__) && CONFIG_USE_OPTION_TABLE
+ static const unsigned baud[8] =
+ { 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200 };
+ unsigned b_index = 0;
+#if defined(__PRE_RAM__)
+ b_index = read_option(baud_rate, 0xff);
+#else
+ if (get_option(&b_index, "baud_rate") != CB_SUCCESS)
+ b_index = 0xff;
+#endif
+ if (b_index < 8)
+ return baud[b_index];
+#endif
+ return CONFIG_TTYS0_BAUD;
+}
+
+/* Calculate divisor. Do not floor but round to nearest integer. */
+unsigned int uart_baudrate_divisor(unsigned int baudrate,
+ unsigned int refclk, unsigned int oversample)
+{
+ return (1 + (2 * refclk) / (baudrate * oversample)) / 2;
+}