/* * 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 /* * 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; }