3 * \brief PXA UART implementation
6 * \author Adam Lackorznynski <adam@os.inf.tu-dresden.de>
7 * Alexander Warg <alexander.warg@os.inf.tu-dresden.de>
11 * (c) 2008-2009 Author(s)
12 * economic rights: Technische Universität Dresden (Germany)
14 * This file is part of TUD:OS and distributed under the terms of the
15 * GNU General Public License 2.
16 * Please see the COPYING-GPL-2 file for details.
23 TRB = 0x00, // Transmit/Receive Buffer (read/write)
24 BRD_LOW = 0x00, // Baud Rate Divisor LSB if bit 7 of LCR is set (read/write)
25 IER = 0x04, // Interrupt Enable Register (read/write)
26 BRD_HIGH = 0x04, // Baud Rate Divisor MSB if bit 7 of LCR is set (read/write)
27 IIR = 0x08, // Interrupt Identification Register (read only)
28 FCR = 0x08, // 16550 FIFO Control Register (write only)
29 LCR = 0x0c, // Line Control Register (read/write)
30 MCR = 0x10, // Modem Control Register (read/write)
31 LSR = 0x14, // Line Status Register (read only)
32 MSR = 0x18, // Modem Status Register (read only)
33 SPR = 0x1c, // Scratch Pad Register (read/write)
38 Base_ier_bits = 1 << 6,
52 MODE_8N1 = PAR_NONE | DAT_8 | STOP_1,
53 MODE_7E1 = PAR_EVEN | DAT_7 | STOP_1,
55 // these two values are to leave either mode
56 // or baud rate unchanged on a call to change_mode
61 unsigned long Uart_pxa::rd(unsigned long reg) const
62 { return *(volatile unsigned long*)(_base + reg); }
64 void Uart_pxa::wr(unsigned long reg, unsigned long val) const
65 { *(volatile unsigned long*)(_base + reg) = val; }
67 bool Uart_pxa::startup(unsigned long base)
71 char scratch, scratch2, scratch3;
82 if (!(scratch2 == 0x00 && scratch3 == 0x0f))
83 return false; // this is not the uart
85 //proc_status o = proc_cli_save();
86 wr(IER, Base_ier_bits);/* disable all rs-232 interrupts */
87 wr(MCR, 0x0b); /* out2, rts, and dtr enabled */
88 wr(FCR, 1); /* enable fifo */
89 wr(FCR, 0x07); /* clear rcv xmit fifo */
90 wr(FCR, 1); /* enable fifo */
91 wr(LCR, 0); /* clear line control register */
93 /* clearall interrupts */
94 /*read*/ rd(MSR); /* IRQID 0*/
95 /*read*/ rd(IIR); /* IRQID 1*/
96 /*read*/ rd(TRB); /* IRQID 2*/
97 /*read*/ rd(LSR); /* IRQID 3*/
99 while (rd(LSR) & 1/*DATA READY*/)
101 //proc_sti_restore(o);
106 void Uart_pxa::shutdown()
108 //proc_status o = proc_cli_save();
113 //proc_sti_restore(o);
116 bool Uart_pxa::enable_rx_irq(bool /*enable*/) { return true; }
117 bool Uart_pxa::enable_tx_irq(bool /*enable*/) { return false; }
118 bool Uart_pxa::change_mode(Transfer_mode m, Baud_rate r)
120 //proc_status o = proc_cli_save();
121 unsigned long old_lcr = rd(LCR);
123 unsigned short divisor = Base_rate / r;
124 wr(LCR, old_lcr | 0x80/*DLAB*/);
125 wr(TRB, divisor & 0x0ff ); /* BRD_LOW */
126 wr(IER, (divisor >> 8) & 0x0ff ); /* BRD_HIGH */
132 //proc_sti_restore(o);
136 int Uart_pxa::get_char(bool blocking) const
140 if (!blocking && !char_avail())
144 wr(IER, old_ier & ~0xf);
145 while (!char_avail())
152 int Uart_pxa::char_avail() const
154 return rd(LSR) & 1; // DATA READY
157 void Uart_pxa::out_char(char c) const
163 int Uart_pxa::write(char const *s, unsigned long count) const
165 /* disable uart irqs */
169 wr(IER, old_ier & ~0x0f);
172 for (i = 0; i < count; i++) {
173 while (!(rd(LSR) & 0x20 /* THRE */))
180 while (!(rd(LSR) & 0x20 /* THRE */))
186 /* wait till everything is transmitted */
187 while (!(rd(LSR) & 0x40 /* TSRE */))