Thread (1 message) 1 message, 1 author, 2013-09-09

Re: [PATCH 10/16] c_can: add 16bit align 32bit access functions

From: Marc Kleine-Budde <mkl@pengutronix.de>
Date: 2013-09-09 09:57:43
Also in: netdev

On 09/09/2013 09:25 AM, Benedikt Spranger wrote:
The FlexCard only allows 32bit access to DCAN registers, otherwise the
register value can be wraped up. Add a new helper function to access
registers 16bit aligned but 32bit access.
You are modifying code you have previously added. You should shuffle
your patches that this is not necessary.
quoted hunk
Signed-off-by: Benedikt Spranger <redacted>
---
 drivers/net/can/c_can/c_can.c          |  1 +
 drivers/net/can/c_can/c_can.h          |  1 +
 drivers/net/can/c_can/c_can_platform.c | 38 ++++++++++++++++++++++++++++++++--
 3 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index c573399..46d741d 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -1305,6 +1305,7 @@ struct net_device *alloc_c_can_dev(void)
 	priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
 					CAN_CTRLMODE_LISTENONLY |
 					CAN_CTRLMODE_BERR_REPORTING;
+	spin_lock_init(&priv->lock);
 
 	return dev;
 }
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index 9f0eda8..beea437 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -175,6 +175,7 @@ struct c_can_priv {
 	u32 __iomem *raminit_ctrlreg;
 	unsigned int instance;
 	void (*raminit) (const struct c_can_priv *priv, bool enable);
+	spinlock_t lock;
 };
 
 struct net_device *alloc_c_can_dev(void);
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index 43a3e3f..c6c1eb4 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -58,6 +58,40 @@ static void c_can_plat_write_reg_aligned_to_16bit(struct c_can_priv *priv,
 	writew(val, priv->base + priv->regs[index]);
 }
 
+#define ALIGN_DOWN(p, a)	((typeof(p))round_down((unsigned long)(p), (a)))
+
+static u16 c_can_plat_read_16bit_align_32bit_access(struct c_can_priv *priv,
+						    enum reg index)
+{
+	void *addr = priv->base + priv->regs[index];
Please compile with C=2. Should be void __iomem *.
+	u32 reg;
+	reg = readl(ALIGN_DOWN(addr, 4));
+
+	return IS_ALIGNED((unsigned long)addr, 4) ?
+			reg & 0xffff :
+			reg >> 16;
+}
+
+static void c_can_plat_write_16bit_align_32bit_access(struct c_can_priv *priv,
+						      enum reg index, u16 val)
+{
+	unsigned long flags;
+	void *addr = priv->base + priv->regs[index];
dito
quoted hunk
+	u32 reg;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	reg = readl(ALIGN_DOWN(addr, 4));
+	if (IS_ALIGNED((unsigned long)addr, 4)) {
+		reg &= 0xffff0000;
+		reg |= val;
+	} else {
+		reg &= 0xffff;
+		reg |= val << 16;
+	}
+	writel(reg, ALIGN_DOWN(addr, 4));
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
 static u16 c_can_plat_read_reg_aligned_to_32bit(struct c_can_priv *priv,
 						enum reg index)
 {
@@ -317,8 +351,8 @@ static int c_can_plat_probe(struct platform_device *pdev)
 	case BOSCH_D_CAN_FLEXCARD:
 		priv->regs = reg_map_d_can;
 		priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;
-		priv->read_reg = c_can_plat_read_reg_aligned_to_16bit;
-		priv->write_reg = c_can_plat_write_reg_aligned_to_16bit;
+		priv->read_reg = c_can_plat_read_16bit_align_32bit_access;
+		priv->write_reg = c_can_plat_write_16bit_align_32bit_access;
 		priv->instance = pdev->id;
 
 		res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |

Attachments

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help