Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mxc: add MX3 support for i.MX internal UART driver

This patch adds MX3 support for the i.MX internal uart driver.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>

authored by

Sascha Hauer and committed by
Robert Schwebel
e3d13ff4 df1bf4bd

+265 -20
+1 -1
arch/arm/mach-mx3/Makefile
··· 4 4 5 5 # Object file lists. 6 6 7 - obj-y := mm.o time.o clock.o 7 + obj-y := mm.o time.o clock.o devices.o 8 8 obj-$(CONFIG_MACH_MX31ADS) += mx31ads.o
+153
arch/arm/mach-mx3/devices.c
··· 1 + /* 2 + * Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved. 3 + * Copyright 2008 Sascha Hauer, kernel@pengutronix.de 4 + * 5 + * This program is free software; you can redistribute it and/or 6 + * modify it under the terms of the GNU General Public License 7 + * as published by the Free Software Foundation; either version 2 8 + * of the License, or (at your option) any later version. 9 + * This program is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 + * GNU General Public License for more details. 13 + * 14 + * You should have received a copy of the GNU General Public License 15 + * along with this program; if not, write to the Free Software 16 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 + * Boston, MA 02110-1301, USA. 18 + */ 19 + 20 + #include <linux/module.h> 21 + #include <linux/platform_device.h> 22 + #include <linux/serial.h> 23 + #include <asm/hardware.h> 24 + #include <asm/arch/imx-uart.h> 25 + 26 + static struct resource uart0[] = { 27 + { 28 + .start = UART1_BASE_ADDR, 29 + .end = UART1_BASE_ADDR + 0x0B5, 30 + .flags = IORESOURCE_MEM, 31 + }, { 32 + .start = MXC_INT_UART1, 33 + .end = MXC_INT_UART1, 34 + .flags = IORESOURCE_IRQ, 35 + }, 36 + }; 37 + 38 + static struct platform_device mxc_uart_device0 = { 39 + .name = "imx-uart", 40 + .id = 0, 41 + .resource = uart0, 42 + .num_resources = ARRAY_SIZE(uart0), 43 + }; 44 + 45 + static struct resource uart1[] = { 46 + { 47 + .start = UART2_BASE_ADDR, 48 + .end = UART2_BASE_ADDR + 0x0B5, 49 + .flags = IORESOURCE_MEM, 50 + }, { 51 + .start = MXC_INT_UART2, 52 + .end = MXC_INT_UART2, 53 + .flags = IORESOURCE_IRQ, 54 + }, 55 + }; 56 + 57 + static struct platform_device mxc_uart_device1 = { 58 + .name = "imx-uart", 59 + .id = 1, 60 + .resource = uart1, 61 + .num_resources = ARRAY_SIZE(uart1), 62 + }; 63 + 64 + static struct resource uart2[] = { 65 + { 66 + .start = UART3_BASE_ADDR, 67 + .end = UART3_BASE_ADDR + 0x0B5, 68 + .flags = IORESOURCE_MEM, 69 + }, { 70 + .start = MXC_INT_UART3, 71 + .end = MXC_INT_UART3, 72 + .flags = IORESOURCE_IRQ, 73 + }, 74 + }; 75 + 76 + static struct platform_device mxc_uart_device2 = { 77 + .name = "imx-uart", 78 + .id = 2, 79 + .resource = uart2, 80 + .num_resources = ARRAY_SIZE(uart2), 81 + }; 82 + 83 + static struct resource uart3[] = { 84 + { 85 + .start = UART4_BASE_ADDR, 86 + .end = UART4_BASE_ADDR + 0x0B5, 87 + .flags = IORESOURCE_MEM, 88 + }, { 89 + .start = MXC_INT_UART4, 90 + .end = MXC_INT_UART4, 91 + .flags = IORESOURCE_IRQ, 92 + }, 93 + }; 94 + 95 + static struct platform_device mxc_uart_device3 = { 96 + .name = "imx-uart", 97 + .id = 3, 98 + .resource = uart3, 99 + .num_resources = ARRAY_SIZE(uart3), 100 + }; 101 + 102 + static struct resource uart4[] = { 103 + { 104 + .start = UART5_BASE_ADDR, 105 + .end = UART5_BASE_ADDR + 0x0B5, 106 + .flags = IORESOURCE_MEM, 107 + }, { 108 + .start = MXC_INT_UART5, 109 + .end = MXC_INT_UART5, 110 + .flags = IORESOURCE_IRQ, 111 + }, 112 + }; 113 + 114 + static struct platform_device mxc_uart_device4 = { 115 + .name = "imx-uart", 116 + .id = 4, 117 + .resource = uart4, 118 + .num_resources = ARRAY_SIZE(uart4), 119 + }; 120 + 121 + /* 122 + * Register only those UARTs that physically exist 123 + */ 124 + int __init imx_init_uart(int uart_no, struct imxuart_platform_data *pdata) 125 + { 126 + switch (uart_no) { 127 + case 0: 128 + mxc_uart_device0.dev.platform_data = pdata; 129 + platform_device_register(&mxc_uart_device0); 130 + break; 131 + case 1: 132 + mxc_uart_device1.dev.platform_data = pdata; 133 + platform_device_register(&mxc_uart_device1); 134 + break; 135 + case 2: 136 + mxc_uart_device2.dev.platform_data = pdata; 137 + platform_device_register(&mxc_uart_device2); 138 + break; 139 + case 3: 140 + mxc_uart_device3.dev.platform_data = pdata; 141 + platform_device_register(&mxc_uart_device3); 142 + break; 143 + case 4: 144 + mxc_uart_device4.dev.platform_data = pdata; 145 + platform_device_register(&mxc_uart_device4); 146 + break; 147 + default: 148 + return -ENODEV; 149 + } 150 + 151 + return 0; 152 + } 153 +
+1 -1
drivers/serial/Kconfig
··· 753 753 754 754 config SERIAL_IMX 755 755 bool "IMX serial port support" 756 - depends on ARM && ARCH_IMX 756 + depends on ARM && (ARCH_IMX || ARCH_MXC) 757 757 select SERIAL_CORE 758 758 help 759 759 If you have a machine based on a Motorola IMX CPU you
+78 -18
drivers/serial/imx.c
··· 62 62 #define UBIR 0xa4 /* BRM Incremental Register */ 63 63 #define UBMR 0xa8 /* BRM Modulator Register */ 64 64 #define UBRC 0xac /* Baud Rate Count Register */ 65 + #ifdef CONFIG_ARCH_MX3 66 + #define ONEMS 0xb0 /* One Millisecond register */ 67 + #define UTS 0xb4 /* UART Test Register */ 68 + #endif 69 + #ifdef CONFIG_ARCH_IMX 65 70 #define BIPR1 0xb0 /* Incremental Preset Register 1 */ 66 71 #define BIPR2 0xb4 /* Incremental Preset Register 2 */ 67 72 #define BIPR3 0xb8 /* Incremental Preset Register 3 */ ··· 76 71 #define BMPR3 0xc8 /* BRM Modulator Register 3 */ 77 72 #define BMPR4 0xcc /* BRM Modulator Register 4 */ 78 73 #define UTS 0xd0 /* UART Test Register */ 74 + #endif 79 75 80 76 /* UART Control Register Bit Fields.*/ 81 77 #define URXD_CHARRDY (1<<15) ··· 96 90 #define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */ 97 91 #define UCR1_SNDBRK (1<<4) /* Send break */ 98 92 #define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */ 93 + #ifdef CONFIG_ARCH_IMX 99 94 #define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */ 95 + #endif 96 + #ifdef CONFIG_ARCH_MX3 97 + #define UCR1_UARTCLKEN (0) /* not present on mx2/mx3 */ 98 + #endif 100 99 #define UCR1_DOZE (1<<1) /* Doze */ 101 100 #define UCR1_UARTEN (1<<0) /* UART enabled */ 102 101 #define UCR2_ESCI (1<<15) /* Escape seq interrupt enable */ ··· 175 164 #define UTS_SOFTRST (1<<0) /* Software reset */ 176 165 177 166 /* We've been assigned a range on the "Low-density serial ports" major */ 167 + #ifdef CONFIG_ARCH_IMX 178 168 #define SERIAL_IMX_MAJOR 204 179 169 #define MINOR_START 41 170 + #define DEV_NAME "ttySMX" 171 + #define MAX_INTERNAL_IRQ IMX_IRQS 172 + #endif 173 + 174 + #ifdef CONFIG_ARCH_MX3 175 + #define SERIAL_IMX_MAJOR 207 176 + #define MINOR_START 16 177 + #define DEV_NAME "ttymxc" 178 + #define MAX_INTERNAL_IRQ MXC_MAX_INT_LINES 179 + #endif 180 180 181 181 /* 182 182 * This determines how often we check the modem status signals ··· 431 409 return IRQ_HANDLED; 432 410 } 433 411 412 + static irqreturn_t imx_int(int irq, void *dev_id) 413 + { 414 + struct imx_port *sport = dev_id; 415 + unsigned int sts; 416 + 417 + sts = readl(sport->port.membase + USR1); 418 + 419 + if (sts & USR1_RRDY) 420 + imx_rxint(irq, dev_id); 421 + 422 + if (sts & USR1_TRDY && 423 + readl(sport->port.membase + UCR1) & UCR1_TXMPTYEN) 424 + imx_txint(irq, dev_id); 425 + 426 + if (sts & USR1_RTSS) 427 + imx_rtsint(irq, dev_id); 428 + 429 + return IRQ_HANDLED; 430 + } 431 + 434 432 /* 435 433 * Return TIOCSER_TEMT when transmitter is not busy. 436 434 */ ··· 556 514 writel(temp & ~UCR4_DREN, sport->port.membase + UCR4); 557 515 558 516 /* 559 - * Allocate the IRQ 517 + * Allocate the IRQ(s) i.MX1 has three interrupts whereas later 518 + * chips only have one interrupt. 560 519 */ 561 - retval = request_irq(sport->rxirq, imx_rxint, 0, 562 - DRIVER_NAME, sport); 563 - if (retval) goto error_out1; 520 + if (sport->txirq > 0) { 521 + retval = request_irq(sport->rxirq, imx_rxint, 0, 522 + DRIVER_NAME, sport); 523 + if (retval) 524 + goto error_out1; 564 525 565 - retval = request_irq(sport->txirq, imx_txint, 0, 566 - DRIVER_NAME, sport); 567 - if (retval) goto error_out2; 526 + retval = request_irq(sport->txirq, imx_txint, 0, 527 + DRIVER_NAME, sport); 528 + if (retval) 529 + goto error_out2; 568 530 569 - retval = request_irq(sport->rtsirq, imx_rtsint, 570 - (sport->rtsirq < IMX_IRQS) ? 0 : 531 + retval = request_irq(sport->rtsirq, imx_rtsint, 532 + (sport->rtsirq < MAX_INTERNAL_IRQ) ? 0 : 571 533 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, 572 - DRIVER_NAME, sport); 573 - if (retval) goto error_out3; 534 + DRIVER_NAME, sport); 535 + if (retval) 536 + goto error_out3; 537 + } else { 538 + retval = request_irq(sport->port.irq, imx_int, 0, 539 + DRIVER_NAME, sport); 540 + if (retval) { 541 + free_irq(sport->port.irq, sport); 542 + goto error_out1; 543 + } 544 + } 574 545 575 546 /* 576 547 * Finally, clear and enable interrupts ··· 608 553 return 0; 609 554 610 555 error_out3: 611 - free_irq(sport->txirq, sport); 556 + if (sport->txirq) 557 + free_irq(sport->txirq, sport); 612 558 error_out2: 613 - free_irq(sport->rxirq, sport); 559 + if (sport->rxirq) 560 + free_irq(sport->rxirq, sport); 614 561 error_out1: 615 562 return retval; 616 563 } ··· 630 573 /* 631 574 * Free the interrupts 632 575 */ 633 - free_irq(sport->rtsirq, sport); 634 - free_irq(sport->txirq, sport); 635 - free_irq(sport->rxirq, sport); 576 + if (sport->txirq > 0) { 577 + free_irq(sport->rtsirq, sport); 578 + free_irq(sport->txirq, sport); 579 + free_irq(sport->rxirq, sport); 580 + } else 581 + free_irq(sport->port.irq, sport); 636 582 637 583 /* 638 584 * Disable all interrupts, port and break condition. ··· 1033 973 1034 974 static struct uart_driver imx_reg; 1035 975 static struct console imx_console = { 1036 - .name = "ttySMX", 976 + .name = DEV_NAME, 1037 977 .write = imx_console_write, 1038 978 .device = uart_console_device, 1039 979 .setup = imx_console_setup, ··· 1050 990 static struct uart_driver imx_reg = { 1051 991 .owner = THIS_MODULE, 1052 992 .driver_name = DRIVER_NAME, 1053 - .dev_name = "ttySMX", 993 + .dev_name = DEV_NAME, 1054 994 .major = SERIAL_IMX_MAJOR, 1055 995 .minor = MINOR_START, 1056 996 .nr = ARRAY_SIZE(imx_ports),
+32
include/asm-arm/arch-mxc/imx-uart.h
··· 1 + /* 2 + * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de> 3 + * 4 + * This program is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU General Public License 6 + * as published by the Free Software Foundation; either version 2 7 + * of the License, or (at your option) any later version. 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + * 13 + * You should have received a copy of the GNU General Public License 14 + * along with this program; if not, write to the Free Software 15 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 16 + * MA 02110-1301, USA. 17 + */ 18 + 19 + #ifndef ASMARM_ARCH_UART_H 20 + #define ASMARM_ARCH_UART_H 21 + 22 + #define IMXUART_HAVE_RTSCTS (1<<0) 23 + 24 + struct imxuart_platform_data { 25 + int (*init)(struct platform_device *pdev); 26 + int (*exit)(struct platform_device *pdev); 27 + unsigned int flags; 28 + }; 29 + 30 + int __init imx_init_uart(int uart_no, struct imxuart_platform_data *pdata); 31 + 32 + #endif