* Re: [RFC PATCH v0.2] net driver: mpc52xx fec
From: Sven Luther @ 2007-09-17 9:53 UTC (permalink / raw)
To: Domen Puncer; +Cc: netdev, linuxppc-embedded
In-Reply-To: <20070915121444.GA19857@nd47.coderock.org>
On Sat, Sep 15, 2007 at 02:14:44PM +0200, Domen Puncer wrote:
> Updated and split version at:
> http://coderock.org/tmp/fec-v3rc1/
>
> I'll repost to lists once I run-test them.
When applying those patches, the build did die with :
ERROR: "phy_mii_ioctl" [drivers/net/fec_mpc52xx/fec_mpc52xx.ko] undefined!
Apparently, phy_mii_ioctl is not an exported symbol.
Domen, did you maybe forget a little snipplet when you cut the patches
in different pieces ? Or did i mess up applying them ?
Friendly,
Sven Luther
^ permalink raw reply
* Re: [PATCH 4/7] powerpc: BestComm core support for Freescale MPC5200
From: Matt Sealey @ 2007-09-17 8:57 UTC (permalink / raw)
To: Sylvain Munaut; +Cc: Grant Likely, Paul Mackerras, PowerPC dev list
In-Reply-To: <1189940011134-git-send-email-tnt@246tNt.com>
My only nitpick is the function naming.
Why not bestcomm_blah() rather than bcom_blah()?
I also think, even though the SRAM functionality is dependant
on BestComm (it's hard to seperate into another driver because
of kernel driver init order being 'random'?) it should be named
after the chip and not the DMA unit - the SRAM can be used for
pretty much anything a developer wants.
For instance, you could allocate it for the power management
code, or simply as some kind of buffer between a PIO managed
port if you do not want to use main memory for some reason.
On the MPC5121E it looks like AXE (audio DSP) and certain other
components will be sharing SRAM with BestComm and there will
be a good deal more of it.
Just looking to the future on some code sharing, because of
the above.
On a lighter note (not something that should block these
patches), would it be a good idea perhaps to abstract SRAM
allocations into a driver class of it's own in this same
way? Nearly every SoC has some kind of built-in SRAM and
even some Northbridges (Marvell Discovery) - ostensibly for
peripheral buffers like ethernet and so on, they can still
be used for anything. Couldn't it be a library or driver
simply with a custom init/teardown function (platform
specific)? I suppose the fact that SRAM could be probed
after BestComm or other peripherals is the problem here,
but there is a platform device for Pegasos ethernet which
modifies Discovery SRAM parameters.. I suppose this is
what I am thinking of getting rid of and allowing code
to be shared and SRAM allocation and usage becoming more
of a tool for other devices and drivers to use, and not
simply something claimed/controlled by BestComm or Ethernet,
and occasionally hijacked by something else.
--
Matt Sealey <matt@genesi-usa.com>
Genesi, Manager, Developer Relations
Sylvain Munaut wrote:
> This patch adds support for the core of the BestComm API
> for the Freescale MPC5200(b). The BestComm engine is a
> microcode-controlled / tasks-based DMA used by several
> of the onchip devices.
>
> Setting up the tasks / memory allocation and all common
> low level functions are handled by this patch.
> The specifics details of each tasks and their microcode
> are split-out in separate patches.
>
> This is not the official API, but a much cleaner one.
> (hopefully)
>
> Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
> ---
> arch/powerpc/platforms/Kconfig | 2 +
> arch/powerpc/sysdev/Makefile | 1 +
> arch/powerpc/sysdev/bestcomm/Kconfig | 18 +
> arch/powerpc/sysdev/bestcomm/Makefile | 8 +
> arch/powerpc/sysdev/bestcomm/bestcomm.c | 657 ++++++++++++++++++++++++++
> arch/powerpc/sysdev/bestcomm/bestcomm.h | 136 ++++++
> arch/powerpc/sysdev/bestcomm/bestcomm_priv.h | 325 +++++++++++++
> arch/powerpc/sysdev/bestcomm/sram.c | 177 +++++++
> arch/powerpc/sysdev/bestcomm/sram.h | 54 +++
> 9 files changed, 1378 insertions(+), 0 deletions(-)
> create mode 100644 arch/powerpc/sysdev/bestcomm/Kconfig
> create mode 100644 arch/powerpc/sysdev/bestcomm/Makefile
> create mode 100644 arch/powerpc/sysdev/bestcomm/bestcomm.c
> create mode 100644 arch/powerpc/sysdev/bestcomm/bestcomm.h
> create mode 100644 arch/powerpc/sysdev/bestcomm/bestcomm_priv.h
> create mode 100644 arch/powerpc/sysdev/bestcomm/sram.c
> create mode 100644 arch/powerpc/sysdev/bestcomm/sram.h
>
> diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
> index 9189ba5..99d48be 100644
> --- a/arch/powerpc/platforms/Kconfig
> +++ b/arch/powerpc/platforms/Kconfig
> @@ -293,4 +293,6 @@ config FSL_ULI1575
> Freescale reference boards. The boards all use the ULI in pretty
> much the same way.
>
> +source "arch/powerpc/sysdev/bestcomm/Kconfig"
> +
> endmenu
> diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
> index 08ce31e..0c8a29d 100644
> --- a/arch/powerpc/sysdev/Makefile
> +++ b/arch/powerpc/sysdev/Makefile
> @@ -15,6 +15,7 @@ obj-$(CONFIG_FSL_SOC) += fsl_soc.o
> obj-$(CONFIG_FSL_PCI) += fsl_pci.o
> obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
> obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
> +obj-$(CONFIG_PPC_BESTCOMM) += bestcomm/
> mv64x60-$(CONFIG_PCI) += mv64x60_pci.o
> obj-$(CONFIG_MV64X60) += $(mv64x60-y) mv64x60_pic.o mv64x60_dev.o
> obj-$(CONFIG_RTC_DRV_CMOS) += rtc_cmos_setup.o
> diff --git a/arch/powerpc/sysdev/bestcomm/Kconfig b/arch/powerpc/sysdev/bestcomm/Kconfig
> new file mode 100644
> index 0000000..3366e24
> --- /dev/null
> +++ b/arch/powerpc/sysdev/bestcomm/Kconfig
> @@ -0,0 +1,18 @@
> +#
> +# Kconfig options for Bestcomm
> +#
> +
> +config PPC_BESTCOMM
> + tristate "Bestcomm DMA engine support"
> + depends on PPC_MPC52xx
> + default n
> + select PPC_LIB_RHEAP
> + help
> + BestComm is the name of the communication coprocessor found
> + on the Freescale MPC5200 family of processor. It's usage is
> + optionnal for some drivers (like ATA), but required for
> + others (like FEC).
> +
> + If you want to use drivers that require DMA operations,
> + answer Y or M. Otherwise say N.
> +
> diff --git a/arch/powerpc/sysdev/bestcomm/Makefile b/arch/powerpc/sysdev/bestcomm/Makefile
> new file mode 100644
> index 0000000..a24aa06
> --- /dev/null
> +++ b/arch/powerpc/sysdev/bestcomm/Makefile
> @@ -0,0 +1,8 @@
> +#
> +# Makefile for BestComm & co
> +#
> +
> +bestcomm-core-objs := bestcomm.o sram.o
> +
> +obj-$(CONFIG_PPC_BESTCOMM) += bestcomm-core.o
> +
> diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm.c b/arch/powerpc/sysdev/bestcomm/bestcomm.c
> new file mode 100644
> index 0000000..10fb476
> --- /dev/null
> +++ b/arch/powerpc/sysdev/bestcomm/bestcomm.c
> @@ -0,0 +1,657 @@
> +/*
> + * Driver for MPC52xx processor BestComm peripheral controller
> + *
> + *
> + * Copyright (C) 2006-2007 Sylvain Munaut <tnt@246tNt.com>
> + * Copyright (C) 2005 Varma Electronics Oy,
> + * ( by Andrey Volkov <avolkov@varma-el.com> )
> + * Copyright (C) 2003-2004 MontaVista, Software, Inc.
> + * ( by Dale Farnsworth <dfarnsworth@mvista.com> )
> + *
> + * This file is licensed under the terms of the GNU General Public License
> + * version 2. This program is licensed "as is" without any warranty of any
> + * kind, whether express or implied.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +
> +#include <asm/io.h>
> +#include <asm/irq.h>
> +#include <asm/prom.h>
> +#include <asm/mpc52xx.h>
> +#include <asm/of_device.h>
> +#include <asm/of_platform.h>
> +
> +#include "sram.h"
> +#include "bestcomm_priv.h"
> +#include "bestcomm.h"
> +
> +#define DRIVER_NAME "bestcomm-core"
> +
> +
> +struct bcom_engine *bcom_eng = NULL;
> +EXPORT_SYMBOL_GPL(bcom_eng); /* needed for inline functions */
> +
> +
> +/* ======================================================================== */
> +/* Public and private API */
> +/* ======================================================================== */
> +
> +/* Debug Dump */
> +
> +#define BCOM_DPRINTK(a,b...) printk(KERN_DEBUG DRIVER_NAME ": " a, ## b)
> +
> +void
> +bcom_dump_status(void)
> +{
> + int i;
> + struct mpc52xx_sdma __iomem *r = bcom_eng->regs;
> +
> + BCOM_DPRINTK("BestComm status dump (pa=%08lx, va=%p)\n",
> + bcom_eng->regs_base, bcom_eng->regs);
> + BCOM_DPRINTK(" taskBar = %08x\n", in_be32(&r->taskBar));
> + BCOM_DPRINTK(" currentPointer = %08x\n", in_be32(&r->currentPointer));
> + BCOM_DPRINTK(" endPointer = %08x\n", in_be32(&r->endPointer));
> + BCOM_DPRINTK(" variablePointer = %08x\n", in_be32(&r->variablePointer));
> + BCOM_DPRINTK(" IntVect1 = %08x\n", (u32)in_8(&r->IntVect1));
> + BCOM_DPRINTK(" IntVect2 = %08x\n", (u32)in_8(&r->IntVect2));
> + BCOM_DPRINTK(" PtdCntrl = %08hx\n", in_be16(&r->PtdCntrl));
> + BCOM_DPRINTK(" IntPend = %08x\n", in_be32(&r->IntPend));
> + BCOM_DPRINTK(" IntMask = %08x\n", in_be32(&r->IntMask));
> +
> + BCOM_DPRINTK(" TCR dump :\n");
> +
> + for (i=0; i<16; i++) {
> + printk("%s%04hx%s",
> + (i&0x7) == 0x0 ? KERN_DEBUG "\t" : "",
> + in_be16(&r->tcr[i]),
> + (i&0x7) == 0x7 ? "\n" : " ");
> + }
> +
> + BCOM_DPRINTK(" IPR dump :\n");
> +
> + for (i=0; i<32; i++) {
> + printk("%s%02x%s",
> + (i&0x7) == 0x0 ? KERN_DEBUG "\t" : "",
> + (u32)in_8(&r->ipr[i]),
> + (i&0x7) == 0x7 ? "\n" : " ");
> + }
> +
> + BCOM_DPRINTK(" cReqSelect = %08x\n", in_be32(&r->cReqSelect));
> + BCOM_DPRINTK(" task_size0 = %08x\n", in_be32(&r->task_size0));
> + BCOM_DPRINTK(" task_size1 = %08x\n", in_be32(&r->task_size1));
> + BCOM_DPRINTK(" MDEDebug = %08x\n", in_be32(&r->MDEDebug));
> + BCOM_DPRINTK(" ADSDebug = %08x\n", in_be32(&r->ADSDebug));
> + BCOM_DPRINTK(" Value1 = %08x\n", in_be32(&r->Value1));
> + BCOM_DPRINTK(" Value2 = %08x\n", in_be32(&r->Value2));
> + BCOM_DPRINTK(" Control = %08x\n", in_be32(&r->Control));
> + BCOM_DPRINTK(" Status = %08x\n", in_be32(&r->Status));
> + BCOM_DPRINTK(" PTDDebug = %08x\n", in_be32(&r->PTDDebug));
> +}
> +EXPORT_SYMBOL_GPL(bcom_dump_status);
> +
> +void
> +bcom_dump_task(int task)
> +{
> + int i;
> + u32 *p;
> + struct bcom_tdt *tdt = &bcom_eng->tdt[task];
> +
> + BCOM_DPRINTK("Task dump %d\n", task);
> + BCOM_DPRINTK(" tcr = %04hx\n", bcom_eng->regs->tcr[task]);
> + BCOM_DPRINTK(" tdt = %p\n", &bcom_eng->tdt[task]);
> + BCOM_DPRINTK(" tdt->start = %08x\n", tdt->start);
> + BCOM_DPRINTK(" tdt->stop = %08x\n", tdt->stop);
> + BCOM_DPRINTK(" tdt->var = %08x\n", tdt->var);
> + BCOM_DPRINTK(" tdt->fdt = %08x\n", tdt->fdt);
> + BCOM_DPRINTK(" tdt->status = %08x\n", tdt->exec_status);
> + BCOM_DPRINTK(" tdt->mvtp = %08x\n", tdt->mvtp);
> + BCOM_DPRINTK(" tdt->context = %08x\n", tdt->context);
> + BCOM_DPRINTK(" tdt->litbase = %08x\n", tdt->litbase);
> +
> + BCOM_DPRINTK(" code :\n");
> +
> + p = bcom_task_desc(task);
> + for (i=0; i<bcom_task_num_descs(task); i++)
> + printk(KERN_DEBUG "\t%p %08x\n", &p[i], p[i]);
> +
> + BCOM_DPRINTK(" var/inc :\n");
> +
> + p = bcom_task_var(task);
> + for (i=0; i<BCOM_MAX_VAR+BCOM_MAX_INC; i++)
> + printk(KERN_DEBUG "\t%p %08x\n", &p[i], p[i]);
> +}
> +EXPORT_SYMBOL_GPL(bcom_dump_task);
> +
> +void
> +bcom_dump_bdring(struct bcom_task *tsk)
> +{
> + int i, j;
> +
> + BCOM_DPRINTK("BD ring dump %d\n", tsk->tasknum);
> +
> + for (i=0; i<tsk->num_bd; i++) {
> + BCOM_DPRINTK(" BD[%02d] :\n", i);
> + BCOM_DPRINTK(" cookie : %p\n", tsk->cookie[i]);
> + BCOM_DPRINTK(" status : %08x\n", tsk->bd[i].status);
> + for (j=0; j<(tsk->bd_size/sizeof(u32))-1; j++)
> + BCOM_DPRINTK(" data[%02d] : %08x\n",
> + j, tsk->bd[i].data[j]);
> + }
> +}
> +EXPORT_SYMBOL_GPL(bcom_dump_bdring);
> +
> +
> +/* Private API */
> +
> +struct bcom_task *
> +bcom_task_alloc(int bd_count, int bd_size, int priv_size)
> +{
> + int i, tasknum = -1;
> + struct bcom_task *tsk;
> +
> + /* Get and reserve a task num */
> + spin_lock(&bcom_eng->lock);
> +
> + for (i=0; i<BCOM_MAX_TASKS; i++)
> + if (!bcom_eng->tdt[i].stop) { /* we use stop as a marker */
> + bcom_eng->tdt[i].stop = 0xfffffffful; /* dummy addr */
> + tasknum = i;
> + break;
> + }
> +
> + spin_unlock(&bcom_eng->lock);
> +
> + if (tasknum < 0)
> + return NULL;
> +
> + /* Allocate our structure */
> + tsk = kzalloc(sizeof(struct bcom_task) + priv_size, GFP_KERNEL);
> + if (!tsk)
> + goto error;
> +
> + tsk->tasknum = tasknum;
> + if (priv_size)
> + tsk->priv = (void*)tsk + sizeof(struct bcom_task);
> +
> + /* Get IRQ of that task */
> + tsk->irq = irq_of_parse_and_map(bcom_eng->ofnode, tsk->tasknum);
> + if (tsk->irq == NO_IRQ)
> + goto error;
> +
> + /* Init the BDs, if needed */
> + if (bd_count) {
> + tsk->cookie = kmalloc(sizeof(void*) * bd_count, GFP_KERNEL);
> + if (!tsk->cookie)
> + goto error;
> +
> + tsk->bd = bcom_sram_alloc(bd_count * bd_size, 4, &tsk->bd_pa);
> + if (!tsk->bd)
> + goto error;
> + memset(tsk->bd, 0x00, bd_count * bd_size);
> +
> + tsk->num_bd = bd_count;
> + tsk->bd_size = bd_size;
> + }
> +
> + return tsk;
> +
> +error:
> + if (tsk) {
> + if (tsk->irq != NO_IRQ)
> + irq_dispose_mapping(tsk->irq);
> + bcom_sram_free(tsk->bd);
> + kfree(tsk->cookie);
> + kfree(tsk);
> + }
> +
> + bcom_eng->tdt[tasknum].stop = 0;
> +
> + return NULL;
> +}
> +EXPORT_SYMBOL_GPL(bcom_task_alloc);
> +
> +void
> +bcom_task_release(struct bcom_task *tsk)
> +{
> + /* Stop the task */
> + bcom_disable_task(tsk->tasknum);
> +
> + /* Clear TDT */
> + bcom_eng->tdt[tsk->tasknum].start = 0;
> + bcom_eng->tdt[tsk->tasknum].stop = 0;
> +
> + /* Free everything */
> + irq_dispose_mapping(tsk->irq);
> + bcom_sram_free(tsk->bd);
> + kfree(tsk->cookie);
> + kfree(tsk);
> +}
> +EXPORT_SYMBOL_GPL(bcom_task_release);
> +
> +int
> +bcom_load_image(int task, u32 *task_image)
> +{
> + struct bcom_task_header *hdr = (struct bcom_task_header *)task_image;
> + struct bcom_tdt *tdt;
> + u32 *desc, *var, *inc;
> + u32 *desc_src, *var_src, *inc_src;
> +
> + /* Safety checks */
> + if (hdr->magic != BCOM_TASK_MAGIC) {
> + printk(KERN_ERR DRIVER_NAME
> + ": Trying to load invalid microcode\n");
> + return -EINVAL;
> + }
> +
> + if ((task < 0) || (task >= BCOM_MAX_TASKS)) {
> + printk(KERN_ERR DRIVER_NAME
> + ": Trying to load invalid task %d\n", task);
> + return -EINVAL;
> + }
> +
> + /* Initial load or reload */
> + tdt = &bcom_eng->tdt[task];
> +
> + if (tdt->start) {
> + desc = bcom_task_desc(task);
> + if (hdr->desc_size != bcom_task_num_descs(task)) {
> + printk(KERN_ERR DRIVER_NAME
> + ": Trying to reload wrong task image "
> + "(%d size %d/%d)!\n",
> + task,
> + hdr->desc_size,
> + bcom_task_num_descs(task));
> + return -EINVAL;
> + }
> + } else {
> + phys_addr_t start_pa;
> +
> + desc = bcom_sram_alloc(hdr->desc_size * sizeof(u32), 4, &start_pa);
> + if (!desc)
> + return -ENOMEM;
> +
> + tdt->start = start_pa;
> + tdt->stop = start_pa + ((hdr->desc_size-1) * sizeof(u32));
> + }
> +
> + var = bcom_task_var(task);
> + inc = bcom_task_inc(task);
> +
> + /* Clear & copy */
> + memset(var, 0x00, BCOM_VAR_SIZE);
> + memset(inc, 0x00, BCOM_INC_SIZE);
> +
> + desc_src = (u32 *)(hdr + 1);
> + var_src = desc_src + hdr->desc_size;
> + inc_src = var_src + hdr->var_size;
> +
> + memcpy(desc, desc_src, hdr->desc_size * sizeof(u32));
> + memcpy(var + hdr->first_var, var_src, hdr->var_size * sizeof(u32));
> + memcpy(inc, inc_src, hdr->inc_size * sizeof(u32));
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(bcom_load_image);
> +
> +void
> +bcom_set_initiator(int task, int initiator)
> +{
> + int i;
> + int num_descs;
> + u32 *desc;
> + int next_drd_has_initiator;
> +
> + bcom_set_tcr_initiator(task, initiator);
> +
> + /* Just setting tcr is apparently not enough due to some problem */
> + /* with it. So we just go thru all the microcode and replace in */
> + /* the DRD directly */
> +
> + desc = bcom_task_desc(task);
> + next_drd_has_initiator = 1;
> + num_descs = bcom_task_num_descs(task);
> +
> + for (i=0; i<num_descs; i++, desc++) {
> + if (!bcom_desc_is_drd(*desc))
> + continue;
> + if (next_drd_has_initiator)
> + if (bcom_desc_initiator(*desc) != BCOM_INITIATOR_ALWAYS)
> + bcom_set_desc_initiator(desc, initiator);
> + next_drd_has_initiator = !bcom_drd_is_extended(*desc);
> + }
> +}
> +EXPORT_SYMBOL_GPL(bcom_set_initiator);
> +
> +
> +/* Public API */
> +
> +void
> +bcom_enable(struct bcom_task *tsk)
> +{
> + bcom_enable_task(tsk->tasknum);
> +}
> +EXPORT_SYMBOL_GPL(bcom_enable);
> +
> +void
> +bcom_disable(struct bcom_task *tsk)
> +{
> + bcom_disable_task(tsk->tasknum);
> +}
> +EXPORT_SYMBOL_GPL(bcom_disable);
> +
> +
> +/* ======================================================================== */
> +/* Engine init/cleanup */
> +/* ======================================================================== */
> +
> +/* Function Descriptor table */
> +/* this will need to be updated if Freescale changes their task code FDT */
> +static u32 fdt_ops[] = {
> + 0xa0045670, /* FDT[48] - load_acc() */
> + 0x80045670, /* FDT[49] - unload_acc() */
> + 0x21800000, /* FDT[50] - and() */
> + 0x21e00000, /* FDT[51] - or() */
> + 0x21500000, /* FDT[52] - xor() */
> + 0x21400000, /* FDT[53] - andn() */
> + 0x21500000, /* FDT[54] - not() */
> + 0x20400000, /* FDT[55] - add() */
> + 0x20500000, /* FDT[56] - sub() */
> + 0x20800000, /* FDT[57] - lsh() */
> + 0x20a00000, /* FDT[58] - rsh() */
> + 0xc0170000, /* FDT[59] - crc8() */
> + 0xc0145670, /* FDT[60] - crc16() */
> + 0xc0345670, /* FDT[61] - crc32() */
> + 0xa0076540, /* FDT[62] - endian32() */
> + 0xa0000760, /* FDT[63] - endian16() */
> +};
> +
> +
> +static int __devinit
> +bcom_engine_init(void)
> +{
> + int task;
> + phys_addr_t tdt_pa, ctx_pa, var_pa, fdt_pa;
> + unsigned int tdt_size, ctx_size, var_size, fdt_size;
> +
> + /* Allocate & clear SRAM zones for FDT, TDTs, contexts and vars/incs */
> + tdt_size = BCOM_MAX_TASKS * sizeof(struct bcom_tdt);
> + ctx_size = BCOM_MAX_TASKS * BCOM_CTX_SIZE;
> + var_size = BCOM_MAX_TASKS * (BCOM_VAR_SIZE + BCOM_INC_SIZE);
> + fdt_size = BCOM_FDT_SIZE;
> +
> + bcom_eng->tdt = bcom_sram_alloc(tdt_size, sizeof(u32), &tdt_pa);
> + bcom_eng->ctx = bcom_sram_alloc(ctx_size, BCOM_CTX_ALIGN, &ctx_pa);
> + bcom_eng->var = bcom_sram_alloc(var_size, BCOM_VAR_ALIGN, &var_pa);
> + bcom_eng->fdt = bcom_sram_alloc(fdt_size, BCOM_FDT_ALIGN, &fdt_pa);
> +
> + if (!bcom_eng->tdt || !bcom_eng->ctx || !bcom_eng->var || !bcom_eng->fdt) {
> + printk(KERN_ERR "DMA: SRAM alloc failed in engine init !\n");
> +
> + bcom_sram_free(bcom_eng->tdt);
> + bcom_sram_free(bcom_eng->ctx);
> + bcom_sram_free(bcom_eng->var);
> + bcom_sram_free(bcom_eng->fdt);
> +
> + return -ENOMEM;
> + }
> +
> + memset(bcom_eng->tdt, 0x00, tdt_size);
> + memset(bcom_eng->ctx, 0x00, ctx_size);
> + memset(bcom_eng->var, 0x00, var_size);
> + memset(bcom_eng->fdt, 0x00, fdt_size);
> +
> + /* Copy the FDT for the EU#3 */
> + memcpy(&bcom_eng->fdt[48], fdt_ops, sizeof(fdt_ops));
> +
> + /* Initialize Task base structure */
> + for (task=0; task<BCOM_MAX_TASKS; task++)
> + {
> + out_be16(&bcom_eng->regs->tcr[task], 0);
> + out_8(&bcom_eng->regs->ipr[task], 0);
> +
> + bcom_eng->tdt[task].context = ctx_pa;
> + bcom_eng->tdt[task].var = var_pa;
> + bcom_eng->tdt[task].fdt = fdt_pa;
> +
> + var_pa += BCOM_VAR_SIZE + BCOM_INC_SIZE;
> + ctx_pa += BCOM_CTX_SIZE;
> + }
> +
> + out_be32(&bcom_eng->regs->taskBar, tdt_pa);
> +
> + /* Init 'always' initiator */
> + out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ALWAYS], BCOM_IPR_ALWAYS);
> +
> + /* Disable COMM Bus Prefetch, apparently it's not reliable yet */
> + /* FIXME: This should be done on 5200 and not 5200B ... */
> + out_be16(&bcom_eng->regs->PtdCntrl, in_be16(&bcom_eng->regs->PtdCntrl) | 1);
> +
> + /* Init lock */
> + spin_lock_init(&bcom_eng->lock);
> +
> + return 0;
> +}
> +
> +static void
> +bcom_engine_cleanup(void)
> +{
> + int task;
> +
> + /* Stop all tasks */
> + for (task=0; task<BCOM_MAX_TASKS; task++)
> + {
> + out_be16(&bcom_eng->regs->tcr[task], 0);
> + out_8(&bcom_eng->regs->ipr[task], 0);
> + }
> +
> + out_be32(&bcom_eng->regs->taskBar, 0ul);
> +
> + /* Release the SRAM zones */
> + bcom_sram_free(bcom_eng->tdt);
> + bcom_sram_free(bcom_eng->ctx);
> + bcom_sram_free(bcom_eng->var);
> + bcom_sram_free(bcom_eng->fdt);
> +}
> +
> +
> +/* ======================================================================== */
> +/* OF platform driver */
> +/* ======================================================================== */
> +
> +static int __devinit
> +mpc52xx_bcom_probe(struct of_device *op, const struct of_device_id *match)
> +{
> + struct device_node *ofn_bcom, *ofn_sram;
> + struct resource res_bcom;
> +
> + int rv;
> +
> + /* Inform user we're ok so far */
> + printk(KERN_INFO "DMA: MPC52xx BestComm driver\n");
> +
> + /* Get the bestcomm node */
> + ofn_bcom = op->node;
> + of_node_get(ofn_bcom);
> +
> + /* Prepare SRAM */
> + ofn_sram = of_find_compatible_node(NULL, "sram", "mpc5200-sram");
> + if (!ofn_sram) {
> + printk(KERN_ERR DRIVER_NAME ": "
> + "No SRAM found in device tree\n");
> + rv = -ENODEV;
> + goto error_ofput;
> + }
> +
> + rv = bcom_sram_init(ofn_sram, DRIVER_NAME);
> +
> + of_node_put(ofn_sram);
> +
> + if (rv) {
> + printk(KERN_ERR DRIVER_NAME ": "
> + "Error in SRAM init\n");
> + goto error_ofput;
> + }
> +
> + /* Get a clean struct */
> + bcom_eng = kzalloc(sizeof(struct bcom_engine), GFP_KERNEL);
> + if (!bcom_eng) {
> + printk(KERN_ERR DRIVER_NAME ": "
> + "Can't allocate state structure\n");
> + rv = -ENOMEM;
> + goto error_sramclean;
> + }
> +
> + /* Save the node */
> + bcom_eng->ofnode = ofn_bcom;
> +
> + /* Get, reserve & map io */
> + if (of_address_to_resource(bcom_eng->ofnode, 0, &res_bcom)) {
> + printk(KERN_ERR DRIVER_NAME ": "
> + "Can't get resource\n");
> + rv = -EINVAL;
> + goto error_sramclean;
> + }
> +
> + if (!request_mem_region(res_bcom.start, sizeof(struct mpc52xx_sdma),
> + DRIVER_NAME)) {
> + printk(KERN_ERR DRIVER_NAME ": "
> + "Can't request registers region\n");
> + rv = -EBUSY;
> + goto error_sramclean;
> + }
> +
> + bcom_eng->regs_base = res_bcom.start;
> + bcom_eng->regs = ioremap(res_bcom.start, sizeof(struct mpc52xx_sdma));
> + if (!bcom_eng->regs) {
> + printk(KERN_ERR DRIVER_NAME ": "
> + "Can't map registers\n");
> + rv = -ENOMEM;
> + goto error_release;
> + }
> +
> + /* Now, do the real init */
> + rv = bcom_engine_init();
> + if (rv)
> + goto error_unmap;
> +
> + /* Done ! */
> + printk(KERN_INFO "DMA: MPC52xx BestComm engine @%08lx ok !\n",
> + bcom_eng->regs_base);
> +
> + return 0;
> +
> + /* Error path */
> +error_unmap:
> + iounmap(bcom_eng->regs);
> +error_release:
> + release_mem_region(res_bcom.start, sizeof(struct mpc52xx_sdma));
> +error_sramclean:
> + bcom_sram_cleanup();
> +error_ofput:
> + of_node_put(bcom_eng->ofnode);
> +
> + printk(KERN_ERR "DMA: MPC52xx BestComm init failed !\n");
> +
> + return rv;
> +}
> +
> +
> +static int
> +mpc52xx_bcom_remove(struct of_device *op)
> +{
> + /* Clean up the engine */
> + bcom_engine_cleanup();
> +
> + /* Cleanup SRAM */
> + bcom_sram_cleanup();
> +
> + /* Release regs */
> + iounmap(bcom_eng->regs);
> + release_mem_region(bcom_eng->regs_base, sizeof(struct mpc52xx_sdma));
> +
> + /* Release the node */
> + of_node_put(bcom_eng->ofnode);
> +
> + /* Release memory */
> + kfree(bcom_eng);
> + bcom_eng = NULL;
> +
> + return 0;
> +}
> +
> +
> +#ifdef CONFIG_PM
> +
> +static int
> +mpc52xx_bcom_suspend(struct of_device *op, pm_message_t state)
> +{
> + return 0; /* FIXME : What to do here ? */
> +}
> +
> +static int
> +mpc52xx_bcom_resume(struct of_device *op)
> +{
> + return 0;
> +}
> +
> +#endif
> +
> +static struct of_device_id mpc52xx_bcom_of_match[] = {
> + {
> + .type = "dma-controller",
> + .compatible = "mpc5200-bestcomm",
> + },
> + {},
> +};
> +
> +MODULE_DEVICE_TABLE(of, mpc52xx_bcom_of_match);
> +
> +
> +static struct of_platform_driver mpc52xx_bcom_of_platform_driver = {
> + .owner = THIS_MODULE,
> + .name = DRIVER_NAME,
> + .match_table = mpc52xx_bcom_of_match,
> + .probe = mpc52xx_bcom_probe,
> + .remove = mpc52xx_bcom_remove,
> +#ifdef CONFIG_PM
> + .suspend = mpc52xx_bcom_suspend,
> + .resume = mpc52xx_bcom_resume,
> +#endif
> + .driver = {
> + .name = DRIVER_NAME,
> + .owner = THIS_MODULE,
> + },
> +};
> +
> +
> +/* ======================================================================== */
> +/* Module */
> +/* ======================================================================== */
> +
> +static int __init
> +mpc52xx_bcom_init(void)
> +{
> + return of_register_platform_driver(&mpc52xx_bcom_of_platform_driver);
> +}
> +
> +static void __exit
> +mpc52xx_bcom_exit(void)
> +{
> + of_unregister_platform_driver(&mpc52xx_bcom_of_platform_driver);
> +}
> +
> +/* If we're not a module, we must make sure everything is setup before */
> +/* anyone tries to use us ... that's why we use subsys_initcall instead */
> +/* of module_init. */
> +subsys_initcall(mpc52xx_bcom_init);
> +module_exit(mpc52xx_bcom_exit);
> +
> +MODULE_DESCRIPTION("Freescale MPC52xx BestComm DMA");
> +MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");
> +MODULE_AUTHOR("Andrey Volkov <avolkov@varma-el.com>");
> +MODULE_AUTHOR("Dale Farnsworth <dfarnsworth@mvista.com>");
> +MODULE_LICENSE("GPL v2");
> +
> diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm.h b/arch/powerpc/sysdev/bestcomm/bestcomm.h
> new file mode 100644
> index 0000000..eac3eec
> --- /dev/null
> +++ b/arch/powerpc/sysdev/bestcomm/bestcomm.h
> @@ -0,0 +1,136 @@
> +/*
> + * Public header for the MPC52xx processor BestComm driver
> + *
> + *
> + * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
> + * Copyright (C) 2005 Varma Electronics Oy,
> + * ( by Andrey Volkov <avolkov@varma-el.com> )
> + * Copyright (C) 2003-2004 MontaVista, Software, Inc.
> + * ( by Dale Farnsworth <dfarnsworth@mvista.com> )
> + *
> + * This file is licensed under the terms of the GNU General Public License
> + * version 2. This program is licensed "as is" without any warranty of any
> + * kind, whether express or implied.
> + */
> +
> +#ifndef __BESTCOMM_H__
> +#define __BESTCOMM_H__
> +
> +struct bcom_bd; /* defined later on ... */
> +
> +
> +/* ======================================================================== */
> +/* Generic task managment */
> +/* ======================================================================== */
> +
> +struct bcom_task {
> + unsigned int tasknum;
> + unsigned int flags;
> + int irq;
> +
> + struct bcom_bd *bd;
> + phys_addr_t bd_pa;
> + void **cookie;
> + unsigned short index;
> + unsigned short outdex;
> + unsigned int num_bd;
> + unsigned int bd_size;
> +
> + void* priv;
> +};
> +
> +#define BCOM_FLAGS_NONE 0x00000000ul
> +#define BCOM_FLAGS_ENABLE_TASK (1ul << 0)
> +
> +
> +extern void bcom_enable(struct bcom_task *tsk);
> +extern void bcom_disable(struct bcom_task *tsk);
> +
> +static inline int
> +bcom_get_task_irq(struct bcom_task *tsk) {
> + return tsk->irq;
> +}
> +
> +
> +/* Debug dumps */
> +extern void bcom_dump_status(void);
> +extern void bcom_dump_task(int task);
> +extern void bcom_dump_bdring(struct bcom_task *tsk);
> +
> +
> +/* ======================================================================== */
> +/* BD based tasks helpers */
> +/* ======================================================================== */
> +
> +struct bcom_bd {
> + u32 status;
> + u32 data[1]; /* variable, but at least 1 */
> +};
> +
> +#define BCOM_BD_READY 0x40000000ul
> +
> +static inline int /* user shouldn't use this ! */
> +_bcom_next_index(struct bcom_task *tsk)
> +{
> + return ((tsk->index + 1) == tsk->num_bd) ? 0 : tsk->index + 1;
> +}
> +
> +static inline int /* user shouldn't use this ! */
> +_bcom_next_outdex(struct bcom_task *tsk)
> +{
> + return ((tsk->outdex + 1) == tsk->num_bd) ? 0 : tsk->outdex + 1;
> +}
> +
> +static inline int
> +bcom_queue_empty(struct bcom_task *tsk)
> +{
> + return tsk->index == tsk->outdex;
> +}
> +
> +static inline int
> +bcom_queue_full(struct bcom_task *tsk)
> +{
> + return tsk->outdex == _bcom_next_index(tsk);
> +}
> +
> +static inline int
> +bcom_buffer_done(struct bcom_task *tsk)
> +{
> + if (bcom_queue_empty(tsk))
> + return 0;
> + return !(tsk->bd[tsk->outdex].status & BCOM_BD_READY);
> +}
> +
> +static inline struct bcom_bd *
> +bcom_prepare_next_buffer(struct bcom_task *tsk)
> +{
> + tsk->bd[tsk->index].status = 0; /* cleanup last status */
> + return &tsk->bd[tsk->index];
> +}
> +
> +static inline void
> +bcom_submit_next_buffer(struct bcom_task *tsk, void *cookie)
> +{
> + tsk->cookie[tsk->index] = cookie;
> + mb(); /* ensure the bd is really up-to-date */
> + tsk->bd[tsk->index].status |= BCOM_BD_READY;
> + tsk->index = _bcom_next_index(tsk);
> + if (tsk->flags & BCOM_FLAGS_ENABLE_TASK)
> + bcom_enable(tsk);
> +}
> +
> +static inline void *
> +bcom_retrieve_buffer(struct bcom_task *tsk, u32 *p_status, struct bcom_bd **p_bd)
> +{
> + void *cookie = tsk->cookie[tsk->outdex];
> + if (p_status)
> + *p_status = tsk->bd[tsk->outdex].status;
> + if (p_bd)
> + *p_bd = &tsk->bd[tsk->outdex];
> + tsk->outdex = _bcom_next_outdex(tsk);
> + return cookie;
> +}
> +
> +
> +#endif /* __BESTCOMM_H__ */
> +
> diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h b/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h
> new file mode 100644
> index 0000000..6f33f0c
> --- /dev/null
> +++ b/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h
> @@ -0,0 +1,325 @@
> +/*
> + * Private header for the MPC52xx processor BestComm driver
> + *
> + *
> + * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
> + * Copyright (C) 2005 Varma Electronics Oy,
> + * ( by Andrey Volkov <avolkov@varma-el.com> )
> + * Copyright (C) 2003-2004 MontaVista, Software, Inc.
> + * ( by Dale Farnsworth <dfarnsworth@mvista.com> )
> + *
> + * This file is licensed under the terms of the GNU General Public License
> + * version 2. This program is licensed "as is" without any warranty of any
> + * kind, whether express or implied.
> + */
> +
> +#ifndef __BESTCOMM_PRIV_H__
> +#define __BESTCOMM_PRIV_H__
> +
> +#include <linux/spinlock.h>
> +#include <asm/io.h>
> +#include <asm/prom.h>
> +#include <asm/mpc52xx.h>
> +
> +#include "sram.h"
> +
> +
> +/* ======================================================================== */
> +/* Engine related stuff */
> +/* ======================================================================== */
> +
> +/* Zones sizes and needed alignments */
> +#define BCOM_MAX_TASKS 16
> +#define BCOM_MAX_VAR 24
> +#define BCOM_MAX_INC 8
> +#define BCOM_MAX_FDT 64
> +#define BCOM_MAX_CTX 20
> +#define BCOM_CTX_SIZE (BCOM_MAX_CTX * sizeof(u32))
> +#define BCOM_CTX_ALIGN 0x100
> +#define BCOM_VAR_SIZE (BCOM_MAX_VAR * sizeof(u32))
> +#define BCOM_INC_SIZE (BCOM_MAX_INC * sizeof(u32))
> +#define BCOM_VAR_ALIGN 0x80
> +#define BCOM_FDT_SIZE (BCOM_MAX_FDT * sizeof(u32))
> +#define BCOM_FDT_ALIGN 0x100
> +
> +/* Task Descriptor Table Entry */
> +struct bcom_tdt {
> + u32 start;
> + u32 stop;
> + u32 var;
> + u32 fdt;
> + u32 exec_status; /* used internally by BestComm engine */
> + u32 mvtp; /* used internally by BestComm engine */
> + u32 context;
> + u32 litbase;
> +};
> +
> +/* This holds all info needed globaly to handle the engine */
> +struct bcom_engine {
> + struct device_node *ofnode;
> + struct mpc52xx_sdma __iomem *regs;
> + phys_addr_t regs_base;
> +
> + struct bcom_tdt *tdt;
> + u32 *ctx;
> + u32 *var;
> + u32 *fdt;
> +
> + spinlock_t lock;
> +};
> +
> +extern struct bcom_engine *bcom_eng;
> +
> +
> +/* ======================================================================== */
> +/* Tasks related stuff */
> +/* ======================================================================== */
> +
> +/* Tasks image header */
> +#define BCOM_TASK_MAGIC 0x4243544B /* 'BCTK' */
> +
> +struct bcom_task_header {
> + u32 magic;
> + u8 desc_size; /* the size fields */
> + u8 var_size; /* are given in number */
> + u8 inc_size; /* of 32-bits words */
> + u8 first_var;
> + u8 reserved[8];
> +};
> +
> +/* Descriptors stucture & co */
> +#define BCOM_DESC_NOP 0x000001f8
> +#define BCOM_LCD_MASK 0x80000000
> +#define BCOM_DRD_EXTENDED 0x40000000
> +#define BCOM_DRD_INITIATOR_SHIFT 21
> +
> +/* Tasks pragma */
> +#define BCOM_PRAGMA_BIT_RSV 7 /* reserved pragma bit */
> +#define BCOM_PRAGMA_BIT_PRECISE_INC 6 /* increment 0=when possible, */
> + /* 1=iter end */
> +#define BCOM_PRAGMA_BIT_RST_ERROR_NO 5 /* don't reset errors on */
> + /* task enable */
> +#define BCOM_PRAGMA_BIT_PACK 4 /* pack data enable */
> +#define BCOM_PRAGMA_BIT_INTEGER 3 /* data alignment */
> + /* 0=frac(msb), 1=int(lsb) */
> +#define BCOM_PRAGMA_BIT_SPECREAD 2 /* XLB speculative read */
> +#define BCOM_PRAGMA_BIT_CW 1 /* write line buffer enable */
> +#define BCOM_PRAGMA_BIT_RL 0 /* read line buffer enable */
> +
> + /* Looks like XLB speculative read generates XLB errors when a buffer
> + * is at the end of the physical memory. i.e. when accessing the
> + * lasts words, the engine tries to prefetch the next but there is no
> + * next ...
> + */
> +#define BCOM_STD_PRAGMA ((0 << BCOM_PRAGMA_BIT_RSV) | \
> + (0 << BCOM_PRAGMA_BIT_PRECISE_INC) | \
> + (0 << BCOM_PRAGMA_BIT_RST_ERROR_NO) | \
> + (0 << BCOM_PRAGMA_BIT_PACK) | \
> + (0 << BCOM_PRAGMA_BIT_INTEGER) | \
> + (0 << BCOM_PRAGMA_BIT_SPECREAD) | \
> + (1 << BCOM_PRAGMA_BIT_CW) | \
> + (1 << BCOM_PRAGMA_BIT_RL))
> +
> +#define BCOM_PCI_PRAGMA ((0 << BCOM_PRAGMA_BIT_RSV) | \
> + (0 << BCOM_PRAGMA_BIT_PRECISE_INC) | \
> + (0 << BCOM_PRAGMA_BIT_RST_ERROR_NO) | \
> + (0 << BCOM_PRAGMA_BIT_PACK) | \
> + (1 << BCOM_PRAGMA_BIT_INTEGER) | \
> + (0 << BCOM_PRAGMA_BIT_SPECREAD) | \
> + (1 << BCOM_PRAGMA_BIT_CW) | \
> + (1 << BCOM_PRAGMA_BIT_RL))
> +
> +#define BCOM_ATA_PRAGMA BCOM_STD_PRAGMA
> +#define BCOM_CRC16_DP_0_PRAGMA BCOM_STD_PRAGMA
> +#define BCOM_CRC16_DP_1_PRAGMA BCOM_STD_PRAGMA
> +#define BCOM_FEC_RX_BD_PRAGMA BCOM_STD_PRAGMA
> +#define BCOM_FEC_TX_BD_PRAGMA BCOM_STD_PRAGMA
> +#define BCOM_GEN_DP_0_PRAGMA BCOM_STD_PRAGMA
> +#define BCOM_GEN_DP_1_PRAGMA BCOM_STD_PRAGMA
> +#define BCOM_GEN_DP_2_PRAGMA BCOM_STD_PRAGMA
> +#define BCOM_GEN_DP_3_PRAGMA BCOM_STD_PRAGMA
> +#define BCOM_GEN_DP_BD_0_PRAGMA BCOM_STD_PRAGMA
> +#define BCOM_GEN_DP_BD_1_PRAGMA BCOM_STD_PRAGMA
> +#define BCOM_GEN_RX_BD_PRAGMA BCOM_STD_PRAGMA
> +#define BCOM_GEN_TX_BD_PRAGMA BCOM_STD_PRAGMA
> +#define BCOM_GEN_LPC_PRAGMA BCOM_STD_PRAGMA
> +#define BCOM_PCI_RX_PRAGMA BCOM_PCI_PRAGMA
> +#define BCOM_PCI_TX_PRAGMA BCOM_PCI_PRAGMA
> +
> +/* Initiators number */
> +#define BCOM_INITIATOR_ALWAYS 0
> +#define BCOM_INITIATOR_SCTMR_0 1
> +#define BCOM_INITIATOR_SCTMR_1 2
> +#define BCOM_INITIATOR_FEC_RX 3
> +#define BCOM_INITIATOR_FEC_TX 4
> +#define BCOM_INITIATOR_ATA_RX 5
> +#define BCOM_INITIATOR_ATA_TX 6
> +#define BCOM_INITIATOR_SCPCI_RX 7
> +#define BCOM_INITIATOR_SCPCI_TX 8
> +#define BCOM_INITIATOR_PSC3_RX 9
> +#define BCOM_INITIATOR_PSC3_TX 10
> +#define BCOM_INITIATOR_PSC2_RX 11
> +#define BCOM_INITIATOR_PSC2_TX 12
> +#define BCOM_INITIATOR_PSC1_RX 13
> +#define BCOM_INITIATOR_PSC1_TX 14
> +#define BCOM_INITIATOR_SCTMR_2 15
> +#define BCOM_INITIATOR_SCLPC 16
> +#define BCOM_INITIATOR_PSC5_RX 17
> +#define BCOM_INITIATOR_PSC5_TX 18
> +#define BCOM_INITIATOR_PSC4_RX 19
> +#define BCOM_INITIATOR_PSC4_TX 20
> +#define BCOM_INITIATOR_I2C2_RX 21
> +#define BCOM_INITIATOR_I2C2_TX 22
> +#define BCOM_INITIATOR_I2C1_RX 23
> +#define BCOM_INITIATOR_I2C1_TX 24
> +#define BCOM_INITIATOR_PSC6_RX 25
> +#define BCOM_INITIATOR_PSC6_TX 26
> +#define BCOM_INITIATOR_IRDA_RX 25
> +#define BCOM_INITIATOR_IRDA_TX 26
> +#define BCOM_INITIATOR_SCTMR_3 27
> +#define BCOM_INITIATOR_SCTMR_4 28
> +#define BCOM_INITIATOR_SCTMR_5 29
> +#define BCOM_INITIATOR_SCTMR_6 30
> +#define BCOM_INITIATOR_SCTMR_7 31
> +
> +/* Initiators priorities */
> +#define BCOM_IPR_ALWAYS 7
> +#define BCOM_IPR_SCTMR_0 2
> +#define BCOM_IPR_SCTMR_1 2
> +#define BCOM_IPR_FEC_RX 6
> +#define BCOM_IPR_FEC_TX 5
> +#define BCOM_IPR_ATA_RX 4
> +#define BCOM_IPR_ATA_TX 3
> +#define BCOM_IPR_SCPCI_RX 2
> +#define BCOM_IPR_SCPCI_TX 2
> +#define BCOM_IPR_PSC3_RX 2
> +#define BCOM_IPR_PSC3_TX 2
> +#define BCOM_IPR_PSC2_RX 2
> +#define BCOM_IPR_PSC2_TX 2
> +#define BCOM_IPR_PSC1_RX 2
> +#define BCOM_IPR_PSC1_TX 2
> +#define BCOM_IPR_SCTMR_2 2
> +#define BCOM_IPR_SCLPC 2
> +#define BCOM_IPR_PSC5_RX 2
> +#define BCOM_IPR_PSC5_TX 2
> +#define BCOM_IPR_PSC4_RX 2
> +#define BCOM_IPR_PSC4_TX 2
> +#define BCOM_IPR_I2C2_RX 2
> +#define BCOM_IPR_I2C2_TX 2
> +#define BCOM_IPR_I2C1_RX 2
> +#define BCOM_IPR_I2C1_TX 2
> +#define BCOM_IPR_PSC6_RX 2
> +#define BCOM_IPR_PSC6_TX 2
> +#define BCOM_IPR_IRDA_RX 2
> +#define BCOM_IPR_IRDA_TX 2
> +#define BCOM_IPR_SCTMR_3 2
> +#define BCOM_IPR_SCTMR_4 2
> +#define BCOM_IPR_SCTMR_5 2
> +#define BCOM_IPR_SCTMR_6 2
> +#define BCOM_IPR_SCTMR_7 2
> +
> +
> +/* ======================================================================== */
> +/* API */
> +/* ======================================================================== */
> +
> +extern struct bcom_task *bcom_task_alloc(int bd_count, int bd_size, int priv_size);
> +extern void bcom_task_release(struct bcom_task *tsk);
> +
> +extern int bcom_load_image(int task, u32 *task_image);
> +extern void bcom_set_initiator(int task, int initiator);
> +
> +
> +#define TASK_ENABLE 0x8000
> +
> +static inline void
> +bcom_enable_task(int task)
> +{
> + u16 reg;
> + reg = in_be16(&bcom_eng->regs->tcr[task]);
> + out_be16(&bcom_eng->regs->tcr[task], reg | TASK_ENABLE);
> +}
> +
> +static inline void
> +bcom_disable_task(int task)
> +{
> + u16 reg = in_be16(&bcom_eng->regs->tcr[task]);
> + out_be16(&bcom_eng->regs->tcr[task], reg & ~TASK_ENABLE);
> +}
> +
> +
> +static inline u32 *
> +bcom_task_desc(int task)
> +{
> + return bcom_sram_pa2va(bcom_eng->tdt[task].start);
> +}
> +
> +static inline int
> +bcom_task_num_descs(int task)
> +{
> + return (bcom_eng->tdt[task].stop - bcom_eng->tdt[task].start)/sizeof(u32) + 1;
> +}
> +
> +static inline u32 *
> +bcom_task_var(int task)
> +{
> + return bcom_sram_pa2va(bcom_eng->tdt[task].var);
> +}
> +
> +static inline u32 *
> +bcom_task_inc(int task)
> +{
> + return &bcom_task_var(task)[BCOM_MAX_VAR];
> +}
> +
> +
> +static inline int
> +bcom_drd_is_extended(u32 desc)
> +{
> + return (desc) & BCOM_DRD_EXTENDED;
> +}
> +
> +static inline int
> +bcom_desc_is_drd(u32 desc)
> +{
> + return !(desc & BCOM_LCD_MASK) && desc != BCOM_DESC_NOP;
> +}
> +
> +static inline int
> +bcom_desc_initiator(u32 desc)
> +{
> + return (desc >> BCOM_DRD_INITIATOR_SHIFT) & 0x1f;
> +}
> +
> +static inline void
> +bcom_set_desc_initiator(u32 *desc, int initiator)
> +{
> + *desc = (*desc & ~(0x1f << BCOM_DRD_INITIATOR_SHIFT)) |
> + ((initiator & 0x1f) << BCOM_DRD_INITIATOR_SHIFT);
> +}
> +
> +
> +static inline void
> +bcom_set_task_pragma(int task, int pragma)
> +{
> + u32 *fdt = &bcom_eng->tdt[task].fdt;
> + *fdt = (*fdt & ~0xff) | pragma;
> +}
> +
> +static inline void
> +bcom_set_task_auto_start(int task, int next_task)
> +{
> + u16 __iomem *tcr = &bcom_eng->regs->tcr[task];
> + out_be16(tcr, (in_be16(tcr) & ~0xff) | 0x00c0 | next_task);
> +}
> +
> +static inline void
> +bcom_set_tcr_initiator(int task, int initiator)
> +{
> + u16 __iomem *tcr = &bcom_eng->regs->tcr[task];
> + out_be16(tcr, (in_be16(tcr) & ~0x1f00) | ((initiator & 0x1f) << 8));
> +}
> +
> +
> +#endif /* __BESTCOMM_PRIV_H__ */
> +
> diff --git a/arch/powerpc/sysdev/bestcomm/sram.c b/arch/powerpc/sysdev/bestcomm/sram.c
> new file mode 100644
> index 0000000..a5094d6
> --- /dev/null
> +++ b/arch/powerpc/sysdev/bestcomm/sram.c
> @@ -0,0 +1,177 @@
> +/*
> + * Simple memory allocator for on-board SRAM
> + *
> + *
> + * Maintainer : Sylvain Munaut <tnt@246tNt.com>
> + *
> + * Copyright (C) 2005 Sylvain Munaut <tnt@246tNt.com>
> + *
> + * This file is licensed under the terms of the GNU General Public License
> + * version 2. This program is licensed "as is" without any warranty of any
> + * kind, whether express or implied.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +#include <linux/string.h>
> +#include <linux/ioport.h>
> +
> +#include <asm/io.h>
> +#include <asm/mmu.h>
> +#include <asm/prom.h>
> +
> +#include "sram.h"
> +
> +
> +/* Struct keeping our 'state' */
> +struct bcom_sram *bcom_sram = NULL;
> +EXPORT_SYMBOL_GPL(bcom_sram); /* needed for inline functions */
> +
> +
> +/* ======================================================================== */
> +/* Public API */
> +/* ======================================================================== */
> +/* DO NOT USE in interrupts, if needed in irq handler, we should use the
> + _irqsave version of the spin_locks */
> +
> +int bcom_sram_init(struct device_node *sram_node, char *owner)
> +{
> + int rv;
> + const u32 *regaddr_p;
> + u64 regaddr64, size64;
> + unsigned int psize;
> +
> + /* Create our state struct */
> + if (bcom_sram) {
> + printk(KERN_ERR "%s: bcom_sram_init: "
> + "Already initialiwed !\n", owner);
> + return -EBUSY;
> + }
> +
> + bcom_sram = kmalloc(sizeof(struct bcom_sram), GFP_KERNEL);
> + if (!bcom_sram) {
> + printk(KERN_ERR "%s: bcom_sram_init: "
> + "Couldn't allocate internal state !\n", owner);
> + return -ENOMEM;
> + }
> +
> + /* Get address and size of the sram */
> + regaddr_p = of_get_address(sram_node, 0, &size64, NULL);
> + if (!regaddr_p) {
> + printk(KERN_ERR "%s: bcom_sram_init: "
> + "Invalid device node !\n", owner);
> + rv = -EINVAL;
> + goto error_free;
> + }
> +
> + regaddr64 = of_translate_address(sram_node, regaddr_p);
> +
> + bcom_sram->base_phys = (phys_addr_t) regaddr64;
> + bcom_sram->size = (unsigned int) size64;
> +
> + /* Request region */
> + if (!request_mem_region(bcom_sram->base_phys, bcom_sram->size, owner)) {
> + printk(KERN_ERR "%s: bcom_sram_init: "
> + "Couln't request region !\n", owner);
> + rv = -EBUSY;
> + goto error_free;
> + }
> +
> + /* Map SRAM */
> + /* sram is not really __iomem */
> + bcom_sram->base_virt = (void*) ioremap(bcom_sram->base_phys, bcom_sram->size);
> +
> + if (!bcom_sram->base_virt) {
> + printk(KERN_ERR "%s: bcom_sram_init: "
> + "Map error SRAM zone 0x%08lx (0x%0x)!\n",
> + owner, bcom_sram->base_phys, bcom_sram->size );
> + rv = -ENOMEM;
> + goto error_release;
> + }
> +
> + /* Create an rheap (defaults to 32 bits word alignment) */
> + bcom_sram->rh = rh_create(4);
> +
> + /* Attach the free zones */
> +#if 0
> + /* Currently disabled ... for future use only */
> + reg_addr_p = of_get_property(sram_node, "available", &psize);
> +#else
> + regaddr_p = NULL;
> + psize = 0;
> +#endif
> +
> + if (!regaddr_p || !psize) {
> + /* Attach the whole zone */
> + rh_attach_region(bcom_sram->rh, 0, bcom_sram->size);
> + } else {
> + /* Attach each zone independently */
> + while (psize >= 2 * sizeof(u32)) {
> + phys_addr_t zbase = of_translate_address(sram_node, regaddr_p);
> + rh_attach_region(bcom_sram->rh, zbase - bcom_sram->base_phys, regaddr_p[1]);
> + regaddr_p += 2;
> + psize -= 2 * sizeof(u32);
> + }
> + }
> +
> + /* Init our spinlock */
> + spin_lock_init(&bcom_sram->lock);
> +
> + return 0;
> +
> +error_release:
> + release_mem_region(bcom_sram->base_phys, bcom_sram->size);
> +error_free:
> + kfree(bcom_sram);
> + bcom_sram = NULL;
> +
> + return rv;
> +}
> +EXPORT_SYMBOL_GPL(bcom_sram_init);
> +
> +void bcom_sram_cleanup(void)
> +{
> + /* Free resources */
> + if (bcom_sram) {
> + rh_destroy(bcom_sram->rh);
> + iounmap((void __iomem *)bcom_sram->base_virt);
> + release_mem_region(bcom_sram->base_phys, bcom_sram->size);
> + kfree(bcom_sram);
> + bcom_sram = NULL;
> + }
> +}
> +EXPORT_SYMBOL_GPL(bcom_sram_cleanup);
> +
> +void* bcom_sram_alloc(int size, int align, phys_addr_t *phys)
> +{
> + unsigned long offset;
> +
> + spin_lock(&bcom_sram->lock);
> + offset = rh_alloc_align(bcom_sram->rh, size, align, NULL);
> + spin_unlock(&bcom_sram->lock);
> +
> + if (IS_ERR_VALUE(offset))
> + return NULL;
> +
> + *phys = bcom_sram->base_phys + offset;
> + return bcom_sram->base_virt + offset;
> +}
> +EXPORT_SYMBOL_GPL(bcom_sram_alloc);
> +
> +void bcom_sram_free(void *ptr)
> +{
> + unsigned long offset;
> +
> + if (!ptr)
> + return;
> +
> + offset = ptr - bcom_sram->base_virt;
> +
> + spin_lock(&bcom_sram->lock);
> + rh_free(bcom_sram->rh, offset);
> + spin_unlock(&bcom_sram->lock);
> +}
> +EXPORT_SYMBOL_GPL(bcom_sram_free);
> +
> diff --git a/arch/powerpc/sysdev/bestcomm/sram.h b/arch/powerpc/sysdev/bestcomm/sram.h
> new file mode 100644
> index 0000000..b6d6689
> --- /dev/null
> +++ b/arch/powerpc/sysdev/bestcomm/sram.h
> @@ -0,0 +1,54 @@
> +/*
> + * Handling of a sram zone for bestcomm
> + *
> + *
> + * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com>
> + *
> + * This file is licensed under the terms of the GNU General Public License
> + * version 2. This program is licensed "as is" without any warranty of any
> + * kind, whether express or implied.
> + */
> +
> +#ifndef __BESTCOMM_SRAM_H__
> +#define __BESTCOMM_SRAM_H__
> +
> +#include <asm/rheap.h>
> +#include <asm/mmu.h>
> +#include <linux/spinlock.h>
> +
> +
> +/* Structure used internally */
> + /* The internals are here for the inline functions
> + * sake, certainly not for the user to mess with !
> + */
> +struct bcom_sram {
> + phys_addr_t base_phys;
> + void *base_virt;
> + unsigned int size;
> + rh_info_t *rh;
> + spinlock_t lock;
> +};
> +
> +extern struct bcom_sram *bcom_sram;
> +
> +
> +/* Public API */
> +extern int bcom_sram_init(struct device_node *sram_node, char *owner);
> +extern void bcom_sram_cleanup(void);
> +
> +extern void* bcom_sram_alloc(int size, int align, phys_addr_t *phys);
> +extern void bcom_sram_free(void *ptr);
> +
> +static inline phys_addr_t bcom_sram_va2pa(void *va) {
> + return bcom_sram->base_phys +
> + (unsigned long)(va - bcom_sram->base_virt);
> +}
> +
> +static inline void *bcom_sram_pa2va(phys_addr_t pa) {
> + return bcom_sram->base_virt +
> + (unsigned long)(pa - bcom_sram->base_phys);
> +}
> +
> +
> +#endif /* __BESTCOMM_SRAM_H__ */
> +
^ permalink raw reply
* DMA Generic Task
From: Pedro Luis D. L. @ 2007-09-17 8:39 UTC (permalink / raw)
To: linuxppc-embedded
Hello,
I=B4m developing an small module to use the DMA API to copy some audio data=
in a PSC wich has attached an digital to analog converter. It is only a pr=
oof of concept before I can use this information to develop an audio driver=
for the SPI interface.=20
I=B4m using a 2.6.20 kernel patched with the bestcomm patches from http://w=
ww.246tnt.com/mpc52xx/dev_full/ at Sylvain's page.=20
My board is also a pcm030. I had the same problems with the Ethernet so I d=
ecided to keep the old fec driver with the old bestcomm driver also just fo=
r the Ethernet stuff until I could take a look over it.
I took a look into the code for the bestcomm API for the generic tasks and =
thought that this was the way to initialize the bestcomm task:
struct bcom_task *tx_bcom; =20
struct bcom_task *rx_bcom;
=09
switch(psc_num) {
case 1:
initiator_tx =3D SDMA_INITIATOR_PSC1_TX;
initiator_rx =3D SDMA_INITIATOR_PSC1_RX;
break;
case 2:
initiator_tx =3D SDMA_INITIATOR_PSC2_TX;
initiator_rx =3D SDMA_INITIATOR_PSC2_RX;
break;
default:
panic("snd-SPImgt.o: invalid value for psc_num (%i)\n",psc_num);
break;
};
tx_bcom =3D bcom_gen_bd_tx_init(512, MPC52xx_PA(MPC52xx_PSCx_OFFSET(psc_nu=
m))+0x80, initiator_tx, 6); //(1)
rx_bcom =3D bcom_gen_bd_rx_init(512, MPC52xx_PA(MPC52xx_PSCx_OFFSET(psc_nu=
m))+0x60, initiator_rx, 6, 1024);
where MPC52xx_PA(MPC52xx_PSCx_OFFSET(psc_num)) =3D 0xf0002000, wich added t=
o 0x80 or 0x60 gives TXFIFO or RXFIFO's physical address.
However, when I insert the module, it crashes at (1) Line (bcom_gen_bd_tx_i=
nit...) with this output:
root@MPC5200B:~ insmod SPIspeaker
Inserting SPIspeaker module
Unable to handle kernel paging request for data at address 0x0000000c
Faulting instruction address: 0xc001525c
Oops: Kernel access of bad area, sig: 11 [#1]
PREEMPT
Modules linked in: SPIspeaker eeprom
NIP: C001525C LR: C0016458 CTR: 00000010
REGS: c3e7bd80 TRAP: 0300 Not tainted (2.6.20)
MSR: 00009032 CR: 24008222 XER: 00000000
DAR: 0000000C, DSISR: 20000000
TASK =3D c3f2c7b0[447] 'insmod' THREAD: c3e7a000
GPR00: 00000010 C3E7BE30 C3F2C7B0 00000200 00000008 00000010 00000006 00004=
000
GPR08: C3E7A000 00000000 00000000 C0016430 24008222 1008B4E8 00000000 00000=
000
GPR16: 00000012 00000011 C5068C74 C3FD08C0 00000000 00000056 C024408C 00000=
000
GPR24: C01E28DC 00000008 C0260000 00000200 0000000E 00000010 00000006 C0244=
338
Call Trace:
[C3E7BE30] [C5060000] (unreliable)
[C3E7BE60] [C0016458]
[C3E7BE80] [C506026C]
[C3E7BEA0] [C003F804]
[C3E7BF40] [C000F5C8]
--- Exception: c01Instruction dump:
7c7b1b78 90010034 7c992378 7cbd2b78 8128000c 39290001 9128000c 3f40c026
38000010 813a01a8 7c0903a6 39400000 7d695b78 396b0004 800b0000
note: insmod[447] exited with preempt_count 1
BUG: scheduling while atomic: insmod/0x10000001/447
Call Trace:
[C3E7BB80] [C00081E0] (unreliable)
[C3E7BBB0] [C01DDCB0]
[C3E7BC00] [C0017CD8]
[C3E7BC10] [C01DE924]
[C3E7BC20] [C00520C0]
[C3E7BCA0] [C0055B0C]
[C3E7BCD0] [C001A764]
[C3E7BCE0] [C001E8A0]
[C3E7BD00] [C0020428]
[C3E7BD40] [C000DB84]
[C3E7BD60] [C0011084]
[C3E7BD70] [C000FA64]
--- Exception: 300[C3E7BE30] [C5060000] (unreliable)
[C3E7BE60] [C0016458]
[C3E7BE80] [C506026C]
[C3E7BEA0] [C003F804]
[C3E7BF40] [C000F5C8]
--- Exception: c01Segmentation fault
How should I use the API to initialize the Bestcomm task?
Regards,
Pedro Dominguez
_________________________________________________________________
Prueba algunos de los nuevos servicios en l=EDnea que te ofrece Windows Liv=
e Ideas: tan nuevos que ni siquiera se han publicado oficialmente todav=EDa=
.
http://ideas.live.com=
^ permalink raw reply
* Re: SYSFS: need a noncaching read
From: Tejun Heo @ 2007-09-17 5:22 UTC (permalink / raw)
To: Greg KH; +Cc: linuxppc-dev, Heiko Schocher, linux-kernel, Detlev Zundel
In-Reply-To: <20070912100123.GA23182@kroah.com>
Greg KH wrote:
> On Wed, Sep 12, 2007 at 07:32:07AM +0200, Robert Schwebel wrote:
>> On Tue, Sep 11, 2007 at 11:43:17AM +0200, Heiko Schocher wrote:
>>> I have developed a device driver and use the sysFS to export some
>>> registers to userspace.
>> Uuuh, uggly. Don't do that. Device drivers are there to abstract things,
>> not to play around with registers from userspace.
>>
>>> I opened the sysFS File for one register and did some reads from this
>>> File, but I alwas becoming the same value from the register, whats not
>>> OK, because they are changing. So I found out that the sysFS caches
>>> the reads ... :-(
>> Yes, it does. What you can do is close()ing the file handle between
>> accesses, which makes it work but is slow.
>
> Do an lseek back to 0 and then re-read, you will get called in your
> driver again.
There should be an intervening sysfs_notify() call from kernel side to
make sysfs re-populate its cache on read again. sysfs bin files buffer
the result but don't cache the result but this again doesn't really fit
the usage case.
Thanks.
--
tejun
^ permalink raw reply
* Re: [PATCH 09/10] ppc64: Convert cpu_sibling_map to a per_cpu data array (v3)
From: Stephen Rothwell @ 2007-09-17 6:39 UTC (permalink / raw)
To: travis
Cc: linux-mm, Andi Kleen, linux-kernel, linuxppc-dev, sparclinux,
Andrew Morton, Christoph Lameter
In-Reply-To: <20070917162831.b2a9d675.sfr@canb.auug.org.au>
[-- Attachment #1: Type: text/plain, Size: 718 bytes --]
On Mon, 17 Sep 2007 16:28:31 +1000 Stephen Rothwell <sfr@canb.auug.org.au> wrote:
>
> the topology (on my POWERPC5+ box) is not correct:
>
> cpu0/topology/thread_siblings:0000000f
> cpu1/topology/thread_siblings:0000000f
> cpu2/topology/thread_siblings:0000000f
> cpu3/topology/thread_siblings:0000000f
>
> it used to be:
>
> cpu0/topology/thread_siblings:00000003
> cpu1/topology/thread_siblings:00000003
> cpu2/topology/thread_siblings:0000000c
> cpu3/topology/thread_siblings:0000000c
This would be because we are setting up the cpu_sibling map before we
call setup_per_cpu_areas().
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH 09/10] ppc64: Convert cpu_sibling_map to a per_cpu data array (v3)
From: Stephen Rothwell @ 2007-09-17 6:28 UTC (permalink / raw)
To: travis
Cc: linux-mm, Andi Kleen, linux-kernel, linuxppc-dev, sparclinux,
Andrew Morton, Christoph Lameter
In-Reply-To: <20070912015647.486500682@sgi.com>
[-- Attachment #1: Type: text/plain, Size: 1319 bytes --]
On Tue, 11 Sep 2007 18:56:53 -0700 travis@sgi.com wrote:
>
> Convert cpu_sibling_map to a per_cpu cpumask_t array for the ppc64
> architecture. This fixes build errors in block/blktrace.c and
> kernel/sched.c when CONFIG_SCHED_SMT is defined.
>
> Note: these changes have not been built nor tested.
After applying all 10 patches, the ppc64_defconfig builds but:
vmlinux is larger:
text data bss dec hex filename
7705776 1756984 504624 9967384 981718 ppc64/vmlinux
7706228 1757120 504624 9967972 981964 trav.bld/vmlinux
the topology (on my POWERPC5+ box) is not correct:
cpu0/topology/thread_siblings:0000000f
cpu1/topology/thread_siblings:0000000f
cpu2/topology/thread_siblings:0000000f
cpu3/topology/thread_siblings:0000000f
it used to be:
cpu0/topology/thread_siblings:00000003
cpu1/topology/thread_siblings:00000003
cpu2/topology/thread_siblings:0000000c
cpu3/topology/thread_siblings:0000000c
Similarly on my iSeries box, the topology is displayed as above
while it used to be:
cpu0/topology/thread_siblings:00000001
cpu1/topology/thread_siblings:00000002
cpu2/topology/thread_siblings:00000004
cpu3/topology/thread_siblings:00000008
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH] i2c: devtree-aware iic support for PPC4xx
From: Eugene Surovegin @ 2007-09-17 6:22 UTC (permalink / raw)
To: Stefan Roese; +Cc: Jean Delvare, linuxppc-dev, i2c
In-Reply-To: <200709170734.09079.sr@denx.de>
On Mon, Sep 17, 2007 at 07:34:08AM +0200, Stefan Roese wrote:
>
> My understanding was, that adding many #ifdef's into the code was not the
> preferred way.
But just making a copy seems to be a proffered one? Wow.
OCP and/or OF part is quite small part of the driver; another approach
would been completely splitting OCP and OF specific part out
(e.g. i2c-ibm_iic.c + i2c-ibm_iic_ocp.c / i2c_ibm_iic_of.c). I
personally thing it's not worth the effort and just adding couple of
ifdef'ed code is good enough, especially as a transitional thing.
> I could of course change this patch to not add an additional
> driver but extend the existing driver with a bunch of #ifdef's to support
> both versions.
>
> This approach of multiple drivers seems to be common in the kernel right now:
>
> drivers/mtd/maps/physmap.c
> drivers/mtd/maps/physmap_of.c
>
> or
>
> drivers/usb/host/ohci-ppc-soc.c
> drivers/usb/host/ohci-ppc-of.c
I don't think these are good examples, physmap.c seems to differ from
physmap_of.c significantly. These drivers are mostly a glue, and it
makes sense to have different versions, because there isn't much there
except for platform/bus/glue specific code.
> Any other opinions on this? How should this be handled to get accepted
> upstream? Two different drivers with removing the "old" one later when
> arch/ppc is gone,
ppc has been going away for the last two years at least and still
isn't gone. What makes you think this isn't gonna take another year or
two :) ?
>
> The "old" name "i2c-ibm_iic" is kind of redundant. Nearly all bus drivers are
> named "i2c-platform". Perhaps a better name would be "i2c-ppc4xx" then.
Sure, that'd be a much better choice.
--
Eugene
^ permalink raw reply
* [PATCH 7/7] Remove msic_dcr_read() and use dcr_map_reg() in axon_msi.c
From: Michael Ellerman @ 2007-09-17 6:05 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <449a181e8169af98984bb2d61a759c23e55d19b4.1190009070.git.michael@ellerman.id.au>
msic_dcr_read() doesn't really do anything useful, just replace it with
direct calls to dcr_read().
Use dcr_map_reg() in the axon_msi setup code, rather than essentially doing
it by hand.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/cell/axon_msi.c | 22 +++-------------------
1 files changed, 3 insertions(+), 19 deletions(-)
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index 26a5e88..57a6149 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -80,18 +80,13 @@ static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val)
dcr_write(msic->dcr_host, dcr_n, val);
}
-static u32 msic_dcr_read(struct axon_msic *msic, unsigned int dcr_n)
-{
- return dcr_read(msic->dcr_host, dcr_n);
-}
-
static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
{
struct axon_msic *msic = get_irq_data(irq);
u32 write_offset, msi;
int idx;
- write_offset = msic_dcr_read(msic, MSIC_WRITE_OFFSET_REG);
+ write_offset = dcr_read(msic->dcr_host, MSIC_WRITE_OFFSET_REG);
pr_debug("axon_msi: original write_offset 0x%x\n", write_offset);
/* write_offset doesn't wrap properly, so we have to mask it */
@@ -306,7 +301,7 @@ static int axon_msi_notify_reboot(struct notifier_block *nb,
list_for_each_entry(msic, &axon_msic_list, list) {
pr_debug("axon_msi: disabling %s\n",
msic->irq_host->of_node->full_name);
- tmp = msic_dcr_read(msic, MSIC_CTRL_REG);
+ tmp = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
msic_dcr_write(msic, MSIC_CTRL_REG, tmp);
}
@@ -323,7 +318,6 @@ static int axon_msi_setup_one(struct device_node *dn)
struct page *page;
struct axon_msic *msic;
unsigned int virq;
- int dcr_base, dcr_len;
pr_debug("axon_msi: setting up dn %s\n", dn->full_name);
@@ -334,17 +328,7 @@ static int axon_msi_setup_one(struct device_node *dn)
goto out;
}
- dcr_base = dcr_resource_start(dn, 0);
- dcr_len = dcr_resource_len(dn, 0);
-
- if (dcr_base == 0 || dcr_len == 0) {
- printk(KERN_ERR
- "axon_msi: couldn't parse dcr properties on %s\n",
- dn->full_name);
- goto out;
- }
-
- msic->dcr_host = dcr_map(dn, dcr_base, dcr_len);
+ msic->dcr_host = dcr_map_reg(dn, 0);
if (!DCR_MAP_OK(msic->dcr_host)) {
printk(KERN_ERR "axon_msi: dcr_map failed for %s\n",
dn->full_name);
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH 6/7] Add dcr_map_reg() helper
From: Michael Ellerman @ 2007-09-17 6:05 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <449a181e8169af98984bb2d61a759c23e55d19b4.1190009070.git.michael@ellerman.id.au>
Add a helper routine to map dcr's based on the "dcr-reg" property of
a device node.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/sysdev/dcr.c | 17 +++++++++++++++++
include/asm-powerpc/dcr.h | 1 +
2 files changed, 18 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c
index ab11c0b..da4f9c6 100644
--- a/arch/powerpc/sysdev/dcr.c
+++ b/arch/powerpc/sysdev/dcr.c
@@ -126,6 +126,23 @@ dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n,
}
EXPORT_SYMBOL_GPL(dcr_map);
+dcr_host_t dcr_map_reg(struct device_node *dev, unsigned int index)
+{
+ dcr_host_t ret = { .token = NULL };
+
+ unsigned int dcr_n, dcr_c;
+
+ dcr_n = dcr_resource_start(dev, index);
+ if (!dcr_n)
+ return ret;
+
+ dcr_c = dcr_resource_len(dev, index);
+ if (!dcr_c)
+ return ret;
+
+ return dcr_map(dev, dcr_n, dcr_c);
+}
+
void dcr_unmap(dcr_host_t host, unsigned int dcr_n, unsigned int dcr_c)
{
dcr_host_t h = host;
diff --git a/include/asm-powerpc/dcr.h b/include/asm-powerpc/dcr.h
index 9338d50..4d42f01 100644
--- a/include/asm-powerpc/dcr.h
+++ b/include/asm-powerpc/dcr.h
@@ -38,6 +38,7 @@ extern unsigned int dcr_resource_start(struct device_node *np,
unsigned int index);
extern unsigned int dcr_resource_len(struct device_node *np,
unsigned int index);
+extern dcr_host_t dcr_map_reg(struct device_node *np, unsigned int index);
#endif /* CONFIG_PPC_MERGE */
#endif /* CONFIG_PPC_DCR */
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH 5/7] Add dcr_host_t.base in dcr_read()/dcr_write()
From: Michael Ellerman @ 2007-09-17 6:05 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <449a181e8169af98984bb2d61a759c23e55d19b4.1190009070.git.michael@ellerman.id.au>
Now that all users of dcr_read()/dcr_write() add the dcr_host_t.base, we can
save them the trouble and do it in dcr_read()/dcr_write().
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/cell/axon_msi.c | 4 ++--
arch/powerpc/sysdev/mpic.c | 4 ++--
drivers/net/ibm_emac/ibm_emac_mal.h | 4 ++--
include/asm-powerpc/dcr-mmio.h | 4 ++--
include/asm-powerpc/dcr-native.h | 4 ++--
5 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index 23e039a..26a5e88 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -77,12 +77,12 @@ static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val)
{
pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n);
- dcr_write(msic->dcr_host, msic->dcr_host.base + dcr_n, val);
+ dcr_write(msic->dcr_host, dcr_n, val);
}
static u32 msic_dcr_read(struct axon_msic *msic, unsigned int dcr_n)
{
- return dcr_read(msic->dcr_host, msic->dcr_host.base + dcr_n);
+ return dcr_read(msic->dcr_host, dcr_n);
}
static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 16b1f4b..61f5730 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -156,7 +156,7 @@ static inline u32 _mpic_read(enum mpic_reg_type type,
switch(type) {
#ifdef CONFIG_PPC_DCR
case mpic_access_dcr:
- return dcr_read(rb->dhost, rb->dhost.base + reg);
+ return dcr_read(rb->dhost, reg);
#endif
case mpic_access_mmio_be:
return in_be32(rb->base + (reg >> 2));
@@ -173,7 +173,7 @@ static inline void _mpic_write(enum mpic_reg_type type,
switch(type) {
#ifdef CONFIG_PPC_DCR
case mpic_access_dcr:
- return dcr_write(rb->dhost, rb->dhost.base + reg, value);
+ return dcr_write(rb->dhost, reg, value);
#endif
case mpic_access_mmio_be:
return out_be32(rb->base + (reg >> 2), value);
diff --git a/drivers/net/ibm_emac/ibm_emac_mal.h b/drivers/net/ibm_emac/ibm_emac_mal.h
index 6b1fbeb..10dc978 100644
--- a/drivers/net/ibm_emac/ibm_emac_mal.h
+++ b/drivers/net/ibm_emac/ibm_emac_mal.h
@@ -208,12 +208,12 @@ struct ibm_ocp_mal {
static inline u32 get_mal_dcrn(struct ibm_ocp_mal *mal, int reg)
{
- return dcr_read(mal->dcrhost, mal->dcrhost.base + reg);
+ return dcr_read(mal->dcrhost, reg);
}
static inline void set_mal_dcrn(struct ibm_ocp_mal *mal, int reg, u32 val)
{
- dcr_write(mal->dcrhost, mal->dcrhost.base + reg, val);
+ dcr_write(mal->dcrhost, reg, val);
}
/* Register MAL devices */
diff --git a/include/asm-powerpc/dcr-mmio.h b/include/asm-powerpc/dcr-mmio.h
index 6b82c3b..a7d9eaf 100644
--- a/include/asm-powerpc/dcr-mmio.h
+++ b/include/asm-powerpc/dcr-mmio.h
@@ -37,12 +37,12 @@ extern void dcr_unmap(dcr_host_t host, unsigned int dcr_n, unsigned int dcr_c);
static inline u32 dcr_read(dcr_host_t host, unsigned int dcr_n)
{
- return in_be32(host.token + dcr_n * host.stride);
+ return in_be32(host.token + ((host.base + dcr_n) * host.stride));
}
static inline void dcr_write(dcr_host_t host, unsigned int dcr_n, u32 value)
{
- out_be32(host.token + dcr_n * host.stride, value);
+ out_be32(host.token + ((host.base + dcr_n) * host.stride), value);
}
extern u64 of_translate_dcr_address(struct device_node *dev,
diff --git a/include/asm-powerpc/dcr-native.h b/include/asm-powerpc/dcr-native.h
index f41058c..3bc780f 100644
--- a/include/asm-powerpc/dcr-native.h
+++ b/include/asm-powerpc/dcr-native.h
@@ -30,8 +30,8 @@ typedef struct {
#define dcr_map(dev, dcr_n, dcr_c) ((dcr_host_t){ .base = (dcr_n) })
#define dcr_unmap(host, dcr_n, dcr_c) do {} while (0)
-#define dcr_read(host, dcr_n) mfdcr(dcr_n)
-#define dcr_write(host, dcr_n, value) mtdcr(dcr_n, value)
+#define dcr_read(host, dcr_n) mfdcr(dcr_n + host.base)
+#define dcr_write(host, dcr_n, value) mtdcr(dcr_n + host.base, value)
/* Device Control Registers */
void __mtdcr(int reg, unsigned int val);
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH 4/7] Update axon_msi to use dcr_host_t.base
From: Michael Ellerman @ 2007-09-17 6:05 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <449a181e8169af98984bb2d61a759c23e55d19b4.1190009070.git.michael@ellerman.id.au>
Now that dcr_host_t contains the base address, we can use that in the
axon_msi code, rather than storing it separately.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/cell/axon_msi.c | 13 ++++++-------
1 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index 74407af..23e039a 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -69,7 +69,6 @@ struct axon_msic {
dcr_host_t dcr_host;
struct list_head list;
u32 read_offset;
- u32 dcr_base;
};
static LIST_HEAD(axon_msic_list);
@@ -78,12 +77,12 @@ static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val)
{
pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n);
- dcr_write(msic->dcr_host, msic->dcr_base + dcr_n, val);
+ dcr_write(msic->dcr_host, msic->dcr_host.base + dcr_n, val);
}
static u32 msic_dcr_read(struct axon_msic *msic, unsigned int dcr_n)
{
- return dcr_read(msic->dcr_host, msic->dcr_base + dcr_n);
+ return dcr_read(msic->dcr_host, msic->dcr_host.base + dcr_n);
}
static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
@@ -324,7 +323,7 @@ static int axon_msi_setup_one(struct device_node *dn)
struct page *page;
struct axon_msic *msic;
unsigned int virq;
- int dcr_len;
+ int dcr_base, dcr_len;
pr_debug("axon_msi: setting up dn %s\n", dn->full_name);
@@ -335,17 +334,17 @@ static int axon_msi_setup_one(struct device_node *dn)
goto out;
}
- msic->dcr_base = dcr_resource_start(dn, 0);
+ dcr_base = dcr_resource_start(dn, 0);
dcr_len = dcr_resource_len(dn, 0);
- if (msic->dcr_base == 0 || dcr_len == 0) {
+ if (dcr_base == 0 || dcr_len == 0) {
printk(KERN_ERR
"axon_msi: couldn't parse dcr properties on %s\n",
dn->full_name);
goto out;
}
- msic->dcr_host = dcr_map(dn, msic->dcr_base, dcr_len);
+ msic->dcr_host = dcr_map(dn, dcr_base, dcr_len);
if (!DCR_MAP_OK(msic->dcr_host)) {
printk(KERN_ERR "axon_msi: dcr_map failed for %s\n",
dn->full_name);
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH 3/7] Use dcr_host_t.base in ibm_emac_mal
From: Michael Ellerman @ 2007-09-17 6:05 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <449a181e8169af98984bb2d61a759c23e55d19b4.1190009070.git.michael@ellerman.id.au>
This requires us to do a sort-of fake dcr_map(), so that base is set
properly. This will be fixed/removed when the device-tree-aware emac driver
is merged.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
drivers/net/ibm_emac/ibm_emac_mal.c | 5 ++++-
drivers/net/ibm_emac/ibm_emac_mal.h | 5 ++---
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ibm_emac/ibm_emac_mal.c b/drivers/net/ibm_emac/ibm_emac_mal.c
index cabd984..b08da96 100644
--- a/drivers/net/ibm_emac/ibm_emac_mal.c
+++ b/drivers/net/ibm_emac/ibm_emac_mal.c
@@ -421,7 +421,10 @@ static int __init mal_probe(struct ocp_device *ocpdev)
ocpdev->def->index);
return -ENOMEM;
}
- mal->dcrbase = maldata->dcr_base;
+
+ /* XXX This only works for native dcr for now */
+ mal->dcrhost = dcr_map(NULL, maldata->dcr_base, 0);
+
mal->def = ocpdev->def;
INIT_LIST_HEAD(&mal->poll_list);
diff --git a/drivers/net/ibm_emac/ibm_emac_mal.h b/drivers/net/ibm_emac/ibm_emac_mal.h
index 64bc338..6b1fbeb 100644
--- a/drivers/net/ibm_emac/ibm_emac_mal.h
+++ b/drivers/net/ibm_emac/ibm_emac_mal.h
@@ -191,7 +191,6 @@ struct mal_commac {
};
struct ibm_ocp_mal {
- int dcrbase;
dcr_host_t dcrhost;
struct list_head poll_list;
@@ -209,12 +208,12 @@ struct ibm_ocp_mal {
static inline u32 get_mal_dcrn(struct ibm_ocp_mal *mal, int reg)
{
- return dcr_read(mal->dcrhost, mal->dcrbase + reg);
+ return dcr_read(mal->dcrhost, mal->dcrhost.base + reg);
}
static inline void set_mal_dcrn(struct ibm_ocp_mal *mal, int reg, u32 val)
{
- dcr_write(mal->dcrhost, mal->dcrbase + reg, val);
+ dcr_write(mal->dcrhost, mal->dcrhost.base + reg, val);
}
/* Register MAL devices */
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH 2/7] Update mpic to use dcr_host_t.base
From: Michael Ellerman @ 2007-09-17 6:05 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <449a181e8169af98984bb2d61a759c23e55d19b4.1190009070.git.michael@ellerman.id.au>
Now that dcr_host_t contains the base address, we can use that in the mpic
code, rather than storing it separately.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/sysdev/mpic.c | 28 +++++++++++-----------------
include/asm-powerpc/mpic.h | 6 ------
2 files changed, 11 insertions(+), 23 deletions(-)
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 8de29f2..16b1f4b 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -156,8 +156,7 @@ static inline u32 _mpic_read(enum mpic_reg_type type,
switch(type) {
#ifdef CONFIG_PPC_DCR
case mpic_access_dcr:
- return dcr_read(rb->dhost,
- rb->dbase + reg + rb->doff);
+ return dcr_read(rb->dhost, rb->dhost.base + reg);
#endif
case mpic_access_mmio_be:
return in_be32(rb->base + (reg >> 2));
@@ -174,8 +173,7 @@ static inline void _mpic_write(enum mpic_reg_type type,
switch(type) {
#ifdef CONFIG_PPC_DCR
case mpic_access_dcr:
- return dcr_write(rb->dhost,
- rb->dbase + reg + rb->doff, value);
+ return dcr_write(rb->dhost, rb->dhost.base + reg, value);
#endif
case mpic_access_mmio_be:
return out_be32(rb->base + (reg >> 2), value);
@@ -279,9 +277,11 @@ static void _mpic_map_mmio(struct mpic *mpic, unsigned long phys_addr,
static void _mpic_map_dcr(struct mpic *mpic, struct mpic_reg_bank *rb,
unsigned int offset, unsigned int size)
{
- rb->dbase = mpic->dcr_base;
- rb->doff = offset;
- rb->dhost = dcr_map(mpic->irqhost->of_node, rb->dbase + rb->doff, size);
+ const u32 *dbasep;
+
+ dbasep = of_get_property(mpic->irqhost->of_node, "dcr-reg", NULL);
+
+ rb->dhost = dcr_map(mpic->irqhost->of_node, *dbasep + offset, size);
BUG_ON(!DCR_MAP_OK(rb->dhost));
}
@@ -1075,20 +1075,14 @@ struct mpic * __init mpic_alloc(struct device_node *node,
BUG_ON(paddr == 0 && node == NULL);
/* If no physical address passed in, check if it's dcr based */
- if (paddr == 0 && of_get_property(node, "dcr-reg", NULL) != NULL)
- mpic->flags |= MPIC_USES_DCR;
-
+ if (paddr == 0 && of_get_property(node, "dcr-reg", NULL) != NULL) {
#ifdef CONFIG_PPC_DCR
- if (mpic->flags & MPIC_USES_DCR) {
- const u32 *dbasep;
- dbasep = of_get_property(node, "dcr-reg", NULL);
- BUG_ON(dbasep == NULL);
- mpic->dcr_base = *dbasep;
+ mpic->flags |= MPIC_USES_DCR;
mpic->reg_type = mpic_access_dcr;
- }
#else
- BUG_ON (mpic->flags & MPIC_USES_DCR);
+ BUG();
#endif /* CONFIG_PPC_DCR */
+ }
/* If the MPIC is not DCR based, and no physical address was passed
* in, try to obtain one
diff --git a/include/asm-powerpc/mpic.h b/include/asm-powerpc/mpic.h
index edb4a7c..ae84dde 100644
--- a/include/asm-powerpc/mpic.h
+++ b/include/asm-powerpc/mpic.h
@@ -224,8 +224,6 @@ struct mpic_reg_bank {
u32 __iomem *base;
#ifdef CONFIG_PPC_DCR
dcr_host_t dhost;
- unsigned int dbase;
- unsigned int doff;
#endif /* CONFIG_PPC_DCR */
};
@@ -289,10 +287,6 @@ struct mpic
struct mpic_reg_bank cpuregs[MPIC_MAX_CPUS];
struct mpic_reg_bank isus[MPIC_MAX_ISU];
-#ifdef CONFIG_PPC_DCR
- unsigned int dcr_base;
-#endif
-
/* Protected sources */
unsigned long *protected;
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH 1/7] Store the base address in dcr_host_t
From: Michael Ellerman @ 2007-09-17 6:05 UTC (permalink / raw)
To: linuxppc-dev
In its current form, dcr_map() doesn't remember the base address you passed
it, which means you need to store it somewhere else. Rather than adding the
base to another struct it seems simpler to store it in the dcr_host_t.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/sysdev/dcr.c | 2 +-
include/asm-powerpc/dcr-mmio.h | 6 +++++-
include/asm-powerpc/dcr-native.h | 6 ++++--
3 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c
index e82d54d..ab11c0b 100644
--- a/arch/powerpc/sysdev/dcr.c
+++ b/arch/powerpc/sysdev/dcr.c
@@ -104,7 +104,7 @@ u64 of_translate_dcr_address(struct device_node *dev,
dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n,
unsigned int dcr_c)
{
- dcr_host_t ret = { .token = NULL, .stride = 0 };
+ dcr_host_t ret = { .token = NULL, .stride = 0, .base = dcr_n };
u64 addr;
pr_debug("dcr_map(%s, 0x%x, 0x%x)\n",
diff --git a/include/asm-powerpc/dcr-mmio.h b/include/asm-powerpc/dcr-mmio.h
index 5dbfca8..6b82c3b 100644
--- a/include/asm-powerpc/dcr-mmio.h
+++ b/include/asm-powerpc/dcr-mmio.h
@@ -23,7 +23,11 @@
#include <asm/io.h>
-typedef struct { void __iomem *token; unsigned int stride; } dcr_host_t;
+typedef struct {
+ void __iomem *token;
+ unsigned int stride;
+ unsigned int base;
+} dcr_host_t;
#define DCR_MAP_OK(host) ((host).token != NULL)
diff --git a/include/asm-powerpc/dcr-native.h b/include/asm-powerpc/dcr-native.h
index 05af081..f41058c 100644
--- a/include/asm-powerpc/dcr-native.h
+++ b/include/asm-powerpc/dcr-native.h
@@ -22,11 +22,13 @@
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
-typedef struct {} dcr_host_t;
+typedef struct {
+ unsigned int base;
+} dcr_host_t;
#define DCR_MAP_OK(host) (1)
-#define dcr_map(dev, dcr_n, dcr_c) ((dcr_host_t){})
+#define dcr_map(dev, dcr_n, dcr_c) ((dcr_host_t){ .base = (dcr_n) })
#define dcr_unmap(host, dcr_n, dcr_c) do {} while (0)
#define dcr_read(host, dcr_n) mfdcr(dcr_n)
#define dcr_write(host, dcr_n, value) mtdcr(dcr_n, value)
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH] Make sure to of_node_get() the result of pci_device_to_OF_node()
From: Michael Ellerman @ 2007-09-17 6:03 UTC (permalink / raw)
To: linuxppc-dev
pci_device_to_OF_node() returns the device node attached to a PCI device,
but doesn't actually grab a reference - we need to do it ourselves.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/cell/axon_msi.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index 57a6149..2b2dfcc 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -119,7 +119,7 @@ static struct axon_msic *find_msi_translator(struct pci_dev *dev)
const phandle *ph;
struct axon_msic *msic = NULL;
- dn = pci_device_to_OF_node(dev);
+ dn = of_node_get(pci_device_to_OF_node(dev));
if (!dn) {
dev_dbg(&dev->dev, "axon_msi: no pci_dn found\n");
return NULL;
@@ -176,7 +176,7 @@ static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg)
int len;
const u32 *prop;
- dn = pci_device_to_OF_node(dev);
+ dn = of_node_get(pci_device_to_OF_node(dev));
if (!dn) {
dev_dbg(&dev->dev, "axon_msi: no pci_dn found\n");
return -ENODEV;
--
1.5.1.3.g7a33b
^ permalink raw reply related
* Re: [PATCH] i2c: devtree-aware iic support for PPC4xx
From: David Gibson @ 2007-09-17 5:50 UTC (permalink / raw)
To: Stefan Roese; +Cc: Jean Delvare, linuxppc-dev, i2c
In-Reply-To: <200709170734.09079.sr@denx.de>
On Mon, Sep 17, 2007 at 07:34:08AM +0200, Stefan Roese wrote:
> On Sunday 16 September 2007, Eugene Surovegin wrote:
> > Hmm, I just noticed that you basically added a copy of existing
> > driver with small changes to support OF while keeping OCP one.
> >
> > Why not just add OF support to the existing code (under some ifdef),
> > and then remove OCP support as soon as ppc -> powerpc transition is
> > finished? Why have two almost identical code in the tree?
>
> My understanding was, that adding many #ifdef's into the code was not the
> preferred way. I could of course change this patch to not add an additional
> driver but extend the existing driver with a bunch of #ifdef's to support
> both versions.
#ifdefs are yucky, but so is duplication. I'm not sure which is the
lesser evil in this case.
> This approach of multiple drivers seems to be common in the kernel right now:
>
> drivers/mtd/maps/physmap.c
> drivers/mtd/maps/physmap_of.c
Not a relevant example. Despite the names, physmap and physmap_of
don't really do the same thing at all. I've been meaning to rename
physmap_of...
>
> or
>
> drivers/usb/host/ohci-ppc-soc.c
> drivers/usb/host/ohci-ppc-of.c
Also ibm_emac vs. ibm_new_emac (not merged yet).
> Any other opinions on this? How should this be handled to get accepted
> upstream? Two different drivers with removing the "old" one later when
> arch/ppc is gone, or one driver which supports both versions and removing the
> ocp support in this driver later?
>
> > I also personally don't like this _iic -> _of name change (you
> > removed peripheral name and added something which has nothing to do
> > with iic, I never heard of OF peripheral in 4xx chips). Whether you
> > use OCP or OF to pass a little information is quite irrelevant to the
> > iic driver operation.
>
> The "old" name "i2c-ibm_iic" is kind of redundant. Nearly all bus drivers are
> named "i2c-platform". Perhaps a better name would be "i2c-ppc4xx" then.
> This "of" name was borrowed from already existing device-tree aware drivers
> like drivers/mtd/maps/physmap_of.c or drivers/usb/host/ohci-ppc-of.c.
'ibm' is not specific enough - it's not like it's used on even a very
large fraction of ibm platforms - and 'of' is verging on misleading
(since OF != device tree, although they're related). 'iic' isn't
arbitrary - it comes from the name used in the documentation.
Although 'i2c-ppc4xx' probably is a better name, in any case.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* libfdt: Consistently use big-endian property data in testcases
From: David Gibson @ 2007-09-17 5:42 UTC (permalink / raw)
To: Jon Loeliger; +Cc: linuxppc-dev
Flat device trees always have integers in their structure stored as
big-endian. From this point of view, property values are
bags-of-bytes and any endianness is up to users of the device tree to
determine.
The libfdt testcases which use properties with integer values,
currently use native endian format for the architecture on which the
testcases are run. This works ok for now, since both the creation and
checking of the example device trees happen in the same endianness.
This will become a problem, however, for tests of dtc which we want to
add in the nearish future. dtc always uses big-endian format for
'cell' format data in properties; as it needs to in order to produce
powerpc-usable device trees when hosted on a little-endian
architecture.
This patch, therefore, changes the libfdt testsuite to use big-endian
format always for integer format data, in order to interoperate sanely
with future dtc testcases. This also means that the example trees
created by the testsuite should now be byte-for-byte identical
regardless of dtc and libfdt's host platform, which is arguably an
advantage.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Index: dtc/tests/testdata.h
===================================================================
--- dtc.orig/tests/testdata.h 2007-09-17 11:50:21.000000000 +1000
+++ dtc/tests/testdata.h 2007-09-17 15:41:10.000000000 +1000
@@ -1,5 +1,16 @@
-#define TEST_VALUE_1 0xdeadbeef
-#define TEST_VALUE_2 0xabcd1234
+#include <endian.h>
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define cell_to_fdt(x) (x)
+#else
+/* We do this as a big hairy expression instead of using bswap_32()
+ * because we need it to work in asm as well as C. */
+#define cell_to_fdt(x) ((((x) >> 24) & 0xff) | (((x) >> 8) & 0xff00) \
+ | (((x) << 8) & 0xff0000) | (((x) << 24) & 0xff000000))
+#endif
+
+#define TEST_VALUE_1 cell_to_fdt(0xdeadbeef)
+#define TEST_VALUE_2 cell_to_fdt(0xabcd1234)
#define TEST_STRING_1 "hello world"
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [PATCH] i2c: devtree-aware iic support for PPC4xx
From: Stefan Roese @ 2007-09-17 5:34 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Jean Delvare, i2c
In-Reply-To: <20070916185330.GA32314@gate.ebshome.net>
On Sunday 16 September 2007, Eugene Surovegin wrote:
> Hmm, I just noticed that you basically added a copy of existing
> driver with small changes to support OF while keeping OCP one.
>
> Why not just add OF support to the existing code (under some ifdef),
> and then remove OCP support as soon as ppc -> powerpc transition is
> finished? Why have two almost identical code in the tree?
My understanding was, that adding many #ifdef's into the code was not the
preferred way. I could of course change this patch to not add an additional
driver but extend the existing driver with a bunch of #ifdef's to support
both versions.
This approach of multiple drivers seems to be common in the kernel right now:
drivers/mtd/maps/physmap.c
drivers/mtd/maps/physmap_of.c
or
drivers/usb/host/ohci-ppc-soc.c
drivers/usb/host/ohci-ppc-of.c
Any other opinions on this? How should this be handled to get accepted
upstream? Two different drivers with removing the "old" one later when
arch/ppc is gone, or one driver which supports both versions and removing the
ocp support in this driver later?
> I also personally don't like this _iic -> _of name change (you
> removed peripheral name and added something which has nothing to do
> with iic, I never heard of OF peripheral in 4xx chips). Whether you
> use OCP or OF to pass a little information is quite irrelevant to the
> iic driver operation.
The "old" name "i2c-ibm_iic" is kind of redundant. Nearly all bus drivers are
named "i2c-platform". Perhaps a better name would be "i2c-ppc4xx" then.
This "of" name was borrowed from already existing device-tree aware drivers
like drivers/mtd/maps/physmap_of.c or drivers/usb/host/ohci-ppc-of.c.
> If you insist on this approach, please add yourself as a maintainer of
> this code, because I'm not going to support two identical copies of my
> code in the kernel tree.
I "insist" in nothing. I'm just trying to get this device-tree aware I2C
driver support upstream.
Best regards,
Stefan
^ permalink raw reply
* Re: Domen's MPC5200 FEC cleanup patch.
From: Domen Puncer @ 2007-09-17 5:33 UTC (permalink / raw)
To: Jon Smirl; +Cc: linuxppc-embedded
In-Reply-To: <9e4733910709161205k15106ba1sd2f0597f2601f222@mail.gmail.com>
On 16/09/07 15:05 -0400, Jon Smirl wrote:
> This adjustment to the error counting is in the Efika patches and not
> in yours, should it be in yours too?
I know about this patch.
Error counting is reworked in newer anyway (mixing rmon and ieee
counters didn't look very nice to me).
Domen
>
> --- a/drivers/net/fec_mpc52xx/fec.c 2007-05-30 16:04:50.000000000 +0200
> +++ b/drivers/net/fec_mpc52xx/fec.c 2007-05-30 16:09:02.000000000 +0200
> @@ -411,7 +411,9 @@
>
> stats->rx_bytes = in_be32(&fec->rmon_r_octets);
> stats->rx_packets = in_be32(&fec->rmon_r_packets);
> - stats->rx_errors = stats->rx_packets - in_be32(&fec->ieee_r_frame_ok);
> + stats->rx_errors = stats->rx_packets - (
> + in_be32(&fec->ieee_r_frame_ok) +
> + in_be32(&fec->rmon_r_mc_pkt));
> stats->tx_bytes = in_be32(&fec->rmon_t_octets);
> stats->tx_packets = in_be32(&fec->rmon_t_packets);
> stats->tx_errors = stats->tx_packets - (
>
> --
> Jon Smirl
> jonsmirl@gmail.com
^ permalink raw reply
* [PATCH] [POWERPC] Remove cmd_line from head*.S
From: Stephen Rothwell @ 2007-09-17 4:41 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
It is just a C char array, so declare it thusly.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/kernel/head_32.S | 8 --------
arch/powerpc/kernel/head_40x.S | 7 -------
arch/powerpc/kernel/head_44x.S | 8 --------
arch/powerpc/kernel/head_64.S | 8 --------
arch/powerpc/kernel/head_8xx.S | 8 --------
arch/powerpc/kernel/head_fsl_booke.S | 8 --------
arch/powerpc/kernel/setup-common.c | 2 ++
7 files changed, 2 insertions(+), 47 deletions(-)
This version has the definition in setup-common.c.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index 0e3df1f..a2e4df0 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -1300,14 +1300,6 @@ empty_zero_page:
swapper_pg_dir:
.space 4096
-/*
- * This space gets a copy of optional info passed to us by the bootstrap
- * Used to pass parameters into the kernel like root=/dev/sda1, etc.
- */
- .globl cmd_line
-cmd_line:
- .space 512
-
.globl intercept_table
intercept_table:
.long 0, 0, i0x200, i0x300, i0x400, 0, i0x600, i0x700
diff --git a/arch/powerpc/kernel/head_40x.S b/arch/powerpc/kernel/head_40x.S
index a8e0457..8a69eec 100644
--- a/arch/powerpc/kernel/head_40x.S
+++ b/arch/powerpc/kernel/head_40x.S
@@ -1006,13 +1006,6 @@ critical_stack_top:
.globl exception_stack_top
exception_stack_top:
-/* This space gets a copy of optional info passed to us by the bootstrap
- * which is used to pass parameters into the kernel like root=/dev/sda1, etc.
- */
- .globl cmd_line
-cmd_line:
- .space 512
-
/* Room for two PTE pointers, usually the kernel and current user pointers
* to their respective root page table.
*/
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
index e26d26e..e405c59 100644
--- a/arch/powerpc/kernel/head_44x.S
+++ b/arch/powerpc/kernel/head_44x.S
@@ -744,14 +744,6 @@ exception_stack_bottom:
exception_stack_top:
/*
- * This space gets a copy of optional info passed to us by the bootstrap
- * which is used to pass parameters into the kernel like root=/dev/sda1, etc.
- */
- .globl cmd_line
-cmd_line:
- .space 512
-
-/*
* Room for two PTE pointers, usually the kernel and current user pointers
* to their respective root page table.
*/
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index cec5908..f4ae82e 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -1540,11 +1540,3 @@ empty_zero_page:
.globl swapper_pg_dir
swapper_pg_dir:
.space PAGE_SIZE
-
-/*
- * This space gets a copy of optional info passed to us by the bootstrap
- * Used to pass parameters into the kernel like root=/dev/sda1, etc.
- */
- .globl cmd_line
-cmd_line:
- .space COMMAND_LINE_SIZE
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 901be47..22e1a3c 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -835,14 +835,6 @@ empty_zero_page:
swapper_pg_dir:
.space 4096
-/*
- * This space gets a copy of optional info passed to us by the bootstrap
- * Used to pass parameters into the kernel like root=/dev/sda1, etc.
- */
- .globl cmd_line
-cmd_line:
- .space 512
-
/* Room for two PTE table poiners, usually the kernel and current user
* pointer to their respective root page table (pgdir).
*/
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 1f155d3..5f47adb 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -1050,14 +1050,6 @@ exception_stack_bottom:
exception_stack_top:
/*
- * This space gets a copy of optional info passed to us by the bootstrap
- * which is used to pass parameters into the kernel like root=/dev/sda1, etc.
- */
- .globl cmd_line
-cmd_line:
- .space 512
-
-/*
* Room for two PTE pointers, usually the kernel and current user pointers
* to their respective root page table.
*/
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 50ef38c..36c90ba 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -76,6 +76,8 @@ EXPORT_SYMBOL(machine_id);
unsigned long klimit = (unsigned long) _end;
+char cmd_line[COMMAND_LINE_SIZE];
+
/*
* This still seems to be needed... -- paulus
*/
--
1.5.3.1
^ permalink raw reply related
* dtc: Cleanup testsuite organization
From: David Gibson @ 2007-09-17 4:39 UTC (permalink / raw)
To: Jon Loeliger; +Cc: linuxppc-dev
run_tests.sh from the dtc testsuite currently has a facility ro run
just "functional" or just "stress" tests. This distinction is carried
over from libhugetlbfs where the test framework originated, and where
it made sense.
In dtc, we have no stress tests, so running these subsections isn't
particularly interesting. This patch removes these test subsets,
instead defining a single "libfdt" test subset for testcases related
to libfdt (and not dtc proper only. Currently that's all of the
testcases, but with any luck we'll have some dtc testcases in the
future.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Index: dtc/tests/Makefile.tests
===================================================================
--- dtc.orig/tests/Makefile.tests 2007-09-04 14:17:32.000000000 +1000
+++ dtc/tests/Makefile.tests 2007-09-04 14:17:36.000000000 +1000
@@ -49,18 +49,6 @@
checkv: tests
cd $(TESTS_PREFIX); ./run_tests.sh -v
-func: tests
- cd $(TESTS_PREFIX); ./run_tests.sh -t func
-
-funcv: tests
- cd $(TESTS_PREFIX); ./run_tests.sh -t func -v
-
-stress: tests
- cd $(TESTS_PREFIX); ./run_tests.sh -t stress
-
-stressv: tests
- cd $(TESTS_PREFIX); ./run_tests.sh -t stress -v
-
ifneq ($(DEPTARGETS),)
-include $(TESTS_DEPFILES)
endif
Index: dtc/tests/run_tests.sh
===================================================================
--- dtc.orig/tests/run_tests.sh 2007-09-04 14:16:22.000000000 +1000
+++ dtc/tests/run_tests.sh 2007-09-04 14:55:29.000000000 +1000
@@ -49,7 +49,7 @@
run_test nop_node $TREE
}
-functional_tests () {
+libfdt_tests () {
# Make sure we don't have stale blobs lying around
rm -f *.test.dtb
@@ -86,10 +86,6 @@
run_test truncated_property
}
-stress_tests () {
- ITERATIONS=10 # Number of iterations for looping tests
-}
-
while getopts "vdt:" ARG ; do
case $ARG in
"v")
@@ -102,16 +98,13 @@
done
if [ -z "$TESTSETS" ]; then
- TESTSETS="func stress"
+ TESTSETS="libfdt"
fi
for set in $TESTSETS; do
case $set in
- "func")
- functional_tests
- ;;
- "stress")
- stress_tests
+ "libfdt")
+ libfdt_tests
;;
esac
done
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* libfdt: Add fdt_node_offset_by_prop_value()
From: David Gibson @ 2007-09-17 4:28 UTC (permalink / raw)
To: Jon Loeliger; +Cc: linuxppc-dev
This patch adds a function to libfdt to locate nodes containing a
property with a specific value.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Index: dtc/libfdt/fdt_ro.c
===================================================================
--- dtc.orig/libfdt/fdt_ro.c 2007-09-17 14:00:22.000000000 +1000
+++ dtc/libfdt/fdt_ro.c 2007-09-17 14:04:18.000000000 +1000
@@ -407,3 +407,54 @@ int fdt_parent_offset(const void *fdt, i
return fdt_supernode_atdepth_offset(fdt, nodeoffset,
nodedepth - 1, NULL);
}
+
+int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
+ const char *propname,
+ const void *propval, int proplen)
+{
+ uint32_t tag;
+ int offset, nextoffset;
+ const void *val;
+ int len;
+
+ CHECK_HEADER(fdt);
+
+ if (startoffset >= 0) {
+ tag = _fdt_next_tag(fdt, startoffset, &nextoffset);
+ if (tag != FDT_BEGIN_NODE)
+ return -FDT_ERR_BADOFFSET;
+ } else {
+ nextoffset = 0;
+ }
+
+ /* FIXME: The algorithm here is pretty horrible: we scan each
+ * property of a node in fdt_getprop(), then if that didn't
+ * find what we want, we scan over them again making our way
+ * to the next node. Still it's the easiest to implement
+ * approach; performance can come later. */
+ do {
+ offset = nextoffset;
+ tag = _fdt_next_tag(fdt, offset, &nextoffset);
+
+ switch (tag) {
+ case FDT_BEGIN_NODE:
+ val = fdt_getprop(fdt, offset, propname, &len);
+ if (val
+ && (len == proplen)
+ && (memcmp(val, propval, len) == 0))
+ return offset;
+ break;
+
+ case FDT_PROP:
+ case FDT_END:
+ case FDT_END_NODE:
+ case FDT_NOP:
+ break;
+
+ default:
+ return -FDT_ERR_BADSTRUCTURE;
+ }
+ } while (tag != FDT_END);
+
+ return -FDT_ERR_NOTFOUND;
+}
Index: dtc/libfdt/libfdt.h
===================================================================
--- dtc.orig/libfdt/libfdt.h 2007-09-17 14:00:04.000000000 +1000
+++ dtc/libfdt/libfdt.h 2007-09-17 14:00:23.000000000 +1000
@@ -146,6 +146,10 @@ int fdt_supernode_atdepth_offset(const v
int fdt_node_depth(const void *fdt, int nodeoffset);
int fdt_parent_offset(const void *fdt, int nodeoffset);
+int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
+ const char *propname,
+ const void *propval, int proplen);
+
/* Write-in-place functions */
int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
const void *val, int len);
Index: dtc/tests/Makefile.tests
===================================================================
--- dtc.orig/tests/Makefile.tests 2007-09-17 14:00:04.000000000 +1000
+++ dtc/tests/Makefile.tests 2007-09-17 14:00:23.000000000 +1000
@@ -1,5 +1,6 @@
LIB_TESTS_L = root_node find_property subnode_offset path_offset \
get_name getprop get_path supernode_atdepth_offset parent_offset \
+ node_offset_by_prop_value \
notfound \
setprop_inplace nop_property nop_node \
sw_tree1 \
Index: dtc/tests/node_offset_by_prop_value.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ dtc/tests/node_offset_by_prop_value.c 2007-09-17 14:00:23.000000000 +1000
@@ -0,0 +1,110 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_path_offset()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdarg.h>
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+void vcheck_search(void *fdt, const char *propname, const void *propval,
+ int proplen, va_list ap)
+{
+ int offset = -1, target;
+
+ do {
+ target = va_arg(ap, int);
+ verbose_printf("Searching (target = %d): %d ->",
+ target, offset);
+ offset = fdt_node_offset_by_prop_value(fdt, offset, propname,
+ propval, proplen);
+ verbose_printf("%d\n", offset);
+
+ if (offset != target)
+ FAIL("fdt_node_offset_by_prop_value() returns %d "
+ "instead of %d", offset, target);
+ } while (target >= 0);
+}
+
+void check_search(void *fdt, const char *propname, const void *propval,
+ int proplen, ...)
+{
+ va_list ap;
+
+ va_start(ap, proplen);
+ vcheck_search(fdt, propname, propval, proplen, ap);
+ va_end(ap);
+}
+
+void check_search_str(void *fdt, const char *propname, const char *propval, ...)
+{
+ va_list ap;
+
+ va_start(ap, propval);
+ vcheck_search(fdt, propname, propval, strlen(propval)+1, ap);
+ va_end(ap);
+}
+
+#define check_search_val(fdt, propname, propval, ...) \
+ { \
+ typeof(propval) val = (propval); \
+ check_search((fdt), (propname), &val, sizeof(val), \
+ ##__VA_ARGS__); \
+ }
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ int subnode1_offset, subnode2_offset;
+ int subsubnode1_offset, subsubnode2_offset;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ subnode1_offset = fdt_path_offset(fdt, "/subnode1");
+ subnode2_offset = fdt_path_offset(fdt, "/subnode2");
+ subsubnode1_offset = fdt_path_offset(fdt, "/subnode1/subsubnode");
+ subsubnode2_offset = fdt_path_offset(fdt, "/subnode2/subsubnode");
+
+ if ((subnode1_offset < 0) || (subnode2_offset < 0)
+ || (subsubnode1_offset < 0) || (subsubnode2_offset < 0))
+ FAIL("Can't find required nodes");
+
+ check_search_val(fdt, "prop-int", TEST_VALUE_1, 0, subnode1_offset,
+ subsubnode1_offset, -FDT_ERR_NOTFOUND);
+
+ check_search_val(fdt, "prop-int", TEST_VALUE_2, subnode2_offset,
+ subsubnode2_offset, -FDT_ERR_NOTFOUND);
+
+ check_search_str(fdt, "prop-str", TEST_STRING_1, 0, -FDT_ERR_NOTFOUND);
+
+ check_search_str(fdt, "prop-str", "no such string", -FDT_ERR_NOTFOUND);
+
+ check_search_val(fdt, "prop-int", TEST_VALUE_1+1, -FDT_ERR_NOTFOUND);
+
+ check_search(fdt, "no-such-prop", NULL, 0, -FDT_ERR_NOTFOUND);
+
+ PASS();
+}
Index: dtc/tests/run_tests.sh
===================================================================
--- dtc.orig/tests/run_tests.sh 2007-09-17 14:00:04.000000000 +1000
+++ dtc/tests/run_tests.sh 2007-09-17 14:00:23.000000000 +1000
@@ -40,6 +40,7 @@ tree1_tests () {
run_test get_path $TREE
run_test supernode_atdepth_offset $TREE
run_test parent_offset $TREE
+ run_test node_offset_by_prop_value $TREE
run_test notfound $TREE
# Write-in-place tests
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [PATCH] fix xmon input on 440
From: Hollis Blanchard @ 2007-09-17 4:15 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev, David Gibson
In-Reply-To: <20070917033924.GA24914@lixom.net>
On Sun, 2007-09-16 at 22:39 -0500, Olof Johansson wrote:
> On Sun, Sep 16, 2007 at 10:26:37PM -0500, Josh Boyer wrote:
> > On Mon, 2007-09-17 at 12:52 +1000, David Gibson wrote:
> > > On Fri, Sep 14, 2007 at 03:44:47PM -0500, Hollis Blanchard wrote:
> > > > Implement udbg_getc() for 440, which fixes xmon input.
> > > > Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
> > > Acked-by: David Gibson <david@gibson.dropbear.id.au>
> > >
> >
> > I fixed up the whitespace issues and applied it to my tree. Oh, and
> > comments don't need semi-colons ;)
>
> Well, there's a big difference between:
>
> while (foo)
> /* moof */;
> return bar;
>
> and:
> while (foo)
> /* moof */
> return bar;
Right, so this commit is broken:
http://git.infradead.org/?p=users/jwboyer/powerpc.git;a=commitdiff;h=81ec428065c01e37fb143ad31dc04fea27fddcac
--
Hollis Blanchard
IBM Linux Technology Center
^ permalink raw reply
* [PATCH] [POWERPC] Fix section mismatch in pci code
From: Stephen Rothwell @ 2007-09-17 4:08 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
Create a helper function (alloc_maybe_bootmem) that is marked __init_refok
to limit the chances of mistakenly refferring to other __init routines.
WARNING: vmlinux.o(.text+0x2a9c4): Section mismatch: reference to .init.text:.__alloc_bootmem (between '.update_dn_pci_info' and '.pci_dn_reconfig_notifier')
WARNING: vmlinux.o(.text+0x36430): Section mismatch: reference to .init.text:.__alloc_bootmem (between '.mpic_msi_init_allocator' and '.find_ht_magic_addr')
WARNING: vmlinux.o(.text+0x5e804): Section mismatch: reference to .init.text:.__alloc_bootmem (between '.celleb_setup_phb' and '.celleb_fake_pci_write_config')
WARNING: vmlinux.o(.text+0x5e8e8): Section mismatch: reference to .init.text:.__alloc_bootmem (between '.celleb_setup_phb' and '.celleb_fake_pci_write_config')
WARNING: vmlinux.o(.text+0x5e968): Section mismatch: reference to .init.text:.__alloc_bootmem (between '.celleb_setup_phb' and '.celleb_fake_pci_write_config')
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/kernel/pci_dn.c | 7 +------
arch/powerpc/lib/Makefile | 2 +-
arch/powerpc/lib/alloc.c | 14 ++++++++++++++
arch/powerpc/platforms/celleb/pci.c | 19 +++++--------------
arch/powerpc/sysdev/mpic_msi.c | 6 +-----
include/asm-powerpc/system.h | 2 ++
6 files changed, 24 insertions(+), 26 deletions(-)
create mode 100644 arch/powerpc/lib/alloc.c
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c
index d7d36df..b483903 100644
--- a/arch/powerpc/kernel/pci_dn.c
+++ b/arch/powerpc/kernel/pci_dn.c
@@ -23,8 +23,6 @@
#include <linux/pci.h>
#include <linux/string.h>
#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/bootmem.h>
#include <asm/io.h>
#include <asm/prom.h>
@@ -45,10 +43,7 @@ static void * __devinit update_dn_pci_info(struct device_node *dn, void *data)
const u32 *regs;
struct pci_dn *pdn;
- if (mem_init_done)
- pdn = kmalloc(sizeof(*pdn), GFP_KERNEL);
- else
- pdn = alloc_bootmem(sizeof(*pdn));
+ pdn = alloc_maybe_bootmem(sizeof(*pdn), GFP_KERNEL);
if (pdn == NULL)
return NULL;
memset(pdn, 0, sizeof(*pdn));
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 0a486d4..23bbb1e 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -7,7 +7,7 @@ EXTRA_CFLAGS += -mno-minimal-toc
endif
ifeq ($(CONFIG_PPC_MERGE),y)
-obj-y := string.o
+obj-y := string.o alloc.o
obj-$(CONFIG_PPC32) += div64.o copy_32.o checksum_32.o
endif
diff --git a/arch/powerpc/lib/alloc.c b/arch/powerpc/lib/alloc.c
new file mode 100644
index 0000000..e58c805
--- /dev/null
+++ b/arch/powerpc/lib/alloc.c
@@ -0,0 +1,14 @@
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/bootmem.h>
+
+#include <asm/system.h>
+
+void * __init_refok alloc_maybe_bootmem(size_t size, gfp_t mask)
+{
+ if (mem_init_done)
+ return kmalloc(size, mask);
+ else
+ return alloc_bootmem(size);
+}
diff --git a/arch/powerpc/platforms/celleb/pci.c b/arch/powerpc/platforms/celleb/pci.c
index 11336b4..1348b23 100644
--- a/arch/powerpc/platforms/celleb/pci.c
+++ b/arch/powerpc/platforms/celleb/pci.c
@@ -327,10 +327,7 @@ static int __init celleb_setup_fake_pci_device(struct device_node *node,
size = 256;
config = &private->fake_config[devno][fn];
- if (mem_init_done)
- *config = kzalloc(size, GFP_KERNEL);
- else
- *config = alloc_bootmem(size);
+ *config = alloc_maybe_bootmem(size, GFP_KERNEL);
if (*config == NULL) {
printk(KERN_ERR "PCI: "
"not enough memory for fake configuration space\n");
@@ -341,10 +338,7 @@ static int __init celleb_setup_fake_pci_device(struct device_node *node,
size = sizeof(struct celleb_pci_resource);
res = &private->res[devno][fn];
- if (mem_init_done)
- *res = kzalloc(size, GFP_KERNEL);
- else
- *res = alloc_bootmem(size);
+ *res = alloc_maybe_bootmem(size, GFP_KERNEL);
if (*res == NULL) {
printk(KERN_ERR
"PCI: not enough memory for resource data space\n");
@@ -436,12 +430,9 @@ static int __init phb_set_bus_ranges(struct device_node *dev,
static void __init celleb_alloc_private_mem(struct pci_controller *hose)
{
- if (mem_init_done)
- hose->private_data =
- kzalloc(sizeof(struct celleb_pci_private), GFP_KERNEL);
- else
- hose->private_data =
- alloc_bootmem(sizeof(struct celleb_pci_private));
+ hose->private_data =
+ alloc_maybe_bootmem(sizeof(struct celleb_pci_private),
+ GFP_KERNEL);
}
int __init celleb_setup_phb(struct pci_controller *phb)
diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c
index 9ca4d8f..d272a52 100644
--- a/arch/powerpc/sysdev/mpic_msi.c
+++ b/arch/powerpc/sysdev/mpic_msi.c
@@ -9,7 +9,6 @@
*/
#include <linux/irq.h>
-#include <linux/bootmem.h>
#include <linux/bitmap.h>
#include <linux/msi.h>
#include <asm/mpic.h>
@@ -152,10 +151,7 @@ int mpic_msi_init_allocator(struct mpic *mpic)
size = BITS_TO_LONGS(mpic->irq_count) * sizeof(long);
pr_debug("mpic: allocator bitmap size is 0x%x bytes\n", size);
- if (mem_init_done)
- mpic->hwirq_bitmap = kmalloc(size, GFP_KERNEL);
- else
- mpic->hwirq_bitmap = alloc_bootmem(size);
+ mpic->hwirq_bitmap = alloc_maybe_bootmem(size, GFP_KERNEL);
if (!mpic->hwirq_bitmap) {
pr_debug("mpic: ENOMEM allocating allocator bitmap!\n");
diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h
index 41520b7..f7879fc 100644
--- a/include/asm-powerpc/system.h
+++ b/include/asm-powerpc/system.h
@@ -189,6 +189,8 @@ extern int mem_init_done; /* set on boot once kmalloc can be called */
extern unsigned long memory_limit;
extern unsigned long klimit;
+extern void *alloc_maybe_bootmem(size_t size, gfp_t mask);
+
extern int powersave_nap; /* set if nap mode can be used in idle loop */
/*
--
1.5.3.1
^ permalink raw reply related
* [PATCH] [POWERPC] Remove unused variabls from drivers/ide/ppc/pmac.c
From: Stephen Rothwell @ 2007-09-17 4:06 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev, linux-ide
Removes these warnings:
/home/sfr/kernels/linus/drivers/ide/ppc/pmac.c: In function 'pmac_ide_dma_check':
/home/sfr/kernels/linus/drivers/ide/ppc/pmac.c:1807: warning: unused variable 'map'
/home/sfr/kernels/linus/drivers/ide/ppc/pmac.c:1805: warning: unused variable 'pmif'
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
drivers/ide/ppc/pmac.c | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index 4b13cd9..f19eb6d 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -1802,9 +1802,7 @@ pmac_ide_dma_check(ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
ide_hwif_t *hwif = HWIF(drive);
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
int enable = 1;
- int map;
drive->using_dma = 0;
if (drive->media == ide_floppy)
--
1.5.3.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox