#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
+#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/serial_core.h>
#include <linux/pm_runtime.h>
#include <linux/of.h>
#include <linux/gpio.h>
+#include <linux/pinctrl/consumer.h>
-#include <plat/dmtimer.h>
#include <plat/omap-serial.h>
#define UART_BUILD_REVISION(x, y) (((x) << 8) | (y))
#define OMAP_UART_SCR_RX_TRIG_GRANU1_MASK (1 << 7)
/* FCR register bitmasks */
-#define OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT 6
#define OMAP_UART_FCR_RX_FIFO_TRIG_MASK (0x3 << 6)
+#define OMAP_UART_FCR_TX_FIFO_TRIG_MASK (0x3 << 4)
/* MVR register bitmasks */
#define OMAP_UART_MVR_SCHEME_SHIFT 30
#define OMAP_UART_MVR_MAJ_SHIFT 8
#define OMAP_UART_MVR_MIN_MASK 0x3f
+struct uart_omap_port {
+ struct uart_port port;
+ struct uart_omap_dma uart_dma;
+ struct device *dev;
+
+ unsigned char ier;
+ unsigned char lcr;
+ unsigned char mcr;
+ unsigned char fcr;
+ unsigned char efr;
+ unsigned char dll;
+ unsigned char dlh;
+ unsigned char mdr1;
+ unsigned char scr;
+
+ int use_dma;
+ /*
+ * Some bits in registers are cleared on a read, so they must
+ * be saved whenever the register is read but the bits will not
+ * be immediately processed.
+ */
+ unsigned int lsr_break_flag;
+ unsigned char msr_saved_flags;
+ char name[20];
+ unsigned long port_activity;
+ u32 context_loss_cnt;
+ u32 errata;
+ u8 wakeups_enabled;
+ unsigned int irq_pending:1;
+
+ int DTR_gpio;
+ int DTR_inverted;
+ int DTR_active;
+
+ struct pm_qos_request pm_qos_request;
+ u32 latency;
+ u32 calc_latency;
+ struct work_struct qos_work;
+ struct pinctrl *pins;
+};
+
+#define to_uart_omap_port(p) ((container_of((p), struct uart_omap_port, port)))
+
static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
/* Forward declaration of functions */
{
struct omap_uart_port_info *pdata = up->dev->platform_data;
- if (!pdata->get_context_loss_count)
+ if (!pdata || !pdata->get_context_loss_count)
return 0;
return pdata->get_context_loss_count(up->dev);
{
struct omap_uart_port_info *pdata = up->dev->platform_data;
- if (pdata->set_forceidle)
- pdata->set_forceidle(up->dev);
+ if (!pdata || !pdata->set_forceidle)
+ return;
+
+ pdata->set_forceidle(up->dev);
}
static void serial_omap_set_noidle(struct uart_omap_port *up)
{
struct omap_uart_port_info *pdata = up->dev->platform_data;
- if (pdata->set_noidle)
- pdata->set_noidle(up->dev);
+ if (!pdata || !pdata->set_noidle)
+ return;
+
+ pdata->set_noidle(up->dev);
}
static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable)
{
struct omap_uart_port_info *pdata = up->dev->platform_data;
- if (pdata->enable_wakeup)
- pdata->enable_wakeup(up->dev, enable);
+ if (!pdata || !pdata->enable_wakeup)
+ return;
+
+ pdata->enable_wakeup(up->dev, enable);
}
/*
static void serial_omap_rlsi(struct uart_omap_port *up, unsigned int lsr)
{
unsigned int flag;
+ unsigned char ch = 0;
+
+ if (likely(lsr & UART_LSR_DR))
+ ch = serial_in(up, UART_RX);
up->port.icount.rx++;
flag = TTY_NORMAL;
up->scr |= OMAP_UART_SCR_RX_TRIG_GRANU1_MASK;
- /* Set receive FIFO threshold to 1 byte */
+ /* Set receive FIFO threshold to 16 characters and
+ * transmit FIFO threshold to 16 spaces
+ */
up->fcr &= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK;
- up->fcr |= (0x1 << OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT);
+ up->fcr &= ~OMAP_UART_FCR_TX_FIFO_TRIG_MASK;
+ up->fcr |= UART_FCR6_R_TRIGGER_16 | UART_FCR6_T_TRIGGER_24 |
+ UART_FCR_ENABLE_FIFO;
serial_out(up, UART_FCR, up->fcr);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
{
struct uart_omap_port *up = dev_get_drvdata(dev);
- if (up) {
- uart_suspend_port(&serial_omap_reg, &up->port);
- flush_work_sync(&up->qos_work);
- }
+ uart_suspend_port(&serial_omap_reg, &up->port);
+ flush_work_sync(&up->qos_work);
return 0;
}
{
struct uart_omap_port *up = dev_get_drvdata(dev);
- if (up)
- uart_resume_port(&serial_omap_reg, &up->port);
+ uart_resume_port(&serial_omap_reg, &up->port);
+
return 0;
}
#endif
goto err_port_line;
}
+ up->pins = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(up->pins)) {
+ dev_warn(&pdev->dev, "did not get pins for uart%i error: %li\n",
+ up->port.line, PTR_ERR(up->pins));
+ up->pins = NULL;
+ }
+
sprintf(up->name, "OMAP UART%d", up->port.line);
up->port.mapbase = mem->start;
up->port.membase = devm_ioremap(&pdev->dev, mem->start,
static int serial_omap_runtime_resume(struct device *dev)
{
struct uart_omap_port *up = dev_get_drvdata(dev);
- struct omap_uart_port_info *pdata = dev->platform_data;
- if (up && pdata) {
- u32 loss_cnt = serial_omap_get_context_loss_count(up);
+ u32 loss_cnt = serial_omap_get_context_loss_count(up);
- if (up->context_loss_cnt != loss_cnt)
- serial_omap_restore_context(up);
+ if (up->context_loss_cnt != loss_cnt)
+ serial_omap_restore_context(up);
- up->latency = up->calc_latency;
- schedule_work(&up->qos_work);
- }
+ up->latency = up->calc_latency;
+ schedule_work(&up->qos_work);
return 0;
}