blob: f68c8d0f0436a3ee1dce54460d799501685bb05d [file] [log] [blame]
wdenkef3386f2004-10-10 21:27:30 +00001/*
Thomas Choub102c512014-08-25 17:43:12 +08002 * Altera NiosII YANU serial interface by Imagos
3 * please see http://www.opencores.org/project,yanu for
4 * information/downloads
5 *
Renato Andreola9f64dcb2010-03-16 16:01:29 -04006 * Copyright 2010, Renato Andreola <renato.andreola@imagos.it>
7 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02008 * SPDX-License-Identifier: GPL-2.0+
wdenkef3386f2004-10-10 21:27:30 +00009 */
10
wdenkef3386f2004-10-10 21:27:30 +000011#include <common.h>
12#include <watchdog.h>
Scott McNutta5721a32006-06-08 11:59:57 -040013#include <asm/io.h>
Axel Lin0bdf0002014-01-16 15:01:49 +080014#include <serial.h>
wdenkef3386f2004-10-10 21:27:30 +000015
Wolfgang Denk6405a152006-03-31 18:32:53 +020016DECLARE_GLOBAL_DATA_PTR;
17
Renato Andreola9f64dcb2010-03-16 16:01:29 -040018/*-----------------------------------------------------------------*/
19/* YANU Imagos serial port */
20/*-----------------------------------------------------------------*/
21
Thomas Choub102c512014-08-25 17:43:12 +080022#define YANU_MAX_PRESCALER_N ((1 << 4) - 1) /* 15 */
23#define YANU_MAX_PRESCALER_M ((1 << 11) -1) /* 2047 */
24#define YANU_FIFO_SIZE (16)
25#define YANU_RXFIFO_SIZE (YANU_FIFO_SIZE)
26#define YANU_TXFIFO_SIZE (YANU_FIFO_SIZE)
27
28#define YANU_RXFIFO_DLY (10*11)
29#define YANU_TXFIFO_THR (10)
30#define YANU_DATA_CHAR_MASK (0xFF)
31
32/* data register */
33#define YANU_DATA_OFFSET (0) /* data register offset */
34
35#define YANU_CONTROL_OFFSET (4) /* control register offset */
36/* interrupt enable */
37#define YANU_CONTROL_IE_RRDY (1<<0) /* ie on received character ready */
38#define YANU_CONTROL_IE_OE (1<<1) /* ie on rx overrun */
39#define YANU_CONTROL_IE_BRK (1<<2) /* ie on break detect */
40#define YANU_CONTROL_IE_FE (1<<3) /* ie on framing error */
41#define YANU_CONTROL_IE_PE (1<<4) /* ie on parity error */
42#define YANU_CONTROL_IE_TRDY (1<<5) /* ie interrupt on tranmitter ready */
43/* control bits */
44#define YANU_CONTROL_BITS_POS (6) /* bits number pos */
45#define YANU_CONTROL_BITS (1<<YANU_CONTROL_BITS_POS) /* number of rx/tx bits per word. 3 bit unsigned integer */
46#define YANU_CONTROL_BITS_N (3) /* ... its bit filed length */
47#define YANU_CONTROL_PARENA (1<<9) /* enable parity bit transmission/reception */
48#define YANU_CONTROL_PAREVEN (1<<10) /* parity even */
49#define YANU_CONTROL_STOPS (1<<11) /* number of stop bits */
50#define YANU_CONTROL_HHENA (1<<12) /* Harware Handshake enable... */
51#define YANU_CONTROL_FORCEBRK (1<<13) /* if set than txd = active (0) */
52/* tuning part */
53#define YANU_CONTROL_RDYDLY (1<<14) /* delay from "first" before setting rrdy (in bit) */
54#define YANU_CONTROL_RDYDLY_N (8) /* ... its bit filed length */
55#define YANU_CONTROL_TXTHR (1<<22) /* tx interrupt threshold: the trdy set if txfifo_chars<= txthr (chars) */
56#define YANU_CONTROL_TXTHR_N (4) /* ... its bit field length */
57
58#define YANU_BAUD_OFFSET (8) /* baud register offset */
59#define YANU_BAUDM (1<<0) /* baud mantissa lsb */
60#define YANU_BAUDM_N (12) /* ...its bit filed length */
61#define YANU_BAUDE (1<<12) /* baud exponent lsb */
62#define YANU_BAUDE_N (4) /* ...its bit field length */
63
64#define YANU_ACTION_OFFSET (12) /* action register... write only */
65#define YANU_ACTION_RRRDY (1<<0) /* reset rrdy */
66#define YANU_ACTION_ROE (1<<1) /* reset oe */
67#define YANU_ACTION_RBRK (1<<2) /* reset brk */
68#define YANU_ACTION_RFE (1<<3) /* reset fe */
69#define YANU_ACTION_RPE (1<<4) /* reset pe */
70#define YANU_ACTION_SRRDY (1<<5) /* set rrdy */
71#define YANU_ACTION_SOE (1<<6) /* set oe */
72#define YANU_ACTION_SBRK (1<<7) /* set brk */
73#define YANU_ACTION_SFE (1<<8) /* set fe */
74#define YANU_ACTION_SPE (1<<9) /* set pe */
75#define YANU_ACTION_RFIFO_PULL (1<<10) /* pull a char from rx fifo we MUST do it before taking a char */
76#define YANU_ACTION_RFIFO_CLEAR (1<<11) /* clear rx fifo */
77#define YANU_ACTION_TFIFO_CLEAR (1<<12) /* clear tx fifo */
78#define YANU_ACTION_RTRDY (1<<13) /* clear trdy */
79#define YANU_ACTION_STRDY (1<<14) /* set trdy */
80
81#define YANU_STATUS_OFFSET (16)
82#define YANU_STATUS_RRDY (1<<0) /* rxrdy flag */
83#define YANU_STATUS_TRDY (1<<1) /* txrdy flag */
84#define YANU_STATUS_OE (1<<2) /* rx overrun error */
85#define YANU_STATUS_BRK (1<<3) /* rx break detect flag */
86#define YANU_STATUS_FE (1<<4) /* rx framing error flag */
87#define YANU_STATUS_PE (1<<5) /* rx parity erro flag */
88#define YANU_RFIFO_CHARS_POS (6)
89#define YANU_RFIFO_CHARS (1<<RFIFO_CHAR_POS) /* number of chars into rx fifo */
90#define YANU_RFIFO_CHARS_N (5) /* ...its bit field length: 32 chars */
91#define YANU_TFIFO_CHARS_POS (11)
92#define YANU_TFIFO_CHARS (1<<TFIFO_CHAR_POS) /* number of chars into tx fifo */
93#define YANU_TFIFO_CHARS_N (5) /* ...its bit field length: 32 chars */
94
95typedef volatile struct {
96 volatile unsigned data;
97 volatile unsigned control; /* control register (RW) 32-bit */
98 volatile unsigned baud; /* baud/prescaler register (RW) 32-bit */
99 volatile unsigned action; /* action register (W) 32-bit */
100 volatile unsigned status; /* status register (R) 32-bit */
101 volatile unsigned magic; /* magic register (R) 32-bit */
102} yanu_uart_t;
103
Renato Andreola9f64dcb2010-03-16 16:01:29 -0400104static yanu_uart_t *uart = (yanu_uart_t *)CONFIG_SYS_NIOS_CONSOLE;
105
Marek Vasutfcb9ef82012-09-13 16:52:38 +0200106static void oc_serial_setbrg(void)
Renato Andreola9f64dcb2010-03-16 16:01:29 -0400107{
108 int n, k;
109 const unsigned max_uns = 0xFFFFFFFF;
110 unsigned best_n, best_m, baud;
Axel Lin4a37b422014-01-16 15:03:52 +0800111 unsigned baudrate;
Renato Andreola9f64dcb2010-03-16 16:01:29 -0400112
Axel Lin4a37b422014-01-16 15:03:52 +0800113#if defined(CONFIG_SYS_NIOS_FIXEDBAUD)
114 /* Everything's already setup for fixed-baud PTF assignment */
115 baudrate = CONFIG_BAUDRATE;
Renato Andreola9f64dcb2010-03-16 16:01:29 -0400116#else
Axel Lin4a37b422014-01-16 15:03:52 +0800117 baudrate = gd->baudrate;
118#endif
Renato Andreola9f64dcb2010-03-16 16:01:29 -0400119 /* compute best N and M couple */
120 best_n = YANU_MAX_PRESCALER_N;
121 for (n = YANU_MAX_PRESCALER_N; n >= 0; n--) {
122 if ((unsigned)CONFIG_SYS_CLK_FREQ / (1 << (n + 4)) >=
Axel Lin4a37b422014-01-16 15:03:52 +0800123 baudrate) {
Renato Andreola9f64dcb2010-03-16 16:01:29 -0400124 best_n = n;
125 break;
126 }
127 }
128 for (k = 0;; k++) {
Axel Lin4a37b422014-01-16 15:03:52 +0800129 if (baudrate <= (max_uns >> (15+n-k)))
Renato Andreola9f64dcb2010-03-16 16:01:29 -0400130 break;
131 }
132 best_m =
Axel Lin4a37b422014-01-16 15:03:52 +0800133 (baudrate * (1 << (15 + n - k))) /
Renato Andreola9f64dcb2010-03-16 16:01:29 -0400134 ((unsigned)CONFIG_SYS_CLK_FREQ >> k);
135
136 baud = best_m + best_n * YANU_BAUDE;
Scott McNutt0fd72d32010-03-21 21:24:43 -0400137 writel(baud, &uart->baud);
Renato Andreola9f64dcb2010-03-16 16:01:29 -0400138
139 return;
140}
141
Marek Vasutfcb9ef82012-09-13 16:52:38 +0200142static int oc_serial_init(void)
Renato Andreola9f64dcb2010-03-16 16:01:29 -0400143{
144 unsigned action,control;
145
146 /* status register cleanup */
147 action = YANU_ACTION_RRRDY |
148 YANU_ACTION_RTRDY |
149 YANU_ACTION_ROE |
150 YANU_ACTION_RBRK |
151 YANU_ACTION_RFE |
152 YANU_ACTION_RPE |
153 YANU_ACTION_RFE | YANU_ACTION_RFIFO_CLEAR | YANU_ACTION_TFIFO_CLEAR;
154
Scott McNutt0fd72d32010-03-21 21:24:43 -0400155 writel(action, &uart->action);
Wolfgang Denkbe2034d2010-05-26 23:51:22 +0200156
157 /*
158 * control register cleanup
159 * no interrupts enabled
160 * one stop bit
161 * hardware flow control disabled
162 * 8 bits
163 */
Renato Andreola9f64dcb2010-03-16 16:01:29 -0400164 control = (0x7 << YANU_CONTROL_BITS_POS);
165 /* enven parity just to be clean */
166 control |= YANU_CONTROL_PAREVEN;
167 /* we set threshold for fifo */
168 control |= YANU_CONTROL_RDYDLY * YANU_RXFIFO_DLY;
169 control |= YANU_CONTROL_TXTHR * YANU_TXFIFO_THR;
170
Scott McNutt0fd72d32010-03-21 21:24:43 -0400171 writel(control, &uart->control);
Renato Andreola9f64dcb2010-03-16 16:01:29 -0400172
173 /* to set baud rate */
174 serial_setbrg();
175
176 return (0);
177}
178
179
180/*-----------------------------------------------------------------------
181 * YANU CONSOLE
182 *---------------------------------------------------------------------*/
Marek Vasutfcb9ef82012-09-13 16:52:38 +0200183static void oc_serial_putc(char c)
Renato Andreola9f64dcb2010-03-16 16:01:29 -0400184{
185 int tx_chars;
186 unsigned status;
187
188 if (c == '\n')
189 serial_putc ('\r');
Wolfgang Denkbe2034d2010-05-26 23:51:22 +0200190
Renato Andreola9f64dcb2010-03-16 16:01:29 -0400191 while (1) {
192 status = readl(&uart->status);
193 tx_chars = (status>>YANU_TFIFO_CHARS_POS)
194 & ((1<<YANU_TFIFO_CHARS_N)-1);
195 if (tx_chars < YANU_TXFIFO_SIZE-1)
196 break;
197 WATCHDOG_RESET ();
198 }
199
Scott McNutt0fd72d32010-03-21 21:24:43 -0400200 writel((unsigned char)c, &uart->data);
Renato Andreola9f64dcb2010-03-16 16:01:29 -0400201}
202
Marek Vasutfcb9ef82012-09-13 16:52:38 +0200203static int oc_serial_tstc(void)
Renato Andreola9f64dcb2010-03-16 16:01:29 -0400204{
205 unsigned status ;
206
207 status = readl(&uart->status);
208 return (((status >> YANU_RFIFO_CHARS_POS) &
209 ((1 << YANU_RFIFO_CHARS_N) - 1)) > 0);
Wolfgang Denkbe2034d2010-05-26 23:51:22 +0200210}
Renato Andreola9f64dcb2010-03-16 16:01:29 -0400211
Axel Lin0bdf0002014-01-16 15:01:49 +0800212static int oc_serial_getc(void)
Renato Andreola9f64dcb2010-03-16 16:01:29 -0400213{
214 while (serial_tstc() == 0)
215 WATCHDOG_RESET ();
Wolfgang Denkbe2034d2010-05-26 23:51:22 +0200216
Renato Andreola9f64dcb2010-03-16 16:01:29 -0400217 /* first we pull the char */
Scott McNutt0fd72d32010-03-21 21:24:43 -0400218 writel(YANU_ACTION_RFIFO_PULL, &uart->action);
Renato Andreola9f64dcb2010-03-16 16:01:29 -0400219
220 return(readl(&uart->data) & YANU_DATA_CHAR_MASK);
221}
Marek Vasutfcb9ef82012-09-13 16:52:38 +0200222
Marek Vasutfcb9ef82012-09-13 16:52:38 +0200223static struct serial_device oc_serial_drv = {
224 .name = "oc_serial",
225 .start = oc_serial_init,
226 .stop = NULL,
227 .setbrg = oc_serial_setbrg,
228 .putc = oc_serial_putc,
Marek Vasutd9c64492012-10-06 14:07:02 +0000229 .puts = default_serial_puts,
Marek Vasutfcb9ef82012-09-13 16:52:38 +0200230 .getc = oc_serial_getc,
231 .tstc = oc_serial_tstc,
232};
233
234void oc_serial_initialize(void)
235{
236 serial_register(&oc_serial_drv);
237}
238
239__weak struct serial_device *default_serial_console(void)
240{
241 return &oc_serial_drv;
242}