[PATCH 15/21] serial: ns16550: Add register read/write function pointers to private data

Sascha Hauer s.hauer at pengutronix.de
Tue Jul 8 01:50:11 PDT 2014


Makes the code a bit cleaner. This also avoids casting from a pointer
to a 32bit integer which may produce compiler warnings.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/serial/serial_ns16550.c | 234 ++++++++++++++++++++--------------------
 1 file changed, 120 insertions(+), 114 deletions(-)

diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c
index 27fae9b..09e6a6a 100644
--- a/drivers/serial/serial_ns16550.c
+++ b/drivers/serial/serial_ns16550.c
@@ -46,11 +46,17 @@
 struct ns16550_priv {
 	struct console_device cdev;
 	struct NS16550_plat plat;
-	int access_width;
-	int mmio;
 	struct clk *clk;
 	uint32_t fcrval;
 	void __iomem *mmiobase;
+	unsigned iobase;
+	void (*write_reg)(struct ns16550_priv *, uint8_t val, unsigned offset);
+	uint8_t (*read_reg)(struct ns16550_priv *, unsigned offset);
+};
+
+struct ns16550_drvdata {
+        void (*init_port)(struct console_device *cdev);
+        const char *linux_console_name;
 };
 
 static inline struct ns16550_priv *to_ns16550_priv(struct console_device *cdev)
@@ -58,93 +64,64 @@ static inline struct ns16550_priv *to_ns16550_priv(struct console_device *cdev)
 	return container_of(cdev, struct ns16550_priv, cdev);
 }
 
-struct ns16550_drvdata {
-	void (*init_port)(struct console_device *cdev);
-	const char *linux_console_name;
-};
+static uint8_t ns16550_read_reg_mmio_8(struct ns16550_priv *priv, unsigned offset)
+{
+	return readb(priv->mmiobase + offset);
+}
 
