aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/nand/Kconfig2
-rw-r--r--drivers/net/Kconfig2
-rw-r--r--drivers/spi/Kconfig6
-rw-r--r--drivers/tty/serial/Kconfig15
-rw-r--r--drivers/tty/serial/Makefile1
-rw-r--r--drivers/tty/serial/mxs-auart.c798
-rw-r--r--drivers/usb/gadget/fsl_mxc_udc.c2
-rw-r--r--drivers/usb/host/ehci-mxc.c5
-rw-r--r--drivers/video/Kconfig9
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/mxsfb.c919
11 files changed, 1749 insertions, 11 deletions
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index c89592239bc7..450afc5df0bd 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -476,7 +476,7 @@ config MTD_NAND_MPC5121_NFC
476 476
477config MTD_NAND_MXC 477config MTD_NAND_MXC
478 tristate "MXC NAND support" 478 tristate "MXC NAND support"
479 depends on ARCH_MX2 || ARCH_MX25 || ARCH_MX3 || ARCH_MX51 479 depends on IMX_HAVE_PLATFORM_MXC_NAND
480 help 480 help
481 This enables the driver for the NAND flash controller on the 481 This enables the driver for the NAND flash controller on the
482 MXC processors. 482 MXC processors.
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 03823327db25..9928115496e6 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1944,7 +1944,7 @@ config 68360_ENET
1944config FEC 1944config FEC
1945 bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)" 1945 bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
1946 depends on M523x || M527x || M5272 || M528x || M520x || M532x || \ 1946 depends on M523x || M527x || M5272 || M528x || M520x || M532x || \
1947 MACH_MX27 || ARCH_MX35 || ARCH_MX25 || ARCH_MX5 || SOC_IMX28 1947 IMX_HAVE_PLATFORM_FEC || SOC_IMX28
1948 select PHYLIB 1948 select PHYLIB
1949 help 1949 help
1950 Say Y here if you want to use the built-in 10/100 Fast ethernet 1950 Say Y here if you want to use the built-in 10/100 Fast ethernet
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index bb233a9cbad2..996cf0359385 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -161,13 +161,13 @@ config SPI_IMX_VER_0_0
161 def_bool y if SOC_IMX21 || SOC_IMX27 161 def_bool y if SOC_IMX21 || SOC_IMX27
162 162
163config SPI_IMX_VER_0_4 163config SPI_IMX_VER_0_4
164 def_bool y if ARCH_MX31 164 def_bool y if SOC_IMX31
165 165
166config SPI_IMX_VER_0_7 166config SPI_IMX_VER_0_7
167 def_bool y if ARCH_MX25 || ARCH_MX35 || ARCH_MX51 || ARCH_MX53 167 def_bool y if ARCH_MX25 || SOC_IMX35 || SOC_IMX51 || SOC_IMX53
168 168
169config SPI_IMX_VER_2_3 169config SPI_IMX_VER_2_3
170 def_bool y if ARCH_MX51 || ARCH_MX53 170 def_bool y if SOC_IMX51 || SOC_IMX53
171 171
172config SPI_IMX 172config SPI_IMX
173 tristate "Freescale i.MX SPI controllers" 173 tristate "Freescale i.MX SPI controllers"
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 2b8334601c8b..5c4b3475621f 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1596,4 +1596,19 @@ config SERIAL_PCH_UART
1596 This driver is for PCH(Platform controller Hub) UART of Intel EG20T 1596 This driver is for PCH(Platform controller Hub) UART of Intel EG20T
1597 which is an IOH(Input/Output Hub) for x86 embedded processor. 1597 which is an IOH(Input/Output Hub) for x86 embedded processor.
1598 Enabling PCH_DMA, this PCH UART works as DMA mode. 1598 Enabling PCH_DMA, this PCH UART works as DMA mode.
1599
1600config SERIAL_MXS_AUART
1601 depends on ARCH_MXS
1602 tristate "MXS AUART support"
1603 select SERIAL_CORE
1604 help
1605 This driver supports the MXS Application UART (AUART) port.
1606
1607config SERIAL_MXS_AUART_CONSOLE
1608 bool "MXS AUART console support"
1609 depends on SERIAL_MXS_AUART=y
1610 select SERIAL_CORE_CONSOLE
1611 help
1612 Enable a MXS AUART port to be the system console.
1613
1599endmenu 1614endmenu
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 8ea92e9c73b0..c8550719de5a 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -92,3 +92,4 @@ obj-$(CONFIG_SERIAL_MRST_MAX3110) += mrst_max3110.o
92obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o 92obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o
93obj-$(CONFIG_SERIAL_IFX6X60) += ifx6x60.o 93obj-$(CONFIG_SERIAL_IFX6X60) += ifx6x60.o
94obj-$(CONFIG_SERIAL_PCH_UART) += pch_uart.o 94obj-$(CONFIG_SERIAL_PCH_UART) += pch_uart.o
95obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
new file mode 100644
index 000000000000..7e02c9c344fe
--- /dev/null
+++ b/drivers/tty/serial/mxs-auart.c
@@ -0,0 +1,798 @@
1/*
2 * Freescale STMP37XX/STMP378X Application UART driver
3 *
4 * Author: dmitry pervushin <dimka@embeddedalley.com>
5 *
6 * Copyright 2008-2010 Freescale Semiconductor, Inc.
7 * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
8 *
9 * The code contained herein is licensed under the GNU General Public
10 * License. You may obtain a copy of the GNU General Public License
11 * Version 2 or later at the following locations:
12 *
13 * http://www.opensource.org/licenses/gpl-license.html
14 * http://www.gnu.org/copyleft/gpl.html
15 */
16
17#include <linux/kernel.h>
18#include <linux/errno.h>
19#include <linux/init.h>
20#include <linux/console.h>
21#include <linux/interrupt.h>
22#include <linux/module.h>
23#include <linux/slab.h>
24#include <linux/wait.h>
25#include <linux/tty.h>
26#include <linux/tty_driver.h>
27#include <linux/tty_flip.h>
28#include <linux/serial.h>
29#include <linux/serial_core.h>
30#include <linux/platform_device.h>
31#include <linux/device.h>
32#include <linux/clk.h>
33#include <linux/delay.h>
34#include <linux/io.h>
35
36#include <asm/cacheflush.h>
37
38#define MXS_AUART_PORTS 5
39
40#define AUART_CTRL0 0x00000000
41#define AUART_CTRL0_SET 0x00000004
42#define AUART_CTRL0_CLR 0x00000008
43#define AUART_CTRL0_TOG 0x0000000c
44#define AUART_CTRL1 0x00000010
45#define AUART_CTRL1_SET 0x00000014
46#define AUART_CTRL1_CLR 0x00000018
47#define AUART_CTRL1_TOG 0x0000001c
48#define AUART_CTRL2 0x00000020
49#define AUART_CTRL2_SET 0x00000024
50#define AUART_CTRL2_CLR 0x00000028
51#define AUART_CTRL2_TOG 0x0000002c
52#define AUART_LINECTRL 0x00000030
53#define AUART_LINECTRL_SET 0x00000034
54#define AUART_LINECTRL_CLR 0x00000038
55#define AUART_LINECTRL_TOG 0x0000003c
56#define AUART_LINECTRL2 0x00000040
57#define AUART_LINECTRL2_SET 0x00000044
58#define AUART_LINECTRL2_CLR 0x00000048
59#define AUART_LINECTRL2_TOG 0x0000004c
60#define AUART_INTR 0x00000050
61#define AUART_INTR_SET 0x00000054
62#define AUART_INTR_CLR 0x00000058
63#define AUART_INTR_TOG 0x0000005c
64#define AUART_DATA 0x00000060
65#define AUART_STAT 0x00000070
66#define AUART_DEBUG 0x00000080
67#define AUART_VERSION 0x00000090
68#define AUART_AUTOBAUD 0x000000a0
69
70#define AUART_CTRL0_SFTRST (1 << 31)
71#define AUART_CTRL0_CLKGATE (1 << 30)
72
73#define AUART_CTRL2_CTSEN (1 << 15)
74#define AUART_CTRL2_RTS (1 << 11)
75#define AUART_CTRL2_RXE (1 << 9)
76#define AUART_CTRL2_TXE (1 << 8)
77#define AUART_CTRL2_UARTEN (1 << 0)
78
79#define AUART_LINECTRL_BAUD_DIVINT_SHIFT 16
80#define AUART_LINECTRL_BAUD_DIVINT_MASK 0xffff0000
81#define AUART_LINECTRL_BAUD_DIVINT(v) (((v) & 0xffff) << 16)
82#define AUART_LINECTRL_BAUD_DIVFRAC_SHIFT 8
83#define AUART_LINECTRL_BAUD_DIVFRAC_MASK 0x00003f00
84#define AUART_LINECTRL_BAUD_DIVFRAC(v) (((v) & 0x3f) << 8)
85#define AUART_LINECTRL_WLEN_MASK 0x00000060
86#define AUART_LINECTRL_WLEN(v) (((v) & 0x3) << 5)
87#define AUART_LINECTRL_FEN (1 << 4)
88#define AUART_LINECTRL_STP2 (1 << 3)
89#define AUART_LINECTRL_EPS (1 << 2)
90#define AUART_LINECTRL_PEN (1 << 1)
91#define AUART_LINECTRL_BRK (1 << 0)
92
93#define AUART_INTR_RTIEN (1 << 22)
94#define AUART_INTR_TXIEN (1 << 21)
95#define AUART_INTR_RXIEN (1 << 20)
96#define AUART_INTR_CTSMIEN (1 << 17)
97#define AUART_INTR_RTIS (1 << 6)
98#define AUART_INTR_TXIS (1 << 5)
99#define AUART_INTR_RXIS (1 << 4)
100#define AUART_INTR_CTSMIS (1 << 1)
101
102#define AUART_STAT_BUSY (1 << 29)
103#define AUART_STAT_CTS (1 << 28)
104#define AUART_STAT_TXFE (1 << 27)
105#define AUART_STAT_TXFF (1 << 25)
106#define AUART_STAT_RXFE (1 << 24)
107#define AUART_STAT_OERR (1 << 19)
108#define AUART_STAT_BERR (1 << 18)
109#define AUART_STAT_PERR (1 << 17)
110#define AUART_STAT_FERR (1 << 16)
111
112static struct uart_driver auart_driver;
113
114struct mxs_auart_port {
115 struct uart_port port;
116
117 unsigned int flags;
118 unsigned int ctrl;
119
120 unsigned int irq;
121
122 struct clk *clk;
123 struct device *dev;
124};
125
126static void mxs_auart_stop_tx(struct uart_port *u);
127
128#define to_auart_port(u) container_of(u, struct mxs_auart_port, port)
129
130static inline void mxs_auart_tx_chars(struct mxs_auart_port *s)
131{
132 struct circ_buf *xmit = &s->port.state->xmit;
133
134 while (!(readl(s->port.membase + AUART_STAT) &
135 AUART_STAT_TXFF)) {
136 if (s->port.x_char) {
137 s->port.icount.tx++;
138 writel(s->port.x_char,
139 s->port.membase + AUART_DATA);
140 s->port.x_char = 0;
141 continue;
142 }
143 if (!uart_circ_empty(xmit) && !uart_tx_stopped(&s->port)) {
144 s->port.icount.tx++;
145 writel(xmit->buf[xmit->tail],
146 s->port.membase + AUART_DATA);
147 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
148 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
149 uart_write_wakeup(&s->port);
150 } else
151 break;
152 }
153 if (uart_circ_empty(&(s->port.state->xmit)))
154 writel(AUART_INTR_TXIEN,
155 s->port.membase + AUART_INTR_CLR);
156 else
157 writel(AUART_INTR_TXIEN,
158 s->port.membase + AUART_INTR_SET);
159
160 if (uart_tx_stopped(&s->port))
161 mxs_auart_stop_tx(&s->port);
162}
163
164static void mxs_auart_rx_char(struct mxs_auart_port *s)
165{
166 int flag;
167 u32 stat;
168 u8 c;
169
170 c = readl(s->port.membase + AUART_DATA);
171 stat = readl(s->port.membase + AUART_STAT);
172
173 flag = TTY_NORMAL;
174 s->port.icount.rx++;
175
176 if (stat & AUART_STAT_BERR) {
177 s->port.icount.brk++;
178 if (uart_handle_break(&s->port))
179 goto out;
180 } else if (stat & AUART_STAT_PERR) {
181 s->port.icount.parity++;
182 } else if (stat & AUART_STAT_FERR) {
183 s->port.icount.frame++;
184 }
185
186 /*
187 * Mask off conditions which should be ingored.
188 */
189 stat &= s->port.read_status_mask;
190
191 if (stat & AUART_STAT_BERR) {
192 flag = TTY_BREAK;
193 } else if (stat & AUART_STAT_PERR)
194 flag = TTY_PARITY;
195 else if (stat & AUART_STAT_FERR)
196 flag = TTY_FRAME;
197
198 if (stat & AUART_STAT_OERR)
199 s->port.icount.overrun++;
200
201 if (uart_handle_sysrq_char(&s->port, c))
202 goto out;
203
204 uart_insert_char(&s->port, stat, AUART_STAT_OERR, c, flag);
205out:
206 writel(stat, s->port.membase + AUART_STAT);
207}
208
209static void mxs_auart_rx_chars(struct mxs_auart_port *s)
210{
211 struct tty_struct *tty = s->port.state->port.tty;
212 u32 stat = 0;
213
214 for (;;) {
215 stat = readl(s->port.membase + AUART_STAT);
216 if (stat & AUART_STAT_RXFE)
217 break;
218 mxs_auart_rx_char(s);
219 }
220
221 writel(stat, s->port.membase + AUART_STAT);
222 tty_flip_buffer_push(tty);
223}
224
225static int mxs_auart_request_port(struct uart_port *u)
226{
227 return 0;
228}
229
230static int mxs_auart_verify_port(struct uart_port *u,
231 struct serial_struct *ser)
232{
233 if (u->type != PORT_UNKNOWN && u->type != PORT_IMX)
234 return -EINVAL;
235 return 0;
236}
237
238static void mxs_auart_config_port(struct uart_port *u, int flags)
239{
240}
241
242static const char *mxs_auart_type(struct uart_port *u)
243{
244 struct mxs_auart_port *s = to_auart_port(u);
245
246 return dev_name(s->dev);
247}
248
249static void mxs_auart_release_port(struct uart_port *u)
250{
251}
252
253static void mxs_auart_set_mctrl(struct uart_port *u, unsigned mctrl)
254{
255 struct mxs_auart_port *s = to_auart_port(u);
256
257 u32 ctrl = readl(u->membase + AUART_CTRL2);
258
259 ctrl &= ~AUART_CTRL2_RTS;
260 if (mctrl & TIOCM_RTS)
261 ctrl |= AUART_CTRL2_RTS;
262 s->ctrl = mctrl;
263 writel(ctrl, u->membase + AUART_CTRL2);
264}
265
266static u32 mxs_auart_get_mctrl(struct uart_port *u)
267{
268 struct mxs_auart_port *s = to_auart_port(u);
269 u32 stat = readl(u->membase + AUART_STAT);
270 int ctrl2 = readl(u->membase + AUART_CTRL2);
271 u32 mctrl = s->ctrl;
272
273 mctrl &= ~TIOCM_CTS;
274 if (stat & AUART_STAT_CTS)
275 mctrl |= TIOCM_CTS;
276
277 if (ctrl2 & AUART_CTRL2_RTS)
278 mctrl |= TIOCM_RTS;
279
280 return mctrl;
281}
282
283static void mxs_auart_settermios(struct uart_port *u,
284 struct ktermios *termios,
285 struct ktermios *old)
286{
287 u32 bm, ctrl, ctrl2, div;
288 unsigned int cflag, baud;
289
290 cflag = termios->c_cflag;
291
292 ctrl = AUART_LINECTRL_FEN;
293 ctrl2 = readl(u->membase + AUART_CTRL2);
294
295 /* byte size */
296 switch (cflag & CSIZE) {
297 case CS5:
298 bm = 0;
299 break;
300 case CS6:
301 bm = 1;
302 break;
303 case CS7:
304 bm = 2;
305 break;
306 case CS8:
307 bm = 3;
308 break;
309 default:
310 return;
311 }
312
313 ctrl |= AUART_LINECTRL_WLEN(bm);
314
315 /* parity */
316 if (cflag & PARENB) {
317 ctrl |= AUART_LINECTRL_PEN;
318 if ((cflag & PARODD) == 0)
319 ctrl |= AUART_LINECTRL_EPS;
320 }
321
322 u->read_status_mask = 0;
323
324 if (termios->c_iflag & INPCK)
325 u->read_status_mask |= AUART_STAT_PERR;
326 if (termios->c_iflag & (BRKINT | PARMRK))
327 u->read_status_mask |= AUART_STAT_BERR;
328
329 /*
330 * Characters to ignore
331 */
332 u->ignore_status_mask = 0;
333 if (termios->c_iflag & IGNPAR)
334 u->ignore_status_mask |= AUART_STAT_PERR;
335 if (termios->c_iflag & IGNBRK) {
336 u->ignore_status_mask |= AUART_STAT_BERR;
337 /*
338 * If we're ignoring parity and break indicators,
339 * ignore overruns too (for real raw support).
340 */
341 if (termios->c_iflag & IGNPAR)
342 u->ignore_status_mask |= AUART_STAT_OERR;
343 }
344
345 /*
346 * ignore all characters if CREAD is not set
347 */
348 if (cflag & CREAD)
349 ctrl2 |= AUART_CTRL2_RXE;
350 else
351 ctrl2 &= ~AUART_CTRL2_RXE;
352
353 /* figure out the stop bits requested */
354 if (cflag & CSTOPB)
355 ctrl |= AUART_LINECTRL_STP2;
356
357 /* figure out the hardware flow control settings */
358 if (cflag & CRTSCTS)
359 ctrl2 |= AUART_CTRL2_CTSEN;
360 else
361 ctrl2 &= ~AUART_CTRL2_CTSEN;
362
363 /* set baud rate */
364 baud = uart_get_baud_rate(u, termios, old, 0, u->uartclk);
365 div = u->uartclk * 32 / baud;
366 ctrl |= AUART_LINECTRL_BAUD_DIVFRAC(div & 0x3F);
367 ctrl |= AUART_LINECTRL_BAUD_DIVINT(div >> 6);
368
369 writel(ctrl, u->membase + AUART_LINECTRL);
370 writel(ctrl2, u->membase + AUART_CTRL2);
371}
372
373static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
374{
375 u32 istatus, istat;
376 struct mxs_auart_port *s = context;
377 u32 stat = readl(s->port.membase + AUART_STAT);
378
379 istatus = istat = readl(s->port.membase + AUART_INTR);
380
381 if (istat & AUART_INTR_CTSMIS) {
382 uart_handle_cts_change(&s->port, stat & AUART_STAT_CTS);
383 writel(AUART_INTR_CTSMIS,
384 s->port.membase + AUART_INTR_CLR);
385 istat &= ~AUART_INTR_CTSMIS;
386 }
387
388 if (istat & (AUART_INTR_RTIS | AUART_INTR_RXIS)) {
389 mxs_auart_rx_chars(s);
390 istat &= ~(AUART_INTR_RTIS | AUART_INTR_RXIS);
391 }
392
393 if (istat & AUART_INTR_TXIS) {
394 mxs_auart_tx_chars(s);
395 istat &= ~AUART_INTR_TXIS;
396 }
397
398 writel(istatus & (AUART_INTR_RTIS
399 | AUART_INTR_TXIS
400 | AUART_INTR_RXIS
401 | AUART_INTR_CTSMIS),
402 s->port.membase + AUART_INTR_CLR);
403
404 return IRQ_HANDLED;
405}
406
407static void mxs_auart_reset(struct uart_port *u)
408{
409 int i;
410 unsigned int reg;
411
412 writel(AUART_CTRL0_SFTRST, u->membase + AUART_CTRL0_CLR);
413
414 for (i = 0; i < 10000; i++) {
415 reg = readl(u->membase + AUART_CTRL0);
416 if (!(reg & AUART_CTRL0_SFTRST))
417 break;
418 udelay(3);
419 }
420 writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
421}
422
423static int mxs_auart_startup(struct uart_port *u)
424{
425 struct mxs_auart_port *s = to_auart_port(u);
426
427 clk_enable(s->clk);
428
429 writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
430
431 writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_SET);
432
433 writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
434 u->membase + AUART_INTR);
435
436 /*
437 * Enable fifo so all four bytes of a DMA word are written to
438 * output (otherwise, only the LSB is written, ie. 1 in 4 bytes)
439 */
440 writel(AUART_LINECTRL_FEN, u->membase + AUART_LINECTRL_SET);
441
442 return 0;
443}
444
445static void mxs_auart_shutdown(struct uart_port *u)
446{
447 struct mxs_auart_port *s = to_auart_port(u);
448
449 writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR);
450
451 writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET);
452
453 writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
454 u->membase + AUART_INTR_CLR);
455
456 clk_disable(s->clk);
457}
458
459static unsigned int mxs_auart_tx_empty(struct uart_port *u)
460{
461 if (readl(u->membase + AUART_STAT) & AUART_STAT_TXFE)
462 return TIOCSER_TEMT;
463 else
464 return 0;
465}
466
467static void mxs_auart_start_tx(struct uart_port *u)
468{
469 struct mxs_auart_port *s = to_auart_port(u);
470
471 /* enable transmitter */
472 writel(AUART_CTRL2_TXE, u->membase + AUART_CTRL2_SET);
473
474 mxs_auart_tx_chars(s);
475}
476
477static void mxs_auart_stop_tx(struct uart_port *u)
478{
479 writel(AUART_CTRL2_TXE, u->membase + AUART_CTRL2_CLR);
480}
481
482static void mxs_auart_stop_rx(struct uart_port *u)
483{
484 writel(AUART_CTRL2_RXE, u->membase + AUART_CTRL2_CLR);
485}
486
487static void mxs_auart_break_ctl(struct uart_port *u, int ctl)
488{
489 if (ctl)
490 writel(AUART_LINECTRL_BRK,
491 u->membase + AUART_LINECTRL_SET);
492 else
493 writel(AUART_LINECTRL_BRK,
494 u->membase + AUART_LINECTRL_CLR);
495}
496
497static void mxs_auart_enable_ms(struct uart_port *port)
498{
499 /* just empty */
500}
501
502static struct uart_ops mxs_auart_ops = {
503 .tx_empty = mxs_auart_tx_empty,
504 .start_tx = mxs_auart_start_tx,
505 .stop_tx = mxs_auart_stop_tx,
506 .stop_rx = mxs_auart_stop_rx,
507 .enable_ms = mxs_auart_enable_ms,
508 .break_ctl = mxs_auart_break_ctl,
509 .set_mctrl = mxs_auart_set_mctrl,
510 .get_mctrl = mxs_auart_get_mctrl,
511 .startup = mxs_auart_startup,
512 .shutdown = mxs_auart_shutdown,
513 .set_termios = mxs_auart_settermios,
514 .type = mxs_auart_type,
515 .release_port = mxs_auart_release_port,
516 .request_port = mxs_auart_request_port,
517 .config_port = mxs_auart_config_port,
518 .verify_port = mxs_auart_verify_port,
519};
520
521static struct mxs_auart_port *auart_port[MXS_AUART_PORTS];
522
523#ifdef CONFIG_SERIAL_MXS_AUART_CONSOLE
524static void mxs_auart_console_putchar(struct uart_port *port, int ch)
525{
526 unsigned int to = 1000;
527
528 while (readl(port->membase + AUART_STAT) & AUART_STAT_TXFF) {
529 if (!to--)
530 break;
531 udelay(1);
532 }
533
534 writel(ch, port->membase + AUART_DATA);
535}
536
537static void
538auart_console_write(struct console *co, const char *str, unsigned int count)
539{
540 struct mxs_auart_port *s;
541 struct uart_port *port;
542 unsigned int old_ctrl0, old_ctrl2;
543 unsigned int to = 1000;
544
545 if (co->index > MXS_AUART_PORTS || co->index < 0)
546 return;
547
548 s = auart_port[co->index];
549 port = &s->port;
550
551 clk_enable(s->clk);
552
553 /* First save the CR then disable the interrupts */
554 old_ctrl2 = readl(port->membase + AUART_CTRL2);
555 old_ctrl0 = readl(port->membase + AUART_CTRL0);
556
557 writel(AUART_CTRL0_CLKGATE,
558 port->membase + AUART_CTRL0_CLR);
559 writel(AUART_CTRL2_UARTEN | AUART_CTRL2_TXE,
560 port->membase + AUART_CTRL2_SET);
561
562 uart_console_write(port, str, count, mxs_auart_console_putchar);
563
564 /*
565 * Finally, wait for transmitter to become empty
566 * and restore the TCR
567 */
568 while (readl(port->membase + AUART_STAT) & AUART_STAT_BUSY) {
569 if (!to--)
570 break;
571 udelay(1);
572 }
573
574 writel(old_ctrl0, port->membase + AUART_CTRL0);
575 writel(old_ctrl2, port->membase + AUART_CTRL2);
576
577 clk_disable(s->clk);
578}
579
580static void __init
581auart_console_get_options(struct uart_port *port, int *baud,
582 int *parity, int *bits)
583{
584 unsigned int lcr_h, quot;
585
586 if (!(readl(port->membase + AUART_CTRL2) & AUART_CTRL2_UARTEN))
587 return;
588
589 lcr_h = readl(port->membase + AUART_LINECTRL);
590
591 *parity = 'n';
592 if (lcr_h & AUART_LINECTRL_PEN) {
593 if (lcr_h & AUART_LINECTRL_EPS)
594 *parity = 'e';
595 else
596 *parity = 'o';
597 }
598
599 if ((lcr_h & AUART_LINECTRL_WLEN_MASK) == AUART_LINECTRL_WLEN(2))
600 *bits = 7;
601 else
602 *bits = 8;
603
604 quot = ((readl(port->membase + AUART_LINECTRL)
605 & AUART_LINECTRL_BAUD_DIVINT_MASK))
606 >> (AUART_LINECTRL_BAUD_DIVINT_SHIFT - 6);
607 quot |= ((readl(port->membase + AUART_LINECTRL)
608 & AUART_LINECTRL_BAUD_DIVFRAC_MASK))
609 >> AUART_LINECTRL_BAUD_DIVFRAC_SHIFT;
610 if (quot == 0)
611 quot = 1;
612
613 *baud = (port->uartclk << 2) / quot;
614}
615
616static int __init
617auart_console_setup(struct console *co, char *options)
618{
619 struct mxs_auart_port *s;
620 int baud = 9600;
621 int bits = 8;
622 int parity = 'n';
623 int flow = 'n';
624 int ret;
625
626 /*
627 * Check whether an invalid uart number has been specified, and
628 * if so, search for the first available port that does have
629 * console support.
630 */
631 if (co->index == -1 || co->index >= ARRAY_SIZE(auart_port))
632 co->index = 0;
633 s = auart_port[co->index];
634 if (!s)
635 return -ENODEV;
636
637 clk_enable(s->clk);
638
639 if (options)
640 uart_parse_options(options, &baud, &parity, &bits, &flow);
641 else
642 auart_console_get_options(&s->port, &baud, &parity, &bits);
643
644 ret = uart_set_options(&s->port, co, baud, parity, bits, flow);
645
646 clk_disable(s->clk);
647
648 return ret;
649}
650
651static struct console auart_console = {
652 .name = "ttyAPP",
653 .write = auart_console_write,
654 .device = uart_console_device,
655 .setup = auart_console_setup,
656 .flags = CON_PRINTBUFFER,
657 .index = -1,
658 .data = &auart_driver,
659};
660#endif
661
662static struct uart_driver auart_driver = {
663 .owner = THIS_MODULE,
664 .driver_name = "ttyAPP",
665 .dev_name = "ttyAPP",
666 .major = 0,
667 .minor = 0,
668 .nr = MXS_AUART_PORTS,
669#ifdef CONFIG_SERIAL_MXS_AUART_CONSOLE
670 .cons = &auart_console,
671#endif
672};
673
674static int __devinit mxs_auart_probe(struct platform_device *pdev)
675{
676 struct mxs_auart_port *s;
677 u32 version;
678 int ret = 0;
679 struct resource *r;
680
681 s = kzalloc(sizeof(struct mxs_auart_port), GFP_KERNEL);
682 if (!s) {
683 ret = -ENOMEM;
684 goto out;
685 }
686
687 s->clk = clk_get(&pdev->dev, NULL);
688 if (IS_ERR(s->clk)) {
689 ret = PTR_ERR(s->clk);
690 goto out_free;
691 }
692
693 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
694 if (!r) {
695 ret = -ENXIO;
696 goto out_free_clk;
697 }
698
699 s->port.mapbase = r->start;
700 s->port.membase = ioremap(r->start, resource_size(r));
701 s->port.ops = &mxs_auart_ops;
702 s->port.iotype = UPIO_MEM;
703 s->port.line = pdev->id < 0 ? 0 : pdev->id;
704 s->port.fifosize = 16;
705 s->port.uartclk = clk_get_rate(s->clk);
706 s->port.type = PORT_IMX;
707 s->port.dev = s->dev = get_device(&pdev->dev);
708
709 s->flags = 0;
710 s->ctrl = 0;
711
712 s->irq = platform_get_irq(pdev, 0);
713 s->port.irq = s->irq;
714 ret = request_irq(s->irq, mxs_auart_irq_handle, 0, dev_name(&pdev->dev), s);
715 if (ret)
716 goto out_free_clk;
717
718 platform_set_drvdata(pdev, s);
719
720 auart_port[pdev->id] = s;
721
722 mxs_auart_reset(&s->port);
723
724 ret = uart_add_one_port(&auart_driver, &s->port);
725 if (ret)
726 goto out_free_irq;
727
728 version = readl(s->port.membase + AUART_VERSION);
729 dev_info(&pdev->dev, "Found APPUART %d.%d.%d\n",
730 (version >> 24) & 0xff,
731 (version >> 16) & 0xff, version & 0xffff);
732
733 return 0;
734
735out_free_irq:
736 auart_port[pdev->id] = NULL;
737 free_irq(s->irq, s);
738out_free_clk:
739 clk_put(s->clk);
740out_free:
741 kfree(s);
742out:
743 return ret;
744}
745
746static int __devexit mxs_auart_remove(struct platform_device *pdev)
747{
748 struct mxs_auart_port *s = platform_get_drvdata(pdev);
749
750 uart_remove_one_port(&auart_driver, &s->port);
751
752 auart_port[pdev->id] = NULL;
753
754 clk_put(s->clk);
755 free_irq(s->irq, s);
756 kfree(s);
757
758 return 0;
759}
760
761static struct platform_driver mxs_auart_driver = {
762 .probe = mxs_auart_probe,
763 .remove = __devexit_p(mxs_auart_remove),
764 .driver = {
765 .name = "mxs-auart",
766 .owner = THIS_MODULE,
767 },
768};
769
770static int __init mxs_auart_init(void)
771{
772 int r;
773
774 r = uart_register_driver(&auart_driver);
775 if (r)
776 goto out;
777
778 r = platform_driver_register(&mxs_auart_driver);
779 if (r)
780 goto out_err;
781
782 return 0;
783out_err:
784 uart_unregister_driver(&auart_driver);
785out:
786 return r;
787}
788
789static void __exit mxs_auart_exit(void)
790{
791 platform_driver_unregister(&mxs_auart_driver);
792 uart_unregister_driver(&auart_driver);
793}
794
795module_init(mxs_auart_init);
796module_exit(mxs_auart_exit);
797MODULE_LICENSE("GPL");
798MODULE_DESCRIPTION("Freescale MXS application uart driver");
diff --git a/drivers/usb/gadget/fsl_mxc_udc.c b/drivers/usb/gadget/fsl_mxc_udc.c
index 77b1eb577029..834fe945f9dd 100644
--- a/drivers/usb/gadget/fsl_mxc_udc.c
+++ b/drivers/usb/gadget/fsl_mxc_udc.c
@@ -88,7 +88,7 @@ eenahb:
88void fsl_udc_clk_finalize(struct platform_device *pdev) 88void fsl_udc_clk_finalize(struct platform_device *pdev)
89{ 89{
90 struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; 90 struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
91#if defined(CONFIG_ARCH_MX35) 91#if defined(CONFIG_SOC_IMX35)
92 unsigned int v; 92 unsigned int v;
93 93
94 /* workaround ENGcm09152 for i.MX35 */ 94 /* workaround ENGcm09152 for i.MX35 */
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index c8e360d7d975..25c8c10bb689 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -203,11 +203,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
203 mdelay(10); 203 mdelay(10);
204 } 204 }
205 205
206 /* setup specific usb hw */
207 ret = mxc_initialize_usb_hw(pdev->id, pdata->flags);
208 if (ret < 0)
209 goto err_init;
210
211 ehci = hcd_to_ehci(hcd); 206 ehci = hcd_to_ehci(hcd);
212 207
213 /* EHCI registers start at offset 0x100 */ 208 /* EHCI registers start at offset 0x100 */
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 6bafb51bb437..e0ea23f07dd1 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2365,6 +2365,15 @@ config FB_JZ4740
2365 help 2365 help
2366 Framebuffer support for the JZ4740 SoC. 2366 Framebuffer support for the JZ4740 SoC.
2367 2367
2368config FB_MXS
2369 tristate "MXS LCD framebuffer support"
2370 depends on FB && ARCH_MXS
2371 select FB_CFB_FILLRECT
2372 select FB_CFB_COPYAREA
2373 select FB_CFB_IMAGEBLIT
2374 help
2375 Framebuffer support for the MXS SoC.
2376
2368source "drivers/video/omap/Kconfig" 2377source "drivers/video/omap/Kconfig"
2369source "drivers/video/omap2/Kconfig" 2378source "drivers/video/omap2/Kconfig"
2370 2379
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 8c8fabdff9d0..9a096aebb855 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -153,6 +153,7 @@ obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o
153obj-$(CONFIG_FB_BFIN_7393) += bfin_adv7393fb.o 153obj-$(CONFIG_FB_BFIN_7393) += bfin_adv7393fb.o
154obj-$(CONFIG_FB_MX3) += mx3fb.o 154obj-$(CONFIG_FB_MX3) += mx3fb.o
155obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o 155obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o
156obj-$(CONFIG_FB_MXS) += mxsfb.o
156 157
157# the test framebuffer is last 158# the test framebuffer is last
158obj-$(CONFIG_FB_VIRTUAL) += vfb.o 159obj-$(CONFIG_FB_VIRTUAL) += vfb.o
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
new file mode 100644
index 000000000000..7d0284882984
--- /dev/null
+++ b/drivers/video/mxsfb.c
@@ -0,0 +1,919 @@
1/*
2 * Copyright (C) 2010 Juergen Beisert, Pengutronix
3 *
4 * This code is based on:
5 * Author: Vitaly Wool <vital@embeddedalley.com>
6 *
7 * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
8 * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
19
20#define DRIVER_NAME "mxsfb"
21
22/**
23 * @file
24 * @brief LCDIF driver for i.MX23 and i.MX28
25 *
26 * The LCDIF support four modes of operation
27 * - MPU interface (to drive smart displays) -> not supported yet
28 * - VSYNC interface (like MPU interface plus Vsync) -> not supported yet
29 * - Dotclock interface (to drive LC displays with RGB data and sync signals)
30 * - DVI (to drive ITU-R BT656) -> not supported yet
31 *
32 * This driver depends on a correct setup of the pins used for this purpose
33 * (platform specific).
34 *
35 * For the developer: Don't forget to set the data bus width to the display
36 * in the imx_fb_videomode structure. You will else end up with ugly colours.
37 * If you fight against jitter you can vary the clock delay. This is a feature
38 * of the i.MX28 and you can vary it between 2 ns ... 8 ns in 2 ns steps. Give
39 * the required value in the imx_fb_videomode structure.
40 */
41
42#include <linux/kernel.h>
43#include <linux/platform_device.h>
44#include <linux/clk.h>
45#include <linux/dma-mapping.h>
46#include <linux/io.h>
47#include <mach/mxsfb.h>
48
49#define REG_SET 4
50#define REG_CLR 8
51
52#define LCDC_CTRL 0x00
53#define LCDC_CTRL1 0x10
54#define LCDC_V4_CTRL2 0x20
55#define LCDC_V3_TRANSFER_COUNT 0x20
56#define LCDC_V4_TRANSFER_COUNT 0x30
57#define LCDC_V4_CUR_BUF 0x40
58#define LCDC_V4_NEXT_BUF 0x50
59#define LCDC_V3_CUR_BUF 0x30
60#define LCDC_V3_NEXT_BUF 0x40
61#define LCDC_TIMING 0x60
62#define LCDC_VDCTRL0 0x70
63#define LCDC_VDCTRL1 0x80
64#define LCDC_VDCTRL2 0x90
65#define LCDC_VDCTRL3 0xa0
66#define LCDC_VDCTRL4 0xb0
67#define LCDC_DVICTRL0 0xc0
68#define LCDC_DVICTRL1 0xd0
69#define LCDC_DVICTRL2 0xe0
70#define LCDC_DVICTRL3 0xf0
71#define LCDC_DVICTRL4 0x100
72#define LCDC_V4_DATA 0x180
73#define LCDC_V3_DATA 0x1b0
74#define LCDC_V4_DEBUG0 0x1d0
75#define LCDC_V3_DEBUG0 0x1f0
76
77#define CTRL_SFTRST (1 << 31)
78#define CTRL_CLKGATE (1 << 30)
79#define CTRL_BYPASS_COUNT (1 << 19)
80#define CTRL_VSYNC_MODE (1 << 18)
81#define CTRL_DOTCLK_MODE (1 << 17)
82#define CTRL_DATA_SELECT (1 << 16)
83#define CTRL_SET_BUS_WIDTH(x) (((x) & 0x3) << 10)
84#define CTRL_GET_BUS_WIDTH(x) (((x) >> 10) & 0x3)
85#define CTRL_SET_WORD_LENGTH(x) (((x) & 0x3) << 8)
86#define CTRL_GET_WORD_LENGTH(x) (((x) >> 8) & 0x3)
87#define CTRL_MASTER (1 << 5)
88#define CTRL_DF16 (1 << 3)
89#define CTRL_DF18 (1 << 2)
90#define CTRL_DF24 (1 << 1)
91#define CTRL_RUN (1 << 0)
92
93#define CTRL1_FIFO_CLEAR (1 << 21)
94#define CTRL1_SET_BYTE_PACKAGING(x) (((x) & 0xf) << 16)
95#define CTRL1_GET_BYTE_PACKAGING(x) (((x) >> 16) & 0xf)
96
97#define TRANSFER_COUNT_SET_VCOUNT(x) (((x) & 0xffff) << 16)
98#define TRANSFER_COUNT_GET_VCOUNT(x) (((x) >> 16) & 0xffff)
99#define TRANSFER_COUNT_SET_HCOUNT(x) ((x) & 0xffff)
100#define TRANSFER_COUNT_GET_HCOUNT(x) ((x) & 0xffff)
101
102
103#define VDCTRL0_ENABLE_PRESENT (1 << 28)
104#define VDCTRL0_VSYNC_ACT_HIGH (1 << 27)
105#define VDCTRL0_HSYNC_ACT_HIGH (1 << 26)
106#define VDCTRL0_DOTCLK_ACT_FAILING (1 << 25)
107#define VDCTRL0_ENABLE_ACT_HIGH (1 << 24)
108#define VDCTRL0_VSYNC_PERIOD_UNIT (1 << 21)
109#define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT (1 << 20)
110#define VDCTRL0_HALF_LINE (1 << 19)
111#define VDCTRL0_HALF_LINE_MODE (1 << 18)
112#define VDCTRL0_SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
113#define VDCTRL0_GET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
114
115#define VDCTRL2_SET_HSYNC_PERIOD(x) ((x) & 0x3ffff)
116#define VDCTRL2_GET_HSYNC_PERIOD(x) ((x) & 0x3ffff)
117
118#define VDCTRL3_MUX_SYNC_SIGNALS (1 << 29)
119#define VDCTRL3_VSYNC_ONLY (1 << 28)
120#define SET_HOR_WAIT_CNT(x) (((x) & 0xfff) << 16)
121#define GET_HOR_WAIT_CNT(x) (((x) >> 16) & 0xfff)
122#define SET_VERT_WAIT_CNT(x) ((x) & 0xffff)
123#define GET_VERT_WAIT_CNT(x) ((x) & 0xffff)
124
125#define VDCTRL4_SET_DOTCLK_DLY(x) (((x) & 0x7) << 29) /* v4 only */
126#define VDCTRL4_GET_DOTCLK_DLY(x) (((x) >> 29) & 0x7) /* v4 only */
127#define VDCTRL4_SYNC_SIGNALS_ON (1 << 18)
128#define SET_DOTCLK_H_VALID_DATA_CNT(x) ((x) & 0x3ffff)
129
130#define DEBUG0_HSYNC (1 < 26)
131#define DEBUG0_VSYNC (1 < 25)
132
133#define MIN_XRES 120
134#define MIN_YRES 120
135
136#define RED 0
137#define GREEN 1
138#define BLUE 2
139#define TRANSP 3
140
141enum mxsfb_devtype {
142 MXSFB_V3,
143 MXSFB_V4,
144};
145
146/* CPU dependent register offsets */
147struct mxsfb_devdata {
148 unsigned transfer_count;
149 unsigned cur_buf;
150 unsigned next_buf;
151 unsigned debug0;
152 unsigned hs_wdth_mask;
153 unsigned hs_wdth_shift;
154 unsigned ipversion;
155};
156
157struct mxsfb_info {
158 struct fb_info fb_info;
159 struct platform_device *pdev;
160 struct clk *clk;
161 void __iomem *base; /* registers */
162 unsigned allocated_size;
163 int enabled;
164 unsigned ld_intf_width;
165 unsigned dotclk_delay;
166 const struct mxsfb_devdata *devdata;
167 int mapped;
168};
169
170#define mxsfb_is_v3(host) (host->devdata->ipversion == 3)
171#define mxsfb_is_v4(host) (host->devdata->ipversion == 4)
172
173static const struct mxsfb_devdata mxsfb_devdata[] = {
174 [MXSFB_V3] = {
175 .transfer_count = LCDC_V3_TRANSFER_COUNT,
176 .cur_buf = LCDC_V3_CUR_BUF,
177 .next_buf = LCDC_V3_NEXT_BUF,
178 .debug0 = LCDC_V3_DEBUG0,
179 .hs_wdth_mask = 0xff,
180 .hs_wdth_shift = 24,
181 .ipversion = 3,
182 },
183 [MXSFB_V4] = {
184 .transfer_count = LCDC_V4_TRANSFER_COUNT,
185 .cur_buf = LCDC_V4_CUR_BUF,
186 .next_buf = LCDC_V4_NEXT_BUF,
187 .debug0 = LCDC_V4_DEBUG0,
188 .hs_wdth_mask = 0x3fff,
189 .hs_wdth_shift = 18,
190 .ipversion = 4,
191 },
192};
193
194#define to_imxfb_host(x) (container_of(x, struct mxsfb_info, fb_info))
195
196/* mask and shift depends on architecture */
197static inline u32 set_hsync_pulse_width(struct mxsfb_info *host, unsigned val)
198{
199 return (val & host->devdata->hs_wdth_mask) <<
200 host->devdata->hs_wdth_shift;
201}
202
203static inline u32 get_hsync_pulse_width(struct mxsfb_info *host, unsigned val)
204{
205 return (val >> host->devdata->hs_wdth_shift) &
206 host->devdata->hs_wdth_mask;
207}
208
209static const struct fb_bitfield def_rgb565[] = {
210 [RED] = {
211 .offset = 11,
212 .length = 5,
213 },
214 [GREEN] = {
215 .offset = 5,
216 .length = 6,
217 },
218 [BLUE] = {
219 .offset = 0,
220 .length = 5,
221 },
222 [TRANSP] = { /* no support for transparency */
223 .length = 0,
224 }
225};
226
227static const struct fb_bitfield def_rgb666[] = {
228 [RED] = {
229 .offset = 16,
230 .length = 6,
231 },
232 [GREEN] = {
233 .offset = 8,
234 .length = 6,
235 },
236 [BLUE] = {
237 .offset = 0,
238 .length = 6,
239 },
240 [TRANSP] = { /* no support for transparency */
241 .length = 0,
242 }
243};
244
245static const struct fb_bitfield def_rgb888[] = {
246 [RED] = {
247 .offset = 16,
248 .length = 8,
249 },
250 [GREEN] = {
251 .offset = 8,
252 .length = 8,
253 },
254 [BLUE] = {
255 .offset = 0,
256 .length = 8,
257 },
258 [TRANSP] = { /* no support for transparency */
259 .length = 0,
260 }
261};
262
263static inline unsigned chan_to_field(unsigned chan, struct fb_bitfield *bf)
264{
265 chan &= 0xffff;
266 chan >>= 16 - bf->length;
267 return chan << bf->offset;
268}
269
270static int mxsfb_check_var(struct fb_var_screeninfo *var,
271 struct fb_info *fb_info)
272{
273 struct mxsfb_info *host = to_imxfb_host(fb_info);
274 const struct fb_bitfield *rgb = NULL;
275
276 if (var->xres < MIN_XRES)
277 var->xres = MIN_XRES;
278 if (var->yres < MIN_YRES)
279 var->yres = MIN_YRES;
280
281 var->xres_virtual = var->xres;
282
283 var->yres_virtual = var->yres;
284
285 switch (var->bits_per_pixel) {
286 case 16:
287 /* always expect RGB 565 */
288 rgb = def_rgb565;
289 break;
290 case 32:
291 switch (host->ld_intf_width) {
292 case STMLCDIF_8BIT:
293 pr_debug("Unsupported LCD bus width mapping\n");
294 break;
295 case STMLCDIF_16BIT:
296 case STMLCDIF_18BIT:
297 /* 24 bit to 18 bit mapping */
298 rgb = def_rgb666;
299 break;
300 case STMLCDIF_24BIT:
301 /* real 24 bit */
302 rgb = def_rgb888;
303 break;
304 }
305 break;
306 default:
307 pr_debug("Unsupported colour depth: %u\n", var->bits_per_pixel);
308 return -EINVAL;
309 }
310
311 /*
312 * Copy the RGB parameters for this display
313 * from the machine specific parameters.
314 */
315 var->red = rgb[RED];
316 var->green = rgb[GREEN];
317 var->blue = rgb[BLUE];
318 var->transp = rgb[TRANSP];
319
320 return 0;
321}
322
323static void mxsfb_enable_controller(struct fb_info *fb_info)
324{
325 struct mxsfb_info *host = to_imxfb_host(fb_info);
326 u32 reg;
327
328 dev_dbg(&host->pdev->dev, "%s\n", __func__);
329
330 clk_enable(host->clk);
331 clk_set_rate(host->clk, PICOS2KHZ(fb_info->var.pixclock) * 1000U);
332
333 /* if it was disabled, re-enable the mode again */
334 writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_SET);
335
336 /* enable the SYNC signals first, then the DMA engine */
337 reg = readl(host->base + LCDC_VDCTRL4);
338 reg |= VDCTRL4_SYNC_SIGNALS_ON;
339 writel(reg, host->base + LCDC_VDCTRL4);
340
341 writel(CTRL_RUN, host->base + LCDC_CTRL + REG_SET);
342
343 host->enabled = 1;
344}
345
346static void mxsfb_disable_controller(struct fb_info *fb_info)
347{
348 struct mxsfb_info *host = to_imxfb_host(fb_info);
349 unsigned loop;
350 u32 reg;
351
352 dev_dbg(&host->pdev->dev, "%s\n", __func__);
353
354 /*
355 * Even if we disable the controller here, it will still continue
356 * until its FIFOs are running out of data
357 */
358 writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_CLR);
359
360 loop = 1000;
361 while (loop) {
362 reg = readl(host->base + LCDC_CTRL);
363 if (!(reg & CTRL_RUN))
364 break;
365 loop--;
366 }
367
368 writel(VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4 + REG_CLR);
369
370 clk_disable(host->clk);
371
372 host->enabled = 0;
373}
374
375static int mxsfb_set_par(struct fb_info *fb_info)
376{
377 struct mxsfb_info *host = to_imxfb_host(fb_info);
378 u32 ctrl, vdctrl0, vdctrl4;
379 int line_size, fb_size;
380 int reenable = 0;
381
382 line_size = fb_info->var.xres * (fb_info->var.bits_per_pixel >> 3);
383 fb_size = fb_info->var.yres_virtual * line_size;
384
385 if (fb_size > fb_info->fix.smem_len)
386 return -ENOMEM;
387
388 fb_info->fix.line_length = line_size;
389
390 /*
391 * It seems, you can't re-program the controller if it is still running.
392 * This may lead into shifted pictures (FIFO issue?).
393 * So, first stop the controller and drain its FIFOs
394 */
395 if (host->enabled) {
396 reenable = 1;
397 mxsfb_disable_controller(fb_info);
398 }
399
400 /* clear the FIFOs */
401 writel(CTRL1_FIFO_CLEAR, host->base + LCDC_CTRL1 + REG_SET);
402
403 ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER |
404 CTRL_SET_BUS_WIDTH(host->ld_intf_width);;
405
406 switch (fb_info->var.bits_per_pixel) {
407 case 16:
408 dev_dbg(&host->pdev->dev, "Setting up RGB565 mode\n");
409 ctrl |= CTRL_SET_WORD_LENGTH(0);
410 writel(CTRL1_SET_BYTE_PACKAGING(0xf), host->base + LCDC_CTRL1);
411 break;
412 case 32:
413 dev_dbg(&host->pdev->dev, "Setting up RGB888/666 mode\n");
414 ctrl |= CTRL_SET_WORD_LENGTH(3);
415 switch (host->ld_intf_width) {
416 case STMLCDIF_8BIT:
417 dev_dbg(&host->pdev->dev,
418 "Unsupported LCD bus width mapping\n");
419 return -EINVAL;
420 case STMLCDIF_16BIT:
421 case STMLCDIF_18BIT:
422 /* 24 bit to 18 bit mapping */
423 ctrl |= CTRL_DF24; /* ignore the upper 2 bits in
424 * each colour component
425 */
426 break;
427 case STMLCDIF_24BIT:
428 /* real 24 bit */
429 break;
430 }
431 /* do not use packed pixels = one pixel per word instead */
432 writel(CTRL1_SET_BYTE_PACKAGING(0x7), host->base + LCDC_CTRL1);
433 break;
434 default:
435 dev_dbg(&host->pdev->dev, "Unhandled color depth of %u\n",
436 fb_info->var.bits_per_pixel);
437 return -EINVAL;
438 }
439
440 writel(ctrl, host->base + LCDC_CTRL);
441
442 writel(TRANSFER_COUNT_SET_VCOUNT(fb_info->var.yres) |
443 TRANSFER_COUNT_SET_HCOUNT(fb_info->var.xres),
444 host->base + host->devdata->transfer_count);
445
446 vdctrl0 = VDCTRL0_ENABLE_PRESENT | /* always in DOTCLOCK mode */
447 VDCTRL0_VSYNC_PERIOD_UNIT |
448 VDCTRL0_VSYNC_PULSE_WIDTH_UNIT |
449 VDCTRL0_SET_VSYNC_PULSE_WIDTH(fb_info->var.vsync_len);
450 if (fb_info->var.sync & FB_SYNC_HOR_HIGH_ACT)
451 vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH;
452 if (fb_info->var.sync & FB_SYNC_VERT_HIGH_ACT)
453 vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH;
454 if (fb_info->var.sync & FB_SYNC_DATA_ENABLE_HIGH_ACT)
455 vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH;
456 if (fb_info->var.sync & FB_SYNC_DOTCLK_FAILING_ACT)
457 vdctrl0 |= VDCTRL0_DOTCLK_ACT_FAILING;
458
459 writel(vdctrl0, host->base + LCDC_VDCTRL0);
460
461 /* frame length in lines */
462 writel(fb_info->var.upper_margin + fb_info->var.vsync_len +
463 fb_info->var.lower_margin + fb_info->var.yres,
464 host->base + LCDC_VDCTRL1);
465
466 /* line length in units of clocks or pixels */
467 writel(set_hsync_pulse_width(host, fb_info->var.hsync_len) |
468 VDCTRL2_SET_HSYNC_PERIOD(fb_info->var.left_margin +
469 fb_info->var.hsync_len + fb_info->var.right_margin +
470 fb_info->var.xres),
471 host->base + LCDC_VDCTRL2);
472
473 writel(SET_HOR_WAIT_CNT(fb_info->var.left_margin +
474 fb_info->var.hsync_len) |
475 SET_VERT_WAIT_CNT(fb_info->var.upper_margin +
476 fb_info->var.vsync_len),
477 host->base + LCDC_VDCTRL3);
478
479 vdctrl4 = SET_DOTCLK_H_VALID_DATA_CNT(fb_info->var.xres);
480 if (mxsfb_is_v4(host))
481 vdctrl4 |= VDCTRL4_SET_DOTCLK_DLY(host->dotclk_delay);
482 writel(vdctrl4, host->base + LCDC_VDCTRL4);
483
484 writel(fb_info->fix.smem_start +
485 fb_info->fix.line_length * fb_info->var.yoffset,
486 host->base + host->devdata->next_buf);
487
488 if (reenable)
489 mxsfb_enable_controller(fb_info);
490
491 return 0;
492}
493
494static int mxsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
495 u_int transp, struct fb_info *fb_info)
496{
497 unsigned int val;
498 int ret = -EINVAL;
499
500 /*
501 * If greyscale is true, then we convert the RGB value
502 * to greyscale no matter what visual we are using.
503 */
504 if (fb_info->var.grayscale)
505 red = green = blue = (19595 * red + 38470 * green +
506 7471 * blue) >> 16;
507
508 switch (fb_info->fix.visual) {
509 case FB_VISUAL_TRUECOLOR:
510 /*
511 * 12 or 16-bit True Colour. We encode the RGB value
512 * according to the RGB bitfield information.
513 */
514 if (regno < 16) {
515 u32 *pal = fb_info->pseudo_palette;
516
517 val = chan_to_field(red, &fb_info->var.red);
518 val |= chan_to_field(green, &fb_info->var.green);
519 val |= chan_to_field(blue, &fb_info->var.blue);
520
521 pal[regno] = val;
522 ret = 0;
523 }
524 break;
525
526 case FB_VISUAL_STATIC_PSEUDOCOLOR:
527 case FB_VISUAL_PSEUDOCOLOR:
528 break;
529 }
530
531 return ret;
532}
533
534static int mxsfb_blank(int blank, struct fb_info *fb_info)
535{
536 struct mxsfb_info *host = to_imxfb_host(fb_info);
537
538 switch (blank) {
539 case FB_BLANK_POWERDOWN:
540 case FB_BLANK_VSYNC_SUSPEND:
541 case FB_BLANK_HSYNC_SUSPEND:
542 case FB_BLANK_NORMAL:
543 if (host->enabled)
544 mxsfb_disable_controller(fb_info);
545 break;
546
547 case FB_BLANK_UNBLANK:
548 if (!host->enabled)
549 mxsfb_enable_controller(fb_info);
550 break;
551 }
552 return 0;
553}
554
555static int mxsfb_pan_display(struct fb_var_screeninfo *var,
556 struct fb_info *fb_info)
557{
558 struct mxsfb_info *host = to_imxfb_host(fb_info);
559 unsigned offset;
560
561 if (var->xoffset != 0)
562 return -EINVAL;
563
564 offset = fb_info->fix.line_length * var->yoffset;
565
566 /* update on next VSYNC */
567 writel(fb_info->fix.smem_start + offset,
568 host->base + host->devdata->next_buf);
569
570 return 0;
571}
572
573static struct fb_ops mxsfb_ops = {
574 .owner = THIS_MODULE,
575 .fb_check_var = mxsfb_check_var,
576 .fb_set_par = mxsfb_set_par,
577 .fb_setcolreg = mxsfb_setcolreg,
578 .fb_blank = mxsfb_blank,
579 .fb_pan_display = mxsfb_pan_display,
580 .fb_fillrect = cfb_fillrect,
581 .fb_copyarea = cfb_copyarea,
582 .fb_imageblit = cfb_imageblit,
583};
584
585static int __devinit mxsfb_restore_mode(struct mxsfb_info *host)
586{
587 struct fb_info *fb_info = &host->fb_info;
588 unsigned line_count;
589 unsigned period;
590 unsigned long pa, fbsize;
591 int bits_per_pixel, ofs;
592 u32 transfer_count, vdctrl0, vdctrl2, vdctrl3, vdctrl4, ctrl;
593 struct fb_videomode vmode;
594
595 /* Only restore the mode when the controller is running */
596 ctrl = readl(host->base + LCDC_CTRL);
597 if (!(ctrl & CTRL_RUN))
598 return -EINVAL;
599
600 vdctrl0 = readl(host->base + LCDC_VDCTRL0);
601 vdctrl2 = readl(host->base + LCDC_VDCTRL2);
602 vdctrl3 = readl(host->base + LCDC_VDCTRL3);
603 vdctrl4 = readl(host->base + LCDC_VDCTRL4);
604
605 transfer_count = readl(host->base + host->devdata->transfer_count);
606
607 vmode.xres = TRANSFER_COUNT_GET_HCOUNT(transfer_count);
608 vmode.yres = TRANSFER_COUNT_GET_VCOUNT(transfer_count);
609
610 switch (CTRL_GET_WORD_LENGTH(ctrl)) {
611 case 0:
612 bits_per_pixel = 16;
613 break;
614 case 3:
615 bits_per_pixel = 32;
616 case 1:
617 default:
618 return -EINVAL;
619 }
620
621 fb_info->var.bits_per_pixel = bits_per_pixel;
622
623 vmode.pixclock = KHZ2PICOS(clk_get_rate(host->clk) / 1000U);
624 vmode.hsync_len = get_hsync_pulse_width(host, vdctrl2);
625 vmode.left_margin = GET_HOR_WAIT_CNT(vdctrl3) - vmode.hsync_len;
626 vmode.right_margin = VDCTRL2_GET_HSYNC_PERIOD(vdctrl2) - vmode.hsync_len -
627 vmode.left_margin - vmode.xres;
628 vmode.vsync_len = VDCTRL0_GET_VSYNC_PULSE_WIDTH(vdctrl0);
629 period = readl(host->base + LCDC_VDCTRL1);
630 vmode.upper_margin = GET_VERT_WAIT_CNT(vdctrl3) - vmode.vsync_len;
631 vmode.lower_margin = period - vmode.vsync_len - vmode.upper_margin - vmode.yres;
632
633 vmode.vmode = FB_VMODE_NONINTERLACED;
634
635 vmode.sync = 0;
636 if (vdctrl0 & VDCTRL0_HSYNC_ACT_HIGH)
637 vmode.sync |= FB_SYNC_HOR_HIGH_ACT;
638 if (vdctrl0 & VDCTRL0_VSYNC_ACT_HIGH)
639 vmode.sync |= FB_SYNC_VERT_HIGH_ACT;
640
641 pr_debug("Reconstructed video mode:\n");
642 pr_debug("%dx%d, hsync: %u left: %u, right: %u, vsync: %u, upper: %u, lower: %u\n",
643 vmode.xres, vmode.yres,
644 vmode.hsync_len, vmode.left_margin, vmode.right_margin,
645 vmode.vsync_len, vmode.upper_margin, vmode.lower_margin);
646 pr_debug("pixclk: %ldkHz\n", PICOS2KHZ(vmode.pixclock));
647
648 fb_add_videomode(&vmode, &fb_info->modelist);
649
650 host->ld_intf_width = CTRL_GET_BUS_WIDTH(ctrl);
651 host->dotclk_delay = VDCTRL4_GET_DOTCLK_DLY(vdctrl4);
652
653 fb_info->fix.line_length = vmode.xres * (bits_per_pixel >> 3);
654
655 pa = readl(host->base + host->devdata->cur_buf);
656 fbsize = fb_info->fix.line_length * vmode.yres;
657 if (pa < fb_info->fix.smem_start)
658 return -EINVAL;
659 if (pa + fbsize > fb_info->fix.smem_start + fb_info->fix.smem_len)
660 return -EINVAL;
661 ofs = pa - fb_info->fix.smem_start;
662 if (ofs) {
663 memmove(fb_info->screen_base, fb_info->screen_base + ofs, fbsize);
664 writel(fb_info->fix.smem_start, host->base + host->devdata->next_buf);
665 }
666
667 line_count = fb_info->fix.smem_len / fb_info->fix.line_length;
668 fb_info->fix.ypanstep = 1;
669
670 clk_enable(host->clk);
671 host->enabled = 1;
672
673 return 0;
674}
675
676static int __devinit mxsfb_init_fbinfo(struct mxsfb_info *host)
677{
678 struct fb_info *fb_info = &host->fb_info;
679 struct fb_var_screeninfo *var = &fb_info->var;
680 struct mxsfb_platform_data *pdata = host->pdev->dev.platform_data;
681 dma_addr_t fb_phys;
682 void *fb_virt;
683 unsigned fb_size = pdata->fb_size;
684
685 fb_info->fbops = &mxsfb_ops;
686 fb_info->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST;
687 strlcpy(fb_info->fix.id, "mxs", sizeof(fb_info->fix.id));
688 fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
689 fb_info->fix.ypanstep = 1;
690 fb_info->fix.visual = FB_VISUAL_TRUECOLOR,
691 fb_info->fix.accel = FB_ACCEL_NONE;
692
693 var->bits_per_pixel = pdata->default_bpp ? pdata->default_bpp : 16;
694 var->nonstd = 0;
695 var->activate = FB_ACTIVATE_NOW;
696 var->accel_flags = 0;
697 var->vmode = FB_VMODE_NONINTERLACED;
698
699 host->dotclk_delay = pdata->dotclk_delay;
700 host->ld_intf_width = pdata->ld_intf_width;
701
702 /* Memory allocation for framebuffer */
703 if (pdata->fb_phys) {
704 if (!fb_size)
705 return -EINVAL;
706
707 fb_phys = pdata->fb_phys;
708
709 if (!request_mem_region(fb_phys, fb_size, host->pdev->name))
710 return -ENOMEM;
711
712 fb_virt = ioremap(fb_phys, fb_size);
713 if (!fb_virt) {
714 release_mem_region(fb_phys, fb_size);
715 return -ENOMEM;
716 }
717 host->mapped = 1;
718 } else {
719 if (!fb_size)
720 fb_size = SZ_2M; /* default */
721 fb_virt = alloc_pages_exact(fb_size, GFP_DMA);
722 if (!fb_virt)
723 return -ENOMEM;
724
725 fb_phys = virt_to_phys(fb_virt);
726 }
727
728 fb_info->fix.smem_start = fb_phys;
729 fb_info->screen_base = fb_virt;
730 fb_info->screen_size = fb_info->fix.smem_len = fb_size;
731
732 if (mxsfb_restore_mode(host))
733 memset(fb_virt, 0, fb_size);
734
735 return 0;
736}
737
738static void __devexit mxsfb_free_videomem(struct mxsfb_info *host)
739{
740 struct fb_info *fb_info = &host->fb_info;
741
742 if (host->mapped) {
743 iounmap(fb_info->screen_base);
744 release_mem_region(fb_info->fix.smem_start,
745 fb_info->screen_size);
746 } else {
747 free_pages_exact(fb_info->screen_base, fb_info->fix.smem_len);
748 }
749}
750
751static int __devinit mxsfb_probe(struct platform_device *pdev)
752{
753 struct mxsfb_platform_data *pdata = pdev->dev.platform_data;
754 struct resource *res;
755 struct mxsfb_info *host;
756 struct fb_info *fb_info;
757 struct fb_modelist *modelist;
758 int i, ret;
759
760 if (!pdata) {
761 dev_err(&pdev->dev, "No platformdata. Giving up\n");
762 return -ENODEV;
763 }
764
765 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
766 if (!res) {
767 dev_err(&pdev->dev, "Cannot get memory IO resource\n");
768 return -ENODEV;
769 }
770
771 if (!request_mem_region(res->start, resource_size(res), pdev->name))
772 return -EBUSY;
773
774 fb_info = framebuffer_alloc(sizeof(struct mxsfb_info), &pdev->dev);
775 if (!fb_info) {
776 dev_err(&pdev->dev, "Failed to allocate fbdev\n");
777 ret = -ENOMEM;
778 goto error_alloc_info;
779 }
780
781 host = to_imxfb_host(fb_info);
782
783 host->base = ioremap(res->start, resource_size(res));
784 if (!host->base) {
785 dev_err(&pdev->dev, "ioremap failed\n");
786 ret = -ENOMEM;
787 goto error_ioremap;
788 }
789
790 host->pdev = pdev;
791 platform_set_drvdata(pdev, host);
792
793 host->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
794
795 host->clk = clk_get(&host->pdev->dev, NULL);
796 if (IS_ERR(host->clk)) {
797 ret = PTR_ERR(host->clk);
798 goto error_getclock;
799 }
800
801 fb_info->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
802 if (!fb_info->pseudo_palette) {
803 ret = -ENOMEM;
804 goto error_pseudo_pallette;
805 }
806
807 INIT_LIST_HEAD(&fb_info->modelist);
808
809 ret = mxsfb_init_fbinfo(host);
810 if (ret != 0)
811 goto error_init_fb;
812
813 for (i = 0; i < pdata->mode_count; i++)
814 fb_add_videomode(&pdata->mode_list[i], &fb_info->modelist);
815
816 modelist = list_first_entry(&fb_info->modelist,
817 struct fb_modelist, list);
818 fb_videomode_to_var(&fb_info->var, &modelist->mode);
819
820 /* init the color fields */
821 mxsfb_check_var(&fb_info->var, fb_info);
822
823 platform_set_drvdata(pdev, fb_info);
824
825 ret = register_framebuffer(fb_info);
826 if (ret != 0) {
827 dev_err(&pdev->dev,"Failed to register framebuffer\n");
828 goto error_register;
829 }
830
831 if (!host->enabled) {
832 writel(0, host->base + LCDC_CTRL);
833 mxsfb_set_par(fb_info);
834 mxsfb_enable_controller(fb_info);
835 }
836
837 dev_info(&pdev->dev, "initialized\n");
838
839 return 0;
840
841error_register:
842 if (host->enabled)
843 clk_disable(host->clk);
844 fb_destroy_modelist(&fb_info->modelist);
845error_init_fb:
846 kfree(fb_info->pseudo_palette);
847error_pseudo_pallette:
848 clk_put(host->clk);
849error_getclock:
850 iounmap(host->base);
851error_ioremap:
852 framebuffer_release(fb_info);
853error_alloc_info:
854 release_mem_region(res->start, resource_size(res));
855
856 return ret;
857}
858
859static int __devexit mxsfb_remove(struct platform_device *pdev)
860{
861 struct fb_info *fb_info = platform_get_drvdata(pdev);
862 struct mxsfb_info *host = to_imxfb_host(fb_info);
863 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
864
865 if (host->enabled)
866 mxsfb_disable_controller(fb_info);
867
868 unregister_framebuffer(fb_info);
869 kfree(fb_info->pseudo_palette);
870 mxsfb_free_videomem(host);
871 iounmap(host->base);
872 clk_put(host->clk);
873
874 framebuffer_release(fb_info);
875 release_mem_region(res->start, resource_size(res));
876
877 platform_set_drvdata(pdev, NULL);
878
879 return 0;
880}
881
882static struct platform_device_id mxsfb_devtype[] = {
883 {
884 .name = "imx23-fb",
885 .driver_data = MXSFB_V3,
886 }, {
887 .name = "imx28-fb",
888 .driver_data = MXSFB_V4,
889 }, {
890 /* sentinel */
891 }
892};
893MODULE_DEVICE_TABLE(platform, mxsfb_devtype);
894
895static struct platform_driver mxsfb_driver = {
896 .probe = mxsfb_probe,
897 .remove = __devexit_p(mxsfb_remove),
898 .id_table = mxsfb_devtype,
899 .driver = {
900 .name = DRIVER_NAME,
901 },
902};
903
904static int __init mxsfb_init(void)
905{
906 return platform_driver_register(&mxsfb_driver);
907}
908
909static void __exit mxsfb_exit(void)
910{
911 platform_driver_unregister(&mxsfb_driver);
912}
913
914module_init(mxsfb_init);
915module_exit(mxsfb_exit);
916
917MODULE_DESCRIPTION("Freescale mxs framebuffer driver");
918MODULE_AUTHOR("Sascha Hauer, Pengutronix");
919MODULE_LICENSE("GPL");