[linux-yocto] [PATCH 2/5] rapidio: axxia-rio: Added support for configuring the sRIO serdes registers
Daniel Dragomir
daniel.dragomir at windriver.com
Mon Feb 9 09:42:24 PST 2015
From: Palani <palaniappan.ramanathan at lsi.com>
Modified the sRIO sw reset handler, required for the reset control
symbol handling. Improved error handling and reporting during sRIO
maintenance and message trasactions.
Signed-off-by: Palani <palaniappan.ramanathan at lsi.com>
---
drivers/rapidio/devices/lsi/axxia-rio-irq.c | 181 +++++++++++++++++++---------
drivers/rapidio/devices/lsi/axxia-rio-irq.h | 23 +++-
drivers/rapidio/devices/lsi/axxia-rio.c | 38 +++++-
drivers/rapidio/devices/lsi/axxia-rio.h | 2 +
4 files changed, 179 insertions(+), 65 deletions(-)
diff --git a/drivers/rapidio/devices/lsi/axxia-rio-irq.c b/drivers/rapidio/devices/lsi/axxia-rio-irq.c
index a5b810e..71e17d1 100644
--- a/drivers/rapidio/devices/lsi/axxia-rio-irq.c
+++ b/drivers/rapidio/devices/lsi/axxia-rio-irq.c
@@ -14,12 +14,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/*
-** Debug Build Flags
-**/
-/* #define AXM55XX_OUTB_DME_BBS 1 */
-
-
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
@@ -80,6 +74,67 @@ static int __init axxia_hrtimer_setup(char *str)
return 1;
}
__setup("axm_srio_tmr_period=", axxia_hrtimer_setup);
+
+/**************************sRIO SERDES *****************************/
+u32 srio_serdes_write32(struct rio_priv *priv, u32 addr, u32 val)
+{
+ void __iomem *regaddr;
+ u32 regval = 0;
+ regaddr = (priv->linkdown_reset.win) +
+ APB2SER_SRIO_PHY0_CFG_OFFSET;
+ iowrite32(val, (regaddr + SERDES_CMD0_OFFSET));
+ regval = ((1<<SERDES_CMD1_VALID_SHIFT) |
+ (0x1 << SERDES_CMD1_HWRITE_SHIFT) |
+ (0x01<<SERDES_CMD1_TSHIFT_SHIFT) |
+ (0x2<<SERDES_CMD1_HSZIE_SHIFT) |
+ (0x2 << SERDES_CMD1_HTRANS_SHIFT) |
+ (addr & SERDES_CMD1_HADDR_MASK));
+ iowrite32(regval, (regaddr + SERDES_CMD1_OFFSET));
+
+ regval = 0xffffffff;
+ while (1) {
+ regval = ioread32((regaddr + SERDES_CMD1_OFFSET));
+ if (!(regval & (1 << SERDES_CMD1_VALID_SHIFT)))
+ break;
+ }
+
+ regval = ioread32((regaddr + SERDES_READDATA1_OFFSET));
+ if (regval & SERDES_READDATA1_HRESP_MASK) {
+ dev_err(priv->dev, "SerDes write Failed... Returning 0\n");
+ return 0;
+ } else
+ return 1;
+}
+
+u32 srio_serdes_read32(struct rio_priv *priv, u32 addr)
+{
+ void __iomem *regaddr;
+ u32 regval = 0;
+ regaddr = (priv->linkdown_reset.win) +
+ APB2SER_SRIO_PHY0_CFG_OFFSET;
+ regval = ((1<<SERDES_CMD1_VALID_SHIFT) |
+ (0x01<<SERDES_CMD1_TSHIFT_SHIFT) |
+ (0x2<<SERDES_CMD1_HSZIE_SHIFT) |
+ (0x2 << SERDES_CMD1_HTRANS_SHIFT) |
+ (addr & SERDES_CMD1_HADDR_MASK));
+
+ iowrite32(regval, (regaddr + SERDES_CMD1_OFFSET));
+ regval = 0xffffffff;
+ while (1) {
+ regval = ioread32((regaddr + SERDES_CMD1_OFFSET));
+ if ((regval & (1 << SERDES_CMD1_VALID_SHIFT)) == 0x0)
+ break;
+ }
+ regval = ioread32((regaddr + SERDES_READDATA1_OFFSET));
+ if (regval & SERDES_READDATA1_HRESP_MASK) {
+ dev_err(priv->dev, "SerDes Read Failed... Returning 0\n");
+ return 0;
+ }
+ regval = ioread32((regaddr + SERDES_READDATA0_OFFSET));
+ return regval;
+}
+
+/**************************sRIO SERDES Ends ***************************/
static void ib_dme_irq_handler(struct rio_irq_handler *h/*, u32 state*/);
/****************************************************************************
**
@@ -96,23 +151,57 @@ static void ib_dme_irq_handler(struct rio_irq_handler *h/*, u32 state*/);
**
*****************************************************************************/
-#if defined(CONFIG_AXXIA_RIO_STAT)
-
-static inline void __dme_dw_dbg(struct rio_msg_dme *dme, u32 dw0)
+static inline void __dme_dw_dbg(struct device *dev, struct rio_msg_dme *dme,
+ u32 iout, u32 dw0, u32 dw1)
{
+ int did, mb, let;
+ char *io;
+ char *id;
if (dw0 & DME_DESC_DW0_ERROR_MASK) {
+ did = DME_DESC_DW0_GET_DST_ID(dw0);
+ let = DME_DESC_DW1_GET_LETTER(dw1);
+ mb = DME_DESC_DW1_GET_MBOX(dw1);
+ if (iout) {
+ io = "OB";
+ id = "DID";
+ } else {
+ io = "IB";
+ id = "SID";
+ }
+#if defined(CONFIG_AXXIA_RIO_STAT)
dme->desc_error_count++;
- if (dw0 & DME_DESC_DW0_RIO_ERR)
+#endif
+ if (dw0 & DME_DESC_DW0_RIO_ERR) {
+ dev_err(dev,
+ "%s RIO ERR: %s = %x,Type:11,mbox=%d,letter=%d\n",
+ io, id, did, mb, let);
+#if defined(CONFIG_AXXIA_RIO_STAT)
dme->desc_rio_err_count++;
- if (dw0 & DME_DESC_DW0_AXI_ERR)
+#endif
+ }
+ if (dw0 & DME_DESC_DW0_AXI_ERR) {
+ dev_err(dev,
+ "%s AXI ERR: %s = %x,Type:11,mbox=%d,letter=%d\n",
+ io, id, did, mb, let);
+#if defined(CONFIG_AXXIA_RIO_STAT)
dme->desc_axi_err_count++;
- if (dw0 & DME_DESC_DW0_TIMEOUT_ERR)
+#endif
+ }
+ if (dw0 & DME_DESC_DW0_TIMEOUT_ERR) {
+ dev_err(dev,
+ "%s TIMEOUT ERR: %s = %x,Type:11,mbox=%d,letter=%d\n",
+ io, id, did, mb, let);
+#if defined(CONFIG_AXXIA_RIO_STAT)
dme->desc_tmo_err_count++;
+#endif
+ }
}
+#if defined(CONFIG_AXXIA_RIO_STAT)
dme->desc_done_count++;
+#endif
}
-
+#if defined(CONFIG_AXXIA_RIO_STAT)
static void reset_state_counters(struct rio_priv *priv)
{
priv->rpio_compl_count = 0;
@@ -320,42 +409,29 @@ static inline void __misc_fatal(struct rio_mport *mport,
/**
* srio_sw_reset - Reset the SRIO (GRIO) module when it reaches a fatal
- * lockup state
- * @mport: Master port with triggered interrupt
+ * lockup state or if it received a reset control symbol
*/
-static void srio_sw_reset(struct rio_mport *mport)
+static void srio_sw_reset(struct rio_priv *priv)
{
- struct rio_priv *priv = mport->priv;
-
- /**
- * Reset platform if port is broken
- */
- if (priv->linkdown_reset.win) {
- u32 r0, r00, r1, r2, r3;
-
- __rio_local_read_config_32(mport, RIO_DID_CSR, &r1);
- __rio_local_read_config_32(mport, RIO_COMPONENT_TAG_CSR, &r2);
- __rio_local_read_config_32(mport, RIO_GCCSR, &r3);
-
-
- r0 = *((u32 *)priv->linkdown_reset.win+
- priv->linkdown_reset.reg_addr);
- *((u32 *)priv->linkdown_reset.win+
- priv->linkdown_reset.reg_addr) =
- r0 | priv->linkdown_reset.reg_mask;
-
- r00 = *((u32 *)priv->linkdown_reset.win+
- priv->linkdown_reset.reg_addr);
- /* Verify that the bit was set? */
-
- *((u32 *)priv->linkdown_reset.win+
- priv->linkdown_reset.reg_addr) = r0;
-
- __rio_local_write_config_32(mport, RIO_DID_CSR, r1);
- __rio_local_write_config_32(mport, RIO_COMPONENT_TAG_CSR, r2);
- __rio_local_write_config_32(mport, RIO_GCCSR, r3);
+ u32 r32;
+ u32 sval;
+ r32 = srio_serdes_read32(priv, SRIO_PHY_CONTROL0_OFFSET);
+ srio_serdes_write32(priv, SRIO_PHY_CONTROL0_OFFSET,
+ (r32 | priv->linkdown_reset.reg_mask));
+ while (1) {
+ sval = srio_serdes_read32(priv, SRIO_PHY_CONTROL0_OFFSET);
+ if ((sval & priv->linkdown_reset.reg_mask))
+ break;
+ }
+ srio_serdes_write32(priv, SRIO_PHY_CONTROL0_OFFSET, (r32));
+ sval = 0;
+ while (1) {
+ sval = srio_serdes_read32(priv, SRIO_PHY_CONTROL0_OFFSET);
+ if ((sval == r32))
+ break;
}
}
+
/**
* PORT WRITE events
*/
@@ -498,7 +574,7 @@ static void misc_irq_handler(struct rio_irq_handler *h)
* Handle miscellaneous 'Link (IPG) Reset Request'
*/
if (misc_state & LINK_REQ_INT)
- srio_sw_reset(mport);
+ srio_sw_reset(priv);
if (misc_state & PORT_WRITE_INT)
pw_irq_handler(h, misc_state & PORT_WRITE_INT);
@@ -1046,7 +1122,7 @@ ob_dme_restart:
= dw0 & DME_DESC_DW0_NXT_DESC_VALID;
dw1 = *((u32 *)DESC_TABLE_W1_MEM(dme,
dme->read_idx));
- __dme_dw_dbg(dme, dw0);
+ __dme_dw_dbg(priv->dev, dme, 1, dw0, dw1);
dme->read_idx = (dme->read_idx + 1) &
(dme->entries - 1);
mbox = (dw1 >> 2) & 0x3;
@@ -1149,13 +1225,8 @@ static int alloc_ob_dme_shared(struct rio_priv *priv,
for (i = 0, desc = me->desc; i < entries; i++, desc++) {
dw0 = 0;
if (!priv->intern_msg_desc) {
-#ifdef AXM55XX_OUTB_DME_BBS
- dw1 = (u32)(desc->msg_phys >> 11) & 0x1fe00000;
- dw2 = (u32)(desc->msg_phys >> 0) & 0x3fffffff;
-#else
dw1 = 0;
dw2 = (u32)(desc->msg_phys >> 8) & 0x3fffffff;
-#endif
*((u32 *)DESC_TABLE_W0_MEM(me, i)) = dw0;
*((u32 *)DESC_TABLE_W1_MEM(me, i)) = dw1;
*((u32 *)DESC_TABLE_W2_MEM(me, i)) = dw2;
@@ -1449,7 +1520,7 @@ ib_dme_restart:
continue;
if (dme_stat & (IB_DME_STAT_DESC_XFER_CPLT |
- IB_DME_STAT_DESC_XFER_CPLT)) {
+ IB_DME_STAT_DESC_CHAIN_XFER_CPLT)) {
if (mport->inb_msg[mbox_no].mcback)
mport->inb_msg[mbox_no].mcback(mport,
me->dev_id, mbox_no, letter);
@@ -1529,7 +1600,7 @@ ib_dme_restart:
continue;
if (dme_stat & (IB_DME_STAT_DESC_XFER_CPLT |
- IB_DME_STAT_DESC_XFER_CPLT)) {
+ IB_DME_STAT_DESC_CHAIN_XFER_CPLT)) {
if (mport->inb_msg[mbox_no].mcback)
mport->inb_msg[mbox_no].mcback(mport,
me->dev_id, mbox_no, letter);
@@ -2466,7 +2537,7 @@ void *axxia_get_inb_message(struct rio_mport *mport, int mbox, int letter,
*sz = 0;
dw0 = *((u32 *)DESC_TABLE_W0_MEM(me, idx));
dw1 = *((u32 *)DESC_TABLE_W1_MEM(me, idx));
- __dme_dw_dbg(me, dw0);
+ __dme_dw_dbg(priv->dev, me, 0, dw0, dw1);
if ((dw0 & DME_DESC_DW0_ERROR_MASK) &&
(dw0 & DME_DESC_DW0_VALID)) {
*((u32 *)DESC_TABLE_W0_MEM(me, idx)) =
diff --git a/drivers/rapidio/devices/lsi/axxia-rio-irq.h b/drivers/rapidio/devices/lsi/axxia-rio-irq.h
index 0220170..eea9307 100644
--- a/drivers/rapidio/devices/lsi/axxia-rio-irq.h
+++ b/drivers/rapidio/devices/lsi/axxia-rio-irq.h
@@ -1,13 +1,28 @@
#ifndef __AXXIA_RIO_IRQ_H__
#define __AXXIA_RIO_IRQ_H__
+/**************************sRIO SERDES *****************************/
+#define SRIO_PHY_CONTROL0_OFFSET (0x200)
+#define APB2SER_SRIO_PHY0_CFG_OFFSET (0x1e0)
+#define SERDES_CMD0_OFFSET (0x0)
+#define SERDES_CMD1_OFFSET (0x4)
+#define SERDES_READDATA0_OFFSET (0x8)
+#define SERDES_READDATA1_OFFSET (0xc)
+
+#define SERDES_CMD1_VALID_SHIFT (31)
+#define SERDES_CMD1_HWRITE_SHIFT (30)
+#define SERDES_CMD1_TSHIFT_SHIFT (26)
+#define SERDES_CMD1_HSZIE_SHIFT (23)
+#define SERDES_CMD1_HTRANS_SHIFT (21)
+#define SERDES_CMD1_HADDR_MASK (0xFFFF)
+
+#define SERDES_READDATA1_TMO_SHIFT (2)
+#define SERDES_READDATA1_HRESP_MASK (0x3)
+/******************************************************************/
+
/* forward declaration */
struct rio_priv;
-#if !defined(CONFIG_AXXIA_RIO_STAT)
-#define __dme_dw_dbg(priv, dw0)
-#endif
-
#define RIO_MSG_MAX_OB_MBOX_MULTI_ENTRIES 15
#define RIO_MSG_MULTI_SIZE 0x1000 /* 4Kb */
#define RIO_MSG_SEG_SIZE 0x0100 /* 256B */
diff --git a/drivers/rapidio/devices/lsi/axxia-rio.c b/drivers/rapidio/devices/lsi/axxia-rio.c
index 1053206..79de85b 100644
--- a/drivers/rapidio/devices/lsi/axxia-rio.c
+++ b/drivers/rapidio/devices/lsi/axxia-rio.c
@@ -287,6 +287,7 @@ int axxia_rio_config_read(struct rio_mport *mport, int index,
u32 rval = 0;
u32 rbar = 0, ctrl;
int rc = 0;
+ u32 error_code = 0;
aoutb = &priv->outb_atmu[priv->maint_win_id];
if (aoutb == NULL)
@@ -294,7 +295,8 @@ int axxia_rio_config_read(struct rio_mport *mport, int index,
/* 16MB maintenance windows possible */
/* Allow only aligned access to maintenance registers */
- if (offset > (0x1000000 - len) || !IS_ALIGNED(offset, len))
+ if (offset > (CONFIG_RIO_MAINT_WIN_SIZE - len) ||
+ !IS_ALIGNED(offset, len))
return -EINVAL;
axxia_local_config_read(priv,
@@ -338,10 +340,20 @@ int axxia_rio_config_read(struct rio_mport *mport, int index,
rc = -EINVAL;
}
+ axxia_local_config_read(priv, 0x608, &error_code);
+ if (0 != error_code) {
+ rc = -EINVAL;
+ *val = 0xffffffffu;
+ /* clear error code */
+ axxia_local_config_write(priv, 0x608, 0);
+ }
+
if (rc) {
dev_dbg(priv->dev,
"axxia_rio_config_read: Error when reading\n");
- *val = 0;
+ dev_dbg(priv->dev,
+ "rio[%d]: RCR(did=%x, hc=%02x, %08x, <%08x)\n",
+ mport->id, destid, hopcount, offset, rval);
} else
*val = rval;
@@ -374,6 +386,7 @@ int axxia_rio_config_write(struct rio_mport *mport, int index,
u8 *data;
u32 rbar = 0, ctrl, rval;
int rc = 0;
+ u32 error_code = 0;
IODP("rio[%d]: RCW(did=%x, hc=%02x, %08x, >%08x)\n",
mport->id, destid, hopcount, offset, val);
@@ -385,11 +398,9 @@ int axxia_rio_config_write(struct rio_mport *mport, int index,
return -EINVAL;
/* 16MB maintenance windows possible */
- if (aoutb == NULL)
- return -EINVAL;
-
/* Allow only aligned access to maintenance registers */
- if (offset > (0x1000000 - len) || !IS_ALIGNED(offset, len))
+ if (offset > (CONFIG_RIO_MAINT_WIN_SIZE - len) ||
+ !IS_ALIGNED(offset, len))
return -EINVAL;
axxia_local_config_read(priv,
@@ -434,6 +445,21 @@ int axxia_rio_config_write(struct rio_mport *mport, int index,
rc = -EINVAL;
}
+ axxia_local_config_read(priv, 0x608, &error_code);
+ if (0 != error_code) {
+
+ dev_dbg(priv->dev,
+ "axxia_rio_config_write: Error when writing\n");
+
+ dev_dbg(priv->dev,
+ "rio[%d]: RCW(did=%x, hc=%02x, %08x, >%08x)\n",
+ mport->id, destid, hopcount, offset, val);
+
+ rc = -EINVAL;
+ /* clear error code */
+ axxia_local_config_write(priv, 0x608, 0);
+ }
+
err:
return rc;
}
diff --git a/drivers/rapidio/devices/lsi/axxia-rio.h b/drivers/rapidio/devices/lsi/axxia-rio.h
index 87dd3e1..479be4b 100644
--- a/drivers/rapidio/devices/lsi/axxia-rio.h
+++ b/drivers/rapidio/devices/lsi/axxia-rio.h
@@ -400,6 +400,8 @@
up and shift to make double word */
#define DME_DESC_DW1_MSGLEN_F(d) (((d) >> 8) & 0x3ff)
#define DME_DESC_DW1_MSGLEN_B(ml) ((ml) << 3) /* double words to bytes */
+#define DME_DESC_DW1_GET_LETTER(dw1) ((dw1) & 0x03)
+#define DME_DESC_DW1_GET_MBOX(dw1) ((dw1 >> 2) & 0x03)
/***********************************/
/* *********** RIO REG *********** */
--
1.8.1.4
More information about the linux-yocto
mailing list