#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
-#include <asm/segment.h>
#include <asm/semaphore.h>
#include <asm/delay.h>
#include <asm/coldfire.h>
* keep going. Perhaps one day the cflag settings for the
* console can be used instead.
*/
-#if defined(CONFIG_ARNEWSH) || defined(CONFIG_MOTOROLA) || defined(CONFIG_senTec) || defined(CONFIG_SNEHA)
+#if defined(CONFIG_HW_FEITH)
+#define CONSOLE_BAUD_RATE 38400
+#define DEFAULT_CBAUD B38400
+#elif defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB) || \
+ defined(CONFIG_M5329EVB) || defined(CONFIG_GILBARCO)
+#define CONSOLE_BAUD_RATE 115200
+#define DEFAULT_CBAUD B115200
+#elif defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \
+ defined(CONFIG_senTec) || defined(CONFIG_SNEHA) || defined(CONFIG_AVNET)
#define CONSOLE_BAUD_RATE 19200
#define DEFAULT_CBAUD B19200
#endif
-#if defined(CONFIG_HW_FEITH)
- #define CONSOLE_BAUD_RATE 38400
- #define DEFAULT_CBAUD B38400
-#endif
-
#ifndef CONSOLE_BAUD_RATE
#define CONSOLE_BAUD_RATE 9600
#define DEFAULT_CBAUD B9600
#undef SERIAL_DEBUG_OPEN
#undef SERIAL_DEBUG_FLOW
-#if defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
+ defined(CONFIG_M520x) || defined(CONFIG_M532x)
#define IRQBASE (MCFINT_VECBASE+MCFINT_UART0)
#else
#define IRQBASE 73
.irq = IRQBASE,
.flags = ASYNC_BOOT_AUTOCONF,
},
+#ifdef MCFUART_BASE2
{ /* ttyS1 */
.magic = 0,
.addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE2),
.irq = IRQBASE+1,
.flags = ASYNC_BOOT_AUTOCONF,
},
+#endif
+#ifdef MCFUART_BASE3
+ { /* ttyS2 */
+ .magic = 0,
+ .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE3),
+ .irq = IRQBASE+2,
+ .flags = ASYNC_BOOT_AUTOCONF,
+ },
+#endif
+#ifdef MCFUART_BASE4
+ { /* ttyS3 */
+ .magic = 0,
+ .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE4),
+ .irq = IRQBASE+3,
+ .flags = ASYNC_BOOT_AUTOCONF,
+ },
+#endif
};
#endif
-/*
- * tmp_buf is used as a temporary buffer by serial_write. We need to
- * lock it in case the copy_from_user blocks while swapping in a page,
- * and some other program tries to do a serial write at the same time.
- * Since the lock will only come under contention when the system is
- * swapping and available memory is low, it makes sense to share one
- * buffer across all the serial ports, since it significantly saves
- * memory if large numbers of serial ports are open.
- */
-static unsigned char mcfrs_tmp_buf[4096]; /* This is cheating */
-static DECLARE_MUTEX(mcfrs_tmp_buf_sem);
-
/*
* Forware declarations...
*/
{
volatile unsigned char *uartp;
struct tty_struct *tty = info->tty;
- unsigned char status, ch;
+ unsigned char status, ch, flag;
if (!tty)
return;
uartp = info->addr;
while ((status = uartp[MCFUART_USR]) & MCFUART_USR_RXREADY) {
-
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- break;
-
ch = uartp[MCFUART_URB];
info->stats.rx++;
}
#endif
- tty->flip.count++;
+ flag = TTY_NORMAL;
if (status & MCFUART_USR_RXERR) {
uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETERR;
if (status & MCFUART_USR_RXBREAK) {
info->stats.rxbreak++;
- *tty->flip.flag_buf_ptr++ = TTY_BREAK;
+ flag = TTY_BREAK;
} else if (status & MCFUART_USR_RXPARITY) {
info->stats.rxparity++;
- *tty->flip.flag_buf_ptr++ = TTY_PARITY;
+ flag = TTY_PARITY;
} else if (status & MCFUART_USR_RXOVERRUN) {
info->stats.rxoverrun++;
- *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+ flag = TTY_OVERRUN;
} else if (status & MCFUART_USR_RXFRAMING) {
info->stats.rxframing++;
- *tty->flip.flag_buf_ptr++ = TTY_FRAME;
- } else {
- /* This should never happen... */
- *tty->flip.flag_buf_ptr++ = 0;
+ flag = TTY_FRAME;
}
- } else {
- *tty->flip.flag_buf_ptr++ = 0;
}
- *tty->flip.char_buf_ptr++ = ch;
+ tty_insert_flip_char(tty, ch, flag);
}
-
- schedule_work(&tty->flip.work);
+ tty_schedule_flip(tty);
return;
}
/*
* This is the serial driver's generic interrupt routine
*/
-irqreturn_t mcfrs_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t mcfrs_interrupt(int irq, void *dev_id)
{
struct mcf_serial *info;
unsigned char isr;
(arg ? CLOCAL : 0));
return 0;
case TIOCGSERIAL:
- error = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(struct serial_struct));
- if (error)
- return error;
- return get_serial_info(info,
+ if (access_ok(VERIFY_WRITE, (void *) arg,
+ sizeof(struct serial_struct)))
+ return get_serial_info(info,
(struct serial_struct *) arg);
+ return -EFAULT;
case TIOCSSERIAL:
return set_serial_info(info,
(struct serial_struct *) arg);
case TIOCSERGETLSR: /* Get line status register */
- error = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(unsigned int));
- if (error)
- return error;
- else
- return get_lsr_info(info, (unsigned int *) arg);
-
+ if (access_ok(VERIFY_WRITE, (void *) arg,
+ sizeof(unsigned int)))
+ return get_lsr_info(info, (unsigned int *) arg);
+ return -EFAULT;
case TIOCSERGSTRUCT:
error = copy_to_user((struct mcf_serial *) arg,
info, sizeof(struct mcf_serial));
return 0;
}
-static void mcfrs_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void mcfrs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
*portp = (*portp & ~0x000000ff) | 0x00000055;
portp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_PDCNT);
*portp = (*portp & ~0x000003fc) | 0x000002a8;
-#elif defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
volatile unsigned char *icrp, *uartp;
volatile unsigned long *imrp;
icrp = (volatile unsigned char *) (MCF_MBAR + MCFICM_INTC0 +
MCFINTC_ICR0 + MCFINT_UART0 + info->line);
- *icrp = 0x33; /* UART0 with level 6, priority 3 */
+ *icrp = 0x30 + info->line; /* level 6, line based priority */
imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 +
MCFINTC_IMRL);
*imrp &= ~((1 << (info->irq - MCFINT_VECBASE)) | 1);
+#if defined(CONFIG_M527x)
+ {
+ /*
+ * External Pin Mask Setting & Enable External Pin for Interface
+ * mrcbis@aliceposta.it
+ */
+ unsigned short *serpin_enable_mask;
+ serpin_enable_mask = (MCF_IPSBAR + MCF_GPIO_PAR_UART);
+ if (info->line == 0)
+ *serpin_enable_mask |= UART0_ENABLE_MASK;
+ else if (info->line == 1)
+ *serpin_enable_mask |= UART1_ENABLE_MASK;
+ else if (info->line == 2)
+ *serpin_enable_mask |= UART2_ENABLE_MASK;
+ }
+#endif
+#elif defined(CONFIG_M520x)
+ volatile unsigned char *icrp, *uartp;
+ volatile unsigned long *imrp;
+
+ uartp = info->addr;
+
+ icrp = (volatile unsigned char *) (MCF_MBAR + MCFICM_INTC0 +
+ MCFINTC_ICR0 + MCFINT_UART0 + info->line);
+ *icrp = 0x03;
+
+ imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 +
+ MCFINTC_IMRL);
+ *imrp &= ~((1 << (info->irq - MCFINT_VECBASE)) | 1);
+ if (info->line < 2) {
+ unsigned short *uart_par;
+ uart_par = (unsigned short *)(MCF_IPSBAR + MCF_GPIO_PAR_UART);
+ if (info->line == 0)
+ *uart_par |= MCF_GPIO_PAR_UART_PAR_UTXD0
+ | MCF_GPIO_PAR_UART_PAR_URXD0;
+ else if (info->line == 1)
+ *uart_par |= MCF_GPIO_PAR_UART_PAR_UTXD1
+ | MCF_GPIO_PAR_UART_PAR_URXD1;
+ } else if (info->line == 2) {
+ unsigned char *feci2c_par;
+ feci2c_par = (unsigned char *)(MCF_IPSBAR + MCF_GPIO_PAR_FECI2C);
+ *feci2c_par &= ~0x0F;
+ *feci2c_par |= MCF_GPIO_PAR_FECI2C_PAR_SCL_UTXD2
+ | MCF_GPIO_PAR_FECI2C_PAR_SDA_URXD2;
+ }
+#elif defined(CONFIG_M532x)
+ volatile unsigned char *uartp;
+ uartp = info->addr;
+ switch (info->line) {
+ case 0:
+ MCF_INTC0_ICR26 = 0x3;
+ MCF_INTC0_CIMR = 26;
+ /* GPIO initialization */
+ MCF_GPIO_PAR_UART |= 0x000F;
+ break;
+ case 1:
+ MCF_INTC0_ICR27 = 0x3;
+ MCF_INTC0_CIMR = 27;
+ /* GPIO initialization */
+ MCF_GPIO_PAR_UART |= 0x0FF0;
+ break;
+ case 2:
+ MCF_INTC0_ICR28 = 0x3;
+ MCF_INTC0_CIMR = 28;
+ /* GPIOs also must be initalized, depends on board */
+ break;
+ }
#else
volatile unsigned char *icrp, *uartp;
/* Clear mask, so no surprise interrupts. */
uartp[MCFUART_UIMR] = 0;
- if (request_irq(info->irq, mcfrs_interrupt, SA_INTERRUPT,
+ if (request_irq(info->irq, mcfrs_interrupt, IRQF_DISABLED,
"ColdFire UART", NULL)) {
printk("MCFRS: Unable to attach ColdFire UART %d interrupt "
"vector=%d\n", info->line, info->irq);
printk(mcfrs_drivername);
}
-static struct tty_operations mcfrs_ops = {
+static const struct tty_operations mcfrs_ops = {
.open = mcfrs_open,
.close = mcfrs_close,
.write = mcfrs_write,
/* Initialize the tty_driver structure */
mcfrs_serial_driver->owner = THIS_MODULE;
mcfrs_serial_driver->name = "ttyS";
- mcfrs_serial_driver->devfs_name = "ttys/";
- mcfrs_serial_driver->driver_name = "serial";
+ mcfrs_serial_driver->driver_name = "mcfserial";
mcfrs_serial_driver->major = TTY_MAJOR;
mcfrs_serial_driver->minor_start = 64;
mcfrs_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
uartp[MCFUART_UMR] = MCFUART_MR1_PARITYNONE | MCFUART_MR1_CS8;
uartp[MCFUART_UMR] = MCFUART_MR2_STOP1;
+#ifdef CONFIG_M5272
+{
+ /*
+ * For the MCF5272, also compute the baudrate fraction.
+ */
+ int fraction = MCF_BUSCLK - (clk * 32 * mcfrs_console_baud);
+ fraction *= 16;
+ fraction /= (32 * mcfrs_console_baud);
+ uartp[MCFUART_UFPD] = (fraction & 0xf); /* set fraction */
+ clk = (MCF_BUSCLK / mcfrs_console_baud) / 32;
+}
+#else
clk = ((MCF_BUSCLK / mcfrs_console_baud) + 16) / 32; /* set baud */
+#endif
+
uartp[MCFUART_UBG1] = (clk & 0xff00) >> 8; /* set msb baud */
uartp[MCFUART_UBG2] = (clk & 0xff); /* set lsb baud */
-
uartp[MCFUART_UCSR] = MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER;
uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE;