Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
  • 3 commits
  • 6 files changed
  • 0 comments
  • 1 contributor
Nov 23, 2011
Michael Walle lm32: update driver for new uart core
Signed-off-by: Michael Walle <michael@walle.cc>
db2002a
Michael Walle milkymist_uart: don't restart tx
Don't start transmission if one is still in progress.

Signed-off-by: Michael Walle <michael@walle.cc>
964d1db
Michael Walle milkymist: new interrupt map
Signed-off-by: Michael Walle <michael@walle.cc>
329e85e
24  arch/lm32/boot/dts/milkymist_one.dts
@@ -23,7 +23,7 @@
23 23
 			device_type = "cpu";
24 24
 			compatible = "lattice,mico32";
25 25
 			reg = <0>;
26  
-			clock-frequency = <83333333>;	/* 83.3333 MHz */
  26
+			clock-frequency = <80000000>;	/* 80 MHz */
27 27
 			i-cache-line-size = <16>;
28 28
 			d-cache-line-size = <16>;
29 29
 			i-cache-size = <4096>;
@@ -75,16 +75,16 @@
75 75
 		uart@0 {
76 76
 			device_type = "serial";
77 77
 			compatible = "milkymist,uart";
78  
-			clock-frequency = <83333333>;
  78
+			clock-frequency = <80000000>;
79 79
 			reg = <0x0 0x1000>;
80  
-			interrupts = <0 1>;
  80
+			interrupts = <0>;
81 81
 			interrupt-parent = <&pic>;
82 82
 		};
83 83
 
84 84
 		sysctl: sysctl@1000 {
85 85
 			compatible = "milkymist,sysctl";
86 86
 			reg = <0x1000 0x1000>;
87  
-			interrupts = <2 3 4>;
  87
+			interrupts = <1 2 3>;
88 88
 			#gpio-cells = <2>;
89 89
 			gpio-controller;
90 90
 			num-gpi = <7>;
@@ -122,21 +122,21 @@
122 122
 		ac97@5000 {
123 123
 			compatible = "milkymist,ac97";
124 124
 			reg = <0x5000 0x1000>;
125  
-			interrupts = <5 6 7 8>;
  125
+			interrupts = <4 5 6 7>;
126 126
 			interrupt-parent = <&pic>;
127 127
 		};
128 128
 
129 129
 		pfpu@6000 {
130 130
 			compatible = "milkymist,pfpu";
131 131
 			reg = <0x6000 0x1000>;
132  
-			interrupts = <9>;
  132
+			interrupts = <8>;
133 133
 			interrupt-parent = <&pic>;
134 134
 		};
135 135
 
136 136
 		tmu@7000 {
137 137
 			compatible = "milkymist,tmu2";
138 138
 			reg = <0x7000 0x1000>;
139  
-			interrupts = <10>;
  139
+			interrupts = <9>;
140 140
 			interrupt-parent = <&pic>;
141 141
 		};
142 142
 
@@ -145,7 +145,7 @@
145 145
 			#size-cells = <0>;
146 146
 			compatible = "milkymist,minimac2";
147 147
 			reg = <0x8000 0x1000>;
148  
-			interrupts = <11 12>;
  148
+			interrupts = <10 11>;
149 149
 			interrupt-parent = <&pic>;
150 150
 
151 151
 			phy0: ethernet-phy@0 {
@@ -159,14 +159,14 @@
159 159
 		video-capture@a000 {
160 160
 			compatible = "milkymist,bt656cap";
161 161
 			reg = <0xa000 0x1000>;
162  
-			interrupts = <13>;
  162
+			interrupts = <12>;
163 163
 			interrupt-parent = <&pic>;
164 164
 		};
165 165
 
166 166
 		midi@b000 {
167 167
 			compatible = "milkymist,midi";
168 168
 			reg = <0xb000 0x1000>;
169  
-			interrupts = <14 15>;
  169
+			interrupts = <13>;
170 170
 			interrupt-parent = <&pic>;
171 171
 		};
172 172
 
@@ -178,14 +178,14 @@
178 178
 		ir-receiver@e000 {
179 179
 			compatible = "milkymist,rc5";
180 180
 			reg = <0xe000 0x1000>;
181  
-			interrupts = <16>;
  181
+			interrupts = <14>;
182 182
 			interrupt-parent = <&pic>;
183 183
 		};
184 184
 
185 185
 		usb-ctrl@f000 {
186 186
 			compatible = "milkymist,softusb";
187 187
 			reg = <0xf000 0x1000>;
188  
-			interrupts = <17>;
  188
+			interrupts = <15>;
189 189
 			interrupt-parent = <&pic>;
190 190
 		};
191 191
 	};
36  arch/lm32/include/asm/hw/interrupts.h
@@ -19,24 +19,22 @@
19 19
 #define __HW_INTERRUPTS_H
20 20
 
21 21
 #define IRQ_UARTRX		(0)
22  
-#define IRQ_UARTTX		(1)
23  
-#define IRQ_GPIO		(2)
24  
-#define IRQ_TIMER0		(3)
25  
-#define IRQ_TIMER1		(4)
26  
-#define IRQ_AC97CRREQUEST	(5)
27  
-#define IRQ_AC97CRREPLY		(6)
28  
-#define IRQ_AC97DMAR		(7)
29  
-#define IRQ_AC97DMAW		(8)
30  
-#define IRQ_PFPU		(9)
31  
-#define IRQ_TMU			(10)
32  
-#define IRQ_ETHRX		(11)
33  
-#define IRQ_ETHTX		(12)
34  
-#define IRQ_VIDEOIN		(13)
35  
-#define IRQ_MIDIRX		(14)
36  
-#define IRQ_MIDITX		(15)
37  
-#define IRQ_IR			(16)
38  
-#define IRQ_USB			(17)
39  
-#define	IRQ_PS2KEYBOARD		(14)
40  
-#define	IRQ_PS2MOUSE		(15)
  22
+#define IRQ_GPIO		(1)
  23
+#define IRQ_TIMER0		(2)
  24
+#define IRQ_TIMER1		(3)
  25
+#define IRQ_AC97CRREQUEST	(4)
  26
+#define IRQ_AC97CRREPLY		(5)
  27
+#define IRQ_AC97DMAR		(6)
  28
+#define IRQ_AC97DMAW		(7)
  29
+#define IRQ_PFPU		(8)
  30
+#define IRQ_TMU			(9)
  31
+#define IRQ_ETHRX		(10)
  32
+#define IRQ_ETHTX		(11)
  33
+#define IRQ_VIDEOIN		(12)
  34
+#define IRQ_MIDIRX		(13)
  35
+#define IRQ_IR			(14)
  36
+#define IRQ_USB			(15)
  37
+#define	IRQ_PS2KEYBOARD		(16)
  38
+#define	IRQ_PS2MOUSE		(17)
41 39
 
42 40
 #endif /* __HW_INTERRUPTS_H */
21  arch/lm32/platforms/milkymist/early_printk.c
@@ -35,20 +35,27 @@
35 35
 #include <linux/string.h>
36 36
 #include <asm/irq.h>
37 37
 #include <linux/io.h>
38  
-#include <asm/hw/milkymist.h>
  38
+
  39
+#define UART_RXTX     (void*)0xe0000000
  40
+#define UART_DIVISOR  (void*)0xe0000004
  41
+#define UART_STAT     (void*)0xe0000008
  42
+#define UART_CTRL     (void*)0xe000000c
  43
+#define UART_DEBUG    (void*)0xe000000c
  44
+
  45
+#define UART_STAT_THRE   (1<<0)
  46
+#define UART_STAT_RX_EVT (1<<1)
  47
+#define UART_STAT_TX_EVT (1<<2)
39 48
 
40 49
 static void __init early_console_putc(char c)
41 50
 {
42 51
 	unsigned int timeout = 1000;
43  
-	uint32_t pending;
  52
+	uint32_t stat;
44 53
 
45  
-	iowrite32be(c, CSR_UART_RXTX);
  54
+	iowrite32be(c, UART_RXTX);
46 55
 
47 56
 	do {
48  
-		pending = lm32_irq_pending();
49  
-	} while (pending & BIT(IRQ_UARTTX) && --timeout);
50  
-
51  
-	lm32_irq_ack(IRQ_UARTTX);
  57
+		stat = ioread32be(UART_STAT);
  58
+	} while (!(stat & UART_STAT_THRE) && --timeout);
52 59
 }
