1*cbab9cadSchs /* $Id: mpcsa_usart.c,v 1.4 2012/10/27 17:17:48 chs Exp $ */
2*cbab9cadSchs /* $NetBSD: mpcsa_usart.c,v 1.4 2012/10/27 17:17:48 chs Exp $ */
3c62a0ac4Smatt
4c62a0ac4Smatt /*
5c62a0ac4Smatt * Copyright (c) 2007 Embedtronics Oy. All rights reserved.
6c62a0ac4Smatt *
7c62a0ac4Smatt * Redistribution and use in source and binary forms, with or without
8c62a0ac4Smatt * modification, are permitted provided that the following conditions
9c62a0ac4Smatt * are met:
10c62a0ac4Smatt * 1. Redistributions of source code must retain the above copyright
11c62a0ac4Smatt * notice, this list of conditions and the following disclaimer.
12c62a0ac4Smatt * 2. Redistributions in binary form must reproduce the above copyright
13c62a0ac4Smatt * notice, this list of conditions and the following disclaimer in the
14c62a0ac4Smatt * documentation and/or other materials provided with the distribution.
15c62a0ac4Smatt *
16c62a0ac4Smatt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17c62a0ac4Smatt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18c62a0ac4Smatt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19c62a0ac4Smatt * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20c62a0ac4Smatt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21c62a0ac4Smatt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22c62a0ac4Smatt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23c62a0ac4Smatt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24c62a0ac4Smatt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25c62a0ac4Smatt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26c62a0ac4Smatt * SUCH DAMAGE.
27c62a0ac4Smatt */
28c62a0ac4Smatt
29c62a0ac4Smatt #include <sys/cdefs.h>
30*cbab9cadSchs __KERNEL_RCSID(0, "$NetBSD: mpcsa_usart.c,v 1.4 2012/10/27 17:17:48 chs Exp $");
31c62a0ac4Smatt
32c62a0ac4Smatt #include <sys/types.h>
33c62a0ac4Smatt #include <sys/param.h>
34c62a0ac4Smatt #include <sys/systm.h>
35c62a0ac4Smatt #include <sys/kernel.h>
36c62a0ac4Smatt #include <sys/device.h>
37c62a0ac4Smatt #include <sys/proc.h>
38c62a0ac4Smatt #include <arm/at91/at91reg.h>
39c62a0ac4Smatt #include <arm/at91/at91var.h>
40c62a0ac4Smatt #include <arm/at91/at91usartvar.h>
41c62a0ac4Smatt #include <arm/at91/at91piovar.h>
42c62a0ac4Smatt #include <arm/at91/at91rm9200reg.h>
43c62a0ac4Smatt #include <evbarm/mpcsa/mpcsa_io.h>
44c62a0ac4Smatt #include <evbarm/mpcsa/mpcsa_leds_var.h>
45c62a0ac4Smatt #include <sys/unistd.h>
46c62a0ac4Smatt
47c62a0ac4Smatt #ifdef MPCSA_USART_DEBUG
48c62a0ac4Smatt int mpcsa_usart_debug = MPCSA_USART_DEBUG;
49c62a0ac4Smatt #define DPRINTFN(n,x) if (mpcsa_usart_debug>(n)) printf x;
50c62a0ac4Smatt #else
51c62a0ac4Smatt #define DPRINTFN(n,x)
52c62a0ac4Smatt #endif
53c62a0ac4Smatt
54c62a0ac4Smatt struct at91pio_softc;
55c62a0ac4Smatt
56c62a0ac4Smatt struct mpcsa_usart_softc {
57c62a0ac4Smatt struct at91usart_softc sc_dev;
58c62a0ac4Smatt struct at91pio_softc *sc_pioa, *sc_piob, *sc_piod;
59c62a0ac4Smatt void *sc_cts_ih;
60c62a0ac4Smatt int sc_tx_busy, sc_rx_busy;
61c62a0ac4Smatt };
62c62a0ac4Smatt
63*cbab9cadSchs static int mpcsa_usart_match(device_t, cfdata_t, void *);
64*cbab9cadSchs static void mpcsa_usart_attach(device_t, device_t, void *);
65c62a0ac4Smatt
66*cbab9cadSchs CFATTACH_DECL_NEW(mpcsa_usart, sizeof(struct mpcsa_usart_softc),
67c62a0ac4Smatt mpcsa_usart_match, mpcsa_usart_attach, NULL, NULL);
68c62a0ac4Smatt
69c62a0ac4Smatt static int mpcsa_usart_enable(struct at91usart_softc *sc);
70c62a0ac4Smatt static int mpcsa_usart_disable(struct at91usart_softc *sc);
71c62a0ac4Smatt static void mpcsa_usart_hwflow(struct at91usart_softc *sc, int cflags);
72c62a0ac4Smatt static void mpcsa_usart_start_tx(struct at91usart_softc *sc);
73c62a0ac4Smatt static void mpcsa_usart_stop_tx(struct at91usart_softc *sc);
74c62a0ac4Smatt static void mpcsa_usart_rx_started(struct at91usart_softc *sc);
75c62a0ac4Smatt static void mpcsa_usart_rx_stopped(struct at91usart_softc *sc);
76c62a0ac4Smatt static void mpcsa_usart_rx_rts_ctl(struct at91usart_softc *sc, int enabled);
77c62a0ac4Smatt
78c62a0ac4Smatt static int mpcsa_gsm_cts_intr(void *);
79c62a0ac4Smatt
80c62a0ac4Smatt static __inline int
led_num(struct mpcsa_usart_softc * mpsc)81c62a0ac4Smatt led_num(struct mpcsa_usart_softc *mpsc)
82c62a0ac4Smatt {
83c62a0ac4Smatt return (mpsc->sc_dev.sc_pid == PID_US3 ? LED_GSM : LED_SER1 + mpsc->sc_dev.sc_pid - PID_US0);
84c62a0ac4Smatt }
85c62a0ac4Smatt
86c62a0ac4Smatt static __inline void
comm_led(struct mpcsa_usart_softc * mpsc,int count)87c62a0ac4Smatt comm_led(struct mpcsa_usart_softc *mpsc, int count)
88c62a0ac4Smatt {
89c62a0ac4Smatt mpcsa_comm_led(led_num(mpsc), count);
90c62a0ac4Smatt }
91c62a0ac4Smatt
92c62a0ac4Smatt static __inline void
conn_led(struct mpcsa_usart_softc * mpsc,int count)93c62a0ac4Smatt conn_led(struct mpcsa_usart_softc *mpsc, int count)
94c62a0ac4Smatt {
95c62a0ac4Smatt mpcsa_conn_led(led_num(mpsc), count);
96c62a0ac4Smatt }
97c62a0ac4Smatt
98c62a0ac4Smatt static int
mpcsa_usart_match(device_t parent,cfdata_t match,void * aux)99*cbab9cadSchs mpcsa_usart_match(device_t parent, cfdata_t match, void *aux)
100c62a0ac4Smatt {
101c62a0ac4Smatt if (strcmp(match->cf_name, "at91usart") == 0 && strcmp(match->cf_atname, "mpcsa_usart") == 0)
102c62a0ac4Smatt return 2;
103c62a0ac4Smatt return 0;
104c62a0ac4Smatt }
105c62a0ac4Smatt
106c62a0ac4Smatt
107c62a0ac4Smatt static void
mpcsa_usart_attach(device_t parent,device_t self,void * aux)108*cbab9cadSchs mpcsa_usart_attach(device_t parent, device_t self, void *aux)
109c62a0ac4Smatt {
110*cbab9cadSchs struct mpcsa_usart_softc *sc = device_private(self);
111c62a0ac4Smatt struct at91bus_attach_args *sa = aux;
112c62a0ac4Smatt
113*cbab9cadSchs sc->sc_dev.sc_dev = self;
114*cbab9cadSchs
115c62a0ac4Smatt // initialize softc
116c62a0ac4Smatt if ((sc->sc_pioa = at91pio_sc(AT91_PIOA)) == NULL) {
117c62a0ac4Smatt printf("no PIOA!\n");
118c62a0ac4Smatt return;
119c62a0ac4Smatt }
120c62a0ac4Smatt if ((sc->sc_piob = at91pio_sc(AT91_PIOB)) == NULL) {
121c62a0ac4Smatt printf("no PIOB!\n");
122c62a0ac4Smatt return;
123c62a0ac4Smatt }
124c62a0ac4Smatt if ((sc->sc_piod = at91pio_sc(AT91_PIOD)) == NULL) {
125c62a0ac4Smatt printf("no PIOD!\n");
126c62a0ac4Smatt return;
127c62a0ac4Smatt }
128c62a0ac4Smatt
129c62a0ac4Smatt // calculate unit number...
130c62a0ac4Smatt switch (sa->sa_pid) {
131c62a0ac4Smatt case PID_US0:
132c62a0ac4Smatt case PID_US1:
133c62a0ac4Smatt case PID_US2:
134c62a0ac4Smatt case PID_US3:
135c62a0ac4Smatt sc->sc_dev.enable = mpcsa_usart_enable;
136c62a0ac4Smatt sc->sc_dev.disable = mpcsa_usart_disable;
137c62a0ac4Smatt sc->sc_dev.hwflow = mpcsa_usart_hwflow;
138c62a0ac4Smatt sc->sc_dev.start_tx = mpcsa_usart_start_tx;
139c62a0ac4Smatt sc->sc_dev.stop_tx = mpcsa_usart_stop_tx;
140c62a0ac4Smatt sc->sc_dev.rx_started = mpcsa_usart_rx_started;
141c62a0ac4Smatt sc->sc_dev.rx_stopped = mpcsa_usart_rx_stopped;
142c62a0ac4Smatt sc->sc_dev.rx_rts_ctl = mpcsa_usart_rx_rts_ctl;
143c62a0ac4Smatt break;
144c62a0ac4Smatt }
145c62a0ac4Smatt
146c62a0ac4Smatt /* configure pins */
147c62a0ac4Smatt switch (sa->sa_pid) {
148c62a0ac4Smatt case PID_US0:
149c62a0ac4Smatt at91pio_set(sc->sc_piob, PB_RTS1);
150c62a0ac4Smatt at91pio_set(sc->sc_piod, PD_DTR1);
151c62a0ac4Smatt at91pio_in(sc->sc_piob, PB_CTS1);
152c62a0ac4Smatt at91pio_out(sc->sc_piob, PB_RTS1);
153c62a0ac4Smatt at91pio_in(sc->sc_piod, PD_DSR1);
154c62a0ac4Smatt at91pio_out(sc->sc_piod, PD_DTR1);
155c62a0ac4Smatt at91pio_per(sc->sc_piob, PB_CTS1, -1);
156c62a0ac4Smatt at91pio_per(sc->sc_piob, PB_RTS1, -1);
157c62a0ac4Smatt at91pio_per(sc->sc_piod, PD_DSR1, -1);
158c62a0ac4Smatt at91pio_per(sc->sc_piod, PD_DTR1, -1);
159c62a0ac4Smatt break;
160c62a0ac4Smatt case PID_US1:
161c62a0ac4Smatt at91pio_set(sc->sc_piob, PB_RTS2);
162c62a0ac4Smatt at91pio_set(sc->sc_piod, PD_DTR2);
163c62a0ac4Smatt at91pio_in(sc->sc_piob, PB_CTS2);
164c62a0ac4Smatt at91pio_out(sc->sc_piob, PB_RTS2);
165c62a0ac4Smatt at91pio_in(sc->sc_piod, PD_DSR2);
166c62a0ac4Smatt at91pio_out(sc->sc_piod, PD_DTR2);
167c62a0ac4Smatt at91pio_per(sc->sc_piob, PB_CTS2, -1);
168c62a0ac4Smatt at91pio_per(sc->sc_piob, PB_RTS2, -1);
169c62a0ac4Smatt at91pio_per(sc->sc_piod, PD_DSR2, -1);
170c62a0ac4Smatt at91pio_per(sc->sc_piod, PD_DTR2, -1);
171c62a0ac4Smatt break;
172c62a0ac4Smatt case PID_US2:
173c62a0ac4Smatt at91pio_set(sc->sc_piob, PB_RTS3);
174c62a0ac4Smatt at91pio_set(sc->sc_piod, PD_DTR3);
175c62a0ac4Smatt at91pio_in(sc->sc_piob, PB_CTS3);
176c62a0ac4Smatt at91pio_out(sc->sc_piob, PB_RTS3);
177c62a0ac4Smatt at91pio_in(sc->sc_piod, PD_DSR3);
178c62a0ac4Smatt at91pio_out(sc->sc_piod, PD_DTR3);
179c62a0ac4Smatt at91pio_per(sc->sc_piob, PB_CTS3, -1);
180c62a0ac4Smatt at91pio_per(sc->sc_piob, PB_RTS3, -1);
181c62a0ac4Smatt at91pio_per(sc->sc_piod, PD_DSR3, -1);
182c62a0ac4Smatt at91pio_per(sc->sc_piod, PD_DTR3, -1);
183c62a0ac4Smatt break;
184c62a0ac4Smatt case PID_US3:
185c62a0ac4Smatt /* configure pin states... */
186c62a0ac4Smatt at91pio_clear(sc->sc_pioa, PA_GSMON);
187c62a0ac4Smatt at91pio_set(sc->sc_pioa, PA_GSMOFF);
188c62a0ac4Smatt at91pio_set(sc->sc_piob, PB_RTS4);
189c62a0ac4Smatt at91pio_set(sc->sc_piod, PD_DTR4);
190c62a0ac4Smatt
191c62a0ac4Smatt /* configure pin directions.. */
192c62a0ac4Smatt at91pio_out(sc->sc_pioa, PA_GSMOFF);
193c62a0ac4Smatt at91pio_out(sc->sc_pioa, PA_GSMON);
194c62a0ac4Smatt at91pio_in(sc->sc_pioa, PA_TXD4);
195c62a0ac4Smatt at91pio_in(sc->sc_piob, PB_RTS4);
196c62a0ac4Smatt at91pio_in(sc->sc_piob, PB_CTS4);
197c62a0ac4Smatt at91pio_in(sc->sc_piod, PD_DTR4);
198c62a0ac4Smatt at91pio_in(sc->sc_piod, PD_DSR4);
199c62a0ac4Smatt at91pio_in(sc->sc_piod, PD_DCD4);
200c62a0ac4Smatt
201c62a0ac4Smatt /* make sure all related pins are configured as PIO */
202c62a0ac4Smatt at91pio_per(sc->sc_pioa, PA_GSMOFF, -1);
203c62a0ac4Smatt at91pio_per(sc->sc_pioa, PA_GSMON, -1);
204c62a0ac4Smatt at91pio_per(sc->sc_pioa, PA_TXD4, -1);
205c62a0ac4Smatt at91pio_per(sc->sc_piob, PB_CTS4, -1);
206c62a0ac4Smatt at91pio_per(sc->sc_piob, PB_RTS4, -1);
207c62a0ac4Smatt at91pio_per(sc->sc_piod, PD_DSR4, -1);
208c62a0ac4Smatt at91pio_per(sc->sc_piod, PD_DTR4, -1);
209c62a0ac4Smatt at91pio_per(sc->sc_piod, PD_DCD4, -1);
210c62a0ac4Smatt break;
211c62a0ac4Smatt }
212c62a0ac4Smatt
213c62a0ac4Smatt // and call common routine
214c62a0ac4Smatt at91usart_attach_subr(&sc->sc_dev, sa);
215c62a0ac4Smatt }
216c62a0ac4Smatt
217c62a0ac4Smatt static int
mpcsa_usart_enable(struct at91usart_softc * dev)218c62a0ac4Smatt mpcsa_usart_enable(struct at91usart_softc *dev)
219c62a0ac4Smatt {
220c62a0ac4Smatt struct mpcsa_usart_softc *sc = (struct mpcsa_usart_softc *)dev;
221c62a0ac4Smatt conn_led(sc, 1);
222c62a0ac4Smatt switch (sc->sc_dev.sc_pid) {
223c62a0ac4Smatt case PID_US3:
224c62a0ac4Smatt /* turn gsm on */
225c62a0ac4Smatt at91pio_clear(sc->sc_pioa, PA_GSMOFF);
2266a0660a9Srmind kpause("gsmond", false, 4 * hz, NULL);
227c62a0ac4Smatt at91pio_set(sc->sc_pioa, PA_GSMON);
2286a0660a9Srmind kpause("gsmon", false, 2 * hz, NULL);
229c62a0ac4Smatt at91pio_clear(sc->sc_pioa, PA_GSMON);
230c62a0ac4Smatt /* then attach pins to devices etc */
231c62a0ac4Smatt at91pio_per(sc->sc_pioa, PA_TXD4, 1);
232c62a0ac4Smatt at91pio_clear(sc->sc_piob, PB_RTS4);
233c62a0ac4Smatt at91pio_clear(sc->sc_piod, PD_DTR4);
234c62a0ac4Smatt at91pio_out(sc->sc_piob, PB_RTS4);
235c62a0ac4Smatt at91pio_out(sc->sc_piod, PD_DTR4);
236c62a0ac4Smatt /* catch CTS interrupt */
237c62a0ac4Smatt sc->sc_cts_ih = at91pio_intr_establish(sc->sc_piob, PB_CTS4,
238c62a0ac4Smatt IPL_TTY, mpcsa_gsm_cts_intr,
239c62a0ac4Smatt sc);
240c62a0ac4Smatt break;
241c62a0ac4Smatt }
242c62a0ac4Smatt return 0;
243c62a0ac4Smatt }
244c62a0ac4Smatt
245c62a0ac4Smatt static int
mpcsa_usart_disable(struct at91usart_softc * dev)246c62a0ac4Smatt mpcsa_usart_disable(struct at91usart_softc *dev)
247c62a0ac4Smatt {
248c62a0ac4Smatt struct mpcsa_usart_softc *sc = (struct mpcsa_usart_softc *)dev;
249c62a0ac4Smatt if (sc->sc_tx_busy || sc->sc_rx_busy) {
250c62a0ac4Smatt sc->sc_tx_busy = sc->sc_rx_busy = 0;
251c62a0ac4Smatt comm_led(sc, 1);
252c62a0ac4Smatt }
253c62a0ac4Smatt switch (sc->sc_dev.sc_pid) {
254c62a0ac4Smatt case PID_US3:
255c62a0ac4Smatt at91pio_intr_disestablish(sc->sc_piob, PB_CTS4, sc->sc_cts_ih);
256c62a0ac4Smatt
257c62a0ac4Smatt at91pio_clear(sc->sc_pioa, PA_GSMON);
2586a0660a9Srmind kpause("gsmoffd", false, (hz * 350 + 999) / 1000, NULL);
259c62a0ac4Smatt
260c62a0ac4Smatt at91pio_per(sc->sc_pioa, PA_TXD4, -1);
261c62a0ac4Smatt at91pio_in(sc->sc_piob, PB_RTS4);
262c62a0ac4Smatt at91pio_in(sc->sc_piod, PD_DTR4);
263c62a0ac4Smatt
264c62a0ac4Smatt at91pio_set(sc->sc_pioa, PA_GSMOFF);
2656a0660a9Srmind kpause("gsmoff", false, hz * 4, NULL);
266c62a0ac4Smatt at91pio_clear(sc->sc_pioa, PA_GSMOFF);
267c62a0ac4Smatt
268c62a0ac4Smatt break;
269c62a0ac4Smatt }
270c62a0ac4Smatt conn_led(sc, 0);
271c62a0ac4Smatt return 0;
272c62a0ac4Smatt }
273c62a0ac4Smatt
mpcsa_gsm_cts_intr(void * cookie)274c62a0ac4Smatt static int mpcsa_gsm_cts_intr(void *cookie)
275c62a0ac4Smatt {
276c62a0ac4Smatt struct mpcsa_usart_softc *sc = (struct mpcsa_usart_softc *)cookie;
277c62a0ac4Smatt if (ISSET(sc->sc_dev.sc_swflags, TIOCFLAG_CRTSCTS)) {
278c62a0ac4Smatt /* hardware flow control is enabled */
279c62a0ac4Smatt if (!(PIOB_READ(PIO_PDSR) & (1U << PB_CTS4))) {
280c62a0ac4Smatt if (bus_space_read_4(sc->sc_dev.sc_iot, sc->sc_dev.sc_ioh,
281c62a0ac4Smatt US_PDC + PDC_TCR) && !sc->sc_tx_busy) {
282c62a0ac4Smatt sc->sc_tx_busy = 1;
283c62a0ac4Smatt if (!sc->sc_rx_busy)
284c62a0ac4Smatt comm_led(sc, INFINITE_BLINK);
285c62a0ac4Smatt }
286c62a0ac4Smatt
287c62a0ac4Smatt bus_space_write_4(sc->sc_dev.sc_iot, sc->sc_dev.sc_ioh,
288c62a0ac4Smatt US_PDC + PDC_PTCR, PDC_PTCR_TXTEN);
289c62a0ac4Smatt SET(sc->sc_dev.sc_ier, US_CSR_TXEMPTY | US_CSR_ENDTX);
290c62a0ac4Smatt bus_space_write_4(sc->sc_dev.sc_iot, sc->sc_dev.sc_ioh,
291c62a0ac4Smatt US_IER, US_CSR_ENDTX);
292c62a0ac4Smatt } else {
293c62a0ac4Smatt bus_space_write_4(sc->sc_dev.sc_iot, sc->sc_dev.sc_ioh,
294c62a0ac4Smatt US_PDC + PDC_PTCR, PDC_PTCR_TXTDIS);
295c62a0ac4Smatt if (sc->sc_tx_busy) {
296c62a0ac4Smatt sc->sc_tx_busy = 0;
297c62a0ac4Smatt if (!sc->sc_rx_busy)
298c62a0ac4Smatt comm_led(sc, 1);
299c62a0ac4Smatt }
300c62a0ac4Smatt }
301c62a0ac4Smatt }
302c62a0ac4Smatt return 0;
303c62a0ac4Smatt }
304c62a0ac4Smatt
305c62a0ac4Smatt static void
mpcsa_usart_hwflow(struct at91usart_softc * dev,int flags)306c62a0ac4Smatt mpcsa_usart_hwflow(struct at91usart_softc *dev, int flags)
307c62a0ac4Smatt {
308c62a0ac4Smatt }
309c62a0ac4Smatt
310c62a0ac4Smatt static void
mpcsa_usart_start_tx(struct at91usart_softc * sc)311c62a0ac4Smatt mpcsa_usart_start_tx(struct at91usart_softc *sc)
312c62a0ac4Smatt {
313c62a0ac4Smatt if (!ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS)
314c62a0ac4Smatt || bus_space_read_4(sc->sc_iot, sc->sc_ioh, US_PDC + PDC_PTSR) & PDC_PTSR_TXTEN) {
315c62a0ac4Smatt bus_space_write_4(sc->sc_iot, sc->sc_ioh,
316c62a0ac4Smatt US_PDC + PDC_PTCR, PDC_PTCR_TXTEN);
317c62a0ac4Smatt struct mpcsa_usart_softc *mpsc = (void*)sc;
318c62a0ac4Smatt if (!mpsc->sc_tx_busy) {
319c62a0ac4Smatt mpsc->sc_tx_busy = 1;
320c62a0ac4Smatt if (!mpsc->sc_rx_busy)
321c62a0ac4Smatt comm_led(mpsc, INFINITE_BLINK);
322c62a0ac4Smatt }
323c62a0ac4Smatt return;
324c62a0ac4Smatt }
325c62a0ac4Smatt }
326c62a0ac4Smatt
327c62a0ac4Smatt static void
mpcsa_usart_stop_tx(struct at91usart_softc * sc)328c62a0ac4Smatt mpcsa_usart_stop_tx(struct at91usart_softc *sc)
329c62a0ac4Smatt {
330c62a0ac4Smatt struct mpcsa_usart_softc *mpsc = (void*)sc;
331c62a0ac4Smatt mpsc->sc_tx_busy = 0;
332c62a0ac4Smatt if (!mpsc->sc_rx_busy)
333c62a0ac4Smatt comm_led(mpsc, 1);
334c62a0ac4Smatt if (!ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS)) {
335c62a0ac4Smatt bus_space_write_4(sc->sc_iot, sc->sc_ioh,
336c62a0ac4Smatt US_PDC + PDC_PTCR, PDC_PTCR_TXTDIS);
337c62a0ac4Smatt }
338c62a0ac4Smatt }
339c62a0ac4Smatt
340c62a0ac4Smatt static void
mpcsa_usart_rx_started(struct at91usart_softc * sc)341c62a0ac4Smatt mpcsa_usart_rx_started(struct at91usart_softc *sc)
342c62a0ac4Smatt {
343c62a0ac4Smatt struct mpcsa_usart_softc *mpsc = (void*)sc;
344c62a0ac4Smatt if (!mpsc->sc_rx_busy) {
345c62a0ac4Smatt mpsc->sc_rx_busy = 1;
346c62a0ac4Smatt if (!mpsc->sc_tx_busy)
347c62a0ac4Smatt comm_led(mpsc, INFINITE_BLINK);
348c62a0ac4Smatt }
349c62a0ac4Smatt }
350c62a0ac4Smatt
351c62a0ac4Smatt static void
mpcsa_usart_rx_stopped(struct at91usart_softc * sc)352c62a0ac4Smatt mpcsa_usart_rx_stopped(struct at91usart_softc *sc)
353c62a0ac4Smatt {
354c62a0ac4Smatt struct mpcsa_usart_softc *mpsc = (void*)sc;
355c62a0ac4Smatt mpsc->sc_rx_busy = 0;
356c62a0ac4Smatt if (!mpsc->sc_tx_busy)
357c62a0ac4Smatt comm_led(mpsc, 1);
358c62a0ac4Smatt }
359c62a0ac4Smatt
360c62a0ac4Smatt static void
mpcsa_usart_rx_rts_ctl(struct at91usart_softc * sc,int enabled)361c62a0ac4Smatt mpcsa_usart_rx_rts_ctl(struct at91usart_softc *sc, int enabled)
362c62a0ac4Smatt {
363c62a0ac4Smatt struct mpcsa_usart_softc *mpsc = (void*)sc;
364c62a0ac4Smatt
365c62a0ac4Smatt switch (mpsc->sc_dev.sc_pid) {
366c62a0ac4Smatt case PID_US0:
367c62a0ac4Smatt if (enabled)
368c62a0ac4Smatt at91pio_set(mpsc->sc_piob, PB_RTS1);
369c62a0ac4Smatt else
370c62a0ac4Smatt at91pio_clear(mpsc->sc_piob, PB_RTS1);
371c62a0ac4Smatt break;
372c62a0ac4Smatt
373c62a0ac4Smatt case PID_US1:
374c62a0ac4Smatt if (enabled)
375c62a0ac4Smatt at91pio_set(mpsc->sc_piob, PB_RTS2);
376c62a0ac4Smatt else
377c62a0ac4Smatt at91pio_clear(mpsc->sc_piob, PB_RTS2);
378c62a0ac4Smatt break;
379c62a0ac4Smatt
380c62a0ac4Smatt case PID_US2:
381c62a0ac4Smatt if (enabled)
382c62a0ac4Smatt at91pio_set(mpsc->sc_piob, PB_RTS3);
383c62a0ac4Smatt else
384c62a0ac4Smatt at91pio_clear(mpsc->sc_piob, PB_RTS3);
385c62a0ac4Smatt break;
386c62a0ac4Smatt
387c62a0ac4Smatt case PID_US3:
388c62a0ac4Smatt if (enabled)
389c62a0ac4Smatt at91pio_set(mpsc->sc_piob, PB_RTS4);
390c62a0ac4Smatt else
391c62a0ac4Smatt at91pio_clear(mpsc->sc_piob, PB_RTS4);
392c62a0ac4Smatt break;
393c62a0ac4Smatt
394c62a0ac4Smatt }
395c62a0ac4Smatt
396c62a0ac4Smatt }
397c62a0ac4Smatt
398