Skip to content

Commit e3d13ff

Browse files
saschahauerrschwebel
authored andcommitted
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 <[email protected]>
1 parent df1bf4b commit e3d13ff

File tree

5 files changed

+267
-22
lines changed

5 files changed

+267
-22
lines changed

arch/arm/mach-mx3/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44

55
# Object file lists.
66

7-
obj-y := mm.o time.o clock.o
7+
obj-y := mm.o time.o clock.o devices.o
88
obj-$(CONFIG_MACH_MX31ADS) += mx31ads.o

arch/arm/mach-mx3/devices.c

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/*
2+
* Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved.
3+
* Copyright 2008 Sascha Hauer, [email protected]
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+

drivers/serial/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,7 @@ config BFIN_UART3_CTSRTS
753753

754754
config SERIAL_IMX
755755
bool "IMX serial port support"
756-
depends on ARM && ARCH_IMX
756+
depends on ARM && (ARCH_IMX || ARCH_MXC)
757757
select SERIAL_CORE
758758
help
759759
If you have a machine based on a Motorola IMX CPU you

drivers/serial/imx.c

Lines changed: 80 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@
6262
#define UBIR 0xa4 /* BRM Incremental Register */
6363
#define UBMR 0xa8 /* BRM Modulator Register */
6464
#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
6570
#define BIPR1 0xb0 /* Incremental Preset Register 1 */
6671
#define BIPR2 0xb4 /* Incremental Preset Register 2 */
6772
#define BIPR3 0xb8 /* Incremental Preset Register 3 */
@@ -71,6 +76,7 @@
7176
#define BMPR3 0xc8 /* BRM Modulator Register 3 */
7277
#define BMPR4 0xcc /* BRM Modulator Register 4 */
7378
#define UTS 0xd0 /* UART Test Register */
79+
#endif
7480

7581
/* UART Control Register Bit Fields.*/
7682
#define URXD_CHARRDY (1<<15)
@@ -90,7 +96,12 @@
9096
#define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */
9197
#define UCR1_SNDBRK (1<<4) /* Send break */
9298
#define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */
99+
#ifdef CONFIG_ARCH_IMX
93100
#define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */
101+
#endif
102+
#ifdef CONFIG_ARCH_MX3
103+
#define UCR1_UARTCLKEN (0) /* not present on mx2/mx3 */
104+
#endif
94105
#define UCR1_DOZE (1<<1) /* Doze */
95106
#define UCR1_UARTEN (1<<0) /* UART enabled */
96107
#define UCR2_ESCI (1<<15) /* Escape seq interrupt enable */
@@ -164,8 +175,19 @@
164175
#define UTS_SOFTRST (1<<0) /* Software reset */
165176

166177
/* We've been assigned a range on the "Low-density serial ports" major */
178+
#ifdef CONFIG_ARCH_IMX
167179
#define SERIAL_IMX_MAJOR 204
168180
#define MINOR_START 41
181+
#define DEV_NAME "ttySMX"
182+
#define MAX_INTERNAL_IRQ IMX_IRQS
183+
#endif
184+
185+
#ifdef CONFIG_ARCH_MX3
186+
#define SERIAL_IMX_MAJOR 207
187+
#define MINOR_START 16
188+
#define DEV_NAME "ttymxc"
189+
#define MAX_INTERNAL_IRQ MXC_MAX_INT_LINES
190+
#endif
169191

170192
/*
171193
* This determines how often we check the modem status signals
@@ -409,6 +431,26 @@ static irqreturn_t imx_rxint(int irq, void *dev_id)
409431
return IRQ_HANDLED;
410432
}
411433

434+
static irqreturn_t imx_int(int irq, void *dev_id)
435+
{
436+
struct imx_port *sport = dev_id;
437+
unsigned int sts;
438+
439+
sts = readl(sport->port.membase + USR1);
440+
441+
if (sts & USR1_RRDY)
442+
imx_rxint(irq, dev_id);
443+
444+
if (sts & USR1_TRDY &&
445+
readl(sport->port.membase + UCR1) & UCR1_TXMPTYEN)
446+
imx_txint(irq, dev_id);
447+
448+
if (sts & USR1_RTSS)
449+
imx_rtsint(irq, dev_id);
450+
451+
return IRQ_HANDLED;
452+
}
453+
412454
/*
413455
* Return TIOCSER_TEMT when transmitter is not busy.
414456
*/
@@ -514,21 +556,34 @@ static int imx_startup(struct uart_port *port)
514556
writel(temp & ~UCR4_DREN, sport->port.membase + UCR4);
515557