53 60
 
54 61
 static void __init early_console_write(struct console *con, const char *s,
5  drivers/tty/serial/Kconfig
@@ -1518,6 +1518,11 @@ config SERIAL_MILKYMIST
1518 1518
 	help
1519 1519
 	  Enable Milkymist UART driver.
1520 1520
 
  1521
+config SERIAL_MILKYMIST_NR_UARTS
  1522
+	int "Maximum number of milkymist serial ports"
  1523
+	depends on SERIAL_MILKYMIST
  1524
+	default "1"
  1525
+
1521 1526
 config SERIAL_MILKYMIST_CONSOLE
1522 1527
 	bool "Enable Milkymist UART driver as system console"
1523 1528
 	depends on SERIAL_MILKYMIST
642  drivers/tty/serial/milkymist_uart.c
... ...
@@ -1,6 +1,10 @@
1 1
 /*
2  
- * (C) Copyright 2009 Sebastien Bourdeauducq, Takeshi Matsuya
3  
- * (C) Copyright 2007 Theobroma Systems <www.theobroma-systems.com>
  2
+ * Copyright (C) 2011 Michael Walle <michael@walle.cc>
  3
+ * Copyright (C) 2009 Sebastien Bourdeauducq, Takeshi Matsuya
  4
+ * Copyright (C) 2006 Peter Korsgaard <jacmet@sunsite.dk>
  5
+ * Copyright (C) 2007 Secret Lab Technologies Ltd.
  6
+ *
  7
+ * based on uartlite.c
4 8
  *
5 9
  * See file CREDITS for list of people who contributed to this
6 10
  * project.
@@ -32,468 +36,490 @@
32 36
 #include <linux/delay.h>
33 37
 #include <linux/slab.h>
34 38
 #include <linux/serial_core.h>
35  
-#include <linux/platform_device.h>
36 39
 #include <asm/io.h>
37 40
 #include <asm/irq.h>
38 41
 #include <asm/setup.h>
39  
-#include <asm/hw/milkymist.h>
40  
-
41  
-#define MILKYMISTUART_DRIVERNAME "milkymist_uart"
42  
-#define MILKYMISTUART_DEVICENAME "ttyS"
43  
-#define MILKYMISTUART_MAJOR TTY_MAJOR
44  
-#define MILKYMISTUART_MINOR 64
45  
-
46  
-static volatile int tx_cts;
47  
-static bool milkymist_uart_irqs_enabled;
48  
-
49  
-/* these two will be initialized by milkymistuart_init */
50  
-static struct uart_port milkymistuart_ports[1];
51  
-
52  
-static struct uart_port* __devinit milkymistuart_init_port(void);
53  
-
54  
-static unsigned int milkymistuart_tx_empty(struct uart_port *port);
55  
-static void milkymistuart_set_mctrl(struct uart_port *port, unsigned int mctrl);
56  
-static unsigned int milkymistuart_get_mctrl(struct uart_port *port);
57  
-static void milkymistuart_start_tx(struct uart_port *port);
58  
-static void milkymistuart_stop_tx(struct uart_port *port);
59  
-static void milkymistuart_stop_rx(struct uart_port *port);
60  
-static void milkymistuart_enable_ms(struct uart_port *port);
61  
-static void milkymistuart_break_ctl(struct uart_port *port, int break_state);
62  
-static int milkymistuart_startup(struct uart_port *port);
63  
-static void milkymistuart_shutdown(struct uart_port *port);
64  
-static void milkymistuart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old);
65  
-static const char *milkymistuart_type(struct uart_port *port);
66  
-static void milkymistuart_release_port(struct uart_port *port);
67  
-static int milkymistuart_request_port(struct uart_port *port);
68  
-static void milkymistuart_config_port(struct uart_port *port, int flags);
69  
-static int milkymistuart_verify_port(struct uart_port *port, struct serial_struct *ser);
70  
-
71  
-static inline void milkymistuart_set_baud_rate(struct uart_port *port, unsigned long baud);
72  
-static irqreturn_t milkymistuart_irq_rx(int irq, void* portarg);
73  
-static irqreturn_t milkymistuart_irq_tx(int irq, void* portarg);
74  
-
75  
-static struct uart_ops milkymistuart_pops = {
76  
-	.tx_empty	= milkymistuart_tx_empty,
77  
-	.set_mctrl	= milkymistuart_set_mctrl,
78  
-	.get_mctrl	= milkymistuart_get_mctrl,
79  
-	.stop_tx	= milkymistuart_stop_tx,
80  
-	.start_tx	= milkymistuart_start_tx,
81  
-	.stop_rx	= milkymistuart_stop_rx,
82  
-	.enable_ms	= milkymistuart_enable_ms,
83  
-	.break_ctl	= milkymistuart_break_ctl,
84  
-	.startup	= milkymistuart_startup,
85  
-	.shutdown	= milkymistuart_shutdown,
86  
-	.set_termios	= milkymistuart_set_termios,
87  
-	.type		= milkymistuart_type,
88  
-	.release_port	= milkymistuart_release_port,
89  
-	.request_port	= milkymistuart_request_port,
90  
-	.config_port	= milkymistuart_config_port,
91  
-	.verify_port	= milkymistuart_verify_port
92  
-};
  42
