Paul Mundt | 373e68b | 2006-09-27 15:41:24 +0900 | [diff] [blame^] | 1 | /* |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2 | * linux/arch/sh/kernel/setup_7751se.c |
| 3 | * |
| 4 | * Copyright (C) 2000 Kazumoto Kojima |
| 5 | * |
| 6 | * Hitachi SolutionEngine Support. |
| 7 | * |
| 8 | * Modified for 7751 Solution Engine by |
| 9 | * Ian da Silva and Jeremy Siegel, 2001. |
| 10 | */ |
| 11 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 12 | #include <linux/init.h> |
| 13 | #include <linux/irq.h> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 14 | #include <linux/ide.h> |
| 15 | #include <asm/io.h> |
Paul Mundt | 373e68b | 2006-09-27 15:41:24 +0900 | [diff] [blame^] | 16 | #include <asm/se7751.h> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 17 | |
| 18 | #ifdef CONFIG_SH_KGDB |
| 19 | #include <asm/kgdb.h> |
| 20 | #endif |
| 21 | |
| 22 | /* |
| 23 | * Configure the Super I/O chip |
| 24 | */ |
| 25 | #if 0 |
| 26 | /* Leftover code from regular Solution Engine, for reference. */ |
| 27 | /* The SH7751 Solution Engine has a different SuperIO. */ |
| 28 | static void __init smsc_config(int index, int data) |
| 29 | { |
| 30 | outb_p(index, INDEX_PORT); |
| 31 | outb_p(data, DATA_PORT); |
| 32 | } |
| 33 | |
| 34 | static void __init init_smsc(void) |
| 35 | { |
| 36 | outb_p(CONFIG_ENTER, CONFIG_PORT); |
| 37 | outb_p(CONFIG_ENTER, CONFIG_PORT); |
| 38 | |
| 39 | /* FDC */ |
| 40 | smsc_config(CURRENT_LDN_INDEX, LDN_FDC); |
| 41 | smsc_config(ACTIVATE_INDEX, 0x01); |
| 42 | smsc_config(IRQ_SELECT_INDEX, 6); /* IRQ6 */ |
| 43 | |
| 44 | /* IDE1 */ |
| 45 | smsc_config(CURRENT_LDN_INDEX, LDN_IDE1); |
| 46 | smsc_config(ACTIVATE_INDEX, 0x01); |
| 47 | smsc_config(IRQ_SELECT_INDEX, 14); /* IRQ14 */ |
| 48 | |
| 49 | /* AUXIO (GPIO): to use IDE1 */ |
| 50 | smsc_config(CURRENT_LDN_INDEX, LDN_AUXIO); |
| 51 | smsc_config(GPIO46_INDEX, 0x00); /* nIOROP */ |
| 52 | smsc_config(GPIO47_INDEX, 0x00); /* nIOWOP */ |
| 53 | |
| 54 | /* COM1 */ |
| 55 | smsc_config(CURRENT_LDN_INDEX, LDN_COM1); |
| 56 | smsc_config(ACTIVATE_INDEX, 0x01); |
| 57 | smsc_config(IO_BASE_HI_INDEX, 0x03); |
| 58 | smsc_config(IO_BASE_LO_INDEX, 0xf8); |
| 59 | smsc_config(IRQ_SELECT_INDEX, 4); /* IRQ4 */ |
| 60 | |
| 61 | /* COM2 */ |
| 62 | smsc_config(CURRENT_LDN_INDEX, LDN_COM2); |
| 63 | smsc_config(ACTIVATE_INDEX, 0x01); |
| 64 | smsc_config(IO_BASE_HI_INDEX, 0x02); |
| 65 | smsc_config(IO_BASE_LO_INDEX, 0xf8); |
| 66 | smsc_config(IRQ_SELECT_INDEX, 3); /* IRQ3 */ |
| 67 | |
| 68 | /* RTC */ |
| 69 | smsc_config(CURRENT_LDN_INDEX, LDN_RTC); |
| 70 | smsc_config(ACTIVATE_INDEX, 0x01); |
| 71 | smsc_config(IRQ_SELECT_INDEX, 8); /* IRQ8 */ |
| 72 | |
| 73 | /* XXX: PARPORT, KBD, and MOUSE will come here... */ |
| 74 | outb_p(CONFIG_EXIT, CONFIG_PORT); |
| 75 | } |
| 76 | #endif |
| 77 | |
| 78 | const char *get_system_type(void) |
| 79 | { |
| 80 | return "7751 SolutionEngine"; |
| 81 | } |
| 82 | |
| 83 | #ifdef CONFIG_SH_KGDB |
| 84 | static int kgdb_uart_setup(void); |
| 85 | static struct kgdb_sermap kgdb_uart_sermap = |
| 86 | { "ttyS", 0, kgdb_uart_setup, NULL }; |
| 87 | #endif |
| 88 | |
| 89 | /* |
| 90 | * Initialize the board |
| 91 | */ |
| 92 | void __init platform_setup(void) |
| 93 | { |
| 94 | /* Call init_smsc() replacement to set up SuperIO. */ |
| 95 | /* XXX: RTC setting comes here */ |
| 96 | #ifdef CONFIG_SH_KGDB |
| 97 | kgdb_register_sermap(&kgdb_uart_sermap); |
| 98 | #endif |
| 99 | } |
| 100 | |
| 101 | /********************************************************************* |
| 102 | * Currently a hack (e.g. does not interact well w/serial.c, lots of * |
| 103 | * hardcoded stuff) but may be useful if SCI/F needs debugging. * |
| 104 | * Mostly copied from x86 code (see files asm-i386/kgdb_local.h and * |
| 105 | * arch/i386/lib/kgdb_serial.c). * |
| 106 | *********************************************************************/ |
| 107 | |
| 108 | #ifdef CONFIG_SH_KGDB |
| 109 | #include <linux/types.h> |
| 110 | #include <linux/serial.h> |
| 111 | #include <linux/serialP.h> |
| 112 | #include <linux/serial_reg.h> |
| 113 | |
| 114 | #define COM1_PORT 0x3f8 /* Base I/O address */ |
| 115 | #define COM1_IRQ 4 /* IRQ not used yet */ |
| 116 | #define COM2_PORT 0x2f8 /* Base I/O address */ |
| 117 | #define COM2_IRQ 3 /* IRQ not used yet */ |
| 118 | |
| 119 | #define SB_CLOCK 1843200 /* Serial baud clock */ |
| 120 | #define SB_BASE (SB_CLOCK/16) |
| 121 | #define SB_MCR UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS |
| 122 | |
| 123 | struct uart_port { |
| 124 | int base; |
| 125 | }; |
| 126 | #define UART_NPORTS 2 |
| 127 | struct uart_port uart_ports[] = { |
| 128 | { COM1_PORT }, |
| 129 | { COM2_PORT }, |
| 130 | }; |
| 131 | struct uart_port *kgdb_uart_port; |
| 132 | |
| 133 | #define UART_IN(reg) inb_p(kgdb_uart_port->base + reg) |
| 134 | #define UART_OUT(reg,v) outb_p((v), kgdb_uart_port->base + reg) |
| 135 | |
| 136 | /* Basic read/write functions for the UART */ |
| 137 | #define UART_LSR_RXCERR (UART_LSR_BI | UART_LSR_FE | UART_LSR_PE) |
| 138 | static int kgdb_uart_getchar(void) |
| 139 | { |
| 140 | int lsr; |
| 141 | int c = -1; |
| 142 | |
| 143 | while (c == -1) { |
| 144 | lsr = UART_IN(UART_LSR); |
| 145 | if (lsr & UART_LSR_DR) |
| 146 | c = UART_IN(UART_RX); |
| 147 | if ((lsr & UART_LSR_RXCERR)) |
| 148 | c = -1; |
| 149 | } |
| 150 | return c; |
| 151 | } |
| 152 | |
| 153 | static void kgdb_uart_putchar(int c) |
| 154 | { |
| 155 | while ((UART_IN(UART_LSR) & UART_LSR_THRE) == 0) |
| 156 | ; |
| 157 | UART_OUT(UART_TX, c); |
| 158 | } |
| 159 | |
| 160 | /* |
| 161 | * Initialize UART to configured/requested values. |
| 162 | * (But we don't interrupts yet, or interact w/serial.c) |
| 163 | */ |
| 164 | static int kgdb_uart_setup(void) |
| 165 | { |
| 166 | int port; |
| 167 | int lcr = 0; |
| 168 | int bdiv = 0; |
| 169 | |
| 170 | if (kgdb_portnum >= UART_NPORTS) { |
| 171 | KGDB_PRINTK("uart port %d invalid.\n", kgdb_portnum); |
| 172 | return -1; |
| 173 | } |
| 174 | |
| 175 | kgdb_uart_port = &uart_ports[kgdb_portnum]; |
| 176 | |
| 177 | /* Init sequence from gdb_hook_interrupt */ |
| 178 | UART_IN(UART_RX); |
| 179 | UART_OUT(UART_IER, 0); |
| 180 | |
| 181 | UART_IN(UART_RX); /* Serial driver comments say */ |
| 182 | UART_IN(UART_IIR); /* this clears interrupt regs */ |
| 183 | UART_IN(UART_MSR); |
| 184 | |
| 185 | /* Figure basic LCR values */ |
| 186 | switch (kgdb_bits) { |
| 187 | case '7': |
| 188 | lcr |= UART_LCR_WLEN7; |
| 189 | break; |
| 190 | default: case '8': |
| 191 | lcr |= UART_LCR_WLEN8; |
| 192 | break; |
| 193 | } |
| 194 | switch (kgdb_parity) { |
| 195 | case 'O': |
| 196 | lcr |= UART_LCR_PARITY; |
| 197 | break; |
| 198 | case 'E': |
| 199 | lcr |= (UART_LCR_PARITY | UART_LCR_EPAR); |
| 200 | break; |
| 201 | default: break; |
| 202 | } |
| 203 | |
| 204 | /* Figure the baud rate divisor */ |
| 205 | bdiv = (SB_BASE/kgdb_baud); |
| 206 | |
| 207 | /* Set the baud rate and LCR values */ |
| 208 | UART_OUT(UART_LCR, (lcr | UART_LCR_DLAB)); |
| 209 | UART_OUT(UART_DLL, (bdiv & 0xff)); |
| 210 | UART_OUT(UART_DLM, ((bdiv >> 8) & 0xff)); |
| 211 | UART_OUT(UART_LCR, lcr); |
| 212 | |
| 213 | /* Set the MCR */ |
| 214 | UART_OUT(UART_MCR, SB_MCR); |
| 215 | |
| 216 | /* Turn off FIFOs for now */ |
| 217 | UART_OUT(UART_FCR, 0); |
| 218 | |
| 219 | /* Setup complete: initialize function pointers */ |
| 220 | kgdb_getchar = kgdb_uart_getchar; |
| 221 | kgdb_putchar = kgdb_uart_putchar; |
| 222 | |
| 223 | return 0; |
| 224 | } |
| 225 | #endif /* CONFIG_SH_KGDB */ |