* [nacc@us.ibm.com: [PATCH 00/15] ppc iommu cleanups]
From: Nishanth Aravamudan @ 2010-09-15 18:13 UTC (permalink / raw)
To: linuxppc-dev
Clearly need to work on my git-send-mail usage! Apologies...
----- Forwarded message from Nishanth Aravamudan <nacc@us.ibm.com> -----
Date: Wed, 15 Sep 2010 11:05:43 -0700
From: Nishanth Aravamudan <nacc@us.ibm.com>
To: nacc@us.ibm.com
Subject: [PATCH 00/15] ppc iommu cleanups
While working on some upcoming IOMMU-related changes, we found the
following cleanups throughout the ppc code.
Nishanth Aravamudan (15):
ppc: fix return type of BUID_{HI,LO} macros
ppc64: fix dma_iommu_dma_supported compare
ppc64 iommu: fix check for direct DMA support
vio: put device on device_register failure
viobus: free TCE table on device release
pseries/dlpar: use kmemdup
ppc: pci-common cleanup
microblaze: pci-common cleanup
ppc/vio: use dma ops helpers
ppc/pasemi: clean up pasemi iommu table initializations
ppc/cell: beat dma ops cleanup
ppc/dart: iommu table cleanup
ppc/pseries: iommu cleanup
ppc64 iommu: use coherent_dma_mask for alloc_coherent
ppc/vio: ensure dma_coherent_mask is set
arch/microblaze/pci/pci-common.c | 6 ++----
arch/powerpc/include/asm/ppc-pci.h | 4 ++--
arch/powerpc/kernel/dma-iommu.c | 23 ++++++++++++-----------
arch/powerpc/kernel/dma.c | 2 +-
arch/powerpc/kernel/pci-common.c | 4 +---
arch/powerpc/kernel/vio.c | 24 ++++++++++++++++++------
arch/powerpc/platforms/cell/beat_iommu.c | 3 +--
arch/powerpc/platforms/pasemi/iommu.c | 19 +------------------
arch/powerpc/platforms/pseries/dlpar.c | 3 +--
arch/powerpc/platforms/pseries/iommu.c | 9 ++-------
arch/powerpc/sysdev/dart_iommu.c | 18 +-----------------
11 files changed, 42 insertions(+), 73 deletions(-)
---
I used git-send-email for this series, and noticed that
get_maintainer.pl will always pull in LKML to the Cc because of the
following in MAINTAINERS:
THE REST
M: Linus Torvalds <torvalds@linux-foundation.org>
L: linux-kernel@vger.kernel.org
Q: http://patchwork.kernel.org/project/LKML/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
S: Buried alive in reporters
F: *
F: */
Is there any way to exclude that in the script that anyone knows of? Or
am I mis-using the script (as the --cc-cmd option to git-send-email).
Thanks,
Nish
----- End forwarded message -----
--
Nishanth Aravamudan <nacc@us.ibm.com>
IBM Linux Technology Center
^ permalink raw reply
* [PATCH 01/15] ppc: fix return type of BUID_{HI,LO} macros
From: Nishanth Aravamudan @ 2010-09-15 18:13 UTC (permalink / raw)
To: nacc
Cc: Milton Miller, Paul Mackerras, Linas Vepstas, linuxppc-dev,
Breno Leitao
In-Reply-To: <1284573958-8397-1-git-send-email-nacc@us.ibm.com>
BUID_HI and BUID_LO are used to pass data to call_rtas, which expects
ints or u32s. But the macro doesn't cast the return, so the result is
still u64. Use the upper_32_bits and lower_32_bits macros that have been
added to kernel.h.
Found by getting printf format errors trying to debug print the args, no
actual code change for 64 bit kernels where the macros are actually
used.
Signed-off-by: Milton Miller <miltonm@bga.com>
Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
---
arch/powerpc/include/asm/ppc-pci.h | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/include/asm/ppc-pci.h b/arch/powerpc/include/asm/ppc-pci.h
index 42fdff0..43268f1 100644
--- a/arch/powerpc/include/asm/ppc-pci.h
+++ b/arch/powerpc/include/asm/ppc-pci.h
@@ -28,8 +28,8 @@ extern void find_and_init_phbs(void);
extern struct pci_dev *isa_bridge_pcidev; /* may be NULL if no ISA bus */
/** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */
-#define BUID_HI(buid) ((buid) >> 32)
-#define BUID_LO(buid) ((buid) & 0xffffffff)
+#define BUID_HI(buid) upper_32_bits(buid)
+#define BUID_LO(buid) lower_32_bits(buid)
/* PCI device_node operations */
struct device_node;
--
1.7.0.4
^ permalink raw reply related
* RE: [PATCH v2 09/10] RapidIO: Add support for IDT CPS Gen2 switches
From: Anderson, Trevor @ 2010-09-15 18:27 UTC (permalink / raw)
To: Bounine, Alexandre, Andrew Morton
Cc: linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org,
Thomas Moll
In-Reply-To: <0CE8B6BE3C4AD74AB97D9D29BD24E5520130321F@CORPEXCH1.na.ads.idt.com>
Keep it in please. We lurkers in the embedded community do use the per-por=
t routing tables.
One of the problems with SRIO switch tables is that access to routes is no=
t atomic; we can use
restricted access to per-port routing tables to reduce the risk of interfe=
rence. And we still use
the Global table during enumeration.
> -----Original Message-----
> From: linuxppc-dev-bounces+tanderson=3Dcurtisswright.com@lists.ozlabs.or=
g [mailto:linuxppc-dev-
> bounces+tanderson=3Dcurtisswright.com@lists.ozlabs.org] On Behalf Of Bou=
nine, Alexandre
> Sent: Wednesday, September 15, 2010 8:31 AM
> To: Andrew Morton
> Cc: linux-kernel@vger.kernel.org; Thomas Moll; linuxppc-dev@lists.ozlabs=
.org
> Subject: RE: [PATCH v2 09/10] RapidIO: Add support for IDT CPS Gen2 swit=
ches
>
> Andrew Morton <akpm@linux-foundation.org> wrote:
>
> > The handling of `table' is strange. One would expect the caller of
> > this function to provide the correct table index, and for the caller
> to
> > increment that index at an appropriate time.
>
> Handling of the 'table' parameter is hardware-dependent.
> RIO switches (at least all that I know) have a per-port routing tables
> (RT)
> which can be configured independently. The 'table' parameter is expected=
> to match
> to the port number (or broadcast if GLOBAL).
> The route set/get routines in this file use the standard route setting
> registers
> defined by RapidIO spec, but switches have internal mapping into an
> individual
> port RT or broadcast capability into all port RTs.
> Unfortunately, this HW design uses index 0 as a broadcast option that
> offsets
> per-port RT numbering by +1 (port 0 =3D=3D table index 1, etc.).
>
> > So I take a look around but cannot find any means by which
> > ->add_entry() is called with anything other than RIO_GLOBAL_TABLE.
> > Maybe I missed something. Is this all dead code?
>
> The current RIO enumeration uses only the global routing table concept.
> In the past, I had a temptation to remove the 'table' parameter and make=
> RT settings simpler. But now I see scenarios when per-port routing
> tables
> may be configured by usermode apps. This capability may be implemented
> through sysfs attributes (probably I have to add them to make standard).=
> Example: system that uses dual-port endpoints which can be enumerated by=
> the host through one RIO port (management) and have individual routes
> configured for the second port (data path).
>
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
_______________________________________________________________________
This e-mail and any files transmitted with it are proprietary and intended=
solely for the use of the individual or entity to whom they are addressed=
. If you have reason to believe that you have received this e-mail in erro=
r, please notify the sender and destroy this email and any attached files.=
Please note that any views or opinions presented in this e-mail are solel=
y those of the author and do not necessarily represent those of the Curtis=
s-Wright Corporation or any of its subsidiaries. Documents attached heret=
o may contain technology subject to government export regulations. Recipie=
nt is solely responsible for ensuring that any re-export, transfer or disc=
losure of this information is in accordance with applicable government exp=
ort regulations. The recipient should check this e-mail and any attachmen=
ts for the presence of viruses. Curtiss-Wright Corporation and its subsidi=
aries accept no liability for any damage caused by any virus transmitted b=
y this e-mail.
^ permalink raw reply
* Re: [PATCH 10/15] ppc/pasemi: clean up pasemi iommu table initializations
From: Olof Johansson @ 2010-09-15 18:29 UTC (permalink / raw)
To: Nishanth Aravamudan
Cc: linuxppc-dev, Milton Miller, Paul Mackerras, Yinghai Lu
In-Reply-To: <1284573958-8397-11-git-send-email-nacc@us.ibm.com>
On Wed, Sep 15, 2010 at 11:05:53AM -0700, Nishanth Aravamudan wrote:
> No need for empty helpers with iommu off, the ppc_md hooks are optional.
Not any more, they used to be needed. :-)
> The direct_dma_ops are the default pci_dma_ops, so no need to set in the
> them iommu off case.
>
> No need to set the device tree device_node pci node iommu pointer, its
> only used for dlpar remove.
>
> Signed-off-by: Milton Miller <miltonm@bga.com>
> Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
Acked-by: Olof Johansson <olof@lixom.net>
-Olof
^ permalink raw reply
* Re: [PATCH 04/15] vio: put device on device_register failure
From: Grant Likely @ 2010-09-15 18:29 UTC (permalink / raw)
To: Nishanth Aravamudan
Cc: Brian King, Paul Mackerras, linuxppc-dev, Milton Miller
In-Reply-To: <1284573958-8397-5-git-send-email-nacc@us.ibm.com>
On Wed, Sep 15, 2010 at 12:05 PM, Nishanth Aravamudan <nacc@us.ibm.com> wro=
te:
> The kernel doc for device_register (and device_initialize) very clearly
> state to call put_device not kfree after calling, even on error.
>
> Signed-off-by: Milton Miller <miltonm@bga.com>
> Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
> ---
> =A0arch/powerpc/kernel/vio.c | =A0 =A03 +--
> =A01 files changed, 1 insertions(+), 2 deletions(-)
>
> diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
> index fa3469d..72db4b0 100644
> --- a/arch/powerpc/kernel/vio.c
> +++ b/arch/powerpc/kernel/vio.c
> @@ -1254,8 +1254,7 @@ struct vio_dev *vio_register_device_node(struct dev=
ice_node *of_node)
> =A0 =A0 =A0 =A0if (device_register(&viodev->dev)) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0printk(KERN_ERR "%s: failed to register de=
vice %s\n",
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0__func__, =
dev_name(&viodev->dev));
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* XXX free TCE table */
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 kfree(viodev);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 put_device(&viodev->dev);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return NULL;
> =A0 =A0 =A0 =A0}
>
> --
> 1.7.0.4
>
>
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: [PATCH 07/15] ppc: pci-common cleanup
From: Grant Likely @ 2010-09-15 18:30 UTC (permalink / raw)
To: Nishanth Aravamudan
Cc: Dominik Brodowski, Milton Miller, Paul Mackerras, Jesse Barnes,
linuxppc-dev, Bjorn Helgaas
In-Reply-To: <1284573958-8397-8-git-send-email-nacc@us.ibm.com>
On Wed, Sep 15, 2010 at 12:05 PM, Nishanth Aravamudan <nacc@us.ibm.com> wro=
te:
> Use set_dma_ops and remove unused oddly-named temp pointer sd.
>
> Signed-off-by: Milton Miller <miltonm@bga.com>
> Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
> ---
> =A0arch/powerpc/kernel/pci-common.c | =A0 =A04 +---
> =A01 files changed, 1 insertions(+), 3 deletions(-)
>
> diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-c=
ommon.c
> index 9021c4a..10a44e6 100644
> --- a/arch/powerpc/kernel/pci-common.c
> +++ b/arch/powerpc/kernel/pci-common.c
> @@ -1090,8 +1090,6 @@ void __devinit pcibios_setup_bus_devices(struct pci=
_bus *bus)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 bus->number, bus->self ? pci_name(bus->se=
lf) : "PHB");
>
> =A0 =A0 =A0 =A0list_for_each_entry(dev, &bus->devices, bus_list) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct dev_archdata *sd =3D &dev->dev.archd=
ata;
> -
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* Cardbus can call us to add new devices =
to a bus, so ignore
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 * those who are already fully discovered
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 */
> @@ -1107,7 +1105,7 @@ void __devinit pcibios_setup_bus_devices(struct pci=
_bus *bus)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0set_dev_node(&dev->dev, pcibus_to_node(dev=
->bus));
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* Hook up default DMA ops */
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 sd->dma_ops =3D pci_dma_ops;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 set_dma_ops(&dev->dev, pci_dma_ops);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0set_dma_offset(&dev->dev, PCI_DRAM_OFFSET)=
;
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* Additional platform DMA/iommu setup */
> --
> 1.7.0.4
>
>
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: [PATCH 09/15] ppc/vio: use dma ops helpers
From: Grant Likely @ 2010-09-15 18:33 UTC (permalink / raw)
To: Nishanth Aravamudan
Cc: Brian King, Paul Mackerras, linuxppc-dev, Milton Miller
In-Reply-To: <1284573958-8397-10-git-send-email-nacc@us.ibm.com>
On Wed, Sep 15, 2010 at 12:05 PM, Nishanth Aravamudan <nacc@us.ibm.com> wro=
te:
> Use the set_dma_ops helper. Instead of modifying vio_dma_mapping_ops,
> just create a trivial wrapper for dma_supported.
>
> Signed-off-by: Milton Miller <miltonm@bga.com>
> Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
Looks right to me.
> ---
> =A0arch/powerpc/kernel/vio.c | =A0 11 ++++++++---
> =A01 files changed, 8 insertions(+), 3 deletions(-)
>
> diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
> index d692989..3c3083f 100644
> --- a/arch/powerpc/kernel/vio.c
> +++ b/arch/powerpc/kernel/vio.c
> @@ -602,6 +602,11 @@ static void vio_dma_iommu_unmap_sg(struct device *de=
v,
> =A0 =A0 =A0 =A0vio_cmo_dealloc(viodev, alloc_size);
> =A0}
>
> +static int vio_dma_iommu_dma_supported(struct device *dev, u64 mask)
> +{
> + =A0 =A0 =A0 =A0return dma_iommu_ops.dma_supported(dev, mask);
> +}
> +
> =A0struct dma_map_ops vio_dma_mapping_ops =3D {
> =A0 =A0 =A0 =A0.alloc_coherent =3D vio_dma_iommu_alloc_coherent,
> =A0 =A0 =A0 =A0.free_coherent =A0=3D vio_dma_iommu_free_coherent,
> @@ -609,6 +614,7 @@ struct dma_map_ops vio_dma_mapping_ops =3D {
> =A0 =A0 =A0 =A0.unmap_sg =A0 =A0 =A0 =3D vio_dma_iommu_unmap_sg,
> =A0 =A0 =A0 =A0.map_page =A0 =A0 =A0 =3D vio_dma_iommu_map_page,
> =A0 =A0 =A0 =A0.unmap_page =A0 =A0 =3D vio_dma_iommu_unmap_page,
> + =A0 =A0 =A0 .dma_supported =A0=3D vio_dma_iommu_dma_supported,
>
> =A0};
>
> @@ -860,8 +866,7 @@ static void vio_cmo_bus_remove(struct vio_dev *viodev=
)
>
> =A0static void vio_cmo_set_dma_ops(struct vio_dev *viodev)
> =A0{
> - =A0 =A0 =A0 vio_dma_mapping_ops.dma_supported =3D dma_iommu_ops.dma_sup=
ported;
> - =A0 =A0 =A0 viodev->dev.archdata.dma_ops =3D &vio_dma_mapping_ops;
> + =A0 =A0 =A0 set_dma_ops(&viodev->dev, &vio_dma_mapping_ops);
> =A0}
>
> =A0/**
> @@ -1246,7 +1251,7 @@ struct vio_dev *vio_register_device_node(struct dev=
ice_node *of_node)
> =A0 =A0 =A0 =A0if (firmware_has_feature(FW_FEATURE_CMO))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0vio_cmo_set_dma_ops(viodev);
> =A0 =A0 =A0 =A0else
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 viodev->dev.archdata.dma_ops =3D &dma_iommu=
_ops;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 set_dma_ops(&viodev->dev, &dma_iommu_ops);
> =A0 =A0 =A0 =A0set_iommu_table_base(&viodev->dev, vio_build_iommu_table(v=
iodev));
> =A0 =A0 =A0 =A0set_dev_node(&viodev->dev, of_node_to_nid(of_node));
>
> --
> 1.7.0.4
>
>
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: [PATCH 13/15] ppc/pseries: iommu cleanup
From: Grant Likely @ 2010-09-15 18:34 UTC (permalink / raw)
To: Nishanth Aravamudan
Cc: devicetree-discuss, Milton Miller, Paul Mackerras,
Anton Blanchard, linuxppc-dev
In-Reply-To: <1284573958-8397-14-git-send-email-nacc@us.ibm.com>
On Wed, Sep 15, 2010 at 12:05 PM, Nishanth Aravamudan <nacc@us.ibm.com> wro=
te:
> No need to initialize per-cpu pointer to NULL, it is the default.
>
> Direct dma ops and no setup are the defaults, no need to set for
> iommu-off.
>
> Signed-off-by: Milton Miller <miltonm@bga.com>
> Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
Also looks correct.
Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
g.
> ---
> =A0arch/powerpc/platforms/pseries/iommu.c | =A0 =A09 ++-------
> =A01 files changed, 2 insertions(+), 7 deletions(-)
>
> diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platfo=
rms/pseries/iommu.c
> index a77bcae..9184db3 100644
> --- a/arch/powerpc/platforms/pseries/iommu.c
> +++ b/arch/powerpc/platforms/pseries/iommu.c
> @@ -140,7 +140,7 @@ static int tce_build_pSeriesLP(struct iommu_table *tb=
l, long tcenum,
> =A0 =A0 =A0 =A0return ret;
> =A0}
>
> -static DEFINE_PER_CPU(u64 *, tce_page) =3D NULL;
> +static DEFINE_PER_CPU(u64 *, tce_page);
>
> =A0static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcen=
um,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 l=
ong npages, unsigned long uaddr,
> @@ -589,13 +589,8 @@ static struct notifier_block iommu_reconfig_nb =3D {
> =A0/* These are called very early. */
> =A0void iommu_init_early_pSeries(void)
> =A0{
> - =A0 =A0 =A0 if (of_chosen && of_get_property(of_chosen, "linux,iommu-of=
f", NULL)) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Direct I/O, IOMMU off */
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 ppc_md.pci_dma_dev_setup =3D NULL;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 ppc_md.pci_dma_bus_setup =3D NULL;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 set_pci_dma_ops(&dma_direct_ops);
> + =A0 =A0 =A0 if (of_chosen && of_get_property(of_chosen, "linux,iommu-of=
f", NULL))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return;
> - =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0if (firmware_has_feature(FW_FEATURE_LPAR)) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (firmware_has_feature(FW_FEATURE_MULTIT=
CE)) {
> --
> 1.7.0.4
>
>
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: [PATCH 15/15] ppc/vio: ensure dma_coherent_mask is set
From: Grant Likely @ 2010-09-15 18:37 UTC (permalink / raw)
To: Nishanth Aravamudan
Cc: Brian King, Paul Mackerras, linuxppc-dev, Milton Miller
In-Reply-To: <1284573958-8397-16-git-send-email-nacc@us.ibm.com>
On Wed, Sep 15, 2010 at 12:05 PM, Nishanth Aravamudan <nacc@us.ibm.com> wro=
te:
> Without this change drivers, such as ibmvscsi, fail to load with the
> previous change.
Shouldn't this patch be ordered before the previous change then to
preserve bisectability?
Also, patch descriptions should be explicit about what the "previous
change" refers to. Once this is committed, git log may very well
insert other changes from other branches between this commit and
whatever "previous change" refers to.
g.
> ---
> =A0arch/powerpc/kernel/vio.c | =A0 =A03 +++
> =A01 files changed, 3 insertions(+), 0 deletions(-)
>
> diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
> index 3c3083f..e8d73de 100644
> --- a/arch/powerpc/kernel/vio.c
> +++ b/arch/powerpc/kernel/vio.c
> @@ -1259,6 +1259,9 @@ struct vio_dev *vio_register_device_node(struct dev=
ice_node *of_node)
> =A0 =A0 =A0 =A0viodev->dev.parent =3D &vio_bus_device.dev;
> =A0 =A0 =A0 =A0viodev->dev.bus =3D &vio_bus_type;
> =A0 =A0 =A0 =A0viodev->dev.release =3D vio_dev_release;
> + =A0 =A0 =A0 =A0/* needed to ensure proper operation of coherent allocat=
ions
> + =A0 =A0 =A0 =A0 * later, in case driver doesn't set it explicitly */
> + =A0 =A0 =A0 =A0dma_set_coherent_mask(&viodev->dev, DMA_BIT_MASK(64));
>
> =A0 =A0 =A0 =A0/* register with generic device framework */
> =A0 =A0 =A0 =A0if (device_register(&viodev->dev)) {
> --
> 1.7.0.4
>
>
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: Question on of_address_to_resource() with offset != 0
From: Grant Likely @ 2010-09-15 18:43 UTC (permalink / raw)
To: Stefan Roese; +Cc: devicetree-discuss, linuxppc-dev, Detlev Zundel
In-Reply-To: <201009151459.43087.sr@denx.de>
On Wed, Sep 15, 2010 at 02:59:42PM +0200, Stefan Roese wrote:
> On Tuesday 14 September 2010 16:29:06 Stefan Roese wrote:
> > I'm stumbling upon a problem noticed on the Ebony (440GP) eval board.
> > Here the first chip-select is connected to 512KiB of SRAM and 512KiB
> > NOR flash.
>
> "Brown paper bag" time for me. Problem was located in U-Boot. Sorry for the
> noise.
:-)
g.
^ permalink raw reply
* Re: [PATCH 15/15] ppc/vio: ensure dma_coherent_mask is set
From: Nishanth Aravamudan @ 2010-09-15 18:44 UTC (permalink / raw)
To: Grant Likely; +Cc: Brian King, Paul Mackerras, linuxppc-dev, Milton Miller
In-Reply-To: <AANLkTi=K+KudbVAqZGA9fXXWq-vXirh9SuSTEHSh=kgC@mail.gmail.com>
On 15.09.2010 [12:37:58 -0600], Grant Likely wrote:
> On Wed, Sep 15, 2010 at 12:05 PM, Nishanth Aravamudan <nacc@us.ibm.com> wrote:
> > Without this change drivers, such as ibmvscsi, fail to load with the
> > previous change.
>
> Shouldn't this patch be ordered before the previous change then to
> preserve bisectability?
You are probably right. I wasn't sure if I should fold it in or keep it
separate. I should have changed the order, though. Sorry about that!
> Also, patch descriptions should be explicit about what the "previous
> change" refers to. Once this is committed, git log may very well
> insert other changes from other branches between this commit and
> whatever "previous change" refers to.
Yep -- what's the best way to make the reference? By subject from the
patch? Obviously I don't have the SHA1 with which the commit will go
upstream.
Thanks,
Nish
--
Nishanth Aravamudan <nacc@us.ibm.com>
IBM Linux Technology Center
^ permalink raw reply
* Re: [PATCH 15/15] ppc/vio: ensure dma_coherent_mask is set
From: Grant Likely @ 2010-09-15 18:49 UTC (permalink / raw)
To: Nishanth Aravamudan
Cc: Brian King, Paul Mackerras, linuxppc-dev, Milton Miller
In-Reply-To: <20100915184456.GC3683@us.ibm.com>
On Wed, Sep 15, 2010 at 11:44:56AM -0700, Nishanth Aravamudan wrote:
> On 15.09.2010 [12:37:58 -0600], Grant Likely wrote:
> > On Wed, Sep 15, 2010 at 12:05 PM, Nishanth Aravamudan <nacc@us.ibm.com> wrote:
> > > Without this change drivers, such as ibmvscsi, fail to load with the
> > > previous change.
> >
> > Shouldn't this patch be ordered before the previous change then to
> > preserve bisectability?
>
> You are probably right. I wasn't sure if I should fold it in or keep it
> separate. I should have changed the order, though. Sorry about that!
It's such a small patch I would just fold it in.
>
> > Also, patch descriptions should be explicit about what the "previous
> > change" refers to. Once this is committed, git log may very well
> > insert other changes from other branches between this commit and
> > whatever "previous change" refers to.
>
> Yep -- what's the best way to make the reference? By subject from the
> patch? Obviously I don't have the SHA1 with which the commit will go
> upstream.
By name should be good. As long as a reader doesn't need background
information from your head to figure out why the change was made then
it should be okay.
g.
^ permalink raw reply
* RE: [PATCH v2 09/10] RapidIO: Add support for IDT CPS Gen2 switches
From: Bounine, Alexandre @ 2010-09-15 18:52 UTC (permalink / raw)
To: Anderson, Trevor, Andrew Morton; +Cc: linuxppc-dev, linux-kernel, Thomas Moll
In-Reply-To: <1682399277683944B902B3657D2FCE216544F4A1F0@CAREXCLUSTER03.ATL.CW.LOCAL>
Anderson, Trevor <tanderson@curtisswright.com> wrote:
>=20
> Keep it in please. We lurkers in the embedded community do use the
per-port routing tables.
> One of the problems with SRIO switch tables is that access to routes
is not atomic; we can use
> restricted access to per-port routing tables to reduce the risk of
interference. And we still use
> the Global table during enumeration.
>=20
Will it help if I add sysfs attribute(s) to handle per-port routes?
^ permalink raw reply
* RE: [PATCH v2 09/10] RapidIO: Add support for IDT CPS Gen2 switches
From: Anderson, Trevor @ 2010-09-15 19:13 UTC (permalink / raw)
To: Bounine, Alexandre, Andrew Morton
Cc: linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org,
Thomas Moll
In-Reply-To: <0CE8B6BE3C4AD74AB97D9D29BD24E5520130332B@CORPEXCH1.na.ads.idt.com>
> -----Original Message-----
> From: Bounine, Alexandre [mailto:Alexandre.Bounine@idt.com]
> Sent: Wednesday, September 15, 2010 11:53 AM
> To: Anderson, Trevor; Andrew Morton
> Cc: linux-kernel@vger.kernel.org; Thomas Moll; linuxppc-dev@lists.ozlabs=
.org
> Subject: RE: [PATCH v2 09/10] RapidIO: Add support for IDT CPS Gen2 swit=
ches
>
> Anderson, Trevor <tanderson@curtisswright.com> wrote:
> >
> > Keep it in please. We lurkers in the embedded community do use the
> per-port routing tables.
> > One of the problems with SRIO switch tables is that access to routes
> is not atomic; we can use
> > restricted access to per-port routing tables to reduce the risk of
> interference. And we still use
> > the Global table during enumeration.
> >
> Will it help if I add sysfs attribute(s) to handle per-port routes?
I don't think so - not from my perspective, at least. All of our routes
are programmed using the broadcast table; but we use the private tables
as a safer method of reading the routes that have been programmed, when we=
need to know that.
_______________________________________________________________________
This e-mail and any files transmitted with it are proprietary and intended=
solely for the use of the individual or entity to whom they are addressed=
. If you have reason to believe that you have received this e-mail in erro=
r, please notify the sender and destroy this email and any attached files.=
Please note that any views or opinions presented in this e-mail are solel=
y those of the author and do not necessarily represent those of the Curtis=
s-Wright Corporation or any of its subsidiaries. Documents attached heret=
o may contain technology subject to government export regulations. Recipie=
nt is solely responsible for ensuring that any re-export, transfer or disc=
losure of this information is in accordance with applicable government exp=
ort regulations. The recipient should check this e-mail and any attachmen=
ts for the presence of viruses. Curtiss-Wright Corporation and its subsidi=
aries accept no liability for any damage caused by any virus transmitted b=
y this e-mail.
^ permalink raw reply
* RE: [PATCH v2 03/10] RapidIO: Use stored ingress port number instead of register read
From: Bounine, Alexandre @ 2010-09-15 19:28 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel, Thomas Moll, linuxppc-dev
In-Reply-To: <20100914151219.5d92c6f9.akpm@linux-foundation.org>
Andrew Morton <akpm@linux-foundation.org> wrote:
=20
> What is the locking for rdev? In other patches I see pointer chases
> with no obvious locking against concurrent changes?
This rdev should be safe because it is intended for use only by
rio_switch
attached to the same rdev. Therefore rio_global_list_lock will work
here.
I will check for safe locking in all my patches - this set and earlier.
^ permalink raw reply
* [PATCH -v4] memblock: Fix section mismatch warnings
From: Yinghai Lu @ 2010-09-15 20:05 UTC (permalink / raw)
To: Ingo Molnar, Stephen Rothwell
Cc: Peter Zijlstra, linux-kernel, linux-next, H. Peter Anvin,
Thomas Gleixner, ppc-dev
In-Reply-To: <20100915092532.GH16593@elte.hu>
Stephen found bunch of section mismatch warnings with memblock new changes.
Use __init_memblock to replace __init in memblock.c and remove __init in memblock.h.
We should not use __init in header files.
Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
Tested-by: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Yinghai Lu <Yinghai@kernel.org>
---
include/linux/memblock.h | 24 ++++++++++++------------
mm/memblock.c | 14 +++++++-------
2 files changed, 19 insertions(+), 19 deletions(-)
Index: linux-2.6/mm/memblock.c
===================================================================
--- linux-2.6.orig/mm/memblock.c
+++ linux-2.6/mm/memblock.c
@@ -125,8 +125,8 @@ static phys_addr_t __init memblock_find_
return MEMBLOCK_ERROR;
}
-static phys_addr_t __init memblock_find_base(phys_addr_t size, phys_addr_t align,
- phys_addr_t start, phys_addr_t end)
+static phys_addr_t __init_memblock memblock_find_base(phys_addr_t size,
+ phys_addr_t align, phys_addr_t start, phys_addr_t end)
{
long i;
@@ -439,12 +439,12 @@ long __init_memblock memblock_remove(phy
return __memblock_remove(&memblock.memory, base, size);
}
-long __init memblock_free(phys_addr_t base, phys_addr_t size)
+long __init_memblock memblock_free(phys_addr_t base, phys_addr_t size)
{
return __memblock_remove(&memblock.reserved, base, size);
}
-long __init memblock_reserve(phys_addr_t base, phys_addr_t size)
+long __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size)
{
struct memblock_type *_rgn = &memblock.reserved;
@@ -671,12 +671,12 @@ int __init memblock_is_reserved(phys_add
return memblock_search(&memblock.reserved, addr) != -1;
}
-int memblock_is_memory(phys_addr_t addr)
+int __init_memblock memblock_is_memory(phys_addr_t addr)
{
return memblock_search(&memblock.memory, addr) != -1;
}
-int memblock_is_region_memory(phys_addr_t base, phys_addr_t size)
+int __init_memblock memblock_is_region_memory(phys_addr_t base, phys_addr_t size)
{
int idx = memblock_search(&memblock.reserved, base);
@@ -693,7 +693,7 @@ int __init_memblock memblock_is_region_r
}
-void __init memblock_set_current_limit(phys_addr_t limit)
+void __init_memblock memblock_set_current_limit(phys_addr_t limit)
{
memblock.current_limit = limit;
}
Index: linux-2.6/include/linux/memblock.h
===================================================================
--- linux-2.6.orig/include/linux/memblock.h
+++ linux-2.6/include/linux/memblock.h
@@ -51,39 +51,39 @@ u64 memblock_find_in_range(u64 start, u6
int memblock_free_reserved_regions(void);
int memblock_reserve_reserved_regions(void);
-extern void __init memblock_init(void);
-extern void __init memblock_analyze(void);
+extern void memblock_init(void);
+extern void memblock_analyze(void);
extern long memblock_add(phys_addr_t base, phys_addr_t size);
extern long memblock_remove(phys_addr_t base, phys_addr_t size);
-extern long __init memblock_free(phys_addr_t base, phys_addr_t size);
-extern long __init memblock_reserve(phys_addr_t base, phys_addr_t size);
+extern long memblock_free(phys_addr_t base, phys_addr_t size);
+extern long memblock_reserve(phys_addr_t base, phys_addr_t size);
/* The numa aware allocator is only available if
* CONFIG_ARCH_POPULATES_NODE_MAP is set
*/
-extern phys_addr_t __init memblock_alloc_nid(phys_addr_t size, phys_addr_t align,
+extern phys_addr_t memblock_alloc_nid(phys_addr_t size, phys_addr_t align,
int nid);
-extern phys_addr_t __init memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align,
+extern phys_addr_t memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align,
int nid);
-extern phys_addr_t __init memblock_alloc(phys_addr_t size, phys_addr_t align);
+extern phys_addr_t memblock_alloc(phys_addr_t size, phys_addr_t align);
/* Flags for memblock_alloc_base() amd __memblock_alloc_base() */
#define MEMBLOCK_ALLOC_ANYWHERE (~(phys_addr_t)0)
#define MEMBLOCK_ALLOC_ACCESSIBLE 0
-extern phys_addr_t __init memblock_alloc_base(phys_addr_t size,
+extern phys_addr_t memblock_alloc_base(phys_addr_t size,
phys_addr_t align,
phys_addr_t max_addr);
-extern phys_addr_t __init __memblock_alloc_base(phys_addr_t size,
+extern phys_addr_t __memblock_alloc_base(phys_addr_t size,
phys_addr_t align,
phys_addr_t max_addr);
-extern phys_addr_t __init memblock_phys_mem_size(void);
+extern phys_addr_t memblock_phys_mem_size(void);
extern phys_addr_t memblock_end_of_DRAM(void);
-extern void __init memblock_enforce_memory_limit(phys_addr_t memory_limit);
+extern void memblock_enforce_memory_limit(phys_addr_t memory_limit);
extern int memblock_is_memory(phys_addr_t addr);
extern int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
-extern int __init memblock_is_reserved(phys_addr_t addr);
+extern int memblock_is_reserved(phys_addr_t addr);
extern int memblock_is_region_reserved(phys_addr_t base, phys_addr_t size);
extern void memblock_dump_all(void);
^ permalink raw reply
* [PATCH] powerpc/5121: pdm360ng: fix touch irq if 8xxx gpio driver is enabled
From: Anatolij Gustschin @ 2010-09-15 20:12 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Anatolij Gustschin
Enabling the MPC8xxx GPIO driver with MPC512x GPIO extension
breaks touch screen support on this board since the GPIO
interrupt will be mapped to 8xxx GPIO irq host resulting in
a not requestable interrupt in the touch screen driver. Fix
it by mapping the touch interrupt on 8xxx GPIO irq host.
Signed-off-by: Anatolij Gustschin <agust@denx.de>
---
arch/powerpc/platforms/512x/pdm360ng.c | 26 ++++++++++++++++++++++----
1 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/platforms/512x/pdm360ng.c b/arch/powerpc/platforms/512x/pdm360ng.c
index 0575e85..558eb9e 100644
--- a/arch/powerpc/platforms/512x/pdm360ng.c
+++ b/arch/powerpc/platforms/512x/pdm360ng.c
@@ -27,6 +27,7 @@
#include <linux/spi/ads7846.h>
#include <linux/spi/spi.h>
#include <linux/notifier.h>
+#include <asm/gpio.h>
static void *pdm360ng_gpio_base;
@@ -50,7 +51,7 @@ static struct ads7846_platform_data pdm360ng_ads7846_pdata = {
.irq_flags = IRQF_TRIGGER_LOW,
};
-static int __init pdm360ng_penirq_init(void)
+static int pdm360ng_penirq_init(void)
{
struct device_node *np;
@@ -73,6 +74,9 @@ static int __init pdm360ng_penirq_init(void)
return 0;
}
+#define GPIO_NR(x) (ARCH_NR_GPIOS - 32 + (x))
+#define PENDOWN_GPIO GPIO_NR(25)
+
static int pdm360ng_touchscreen_notifier_call(struct notifier_block *nb,
unsigned long event, void *__dev)
{
@@ -80,7 +84,24 @@ static int pdm360ng_touchscreen_notifier_call(struct notifier_block *nb,
if ((event == BUS_NOTIFY_ADD_DEVICE) &&
of_device_is_compatible(dev->of_node, "ti,ads7846")) {
+ struct spi_device *spi = to_spi_device(dev);
+ int gpio = PENDOWN_GPIO;
+
dev->platform_data = &pdm360ng_ads7846_pdata;
+ if (pdm360ng_penirq_init())
+ return NOTIFY_DONE;
+
+ if (gpio_request_one(gpio, GPIOF_IN, "ads7845_pen_down") < 0) {
+ pr_err("Failed to request GPIO %d for "
+ "ads7845 pen down IRQ\n", gpio);
+ return NOTIFY_DONE;
+ }
+ spi->irq = gpio_to_irq(gpio);
+ if (spi->irq < 0) {
+ pr_err("Can't map GPIO IRQ\n");
+ gpio_free(gpio);
+ return NOTIFY_DONE;
+ }
return NOTIFY_OK;
}
return NOTIFY_DONE;
@@ -92,9 +113,6 @@ static struct notifier_block pdm360ng_touchscreen_nb = {
static void __init pdm360ng_touchscreen_init(void)
{
- if (pdm360ng_penirq_init())
- return;
-
bus_register_notifier(&spi_bus_type, &pdm360ng_touchscreen_nb);
}
#else
--
1.7.0.4
^ permalink raw reply related
* Re: Generating elf kernel ?
From: tiejun.chen @ 2010-09-16 2:37 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev, Guillaume Dargaud
In-Reply-To: <20100915114912.06bc7ed1@schlenkerla.am.freescale.net>
Scott Wood wrote:
> On Wed, 15 Sep 2010 16:27:10 +0800
> "tiejun.chen" <tiejun.chen@windriver.com> wrote:
>
>> It's impossible to boot PPC vmlinux format directly if you only change the
>> original entry point address, 0xc0000000.
>
> Why? That's pretty much what the bootwrapper does. Our hypervisor has
> directly booted vmlinux this way.
Maybe you misunderstand what I mean.
Although you can change entry point of vmlinux
1> can you load the Linux vmlinux directly to the physical address '0' on
current bootloader?
2> additionally you have to find a way to pass dtb to the native vmlinux.
I believe the hypervisor can boot vmlinux directly. But your so-called vmlinux
should be guest OS. And the hypervisor will handle/assit TLB exception for the
guest OS on MMU. Right? So you can use the hypervisor to load vmlinux to any
physical address as you expect. But the guest OS should not be same as the
native Linux.
>
> Note that in recent kernels physaddr is even set to zero, allowing the
> ELF loader to just use that instead of magically knowing the kernel
> wants to go at address zero.
Sure.
>
>> For kernel the following is as default:
>> v:0xc0000000 --> p:0x0
>
> That mapping is set up by code at the entry point of vmlinux, not by
> the bootwrapper.
Absolutely.
Tiejun
>
> -Scott
>
>
^ permalink raw reply
* Re: [PATCH] powerpc/5121: pdm360ng: fix touch irq if 8xxx gpio driver is enabled
From: Grant Likely @ 2010-09-16 2:38 UTC (permalink / raw)
To: Anatolij Gustschin; +Cc: linuxppc-dev
In-Reply-To: <1284581577-2217-1-git-send-email-agust@denx.de>
On Wed, Sep 15, 2010 at 10:12:57PM +0200, Anatolij Gustschin wrote:
> Enabling the MPC8xxx GPIO driver with MPC512x GPIO extension
> breaks touch screen support on this board since the GPIO
> interrupt will be mapped to 8xxx GPIO irq host resulting in
> a not requestable interrupt in the touch screen driver. Fix
> it by mapping the touch interrupt on 8xxx GPIO irq host.
This looks wrong to me. The touchscreen code should not go mucking
about in the GPIO controller registers; that is the job of the gpio
driver. What is the reason that the touch interrupt isn't
requestable? It looks like the 8xxx gpio driver is designed to hand
out a separate virq number for each gpio pin (I've not had time to dig
into details, so you'll need to educate me on the problem details)
g.
>
> Signed-off-by: Anatolij Gustschin <agust@denx.de>
> ---
> arch/powerpc/platforms/512x/pdm360ng.c | 26 ++++++++++++++++++++++----
> 1 files changed, 22 insertions(+), 4 deletions(-)
>
> diff --git a/arch/powerpc/platforms/512x/pdm360ng.c b/arch/powerpc/platforms/512x/pdm360ng.c
> index 0575e85..558eb9e 100644
> --- a/arch/powerpc/platforms/512x/pdm360ng.c
> +++ b/arch/powerpc/platforms/512x/pdm360ng.c
> @@ -27,6 +27,7 @@
> #include <linux/spi/ads7846.h>
> #include <linux/spi/spi.h>
> #include <linux/notifier.h>
> +#include <asm/gpio.h>
>
> static void *pdm360ng_gpio_base;
>
> @@ -50,7 +51,7 @@ static struct ads7846_platform_data pdm360ng_ads7846_pdata = {
> .irq_flags = IRQF_TRIGGER_LOW,
> };
>
> -static int __init pdm360ng_penirq_init(void)
> +static int pdm360ng_penirq_init(void)
> {
> struct device_node *np;
>
> @@ -73,6 +74,9 @@ static int __init pdm360ng_penirq_init(void)
> return 0;
> }
>
> +#define GPIO_NR(x) (ARCH_NR_GPIOS - 32 + (x))
> +#define PENDOWN_GPIO GPIO_NR(25)
> +
> static int pdm360ng_touchscreen_notifier_call(struct notifier_block *nb,
> unsigned long event, void *__dev)
> {
> @@ -80,7 +84,24 @@ static int pdm360ng_touchscreen_notifier_call(struct notifier_block *nb,
>
> if ((event == BUS_NOTIFY_ADD_DEVICE) &&
> of_device_is_compatible(dev->of_node, "ti,ads7846")) {
> + struct spi_device *spi = to_spi_device(dev);
> + int gpio = PENDOWN_GPIO;
> +
> dev->platform_data = &pdm360ng_ads7846_pdata;
> + if (pdm360ng_penirq_init())
> + return NOTIFY_DONE;
> +
> + if (gpio_request_one(gpio, GPIOF_IN, "ads7845_pen_down") < 0) {
> + pr_err("Failed to request GPIO %d for "
> + "ads7845 pen down IRQ\n", gpio);
> + return NOTIFY_DONE;
> + }
> + spi->irq = gpio_to_irq(gpio);
> + if (spi->irq < 0) {
> + pr_err("Can't map GPIO IRQ\n");
> + gpio_free(gpio);
> + return NOTIFY_DONE;
> + }
> return NOTIFY_OK;
> }
> return NOTIFY_DONE;
> @@ -92,9 +113,6 @@ static struct notifier_block pdm360ng_touchscreen_nb = {
>
> static void __init pdm360ng_touchscreen_init(void)
> {
> - if (pdm360ng_penirq_init())
> - return;
> -
> bus_register_notifier(&spi_bus_type, &pdm360ng_touchscreen_nb);
> }
> #else
> --
> 1.7.0.4
>
^ permalink raw reply
* Re: Generating elf kernel ?
From: tiejun.chen @ 2010-09-16 3:02 UTC (permalink / raw)
To: Guillaume Dargaud; +Cc: linuxppc-dev
In-Reply-To: <201009151651.06816.dargaud@lpsc.in2p3.fr>
Guillaume Dargaud wrote:
>> Please use simpleImage.<your target dts name>.elf.
>
> Great, that seems to be it...
> Except that nothing happens when I jump to 0x40000, no message from the
0x40000? I recalled the entry point should be 0x400000 for simepleImage.*.elf.
So you have to change this on the file, arch/powerpc/boot/wrapper.
And also you should confirm if the upstream kernel support your board.
Additionally let's assume your bootloader create the map between the virtual
address and the physical address as 1:1. If so you want to execute from 0x40000.
But the actual PC address should be the loader address + offset. You can get
this by readelf. Here if your loader address is zero, the offset will be pc
address, not 0x40000. You can dump your memory to check this.
Cheers
Tiejun
> kernel, nothing.
> I'm a bit stumped here as my old kernel worked fine.
^ permalink raw reply
* Reserved pages in PowerPC
From: Ankita Garg @ 2010-09-16 5:23 UTC (permalink / raw)
To: linuxppc-dev, linux-mm
Hi,
I am trying to hotplug/offline sections of memory on a Power machine.
I boot the kernel with kernelcore=1G commandline parameter. I see that except
for 512MB, the rest of the memory is movable. When trying to do hot-remove, I
notice that I am unable to remove the very last section of memory, one with
the highest physical address. It is always marked as non-movable.
With some debugging I found that that section has reserved pages. On
instrumenting the memblock_reserve() and reserve_bootmem() routines, I can see
that many of the memory areas are reserved for kernel and initrd by the
memblock reserve() itself. reserve_bootmem then looks at the pages already
reserved and marks them reserved. However, for the very last section, I see
that bootmem reserves it but I am unable to find a corresponding reservation
by the memblock code.
memblock_reserve: start 0 size 3519
reserve_bootmem 0 dbf000 nid=0
memblock_reserve: start 12096 size 15372
reserve_bootmem 2f40000 ccc000 nid=0
memblock_reserve: start 15628 size 15650
reserve_bootmem 3d0c000 16000 nid=0
...
...
memblock_reserve: start 1982455 size 1982464
reserve_bootmem 1e3ff7c00 8400 nid=0
reserve_bootmem 3d7f64000 3f000 nid=1
reserve_bootmem 3d7fa3c00 48400 nid=1
reserve_bootmem 3d7feeda8 11258 nid=1
..
Is it a known behavior on Power ? If yes, for what purpose is the memory
in the higher address reserved for ? I have seen that even if the system
has multiple nodes, only the very last section of the last node is not
removable.
--
Regards,
Ankita Garg (ankita@in.ibm.com)
Linux Technology Center
IBM India Systems & Technology Labs,
Bangalore, India
^ permalink raw reply
* cuImage and multi image?
From: Shawn Jin @ 2010-09-16 6:21 UTC (permalink / raw)
To: ppcdev, uboot
Hi,
I have a cuImage kernel in order to support legacy u-boot and a
ramdisk image. Kernel boots fine if these two images are separate and
"bootm $kernel $ramdisk" is used. But I can not make it to work using
a single multi image that contains the kernel and ramdisk images. Is
it even technically possible to boot a multi-image with cuboot
wrapper?
On the cuImage kernel I have load address set to 0x400000 and the
entry address set to 0x400554 due to the cuboot wrapper. But to make a
multi image, both the load and the entry addresses should be set to
zero. And u-boot (1.1.2) bootm takes the entry address of the multi
image (i.e. 0x0) as the kernel entry address. 0x0 is certainly not the
entry address for a cuImage kernel.
Is there a possible workaround other than using two separate images?
Thanks,
-Shawn.
^ permalink raw reply
* [PATCH 2/3 v3] P4080/mtd: Only make elbc nand driver detect nand flash partitions
From: Roy Zang @ 2010-09-16 6:41 UTC (permalink / raw)
To: linux-mtd; +Cc: B07421, dedekind1, B25806, linuxppc-dev, akpm, dwmw2, B11780
In-Reply-To: <1284619284-23614-1-git-send-email-tie-fei.zang@freescale.com>
From: Jack Lan <jack.lan@freescale.com>
The former driver had the two functions:
1. detecting nand flash partitions;
2. registering elbc interrupt.
Now, second function is removed to fsl_lbc.c.
Signed-off-by: Lan Chunhe-B25806 <b25806@freescale.com>
Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
---
drivers/mtd/nand/Kconfig | 1 +
drivers/mtd/nand/fsl_elbc_nand.c | 474 +++++++++++++++-----------------------
2 files changed, 190 insertions(+), 285 deletions(-)
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 8b4b67c..4132c46 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -458,6 +458,7 @@ config MTD_NAND_ORION
config MTD_NAND_FSL_ELBC
tristate "NAND support for Freescale eLBC controllers"
depends on PPC_OF
+ select FSL_LBC
help
Various Freescale chips, including the 8313, include a NAND Flash
Controller Module with built-in hardware ECC capabilities.
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 80de0bf..91c5c05 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -1,9 +1,10 @@
/* Freescale Enhanced Local Bus Controller NAND driver
*
- * Copyright (c) 2006-2007 Freescale Semiconductor
+ * Copyright (c) 2006-2007, 2010 Freescale Semiconductor
*
* Authors: Nick Spence <nick.spence@freescale.com>,
* Scott Wood <scottwood@freescale.com>
+ * Jack Lan <jack.lan@freescale.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -27,6 +28,7 @@
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/of_platform.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
@@ -42,14 +44,12 @@
#define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */
#define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */
-struct fsl_elbc_ctrl;
-
/* mtd information per set */
struct fsl_elbc_mtd {
struct mtd_info mtd;
struct nand_chip chip;
- struct fsl_elbc_ctrl *ctrl;
+ struct fsl_lbc_ctrl *ctrl;
struct device *dev;
int bank; /* Chip select bank number */
@@ -58,18 +58,12 @@ struct fsl_elbc_mtd {
unsigned int fmr; /* FCM Flash Mode Register value */
};
-/* overview of the fsl elbc controller */
+/* Freescale eLBC FCM controller infomation */
-struct fsl_elbc_ctrl {
+struct fsl_elbc_fcm_ctrl {
struct nand_hw_control controller;
struct fsl_elbc_mtd *chips[MAX_BANKS];
- /* device info */
- struct device *dev;
- struct fsl_lbc_regs __iomem *regs;
- int irq;
- wait_queue_head_t irq_wait;
- unsigned int irq_status; /* status read from LTESR by irq handler */
u8 __iomem *addr; /* Address of assigned FCM buffer */
unsigned int page; /* Last page written to / read from */
unsigned int read_bytes; /* Number of bytes read during command */
@@ -164,11 +158,12 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_lbc_ctrl *ctrl = priv->ctrl;
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
int buf_num;
- ctrl->page = page_addr;
+ elbc_fcm_ctrl->page = page_addr;
out_be32(&lbc->fbar,
page_addr >> (chip->phys_erase_shift - chip->page_shift));
@@ -185,16 +180,18 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
buf_num = page_addr & 7;
}
- ctrl->addr = priv->vbase + buf_num * 1024;
- ctrl->index = column;
+ elbc_fcm_ctrl->addr = priv->vbase + buf_num * 1024;
+ elbc_fcm_ctrl->index = column;
/* for OOB data point to the second half of the buffer */
if (oob)
- ctrl->index += priv->page_size ? 2048 : 512;
+ elbc_fcm_ctrl->index += priv->page_size ? 2048 : 512;
- dev_vdbg(ctrl->dev, "set_addr: bank=%d, ctrl->addr=0x%p (0x%p), "
+ dev_vdbg(priv->dev, "set_addr: bank=%d, "
+ "elbc_fcm_ctrl->addr=0x%p (0x%p), "
"index %x, pes %d ps %d\n",
- buf_num, ctrl->addr, priv->vbase, ctrl->index,
+ buf_num, elbc_fcm_ctrl->addr, priv->vbase,
+ elbc_fcm_ctrl->index,
chip->phys_erase_shift, chip->page_shift);
}
@@ -205,18 +202,19 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_lbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
/* Setup the FMR[OP] to execute without write protection */
out_be32(&lbc->fmr, priv->fmr | 3);
- if (ctrl->use_mdr)
- out_be32(&lbc->mdr, ctrl->mdr);
+ if (elbc_fcm_ctrl->use_mdr)
+ out_be32(&lbc->mdr, elbc_fcm_ctrl->mdr);
- dev_vdbg(ctrl->dev,
+ dev_vdbg(priv->dev,
"fsl_elbc_run_command: fmr=%08x fir=%08x fcr=%08x\n",
in_be32(&lbc->fmr), in_be32(&lbc->fir), in_be32(&lbc->fcr));
- dev_vdbg(ctrl->dev,
+ dev_vdbg(priv->dev,
"fsl_elbc_run_command: fbar=%08x fpar=%08x "
"fbcr=%08x bank=%d\n",
in_be32(&lbc->fbar), in_be32(&lbc->fpar),
@@ -229,19 +227,18 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
/* wait for FCM complete flag or timeout */
wait_event_timeout(ctrl->irq_wait, ctrl->irq_status,
FCM_TIMEOUT_MSECS * HZ/1000);
- ctrl->status = ctrl->irq_status;
-
+ elbc_fcm_ctrl->status = ctrl->irq_status;
/* store mdr value in case it was needed */
- if (ctrl->use_mdr)
- ctrl->mdr = in_be32(&lbc->mdr);
+ if (elbc_fcm_ctrl->use_mdr)
+ elbc_fcm_ctrl->mdr = in_be32(&lbc->mdr);
- ctrl->use_mdr = 0;
+ elbc_fcm_ctrl->use_mdr = 0;
- if (ctrl->status != LTESR_CC) {
- dev_info(ctrl->dev,
+ if (elbc_fcm_ctrl->status != LTESR_CC) {
+ dev_info(priv->dev,
"command failed: fir %x fcr %x status %x mdr %x\n",
in_be32(&lbc->fir), in_be32(&lbc->fcr),
- ctrl->status, ctrl->mdr);
+ elbc_fcm_ctrl->status, elbc_fcm_ctrl->mdr);
return -EIO;
}
@@ -251,7 +248,7 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
{
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_lbc_ctrl *ctrl = priv->ctrl;
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
if (priv->page_size) {
@@ -284,15 +281,16 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_lbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
- ctrl->use_mdr = 0;
+ elbc_fcm_ctrl->use_mdr = 0;
/* clear the read buffer */
- ctrl->read_bytes = 0;
+ elbc_fcm_ctrl->read_bytes = 0;
if (command != NAND_CMD_PAGEPROG)
- ctrl->index = 0;
+ elbc_fcm_ctrl->index = 0;
switch (command) {
/* READ0 and READ1 read the entire buffer to use hardware ECC. */
@@ -301,7 +299,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* fall-through */
case NAND_CMD_READ0:
- dev_dbg(ctrl->dev,
+ dev_dbg(priv->dev,
"fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:"
" 0x%x, column: 0x%x.\n", page_addr, column);
@@ -309,8 +307,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
out_be32(&lbc->fbcr, 0); /* read entire page to enable ECC */
set_addr(mtd, 0, page_addr, 0);
- ctrl->read_bytes = mtd->writesize + mtd->oobsize;
- ctrl->index += column;
+ elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+ elbc_fcm_ctrl->index += column;
fsl_elbc_do_read(chip, 0);
fsl_elbc_run_command(mtd);
@@ -318,14 +316,14 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* READOOB reads only the OOB because no ECC is performed. */
case NAND_CMD_READOOB:
- dev_vdbg(ctrl->dev,
+ dev_vdbg(priv->dev,
"fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:"
" 0x%x, column: 0x%x.\n", page_addr, column);
out_be32(&lbc->fbcr, mtd->oobsize - column);
set_addr(mtd, column, page_addr, 1);
- ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+ elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
fsl_elbc_do_read(chip, 1);
fsl_elbc_run_command(mtd);
@@ -333,7 +331,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* READID must read all 5 possible bytes while CEB is active */
case NAND_CMD_READID:
- dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
+ dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) |
(FIR_OP_UA << FIR_OP1_SHIFT) |
@@ -341,9 +339,9 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT);
/* 5 bytes for manuf, device and exts */
out_be32(&lbc->fbcr, 5);
- ctrl->read_bytes = 5;
- ctrl->use_mdr = 1;
- ctrl->mdr = 0;
+ elbc_fcm_ctrl->read_bytes = 5;
+ elbc_fcm_ctrl->use_mdr = 1;
+ elbc_fcm_ctrl->mdr = 0;
set_addr(mtd, 0, 0, 0);
fsl_elbc_run_command(mtd);
@@ -351,7 +349,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* ERASE1 stores the block and page address */
case NAND_CMD_ERASE1:
- dev_vdbg(ctrl->dev,
+ dev_vdbg(priv->dev,
"fsl_elbc_cmdfunc: NAND_CMD_ERASE1, "
"page_addr: 0x%x.\n", page_addr);
set_addr(mtd, 0, page_addr, 0);
@@ -359,7 +357,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* ERASE2 uses the block and page address from ERASE1 */
case NAND_CMD_ERASE2:
- dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
+ dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
out_be32(&lbc->fir,
(FIR_OP_CM0 << FIR_OP0_SHIFT) |
@@ -374,8 +372,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
(NAND_CMD_ERASE2 << FCR_CMD2_SHIFT));
out_be32(&lbc->fbcr, 0);
- ctrl->read_bytes = 0;
- ctrl->use_mdr = 1;
+ elbc_fcm_ctrl->read_bytes = 0;
+ elbc_fcm_ctrl->use_mdr = 1;
fsl_elbc_run_command(mtd);
return;
@@ -383,14 +381,12 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* SEQIN sets up the addr buffer and all registers except the length */
case NAND_CMD_SEQIN: {
__be32 fcr;
- dev_vdbg(ctrl->dev,
- "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, "
+ dev_vdbg(priv->dev,
+ "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, "
"page_addr: 0x%x, column: 0x%x.\n",
page_addr, column);
- ctrl->column = column;
- ctrl->oob = 0;
- ctrl->use_mdr = 1;
+ elbc_fcm_ctrl->use_mdr = 1;
fcr = (NAND_CMD_STATUS << FCR_CMD1_SHIFT) |
(NAND_CMD_SEQIN << FCR_CMD2_SHIFT) |
@@ -420,7 +416,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* OOB area --> READOOB */
column -= mtd->writesize;
fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT;
- ctrl->oob = 1;
+ elbc_fcm_ctrl->oob = 1;
} else {
WARN_ON(column != 0);
/* First 256 bytes --> READ0 */
@@ -429,24 +425,24 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
}
out_be32(&lbc->fcr, fcr);
- set_addr(mtd, column, page_addr, ctrl->oob);
+ set_addr(mtd, column, page_addr, elbc_fcm_ctrl->oob);
return;
}
/* PAGEPROG reuses all of the setup from SEQIN and adds the length */
case NAND_CMD_PAGEPROG: {
int full_page;
- dev_vdbg(ctrl->dev,
+ dev_vdbg(priv->dev,
"fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG "
- "writing %d bytes.\n", ctrl->index);
+ "writing %d bytes.\n", elbc_fcm_ctrl->index);
/* if the write did not start at 0 or is not a full page
* then set the exact length, otherwise use a full page
* write so the HW generates the ECC.
*/
- if (ctrl->oob || ctrl->column != 0 ||
- ctrl->index != mtd->writesize + mtd->oobsize) {
- out_be32(&lbc->fbcr, ctrl->index);
+ if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 ||
+ elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize) {
+ out_be32(&lbc->fbcr, elbc_fcm_ctrl->index);
full_page = 0;
} else {
out_be32(&lbc->fbcr, 0);
@@ -458,21 +454,21 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* Read back the page in order to fill in the ECC for the
* caller. Is this really needed?
*/
- if (full_page && ctrl->oob_poi) {
+ if (full_page && elbc_fcm_ctrl->oob_poi) {
out_be32(&lbc->fbcr, 3);
set_addr(mtd, 6, page_addr, 1);
- ctrl->read_bytes = mtd->writesize + 9;
+ elbc_fcm_ctrl->read_bytes = mtd->writesize + 9;
fsl_elbc_do_read(chip, 1);
fsl_elbc_run_command(mtd);
- memcpy_fromio(ctrl->oob_poi + 6,
- &ctrl->addr[ctrl->index], 3);
- ctrl->index += 3;
+ memcpy_fromio(elbc_fcm_ctrl->oob_poi + 6,
+ &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], 3);
+ elbc_fcm_ctrl->index += 3;
}
- ctrl->oob_poi = NULL;
+ elbc_fcm_ctrl->oob_poi = NULL;
return;
}
@@ -485,26 +481,26 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT);
out_be32(&lbc->fbcr, 1);
set_addr(mtd, 0, 0, 0);
- ctrl->read_bytes = 1;
+ elbc_fcm_ctrl->read_bytes = 1;
fsl_elbc_run_command(mtd);
/* The chip always seems to report that it is
* write-protected, even when it is not.
*/
- setbits8(ctrl->addr, NAND_STATUS_WP);
+ setbits8(elbc_fcm_ctrl->addr, NAND_STATUS_WP);
return;
/* RESET without waiting for the ready line */
case NAND_CMD_RESET:
- dev_dbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n");
+ dev_dbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n");
out_be32(&lbc->fir, FIR_OP_CM0 << FIR_OP0_SHIFT);
out_be32(&lbc->fcr, NAND_CMD_RESET << FCR_CMD0_SHIFT);
fsl_elbc_run_command(mtd);
return;
default:
- dev_err(ctrl->dev,
+ dev_err(priv->dev,
"fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n",
command);
}
@@ -524,24 +520,24 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
unsigned int bufsize = mtd->writesize + mtd->oobsize;
if (len <= 0) {
- dev_err(ctrl->dev, "write_buf of %d bytes", len);
- ctrl->status = 0;
+ dev_err(priv->dev, "write_buf of %d bytes", len);
+ elbc_fcm_ctrl->status = 0;
return;
}
- if ((unsigned int)len > bufsize - ctrl->index) {
- dev_err(ctrl->dev,
+ if ((unsigned int)len > bufsize - elbc_fcm_ctrl->index) {
+ dev_err(priv->dev,
"write_buf beyond end of buffer "
"(%d requested, %u available)\n",
- len, bufsize - ctrl->index);
- len = bufsize - ctrl->index;
+ len, bufsize - elbc_fcm_ctrl->index);
+ len = bufsize - elbc_fcm_ctrl->index;
}
- memcpy_toio(&ctrl->addr[ctrl->index], buf, len);
+ memcpy_toio(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], buf, len);
/*
* This is workaround for the weird elbc hangs during nand write,
* Scott Wood says: "...perhaps difference in how long it takes a
@@ -549,9 +545,9 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
* is causing problems, and sync isn't helping for some reason."
* Reading back the last byte helps though.
*/
- in_8(&ctrl->addr[ctrl->index] + len - 1);
+ in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index] + len - 1);
- ctrl->index += len;
+ elbc_fcm_ctrl->index += len;
}
/*
@@ -562,13 +558,13 @@ static u8 fsl_elbc_read_byte(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
/* If there are still bytes in the FCM, then use the next byte. */
- if (ctrl->index < ctrl->read_bytes)
- return in_8(&ctrl->addr[ctrl->index++]);
+ if (elbc_fcm_ctrl->index < elbc_fcm_ctrl->read_bytes)
+ return in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index++]);
- dev_err(ctrl->dev, "read_byte beyond end of buffer\n");
+ dev_err(priv->dev, "read_byte beyond end of buffer\n");
return ERR_BYTE;
}
@@ -579,18 +575,19 @@ static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
int avail;
if (len < 0)
return;
- avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index);
- memcpy_fromio(buf, &ctrl->addr[ctrl->index], avail);
- ctrl->index += avail;
+ avail = min((unsigned int)len,
+ elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index);
+ memcpy_fromio(buf, &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], avail);
+ elbc_fcm_ctrl->index += avail;
if (len > avail)
- dev_err(ctrl->dev,
+ dev_err(priv->dev,
"read_buf beyond end of buffer "
"(%d requested, %d available)\n",
len, avail);
@@ -603,30 +600,32 @@ static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
int i;
if (len < 0) {
- dev_err(ctrl->dev, "write_buf of %d bytes", len);
+ dev_err(priv->dev, "write_buf of %d bytes", len);
return -EINVAL;
}
- if ((unsigned int)len > ctrl->read_bytes - ctrl->index) {
- dev_err(ctrl->dev,
- "verify_buf beyond end of buffer "
- "(%d requested, %u available)\n",
- len, ctrl->read_bytes - ctrl->index);
+ if ((unsigned int)len >
+ elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index) {
+ dev_err(priv->dev,
+ "verify_buf beyond end of buffer "
+ "(%d requested, %u available)\n",
+ len, elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index);
- ctrl->index = ctrl->read_bytes;
+ elbc_fcm_ctrl->index = elbc_fcm_ctrl->read_bytes;
return -EINVAL;
}
for (i = 0; i < len; i++)
- if (in_8(&ctrl->addr[ctrl->index + i]) != buf[i])
+ if (in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index + i])
+ != buf[i])
break;
- ctrl->index += len;
- return i == len && ctrl->status == LTESR_CC ? 0 : -EIO;
+ elbc_fcm_ctrl->index += len;
+ return i == len && elbc_fcm_ctrl->status == LTESR_CC ? 0 : -EIO;
}
/* This function is called after Program and Erase Operations to
@@ -635,22 +634,22 @@ static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
{
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
- if (ctrl->status != LTESR_CC)
+ if (elbc_fcm_ctrl->status != LTESR_CC)
return NAND_STATUS_FAIL;
/* The chip always seems to report that it is
* write-protected, even when it is not.
*/
- return (ctrl->mdr & 0xff) | NAND_STATUS_WP;
+ return (elbc_fcm_ctrl->mdr & 0xff) | NAND_STATUS_WP;
}
static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_lbc_ctrl *ctrl = priv->ctrl;
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
unsigned int al;
@@ -665,41 +664,41 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
priv->fmr |= (12 << FMR_CWTO_SHIFT) | /* Timeout > 12 ms */
(al << FMR_AL_SHIFT);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->numchips = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n",
chip->numchips);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chipsize = %lld\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->chipsize = %lld\n",
chip->chipsize);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->pagemask = %8x\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->pagemask = %8x\n",
chip->pagemask);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chip_delay = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_delay = %d\n",
chip->chip_delay);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->badblockpos = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->badblockpos = %d\n",
chip->badblockpos);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chip_shift = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_shift = %d\n",
chip->chip_shift);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->page_shift = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->page_shift = %d\n",
chip->page_shift);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n",
chip->phys_erase_shift);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecclayout = %p\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->ecclayout = %p\n",
chip->ecclayout);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.mode = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.mode = %d\n",
chip->ecc.mode);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.steps = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.steps = %d\n",
chip->ecc.steps);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n",
chip->ecc.bytes);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.total = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.total = %d\n",
chip->ecc.total);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.layout = %p\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.layout = %p\n",
chip->ecc.layout);
- dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags);
- dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size);
- dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->erasesize = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags);
+ dev_dbg(priv->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size);
+ dev_dbg(priv->dev, "fsl_elbc_init: mtd->erasesize = %d\n",
mtd->erasesize);
- dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->writesize = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: mtd->writesize = %d\n",
mtd->writesize);
- dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->oobsize = %d\n",
+ dev_dbg(priv->dev, "fsl_elbc_init: mtd->oobsize = %d\n",
mtd->oobsize);
/* adjust Option Register and ECC to match Flash page size */
@@ -719,7 +718,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
chip->badblock_pattern = &largepage_memorybased;
}
} else {
- dev_err(ctrl->dev,
+ dev_err(priv->dev,
"fsl_elbc_init: page size %d is not supported\n",
mtd->writesize);
return -1;
@@ -750,18 +749,19 @@ static void fsl_elbc_write_page(struct mtd_info *mtd,
const uint8_t *buf)
{
struct fsl_elbc_mtd *priv = chip->priv;
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
fsl_elbc_write_buf(mtd, buf, mtd->writesize);
fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
- ctrl->oob_poi = chip->oob_poi;
+ elbc_fcm_ctrl->oob_poi = chip->oob_poi;
}
static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
{
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ struct fsl_lbc_ctrl *ctrl = priv->ctrl;
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
struct nand_chip *chip = &priv->chip;
dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank);
@@ -790,7 +790,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR |
NAND_USE_FLASH_BBT;
- chip->controller = &ctrl->controller;
+ chip->controller = &elbc_fcm_ctrl->controller;
chip->priv = priv;
chip->ecc.read_page = fsl_elbc_read_page;
@@ -815,8 +815,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
{
- struct fsl_elbc_ctrl *ctrl = priv->ctrl;
-
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
nand_release(&priv->mtd);
kfree(priv->mtd.name);
@@ -824,18 +823,22 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
if (priv->vbase)
iounmap(priv->vbase);
- ctrl->chips[priv->bank] = NULL;
+ elbc_fcm_ctrl->chips[priv->bank] = NULL;
kfree(priv);
-
+ kfree(elbc_fcm_ctrl);
return 0;
}
-static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
- struct device_node *node)
+/*
+ * Currently only one elbc probe is supported.
+ */
+static int __devinit fsl_elbc_nand_probe(struct platform_device *dev)
{
- struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_lbc_regs __iomem *lbc;
struct fsl_elbc_mtd *priv;
struct resource res;
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = NULL;
+
#ifdef CONFIG_MTD_PARTITIONS
static const char *part_probe_types[]
= { "cmdlinepart", "RedBoot", NULL };
@@ -843,11 +846,16 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
#endif
int ret;
int bank;
+ struct device_node *node = dev->dev.of_node;
+
+ if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
+ return -ENODEV;
+ lbc = fsl_lbc_ctrl_dev->regs;
/* get, allocate and map the memory resource */
ret = of_address_to_resource(node, 0, &res);
if (ret) {
- dev_err(ctrl->dev, "failed to get resource\n");
+ dev_err(fsl_lbc_ctrl_dev->dev, "failed to get resource\n");
return ret;
}
@@ -861,7 +869,8 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
break;
if (bank >= MAX_BANKS) {
- dev_err(ctrl->dev, "address did not match any chip selects\n");
+ dev_err(fsl_lbc_ctrl_dev->dev, "address did not match any "
+ "chip selects\n");
return -ENODEV;
}
@@ -869,14 +878,32 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
if (!priv)
return -ENOMEM;
- ctrl->chips[bank] = priv;
+ if (fsl_lbc_ctrl_dev->nand == NULL) {
+ elbc_fcm_ctrl = kzalloc(sizeof(*elbc_fcm_ctrl), GFP_KERNEL);
+ if (!elbc_fcm_ctrl) {
+ dev_err(fsl_lbc_ctrl_dev->dev, "failed to allocate "
+ "memory\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ elbc_fcm_ctrl->read_bytes = 0;
+ elbc_fcm_ctrl->index = 0;
+ elbc_fcm_ctrl->addr = NULL;
+
+ spin_lock_init(&elbc_fcm_ctrl->controller.lock);
+ init_waitqueue_head(&elbc_fcm_ctrl->controller.wq);
+ fsl_lbc_ctrl_dev->nand = elbc_fcm_ctrl;
+ }
+
+ elbc_fcm_ctrl->chips[bank] = priv;
priv->bank = bank;
- priv->ctrl = ctrl;
- priv->dev = ctrl->dev;
+ priv->ctrl = fsl_lbc_ctrl_dev;
+ priv->dev = fsl_lbc_ctrl_dev->dev;
priv->vbase = ioremap(res.start, resource_size(&res));
if (!priv->vbase) {
- dev_err(ctrl->dev, "failed to map chip region\n");
+ dev_err(fsl_lbc_ctrl_dev->dev, "failed to map chip region\n");
ret = -ENOMEM;
goto err;
}
@@ -933,171 +960,48 @@ err:
return ret;
}
-static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl)
+static int fsl_elbc_nand_remove(struct platform_device *dev)
{
- struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
-
- /*
- * NAND transactions can tie up the bus for a long time, so set the
- * bus timeout to max by clearing LBCR[BMT] (highest base counter
- * value) and setting LBCR[BMTPS] to the highest prescaler value.
- */
- clrsetbits_be32(&lbc->lbcr, LBCR_BMT, 15);
-
- /* clear event registers */
- setbits32(&lbc->ltesr, LTESR_NAND_MASK);
- out_be32(&lbc->lteatr, 0);
-
- /* Enable interrupts for any detected events */
- out_be32(&lbc->lteir, LTESR_NAND_MASK);
-
- ctrl->read_bytes = 0;
- ctrl->index = 0;
- ctrl->addr = NULL;
-
- return 0;
-}
-
-static int fsl_elbc_ctrl_remove(struct platform_device *ofdev)
-{
- struct fsl_elbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev);
int i;
-
+ struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand;
for (i = 0; i < MAX_BANKS; i++)
- if (ctrl->chips[i])
- fsl_elbc_chip_remove(ctrl->chips[i]);
-
- if (ctrl->irq)
- free_irq(ctrl->irq, ctrl);
+ if (elbc_fcm_ctrl->chips[i])
+ fsl_elbc_chip_remove(elbc_fcm_ctrl->chips[i]);
- if (ctrl->regs)
- iounmap(ctrl->regs);
+ fsl_lbc_ctrl_dev->nand = NULL;
+ kfree(elbc_fcm_ctrl);
- dev_set_drvdata(&ofdev->dev, NULL);
- kfree(ctrl);
return 0;
-}
-
-/* NOTE: This interrupt is also used to report other localbus events,
- * such as transaction errors on other chipselects. If we want to
- * capture those, we'll need to move the IRQ code into a shared
- * LBC driver.
- */
-static irqreturn_t fsl_elbc_ctrl_irq(int irqno, void *data)
-{
- struct fsl_elbc_ctrl *ctrl = data;
- struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
- __be32 status = in_be32(&lbc->ltesr) & LTESR_NAND_MASK;
-
- if (status) {
- out_be32(&lbc->ltesr, status);
- out_be32(&lbc->lteatr, 0);
-
- ctrl->irq_status = status;
- smp_wmb();
- wake_up(&ctrl->irq_wait);
-
- return IRQ_HANDLED;
- }
-
- return IRQ_NONE;
}
-/* fsl_elbc_ctrl_probe
- *
- * called by device layer when it finds a device matching
- * one our driver can handled. This code allocates all of
- * the resources needed for the controller only. The
- * resources for the NAND banks themselves are allocated
- * in the chip probe function.
-*/
-
-static int __devinit fsl_elbc_ctrl_probe(struct platform_device *ofdev,
- const struct of_device_id *match)
-{
- struct device_node *child;
- struct fsl_elbc_ctrl *ctrl;
- int ret;
-
- ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
- if (!ctrl)
- return -ENOMEM;
-
- dev_set_drvdata(&ofdev->dev, ctrl);
-
- spin_lock_init(&ctrl->controller.lock);
- init_waitqueue_head(&ctrl->controller.wq);
- init_waitqueue_head(&ctrl->irq_wait);
-
- ctrl->regs = of_iomap(ofdev->dev.of_node, 0);
- if (!ctrl->regs) {
- dev_err(&ofdev->dev, "failed to get memory region\n");
- ret = -ENODEV;
- goto err;
- }
-
- ctrl->irq = of_irq_to_resource(ofdev->dev.of_node, 0, NULL);
- if (ctrl->irq == NO_IRQ) {
- dev_err(&ofdev->dev, "failed to get irq resource\n");
- ret = -ENODEV;
- goto err;
- }
-
- ctrl->dev = &ofdev->dev;
-
- ret = fsl_elbc_ctrl_init(ctrl);
- if (ret < 0)
- goto err;
-
- ret = request_irq(ctrl->irq, fsl_elbc_ctrl_irq, 0, "fsl-elbc", ctrl);
- if (ret != 0) {
- dev_err(&ofdev->dev, "failed to install irq (%d)\n",
- ctrl->irq);
- ret = ctrl->irq;
- goto err;
- }
-
- for_each_child_of_node(ofdev->dev.of_node, child)
- if (of_device_is_compatible(child, "fsl,elbc-fcm-nand"))
- fsl_elbc_chip_probe(ctrl, child);
-
- return 0;
-
-err:
- fsl_elbc_ctrl_remove(ofdev);
- return ret;
-}
-
-static const struct of_device_id fsl_elbc_match[] = {
- {
- .compatible = "fsl,elbc",
- },
+static const struct platform_device_id fsl_elbc_nand_match[] = {
+ { "fsl,elbc-fcm-nand", },
{}
};
-static struct of_platform_driver fsl_elbc_ctrl_driver = {
+static struct platform_driver fsl_elbc_nand_driver = {
.driver = {
- .name = "fsl-elbc",
+ .name = "fsl,elbc-fcm-nand",
.owner = THIS_MODULE,
- .of_match_table = fsl_elbc_match,
},
- .probe = fsl_elbc_ctrl_probe,
- .remove = fsl_elbc_ctrl_remove,
+ .id_table = fsl_elbc_nand_match,
+ .probe = fsl_elbc_nand_probe,
+ .remove = fsl_elbc_nand_remove,
};
-static int __init fsl_elbc_init(void)
+static int __init fsl_elbc_nand_init(void)
{
- return of_register_platform_driver(&fsl_elbc_ctrl_driver);
+ return platform_driver_register(&fsl_elbc_nand_driver);
}
-static void __exit fsl_elbc_exit(void)
+static void __exit fsl_elbc_nand_exit(void)
{
- of_unregister_platform_driver(&fsl_elbc_ctrl_driver);
+ platform_driver_unregister(&fsl_elbc_nand_driver);
}
-module_init(fsl_elbc_init);
-module_exit(fsl_elbc_exit);
+module_init(fsl_elbc_nand_init);
+module_exit(fsl_elbc_nand_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Freescale");
--
1.5.6.5
^ permalink raw reply related
* [PATCH 1/3 v3] P4080/eLBC: Make Freescale elbc interrupt common to elbc devices
From: Roy Zang @ 2010-09-16 6:41 UTC (permalink / raw)
To: linux-mtd; +Cc: B07421, dedekind1, B25806, linuxppc-dev, akpm, dwmw2, B11780
From: Lan Chunhe-B25806 <b25806@freescale.com>
Move Freescale elbc interrupt from nand dirver to elbc driver.
Then all elbc devices can use the interrupt instead of ONLY nand.
Signed-off-by: Lan Chunhe-B25806 <b25806@freescale.com>
Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
---
Comparing with v2:
1. according to the feedback, add some decorations.
2. change of_platform_driver to platform_driver
3. rebase to 2.6.36-rc4
arch/powerpc/Kconfig | 7 +-
arch/powerpc/include/asm/fsl_lbc.h | 31 +++++-
arch/powerpc/sysdev/fsl_lbc.c | 246 ++++++++++++++++++++++++++++++------
3 files changed, 242 insertions(+), 42 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 631e5a0..44df1ba 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -687,9 +687,12 @@ config 4xx_SOC
bool
config FSL_LBC
- bool
+ bool "Freescale Local Bus support"
+ depends on FSL_SOC
help
- Freescale Localbus support
+ Enables reporting of errors from the Freescale local bus
+ controller. Also contains some common code used by
+ drivers for specific local bus peripherals.
config FSL_GTM
bool
diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h
index 1b5a210..db94698 100644
--- a/arch/powerpc/include/asm/fsl_lbc.h
+++ b/arch/powerpc/include/asm/fsl_lbc.h
@@ -1,9 +1,10 @@
/* Freescale Local Bus Controller
*
- * Copyright (c) 2006-2007 Freescale Semiconductor
+ * Copyright (c) 2006-2007, 2010 Freescale Semiconductor
*
* Authors: Nick Spence <nick.spence@freescale.com>,
* Scott Wood <scottwood@freescale.com>
+ * Jack Lan <jack.lan@freescale.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -125,13 +126,23 @@ struct fsl_lbc_regs {
#define LTESR_ATMW 0x00800000
#define LTESR_ATMR 0x00400000
#define LTESR_CS 0x00080000
+#define LTESR_UPM 0x00000002
#define LTESR_CC 0x00000001
#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
+#define LTESR_MASK (LTESR_BM | LTESR_FCT | LTESR_PAR | LTESR_WP \
+ | LTESR_ATMW | LTESR_ATMR | LTESR_CS | LTESR_UPM \
+ | LTESR_CC)
+#define LTESR_CLEAR 0xFFFFFFFF
+#define LTECCR_CLEAR 0xFFFFFFFF
+#define LTESR_STATUS LTESR_MASK
+#define LTEIR_ENABLE LTESR_MASK
+#define LTEDR_ENABLE 0x00000000
__be32 ltedr; /**< Transfer Error Disable Register */
__be32 lteir; /**< Transfer Error Interrupt Register */
__be32 lteatr; /**< Transfer Error Attributes Register */
__be32 ltear; /**< Transfer Error Address Register */
- u8 res6[0xC];
+ __be32 lteccr; /**< Transfer Error ECC Register */
+ u8 res6[0x8];
__be32 lbcr; /**< Configuration Register */
#define LBCR_LDIS 0x80000000
#define LBCR_LDIS_SHIFT 31
@@ -265,7 +276,23 @@ static inline void fsl_upm_end_pattern(struct fsl_upm *upm)
cpu_relax();
}
+/* overview of the fsl lbc controller */
+
+struct fsl_lbc_ctrl {
+ /* device info */
+ struct device *dev;
+ struct fsl_lbc_regs __iomem *regs;
+ int irq;
+ wait_queue_head_t irq_wait;
+ spinlock_t lock;
+ void *nand;
+
+ /* status read from LTESR by irq handler */
+ unsigned int irq_status;
+};
+
extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base,
u32 mar);
+extern struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
#endif /* __ASM_FSL_LBC_H */
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
index dceb8d1..edd6d95 100644
--- a/arch/powerpc/sysdev/fsl_lbc.c
+++ b/arch/powerpc/sysdev/fsl_lbc.c
@@ -2,8 +2,11 @@
* Freescale LBC and UPM routines.
*
* Copyright (c) 2007-2008 MontaVista Software, Inc.
+ * Copyright (c) 2010 Freescale Semiconductor
*
* Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ * Author: Jack Lan <Jack.Lan@freescale.com>
+ * Author: Roy Zang <tie-fei.zang@freescale.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,37 +24,14 @@
#include <linux/of.h>
#include <asm/prom.h>
#include <asm/fsl_lbc.h>
+#include <linux/slab.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
-static struct fsl_lbc_regs __iomem *fsl_lbc_regs;
-
-static char __initdata *compat_lbc[] = {
- "fsl,pq2-localbus",
- "fsl,pq2pro-localbus",
- "fsl,pq3-localbus",
- "fsl,elbc",
-};
-
-static int __init fsl_lbc_init(void)
-{
- struct device_node *lbus;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) {
- lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]);
- if (lbus)
- goto found;
- }
- return -ENODEV;
-
-found:
- fsl_lbc_regs = of_iomap(lbus, 0);
- of_node_put(lbus);
- if (!fsl_lbc_regs)
- return -ENOMEM;
- return 0;
-}
-arch_initcall(fsl_lbc_init);
+struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
+EXPORT_SYMBOL(fsl_lbc_ctrl_dev);
/**
* fsl_lbc_find - find Localbus bank
@@ -65,13 +45,15 @@ arch_initcall(fsl_lbc_init);
int fsl_lbc_find(phys_addr_t addr_base)
{
int i;
+ struct fsl_lbc_regs __iomem *lbc;
- if (!fsl_lbc_regs)
+ if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
return -ENODEV;
- for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) {
- __be32 br = in_be32(&fsl_lbc_regs->bank[i].br);
- __be32 or = in_be32(&fsl_lbc_regs->bank[i].or);
+ lbc = fsl_lbc_ctrl_dev->regs;
+ for (i = 0; i < ARRAY_SIZE(lbc->bank); i++) {
+ __be32 br = in_be32(&lbc->bank[i].br);
+ __be32 or = in_be32(&lbc->bank[i].or);
if (br & BR_V && (br & or & BR_BA) == addr_base)
return i;
@@ -94,22 +76,27 @@ int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm)
{
int bank;
__be32 br;
+ struct fsl_lbc_regs __iomem *lbc;
bank = fsl_lbc_find(addr_base);
if (bank < 0)
return bank;
- br = in_be32(&fsl_lbc_regs->bank[bank].br);
+ if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
+ return -ENODEV;
+
+ lbc = fsl_lbc_ctrl_dev->regs;
+ br = in_be32(&lbc->bank[bank].br);
switch (br & BR_MSEL) {
case BR_MS_UPMA:
- upm->mxmr = &fsl_lbc_regs->mamr;
+ upm->mxmr = &lbc->mamr;
break;
case BR_MS_UPMB:
- upm->mxmr = &fsl_lbc_regs->mbmr;
+ upm->mxmr = &lbc->mbmr;
break;
case BR_MS_UPMC:
- upm->mxmr = &fsl_lbc_regs->mcmr;
+ upm->mxmr = &lbc->mcmr;
break;
default:
return -EINVAL;
@@ -143,14 +130,18 @@ EXPORT_SYMBOL(fsl_upm_find);
* thus UPM pattern actually executed. Note that mar usage depends on the
* pre-programmed AMX bits in the UPM RAM.
*/
+
int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
{
int ret = 0;
unsigned long flags;
+ if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
+ return -ENODEV;
+
spin_lock_irqsave(&fsl_lbc_lock, flags);
- out_be32(&fsl_lbc_regs->mar, mar);
+ out_be32(&fsl_lbc_ctrl_dev->regs->mar, mar);
switch (upm->width) {
case 8:
@@ -172,3 +163,182 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
return ret;
}
EXPORT_SYMBOL(fsl_upm_run_pattern);
+
+static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl)
+{
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+
+ /* clear event registers */
+ setbits32(&lbc->ltesr, LTESR_CLEAR);
+ out_be32(&lbc->lteatr, 0);
+ out_be32(&lbc->ltear, 0);
+ out_be32(&lbc->lteccr, LTECCR_CLEAR);
+ out_be32(&lbc->ltedr, LTEDR_ENABLE);
+
+ /* Enable interrupts for any detected events */
+ out_be32(&lbc->lteir, LTEIR_ENABLE);
+
+ return 0;
+}
+
+static int __devexit fsl_lbc_ctrl_remove(struct platform_device *dev)
+{
+ struct fsl_lbc_ctrl *ctrl = dev_get_drvdata(&dev->dev);
+
+ if (ctrl->irq)
+ free_irq(ctrl->irq, ctrl);
+
+ if (ctrl->regs)
+ iounmap(ctrl->regs);
+
+ dev_set_drvdata(&dev->dev, NULL);
+
+ kfree(ctrl);
+
+ return 0;
+}
+
+/*
+ * NOTE: This interrupt is used to report localbus events of various kinds,
+ * such as transaction errors on the chipselects.
+ */
+
+static irqreturn_t fsl_lbc_ctrl_irq(int irqno, void *data)
+{
+ struct fsl_lbc_ctrl *ctrl = data;
+ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ u32 status;
+
+ status = in_be32(&lbc->ltesr);
+ if (!status)
+ return IRQ_NONE;
+
+ out_be32(&lbc->ltesr, LTESR_CLEAR);
+ out_be32(&lbc->lteatr, 0);
+ out_be32(&lbc->ltear, 0);
+ ctrl->irq_status = status;
+
+ if (status & LTESR_BM)
+ dev_err(ctrl->dev, "Local bus monitor time-out: "
+ "LTESR 0x%08X\n", status);
+ if (status & LTESR_WP)
+ dev_err(ctrl->dev, "Write protect error: "
+ "LTESR 0x%08X\n", status);
+ if (status & LTESR_ATMW)
+ dev_err(ctrl->dev, "Atomic write error: "
+ "LTESR 0x%08X\n", status);
+ if (status & LTESR_ATMR)
+ dev_err(ctrl->dev, "Atomic read error: "
+ "LTESR 0x%08X\n", status);
+ if (status & LTESR_CS)
+ dev_err(ctrl->dev, "Chip select error: "
+ "LTESR 0x%08X\n", status);
+ if (status & LTESR_UPM)
+ ;
+ if (status & LTESR_FCT) {
+ dev_err(ctrl->dev, "FCM command time-out: "
+ "LTESR 0x%08X\n", status);
+ smp_wmb();
+ wake_up(&ctrl->irq_wait);
+ }
+ if (status & LTESR_PAR) {
+ dev_err(ctrl->dev, "Parity or Uncorrectable ECC error: "
+ "LTESR 0x%08X\n", status);
+ smp_wmb();
+ wake_up(&ctrl->irq_wait);
+ }
+ if (status & LTESR_CC) {
+ smp_wmb();
+ wake_up(&ctrl->irq_wait);
+ }
+ if (status & ~LTESR_MASK)
+ dev_err(ctrl->dev, "Unknown error: "
+ "LTESR 0x%08X\n", status);
+ return IRQ_HANDLED;
+}
+
+/*
+ * fsl_lbc_ctrl_probe
+ *
+ * called by device layer when it finds a device matching
+ * one our driver can handled. This code allocates all of
+ * the resources needed for the controller only. The
+ * resources for the NAND banks themselves are allocated
+ * in the chip probe function.
+*/
+
+static int __devinit fsl_lbc_ctrl_probe(struct platform_device *dev)
+{
+ int ret;
+
+ if (!dev->dev.of_node) {
+ dev_err(&dev->dev, "Device OF-Node is NULL");
+ return -EFAULT;
+ }
+ fsl_lbc_ctrl_dev = kzalloc(sizeof(*fsl_lbc_ctrl_dev), GFP_KERNEL);
+ if (!fsl_lbc_ctrl_dev)
+ return -ENOMEM;
+
+ dev_set_drvdata(&dev->dev, fsl_lbc_ctrl_dev);
+
+ spin_lock_init(&fsl_lbc_ctrl_dev->lock);
+ init_waitqueue_head(&fsl_lbc_ctrl_dev->irq_wait);
+
+ fsl_lbc_ctrl_dev->regs = of_iomap(dev->dev.of_node, 0);
+ if (!fsl_lbc_ctrl_dev->regs) {
+ dev_err(&dev->dev, "failed to get memory region\n");
+ ret = -ENODEV;
+ goto err;
+ }
+
+ fsl_lbc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0);
+ if (fsl_lbc_ctrl_dev->irq == NO_IRQ) {
+ dev_err(&dev->dev, "failed to get irq resource\n");
+ ret = -ENODEV;
+ goto err;
+ }
+
+ fsl_lbc_ctrl_dev->dev = &dev->dev;
+
+ ret = fsl_lbc_ctrl_init(fsl_lbc_ctrl_dev);
+ if (ret < 0)
+ goto err;
+
+ ret = request_irq(fsl_lbc_ctrl_dev->irq, fsl_lbc_ctrl_irq, 0,
+ "fsl-lbc", fsl_lbc_ctrl_dev);
+ if (ret != 0) {
+ dev_err(&dev->dev, "failed to install irq (%d)\n",
+ fsl_lbc_ctrl_dev->irq);
+ ret = fsl_lbc_ctrl_dev->irq;
+ goto err;
+ }
+
+ return 0;
+
+err:
+ iounmap(fsl_lbc_ctrl_dev->regs);
+ kfree(fsl_lbc_ctrl_dev);
+ return ret;
+}
+
+static const struct platform_device_id fsl_lbc_match[] = {
+ { "fsl,elbc", },
+ { "fsl,pq3-localbus", },
+ { "fsl,pq2-localbus", },
+ { "fsl,pq2pro-localbus", },
+ {},
+};
+
+static struct platform_driver fsl_lbc_ctrl_driver = {
+ .driver = {
+ .name = "fsl-lbc",
+ },
+ .probe = fsl_lbc_ctrl_probe,
+ .id_table = fsl_lbc_match,
+};
+
+static int __init fsl_lbc_init(void)
+{
+ return platform_driver_register(&fsl_lbc_ctrl_driver);
+}
+module_init(fsl_lbc_init);
--
1.5.6.5
^ permalink raw reply related
* [PATCH 3/3 v3] P4080/mtd: Fix the freescale lbc issue with 36bit mode
From: Roy Zang @ 2010-09-16 6:41 UTC (permalink / raw)
To: linux-mtd; +Cc: B07421, dedekind1, B25806, linuxppc-dev, akpm, dwmw2, B11780
In-Reply-To: <1284619284-23614-2-git-send-email-tie-fei.zang@freescale.com>
From: Lan Chunhe-B25806 <b25806@freescale.com>
When system uses 36bit physical address, res.start is 36bit
physical address. But the function of in_be32 returns 32bit
physical address. Then both of them compared each other is
wrong. So by converting the address of res.start into
the right format fixes this issue.
Signed-off-by: Lan Chunhe-B25806 <b25806@freescale.com>
Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
---
arch/powerpc/include/asm/fsl_lbc.h | 1 +
arch/powerpc/sysdev/fsl_lbc.c | 23 ++++++++++++++++++++++-
drivers/mtd/nand/fsl_elbc_nand.c | 2 +-
3 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h
index db94698..5638b1e 100644
--- a/arch/powerpc/include/asm/fsl_lbc.h
+++ b/arch/powerpc/include/asm/fsl_lbc.h
@@ -246,6 +246,7 @@ struct fsl_upm {
int width;
};
+extern unsigned int fsl_lbc_addr(phys_addr_t addr_base);
extern int fsl_lbc_find(phys_addr_t addr_base);
extern int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm);
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
index edd6d95..8a835ef 100644
--- a/arch/powerpc/sysdev/fsl_lbc.c
+++ b/arch/powerpc/sysdev/fsl_lbc.c
@@ -34,6 +34,27 @@ struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
EXPORT_SYMBOL(fsl_lbc_ctrl_dev);
/**
+ * fsl_lbc_addr - convert the base address
+ * @addr_base: base address of the memory bank
+ *
+ * This function converts a base address of lbc into the right format for the
+ * BR register. If the SOC has eLBC then it returns 32bit physical address
+ * else it convers a 34bit local bus physical address to correct format of
+ * 32bit address for BR register (Example: MPC8641).
+ */
+u32 fsl_lbc_addr(phys_addr_t addr_base)
+{
+ struct device_node *np = fsl_lbc_ctrl_dev->dev->of_node;
+ u32 addr = addr_base & 0xffff8000;
+
+ if (of_device_is_compatible(np, "fsl,elbc"))
+ return addr;
+
+ return addr | ((addr_base & 0x300000000ull) >> 19);
+}
+EXPORT_SYMBOL(fsl_lbc_addr);
+
+/**
* fsl_lbc_find - find Localbus bank
* @addr_base: base address of the memory bank
*
@@ -55,7 +76,7 @@ int fsl_lbc_find(phys_addr_t addr_base)
__be32 br = in_be32(&lbc->bank[i].br);
__be32 or = in_be32(&lbc->bank[i].or);
- if (br & BR_V && (br & or & BR_BA) == addr_base)
+ if (br & BR_V && (br & or & BR_BA) == fsl_lbc_addr(addr_base))
return i;
}
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 91c5c05..85858e3 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -865,7 +865,7 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *dev)
(in_be32(&lbc->bank[bank].br) & BR_MSEL) == BR_MS_FCM &&
(in_be32(&lbc->bank[bank].br) &
in_be32(&lbc->bank[bank].or) & BR_BA)
- == res.start)
+ == fsl_lbc_addr(res.start))
break;
if (bank >= MAX_BANKS) {
--
1.5.6.5
^ 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