+#include <linux/of_device.h>
  43
+#include <linux/of_address.h>
  44
+#include <linux/of_irq.h>
93 45
 
94  
-static inline void milkymistuart_set_baud_rate(struct uart_port *port, unsigned long baud)
95  
-{
96  
-	// TODO: use the board configuration option to get the frequency
97  
-	iowrite32be((unsigned long)CONFIG_CPU_CLOCK/baud/16, CSR_UART_DIVISOR);
98  
-}
  46
+#define MILKYMIST_UART_MAJOR TTY_MAJOR
  47
+#define MILKYMIST_UART_MINOR 64
  48
+
  49
+#define MILKYMIST_NR_UARTS CONFIG_SERIAL_MILKYMIST_NR_UARTS
  50
+
  51
+#define UART_RXTX  0x00
  52
+#define UART_DIV   0x04
  53
+#define UART_STAT  0x08
  54
+#define UART_CTRL  0x0c
  55
+#define UART_DEBUG 0x10
  56
+
  57
+#define UART_STAT_THRE    0x01
  58
+#define UART_STAT_RX_EVT  0x02
  59
+#define UART_STAT_TX_EVT  0x04
  60
+
  61
+#define UART_CTRL_RX_INT  0x01
  62
+#define UART_CTRL_TX_INT  0x02
  63
+#define UART_CTRL_THRU    0x04
  64
+
  65
+#define UART_DEBUG_BREAK  0x01
99 66
 
100  
-static void milkymistuart_tx_next_char(struct uart_port* port)
  67
+static struct uart_port milkymist_uart_ports[MILKYMIST_NR_UARTS];
  68
+
  69
+static void milkymist_uart_tx_char(struct uart_port *port)
101 70
 {
102  
-	struct circ_buf *xmit = &(port->state->xmit);
  71
+	struct circ_buf *xmit = &port->state->xmit;
103 72
 
104 73
 	if (port->x_char) {
105  
-		/* send xon/xoff character */
106  
-		tx_cts = 0;
107  
-		iowrite32be(port->x_char, CSR_UART_RXTX);
  74
+		iowrite32be(port->x_char, port->membase + UART_RXTX);
108 75
 		port->x_char = 0;
109 76
 		port->icount.tx++;
110 77
 		return;
111 78
 	}
112 79
 
113  
-	/* stop transmitting if buffer empty */
114  
-	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
115  
-		tx_cts = 1;
  80
+	if (uart_circ_empty(xmit) || uart_tx_stopped(port))
116 81
 		return;
117  
-	}
118 82
 
119  
-	/* send next character */
120  
-	tx_cts = 0;
121  
-	iowrite32be(xmit->buf[xmit->tail], CSR_UART_RXTX);
122  
-	xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
  83
+	iowrite32be(xmit->buf[xmit->tail], port->membase + UART_RXTX);
  84
+	xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1);
123 85
 	port->icount.tx++;
124 86
 
125 87
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
126 88
 		uart_write_wakeup(port);
127  
-#if 0
128  
-while(!(lm32_irq_pending() & (1 << IRQ_UARTTX)));
129  
-#endif
130 89
 }
131 90
 
132  
-static void milkymistuart_rx_next_char(struct uart_port* port)
  91
+static void milkymist_uart_rx_char(struct uart_port *port)
133 92
 {
134 93
 	struct tty_struct *tty = port->state->port.tty;
135 94
 	unsigned char ch;
136 95
 
137  
-	ch = ioread32be(CSR_UART_RXTX) & 0xFF;
  96
+	ch = ioread32be(port->membase + UART_RXTX) & 0xff;
138 97
 	port->icount.rx++;
139 98
 
140 99
 	if (uart_handle_sysrq_char(port, ch))
141 100
 		goto ignore_char;
142 101
 
143  
-	tty_insert_flip_char(tty, ch, TTY_NORMAL);
  102
+	uart_insert_char(port, 0, 0, ch, TTY_NORMAL);
144 103
 
145 104
 ignore_char:
146 105
 	tty_flip_buffer_push(tty);
147 106
 }
