On Thu, Oct 13, 2011 at 10:09 AM, Kumar Gala wrote: > > From: Liu Gang <gang....@freescale.com> > > Usually, freescale rapidio endpoint can support one 1X or two 4X LP- > Serial > link interfaces, and rapidio message transactions can be implemented by > two
Is the number of 1x ports described correctly? Can we have two 1x ports as well? > message units. This patch adds the support of two rapidio ports and > initializes message unit 0 and message unit 1. And these ports and > message ... skip ... > + > + /* Probe the master port phy type */ > + ccsr = in_be32(priv->regs_win + RIO_CCSR + i*0x20); > + port->phy_type = (ccsr & 1) ? RIO_PHY_SERIAL : > RIO_PHY_PARALLEL; > + dev_info(&dev->dev, "RapidIO PHY type: %s\n", > + (port->phy_type == RIO_PHY_PARALLEL) ? > + "parallel" : > + ((port->phy_type == RIO_PHY_SERIAL) ? "serial" > : > + "unknown")); > + /* Checking the port training status */ > + if (in_be32((priv->regs_win + RIO_ESCSR + i*0x20)) & 1) { > + dev_err(&dev->dev, "Port %d is not ready. " > + "Try to restart connection...\n", i); > + switch (port->phy_type) { > + case RIO_PHY_SERIAL: > + /* Disable ports */ > + out_be32(priv->regs_win > + + RIO_CCSR + i*0x20, 0); > + /* Set 1x lane */ > + setbits32(priv->regs_win > + + RIO_CCSR + i*0x20, 0x02000000); > + /* Enable ports */ > + setbits32(priv->regs_win > + + RIO_CCSR + i*0x20, 0x00600000); > + break; > + case RIO_PHY_PARALLEL: > + /* Disable ports */ > + out_be32(priv->regs_win > + + RIO_CCSR + i*0x20, 0x22000000); > + /* Enable ports */ > + out_be32(priv->regs_win > + + RIO_CCSR + i*0x20, 0x44000000); > + break; > + } Probably this may be a good moment to drop the support for parallel link. Especially after you renamed controller to "srio" in the device tree. > + msleep(100); > + if (in_be32((priv->regs_win > + + RIO_ESCSR + i*0x20)) & 1) { > + dev_err(&dev->dev, > + "Port %d restart failed.\n", i); > + release_resource(&port->iores); > + kfree(priv); > + kfree(port); > + continue; > + } > + dev_info(&dev->dev, "Port %d restart success!\n", i); > + } > + fsl_rio_info(&dev->dev, ccsr); > + ... skip ... > > struct rio_msg_regs { > - u32 omr; /* 0xD_3000 - Outbound message 0 mode register */ > - u32 osr; /* 0xD_3004 - Outbound message 0 status register */ > + u32 omr; > + u32 osr; > u32 pad1; > - u32 odqdpar; /* 0xD_300C - Outbound message 0 descriptor > queue > - dequeue pointer address register */ > + u32 odqdpar; > u32 pad2; > - u32 osar; /* 0xD_3014 - Outbound message 0 source address > - register */ > - u32 odpr; /* 0xD_3018 - Outbound message 0 destination port > - register */ > - u32 odatr; /* 0xD_301C - Outbound message 0 destination > attributes > - Register*/ > - u32 odcr; /* 0xD_3020 - Outbound message 0 double-word count > - register */ > + u32 osar; > + u32 odpr; > + u32 odatr; > + u32 odcr; > u32 pad3; > - u32 odqepar; /* 0xD_3028 - Outbound message 0 descriptor > queue > - enqueue pointer address register */ > + u32 odqepar; > u32 pad4[13]; > - u32 imr; /* 0xD_3060 - Inbound message 0 mode register */ > - u32 isr; /* 0xD_3064 - Inbound message 0 status register */ > + u32 imr; > + u32 isr; > u32 pad5; > - u32 ifqdpar; /* 0xD_306C - Inbound message 0 frame queue > dequeue > - pointer address register*/ > + u32 ifqdpar; > u32 pad6; > - u32 ifqepar; /* 0xD_3074 - Inbound message 0 frame queue > enqueue > - pointer address register */ > - u32 pad7[226]; > - u32 odmr; /* 0xD_3400 - Outbound doorbell mode register */ > - u32 odsr; /* 0xD_3404 - Outbound doorbell status register */ > + u32 ifqepar; > + u32 pad7; Do we need pad7 here? > +}; > + > +struct rio_dbell_regs { > + u32 odmr; > + u32 odsr; > u32 res0[4]; > - u32 oddpr; /* 0xD_3418 - Outbound doorbell destination port > - register */ ... skip ... > > @@ -340,35 +327,45 @@ fsl_rio_dbell_handler(int irq, void > *dev_instance) > " sid %2.2x tid %2.2x info %4.4x\n", > DBELL_SID(dmsg), DBELL_TID(dmsg), DBELL_INF(dmsg)); > > - list_for_each_entry(dbell, &port->dbells, node) { > - if ((dbell->res->start <= DBELL_INF(dmsg)) && > - (dbell->res->end >= DBELL_INF(dmsg))) { > - found = 1; > - break; > + for (i = 0; i < MAX_PORT_NUM; i++) { > + if (fsl_dbell->mport[i]) { > + list_for_each_entry(dbell, > + &fsl_dbell->mport[i]->dbells, node) { > + if ((dbell->res->start > + <= DBELL_INF(dmsg)) > + && (dbell->res->end > + >= DBELL_INF(dmsg))) { > + found = 1; > + break; > + } > + } > + if (found && dbell->dinb) { > + dbell->dinb(fsl_dbell->mport[i], > + dbell->dev_id, DBELL_SID(dmsg), > + DBELL_TID(dmsg), > + DBELL_INF(dmsg)); > + break; > + } > } > } Do we need to check for matching DBELL_TID and mport destID here and scan only doorbell list attached to the right port? Otherwise this may call service routine associated with doorbell on a wrong port. > - if (found) { > - dbell->dinb(port, dbell->dev_id, > - DBELL_SID(dmsg), > - DBELL_TID(dmsg), DBELL_INF(dmsg)); > - } else { > + > + if (!found) { > pr_debug > ("RIO: spurious doorbell," > " sid %2.2x tid %2.2x info %4.4x\n", > DBELL_SID(dmsg), DBELL_TID(dmsg), > DBELL_INF(dmsg)); > } > - setbits32(&rmu->msg_regs->dmr, DOORBELL_DMR_DI); > - out_be32(&rmu->msg_regs->dsr, DOORBELL_DSR_DIQI); > + setbits32(&fsl_dbell->dbell_regs->dmr, DOORBELL_DMR_DI); > + out_be32(&fsl_dbell->dbell_regs->dsr, DOORBELL_DSR_DIQI); > } > > out: > return IRQ_HANDLED; > } > ... skip ... > @@ -1114,50 +1104,48 @@ int fsl_rio_setup_rmu(struct rio_mport *mport, > struct device_node *node) > { > struct rio_priv *priv; > struct fsl_rmu *rmu; > - struct rio_ops *ops; > + u64 msg_start; > + const u32 *msg_addr; > + int mlen; > + int aw; > > - if (!mport || !mport->priv || !node) > - return -1; > + if (!mport || !mport->priv) > + return -EFAULT; EINVAL may be better here? > + > + priv = mport->priv; > + > + if (!node) { > + dev_warn(priv->dev, "Can't get %s property 'fsl,rmu'\n", > + priv->dev->of_node->full_name); > + return -EFAULT; EINVAL as well? > + } Regards, Alex. _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev