[PATCH 5/6] net: can: flexcan: split the Message Buffer RAM area

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The message buffer RAM area is not a contiguous 1KB area but 2 partitions
of 512 bytes each. Till now, we used Message buffers with payload size 8
bytes, which translates to 32 MBs per partition and no spare space is left
in any partition.
However, in upcoming SOC LX2160A the message buffers can have payload size
greater than 8 bytes. This results in less than 32 MBs per partition and
some empty area is left at the end of each partition.This empty area should
not be accessed.
Therefore, split the Message Buffer RAM area into two partitions.

Signed-off-by: Pankaj Bansal <pankaj.bansal@xxxxxxx>
---
 drivers/net/can/flexcan.c | 66 ++++++++++++++++++++++++++++---------
 1 file changed, 50 insertions(+), 16 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 15fa983a8237..147405e703f0 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -223,7 +223,8 @@ struct flexcan_regs {
 	u32 rxfgmask;		/* 0x48 */
 	u32 rxfir;		/* 0x4c */
 	u32 _reserved3[12];	/* 0x50 */
-	u32 mb[256];		/* 0x80 */
+	u32 mb1[128];		/* 0x80 */
+	u32 mb2[128];		/* 0x280 */
 	/* FIFO-mode:
 	 *			MB
 	 * 0x080...0x08f	0	RX message buffer
@@ -262,6 +263,8 @@ struct flexcan_priv {
 	struct flexcan_mb __iomem *tx_mb;
 	struct flexcan_mb __iomem *tx_mb_reserved;
 	u8 tx_mb_idx;
+	u8 mb_count_block1;
+	u8 mb_count_block2;
 	u32 reg_ctrl_default;
 	u32 reg_imask1_default;
 	u32 reg_imask2_default;
@@ -676,7 +679,13 @@ static unsigned int flexcan_mailbox_read(struct can_rx_offload *offload,
 
 	mb_size = sizeof(struct flexcan_mb) + priv->devtype_data->payload_size;
 
-	mb = (struct flexcan_mb __iomem *)((u8 *)&regs->mb + (mb_size * n));
+	if (n < priv->mb_count_block1)
+		mb = (struct flexcan_mb __iomem *)
+		     ((u8 *)&regs->mb1 + (mb_size * n));
+	else
+		mb = (struct flexcan_mb __iomem *)
+		     ((u8 *)&regs->mb2 +
+		     (mb_size * (n - priv->mb_count_block1)));
 
 	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {
 		u32 code;
@@ -1003,9 +1012,14 @@ static int flexcan_chip_start(struct net_device *dev)
 	}
 
 	/* clear and invalidate all mailboxes first */
-	for (i = priv->tx_mb_idx; i < (sizeof(regs->mb) / mb_size); i++) {
+	for (i = priv->tx_mb_idx; i < priv->mb_count_block1; i++) {
+		mb = (struct flexcan_mb __iomem *)
+		     ((u8 *)&regs->mb1 + (mb_size * i));
+		priv->write(FLEXCAN_MB_CODE_RX_INACTIVE, &mb->can_ctrl);
+	}
+	for (i -= priv->mb_count_block1; i < priv->mb_count_block2; i++) {
 		mb = (struct flexcan_mb __iomem *)
-		     ((u8 *)&regs->mb + (mb_size * i));
+		     ((u8 *)&regs->mb2 + (mb_size * i));
 		priv->write(FLEXCAN_MB_CODE_RX_INACTIVE, &mb->can_ctrl);
 	}
 
@@ -1013,8 +1027,13 @@ static int flexcan_chip_start(struct net_device *dev)
 		for (i = priv->offload.mb_first;
 		     i <= priv->offload.mb_last;
 		     i++) {
-			mb = (struct flexcan_mb __iomem *)
-			     ((u8 *)&regs->mb + (mb_size * i));
+			if (i < priv->mb_count_block1)
+				mb = (struct flexcan_mb __iomem *)
+				     ((u8 *)&regs->mb1 + (mb_size * i));
+			else
+				mb = (struct flexcan_mb __iomem *)
+				     ((u8 *)&regs->mb2 +
+				     (mb_size * (i - priv->mb_count_block1)));
 			priv->write(FLEXCAN_MB_CODE_RX_EMPTY, &mb->can_ctrl);
 		}
 	}
@@ -1300,7 +1319,7 @@ static int flexcan_probe(struct platform_device *pdev)
 	struct flexcan_regs __iomem *regs;
 	int err, irq;
 	u32 clock_freq = 0;
-	u8 mb_size;
+	u8 mb_size, tx_mb_reserved_idx;
 
 	reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver");
 	if (PTR_ERR(reg_xceiver) == -EPROBE_DEFER)
@@ -1376,6 +1395,8 @@ static int flexcan_probe(struct platform_device *pdev)
 	}
 	mb_size = sizeof(struct flexcan_mb) + devtype_data->payload_size;
 