148 107
 
149  
-static irqreturn_t milkymistuart_irq_rx(int irq, void* portarg)
  108
+static irqreturn_t milkymist_uart_isr(int irq, void *data)
150 109
 {
151  
-	struct uart_port* port = (struct uart_port*)portarg;
  110
+	struct uart_port *port = data;
  111
+	u8 stat;
  112
+
  113
+	spin_lock(&port->lock);
  114
+
  115
+	/* read and ack events */
  116
+	stat = ioread32be(port->membase + UART_STAT) & 0xff;
  117
+	iowrite32be(stat, port->membase + UART_STAT);
  118
+
  119
+	if (stat & UART_STAT_RX_EVT)
  120
+		milkymist_uart_rx_char(port);
  121
+	if (stat & UART_STAT_TX_EVT)
  122
+		milkymist_uart_tx_char(port);
  123
+
  124
+	spin_unlock(&port->lock);
152 125
 
153  
-	milkymistuart_rx_next_char(port);
154  
-	
155 126
 	return IRQ_HANDLED;
156 127
 }
157 128
 
158  
-static irqreturn_t milkymistuart_irq_tx(int irq, void* portarg)
  129
+static void milkymist_uart_start_tx(struct uart_port *port)
159 130
 {
160  
-	struct uart_port* port = (struct uart_port*)portarg;
  131
+	u8 stat;
  132
+	stat = ioread32be(port->membase + UART_STAT) & 0xff;
161 133
 
162  
-	milkymistuart_tx_next_char(port);
  134
+	/* transmission is still in progress */
  135
+	if (!(stat & UART_STAT_THRE))
  136
+		return;
163 137
 
164  
-	return IRQ_HANDLED;
  138
+	milkymist_uart_tx_char(port);
165 139
 }
166 140
 
167  
-static unsigned int milkymistuart_tx_empty(struct uart_port *port)
  141
+static unsigned int milkymist_uart_tx_empty(struct uart_port *port)
168 142
 {
  143
+	/* XXX return tx_pending */
169 144
 	return TIOCSER_TEMT;
170 145
 }
171 146
 
172  
-static void milkymistuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
  147
+static void milkymist_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
173 148
 {
174  
-	/* no modem control */
175 149
 }
176 150
 
177  
-static unsigned int milkymistuart_get_mctrl(struct uart_port *port)
  151
+static unsigned int milkymist_uart_get_mctrl(struct uart_port *port)
178 152
 {
179 153
 	return 0;
180 154
 }
181 155
 
182  
-static void milkymistuart_start_tx(struct uart_port *port)
  156
+static void milkymist_uart_stop_tx(struct uart_port *port)
183 157
 {
184  
-	if (tx_cts) {
185  
-		struct circ_buf *xmit = &(port->state->xmit);
186  
-
187  
-		if (port->x_char) {
188  
-			/* send xon/xoff character */
189  
-			tx_cts = 0;
190  
-			iowrite32be(port->x_char, CSR_UART_RXTX);
191  
-			port->x_char = 0;
192  
-			port->icount.tx++;
193  
-			return;
194  
-		}
195  
-
196  
-		/* stop transmitting if buffer empty */
197  
-		if (uart_circ_empty(xmit) || uart_tx_stopped(port))
198  
-			return;
199  
-
200  
-		/* send next character */
201  
-		tx_cts = 0;
202  
-		iowrite32be(xmit->buf[xmit->tail], CSR_UART_RXTX);
203  
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
204  
-		port->icount.tx++;
  158
+}
205 159
 
206  
-		if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
207  
-			uart_write_wakeup(port);
208  
-	}
209  
-	return;
  160
+static void milkymist_uart_stop_rx(struct uart_port *port)
  161
+{
210 162
 }
211 163
 
212  
-static void milkymistuart_stop_tx(struct uart_port *port)
  164
+static void milkymist_uart_enable_ms(struct uart_port *port)
213 165
 {
214  
-	return;
215 166
 }
216 167
 
  168
+static void milkymist_uart_break_ctl(struct uart_port *port, int break_state)
  169
+{
  170
+}
217 171
 
218  
-static void milkymistuart_stop_rx(struct uart_port *port)
  172
+static int milkymist_uart_startup(struct uart_port *port)
219 173
 {
220  
-	return;
  174
+	int ret;
  175
+
  176
+	ret = request_irq(port->irq, milkymist_uart_isr,
  177
+			IRQF_DISABLED, "milkymist_uart", port);
  178
+
  179
+	/* ack events */
  180
+	iowrite32be(UART_STAT_TX_EVT | UART_STAT_RX_EVT,
  181
+			port->membase + UART_STAT);
  182
+
  183
+	iowrite32be(UART_CTRL_RX_INT | UART_CTRL_TX_INT,
  184
+			port->membase + UART_CTRL);
  185
+
  186
+	if (ret) {
  187
+		pr_err("milkymist_uart: unable to attach interrupt\n");
  188
+		return ret;
  189
+	}
  190
+
  191
+	return 0;
221 192
 }
222 193
 
223  
-static void milkymistuart_enable_ms(struct uart_port *port)
  194
+static void milkymist_uart_shutdown(struct uart_port *port)
224 195
 {
  196
+	iowrite32be(0, port->membase + UART_CTRL);
  197
+	free_irq(port->irq, port);
225 198
 }
226 199
 
227  
-static void milkymistuart_break_ctl(struct uart_port *port, int break_state)
  200
+static const char *milkymist_uart_type(struct uart_port *port)
228 201
 {
  202
+	return (port->type == PORT_MILKYMIST_UART) ? "Milkymist UART" : NULL;
229 203
 }
230 204
 
231  
-static int milkymistuart_startup(struct uart_port *port)
  205
+static int milkymist_uart_request_port(struct uart_port *port)
232 206
 {
233  
-	if( request_irq(IRQ_UARTRX, milkymistuart_irq_rx,
234  
-				IRQF_DISABLED, "milkymist_uart RX", port) ) {
235  
-		printk(KERN_NOTICE "Unable to attach Milkymist UART RX interrupt\n");
  207
+	if (!request_mem_region(port->mapbase, 16, "milkymist_uart")) {
  208
+		dev_err(port->dev, "memory region busy\n");
236 209
 		return -EBUSY;
237 210
 	}
238  
-	if( request_irq(IRQ_UARTTX, milkymistuart_irq_tx,
239  
-				IRQF_DISABLED, "milkymist_uart TX", port) ) {
240  
-		printk(KERN_NOTICE "Unable to attach Milkymist UART TX interrupt\n");
  211
+
  212
+	port->membase = ioremap(port->mapbase, 16);
  213
+	if (!port->membase) {
  214
+		dev_err(port->dev, "unable to map registers\n");
  215
+		release_mem_region(port->mapbase, 16);
241 216
 		return -EBUSY;
242 217
 	}
243 218
 
244  
-	milkymist_uart_irqs_enabled = true;
245  
-
246 219
 	return 0;
247 220
 }
248 221
 
249  
-static void milkymistuart_shutdown(struct uart_port *port)
  222
+static void milkymist_uart_release_port(struct uart_port *port)
250 223
 {
251  
-	milkymist_uart_irqs_enabled = false;
  224
+	release_mem_region(port->mapbase, 16);
  225
+	iounmap(port->membase);
  226
+	port->membase = NULL;
  227
+}
  228
+
  229
+static void milkymist_uart_config_port(struct uart_port *port, int flags)
  230
+{
  231
+	if (!milkymist_uart_request_port(port))
  232
+		port->type = PORT_MILKYMIST_UART;
  233
+}
252 234
 
253  
-	free_irq(IRQ_UARTRX, port);
254  
-	free_irq(IRQ_UARTTX, port);
  235
+static int milkymist_uart_verify_port(struct uart_port *port,
  236
+		struct serial_struct *ser)
  237
+{
  238
+	if ((ser->type != PORT_UNKNOWN) && (ser->type != PORT_MILKYMIST_UART))
  239
+		return -EINVAL;
  240
+	return 0;
255 241
 }
256 242
 
257  
-static void milkymistuart_set_termios(
258  
-		struct uart_port *port, struct ktermios *termios, struct ktermios *old)
  243
+static void milkymist_uart_set_termios(struct uart_port *port,
  244
+		struct ktermios *termios, struct ktermios *old)
259 245
 {
260  
-	unsigned long baud;
261 246
 	unsigned long flags;
  247
+	unsigned int baud;
  248
+	unsigned int quot;
262 249
 
263  
-	/* >> 4 means / 16 */
264  
-	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk >> 4);
  250
+	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
  251
+	quot = uart_get_divisor(port, baud);
265 252
 
266  
-	/* deactivate irqs */
267 253
 	spin_lock_irqsave(&port->lock, flags);
268  
-
269  
-	milkymistuart_set_baud_rate(port, baud);
270  
-
271 254
 	uart_update_timeout(port, termios->c_cflag, baud);
272  
-
273  
-	/* restore irqs */
  255
+	iowrite32be(quot, port->membase + UART_DIV);
274 256
 	spin_unlock_irqrestore(&port->lock, flags);
275  
-}
276  
-
277  
-static const char *milkymistuart_type(struct uart_port *port)
278  
-{
279  
-	/* check, to be on the safe side */
280  
-	if( port->type == PORT_UARTLITE )
281  
-		return "milkymist_uart";
282  
-	else
283  
-		return "error";
284  
-}
285 257
 
286  
-static void milkymistuart_release_port(struct uart_port *port)
287  
-{
  258
+	if (tty_termios_baud_rate(termios))
  259
+		tty_termios_encode_baud_rate(termios, baud, baud);
288 260
 }
289 261
 
290  
-static int milkymistuart_request_port(struct uart_port *port)
291  
-{
292  
-	return 0;
293  
-}
  262
+static struct uart_ops milkymist_uart_ops = {
  263
+	.tx_empty       = milkymist_uart_tx_empty,
  264
+	.set_mctrl      = milkymist_uart_set_mctrl,
  265
+	.get_mctrl      = milkymist_uart_get_mctrl,
  266
+	.stop_tx        = milkymist_uart_stop_tx,
  267
+	.start_tx       = milkymist_uart_start_tx,
  268
+	.stop_rx        = milkymist_uart_stop_rx,
  269
+	.enable_ms      = milkymist_uart_enable_ms,
  270
+	.break_ctl      = milkymist_uart_break_ctl,
  271
+	.startup        = milkymist_uart_startup,
  272
+	.shutdown       = milkymist_uart_shutdown,
  273
+	.set_termios    = milkymist_uart_set_termios,
  274
+	.type           = milkymist_uart_type,
  275
+	.release_port   = milkymist_uart_release_port,
  276
+	.request_port   = milkymist_uart_request_port,
  277
+	.config_port    = milkymist_uart_config_port,
  278
+	.verify_port    = milkymist_uart_verify_port,
  279
+#if 0
  280
+#ifdef CONFIG_CONSOLE_POLL
  281
+	.poll_get_char  = milkymist_uart_get_poll_char,
  282
+	.poll_put_char  = milkymist_uart_put_poll_char,
  283
+#endif
  284
+#endif
  285
+};
294 286
 
295  
-/* we will only configure the port type here */
296  
-static void milkymistuart_config_port(struct uart_port *port, int flags)
  287
+#ifdef CONFIG_SERIAL_MILKYMIST_CONSOLE
  288
+static void milkymist_uart_console_wait_tx(struct uart_port *port)
297 289
 {
298  
-	if( flags & UART_CONFIG_TYPE ) {
299  
-		port->type = PORT_UARTLITE;
  290
+	int i;
  291
+	u8 stat;
  292
+
  293
+	for (i = 0; i < 100000; i++) {
  294
+		stat = ioread32be(port->membase + UART_STAT) & 0xff;
  295
+		if (stat & UART_STAT_THRE)
  296
+			break;
  297
+		cpu_relax();
300 298
 	}
301 299
 }
302 300
 
303  
-/* we do not allow the user to configure via this method */
304  
-static int milkymistuart_verify_port(struct uart_port *port, struct serial_struct *ser)
  301
+static void milkymist_uart_console_putchar(struct uart_port *port, int ch)
305 302
 {
306  
-	return -EINVAL;
  303
+	milkymist_uart_console_wait_tx(port);
  304
+	iowrite32be(ch, port->membase + UART_RXTX);
307 305
 }
308 306
 
309  
-#ifdef CONFIG_SERIAL_MILKYMIST_CONSOLE
310  
-static void milkymist_console_putchar(struct uart_port *port, int ch)
  307
+static void milkymist_uart_console_write(struct console *co, const char *s,
  308
+		unsigned int count)
311 309
 {
312  
-	if (milkymist_uart_irqs_enabled)
313  
-		disable_irq(IRQ_UARTTX);
314  
-	iowrite32be(ch, CSR_UART_RXTX);
315  
-	while(!(lm32_irq_pending() & (1 << IRQ_UARTTX)));
316  
-	lm32_irq_ack(IRQ_UARTTX);
317  
-	if (milkymist_uart_irqs_enabled)
318  
-		enable_irq(IRQ_UARTTX);
319  
-}
  310
+	struct uart_port *port = &milkymist_uart_ports[co->index];
  311
+	u32 ctrl;
  312
+	unsigned long flags;
  313
+	int locked = 1;
320 314
 
321  
-/*
322  
- * Interrupts are disabled on entering
323  
- */
324  
-static void milkymist_console_write(struct console *co, const char *s, u_int count)
325  
-{
326  
-	struct uart_port *port = &milkymistuart_ports[co->index];
  315
+	if (oops_in_progress)
  316
+		locked = spin_trylock_irqsave(&port->lock, flags);
  317
+	else
  318
+		spin_lock_irqsave(&port->lock, flags);
  319
+
  320
+	/* wait until current transmission is finished */
  321
+	milkymist_uart_console_wait_tx(port);
  322
+
  323
+	/* save ctrl and stat */
  324
+	ctrl = ioread32be(port->membase + UART_CTRL);
  325
+
  326
+	/* disable irqs */
  327
+	iowrite32be(ctrl & ~(UART_CTRL_RX_INT | UART_CTRL_TX_INT),
  328
+			port->membase + UART_CTRL);
327 329
 
328  
-	uart_console_write(port, s, count, milkymist_console_putchar);
  330
+	uart_console_write(port, s, count, milkymist_uart_console_putchar);
  331
+	milkymist_uart_console_wait_tx(port);
  332
+
  333
+	/* ack write event */
  334
+	iowrite32be(UART_STAT_TX_EVT, port->membase + UART_STAT);
  335
+
  336
+	/* restore control register */
  337
+	iowrite32be(ctrl, port->membase + UART_CTRL);
  338
+
  339
+	if (locked)
  340
+		spin_unlock_irqrestore(&port->lock, flags);
329 341
 }
330 342
 
331  
-static int __init milkymist_console_setup(struct console *co, char *options)
  343
+static int __devinit milkymist_uart_console_setup(struct console *co,
  344
+		char *options)
332 345
 {
333  
-	struct uart_port *port = &milkymistuart_ports[co->index];
334  
-
  346
+	struct uart_port *port;
335 347
 	int baud = 115200;
336 348
 	int bits = 8;
337 349
 	int parity = 'n';
338 350
 	int flow = 'n';
339 351
 
  352
+	if (co->index < 0 || co->index >= MILKYMIST_NR_UARTS)
  353
+		return -EINVAL;
  354
+
  355
+	port = &milkymist_uart_ports[co->index];
  356
+
  357
+	if (!port->mapbase) {
  358
+		pr_debug("console on ttyS%i not present\n", co->index);
  359
+		return -ENODEV;
  360
+	}
  361
+
340 362
 	if (options)
341 363
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
342 364
 
343 365
 	return uart_set_options(port, co, baud, parity, bits, flow);
344 366
 }
345 367
 
346  
-static struct uart_driver milkymistuart_driver;
  368
+static struct uart_driver milkymist_uart_driver;
347 369
 
348  
-static struct console milkymist_console = {
349  
-	.name		= MILKYMISTUART_DEVICENAME,
350  
-	.write		= milkymist_console_write,
351  
-	.device		= uart_console_device,
352  
-	.setup		= milkymist_console_setup,
353  
-	.flags		= CON_PRINTBUFFER,
354  
-	.index		= -1,
355  
-	.data		= &milkymistuart_driver,
  370
+static struct console milkymist_uart_console = {
  371
+	.name	=	"ttyS",
  372
+	.write	=	milkymist_uart_console_write,
  373
+	.device	=	uart_console_device,
  374
+	.setup	=	milkymist_uart_console_setup,
  375
+	.flags	=	CON_PRINTBUFFER,
  376
+	.index	=	-1,
  377
+	.data	=	&milkymist_uart_driver,
356 378
 };
357 379
 
358  
-/*
359  
- * Early console initialization
360  
- */
361  
-static int __init milkymist_early_console_init(void)
  380
+static int __init milkymist_uart_console_init(void)
362 381
 {
363  
-	add_preferred_console(MILKYMISTUART_DEVICENAME, 0, NULL);
364  
-	milkymistuart_init_port();
365  
-	register_console(&milkymist_console);
366  
-	pr_info("milkymist_uart: registered real console\n");
  382
+	register_console(&milkymist_uart_console);
367 383
 	return 0;
368 384
 }
369  
-console_initcall(milkymist_early_console_init);
  385
+console_initcall(milkymist_uart_console_init);
  386
+#endif
370 387
 
371  
-/*
372  
- * Late console initialization
373  
- */
374  
-static int __init milkymist_late_console_init(void)
  388
+static struct uart_driver milkymist_uart_driver = {
  389
+	.owner = THIS_MODULE,
  390
+	.driver_name = "milkymist_uart",
  391
+	.dev_name    = "ttyS",
  392
+	.major       = MILKYMIST_UART_MAJOR,
  393
+	.minor       = MILKYMIST_UART_MINOR,
  394
+	.nr          = MILKYMIST_NR_UARTS,
  395
+#ifdef CONFIG_SERIAL_MILKYMIST_CONSOLE
  396
+	.cons        = &milkymist_uart_console,
  397
+#endif
  398
+};
  399
+
  400
+static int __devinit milkymist_uart_probe(struct platform_device *op)
375 401
 {
376  
-	if( !(milkymist_console.flags & CON_ENABLED) ) {
377  
-		register_console(&milkymist_console);
378  
-		pr_info("milkymist_uart: registered real console\n");
  402
+	struct uart_port *port;
  403
+	struct device_node *np = op->dev.of_node;
  404
+	int ret;
  405
+	struct resource res;
  406
+	const unsigned int *pid, *clk;
  407
+	int id;
  408
+	int irq;
  409
+
  410
+	ret = of_address_to_resource(np, 0, &res);
  411
+	if (ret) {
  412
+		dev_err(&op->dev, "invalid address\n");
  413
+		return ret;
379 414
 	}
380  
-	return 0;
381  
-}
382  
-core_initcall(milkymist_late_console_init);
383 415
 
384  
-#define MILKYMIST_CONSOLE_DEVICE	&milkymist_console
385  
-#else
386  
-#define MILKYMIST_CONSOLE_DEVICE	NULL
387  
-#endif
  416
+	irq = irq_of_parse_and_map(np, 0);
388 417
 
389  
-static struct uart_driver milkymistuart_driver = {
390  
-	.owner       = THIS_MODULE,
391  
-	.driver_name = MILKYMISTUART_DRIVERNAME,
392  
-	.dev_name    = MILKYMISTUART_DEVICENAME,
393  
-	.major       = MILKYMISTUART_MAJOR,
394  
-	.minor       = MILKYMISTUART_MINOR,
395  
-	.nr          = 0, /* will be filled by init */
396  
-	.cons        = MILKYMIST_CONSOLE_DEVICE
397  
-};
  418
+	clk = of_get_property(np, "clock-frequency", NULL);
  419
+	if (!clk) {
  420
+		dev_warn(&op->dev, "no clock-frequency property set\n");
  421
+		return -ENODEV;
  422
+	}
398 423
 
399  
-static struct uart_port* __devinit milkymistuart_init_port(void)
400  
-{
401  
-	struct uart_port* port;
  424
+	pid = of_get_property(np, "port-number", NULL);
  425
+
  426
+	if (pid)
  427
+		id = *pid;
  428
+	else {
  429
+		/* find free id */
  430
+		for (id = 0; id < MILKYMIST_NR_UARTS; id++)
  431
+			if (milkymist_uart_ports[id].mapbase == 0)
  432
+				break;
  433
+	}
  434
+
  435
+	if (id < 0 || id >= MILKYMIST_NR_UARTS) {
  436
+		dev_err(&op->dev, "milkymist_uart%i too large\n", id);
  437
+		return -EINVAL;
  438
+	}
  439
+
  440
+	if (milkymist_uart_ports[id].mapbase
  441
+			&& milkymist_uart_ports[id].mapbase != res.start) {
  442
+		dev_err(&op->dev, "milkymist_uart%i already in use\n", id);
  443
+		return -EBUSY;
  444
+	}
  445
+
  446
+	ret = uart_register_driver(&milkymist_uart_driver);
  447
+	if (ret) {
  448
+		dev_err(&op->dev, "uart_register_driver() failed; err=%i\n", ret);
  449
+		return ret;
  450
+	}
  451
+
  452
+	port = &milkymist_uart_ports[id];
  453
+
  454
+	spin_lock_init(&port->lock);
  455
+	port->line = id;
  456
+	port->regshift = 2;
  457
+	port->iotype = UPIO_MEM;
  458
+	port->mapbase = res.start;
  459
+	port->membase = NULL;
  460
+	port->flags = UPF_BOOT_AUTOCONF;
  461
+	port->irq = irq;
  462
+
  463
+	port->ops = &milkymist_uart_ops;
  464
+	port->type = PORT_UNKNOWN;
  465
+	port->uartclk = *clk;
402 466
 	
403  
-	port = &milkymistuart_ports[0];
404  
-	port->type = PORT_UARTLITE;
405  
-	port->iobase = 0x0;
406  
-	port->membase = (void __iomem*)CSR_UART_RXTX;
407  
-	port->irq = IRQ_UARTRX;
408  
-	port->uartclk = CONFIG_CPU_CLOCK;
409  
-	port->flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; // TODO perhaps this is not completely correct
410  
-	port->iotype = UPIO_PORT; // TODO perhaps this is not completely correct
411  
-	port->regshift = 0;
412  
-	port->ops = &milkymistuart_pops;
413  
-	port->line = 0;
414  
-	port->private_data = NULL;
415  
-	return port;
416  
-}
  467
+	port->dev = &op->dev;
417 468
 
418  
-static int __devinit milkymistuart_serial_probe(struct platform_device *pdev)
419  
-{
420  
-	struct uart_port *port;
421  
-	int ret;
  469
+	dev_set_drvdata(&op->dev, port);
422 470
 
423  
-	port = milkymistuart_init_port();
  471
+	ret = uart_add_one_port(&milkymist_uart_driver, port);
  472
+	if (ret) {
  473
+		dev_err(&op->dev, "uart_add_one_port() failed; err=%i\n", ret);
  474
+		port->mapbase = 0;
  475
+		return ret;
  476
+	}
424 477
 
425  
-	ret = uart_add_one_port(&milkymistuart_driver, port);
426  
-	if (!ret) {
427  
-		pr_info("milkymist_uart: added port %d with irq %d-%d at 0x%lx\n",
428  
-				port->line, IRQ_UARTRX, IRQ_UARTTX, (unsigned long)port->membase);
429  
-		device_init_wakeup(&pdev->dev, 1);
430  
-		platform_set_drvdata(pdev, port);
431  
-	} else
432  
-		printk(KERN_ERR "milkymist_uart: could not add port %d: %d\n", port->line, ret);
  478
+	//device_init_wakeup(&op->dev, 1);
433 479
 
434  
-	return ret;
  480
+	return 0;
435 481
 }
436 482
 
437  
-static int __devexit milkymistuart_serial_remove(struct platform_device *pdev)
  483
+static int __devexit milkymist_uart_remove(struct platform_device *dev)
438 484
 {
439  
-	struct uart_port *port = platform_get_drvdata(pdev);
440  
-	int ret = 0;
441  
-
442  
-	device_init_wakeup(&pdev->dev, 0);
443  
-	platform_set_drvdata(pdev, NULL);
  485
+	struct uart_port *port = dev_get_drvdata(&dev->dev);
444 486
 
445  
-	if (port) {
446  
-		ret = uart_remove_one_port(&milkymistuart_driver, port);
447  
-		kfree(port);
448  
-	}
  487
+	uart_remove_one_port(&milkymist_uart_driver, port);
  488
+	dev_set_drvdata(&dev->dev, NULL);
  489
+	port->mapbase = 0;
449 490
 
450  
-	return ret;
  491
+	return 0;
451 492
 }
452 493
 
453  
-static const struct of_device_id milkymistuart_of_ids[] = {
  494
+static const struct of_device_id milkymist_uart_match[] = {
454 495
 	{ .compatible = "milkymist,uart", },
455  
-	{}
  496
+	{},
456 497
 };
  498
+MODULE_DEVICE_TABLE(of, milkymist_uart_match);
457 499
 
458  
-static struct platform_driver milkymistuart_serial_driver = {
459  
-	.probe		= milkymistuart_serial_probe,
460  
-	.remove		= __devexit_p(milkymistuart_serial_remove),
461  
-	.driver		= {
462  
-		.name	= "milkymist_uart",
463  
-		.owner	= THIS_MODULE,
464  
-		.of_match_table = milkymistuart_of_ids,
  500
+static struct platform_driver milkymist_uart_of_driver = {
  501
+	.driver = {
  502
+		.name = "milkymist_uart",
  503
+		.owner = THIS_MODULE,
  504
+		.of_match_table = milkymist_uart_match,
465 505
 	},
  506
+	.probe		= milkymist_uart_probe,
  507
+	.remove		= __devexit_p(milkymist_uart_remove),
466 508
 };
467 509
 
468  
-static int __init milkymistuart_init(void)
  510
+static int __init milkymist_uart_init(void)
469 511
 {
470  
-	int ret;
471  
-	
472  
-	pr_info("milkymist_uart: Milkymist UART driver\n");
473  
-
474  
-	/* configure from hardware setup structures */
475  
-	milkymistuart_driver.nr = 1;
476  
-	tx_cts = 1;
477  
-	ret = uart_register_driver(&milkymistuart_driver);
478  
-	if( ret < 0 )
479  
-		return ret;
480  
-
481  
-	ret = platform_driver_register(&milkymistuart_serial_driver);
482  
-	if( ret < 0 )
483  
-		uart_unregister_driver(&milkymistuart_driver);
484  
-
485  
-	return ret;
  512
+	return platform_driver_register(&milkymist_uart_of_driver);
486 513
 }
487 514
 
488  
-static void __exit milkymistuart_exit(void)
  515
+static void __exit milkymist_uart_exit(void)
489 516
 {
490  
-	platform_driver_unregister(&milkymistuart_serial_driver);
491  
-	uart_unregister_driver(&milkymistuart_driver);
  517
+	platform_driver_unregister(&milkymist_uart_of_driver);
492 518
 }
493 519
 
494  
-module_init(milkymistuart_init);
495  
-module_exit(milkymistuart_exit);
  520
+module_init(milkymist_uart_init);
  521
+module_exit(milkymist_uart_exit);
496 522
 
497  
-MODULE_LICENSE("GPL");
498  
-MODULE_DESCRIPTION("Milkymist UART driver");
499 523
 MODULE_AUTHOR("Milkymist Project");
  524
+MODULE_DESCRIPTION("Milkymist UART driver");
  525
+MODULE_LICENSE("GPL");
3  include/linux/serial_core.h
@@ -206,6 +206,9 @@
206 206
 /* Xilinx PSS UART */
207 207
 #define PORT_XUARTPS	98
208 208
 
  209
+/* Milkymist UART */
  210
+#define PORT_MILKYMIST_UART	99
  211
+
209 212
 #ifdef __KERNEL__
210 213
 
211 214
 #include <linux/compiler.h>

No commit comments for this range

Something went wrong with that request. Please try again.