blob: 13adabd1126767951f46c1834a88a2195050a29f [file] [log] [blame]
wdenka21ad7b2005-05-19 22:39:42 +00001/*
2 * serial.c -- KS8695 serial driver
3 *
4 * (C) Copyright 2004, Greg Ungerer <greg.ungerer@opengear.com>
5 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02006 * SPDX-License-Identifier: GPL-2.0+
wdenka21ad7b2005-05-19 22:39:42 +00007 */
8
9#include <common.h>
10#include <asm/arch/platform.h>
Marek Vasut5ee46562012-09-14 22:35:43 +020011#include <serial.h>
12#include <linux/compiler.h>
wdenka21ad7b2005-05-19 22:39:42 +000013
14#ifndef CONFIG_SERIAL1
15#error "Bad: you didn't configure serial ..."
16#endif
17
Wolfgang Denk6405a152006-03-31 18:32:53 +020018DECLARE_GLOBAL_DATA_PTR;
19
wdenka21ad7b2005-05-19 22:39:42 +000020/*
21 * Define the UART hardware register access structure.
22 */
23struct ks8695uart {
24 unsigned int RX; /* 0x00 - Receive data (r) */
25 unsigned int TX; /* 0x04 - Transmit data (w) */
26 unsigned int FCR; /* 0x08 - Fifo Control (r/w) */
27 unsigned int LCR; /* 0x0c - Line Control (r/w) */
28 unsigned int MCR; /* 0x10 - Modem Control (r/w) */
29 unsigned int LSR; /* 0x14 - Line Status (r/w) */
30 unsigned int MSR; /* 0x18 - Modem Status (r/w) */
31 unsigned int BD; /* 0x1c - Baud Rate (r/w) */
32 unsigned int SR; /* 0x20 - Status (r/w) */
33};
34
35#define KS8695_UART_ADDR ((void *) (KS8695_IO_BASE + KS8695_UART_RX_BUFFER))
36#define KS8695_UART_CLK 25000000
37
38
39/*
40 * Under some circumstances we want to be "quiet" and not issue any
41 * serial output - though we want u-boot to otherwise work and behave
42 * the same. By default be noisy.
43 */
44int serial_console = 1;
45
46
Marek Vasut5ee46562012-09-14 22:35:43 +020047static void ks8695_serial_setbrg(void)
wdenka21ad7b2005-05-19 22:39:42 +000048{
wdenka21ad7b2005-05-19 22:39:42 +000049 volatile struct ks8695uart *uartp = KS8695_UART_ADDR;
50
51 /* Set to global baud rate and 8 data bits, no parity, 1 stop bit*/
52 uartp->BD = KS8695_UART_CLK / gd->baudrate;
53 uartp->LCR = KS8695_UART_LINEC_WLEN8;
54}
55
Marek Vasut5ee46562012-09-14 22:35:43 +020056static int ks8695_serial_init(void)
wdenka21ad7b2005-05-19 22:39:42 +000057{
58 serial_console = 1;
59 serial_setbrg();
60 return 0;
61}
62
Marek Vasut5ee46562012-09-14 22:35:43 +020063static void ks8695_serial_raw_putc(const char c)
wdenka21ad7b2005-05-19 22:39:42 +000064{
65 volatile struct ks8695uart *uartp = KS8695_UART_ADDR;
66 int i;
67
68 for (i = 0; (i < 0x100000); i++) {
69 if (uartp->LSR & KS8695_UART_LINES_TXFE)
70 break;
71 }
72
73 uartp->TX = c;
74}
75
Marek Vasut5ee46562012-09-14 22:35:43 +020076static void ks8695_serial_putc(const char c)
wdenka21ad7b2005-05-19 22:39:42 +000077{
78 if (serial_console) {
Marek Vasut5ee46562012-09-14 22:35:43 +020079 ks8695_serial_raw_putc(c);
wdenka21ad7b2005-05-19 22:39:42 +000080 if (c == '\n')
Marek Vasut5ee46562012-09-14 22:35:43 +020081 ks8695_serial_raw_putc('\r');
wdenka21ad7b2005-05-19 22:39:42 +000082 }
83}
84
Marek Vasut5ee46562012-09-14 22:35:43 +020085static int ks8695_serial_tstc(void)
wdenka21ad7b2005-05-19 22:39:42 +000086{
87 volatile struct ks8695uart *uartp = KS8695_UART_ADDR;
88 if (serial_console)
89 return ((uartp->LSR & KS8695_UART_LINES_RXFE) ? 1 : 0);
90 return 0;
91}
92
Marek Vasut5ee46562012-09-14 22:35:43 +020093static int ks8695_serial_getc(void)
wdenka21ad7b2005-05-19 22:39:42 +000094{
95 volatile struct ks8695uart *uartp = KS8695_UART_ADDR;
96
97 while ((uartp->LSR & KS8695_UART_LINES_RXFE) == 0)
98 ;
99 return (uartp->RX);
100}
Marek Vasut5ee46562012-09-14 22:35:43 +0200101
Marek Vasut5ee46562012-09-14 22:35:43 +0200102static struct serial_device ks8695_serial_drv = {
103 .name = "ks8695_serial",
104 .start = ks8695_serial_init,
105 .stop = NULL,
106 .setbrg = ks8695_serial_setbrg,
107 .putc = ks8695_serial_putc,
Marek Vasutd9c64492012-10-06 14:07:02 +0000108 .puts = default_serial_puts,
Marek Vasut5ee46562012-09-14 22:35:43 +0200109 .getc = ks8695_serial_getc,
110 .tstc = ks8695_serial_tstc,
111};
112
113void ks8695_serial_initialize(void)
114{
115 serial_register(&ks8695_serial_drv);
116}
117
118__weak struct serial_device *default_serial_console(void)
119{
120 return &ks8695_serial_drv;
121}