+	priv->mb_count_block1 = sizeof(regs->mb1) / mb_size;
+	priv->mb_count_block2 = sizeof(regs->mb2) / mb_size;
 	priv->can.clock.freq = clock_freq;
 	priv->can.bittiming_const = &flexcan_bittiming_const;
 	priv->can.do_set_mode = flexcan_set_mode;
@@ -1391,17 +1412,29 @@ static int flexcan_probe(struct platform_device *pdev)
 
 	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {
 		priv->tx_mb_idx = FLEXCAN_TX_MB_OFF_TIMESTAMP;
-		priv->tx_mb_reserved = (struct flexcan_mb __iomem *)
-				       ((u8 *)&regs->mb + (mb_size *
-				       FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP));
+		tx_mb_reserved_idx = FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP;
 	} else {
 		priv->tx_mb_idx = FLEXCAN_TX_MB_OFF_FIFO;
-		priv->tx_mb_reserved = (struct flexcan_mb __iomem *)
-				       ((u8 *)&regs->mb + (mb_size *
-				       FLEXCAN_TX_MB_RESERVED_OFF_FIFO));
+		tx_mb_reserved_idx = FLEXCAN_TX_MB_RESERVED_OFF_FIFO;
 	}
-	priv->tx_mb = (struct flexcan_mb __iomem *)
-		      ((u8 *)&regs->mb + (mb_size * priv->tx_mb_idx));
+
+	if (priv->tx_mb_idx < priv->mb_count_block1)
+		priv->tx_mb = (struct flexcan_mb __iomem *)
+			      ((u8 *)&regs->mb1 + (mb_size * priv->tx_mb_idx));
+	else
+		priv->tx_mb = (struct flexcan_mb __iomem *)
+			      ((u8 *)&regs->mb2 + (mb_size *
+			      (priv->tx_mb_idx - priv->mb_count_block1)));
+
+	if (tx_mb_reserved_idx < priv->mb_count_block1)
+		priv->tx_mb_reserved = (struct flexcan_mb __iomem *)
+				       ((u8 *)&regs->mb1 +
+				       (mb_size * tx_mb_reserved_idx));
+	else
+		priv->tx_mb_reserved = (struct flexcan_mb __iomem *)
+				       ((u8 *)&regs->mb2 + (mb_size *
+				       (tx_mb_reserved_idx -
+				       priv->mb_count_block1)));
 
 	priv->reg_imask1_default = FLEXCAN_IFLAG_MB(priv->tx_mb_idx);
 	priv->reg_imask2_default = 0;
@@ -1412,7 +1445,8 @@ static int flexcan_probe(struct platform_device *pdev)
 		u64 imask;
 
 		priv->offload.mb_first = FLEXCAN_RX_MB_OFF_TIMESTAMP_FIRST;
-		priv->offload.mb_last = (sizeof(regs->mb) / mb_size) - 1;
+		priv->offload.mb_last = priv->mb_count_block1 +
+					priv->mb_count_block2 - 1;
 
 		imask = GENMASK_ULL(priv->offload.mb_last, priv->offload.mb_first);
 		priv->reg_imask1_default |= imask;
-- 
2.17.1

--
To unsubscribe from this list: send the line "unsubscribe linux-can" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Automotive Discussions]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]     [CAN Bus]

  Powered by Linux