#include <linux/platform_device.h>
 #include <linux/slab.h>
 
+/* Offsets for the DesignWare specific registers */
+#define DW_UART_USR    0x1f /* UART Status Register */
+#define DW_UART_CPR    0xf4 /* Component Parameter Register */
+#define DW_UART_UCV    0xf8 /* UART Component Version */
+
+/* Component Parameter Register bits */
+#define DW_UART_CPR_ABP_DATA_WIDTH     (3 << 0)
+#define DW_UART_CPR_AFCE_MODE          (1 << 4)
+#define DW_UART_CPR_THRE_MODE          (1 << 5)
+#define DW_UART_CPR_SIR_MODE           (1 << 6)
+#define DW_UART_CPR_SIR_LP_MODE                (1 << 7)
+#define DW_UART_CPR_ADDITIONAL_FEATURES        (1 << 8)
+#define DW_UART_CPR_FIFO_ACCESS                (1 << 9)
+#define DW_UART_CPR_FIFO_STAT          (1 << 10)
+#define DW_UART_CPR_SHADOW             (1 << 11)
+#define DW_UART_CPR_ENCODED_PARMS      (1 << 12)
+#define DW_UART_CPR_DMA_EXTRA          (1 << 13)
+#define DW_UART_CPR_FIFO_MODE          (0xff << 16)
+/* Helper for fifo size calculation */
+#define DW_UART_CPR_FIFO_SIZE(a)       (((a >> 16) & 0xff) * 16)
+
+
 struct dw8250_data {
        int     last_lcr;
        int     line;
        return readl(p->membase + offset);
 }
 
-/* Offset for the DesignWare's UART Status Register. */
-#define UART_USR       0x1f
-
 static int dw8250_handle_irq(struct uart_port *p)
 {
        struct dw8250_data *d = p->private_data;
                return 1;
        } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
                /* Clear the USR and write the LCR again. */
-               (void)p->serial_in(p, UART_USR);
+               (void)p->serial_in(p, DW_UART_USR);
                p->serial_out(p, d->last_lcr, UART_LCR);
 
                return 1;
        return 0;
 }
 
+static void dw8250_setup_port(struct uart_8250_port *up)
+{
+       struct uart_port        *p = &up->port;
+       u32                     reg = readl(p->membase + DW_UART_UCV);
+
+       /*
+        * If the Component Version Register returns zero, we know that
+        * ADDITIONAL_FEATURES are not enabled. No need to go any further.
+        */
+       if (!reg)
+               return;
+
+       dev_dbg_ratelimited(p->dev, "Designware UART version %c.%c%c\n",
+               (reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff);
+
+       reg = readl(p->membase + DW_UART_CPR);
+       if (!reg)
+               return;
+
+       /* Select the type based on fifo */
+       if (reg & DW_UART_CPR_FIFO_MODE) {
+               p->type = PORT_16550A;
+               p->flags |= UPF_FIXED_TYPE;
+               p->fifosize = DW_UART_CPR_FIFO_SIZE(reg);
+               up->tx_loadsz = p->fifosize;
+       }
+}
+
 static int dw8250_probe(struct platform_device *pdev)
 {
        struct uart_8250_port uart = {};
                return -ENODEV;
        }
 
+       dw8250_setup_port(&uart);
+
        data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
        if (!data)
                return -ENOMEM;