summaryrefslogtreecommitdiffstats
path: root/drivers/serial
diff options
context:
space:
mode:
authorMichel Stam <m.stam@fugro.nl>2014-04-07 12:01:22 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2014-04-09 19:31:42 +0200
commit9f556d4b6fc71d548e5c984c416f4f1b7d599d2f (patch)
tree96adeb2f953a59e7353f441023e17f4d09c7e9cb /drivers/serial
parent940237285ebbdbfb4b341eb248fd77e9546df61e (diff)
downloadbarebox-9f556d4b6fc71d548e5c984c416f4f1b7d599d2f.tar.gz
barebox-9f556d4b6fc71d548e5c984c416f4f1b7d599d2f.tar.xz
x86: ns16550: Rework driver to allow for x86 I/O space
The current implementation fakes a memory-mapped I/O device at 0x3f8 and 0x2f8, then uses platform read/write functions to do the actual reading and writing. These platform functions only exist for the x86 platform; better to move the I/O routines into the driver and have the driver request I/O ports using request_ioport_region. Signed-off-by: Michel Stam <michel@reverze.net> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/serial_ns16550.c123
1 files changed, 107 insertions, 16 deletions
diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c
index 0c00eb182c..7d22873835 100644
--- a/drivers/serial/serial_ns16550.c
+++ b/drivers/serial/serial_ns16550.c
@@ -47,6 +47,7 @@ struct ns16550_priv {
struct console_device cdev;
struct NS16550_plat plat;
int access_width;
+ int mmio;
struct clk *clk;
uint32_t fcrval;
};
@@ -62,6 +63,90 @@ struct ns16550_drvdata {
};
/**
+ * @brief read system i/o (byte)
+ * @param[in] addr address to read
+ * @param[in] mmio memory i/o space or i/o port space
+ */
+static inline uint8_t ns16550_sys_readb(void __iomem *addr, int mmio)
+{
+ if (mmio)
+ return readb(addr);
+ else
+ return (uint8_t) inb((int) addr);
+}
+
+/**
+ * @brief read system i/o (word)
+ * @param[in] addr address to read
+ * @param[in] mmio memory i/o space or i/o port space
+ */
+static inline uint16_t ns16550_sys_readw(void __iomem *addr, int mmio)
+{
+ if (mmio)
+ return readw(addr);
+ else
+ return (uint16_t) inw((int) addr);
+}
+
+/**
+ * @brief read system i/o (dword)
+ * @param[in] addr address to read
+ * @param[in] mmio memory i/o space or i/o port space
+ */
+static inline uint32_t ns16550_sys_readl(void __iomem *addr, int mmio)
+{
+ if (mmio)
+ return readl(addr);
+ else
+ return (uint32_t) inl((int) addr);
+}
+
+/**
+ * @brief write system i/o (byte)
+ * @param[in] val data to write
+ * @param[in] addr address to write to
+ * @param[in] mmio memory i/o space or i/o port space
+ */
+static inline void ns16550_sys_writeb(uint8_t val, void __iomem *addr,
+ int mmio)
+{
+ if (mmio)
+ writeb(val, addr);
+ else
+ outb(val, (int) addr);
+}
+
+/**
+ * @brief read system i/o (word)
+ * @param[in] val data to write
+ * @param[in] addr address to write to
+ * @param[in] mmio memory i/o space or i/o port space
+ */
+static inline void ns16550_sys_writew(uint16_t val, void __iomem *addr,
+ int mmio)
+{
+ if (mmio)
+ writew(val, addr);
+ else
+ outw(val, (int) addr);
+}
+
+/**
+ * @brief read system i/o (dword)
+ * @param[in] val data to write
+ * @param[in] addr address to write to
+ * @param[in] mmio memory i/o space or i/o port space
+ */
+static inline void ns16550_sys_writel(uint32_t val, void __iomem *addr,
+ int mmio)
+{
+ if (mmio)
+ writel(val, addr);
+ else
+ outl(val, (int) addr);
+}
+
+/**
* @brief read register
*
* @param[in] cdev pointer to console device
@@ -78,16 +163,13 @@ static uint32_t ns16550_read(struct console_device *cdev, uint32_t off)
off <<= plat->shift;
- if (plat->reg_read)
- return plat->reg_read((unsigned long)dev->priv, off);
-
switch (width) {
case IORESOURCE_MEM_8BIT:
- return readb(dev->priv + off);
+ return ns16550_sys_readb(dev->priv + off, priv->mmio);
case IORESOURCE_MEM_16BIT:
- return readw(dev->priv + off);
+ return ns16550_sys_readw(dev->priv + off, priv->mmio);
case IORESOURCE_MEM_32BIT:
- return readl(dev->priv + off);
+ return ns16550_sys_readl(dev->priv + off, priv->mmio);
}
return -1;
}
@@ -109,20 +191,15 @@ static void ns16550_write(struct console_device *cdev, uint32_t val,
off <<= plat->shift;
- if (plat->reg_write) {
- plat->reg_write(val, (unsigned long)dev->priv, off);
- return;
- }
-
switch (width) {
case IORESOURCE_MEM_8BIT:
- writeb(val & 0xff, dev->priv + off);
+ ns16550_sys_writeb(val & 0xff, dev->priv + off, priv->mmio);
break;
case IORESOURCE_MEM_16BIT:
- writew(val & 0xffff, dev->priv + off);
+ ns16550_sys_writew(val & 0xffff, dev->priv + off, priv->mmio);
break;
case IORESOURCE_MEM_32BIT:
- writel(val, dev->priv + off);
+ ns16550_sys_writel(val, dev->priv + off, priv->mmio);
break;
}
}
@@ -293,16 +370,30 @@ static int ns16550_probe(struct device_d *dev)
struct console_device *cdev;
struct NS16550_plat *plat = (struct NS16550_plat *)dev->platform_data;
struct ns16550_drvdata *devtype;
+ struct resource *res;
int ret;
ret = dev_get_drvdata(dev, (unsigned long *)&devtype);
if (ret)
devtype = &ns16550_drvdata;
- dev->priv = dev_request_mem_region(dev, 0);
-
priv = xzalloc(sizeof(*priv));
+ res = dev_get_resource(dev, IORESOURCE_MEM, 0);
+ priv->mmio = (res != NULL);
+ if (res) {
+ res = request_iomem_region(dev_name(dev), res->start, res->end);
+ } else {
+ res = dev_get_resource(dev, IORESOURCE_IO, 0);
+ if (res)
+ res = request_ioport_region(dev_name(dev), res->start,
+ res->end);
+ }
+ if (!res)
+ goto err;
+ dev->priv = (void __force __iomem *) res->start;
+
+
if (plat)
priv->plat = *plat;
else