diff options
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r-- | arch/powerpc/sysdev/Makefile | 1 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_soc.c | 19 | ||||
-rw-r--r-- | arch/powerpc/sysdev/mpic.c | 2 | ||||
-rw-r--r-- | arch/powerpc/sysdev/pmi.c | 305 | ||||
-rw-r--r-- | arch/powerpc/sysdev/qe_lib/ucc_fast.c | 163 | ||||
-rw-r--r-- | arch/powerpc/sysdev/qe_lib/ucc_slow.c | 137 |
6 files changed, 428 insertions, 199 deletions
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 85dcdf17841..26ca3ffbc1d 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o obj-$(CONFIG_PPC_MPC106) += grackle.o obj-$(CONFIG_PPC_DCR) += dcr.o obj-$(CONFIG_PPC_DCR_NATIVE) += dcr-low.o +obj-$(CONFIG_PPC_PMI) += pmi.o obj-$(CONFIG_U3_DART) += dart_iommu.o obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o obj-$(CONFIG_FSL_SOC) += fsl_soc.o diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index 34161bc5a02..d20f02927f7 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c @@ -233,14 +233,7 @@ static int __init gfar_of_init(void) goto err; } - mac_addr = get_property(np, "local-mac-address", NULL); - if (mac_addr == NULL) - mac_addr = get_property(np, "mac-address", NULL); - if (mac_addr == NULL) { - /* Obsolete */ - mac_addr = get_property(np, "address", NULL); - } - + mac_addr = of_get_mac_address(np); if (mac_addr) memcpy(gfar_data.mac_addr, mac_addr, 6); @@ -646,8 +639,9 @@ static int __init fs_enet_of_init(void) goto unreg; } - mac_addr = get_property(np, "mac-address", NULL); - memcpy(fs_enet_data.macaddr, mac_addr, 6); + mac_addr = of_get_mac_address(np); + if (mac_addr) + memcpy(fs_enet_data.macaddr, mac_addr, 6); ph = get_property(np, "phy-handle", NULL); phy = of_find_node_by_phandle(*ph); @@ -931,8 +925,9 @@ static int __init fs_enet_of_init(void) goto err; r[0].name = enet_regs; - mac_addr = (void *)get_property(np, "mac-address", NULL); - memcpy(fs_enet_data.macaddr, mac_addr, 6); + mac_addr = of_get_mac_address(np); + if (mac_addr) + memcpy(fs_enet_data.macaddr, mac_addr, 6); ph = (phandle *) get_property(np, "phy-handle", NULL); if (ph != NULL) diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 4e54a09dd33..bcfb900481f 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -1370,7 +1370,7 @@ void mpic_request_ipis(void) printk(KERN_ERR "Failed to map IPI %d\n", i); break; } - request_irq(vipi, mpic_ipi_action, IRQF_DISABLED, + request_irq(vipi, mpic_ipi_action, IRQF_DISABLED|IRQF_PERCPU, ipi_names[i], mpic); } } diff --git a/arch/powerpc/sysdev/pmi.c b/arch/powerpc/sysdev/pmi.c new file mode 100644 index 00000000000..a5282011d39 --- /dev/null +++ b/arch/powerpc/sysdev/pmi.c @@ -0,0 +1,305 @@ +/* + * pmi driver + * + * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 + * + * PMI (Platform Management Interrupt) is a way to communicate + * with the BMC (Baseboard Management Controller) via interrupts. + * Unlike IPMI it is bidirectional and has a low latency. + * + * Author: Christian Krafft <krafft@de.ibm.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/interrupt.h> +#include <linux/completion.h> +#include <linux/spinlock.h> +#include <linux/workqueue.h> + +#include <asm/of_device.h> +#include <asm/of_platform.h> +#include <asm/io.h> +#include <asm/pmi.h> + + +struct pmi_data { + struct list_head handler; + spinlock_t handler_spinlock; + spinlock_t pmi_spinlock; + struct mutex msg_mutex; + pmi_message_t msg; + struct completion *completion; + struct of_device *dev; + int irq; + u8 __iomem *pmi_reg; + struct work_struct work; +}; + + + +static void __iomem *of_iomap(struct device_node *np) +{ + struct resource res; + + if (of_address_to_resource(np, 0, &res)) + return NULL; + + pr_debug("Resource start: 0x%lx\n", res.start); + pr_debug("Resource end: 0x%lx\n", res.end); + + return ioremap(res.start, 1 + res.end - res.start); +} + + +static int pmi_irq_handler(int irq, void *dev_id) +{ + struct pmi_data *data; + u8 type; + int rc; + + data = dev_id; + + spin_lock(&data->pmi_spinlock); + + type = ioread8(data->pmi_reg + PMI_READ_TYPE); + pr_debug("pmi: got message of type %d\n", type); + + if (type & PMI_ACK && !data->completion) { + printk(KERN_WARNING "pmi: got unexpected ACK message.\n"); + rc = -EIO; + goto unlock; + } + + if (data->completion && !(type & PMI_ACK)) { + printk(KERN_WARNING "pmi: expected ACK, but got %d\n", type); + rc = -EIO; + goto unlock; + } + + data->msg.type = type; + data->msg.data0 = ioread8(data->pmi_reg + PMI_READ_DATA0); + data->msg.data1 = ioread8(data->pmi_reg + PMI_READ_DATA1); + data->msg.data2 = ioread8(data->pmi_reg + PMI_READ_DATA2); + rc = 0; +unlock: + spin_unlock(&data->pmi_spinlock); + + if (rc == -EIO) { + rc = IRQ_HANDLED; + goto out; + } + + if (data->msg.type & PMI_ACK) { + complete(data->completion); + rc = IRQ_HANDLED; + goto out; + } + + schedule_work(&data->work); + + rc = IRQ_HANDLED; +out: + return rc; +} + + +static struct of_device_id pmi_match[] = { + { .type = "ibm,pmi", .name = "ibm,pmi" }, + {}, +}; + +MODULE_DEVICE_TABLE(of, pmi_match); + +static void pmi_notify_handlers(struct work_struct *work) +{ + struct pmi_data *data; + struct pmi_handler *handler; + + data = container_of(work, struct pmi_data, work); + + spin_lock(&data->handler_spinlock); + list_for_each_entry(handler, &data->handler, node) { + pr_debug(KERN_INFO "pmi: notifying handler %p\n", handler); + if (handler->type == data->msg.type) + handler->handle_pmi_message(data->dev, data->msg); + } + spin_unlock(&data->handler_spinlock); +} + +static int pmi_of_probe(struct of_device *dev, + const struct of_device_id *match) +{ + struct device_node *np = dev->node; + struct pmi_data *data; + int rc; + + data = kzalloc(sizeof(struct pmi_data), GFP_KERNEL); + if (!data) { + printk(KERN_ERR "pmi: could not allocate memory.\n"); + rc = -ENOMEM; + goto out; + } + + data->pmi_reg = of_iomap(np); + if (!data->pmi_reg) { + printk(KERN_ERR "pmi: invalid register address.\n"); + rc = -EFAULT; + goto error_cleanup_data; + } + + INIT_LIST_HEAD(&data->handler); + + mutex_init(&data->msg_mutex); + spin_lock_init(&data->pmi_spinlock); + spin_lock_init(&data->handler_spinlock); + + INIT_WORK(&data->work, pmi_notify_handlers); + + dev->dev.driver_data = data; + data->dev = dev; + + data->irq = irq_of_parse_and_map(np, 0); + if (data->irq == NO_IRQ) { + printk(KERN_ERR "pmi: invalid interrupt.\n"); + rc = -EFAULT; + goto error_cleanup_iomap; + } + + rc = request_irq(data->irq, pmi_irq_handler, 0, "pmi", data); + if (rc) { + printk(KERN_ERR "pmi: can't request IRQ %d: returned %d\n", + data->irq, rc); + goto error_cleanup_iomap; + } + + printk(KERN_INFO "pmi: found pmi device at addr %p.\n", data->pmi_reg); + + goto out; + +error_cleanup_iomap: + iounmap(data->pmi_reg); + +error_cleanup_data: + kfree(data); + +out: + return rc; +} + +static int pmi_of_remove(struct of_device *dev) +{ + struct pmi_data *data; + struct pmi_handler *handler, *tmp; + + data = dev->dev.driver_data; + + free_irq(data->irq, data); + iounmap(data->pmi_reg); + + spin_lock(&data->handler_spinlock); + + list_for_each_entry_safe(handler, tmp, &data->handler, node) + list_del(&handler->node); + + spin_unlock(&data->handler_spinlock); + + kfree(dev->dev.driver_data); + + return 0; +} + +static struct of_platform_driver pmi_of_platform_driver = { + .name = "pmi", + .match_table = pmi_match, + .probe = pmi_of_probe, + .remove = pmi_of_remove +}; + +static int __init pmi_module_init(void) +{ + return of_register_platform_driver(&pmi_of_platform_driver); +} +module_init(pmi_module_init); + +static void __exit pmi_module_exit(void) +{ + of_unregister_platform_driver(&pmi_of_platform_driver); +} +module_exit(pmi_module_exit); + +void pmi_send_message(struct of_device *device, pmi_message_t msg) +{ + struct pmi_data *data; + unsigned long flags; + DECLARE_COMPLETION_ONSTACK(completion); + + data = device->dev.driver_data; + + mutex_lock(&data->msg_mutex); + + data->msg = msg; + pr_debug("pmi_send_message: msg is %08x\n", *(u32*)&msg); + + data->completion = &completion; + + spin_lock_irqsave(&data->pmi_spinlock, flags); + iowrite8(msg.data0, data->pmi_reg + PMI_WRITE_DATA0); + iowrite8(msg.data1, data->pmi_reg + PMI_WRITE_DATA1); + iowrite8(msg.data2, data->pmi_reg + PMI_WRITE_DATA2); + iowrite8(msg.type, data->pmi_reg + PMI_WRITE_TYPE); + spin_unlock_irqrestore(&data->pmi_spinlock, flags); + + pr_debug("pmi_send_message: wait for completion\n"); + + wait_for_completion_interruptible_timeout(data->completion, + PMI_TIMEOUT); + + data->completion = NULL; + + mutex_unlock(&data->msg_mutex); +} +EXPORT_SYMBOL_GPL(pmi_send_message); + +void pmi_register_handler(struct of_device *device, + struct pmi_handler *handler) +{ + struct pmi_data *data; + data = device->dev.driver_data; + + spin_lock(&data->handler_spinlock); + list_add_tail(&handler->node, &data->handler); + spin_unlock(&data->handler_spinlock); +} +EXPORT_SYMBOL_GPL(pmi_register_handler); + +void pmi_unregister_handler(struct of_device *device, + struct pmi_handler *handler) +{ + struct pmi_data *data; + + pr_debug("pmi: unregistering handler %p\n", handler); + + data = device->dev.driver_data; + + spin_lock(&data->handler_spinlock); + list_del(&handler->node); + spin_unlock(&data->handler_spinlock); +} +EXPORT_SYMBOL_GPL(pmi_unregister_handler); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>"); +MODULE_DESCRIPTION("IBM Platform Management Interrupt driver"); diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c index e657559bea9..a457ac1c663 100644 --- a/arch/powerpc/sysdev/qe_lib/ucc_fast.c +++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c @@ -1,13 +1,12 @@ /* - * arch/powerpc/sysdev/qe_lib/ucc_fast.c - * - * QE UCC Fast API Set - UCC Fast specific routines implementations. - * * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved. * * Authors: Shlomi Gridish <gridish@freescale.com> * Li Yang <leoli@freescale.com> * + * Description: + * QE UCC Fast API Set - UCC Fast specific routines implementations. + * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your @@ -27,79 +26,61 @@ #include <asm/ucc.h> #include <asm/ucc_fast.h> -#define uccf_printk(level, format, arg...) \ - printk(level format "\n", ## arg) - -#define uccf_dbg(format, arg...) \ - uccf_printk(KERN_DEBUG , format , ## arg) -#define uccf_err(format, arg...) \ - uccf_printk(KERN_ERR , format , ## arg) -#define uccf_info(format, arg...) \ - uccf_printk(KERN_INFO , format , ## arg) -#define uccf_warn(format, arg...) \ - uccf_printk(KERN_WARNING , format , ## arg) - -#ifdef UCCF_VERBOSE_DEBUG -#define uccf_vdbg uccf_dbg -#else -#define uccf_vdbg(fmt, args...) do { } while (0) -#endif /* UCCF_VERBOSE_DEBUG */ - void ucc_fast_dump_regs(struct ucc_fast_private * uccf) { - uccf_info("UCC%d Fast registers:", uccf->uf_info->ucc_num); - uccf_info("Base address: 0x%08x", (u32) uccf->uf_regs); + printk(KERN_INFO "UCC%d Fast registers:", uccf->uf_info->ucc_num); + printk(KERN_INFO "Base address: 0x%08x", (u32) uccf->uf_regs); - uccf_info("gumr : addr - 0x%08x, val - 0x%08x", + printk(KERN_INFO "gumr : addr - 0x%08x, val - 0x%08x", (u32) & uccf->uf_regs->gumr, in_be32(&uccf->uf_regs->gumr)); - uccf_info("upsmr : addr - 0x%08x, val - 0x%08x", + printk(KERN_INFO "upsmr : addr - 0x%08x, val - 0x%08x", (u32) & uccf->uf_regs->upsmr, in_be32(&uccf->uf_regs->upsmr)); - uccf_info("utodr : addr - 0x%08x, val - 0x%04x", + printk(KERN_INFO "utodr : addr - 0x%08x, val - 0x%04x", (u32) & uccf->uf_regs->utodr, in_be16(&uccf->uf_regs->utodr)); - uccf_info("udsr : addr - 0x%08x, val - 0x%04x", + printk(KERN_INFO "udsr : addr - 0x%08x, val - 0x%04x", (u32) & uccf->uf_regs->udsr, in_be16(&uccf->uf_regs->udsr)); - uccf_info("ucce : addr - 0x%08x, val - 0x%08x", + printk(KERN_INFO "ucce : addr - 0x%08x, val - 0x%08x", (u32) & uccf->uf_regs->ucce, in_be32(&uccf->uf_regs->ucce)); - uccf_info("uccm : addr - 0x%08x, val - 0x%08x", + printk(KERN_INFO "uccm : addr - 0x%08x, val - 0x%08x", (u32) & uccf->uf_regs->uccm, in_be32(&uccf->uf_regs->uccm)); - uccf_info("uccs : addr - 0x%08x, val - 0x%02x", + printk(KERN_INFO "uccs : addr - 0x%08x, val - 0x%02x", (u32) & uccf->uf_regs->uccs, uccf->uf_regs->uccs); - uccf_info("urfb : addr - 0x%08x, val - 0x%08x", + printk(KERN_INFO "urfb : addr - 0x%08x, val - 0x%08x", (u32) & uccf->uf_regs->urfb, in_be32(&uccf->uf_regs->urfb)); - uccf_info("urfs : addr - 0x%08x, val - 0x%04x", + printk(KERN_INFO "urfs : addr - 0x%08x, val - 0x%04x", (u32) & uccf->uf_regs->urfs, in_be16(&uccf->uf_regs->urfs)); - uccf_info("urfet : addr - 0x%08x, val - 0x%04x", + printk(KERN_INFO "urfet : addr - 0x%08x, val - 0x%04x", (u32) & uccf->uf_regs->urfet, in_be16(&uccf->uf_regs->urfet)); - uccf_info("urfset: addr - 0x%08x, val - 0x%04x", + printk(KERN_INFO "urfset: addr - 0x%08x, val - 0x%04x", (u32) & uccf->uf_regs->urfset, in_be16(&uccf->uf_regs->urfset)); - uccf_info("utfb : addr - 0x%08x, val - 0x%08x", + printk(KERN_INFO "utfb : addr - 0x%08x, val - 0x%08x", (u32) & uccf->uf_regs->utfb, in_be32(&uccf->uf_regs->utfb)); - uccf_info("utfs : addr - 0x%08x, val - 0x%04x", + printk(KERN_INFO "utfs : addr - 0x%08x, val - 0x%04x", (u32) & uccf->uf_regs->utfs, in_be16(&uccf->uf_regs->utfs)); - uccf_info("utfet : addr - 0x%08x, val - 0x%04x", + printk(KERN_INFO "utfet : addr - 0x%08x, val - 0x%04x", (u32) & uccf->uf_regs->utfet, in_be16(&uccf->uf_regs->utfet)); - uccf_info("utftt : addr - 0x%08x, val - 0x%04x", + printk(KERN_INFO "utftt : addr - 0x%08x, val - 0x%04x", (u32) & uccf->uf_regs->utftt, in_be16(&uccf->uf_regs->utftt)); - uccf_info("utpt : addr - 0x%08x, val - 0x%04x", + printk(KERN_INFO "utpt : addr - 0x%08x, val - 0x%04x", (u32) & uccf->uf_regs->utpt, in_be16(&uccf->uf_regs->utpt)); - uccf_info("urtry : addr - 0x%08x, val - 0x%08x", + printk(KERN_INFO "urtry : addr - 0x%08x, val - 0x%08x", (u32) & uccf->uf_regs->urtry, in_be32(&uccf->uf_regs->urtry)); - uccf_info("guemr : addr - 0x%08x, val - 0x%02x", + printk(KERN_INFO "guemr : addr - 0x%08x, val - 0x%02x", (u32) & uccf->uf_regs->guemr, uccf->uf_regs->guemr); } u32 ucc_fast_get_qe_cr_subblock(int uccf_num) { switch (uccf_num) { - case 0: return QE_CR_SUBBLOCK_UCCFAST1; + case 0: return QE_CR_SUBBLOCK_UCCFAST1; case 1: return QE_CR_SUBBLOCK_UCCFAST2; case 2: return QE_CR_SUBBLOCK_UCCFAST3; case 3: return QE_CR_SUBBLOCK_UCCFAST4; case 4: return QE_CR_SUBBLOCK_UCCFAST5; case 5: return QE_CR_SUBBLOCK_UCCFAST6; case 6: return QE_CR_SUBBLOCK_UCCFAST7; - case 7: return QE_CR_SUBBLOCK_UCCFAST8; + case 7: return QE_CR_SUBBLOCK_UCCFAST8; default: return QE_CR_SUBBLOCK_INVALID; } } @@ -153,84 +134,72 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc { struct ucc_fast_private *uccf; struct ucc_fast *uf_regs; - u32 gumr = 0; + u32 gumr; int ret; - uccf_vdbg("%s: IN", __FUNCTION__); - if (!uf_info) return -EINVAL; /* check if the UCC port number is in range. */ if ((uf_info->ucc_num < 0) || (uf_info->ucc_num > UCC_MAX_NUM - 1)) { - uccf_err("ucc_fast_init: Illegal UCC number!"); + printk(KERN_ERR "%s: illegal UCC number", __FUNCTION__); return -EINVAL; } /* Check that 'max_rx_buf_length' is properly aligned (4). */ if (uf_info->max_rx_buf_length & (UCC_FAST_MRBLR_ALIGNMENT - 1)) { - uccf_err("ucc_fast_init: max_rx_buf_length not aligned."); + printk(KERN_ERR "%s: max_rx_buf_length not aligned", __FUNCTION__); return -EINVAL; } /* Validate Virtual Fifo register values */ if (uf_info->urfs < UCC_FAST_URFS_MIN_VAL) { - uccf_err - ("ucc_fast_init: Virtual Fifo register urfs too small."); + printk(KERN_ERR "%s: urfs is too small", __FUNCTION__); return -EINVAL; } if (uf_info->urfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) { - uccf_err - ("ucc_fast_init: Virtual Fifo register urfs not aligned."); + printk(KERN_ERR "%s: urfs is not aligned", __FUNCTION__); return -EINVAL; } if (uf_info->urfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) { - uccf_err - ("ucc_fast_init: Virtual Fifo register urfet not aligned."); + printk(KERN_ERR "%s: urfet is not aligned.", __FUNCTION__); return -EINVAL; } if (uf_info->urfset & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) { - uccf_err - ("ucc_fast_init: Virtual Fifo register urfset not aligned."); + printk(KERN_ERR "%s: urfset is not aligned", __FUNCTION__); return -EINVAL; } if (uf_info->utfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) { - uccf_err - ("ucc_fast_init: Virtual Fifo register utfs not aligned."); + printk(KERN_ERR "%s: utfs is not aligned", __FUNCTION__); return -EINVAL; } if (uf_info->utfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) { - uccf_err - ("ucc_fast_init: Virtual Fifo register utfet not aligned."); + printk(KERN_ERR "%s: utfet is not aligned", __FUNCTION__); return -EINVAL; } if (uf_info->utftt & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) { - uccf_err - ("ucc_fast_init: Virtual Fifo register utftt not aligned."); + printk(KERN_ERR "%s: utftt is not aligned", __FUNCTION__); return -EINVAL; } uccf = kzalloc(sizeof(struct ucc_fast_private), GFP_KERNEL); if (!uccf) { - uccf_err - ("ucc_fast_init: No memory for UCC slow data structure!"); + printk(KERN_ERR "%s: Cannot allocate private data", __FUNCTION__); return -ENOMEM; } /* Fill fast UCC structure */ uccf->uf_info = uf_info; /* Set the PHY base address */ - uccf->uf_regs = - (struct ucc_fast *) ioremap(uf_info->regs, sizeof(struct ucc_fast)); + uccf->uf_regs = ioremap(uf_info->regs, sizeof(struct ucc_fast)); if (uccf->uf_regs == NULL) { - uccf_err - ("ucc_fast_init: No memory map for UCC slow controller!"); + printk(KERN_ERR "%s: Cannot map UCC registers", __FUNCTION__); return -ENOMEM; } @@ -249,7 +218,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc /* Init Guemr register */ if ((ret = ucc_init_guemr((struct ucc_common *) (uf_regs)))) { - uccf_err("ucc_fast_init: Could not init the guemr register."); + printk(KERN_ERR "%s: cannot init GUEMR", __FUNCTION__); ucc_fast_free(uccf); return ret; } @@ -258,7 +227,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc if ((ret = ucc_set_type(uf_info->ucc_num, (struct ucc_common *) (uf_regs), UCC_SPEED_TYPE_FAST))) { - uccf_err("ucc_fast_init: Could not set type to fast."); + printk(KERN_ERR "%s: cannot set UCC type", __FUNCTION__); ucc_fast_free(uccf); return ret; } @@ -267,10 +236,9 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc /* Set GUMR */ /* For more details see the hardware spec. */ - /* gumr starts as zero. */ + gumr = uf_info->ttx_trx; if (uf_info->tci) gumr |= UCC_FAST_GUMR_TCI; - gumr |= uf_info->ttx_trx; if (uf_info->cdp) gumr |= UCC_FAST_GUMR_CDP; if (uf_info->ctsp) @@ -298,9 +266,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc uccf->ucc_fast_tx_virtual_fifo_base_offset = qe_muram_alloc(uf_info->utfs, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT); if (IS_MURAM_ERR(uccf->ucc_fast_tx_virtual_fifo_base_offset)) { - uccf_err - ("ucc_fast_init: Can not allocate MURAM memory for " - "struct ucc_fastx_virtual_fifo_base_offset."); + printk(KERN_ERR "%s: cannot allocate MURAM for TX FIFO", __FUNCTION__); uccf->ucc_fast_tx_virtual_fifo_base_offset = 0; ucc_fast_free(uccf); return -ENOMEM; @@ -308,14 +274,11 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc /* Allocate memory for Rx Virtual Fifo */ uccf->ucc_fast_rx_virtual_fifo_base_offset = - qe_muram_alloc(uf_info->urfs + - (u32) + qe_muram_alloc(uf_info->urfs + UCC_FAST_RECEIVE_VIRTUAL_FIFO_SIZE_FUDGE_FACTOR, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT); if (IS_MURAM_ERR(uccf->ucc_fast_rx_virtual_fifo_base_offset)) { - uccf_err - ("ucc_fast_init: Can not allocate MURAM memory for " - "ucc_fast_rx_virtual_fifo_base_offset."); + printk(KERN_ERR "%s: cannot allocate MURAM for RX FIFO", __FUNCTION__); uccf->ucc_fast_rx_virtual_fifo_base_offset = 0; ucc_fast_free(uccf); return -ENOMEM; @@ -342,26 +305,22 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc /* If NMSI (not Tsa), set Tx and Rx clock. */ if (!uf_info->tsa) { /* Rx clock routing */ - if (uf_info->rx_clock != QE_CLK_NONE) { - if (ucc_set_qe_mux_rxtx - (uf_info->ucc_num, uf_info->rx_clock, - COMM_DIR_RX)) { - uccf_err - ("ucc_fast_init: Illegal value for parameter 'RxClock'."); - ucc_fast_free(uccf); - return -EINVAL; - } + if ((uf_info->rx_clock != QE_CLK_NONE) && + ucc_set_qe_mux_rxtx(uf_info->ucc_num, uf_info->rx_clock, + COMM_DIR_RX)) { + printk(KERN_ERR "%s: illegal value for RX clock", + __FUNCTION__); + ucc_fast_free(uccf); + return -EINVAL; } /* Tx clock routing */ - if (uf_info->tx_clock != QE_CLK_NONE) { - if (ucc_set_qe_mux_rxtx - (uf_info->ucc_num, uf_info->tx_clock, - COMM_DIR_TX)) { - uccf_err - ("ucc_fast_init: Illegal value for parameter 'TxClock'."); - ucc_fast_free(uccf); - return -EINVAL; - } + if ((uf_info->tx_clock != QE_CLK_NONE) && + ucc_set_qe_mux_rxtx(uf_info->ucc_num, uf_info->tx_clock, + COMM_DIR_TX)) { + printk(KERN_ERR "%s: illegal value for TX clock", + __FUNCTION__); + ucc_fast_free(uccf); + return -EINVAL; } } @@ -370,9 +329,9 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc /* First, clear anything pending at UCC level, * otherwise, old garbage may come through - * as soon as the dam is opened - * Writing '1' clears - */ + * as soon as the dam is opened. */ + + /* Writing '1' clears */ out_be32(&uf_regs->ucce, 0xffffffff); *uccf_ret = uccf; diff --git a/arch/powerpc/sysdev/qe_lib/ucc_slow.c b/arch/powerpc/sysdev/qe_lib/ucc_slow.c index 0e97e5c94f8..817df73ecf5 100644 --- a/arch/powerpc/sysdev/qe_lib/ucc_slow.c +++ b/arch/powerpc/sysdev/qe_lib/ucc_slow.c @@ -19,7 +19,6 @@ #include <linux/stddef.h> #include <linux/interrupt.h> -#include <asm/irq.h> #include <asm/io.h> #include <asm/immap_qe.h> #include <asm/qe.h> @@ -27,24 +26,6 @@ #include <asm/ucc.h> #include <asm/ucc_slow.h> -#define uccs_printk(level, format, arg...) \ - printk(level format "\n", ## arg) - -#define uccs_dbg(format, arg...) \ - uccs_printk(KERN_DEBUG , format , ## arg) -#define uccs_err(format, arg...) \ - uccs_printk(KERN_ERR , format , ## arg) -#define uccs_info(format, arg...) \ - uccs_printk(KERN_INFO , format , ## arg) -#define uccs_warn(format, arg...) \ - uccs_printk(KERN_WARNING , format , ## arg) - -#ifdef UCCS_VERBOSE_DEBUG -#define uccs_vdbg uccs_dbg -#else -#define uccs_vdbg(fmt, args...) do { } while (0) -#endif /* UCCS_VERBOSE_DEBUG */ - u32 ucc_slow_get_qe_cr_subblock(int uccs_num) { switch (uccs_num) { @@ -135,51 +116,53 @@ void ucc_slow_disable(struct ucc_slow_private * uccs, enum comm_dir mode) int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** uccs_ret) { + struct ucc_slow_private *uccs; u32 i; struct ucc_slow *us_regs; u32 gumr; - u8 function_code = 0; - u8 *bd; - struct ucc_slow_private *uccs; + struct qe_bd *bd; u32 id; u32 command; - int ret; - - uccs_vdbg("%s: IN", __FUNCTION__); + int ret = 0; if (!us_info) return -EINVAL; /* check if the UCC port number is in range. */ if ((us_info->ucc_num < 0) || (us_info->ucc_num > UCC_MAX_NUM - 1)) { - uccs_err("ucc_slow_init: Illegal UCC number!"); + printk(KERN_ERR "%s: illegal UCC number", __FUNCTION__); return -EINVAL; } /* * Set mrblr * Check that 'max_rx_buf_length' is properly aligned (4), unless - * rfw is 1, meaning that QE accepts one byte at a time, unlike normal + * rfw is 1, meaning that QE accepts one byte at a time, unlike normal * case when QE accepts 32 bits at a time. */ if ((!us_info->rfw) && (us_info->max_rx_buf_length & (UCC_SLOW_MRBLR_ALIGNMENT - 1))) { - uccs_err("max_rx_buf_length not aligned."); + printk(KERN_ERR "max_rx_buf_length not aligned."); return -EINVAL; } uccs = kzalloc(sizeof(struct ucc_slow_private), GFP_KERNEL); if (!uccs) { - uccs_err - ("ucc_slow_init: No memory for UCC slow data structure!"); + printk(KERN_ERR "%s: Cannot allocate private data", __FUNCTION__); return -ENOMEM; } /* Fill slow UCC structure */ uccs->us_info = us_info; + /* Set the PHY base address */ + uccs->us_regs = ioremap(us_info->regs, sizeof(struct ucc_slow)); + if (uccs->us_regs == NULL) { + printk(KERN_ERR "%s: Cannot map UCC registers", __FUNCTION__); + return -ENOMEM; + } + uccs->saved_uccm = 0; uccs->p_rx_frame = 0; - uccs->us_regs = us_info->regs; us_regs = uccs->us_regs; uccs->p_ucce = (u16 *) & (us_regs->ucce); uccs->p_uccm = (u16 *) & (us_regs->uccm); @@ -190,24 +173,22 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc #endif /* STATISTICS */ /* Get PRAM base */ - uccs->us_pram_offset = qe_muram_alloc(UCC_SLOW_PRAM_SIZE, - ALIGNMENT_OF_UCC_SLOW_PRAM); + uccs->us_pram_offset = + qe_muram_alloc(UCC_SLOW_PRAM_SIZE, ALIGNMENT_OF_UCC_SLOW_PRAM); if (IS_MURAM_ERR(uccs->us_pram_offset)) { - uccs_err - ("ucc_slow_init: Can not allocate MURAM memory " - "for Slow UCC."); + printk(KERN_ERR "%s: cannot allocate MURAM for PRAM", __FUNCTION__); ucc_slow_free(uccs); return -ENOMEM; } id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num); qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, id, QE_CR_PROTOCOL_UNSPECIFIED, - (u32) uccs->us_pram_offset); + uccs->us_pram_offset); uccs->us_pram = qe_muram_addr(uccs->us_pram_offset); /* Init Guemr register */ if ((ret = ucc_init_guemr((struct ucc_common *) (us_info->regs)))) { - uccs_err("ucc_slow_init: Could not init the guemr register."); + printk(KERN_ERR "%s: cannot init GUEMR", __FUNCTION__); ucc_slow_free(uccs); return ret; } @@ -216,7 +197,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc if ((ret = ucc_set_type(us_info->ucc_num, (struct ucc_common *) (us_info->regs), UCC_SPEED_TYPE_SLOW))) { - uccs_err("ucc_slow_init: Could not init the guemr register."); + printk(KERN_ERR "%s: cannot set UCC type", __FUNCTION__); ucc_slow_free(uccs); return ret; } @@ -230,7 +211,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc qe_muram_alloc(us_info->rx_bd_ring_len * sizeof(struct qe_bd), QE_ALIGNMENT_OF_BD); if (IS_MURAM_ERR(uccs->rx_base_offset)) { - uccs_err("ucc_slow_init: No memory for Rx BD's."); + printk(KERN_ERR "%s: cannot allocate RX BDs", __FUNCTION__); uccs->rx_base_offset = 0; ucc_slow_free(uccs); return -ENOMEM; @@ -240,7 +221,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc qe_muram_alloc(us_info->tx_bd_ring_len * sizeof(struct qe_bd), QE_ALIGNMENT_OF_BD); if (IS_MURAM_ERR(uccs->tx_base_offset)) { - uccs_err("ucc_slow_init: No memory for Tx BD's."); + printk(KERN_ERR "%s: cannot allocate TX BDs", __FUNCTION__); uccs->tx_base_offset = 0; ucc_slow_free(uccs); return -ENOMEM; @@ -248,34 +229,33 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc /* Init Tx bds */ bd = uccs->confBd = uccs->tx_bd = qe_muram_addr(uccs->tx_base_offset); - for (i = 0; i < us_info->tx_bd_ring_len; i++) { + for (i = 0; i < us_info->tx_bd_ring_len - 1; i++) { /* clear bd buffer */ - out_be32(&(((struct qe_bd *)bd)->buf), 0); + out_be32(&bd->buf, 0); /* set bd status and length */ - out_be32((u32*)bd, 0); - bd += sizeof(struct qe_bd); + out_be32((u32 *) bd, 0); + bd++; } - bd -= sizeof(struct qe_bd); - /* set bd status and length */ - out_be32((u32*)bd, T_W); /* for last BD set Wrap bit */ + /* for last BD set Wrap bit */ + out_be32(&bd->buf, 0); + out_be32((u32 *) bd, cpu_to_be32(T_W)); /* Init Rx bds */ bd = uccs->rx_bd = qe_muram_addr(uccs->rx_base_offset); - for (i = 0; i < us_info->rx_bd_ring_len; i++) { + for (i = 0; i < us_info->rx_bd_ring_len - 1; i++) { /* set bd status and length */ out_be32((u32*)bd, 0); /* clear bd buffer */ - out_be32(&(((struct qe_bd *)bd)->buf), 0); - bd += sizeof(struct qe_bd); + out_be32(&bd->buf, 0); + bd++; } - bd -= sizeof(struct qe_bd); - /* set bd status and length */ - out_be32((u32*)bd, R_W); /* for last BD set Wrap bit */ + /* for last BD set Wrap bit */ + out_be32((u32*)bd, cpu_to_be32(R_W)); + out_be32(&bd->buf, 0); /* Set GUMR (For more details see the hardware spec.). */ /* gumr_h */ - gumr = 0; - gumr |= us_info->tcrc; + gumr = us_info->tcrc; if (us_info->cdp) gumr |= UCC_SLOW_GUMR_H_CDP; if (us_info->ctsp) @@ -295,7 +275,8 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc out_be32(&us_regs->gumr_h, gumr); /* gumr_l */ - gumr = 0; + gumr = us_info->tdcr | us_info->rdcr | us_info->tenc | us_info->renc | + us_info->diag | us_info->mode; if (us_info->tci) gumr |= UCC_SLOW_GUMR_L_TCI; if (us_info->rinv) @@ -304,23 +285,14 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc gumr |= UCC_SLOW_GUMR_L_TINV; if (us_info->tend) gumr |= UCC_SLOW_GUMR_L_TEND; - gumr |= us_info->tdcr; - gumr |= us_info->rdcr; - gumr |= us_info->tenc; - gumr |= us_info->renc; - gumr |= us_info->diag; - gumr |= us_info->mode; out_be32(&us_regs->gumr_l, gumr); /* Function code registers */ - /* function_code has initial value 0 */ /* if the data is in cachable memory, the 'global' */ /* in the function code should be set. */ - function_code |= us_info->data_mem_part; - function_code |= QE_BMR_BYTE_ORDER_BO_MOT; /* Required for QE */ - uccs->us_pram->tfcr = function_code; - uccs->us_pram->rfcr = function_code; + uccs->us_pram->tfcr = uccs->us_pram->rfcr = + us_info->data_mem_part | QE_BMR_BYTE_ORDER_BO_MOT; /* rbase, tbase are offsets from MURAM base */ out_be16(&uccs->us_pram->rbase, uccs->us_pram_offset); @@ -336,34 +308,29 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc /* If NMSI (not Tsa), set Tx and Rx clock. */ if (!us_info->tsa) { /* Rx clock routing */ - if (ucc_set_qe_mux_rxtx - (us_info->ucc_num, us_info->rx_clock, COMM_DIR_RX)) { - uccs_err - ("ucc_slow_init: Illegal value for parameter" - " 'RxClock'."); + if (ucc_set_qe_mux_rxtx(us_info->ucc_num, us_info->rx_clock, + COMM_DIR_RX)) { + printk(KERN_ERR "%s: illegal value for RX clock", + __FUNCTION__); ucc_slow_free(uccs); return -EINVAL; } /* Tx clock routing */ - if (ucc_set_qe_mux_rxtx(us_info->ucc_num, - us_info->tx_clock, COMM_DIR_TX)) { - uccs_err - ("ucc_slow_init: Illegal value for parameter " - "'TxClock'."); + if (ucc_set_qe_mux_rxtx(us_info->ucc_num, us_info->tx_clock, + COMM_DIR_TX)) { + printk(KERN_ERR "%s: illegal value for TX clock", + __FUNCTION__); ucc_slow_free(uccs); return -EINVAL; } } - /* - * INTERRUPTS - */ /* Set interrupt mask register at UCC level. */ out_be16(&us_regs->uccm, us_info->uccm_mask); - /* First, clear anything pending at UCC level, */ - /* otherwise, old garbage may come through */ - /* as soon as the dam is opened. */ + /* First, clear anything pending at UCC level, + * otherwise, old garbage may come through + * as soon as the dam is opened. */ /* Writing '1' clears */ out_be16(&us_regs->ucce, 0xffff); @@ -400,3 +367,5 @@ void ucc_slow_free(struct ucc_slow_private * uccs) kfree(uccs); } + + |