516558
/*
517-
* Allocate the IRQ
559+
* Allocate the IRQ(s) i.MX1 has three interrupts whereas later
560+
* chips only have one interrupt.
518561
*/
519-
retval = request_irq(sport->rxirq, imx_rxint, 0,
520-
DRIVER_NAME, sport);
521-
if (retval) goto error_out1;
522-
523-
retval = request_irq(sport->txirq, imx_txint, 0,
524-
DRIVER_NAME, sport);
525-
if (retval) goto error_out2;
526-
527-
retval = request_irq(sport->rtsirq, imx_rtsint,
528-
(sport->rtsirq < IMX_IRQS) ? 0 :
562+
if (sport->txirq > 0) {
563+
retval = request_irq(sport->rxirq, imx_rxint, 0,
564+
DRIVER_NAME, sport);
565+
if (retval)
566+
goto error_out1;
567+
568+
retval = request_irq(sport->txirq, imx_txint, 0,
569+
DRIVER_NAME, sport);
570+
if (retval)
571+
goto error_out2;
572+
573+
retval = request_irq(sport->rtsirq, imx_rtsint,
574+
(sport->rtsirq < MAX_INTERNAL_IRQ) ? 0 :
529575
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
530-
DRIVER_NAME, sport);
531-
if (retval) goto error_out3;
576+
DRIVER_NAME, sport);
577+
if (retval)
578+
goto error_out3;
579+
} else {
580+
retval = request_irq(sport->port.irq, imx_int, 0,
581+
DRIVER_NAME, sport);
582+
if (retval) {
583+
free_irq(sport->port.irq, sport);
584+
goto error_out1;
585+
}
586+
}
532587

533588
/*
534589
* Finally, clear and enable interrupts
@@ -553,9 +608,11 @@ static int imx_startup(struct uart_port *port)
553608
return 0;
554609

555610
error_out3:
556-
free_irq(sport->txirq, sport);
611+
if (sport->txirq)
612+
free_irq(sport->txirq, sport);
557613
error_out2:
558-
free_irq(sport->rxirq, sport);
614+
if (sport->rxirq)
615+
free_irq(sport->rxirq, sport);
559616
error_out1:
560617
return retval;
561618
}
@@ -573,9 +630,12 @@ static void imx_shutdown(struct uart_port *port)
573630
/*
574631
* Free the interrupts
575632
*/
576-
free_irq(sport->rtsirq, sport);
577-
free_irq(sport->txirq, sport);
578-
free_irq(sport->rxirq, sport);
633+
if (sport->txirq > 0) {
634+
free_irq(sport->rtsirq, sport);
635+
free_irq(sport->txirq, sport);
636+
free_irq(sport->rxirq, sport);
637+
} else
638+
free_irq(sport->port.irq, sport);
579639

580640
/*
581641
* Disable all interrupts, port and break condition.
@@ -973,7 +1033,7 @@ imx_console_setup(struct console *co, char *options)
9731033

9741034
static struct uart_driver imx_reg;
9751035
static struct console imx_console = {
976-
.name = "ttySMX",
1036+
.name = DEV_NAME,
9771037
.write = imx_console_write,
9781038
.device = uart_console_device,
9791039
.setup = imx_console_setup,
@@ -990,7 +1050,7 @@ static struct console imx_console = {
9901050
static struct uart_driver imx_reg = {
9911051
.owner = THIS_MODULE,
9921052
.driver_name = DRIVER_NAME,
993-
.dev_name = "ttySMX",
1053+
.dev_name = DEV_NAME,
9941054
.major = SERIAL_IMX_MAJOR,
9951055
.minor = MINOR_START,
9961056
.nr = ARRAY_SIZE(imx_ports),
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (C) 2008 by Sascha Hauer <[email protected]>
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

0 commit comments

Comments
 (0)