| /* |
| * Copyright 2003 PMC-Sierra |
| * Author: Manish Lachwani (lachwani@pmc-sierra.com) |
| * |
| * This program is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License as published by the |
| * Free Software Foundation; either version 2 of the License, or (at your |
| * option) any later version. |
| * |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN |
| * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
| * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
| * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| * You should have received a copy of the GNU General Public License along |
| * with this program; if not, write to the Free Software Foundation, Inc., |
| * 675 Mass Ave, Cambridge, MA 02139, USA. |
| */ |
| |
| /* |
| * Support for KGDB for the Yosemite board. We make use of single serial |
| * port to be used for KGDB as well as console. The second serial port |
| * seems to be having a problem. Single IRQ is allocated for both the |
| * ports. Hence, the interrupt routing code needs to figure out whether |
| * the interrupt came from channel A or B. |
| */ |
| |
| #include <asm/serial.h> |
| |
| /* |
| * Baud rate, Parity, Data and Stop bit settings for the |
| * serial port on the Yosemite. Note that the Early printk |
| * patch has been added. So, we should be all set to go |
| */ |
| #define YOSEMITE_BAUD_2400 2400 |
| #define YOSEMITE_BAUD_4800 4800 |
| #define YOSEMITE_BAUD_9600 9600 |
| #define YOSEMITE_BAUD_19200 19200 |
| #define YOSEMITE_BAUD_38400 38400 |
| #define YOSEMITE_BAUD_57600 57600 |
| #define YOSEMITE_BAUD_115200 115200 |
| |
| #define YOSEMITE_PARITY_NONE 0 |
| #define YOSEMITE_PARITY_ODD 0x08 |
| #define YOSEMITE_PARITY_EVEN 0x18 |
| #define YOSEMITE_PARITY_MARK 0x28 |
| #define YOSEMITE_PARITY_SPACE 0x38 |
| |
| #define YOSEMITE_DATA_5BIT 0x0 |
| #define YOSEMITE_DATA_6BIT 0x1 |
| #define YOSEMITE_DATA_7BIT 0x2 |
| #define YOSEMITE_DATA_8BIT 0x3 |
| |
| #define YOSEMITE_STOP_1BIT 0x0 |
| #define YOSEMITE_STOP_2BIT 0x4 |
| |
| /* This is crucial */ |
| #define SERIAL_REG_OFS 0x1 |
| |
| #define SERIAL_RCV_BUFFER 0x0 |
| #define SERIAL_TRANS_HOLD 0x0 |
| #define SERIAL_SEND_BUFFER 0x0 |
| #define SERIAL_INTR_ENABLE (1 * SERIAL_REG_OFS) |
| #define SERIAL_INTR_ID (2 * SERIAL_REG_OFS) |
| #define SERIAL_DATA_FORMAT (3 * SERIAL_REG_OFS) |
| #define SERIAL_LINE_CONTROL (3 * SERIAL_REG_OFS) |
| #define SERIAL_MODEM_CONTROL (4 * SERIAL_REG_OFS) |
| #define SERIAL_RS232_OUTPUT (4 * SERIAL_REG_OFS) |
| #define SERIAL_LINE_STATUS (5 * SERIAL_REG_OFS) |
| #define SERIAL_MODEM_STATUS (6 * SERIAL_REG_OFS) |
| #define SERIAL_RS232_INPUT (6 * SERIAL_REG_OFS) |
| #define SERIAL_SCRATCH_PAD (7 * SERIAL_REG_OFS) |
| |
| #define SERIAL_DIVISOR_LSB (0 * SERIAL_REG_OFS) |
| #define SERIAL_DIVISOR_MSB (1 * SERIAL_REG_OFS) |
| |
| /* |
| * Functions to READ and WRITE to serial port 0 |
| */ |
| #define SERIAL_READ(ofs) (*((volatile unsigned char*) \ |
| (TITAN_SERIAL_BASE + ofs))) |
| |
| #define SERIAL_WRITE(ofs, val) ((*((volatile unsigned char*) \ |
| (TITAN_SERIAL_BASE + ofs))) = val) |
| |
| /* |
| * Functions to READ and WRITE to serial port 1 |
| */ |
| #define SERIAL_READ_1(ofs) (*((volatile unsigned char*) \ |
| (TITAN_SERIAL_BASE_1 + ofs))) |
| |
| #define SERIAL_WRITE_1(ofs, val) ((*((volatile unsigned char*) \ |
| (TITAN_SERIAL_BASE_1 + ofs))) = val) |
| |
| /* |
| * Second serial port initialization |
| */ |
| void init_second_port(void) |
| { |
| /* Disable Interrupts */ |
| SERIAL_WRITE_1(SERIAL_LINE_CONTROL, 0x0); |
| SERIAL_WRITE_1(SERIAL_INTR_ENABLE, 0x0); |
| |
| { |
| unsigned int divisor; |
| |
| SERIAL_WRITE_1(SERIAL_LINE_CONTROL, 0x80); |
| divisor = TITAN_SERIAL_BASE_BAUD / YOSEMITE_BAUD_115200; |
| SERIAL_WRITE_1(SERIAL_DIVISOR_LSB, divisor & 0xff); |
| |
| SERIAL_WRITE_1(SERIAL_DIVISOR_MSB, |
| (divisor & 0xff00) >> 8); |
| SERIAL_WRITE_1(SERIAL_LINE_CONTROL, 0x0); |
| } |
| |
| SERIAL_WRITE_1(SERIAL_DATA_FORMAT, YOSEMITE_DATA_8BIT | |
| YOSEMITE_PARITY_NONE | YOSEMITE_STOP_1BIT); |
| |
| /* Enable Interrupts */ |
| SERIAL_WRITE_1(SERIAL_INTR_ENABLE, 0xf); |
| } |
| |
| /* Initialize the serial port for KGDB debugging */ |
| void debugInit(unsigned int baud, unsigned char data, unsigned char parity, |
| unsigned char stop) |
| { |
| /* Disable Interrupts */ |
| SERIAL_WRITE(SERIAL_LINE_CONTROL, 0x0); |
| SERIAL_WRITE(SERIAL_INTR_ENABLE, 0x0); |
| |
| { |
| unsigned int divisor; |
| |
| SERIAL_WRITE(SERIAL_LINE_CONTROL, 0x80); |
| |
| divisor = TITAN_SERIAL_BASE_BAUD / baud; |
| SERIAL_WRITE(SERIAL_DIVISOR_LSB, divisor & 0xff); |
| |
| SERIAL_WRITE(SERIAL_DIVISOR_MSB, (divisor & 0xff00) >> 8); |
| SERIAL_WRITE(SERIAL_LINE_CONTROL, 0x0); |
| } |
| |
| SERIAL_WRITE(SERIAL_DATA_FORMAT, data | parity | stop); |
| } |
| |
| static int remoteDebugInitialized = 0; |
| |
| unsigned char getDebugChar(void) |
| { |
| if (!remoteDebugInitialized) { |
| remoteDebugInitialized = 1; |
| debugInit(YOSEMITE_BAUD_115200, |
| YOSEMITE_DATA_8BIT, |
| YOSEMITE_PARITY_NONE, YOSEMITE_STOP_1BIT); |
| } |
| |
| while ((SERIAL_READ(SERIAL_LINE_STATUS) & 0x1) == 0); |
| return SERIAL_READ(SERIAL_RCV_BUFFER); |
| } |
| |
| int putDebugChar(unsigned char byte) |
| { |
| if (!remoteDebugInitialized) { |
| remoteDebugInitialized = 1; |
| debugInit(YOSEMITE_BAUD_115200, |
| YOSEMITE_DATA_8BIT, |
| YOSEMITE_PARITY_NONE, YOSEMITE_STOP_1BIT); |
| } |
| |
| while ((SERIAL_READ(SERIAL_LINE_STATUS) & 0x20) == 0); |
| SERIAL_WRITE(SERIAL_SEND_BUFFER, byte); |
| |
| return 1; |
| } |