diff options
author | Kevin Hilman <khilman@deeprootsystems.com> | 2009-04-14 09:04:26 -0400 |
---|---|---|
committer | Kevin Hilman <khilman@deeprootsystems.com> | 2009-04-27 12:49:45 -0400 |
commit | 617b925f94e0126841164ffd40dd3a8879502b57 (patch) | |
tree | fd078ef27fb9c97aa4d572f02f78b9832471d1e2 /arch/arm/mach-davinci/serial.c | |
parent | f9337405b21bafb1c1a24316b3e43b3d3d697925 (diff) |
davinci: serial: generalize for more SoCs
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Diffstat (limited to 'arch/arm/mach-davinci/serial.c')
-rw-r--r-- | arch/arm/mach-davinci/serial.c | 95 |
1 files changed, 78 insertions, 17 deletions
diff --git a/arch/arm/mach-davinci/serial.c b/arch/arm/mach-davinci/serial.c index 3010f997125..69507579652 100644 --- a/arch/arm/mach-davinci/serial.c +++ b/arch/arm/mach-davinci/serial.c | |||
@@ -32,32 +32,47 @@ | |||
32 | #include <mach/hardware.h> | 32 | #include <mach/hardware.h> |
33 | #include <mach/serial.h> | 33 | #include <mach/serial.h> |
34 | #include <mach/irqs.h> | 34 | #include <mach/irqs.h> |
35 | #include <mach/cputype.h> | ||
36 | #include "clock.h" | ||
35 | 37 | ||
36 | #define UART_DAVINCI_PWREMU 0x0c | 38 | static inline unsigned int serial_read_reg(struct plat_serial8250_port *up, |
37 | 39 | int offset) | |
38 | static inline unsigned int davinci_serial_in(struct plat_serial8250_port *up, | ||
39 | int offset) | ||
40 | { | 40 | { |
41 | offset <<= up->regshift; | 41 | offset <<= up->regshift; |
42 | return (unsigned int)__raw_readb(up->membase + offset); | 42 | return (unsigned int)__raw_readl(IO_ADDRESS(up->mapbase) + offset); |
43 | } | 43 | } |
44 | 44 | ||
45 | static inline void davinci_serial_outp(struct plat_serial8250_port *p, | 45 | static inline void serial_write_reg(struct plat_serial8250_port *p, int offset, |
46 | int offset, int value) | 46 | int value) |
47 | { | 47 | { |
48 | offset <<= p->regshift; | 48 | offset <<= p->regshift; |
49 | __raw_writeb(value, p->membase + offset); | 49 | __raw_writel(value, IO_ADDRESS(p->mapbase) + offset); |
50 | } | 50 | } |
51 | 51 | ||
52 | static struct plat_serial8250_port serial_platform_data[] = { | 52 | static struct plat_serial8250_port serial_platform_data[] = { |
53 | { | 53 | { |
54 | .membase = (char *)IO_ADDRESS(DAVINCI_UART0_BASE), | 54 | .mapbase = DAVINCI_UART0_BASE, |
55 | .mapbase = (unsigned long)DAVINCI_UART0_BASE, | ||
56 | .irq = IRQ_UARTINT0, | 55 | .irq = IRQ_UARTINT0, |
57 | .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, | 56 | .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | |
57 | UPF_IOREMAP, | ||
58 | .iotype = UPIO_MEM, | ||
59 | .regshift = 2, | ||
60 | }, | ||
61 | { | ||
62 | .mapbase = DAVINCI_UART1_BASE, | ||
63 | .irq = IRQ_UARTINT1, | ||
64 | .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | | ||
65 | UPF_IOREMAP, | ||
66 | .iotype = UPIO_MEM, | ||
67 | .regshift = 2, | ||
68 | }, | ||
69 | { | ||
70 | .mapbase = DAVINCI_UART2_BASE, | ||
71 | .irq = IRQ_UARTINT2, | ||
72 | .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | | ||
73 | UPF_IOREMAP, | ||
58 | .iotype = UPIO_MEM, | 74 | .iotype = UPIO_MEM, |
59 | .regshift = 2, | 75 | .regshift = 2, |
60 | .uartclk = 27000000, | ||
61 | }, | 76 | }, |
62 | { | 77 | { |
63 | .flags = 0 | 78 | .flags = 0 |
@@ -74,22 +89,68 @@ static struct platform_device serial_device = { | |||
74 | 89 | ||
75 | static void __init davinci_serial_reset(struct plat_serial8250_port *p) | 90 | static void __init davinci_serial_reset(struct plat_serial8250_port *p) |
76 | { | 91 | { |
77 | /* reset both transmitter and receiver: bits 14,13 = UTRST, URRST */ | ||
78 | unsigned int pwremu = 0; | 92 | unsigned int pwremu = 0; |
79 | 93 | ||
80 | davinci_serial_outp(p, UART_IER, 0); /* disable all interrupts */ | 94 | serial_write_reg(p, UART_IER, 0); /* disable all interrupts */ |
81 | 95 | ||
82 | davinci_serial_outp(p, UART_DAVINCI_PWREMU, pwremu); | 96 | /* reset both transmitter and receiver: bits 14,13 = UTRST, URRST */ |
97 | serial_write_reg(p, UART_DAVINCI_PWREMU, pwremu); | ||
83 | mdelay(10); | 98 | mdelay(10); |
84 | 99 | ||
85 | pwremu |= (0x3 << 13); | 100 | pwremu |= (0x3 << 13); |
86 | pwremu |= 0x1; | 101 | pwremu |= 0x1; |
87 | davinci_serial_outp(p, UART_DAVINCI_PWREMU, pwremu); | 102 | serial_write_reg(p, UART_DAVINCI_PWREMU, pwremu); |
103 | |||
104 | if (cpu_is_davinci_dm646x()) | ||
105 | serial_write_reg(p, UART_DM646X_SCR, | ||
106 | UART_DM646X_SCR_TX_WATERMARK); | ||
107 | } | ||
108 | |||
109 | void __init davinci_serial_init(struct davinci_uart_config *info) | ||
110 | { | ||
111 | int i; | ||
112 | char name[16]; | ||
113 | struct clk *uart_clk; | ||
114 | struct device *dev = &serial_device.dev; | ||
115 | |||
116 | /* | ||
117 | * Make sure the serial ports are muxed on at this point. | ||
118 | * You have to mux them off in device drivers later on | ||
119 | * if not needed. | ||
120 | */ | ||
121 | for (i = 0; i < DAVINCI_MAX_NR_UARTS; i++) { | ||
122 | struct plat_serial8250_port *p = serial_platform_data + i; | ||
123 | |||
124 | if (!(info->enabled_uarts & (1 << i))) { | ||
125 | p->flags = 0; | ||
126 | continue; | ||
127 | } | ||
128 | |||
129 | if (cpu_is_davinci_dm646x()) | ||
130 | p->iotype = UPIO_MEM32; | ||
131 | |||
132 | if (cpu_is_davinci_dm355()) { | ||
133 | if (i == 2) { | ||
134 | p->mapbase = (unsigned long)DM355_UART2_BASE; | ||
135 | p->irq = IRQ_DM355_UARTINT2; | ||
136 | } | ||
137 | } | ||
138 | |||
139 | sprintf(name, "uart%d", i); | ||
140 | uart_clk = clk_get(dev, name); | ||
141 | if (IS_ERR(uart_clk)) | ||
142 | printk(KERN_ERR "%s:%d: failed to get UART%d clock\n", | ||
143 | __func__, __LINE__, i); | ||
144 | else { | ||
145 | clk_enable(uart_clk); | ||
146 | p->uartclk = clk_get_rate(uart_clk); | ||
147 | davinci_serial_reset(p); | ||
148 | } | ||
149 | } | ||
88 | } | 150 | } |
89 | 151 | ||
90 | static int __init davinci_init(void) | 152 | static int __init davinci_init(void) |
91 | { | 153 | { |
92 | davinci_serial_reset(&serial_platform_data[0]); | ||
93 | return platform_device_register(&serial_device); | 154 | return platform_device_register(&serial_device); |
94 | } | 155 | } |
95 | 156 | ||