diff options
Diffstat (limited to 'arch/powerpc/sysdev/fsl_rio.c')
| -rw-r--r-- | arch/powerpc/sysdev/fsl_rio.c | 186 |
1 files changed, 90 insertions, 96 deletions
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 412763672d2..49798532b47 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -50,6 +50,7 @@ #define RIO_ATMU_REGS_OFFSET 0x10c00 #define RIO_P_MSG_REGS_OFFSET 0x11000 #define RIO_S_MSG_REGS_OFFSET 0x13000 +#define RIO_GCCSR 0x13c #define RIO_ESCSR 0x158 #define RIO_CCSR 0x15c #define RIO_LTLEDCSR 0x0608 @@ -87,6 +88,9 @@ #define RIO_IPWSR_PWD 0x00000008 #define RIO_IPWSR_PWB 0x00000004 +#define RIO_EPWISR_PINT 0x80000000 +#define RIO_EPWISR_PW 0x00000001 + #define RIO_MSG_DESC_SIZE 32 #define RIO_MSG_BUFFER_SIZE 4096 #define RIO_MIN_TX_RING_SIZE 2 @@ -478,7 +482,7 @@ fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid, } /** - * rio_hw_add_outb_message - Add message to the MPC85xx outbound message queue + * fsl_add_outb_message - Add message to the MPC85xx outbound message queue * @mport: Master port with outbound message queue * @rdev: Target of outbound message * @mbox: Outbound mailbox @@ -488,8 +492,8 @@ fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid, * Adds the @buffer message to the MPC85xx outbound message queue. Returns * %0 on success or %-EINVAL on failure. */ -int -rio_hw_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox, +static int +fsl_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox, void *buffer, size_t len) { struct rio_priv *priv = mport->priv; @@ -498,9 +502,8 @@ rio_hw_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox, + priv->msg_tx_ring.tx_slot; int ret = 0; - pr_debug - ("RIO: rio_hw_add_outb_message(): destid %4.4x mbox %d buffer %8.8x len %8.8x\n", - rdev->destid, mbox, (int)buffer, len); + pr_debug("RIO: fsl_add_outb_message(): destid %4.4x mbox %d buffer " \ + "%8.8x len %8.8x\n", rdev->destid, mbox, (int)buffer, len); if ((len < 8) || (len > RIO_MAX_MSG_SIZE)) { ret = -EINVAL; @@ -550,8 +553,6 @@ rio_hw_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox, return ret; } -EXPORT_SYMBOL_GPL(rio_hw_add_outb_message); - /** * fsl_rio_tx_handler - MPC85xx outbound message interrupt handler * @irq: Linux interrupt number @@ -596,7 +597,7 @@ fsl_rio_tx_handler(int irq, void *dev_instance) } /** - * rio_open_outb_mbox - Initialize MPC85xx outbound mailbox + * fsl_open_outb_mbox - Initialize MPC85xx outbound mailbox * @mport: Master port implementing the outbound message unit * @dev_id: Device specific pointer to pass on event * @mbox: Mailbox to open @@ -606,7 +607,8 @@ fsl_rio_tx_handler(int irq, void *dev_instance) * and enables the outbound message unit. Returns %0 on success and * %-EINVAL or %-ENOMEM on failure. */ -int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) +static int +fsl_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) { int i, j, rc = 0; struct rio_priv *priv = mport->priv; @@ -702,14 +704,14 @@ int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entr } /** - * rio_close_outb_mbox - Shut down MPC85xx outbound mailbox + * fsl_close_outb_mbox - Shut down MPC85xx outbound mailbox * @mport: Master port implementing the outbound message unit * @mbox: Mailbox to close * * Disables the outbound message unit, free all buffers, and * frees the outbound message interrupt. */ -void rio_close_outb_mbox(struct rio_mport *mport, int mbox) +static void fsl_close_outb_mbox(struct rio_mport *mport, int mbox) { struct rio_priv *priv = mport->priv; /* Disable inbound message unit */ @@ -766,7 +768,7 @@ fsl_rio_rx_handler(int irq, void *dev_instance) } /** - * rio_open_inb_mbox - Initialize MPC85xx inbound mailbox + * fsl_open_inb_mbox - Initialize MPC85xx inbound mailbox * @mport: Master port implementing the inbound message unit * @dev_id: Device specific pointer to pass on event * @mbox: Mailbox to open @@ -776,7 +778,8 @@ fsl_rio_rx_handler(int irq, void *dev_instance) * and enables the inbound message unit. Returns %0 on success * and %-EINVAL or %-ENOMEM on failure. */ -int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) +static int +fsl_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) { int i, rc = 0; struct rio_priv *priv = mport->priv; @@ -840,14 +843,14 @@ int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entri } /** - * rio_close_inb_mbox - Shut down MPC85xx inbound mailbox + * fsl_close_inb_mbox - Shut down MPC85xx inbound mailbox * @mport: Master port implementing the inbound message unit * @mbox: Mailbox to close * * Disables the inbound message unit, free all buffers, and * frees the inbound message interrupt. */ -void rio_close_inb_mbox(struct rio_mport *mport, int mbox) +static void fsl_close_inb_mbox(struct rio_mport *mport, int mbox) { struct rio_priv *priv = mport->priv; /* Disable inbound message unit */ @@ -862,7 +865,7 @@ void rio_close_inb_mbox(struct rio_mport *mport, int mbox) } /** - * rio_hw_add_inb_buffer - Add buffer to the MPC85xx inbound message queue + * fsl_add_inb_buffer - Add buffer to the MPC85xx inbound message queue * @mport: Master port implementing the inbound message unit * @mbox: Inbound mailbox number * @buf: Buffer to add to inbound queue @@ -870,12 +873,12 @@ void rio_close_inb_mbox(struct rio_mport *mport, int mbox) * Adds the @buf buffer to the MPC85xx inbound message queue. Returns * %0 on success or %-EINVAL on failure. */ -int rio_hw_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf) +static int fsl_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf) { int rc = 0; struct rio_priv *priv = mport->priv; - pr_debug("RIO: rio_hw_add_inb_buffer(), msg_rx_ring.rx_slot %d\n", + pr_debug("RIO: fsl_add_inb_buffer(), msg_rx_ring.rx_slot %d\n", priv->msg_rx_ring.rx_slot); if (priv->msg_rx_ring.virt_buffer[priv->msg_rx_ring.rx_slot]) { @@ -894,17 +897,15 @@ int rio_hw_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf) return rc; } -EXPORT_SYMBOL_GPL(rio_hw_add_inb_buffer); - /** - * rio_hw_get_inb_message - Fetch inbound message from the MPC85xx message unit + * fsl_get_inb_message - Fetch inbound message from the MPC85xx message unit * @mport: Master port implementing the inbound message unit * @mbox: Inbound mailbox number * * Gets the next available inbound message from the inbound message queue. * A pointer to the message is returned on success or NULL on failure. */ -void *rio_hw_get_inb_message(struct rio_mport *mport, int mbox) +static void *fsl_get_inb_message(struct rio_mport *mport, int mbox) { struct rio_priv *priv = mport->priv; u32 phys_buf, virt_buf; @@ -941,8 +942,6 @@ void *rio_hw_get_inb_message(struct rio_mport *mport, int mbox) return buf; } -EXPORT_SYMBOL_GPL(rio_hw_get_inb_message); - /** * fsl_rio_dbell_handler - MPC85xx doorbell interrupt handler * @irq: Linux interrupt number @@ -969,7 +968,6 @@ fsl_rio_dbell_handler(int irq, void *dev_instance) if (dsr & DOORBELL_DSR_QFI) { pr_info("RIO: doorbell queue full\n"); out_be32(&priv->msg_regs->dsr, DOORBELL_DSR_QFI); - goto out; } /* XXX Need to check/dispatch until queue empty */ @@ -1082,18 +1080,12 @@ fsl_rio_port_write_handler(int irq, void *dev_instance) struct rio_priv *priv = port->priv; u32 epwisr, tmp; - ipwmr = in_be32(&priv->msg_regs->pwmr); - ipwsr = in_be32(&priv->msg_regs->pwsr); - epwisr = in_be32(priv->regs_win + RIO_EPWISR); - if (epwisr & 0x80000000) { - tmp = in_be32(priv->regs_win + RIO_LTLEDCSR); - pr_info("RIO_LTLEDCSR = 0x%x\n", tmp); - out_be32(priv->regs_win + RIO_LTLEDCSR, 0); - } + if (!(epwisr & RIO_EPWISR_PW)) + goto pw_done; - if (!(epwisr & 0x00000001)) - return IRQ_HANDLED; + ipwmr = in_be32(&priv->msg_regs->pwmr); + ipwsr = in_be32(&priv->msg_regs->pwsr); #ifdef DEBUG_PW pr_debug("PW Int->IPWMR: 0x%08x IPWSR: 0x%08x (", ipwmr, ipwsr); @@ -1109,20 +1101,6 @@ fsl_rio_port_write_handler(int irq, void *dev_instance) pr_debug(" PWB"); pr_debug(" )\n"); #endif - out_be32(&priv->msg_regs->pwsr, - ipwsr & (RIO_IPWSR_TE | RIO_IPWSR_QFI | RIO_IPWSR_PWD)); - - if ((ipwmr & RIO_IPWMR_EIE) && (ipwsr & RIO_IPWSR_TE)) { - priv->port_write_msg.err_count++; - pr_info("RIO: Port-Write Transaction Err (%d)\n", - priv->port_write_msg.err_count); - } - if (ipwsr & RIO_IPWSR_PWD) { - priv->port_write_msg.discard_count++; - pr_info("RIO: Port Discarded Port-Write Msg(s) (%d)\n", - priv->port_write_msg.discard_count); - } - /* Schedule deferred processing if PW was received */ if (ipwsr & RIO_IPWSR_QFI) { /* Save PW message (if there is room in FIFO), @@ -1134,16 +1112,43 @@ fsl_rio_port_write_handler(int irq, void *dev_instance) RIO_PW_MSG_SIZE); } else { priv->port_write_msg.discard_count++; - pr_info("RIO: ISR Discarded Port-Write Msg(s) (%d)\n", + pr_debug("RIO: ISR Discarded Port-Write Msg(s) (%d)\n", priv->port_write_msg.discard_count); } + /* Clear interrupt and issue Clear Queue command. This allows + * another port-write to be received. + */ + out_be32(&priv->msg_regs->pwsr, RIO_IPWSR_QFI); + out_be32(&priv->msg_regs->pwmr, ipwmr | RIO_IPWMR_CQ); + schedule_work(&priv->pw_work); } - /* Issue Clear Queue command. This allows another - * port-write to be received. - */ - out_be32(&priv->msg_regs->pwmr, ipwmr | RIO_IPWMR_CQ); + if ((ipwmr & RIO_IPWMR_EIE) && (ipwsr & RIO_IPWSR_TE)) { + priv->port_write_msg.err_count++; + pr_debug("RIO: Port-Write Transaction Err (%d)\n", + priv->port_write_msg.err_count); + /* Clear Transaction Error: port-write controller should be + * disabled when clearing this error + */ + out_be32(&priv->msg_regs->pwmr, ipwmr & ~RIO_IPWMR_PWE); + out_be32(&priv->msg_regs->pwsr, RIO_IPWSR_TE); + out_be32(&priv->msg_regs->pwmr, ipwmr); + } + + if (ipwsr & RIO_IPWSR_PWD) { + priv->port_write_msg.discard_count++; + pr_debug("RIO: Port Discarded Port-Write Msg(s) (%d)\n", + priv->port_write_msg.discard_count); + out_be32(&priv->msg_regs->pwsr, RIO_IPWSR_PWD); + } + +pw_done: + if (epwisr & RIO_EPWISR_PINT) { + tmp = in_be32(priv->regs_win + RIO_LTLEDCSR); + pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp); + out_be32(priv->regs_win + RIO_LTLEDCSR, 0); + } return IRQ_HANDLED; } @@ -1283,28 +1288,6 @@ err_out: return rc; } -static char *cmdline = NULL; - -static int fsl_rio_get_hdid(int index) -{ - /* XXX Need to parse multiple entries in some format */ - if (!cmdline) - return -1; - - return simple_strtol(cmdline, NULL, 0); -} - -static int fsl_rio_get_cmdline(char *s) -{ - if (!s) - return 0; - - cmdline = s; - return 1; -} - -__setup("riohdid=", fsl_rio_get_cmdline); - static inline void fsl_rio_info(struct device *dev, u32 ccsr) { const char *str; @@ -1421,13 +1404,19 @@ int fsl_rio_setup(struct platform_device *dev) ops->cwrite = fsl_rio_config_write; ops->dsend = fsl_rio_doorbell_send; ops->pwenable = fsl_rio_pw_enable; + ops->open_outb_mbox = fsl_open_outb_mbox; + ops->open_inb_mbox = fsl_open_inb_mbox; + ops->close_outb_mbox = fsl_close_outb_mbox; + ops->close_inb_mbox = fsl_close_inb_mbox; + ops->add_outb_message = fsl_add_outb_message; + ops->add_inb_buffer = fsl_add_inb_buffer; + ops->get_inb_message = fsl_get_inb_message; port = kzalloc(sizeof(struct rio_mport), GFP_KERNEL); if (!port) { rc = -ENOMEM; goto err_port; } - port->id = 0; port->index = 0; priv = kzalloc(sizeof(struct rio_priv), GFP_KERNEL); @@ -1443,6 +1432,14 @@ int fsl_rio_setup(struct platform_device *dev) port->iores.flags = IORESOURCE_MEM; port->iores.name = "rio_io_win"; + if (request_resource(&iomem_resource, &port->iores) < 0) { + dev_err(&dev->dev, "RIO: Error requesting master port region" + " 0x%016llx-0x%016llx\n", + (u64)port->iores.start, (u64)port->iores.end); + rc = -ENOMEM; + goto err_res; + } + priv->pwirq = irq_of_parse_and_map(dev->dev.of_node, 0); priv->bellirq = irq_of_parse_and_map(dev->dev.of_node, 2); priv->txirq = irq_of_parse_and_map(dev->dev.of_node, 3); @@ -1458,10 +1455,8 @@ int fsl_rio_setup(struct platform_device *dev) priv->dev = &dev->dev; port->ops = ops; - port->host_deviceid = fsl_rio_get_hdid(port->id); - port->priv = priv; - rio_register_mport(port); + port->phys_efptr = 0x100; priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1); rio_regs_win = priv->regs_win; @@ -1508,6 +1503,15 @@ int fsl_rio_setup(struct platform_device *dev) dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n", port->sys_size ? 65536 : 256); + if (rio_register_mport(port)) + goto err; + + if (port->host_deviceid >= 0) + out_be32(priv->regs_win + RIO_GCCSR, RIO_PORT_GEN_HOST | + RIO_PORT_GEN_MASTER | RIO_PORT_GEN_DISCOVERED); + else + out_be32(priv->regs_win + RIO_GCCSR, 0x00000000); + priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win + RIO_ATMU_REGS_OFFSET); priv->maint_atmu_regs = priv->atmu_regs + 1; @@ -1538,12 +1542,11 @@ int fsl_rio_setup(struct platform_device *dev) saved_mcheck_exception = ppc_md.machine_check_exception; ppc_md.machine_check_exception = fsl_rio_mcheck_exception; #endif - /* Ensure that RFXE is set */ - mtspr(SPRN_HID1, (mfspr(SPRN_HID1) | 0x20000)); return 0; err: iounmap(priv->regs_win); +err_res: kfree(priv); err_priv: kfree(port); @@ -1555,21 +1558,12 @@ err_ops: /* The probe function for RapidIO peer-to-peer network. */ -static int __devinit fsl_of_rio_rpn_probe(struct platform_device *dev, - const struct of_device_id *match) +static int __devinit fsl_of_rio_rpn_probe(struct platform_device *dev) { - int rc; printk(KERN_INFO "Setting up RapidIO peer-to-peer network %s\n", dev->dev.of_node->full_name); - rc = fsl_rio_setup(dev); - if (rc) - goto out; - - /* Enumerate all registered ports */ - rc = rio_init_mports(); -out: - return rc; + return fsl_rio_setup(dev); }; static const struct of_device_id fsl_of_rio_rpn_ids[] = { @@ -1579,7 +1573,7 @@ static const struct of_device_id fsl_of_rio_rpn_ids[] = { {}, }; -static struct of_platform_driver fsl_of_rio_rpn_driver = { +static struct platform_driver fsl_of_rio_rpn_driver = { .driver = { .name = "fsl-of-rio", .owner = THIS_MODULE, @@ -1590,7 +1584,7 @@ static struct of_platform_driver fsl_of_rio_rpn_driver = { static __init int fsl_of_rio_rpn_init(void) { - return of_register_platform_driver(&fsl_of_rio_rpn_driver); + return platform_driver_register(&fsl_of_rio_rpn_driver); } subsys_initcall(fsl_of_rio_rpn_init); |