-/**
- * @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)
+static void ns16550_write_reg_mmio_8(struct ns16550_priv *priv, uint8_t val, unsigned offset)
 {
-	if (mmio)
-		return readb(addr);
-	else
-		return (uint8_t) inb((int) addr);
+	writeb(val, priv->mmiobase + offset);
 }
 
-/**
- * @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)
+static uint8_t ns16550_read_reg_mmio_16(struct ns16550_priv *priv, unsigned offset)
 {
-	if (mmio)
-		return readw(addr);
-	else
-		return (uint16_t) inw((int) addr);
+	return readw(priv->mmiobase + offset);
 }
 
-/**
- * @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)
+static void ns16550_write_reg_mmio_16(struct ns16550_priv *priv, uint8_t val, unsigned offset)
 {
-	if (mmio)
-		return readl(addr);
-	else
-		return (uint32_t) inl((int) addr);
+	writew(val, priv->mmiobase + offset);
 }
 
-/**
- * @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)
+static uint8_t ns16550_read_reg_mmio_32(struct ns16550_priv *priv, unsigned offset)
 {
-	if (mmio)
-		writeb(val, addr);
-	else
-		outb(val, (int) addr);
+	return readl(priv->mmiobase + offset);
 }
 
-/**
- * @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)
+static void ns16550_write_reg_mmio_32(struct ns16550_priv *priv, uint8_t val, unsigned offset)
 {
-	if (mmio)
-		writew(val, addr);
-	else
-		outw(val, (int) addr);
+	writel(val, priv->mmiobase + offset);
 }
 
-/**
- * @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)
+static uint8_t ns16550_read_reg_ioport_8(struct ns16550_priv *priv, unsigned offset)
 {
-	if (mmio)
-		writel(val, addr);
-	else
-		outl(val, (int) addr);
+	return inb(priv->iobase + offset);
+}
+
+static void ns16550_write_reg_ioport_8(struct ns16550_priv *priv, uint8_t val, unsigned offset)
+{
+	outb(val, priv->iobase + offset);
+}
+
+static uint8_t ns16550_read_reg_ioport_16(struct ns16550_priv *priv, unsigned offset)
+{
+	return inw(priv->iobase + offset);
+}
+
+static void ns16550_write_reg_ioport_16(struct ns16550_priv *priv, uint8_t val, unsigned offset)
+{
+	outw(val, priv->iobase + offset);
+}
+
+static uint8_t ns16550_read_reg_ioport_32(struct ns16550_priv *priv, unsigned offset)
+{
+	return inl(priv->iobase + offset);
+}
+
+static void ns16550_write_reg_ioport_32(struct ns16550_priv *priv, uint8_t val, unsigned offset)
+{
+	outl(val, priv->iobase + offset);
 }
 
 /**
@@ -159,19 +136,8 @@ static uint32_t ns16550_read(struct console_device *cdev, uint32_t off)
 {
 	struct ns16550_priv *priv = to_ns16550_priv(cdev);
 	struct NS16550_plat *plat = &priv->plat;
-	int width = priv->access_width;
-
-	off <<= plat->shift;
 
-	switch (width) {
-	case IORESOURCE_MEM_8BIT:
-		return ns16550_sys_readb(priv->mmiobase + off, priv->mmio);
-	case IORESOURCE_MEM_16BIT:
-		return ns16550_sys_readw(priv->mmiobase + off, priv->mmio);
-	case IORESOURCE_MEM_32BIT:
-		return ns16550_sys_readl(priv->mmiobase + off, priv->mmio);
-	}
-	return -1;
+	return priv->read_reg(priv, off << plat->shift);
 }
 
 /**
@@ -186,21 +152,8 @@ static void ns16550_write(struct console_device *cdev, uint32_t val,
 {
 	struct ns16550_priv *priv = to_ns16550_priv(cdev);
 	struct NS16550_plat *plat = &priv->plat;
-	int width = priv->access_width;
-
-	off <<= plat->shift;
 
-	switch (width) {
-	case IORESOURCE_MEM_8BIT:
-		ns16550_sys_writeb(val & 0xff, priv->mmiobase + off, priv->mmio);
-		break;
-	case IORESOURCE_MEM_16BIT:
-		ns16550_sys_writew(val & 0xffff, priv->mmiobase + off, priv->mmio);
-		break;
-	case IORESOURCE_MEM_32BIT:
-		ns16550_sys_writel(val, priv->mmiobase + off, priv->mmio);
-		break;
-	}
+	priv->write_reg(priv, val, off << plat->shift);
 }
 
 /**
@@ -358,6 +311,70 @@ static __maybe_unused struct ns16550_drvdata jz_drvdata = {
 	.init_port = ns16550_jz_init_port,
 };
 
+static int ns16550_init_iomem(struct device_d *dev, struct ns16550_priv *priv)
+{
+	struct resource *res;
+	int width;
+
+	res = dev_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	priv->mmiobase = dev_request_mem_region(dev, 0);
+
+	width = res->flags & IORESOURCE_MEM_TYPE_MASK;
+	switch (width) {
+	case IORESOURCE_MEM_8BIT:
+		priv->read_reg = ns16550_read_reg_mmio_8;
+		priv->write_reg = ns16550_write_reg_mmio_8;
+		break;
+	case IORESOURCE_MEM_16BIT:
+		priv->read_reg = ns16550_read_reg_mmio_16;
+		priv->write_reg = ns16550_write_reg_mmio_16;
+		break;
+	case IORESOURCE_MEM_32BIT:
+		priv->read_reg = ns16550_read_reg_mmio_32;
+		priv->write_reg = ns16550_write_reg_mmio_32;
+		break;
+	}
+
+	return 0;
+}
+
+static int ns16550_init_ioport(struct device_d *dev, struct ns16550_priv *priv)
+{
+	struct resource *res;
+	int width;
+
+	res = dev_get_resource(dev, IORESOURCE_IO, 0);
+	if (!res)
+		return -ENODEV;
+
+	res = request_ioport_region(dev_name(dev), res->start, res->end);
+	if (!res)
+		return -ENODEV;
+
+	priv->iobase = res->start;
+
+	width = res->flags & IORESOURCE_MEM_TYPE_MASK;
+	switch (width) {
+	case IORESOURCE_MEM_8BIT:
+		priv->read_reg = ns16550_read_reg_ioport_8;
+		priv->write_reg = ns16550_write_reg_ioport_8;
+		break;
+	case IORESOURCE_MEM_16BIT:
+		priv->read_reg = ns16550_read_reg_ioport_16;
+		priv->write_reg = ns16550_write_reg_ioport_16;
+		break;
+	case IORESOURCE_MEM_32BIT:
+		priv->read_reg = ns16550_read_reg_ioport_32;
+		priv->write_reg = ns16550_write_reg_ioport_32;
+		break;
+	}
+
+	return 0;
+}
+
 /**
  * @brief Probe entry point -called on the first match for device
  *
@@ -373,7 +390,6 @@ 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);
@@ -382,20 +398,12 @@ static int ns16550_probe(struct device_d *dev)
 
 	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;
-	priv->mmiobase = (void __force __iomem *) res->start;
+	ret = ns16550_init_iomem(dev, priv);
+	if (ret)
+		ret = ns16550_init_ioport(dev, priv);
 
+	if (ret)
+		return ret;
 
 	if (plat)
 		priv->plat = *plat;
@@ -423,8 +431,6 @@ static int ns16550_probe(struct device_d *dev)
 		goto err;
 	}
 
-	priv->access_width = dev->resource[0].flags & IORESOURCE_MEM_TYPE_MASK;
-
 	cdev = &priv->cdev;
 	cdev->dev = dev;
 	cdev->tstc = ns16550_tstc;
-- 
2.0.0




More information about the barebox mailing list