aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/mach-omap2/serial.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/serial.c')
-rw-r--r--arch/arm/mach-omap2/serial.c116
1 files changed, 89 insertions, 27 deletions
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 54dfeb5d566..39b797bc14d 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -24,15 +24,16 @@
#include <linux/clk.h>
#include <linux/io.h>
-#include <mach/common.h>
-#include <mach/board.h>
-#include <mach/clock.h>
-#include <mach/control.h>
+#include <plat/common.h>
+#include <plat/board.h>
+#include <plat/clock.h>
+#include <plat/control.h>
#include "prm.h"
#include "pm.h"
#include "prm-regbits-34xx.h"
+#define UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV 0x52
#define UART_OMAP_WER 0x17 /* Wake-up enable register */
#define DEFAULT_TIMEOUT (5 * HZ)
@@ -73,7 +74,6 @@ static LIST_HEAD(uart_list);
static struct plat_serial8250_port serial_platform_data0[] = {
{
- .membase = OMAP2_IO_ADDRESS(OMAP_UART1_BASE),
.mapbase = OMAP_UART1_BASE,
.irq = 72,
.flags = UPF_BOOT_AUTOCONF,
@@ -87,7 +87,6 @@ static struct plat_serial8250_port serial_platform_data0[] = {
static struct plat_serial8250_port serial_platform_data1[] = {
{
- .membase = OMAP2_IO_ADDRESS(OMAP_UART2_BASE),
.mapbase = OMAP_UART2_BASE,
.irq = 73,
.flags = UPF_BOOT_AUTOCONF,
@@ -101,7 +100,6 @@ static struct plat_serial8250_port serial_platform_data1[] = {
static struct plat_serial8250_port serial_platform_data2[] = {
{
- .membase = OMAP2_IO_ADDRESS(OMAP_UART3_BASE),
.mapbase = OMAP_UART3_BASE,
.irq = 74,
.flags = UPF_BOOT_AUTOCONF,
@@ -116,7 +114,6 @@ static struct plat_serial8250_port serial_platform_data2[] = {
#ifdef CONFIG_ARCH_OMAP4
static struct plat_serial8250_port serial_platform_data3[] = {
{
- .membase = OMAP2_IO_ADDRESS(OMAP_UART4_BASE),
.mapbase = OMAP_UART4_BASE,
.irq = 70,
.flags = UPF_BOOT_AUTOCONF,
@@ -159,8 +156,6 @@ static inline void __init omap_uart_reset(struct omap_uart_state *uart)
#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
-static int enable_off_mode; /* to be removed by full off-mode patches */
-
static void omap_uart_save_context(struct omap_uart_state *uart)
{
u16 lcr = 0;
@@ -539,7 +534,7 @@ static inline void omap_uart_idle_init(struct omap_uart_state *uart) {}
#define DEV_CREATE_FILE(dev, attr)
#endif /* CONFIG_PM */
-static struct omap_uart_state omap_uart[OMAP_MAX_NR_PORTS] = {
+static struct omap_uart_state omap_uart[] = {
{
.pdev = {
.name = "serial8250",
@@ -578,6 +573,23 @@ static struct omap_uart_state omap_uart[OMAP_MAX_NR_PORTS] = {
#endif
};
+/*
+ * Override the default 8250 read handler: mem_serial_in()
+ * Empty RX fifo read causes an abort on omap3630 and omap4
+ * This function makes sure that an empty rx fifo is not read on these silicons
+ * (OMAP1/2/3430 are not affected)
+ */
+static unsigned int serial_in_override(struct uart_port *up, int offset)
+{
+ if (UART_RX == offset) {
+ unsigned int lsr;
+ lsr = serial_read_reg(omap_uart[up->line].p, UART_LSR);
+ if (!(lsr & UART_LSR_DR))
+ return -EPERM;
+ }
+ return serial_read_reg(omap_uart[up->line].p, offset);
+}
+
void __init omap_serial_early_init(void)
{
int i;
@@ -589,12 +601,22 @@ void __init omap_serial_early_init(void)
* if not needed.
*/
- for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
+ for (i = 0; i < ARRAY_SIZE(omap_uart); i++) {
struct omap_uart_state *uart = &omap_uart[i];
struct platform_device *pdev = &uart->pdev;
struct device *dev = &pdev->dev;
struct plat_serial8250_port *p = dev->platform_data;
+ /*
+ * Module 4KB + L4 interconnect 4KB
+ * Static mapping, never released
+ */
+ p->membase = ioremap(p->mapbase, SZ_8K);
+ if (!p->membase) {
+ printk(KERN_ERR "ioremap failed for uart%i\n", i + 1);
+ continue;
+ }
+
sprintf(name, "uart%d_ick", i+1);
uart->ick = clk_get(NULL, name);
if (IS_ERR(uart->ick)) {
@@ -627,24 +649,64 @@ void __init omap_serial_early_init(void)
}
}
-void __init omap_serial_init(void)
+/**
+ * omap_serial_init_port() - initialize single serial port
+ * @port: serial port number (0-3)
+ *
+ * This function initialies serial driver for given @port only.
+ * Platforms can call this function instead of omap_serial_init()
+ * if they don't plan to use all available UARTs as serial ports.
+ *
+ * Don't mix calls to omap_serial_init_port() and omap_serial_init(),
+ * use only one of the two.
+ */
+void __init omap_serial_init_port(int port)
{
- int i;
+ struct omap_uart_state *uart;
+ struct platform_device *pdev;
+ struct device *dev;
- for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
- struct omap_uart_state *uart = &omap_uart[i];
- struct platform_device *pdev = &uart->pdev;
- struct device *dev = &pdev->dev;
+ BUG_ON(port < 0);
+ BUG_ON(port >= ARRAY_SIZE(omap_uart));
- omap_uart_reset(uart);
- omap_uart_idle_init(uart);
+ uart = &omap_uart[port];
+ pdev = &uart->pdev;
+ dev = &pdev->dev;
- if (WARN_ON(platform_device_register(pdev)))
- continue;
- if ((cpu_is_omap34xx() && uart->padconf) ||
- (uart->wk_en && uart->wk_mask)) {
- device_init_wakeup(dev, true);
- DEV_CREATE_FILE(dev, &dev_attr_sleep_timeout);
- }
+ omap_uart_reset(uart);
+ omap_uart_idle_init(uart);
+
+ if (WARN_ON(platform_device_register(pdev)))
+ return;
+
+ if ((cpu_is_omap34xx() && uart->padconf) ||
+ (uart->wk_en && uart->wk_mask)) {
+ device_init_wakeup(dev, true);
+ DEV_CREATE_FILE(dev, &dev_attr_sleep_timeout);
}
+
+ /* omap44xx: Never read empty UART fifo
+ * omap3xxx: Never read empty UART fifo on UARTs
+ * with IP rev >=0x52
+ */
+ if (cpu_is_omap44xx())
+ uart->p->serial_in = serial_in_override;
+ else if ((serial_read_reg(uart->p, UART_OMAP_MVER) & 0xFF)
+ >= UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV)
+ uart->p->serial_in = serial_in_override;
+}
+
+/**
+ * omap_serial_init() - intialize all supported serial ports
+ *
+ * Initializes all available UARTs as serial ports. Platforms
+ * can call this function when they want to have default behaviour
+ * for serial ports (e.g initialize them all as serial ports).
+ */
+void __init omap_serial_init(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(omap_uart); i++)
+ omap_serial_init_port(i);
}