LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [RFCv2 02/14] dt: Make irqdomain less verbose
From: Grant Likely @ 2012-01-23 21:07 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev, devicetree-discuss, Milton Miller,
	benh, Rob Herring
  Cc: Thomas Gleixner
In-Reply-To: <1327352870-14687-1-git-send-email-grant.likely@secretlab.ca>

It printk's too much.  Drop some output.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Cc: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/irq/irqdomain.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 1f9e265..cc2cd43 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -170,13 +170,11 @@ void irq_domain_generate_simple(const struct of_device_id *match,
 				u64 phys_base, unsigned int irq_start)
 {
 	struct device_node *node;
-	pr_info("looking for phys_base=%llx, irq_start=%i\n",
+	pr_debug("looking for phys_base=%llx, irq_start=%i\n",
 		(unsigned long long) phys_base, (int) irq_start);
 	node = of_find_matching_node_by_address(NULL, match, phys_base);
 	if (node)
 		irq_domain_add_simple(node, irq_start);
-	else
-		pr_info("no node found\n");
 }
 EXPORT_SYMBOL_GPL(irq_domain_generate_simple);
 #endif /* CONFIG_OF_IRQ */
-- 
1.7.5.4

^ permalink raw reply related

* [RFCv2 01/14] irq_domain: add documentation and MAINTAINERS entry.
From: Grant Likely @ 2012-01-23 21:07 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev, devicetree-discuss, Milton Miller,
	benh, Rob Herring
  Cc: Thomas Gleixner
In-Reply-To: <1327352870-14687-1-git-send-email-grant.likely@secretlab.ca>

Documentation for irq_domain library which will be created in subsequent
patches.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
---
 Documentation/IRQ-domain.txt |  113 ++++++++++++++++++++++++++++++++++++++++++
 MAINTAINERS                  |    9 +++
 2 files changed, 122 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/IRQ-domain.txt

diff --git a/Documentation/IRQ-domain.txt b/Documentation/IRQ-domain.txt
new file mode 100644
index 0000000..247f32a
--- /dev/null
+++ b/Documentation/IRQ-domain.txt
@@ -0,0 +1,113 @@
+irq_domain interrupt number mapping library
+
+The current design of the Linux kernel uses a single large number
+space where each separate IRQ source is assigned a different number.
+This is simple when there is only one interrupt controller, but in
+systems with controllers the kernel must ensure that each one does not
+get assigned overlapping allocations of Linux irq numbers.
+
+The irq_alloc_desc*() and irq_free_desc*() API provides allocation of
+irq numbers, but it doesn't provide any support for reverse mapping of
+the controller-local irq (hwirq) number into the Linux irq number
+space.
+
+The irq_domain library adds mapping between hwirq and irq numbers on
+top of the irq_alloc_desc*() API.  An irq_domain to manage mapping is
+preferred over interrupt controller drivers open coding their own
+reverse mapping scheme.
+
+irq_domain also implements translation from Device Tree interrupt
+specifiers to hwirq numbers, and can be easily extended to support
+other irq topology data sources.
+
+=== irq_domain usage ===
+An interrupt controller driver creates and registers an irq_domain by
+calling one of the irq_domain_add_*() functions (each mapping method
+has a different allocator function, more on that later).  The function
+will return a pointer to the irq_domain on success.  It must provide
+the allocator function with an irq_domain_ops structure with the .map
+callback populated as a minimum.
+
+In most cases, the irq_domain will begin empty without any mappings
+between hwirq and irq numbers.  Mappings are added to the irq_domain
+by calling irq_create_mapping() which accepts the irq_domain and a
+hwirq number as arguments.  If a mapping for the hwirq doesn't already
+exist then it will allocate a new linux irq_desc, associate it with
+the hwirq, and call the .map() callback so the driver can perform any
+required hardware setup.
+
+When an interrupt is received, irq_find_mapping() function should
+be used to find the Linux irq number from the hwirq number.
+
+If the driver has the Linux irq number or the irq_data pointer, and
+needs to know the associated hwirq number (such as in the irq_chip
+callbacks) then it can be directly obtained from irq_data->hwirq.
+
+=== Types of irq_domain mappings ===
+There are several mechanisms available for reverse mapping from hwirq
+to Linux irq, and each mechanism uses a different allocation function.
+Which reverse map type should be used depends on the use case.  Each
+of the reverse map types are described below:
+
+==== Linear ====
+irq_domain_add_linear()
+
+The linear reverse map maintains a fixed size table indexed by the
+hwirq number.  When a hwirq is mapped, an irq_desc is allocated for
+the hwirq, and the irq number is stored in the table.
+
+The Linear map is a good choice when the maximum number of hwirqs is
+fixed and a relatively small number (~ < 256).  The advantages of this
+map are fixed time lookup for irq numbers, and irq_descs are only
+allocated for in-use irqs.  The disadvantage is that the table must be
+as large as the largest possible hwirq number.
+
+The majority of drivers should use the linear map.
+
+==== Tree ====
+irq_domain_add_tree()
+
+The irq_domain maintains a radix tree map from hwirq numbers to linux
+irqs.  When an hwirq is mapped, and irq_desc is allocated and the
+hwirq is used as the lookup key for the radix tree.
+
+The tree map is a good choice if the hwirq number can be very large
+since it doesn't need to allocate a table as large as the largest
+hwirq number.  The disadvantage is that hwirq to irq number lookup is
+dependent on how many entries are in the table.
+
+Very few drivers should need this mapping.  At the moment, powerpc
+iseries is the only user.
+
+==== No Map ===-
+irq_domain_add_nomap()
+
+The No Map mapping is to be used when the hwirq number is
+programmable in the hardware.  In this case it is best to program the
+Linux irq number into the hardware itself so that no mapping is
+required.  Calling irq_create_direct_mapping() will allocate a linux
+irq number and call the .map() callback so that driver can program the
+Linux irq number into the hardware.
+
+Most drivers cannot use this mapping.
+
+==== Legacy ====
+irq_domain_add_legacy()
+irq_domain_add_legacy_isa()
+
+The Legacy mapping is a special case for drivers that already have a
+range of irq_descs allocated for the hwirqs.  It is used when the
+driver cannot be immediately converted to use the linear mapping, such
+as when the driver is used in a system with fixed irq number
+assignments, as is typical in many embedded system board files.
+
+The legacy map assumes a contiguous range of irq numbers has already
+been allocated for the controller and that the irq number can be
+calculated by adding a fixed offset to the hwirq number, and
+visa-versa.  The disadvantage is that it requires the interrupt
+controller to manage irq allocations and it requires an irq_desc to be
+allocated for every hwirq, even if it is unused.
+
+Drivers should only use the legacy map if they have fixed irq mappings
+(#define IRQ_* in embedded board files).  For example, ISA controllers
+mapped to Linux irqs 0-15 would use the legacy map.
diff --git a/MAINTAINERS b/MAINTAINERS
index 89b70df..d308f0f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3626,6 +3626,15 @@ S:	Maintained
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core
 F:	kernel/irq/
 
+IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY)
+M:	Benjamin Herrenschmidt <benh@kernel.crashing.org>
+M:	Grant Likely <grant.likely@secretlab.ca>
+T:	git git://git.secretlab.ca/git/linux-2.6.git irqdomain/next
+S:	Maintained
+F:	Documentation/IRQ-domain.txt
+F:	include/linux/irqdomain.h
+F:	kernel/irq/irqdomain.c
+
 ISAPNP
 M:	Jaroslav Kysela <perex@perex.cz>
 S:	Maintained
-- 
1.7.5.4

^ permalink raw reply related

* [RFCv2 00/14]
From: Grant Likely @ 2012-01-23 21:07 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev, devicetree-discuss, Milton Miller,
	benh, Rob Herring


Hey everyone,

Here's the second RFC for the irq_domain patches.  I could use some
help testing now.  I still expect there will be a few bugs.  The
series is based on v3.3-rc1, and I've pushed it out to my git server:

git://git.secretlab.ca/git/linux-2.6.git irqdomain/next

On Wed, Jan 11, 2012 at 1:22 PM, Grant Likely <grant.likely@secretlab.ca> wrote:
> Here are the patches that I've been working on to finish up the creation
> of the generic irq_domain infrastructure.
> 
> I'm taking a different approach that I originally intended.
> Originally I intended to start with the basic design of irq_host from
> powerpc, but there were some things about the implementation that I
> didn't like, so I was going to reimplement those bits and then migrate
> powerpc over to use it.  That was a mistake and would have resulted in
> a lot more work.  Instead, I should have started with the powerpc
> irq_host code, moved it to a common location, and then reworked it in
> place.  The powerpc code is working and well tested.  It is a lot less
> risky to use it as the starting point with a nicely bisectable series
> of changes to make it do what other architectures need.

[RFCv2 01/14] irq_domain: add documentation and MAINTAINERS entry.
[RFCv2 02/14] dt: Make irqdomain less verbose
[RFCv2 03/14] irq_domain: Make irq_domain structure match powerpc's
[RFCv2 04/14] irq_domain: convert microblaze from irq_host to
[RFCv2 05/14] irq_domain/powerpc: Use common irq_domain structure
[RFCv2 06/14] irq_domain/powerpc: eliminate irq_map; use
[RFCv2 07/14] irq_domain/powerpc: Eliminate virq_is_host()
[RFCv2 08/14] irq_domain: Move irq_domain code from powerpc to
[RFCv2 09/14] irqdomain: remove NO_IRQ from irq domain code
[RFCv2 10/14] irq_domain: Remove references to old irq_host names
[RFCv2 11/14] irq_domain: Replace irq_alloc_host() with
[RFCv2 12/14] irq_domain: Add support for base irq and hwirq in
[RFCv2 13/14] irq_domain: Remove 'new' irq_domain in favour of the
[RFCv2 14/14] irq_domain: Remove irq_domain_add_simple()

 Documentation/IRQ-domain.txt                     |  113 ++++
 MAINTAINERS                                      |    9 +
 arch/arm/common/gic.c                            |   97 ++--
 arch/arm/common/vic.c                            |   16 +-
 arch/arm/include/asm/hardware/gic.h              |    4 +-
 arch/arm/include/asm/hardware/vic.h              |    2 +
 arch/arm/mach-exynos/common.c                    |    2 +-
 arch/arm/mach-imx/mach-imx6q.c                   |    3 +-
 arch/arm/mach-msm/board-msm8x60.c                |    8 +-
 arch/arm/mach-mx5/imx51-dt.c                     |    4 +-
 arch/arm/mach-mx5/imx53-dt.c                     |    4 +-
 arch/arm/mach-omap2/board-generic.c              |    2 +-
 arch/arm/mach-prima2/irq.c                       |    2 +-
 arch/arm/mach-versatile/core.c                   |    5 +-
 arch/microblaze/include/asm/irq.h                |    4 +-
 arch/microblaze/kernel/irq.c                     |    2 +-
 arch/microblaze/kernel/setup.c                   |    2 -
 arch/powerpc/Kconfig                             |    1 +
 arch/powerpc/include/asm/ehv_pic.h               |    2 +-
 arch/powerpc/include/asm/i8259.h                 |    2 +-
 arch/powerpc/include/asm/irq.h                   |  247 +-------
 arch/powerpc/include/asm/mpic.h                  |    2 +-
 arch/powerpc/include/asm/xics.h                  |    2 +-
 arch/powerpc/kernel/irq.c                        |  617 +------------------
 arch/powerpc/platforms/512x/mpc5121_ads_cpld.c   |   12 +-
 arch/powerpc/platforms/52xx/media5200.c          |   15 +-
 arch/powerpc/platforms/52xx/mpc52xx_gpt.c        |   16 +-
 arch/powerpc/platforms/52xx/mpc52xx_pic.c        |   12 +-
 arch/powerpc/platforms/82xx/pq2ads-pci-pic.c     |   14 +-
 arch/powerpc/platforms/85xx/socrates_fpga_pic.c  |   15 +-
 arch/powerpc/platforms/86xx/gef_pic.c            |   15 +-
 arch/powerpc/platforms/cell/axon_msi.c           |   29 +-
 arch/powerpc/platforms/cell/beat_interrupt.c     |   16 +-
 arch/powerpc/platforms/cell/interrupt.c          |   16 +-
 arch/powerpc/platforms/cell/spider-pic.c         |   14 +-
 arch/powerpc/platforms/embedded6xx/flipper-pic.c |   30 +-
 arch/powerpc/platforms/embedded6xx/hlwd-pic.c    |   35 +-
 arch/powerpc/platforms/iseries/irq.c             |   11 +-
 arch/powerpc/platforms/powermac/pic.c            |   15 +-
 arch/powerpc/platforms/powermac/smp.c            |    9 +-
 arch/powerpc/platforms/ps3/interrupt.c           |   11 +-
 arch/powerpc/platforms/wsp/opb_pic.c             |   15 +-
 arch/powerpc/sysdev/cpm1.c                       |    9 +-
 arch/powerpc/sysdev/cpm2_pic.c                   |   11 +-
 arch/powerpc/sysdev/ehv_pic.c                    |   14 +-
 arch/powerpc/sysdev/fsl_msi.c                    |   10 +-
 arch/powerpc/sysdev/fsl_msi.h                    |    2 +-
 arch/powerpc/sysdev/i8259.c                      |   15 +-
 arch/powerpc/sysdev/ipic.c                       |   15 +-
 arch/powerpc/sysdev/ipic.h                       |    2 +-
 arch/powerpc/sysdev/mpc8xx_pic.c                 |   11 +-
 arch/powerpc/sysdev/mpic.c                       |   17 +-
 arch/powerpc/sysdev/mpic_msi.c                   |    2 +-
 arch/powerpc/sysdev/mv64x60_pic.c                |   11 +-
 arch/powerpc/sysdev/qe_lib/qe_ic.c               |   13 +-
 arch/powerpc/sysdev/qe_lib/qe_ic.h               |    2 +-
 arch/powerpc/sysdev/tsi108_pci.c                 |   13 +-
 arch/powerpc/sysdev/uic.c                        |   14 +-
 arch/powerpc/sysdev/xics/xics-common.c           |   25 +-
 arch/powerpc/sysdev/xilinx_intc.c                |   19 +-
 drivers/gpio/gpio-mpc8xxx.c                      |   15 +-
 drivers/mfd/twl-core.c                           |   12 +-
 include/linux/irqdomain.h                        |  180 ++++--
 kernel/irq/irqdomain.c                           |  757 ++++++++++++++++++----
 64 files changed, 1207 insertions(+), 1414 deletions(-)

^ permalink raw reply

* Re: [PATCH] powerpc/booke64: Configurable lazy interrupt disabling
From: Benjamin Herrenschmidt @ 2012-01-23 20:50 UTC (permalink / raw)
  To: Scott Wood; +Cc: Laurentiu Tudor, linuxppc-dev, Stuart Yoder
In-Reply-To: <4F1DB344.9030709@freescale.com>

On Mon, 2012-01-23 at 13:21 -0600, Scott Wood wrote:

> > BTW, for non-booke, when is DEC checked when interrupts are hard-enabled
> > as part of exception return?  Likewise with the PS3 HV thing.  I only
> > see the iseries check in the exception path.

Exception return restores them to their previous state, so shouldn't be
a problem unless your exception takes long enough to overflow the DEC in
which case you have other problems. The PS/3 case might be broken.

> Perhaps the issues with a higher priority interrupt intervening can be
> addressed by messing around with current task priority at the MPIC (with
> an hcall introduced for the hv case, since currently task priority is
> not exposed to the guest).  I haven't had time to revisit this, and
> don't expect to soon.  If someone else wants to try, fine.  In the
> meantime, lazy EE is causing problems.

Or by storing pending interrupts in an array.

> I'd still like to know the answer to that last question.  It's difficult
> to determine how to correctly implement this stuff for our hardware if
> it looks like there are holes in the scheme for hardware that this is
> supposed to already work with.
> 
> > Traditionally EE's have always been "level sensitive" on PowerPC,
> 
> You mean besides the places you already have to work around, such as
> doorbells 

Which you introduced as well... this is especially ironic since BookE
had the decrementer done right in the first place :-)

> and book3s decrementers 

Book3s decrementer is level sensitive based on the sign bit of the
decrementer (a bit odd but heh....) at least on 64-bit processors.

> and other hypervisors... 

I wouldn't take the PS3 HV and legacy iseries HV as good design
examples :-) The later was working around limited HW functionality at
the time as well. 

> and you force
> all functions that enable interrupts to create a stack frame to deal
> with this.

Right, but overall this is still more efficient performance wise on most
processors than whacking the MSR.

However the main thing is that this significantly improves the quality
of the samples obtained from performance interrupts which can now act as
pseudo-NMI up to a certain point.

It also helps with Alex PR KVM but that's just a detail really.

> > the way you changed that is arguably an utterly broken HW design
> 
> Just because you don't like it, and it doesn't play well with your hack,
> doesn't make it "utterly broken".

Deal with it. The "hack" has been there for long enough and works well.
I don't want compile-time conditional to change that behaviour.

> > and I am not too keen on changing our core interrupt handling to deal with it via
> > ifdef's if we can find a less invasive solution.
> 
> Wheras having to significantly change the way interrupts work because
> the register size doubled is so totally reasonable...

We were very tempted at some point to do lazy EE for 32-bit as well,
eventually decided we didn't care enough :-)

> What is the compelling reason for forcing lazy EE on us?  Why is it tied
> to 64-bit?

Because that's where we historically implemented it and because iSeries
more/less required to begin with. And I don't want to have a split
scheme, especially not a compile time one.

Cheers,
Ben.

^ permalink raw reply

* Re: Searching TLB entry for a page frame number.
From: Scott Wood @ 2012-01-23 19:33 UTC (permalink / raw)
  To: Arshad, Farrukh; +Cc: linuxppc-dev@lists.ozlabs.org
In-Reply-To: <93CD5F41FDBC6042A6B449764F3B35CC050CDFE1@EU-MBX-03.mgc.mentorg.com>

On 01/23/2012 01:49 AM, Arshad, Farrukh wrote:
> Greetings All,
>=20
> =20
>=20
> I have a quick question regarding TLB dump for P1022. Please excuse me
> for being na=EFve. I want to dump the TLB entry for a page number. I kn=
ow
> my page frame number. If I read TLB0 dump using tlbre instruction, the
> instruction output TLB0 entries in MAS0 =96 MAS3 registers. After the
> tlbre instruction the value of MAS3 register [32-51] RPN, Is this Real
> Page Number is the page frame number for which I am searching the TLB e=
ntry.

Yes, and MAS7 contains the upper 4 bits.

-Scott

^ permalink raw reply

* Re: [PATCH] powerpc/booke64: Configurable lazy interrupt disabling
From: Scott Wood @ 2012-01-23 19:31 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: Laurentiu Tudor, linuxppc-dev, Stuart Yoder
In-Reply-To: <1327100531.2923.3.camel@pasglop>

On 01/20/2012 05:02 PM, Benjamin Herrenschmidt wrote:
> 
>> With Topaz, interrupts go directly to guests and we don't want to require a
>> trap/hcall to do an IACK, as that adds potentially thousands of cycles of
>> latency to every interrupt.
>>
>> As you know, with external proxy interrupts are acknowledged by the
>> hardware and it becomes problematic to replay the interrupt in
>> the context of lazy EE when interrupts are re-enabled.   The interrupt
>> will not fire again when you enable EE.
> 
> So you have a broken HW and broken HV design to start with ... :-)

That "breakage" significantly reduces the overhead of handling
interrupts in a guest, since we don't need to involve the hypervisor (at
least on the entry side -- there's a hack to avoid it on EOI as well,
though that involves exposing some MPIC registers directly; users can
decide whether it's worth enabling for their use case).

-Scott

^ permalink raw reply

* Re: [PATCH] powerpc/booke64: Configurable lazy interrupt disabling
From: Scott Wood @ 2012-01-23 19:21 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: Laurentiu Tudor, linuxppc-dev, Stuart Yoder
In-Reply-To: <1327100755.2923.6.camel@pasglop>

On 01/20/2012 05:05 PM, Benjamin Herrenschmidt wrote:
> On Thu, 2012-01-19 at 13:29 -0600, Stuart Yoder wrote:
>> Also, Scott had posted an approach to do option #2 a while back,
>> but as I  recall there was some negative feedback about this.  See:
>> <http://lists.ozlabs.org/pipermail/linuxppc-dev/2011-August/092103.html>
> 
> I see... the problems with doorbells are workable tho. A reject hcall
> could also raise the CPU priority to avoid lower priority interrupts for
> example. The decrementer option works too.
> 
> Another approach is to do an hcall into the interrupt re-enable path
> when an interrupt occurred while masked, which is what we do on i or
> ps3, which could then trigger a replay.

Here's what I previously wrote to you about this:
> If we never hard-enable with a pending interrupt (go straight to the
> exception entry), we can leave the interrupt in EPR.  If we hard-enable
> even briefly, we can't guarantee that another (higher priority)
> interrupt won't come in before the doorbell, so we need to be able to
> queue up a number of interrupts equal to the number of priorities in use.
> 
> Care will need to be taken to dequeue in proper order, whether the
> interrupt comes in via extirq or doorbell (e.g. if we take an extirq on
> hard-enable, and then the doorbell fires when that interrupt
> hard-enables, we don't want to run the lower-priority queued interrupt
> until after the high prio handler is done).
> 
> BTW, for non-booke, when is DEC checked when interrupts are hard-enabled
> as part of exception return?  Likewise with the PS3 HV thing.  I only
> see the iseries check in the exception path.

Perhaps the issues with a higher priority interrupt intervening can be
addressed by messing around with current task priority at the MPIC (with
an hcall introduced for the hv case, since currently task priority is
not exposed to the guest).  I haven't had time to revisit this, and
don't expect to soon.  If someone else wants to try, fine.  In the
meantime, lazy EE is causing problems.

I'd still like to know the answer to that last question.  It's difficult
to determine how to correctly implement this stuff for our hardware if
it looks like there are holes in the scheme for hardware that this is
supposed to already work with.

> Traditionally EE's have always been "level sensitive" on PowerPC,

You mean besides the places you already have to work around, such as
doorbells and book3s decrementers and other hypervisors... and you force
all functions that enable interrupts to create a stack frame to deal
with this.

> the way you changed that is arguably an utterly broken HW design

Just because you don't like it, and it doesn't play well with your hack,
doesn't make it "utterly broken".

> and I am not too keen on changing our core interrupt handling to deal with it via
> ifdef's if we can find a less invasive solution.

Wheras having to significantly change the way interrupts work because
the register size doubled is so totally reasonable...

What is the compelling reason for forcing lazy EE on us?  Why is it tied
to 64-bit?

-Scott

^ permalink raw reply

* Problem with ADS512101 : Switch from serial I/O to LCD
From: ehodys @ 2012-01-23 18:01 UTC (permalink / raw)
  To: linuxppc-dev

Hello all,

I am newbie about porting Linux on a ADS512101 Dev tool and I don't  
know how to put the video display at work. The only thing that works  
is the serial interface and I find no information to switch to the LCD  
display.

Can some one help me please, thank you.

Best regards

Edgar

^ permalink raw reply

* Cannot wake-up from standby with MPC8313
From: nvbolhuis @ 2012-01-23  9:34 UTC (permalink / raw)
  To: scottwood; +Cc: linuxppc-dev


>
> It is mentioned in the MPC8313E manual (4.2.2 step #10) that TRST must
> not be asserted except when PORESET is asserted.  The mpc8313erdb bug
> was that the board was not complying with this.
>

ok, I see.

The board did not comply to the spec and as a side-effect PMC
registers could not be accessed.

Thanks again for all help!

---
NvBolhuis

^ permalink raw reply

* Re: Cannot wake-up from standby with MPC8313
From: ehodys @ 2012-01-23 10:08 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <4F19C8F8.1090801@freescale.com>

Hello al,

I am newbie about porting Linux on a ADS512101 Dev tool and I don't  
know how to put the video display at work. The only thing that works  
is the serial interface and I find no information to switch to the LCD  
display.

Can some one help me please, thank you.

Best regards

Edgar

^ permalink raw reply

* Searching TLB entry for a page frame number.
From: Arshad, Farrukh @ 2012-01-23  7:49 UTC (permalink / raw)
  To: linuxppc-dev@lists.ozlabs.org

[-- Attachment #1: Type: text/plain, Size: 614 bytes --]

Greetings All,

I have a quick question regarding TLB dump for P1022. Please excuse me for being naïve. I want to dump the TLB entry for a page number. I know my page frame number. If I read TLB0 dump using tlbre instruction, the instruction output TLB0 entries in MAS0 - MAS3 registers. After the tlbre instruction the value of MAS3 register [32-51] RPN, Is this Real Page Number is the page frame number for which I am searching the TLB entry.


Best Regards

Farrukh Arshad
Sr. Software Development Engineer
Mentor Graphics Pakistan
Ph:   +92 - 423 - 609 - 92 - 09
Cell: +92 - 303 - 444 - 77 - 05


[-- Attachment #2: Type: text/html, Size: 3035 bytes --]

^ permalink raw reply

* Re: [PATCH] powerpc/85xx: fix build failure from p1022 in SMP defconfig
From: Paul Gortmaker @ 2012-01-21 15:50 UTC (permalink / raw)
  To: galak; +Cc: linuxppc-dev, paulus
In-Reply-To: <1327157528-12312-1-git-send-email-paul.gortmaker@windriver.com>

On Sat, Jan 21, 2012 at 9:52 AM, Paul Gortmaker
<paul.gortmaker@windriver.com> wrote:
> Using the configs/mpc85xx_smp_defconfig shows this build error:
>
> arch/powerpc/platforms/85xx/p1022_ds.c:341: error: 'udbg_progress' undecl=
ared here (not in a function)
>
> Adding in the obvious missing header <asm/udbg.h> fixes it.

I just noticed this fix is a duplicate, it seems that it was already
queued back in Dec 11th last year:

http://patchwork.ozlabs.org/patch/130620/

...but for one reason or another didn't make it into 3.3-rc1.

P.

>
> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
>
> diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platfo=
rms/85xx/p1022_ds.c
> index bb3d84f..aa4022e 100644
> --- a/arch/powerpc/platforms/85xx/p1022_ds.c
> +++ b/arch/powerpc/platforms/85xx/p1022_ds.c
> @@ -26,6 +26,7 @@
> =A0#include <sysdev/fsl_soc.h>
> =A0#include <sysdev/fsl_pci.h>
> =A0#include <asm/fsl_guts.h>
> +#include <asm/udbg.h>
> =A0#include "smp.h"
>
> =A0#include "mpc85xx.h"
> --
> 1.7.7.2
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev

^ permalink raw reply

* [PATCH] powerpc/85xx: fix build failure from p1022 in SMP defconfig
From: Paul Gortmaker @ 2012-01-21 14:52 UTC (permalink / raw)
  To: galak; +Cc: paulus, linuxppc-dev, Paul Gortmaker

Using the configs/mpc85xx_smp_defconfig shows this build error:

arch/powerpc/platforms/85xx/p1022_ds.c:341: error: 'udbg_progress' undeclared here (not in a function)

Adding in the obvious missing header <asm/udbg.h> fixes it.

Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>

diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index bb3d84f..aa4022e 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -26,6 +26,7 @@
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
 #include <asm/fsl_guts.h>
+#include <asm/udbg.h>
 #include "smp.h"
 
 #include "mpc85xx.h"
-- 
1.7.7.2

^ permalink raw reply related

* [PATCH] powerpc: dont include 8250 pre-setup if 8250 driver isn't enabled.
From: Paul Gortmaker @ 2012-01-21  3:50 UTC (permalink / raw)
  To: benh, paulus; +Cc: Paul Gortmaker, linuxppc-dev

The legacy_serial code was setting things up based on the assumption
that the main 8250 driver would be loaded shortly after.  But some
randconfigs exposed an issue where early debug (UDB) UART support was
enabled, yet the core UART 8250 support was disabled.

In theory a person could care about _really_ early UART output for
early debug, but not care about generic console output via UART on
embedded devices, so fix things so it is a valid combination.

While this might seem like a pointless randconfig change, there are
some existing default configs that actually reflect the above setup.

Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>

diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
index 3fea368..9a82a49 100644
--- a/arch/powerpc/kernel/legacy_serial.c
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -413,6 +413,14 @@ void __init find_legacy_serial_ports(void)
 	DBG(" <- find_legacy_serial_port()\n");
 }
 
+/*
+ * In theory, one could have the early debugging enabled, but yet not care
+ * about 8250 after that, i.e. PPC_UDBG_16550=y but "SERIAL_8250 is not set".
+ * Mostly appears in randconfig builds, but some defconfigs have this.
+ */
+
+#ifdef CONFIG_SERIAL_8250
+
 static struct platform_device serial_device = {
 	.name	= "serial8250",
 	.id	= PLAT8250_DEV_PLATFORM,
@@ -523,6 +531,7 @@ static int __init serial_dev_init(void)
 }
 device_initcall(serial_dev_init);
 
+#endif	/* CONFIG_SERIAL_8250 */
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
 /*
-- 
1.7.7.2

^ permalink raw reply related

* Re: error: 'cpus_in_crash' defined but not used
From: Christian Kujau @ 2012-01-21  0:45 UTC (permalink / raw)
  To: LKML; +Cc: linuxppc-dev
In-Reply-To: <alpine.DEB.2.01.1201172104410.2895@trent.utfs.org>

> On Tue, 17 Jan 2012 at 20:13, Christian Kujau wrote:
> > 
> > compiling today's git (mainline, a25a2b8) on powerpc32 gives:
> > 
> >   CC      arch/powerpc/kernel/crash.o
> > cc1: warnings being treated as errors
> > /usr/local/src/linux-2.6-git/arch/powerpc/kernel/crash.c:49: error: 
> > ‘cpus_in_crash’ defined but not used
> > make[2]: *** [arch/powerpc/kernel/crash.o] Error 1
> > make[1]: *** [arch/powerpc/kernel] Error 2
> > make: *** [sub-make] Error 2

This still happens in 3.3.0-rc1 and is fixed by the patch below.

.config is here: http://nerdbynature.de/bits/3.2.0/

Thoughts?

Thanks,
Christian.

> I could not find cpus_in_crash anywhere in the sourcetree, except for 
> arch/powerpc/kernel/crash.c. Moving the definition into the CONFIG_SMP 
> ifdef helps on my UP system, of course - not sure about other machines 
> though:
> 
> diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
> index 28be345..abef751 100644
> --- a/arch/powerpc/kernel/crash.c
> +++ b/arch/powerpc/kernel/crash.c
> @@ -46,7 +46,6 @@
>  
>  /* This keeps a track of which one is the crashing cpu. */
>  int crashing_cpu = -1;
> -static atomic_t cpus_in_crash;
>  static int time_to_dump;
>  
>  #define CRASH_HANDLER_MAX 3
> @@ -66,6 +65,7 @@ static int handle_fault(struct pt_regs *regs)
>  
>  #ifdef CONFIG_SMP
>  
> +static atomic_t cpus_in_crash;
>  void crash_ipi_callback(struct pt_regs *regs)
>  {
>  	static cpumask_t cpus_state_saved = CPU_MASK_NONE;
> 
> 
> Christian.
> -- 
> BOFH excuse #272:
> 
> Netscape has crashed
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 

-- 
BOFH excuse #51:

Cosmic ray particles crashed through the hard disk platter

^ permalink raw reply

* Re: [PATCH] powerpc/booke64: Configurable lazy interrupt disabling
From: Benjamin Herrenschmidt @ 2012-01-20 23:05 UTC (permalink / raw)
  To: Stuart Yoder; +Cc: Laurentiu Tudor, linuxppc-dev
In-Reply-To: <CALRxmdA9mh6x5YGK1oFHvgmV-RsnN6WkxhpZbcRJv1S8Y0RH1w@mail.gmail.com>

On Thu, 2012-01-19 at 13:29 -0600, Stuart Yoder wrote:
> Also, Scott had posted an approach to do option #2 a while back,
> but as I  recall there was some negative feedback about this.  See:
> <http://lists.ozlabs.org/pipermail/linuxppc-dev/2011-August/092103.html>

I see... the problems with doorbells are workable tho. A reject hcall
could also raise the CPU priority to avoid lower priority interrupts for
example. The decrementer option works too.

Another approach is to do an hcall into the interrupt re-enable path
when an interrupt occurred while masked, which is what we do on i or
ps3, which could then trigger a replay.

Traditionally EE's have always been "level sensitive" on PowerPC, the
way you changed that is arguably an utterly broken HW design and I am
not too keen on changing our core interrupt handling to deal with it via
ifdef's if we can find a less invasive solution.

Cheers,
Ben.

^ permalink raw reply

* Re: [PATCH] powerpc/booke64: Configurable lazy interrupt disabling
From: Benjamin Herrenschmidt @ 2012-01-20 23:02 UTC (permalink / raw)
  To: Stuart Yoder; +Cc: Laurentiu Tudor, linuxppc-dev
In-Reply-To: <CALRxmdC_E4Z==4R_2MGHAi3T7mdF9oHx3rBE6Meb+3R1gWF5VQ@mail.gmail.com>


> With Topaz, interrupts go directly to guests and we don't want to require a
> trap/hcall to do an IACK, as that adds potentially thousands of cycles of
> latency to every interrupt.
> 
> As you know, with external proxy interrupts are acknowledged by the
> hardware and it becomes problematic to replay the interrupt in
> the context of lazy EE when interrupts are re-enabled.   The interrupt
> will not fire again when you enable EE.

So you have a broken HW and broken HV design to start with ... :-)

> That is currently the issue, as we can't run the 64-bit kernel on Topaz.
> Our option are:
>   1) to provide an option to disable lazy EE
>   2) do some kind of hack to replay interrupts with lazy EE
>   3) change Topaz to support legacy IACK, but this gets ugly for
>       various reasons.
> 
> Providing a config option to disable lazy EE seemed to be a good
> approach.

A config option is bad because it gets us yet another step toward
non-generic kernels.

Why don't you look into what would be needed to do a replay ? There are
many ways to achieve this, using the DEC is one that wouldn't involve
the hypervisor for example. But the case of an interrupt occurring while
masked is actually pretty low key so the overhead of an hcall at that
point wouldn't be too bad I beleive, so you could also implement some
kind of retry hcall which can internally be implemented using a guest
doorbell or something similar.

Cheers,
Ben.

^ permalink raw reply

* Re: [PATCH 1/2] P1025RDB: add Quicc Engine support
From: Tabi Timur-B04825 @ 2012-01-20 20:50 UTC (permalink / raw)
  To: Fan Zhicheng-B32736; +Cc: linuxppc-dev@lists.ozlabs.org, Fanzc
In-Reply-To: <1327035611-22794-1-git-send-email-B32736@freescale.com>

On Thu, Jan 19, 2012 at 11:00 PM, Zhicheng Fan <B32736@freescale.com> wrote=
:
> From: Fanzc <b32736@freeescale.com>
>
> Signed-off-by: Fanzc <b32736@freeescale.com>

Please use your full name (first and last name)

> ---
> =A0arch/powerpc/platforms/85xx/mpc85xx_rdb.c | =A0 79 +++++++++++++++++++=
+++++++++-
> =A01 files changed, 78 insertions(+), 1 deletions(-)
>
> diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/pla=
tforms/85xx/mpc85xx_rdb.c
> index 1950076..1ba67aa 100644
> --- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
> +++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
> @@ -26,6 +26,9 @@
> =A0#include <asm/prom.h>
> =A0#include <asm/udbg.h>
> =A0#include <asm/mpic.h>
> +#include <asm/qe.h>
> +#include <asm/qe_ic.h>
> +#include <asm/fsl_guts.h>
>
> =A0#include <sysdev/fsl_soc.h>
> =A0#include <sysdev/fsl_pci.h>
> @@ -47,6 +50,10 @@ void __init mpc85xx_rdb_pic_init(void)
> =A0 =A0 =A0 =A0struct mpic *mpic;
> =A0 =A0 =A0 =A0unsigned long root =3D of_get_flat_dt_root();
>
> +#ifdef CONFIG_QUICC_ENGINE
> + =A0 =A0 =A0 struct device_node *np;
> +#endif
> +
> =A0 =A0 =A0 =A0if (of_flat_dt_is_compatible(root, "fsl,MPC85XXRDB-CAMP"))=
 {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0mpic =3D mpic_alloc(NULL, 0,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0MPIC_BIG_ENDIAN | MPIC_BRO=
KEN_FRR_NIRQS |
> @@ -62,6 +69,18 @@ void __init mpc85xx_rdb_pic_init(void)
>
> =A0 =A0 =A0 =A0BUG_ON(mpic =3D=3D NULL);
> =A0 =A0 =A0 =A0mpic_init(mpic);
> +
> +#ifdef CONFIG_QUICC_ENGINE
> + =A0 =A0 =A0 np =3D of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
> + =A0 =A0 =A0 if (np) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 qe_ic_init(np, 0, qe_ic_cascade_low_mpic,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qe_ic_casca=
de_high_mpic);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 of_node_put(np);
> +
> + =A0 =A0 =A0 } else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 printk(KERN_ERR "Could not find qe-ic node\=
n");

Use pr_err instead of printk(KERN_ERR

> +#endif
> +
> =A0}
>
> =A0/*
> @@ -69,7 +88,7 @@ void __init mpc85xx_rdb_pic_init(void)
> =A0*/
> =A0static void __init mpc85xx_rdb_setup_arch(void)
> =A0{
> -#ifdef CONFIG_PCI
> +#if defined(CONFIG_PCI) || defined(CONFIG_QUICC_ENGINE)
> =A0 =A0 =A0 =A0struct device_node *np;
> =A0#endif
>
> @@ -85,6 +104,64 @@ static void __init mpc85xx_rdb_setup_arch(void)
> =A0#endif
>
> =A0 =A0 =A0 =A0mpc85xx_smp_init();
> +
> +#ifdef CONFIG_QUICC_ENGINE
> + =A0 =A0 =A0 np =3D of_find_compatible_node(NULL, NULL, "fsl,qe");
> + =A0 =A0 =A0 if (!np) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 printk(KERN_ERR "Could not find Quicc Engin=
e node\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto qe_fail;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 qe_reset();
> + =A0 =A0 =A0 of_node_put(np);
> +
> + =A0 =A0 =A0 np =3D of_find_node_by_name(NULL, "par_io");
> + =A0 =A0 =A0 if (np) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct device_node *ucc;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 par_io_init(np);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 of_node_put(np);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 for_each_node_by_name(ucc, "ucc")
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 par_io_of_config(ucc);
> +
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 if (machine_is(p1025_rdb)) {
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 __be32 __iomem *pmuxcr;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 np =3D of_find_node_by_name(NULL, "global-u=
tilities");
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (np) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pmuxcr =3D of_iomap(np, 0) =
+ MPC85xx_PMUXCR_OFFSET;

You're missing the iounmap().

--=20
Timur Tabi
Linux kernel developer at Freescale=

^ permalink raw reply

* Re: [PATCH] mtd/nand:Fix wrong usage of is_blank() in fsl_ifc_run_command
From: Scott Wood @ 2012-01-20 20:20 UTC (permalink / raw)
  To: Prabhakar Kushwaha; +Cc: linux-mtd, linuxppc-dev, Poonam Aggrwal
In-Reply-To: <1326859991-7469-1-git-send-email-prabhakar@freescale.com>

On 01/17/2012 10:13 PM, Prabhakar Kushwaha wrote:
> +		for (i = sector; i <= sector_end; i++) {
> +			errors = check_read_ecc(mtd, ctrl, eccstat, i);
> +
> +			if (errors == 15) {
> +				/*
> +				 * Uncorrectable error.
> +				 * OK only if the whole page is blank.
> +				 *
> +				 * We disable ECCER reporting due to...

s/due to.../due to/

Otherwise looks good.

-Scott

^ permalink raw reply

* Re: Cannot wake-up from standby with MPC8313
From: Scott Wood @ 2012-01-20 20:05 UTC (permalink / raw)
  To: Norbert van Bolhuis; +Cc: linuxppc-dev@ozlabs.org
In-Reply-To: <4F169BE3.30102@aimvalley.nl>

On 01/18/2012 04:16 AM, Norbert van Bolhuis wrote:
> Yes this is it!
> You mentioned mpc8313erdb bug before, I guess you had to mention it
> twice before
> I looked at mpc8313erdb bug description.
>=20
> The mpc8313erdb bug is described as follows:
>=20
> 3.5 Power management control (PMC) registers cannot be
> accessed?
> The PMC registers range from IMMR + 0x0B00 to IMMR + 0x0BFF. When this
> area is accessed in u-boot,
> the RDB hangs up. It appears that the PMC block is related to the JTAG
> interface; TRST must not be pulled
> down for normal operation of the PMC block. Possible workarounds are as
> follows:
> =95 Attach a debugger to drive TRST high during normal operation.
> =95 Remove the pull-down resistor (R37) for TRST. Although this tested =
on
> some RDBs without any
> problem, it violates the hardware specification. If it does not work on
> your RDB, use another workaround.
>=20
>=20
> I guess this is an MPC8313 problem rather than an MPC8313E-RDB problem =
?
> and I would expect it to be mentioned in MPC8313E Errata (which isn't t=
he
> case).

It is mentioned in the MPC8313E manual (4.2.2 step #10) that TRST must
not be asserted except when PORESET is asserted.  The mpc8313erdb bug
was that the board was not complying with this.

-Scott

^ permalink raw reply

* [PATCH][v3] NAND Machine support for Integrated Flash Controller
From: Prabhakar Kushwaha @ 2012-01-20 12:52 UTC (permalink / raw)
  To: linuxppc-dev, linux-mtd
  Cc: Poonam Aggrwal, Liu Shuo, Scott Wood, Dipen Dudhat,
	Prabhakar Kushwaha

Integrated Flash Controller(IFC) can be used to hook NAND Flash
chips using NAND Flash Machine available on it.

Signed-off-by: Dipen Dudhat <Dipen.Dudhat@freescale.com>
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Liu Shuo <b35362@freescale.com>
Signed-off-by: Poonam Aggrwal <poonam.aggrwal@freescale.com>
Signed-off-by: Prabhakar Kushwaha <prabhakar@freescale.com>
---
 Based upon git://git.kernel.org/pub/scm/linux/kernel/git/galak/powerpc.git (branch next)

 Tested on P1010RDB

 Changes for v2: Ported IFC driver for linux-3.2.0-rc3 
	- Use chip->bbt_options for BBT
	- Use mtd_device_parse_register instead of old parse_mtd_partitions

  Changes for v3: Squashed following patch to make singe NAND driver patch
	- mtd/nand:Fix wrong usage of is_blank() in fsl_ifc_run_command
		http://patchwork.ozlabs.org/patch/136547/
	- mtd/nand: Fix IFC driver to support 2K NAND page
		http://patchwork.ozlabs.org/patch/135010/

 drivers/mtd/nand/Kconfig        |   10 +
 drivers/mtd/nand/Makefile       |    1 +
 drivers/mtd/nand/fsl_ifc_nand.c | 1071 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 1082 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/nand/fsl_ifc_nand.c

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index cce7b70..2fff5c7 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -463,6 +463,16 @@ config MTD_NAND_FSL_ELBC
 	  Enabling this option will enable you to use this to control
 	  external NAND devices.
 
+config MTD_NAND_FSL_IFC
+	tristate "NAND support for Freescale IFC controller"
+	depends on MTD_NAND && FSL_SOC
+	select FSL_IFC
+	help
+	  Various Freescale chips e.g P1010, include a NAND Flash machine
+	  with built-in hardware ECC capabilities.
+	  Enabling this option will enable you to use this to control
+	  external NAND devices.
+
 config MTD_NAND_FSL_UPM
 	tristate "Support for NAND on Freescale UPM"
 	depends on PPC_83xx || PPC_85xx
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 618f4ba..19bc8cb 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_MTD_ALAUDA)		+= alauda.o
 obj-$(CONFIG_MTD_NAND_PASEMI)		+= pasemi_nand.o
 obj-$(CONFIG_MTD_NAND_ORION)		+= orion_nand.o
 obj-$(CONFIG_MTD_NAND_FSL_ELBC)		+= fsl_elbc_nand.o
+obj-$(CONFIG_MTD_NAND_FSL_IFC)		+= fsl_ifc_nand.o
 obj-$(CONFIG_MTD_NAND_FSL_UPM)		+= fsl_upm.o
 obj-$(CONFIG_MTD_NAND_SH_FLCTL)		+= sh_flctl.o
 obj-$(CONFIG_MTD_NAND_MXC)		+= mxc_nand.o
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
new file mode 100644
index 0000000..33b55d2
--- /dev/null
+++ b/drivers/mtd/nand/fsl_ifc_nand.c
@@ -0,0 +1,1071 @@
+/*
+ * Freescale Integrated Flash Controller NAND driver
+ *
+ * Copyright 2011,2012 Freescale Semiconductor, Inc
+ *
+ * Author: Dipen Dudhat <Dipen.Dudhat@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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand_ecc.h>
+#include <asm/fsl_ifc.h>
+
+#define ERR_BYTE		0xFF /* Value returned for read
+					bytes when read failed	*/
+#define IFC_TIMEOUT_MSECS	500  /* Maximum number of mSecs to wait
+					for IFC NAND Machine	*/
+
+struct fsl_ifc_ctrl;
+
+/* mtd information per set */
+struct fsl_ifc_mtd {
+	struct mtd_info mtd;
+	struct nand_chip chip;
+	struct fsl_ifc_ctrl *ctrl;
+
+	struct device *dev;
+	int bank;		/* Chip select bank number		*/
+	unsigned int bufnum_mask; /* bufnum = page & bufnum_mask */
+	u8 __iomem *vbase;      /* Chip select base virtual address	*/
+};
+
+/* overview of the fsl ifc controller */
+struct fsl_ifc_nand_ctrl {
+	struct nand_hw_control controller;
+	struct fsl_ifc_mtd *chips[FSL_IFC_BANK_COUNT];
+
+	u8 __iomem *addr;	/* Address of assigned IFC buffer	*/
+	unsigned int page;	/* Last page written to / read from	*/
+	unsigned int read_bytes;/* Number of bytes read during command	*/
+	unsigned int column;	/* Saved column from SEQIN		*/
+	unsigned int index;	/* Pointer to next byte to 'read'	*/
+	unsigned int oob;	/* Non zero if operating on OOB data	*/
+	unsigned int eccread;	/* Non zero for a full-page ECC read	*/
+	unsigned int counter;	/* counter for the initializations	*/
+};
+
+static struct fsl_ifc_nand_ctrl *ifc_nand_ctrl;
+
+/* 512-byte page with 4-bit ECC, 8-bit */
+static struct nand_ecclayout oob_512_8bit_ecc4 = {
+	.eccbytes = 8,
+	.eccpos = {8, 9, 10, 11, 12, 13, 14, 15},
+	.oobfree = { {0, 5}, {6, 2} },
+};
+
+/* 512-byte page with 4-bit ECC, 16-bit */
+static struct nand_ecclayout oob_512_16bit_ecc4 = {
+	.eccbytes = 8,
+	.eccpos = {8, 9, 10, 11, 12, 13, 14, 15},
+	.oobfree = { {2, 6}, },
+};
+
+/* 2048-byte page size with 4-bit ECC */
+static struct nand_ecclayout oob_2048_ecc4 = {
+	.eccbytes = 32,
+	.eccpos = {
+		8, 9, 10, 11, 12, 13, 14, 15,
+		16, 17, 18, 19, 20, 21, 22, 23,
+		24, 25, 26, 27, 28, 29, 30, 31,
+		32, 33, 34, 35, 36, 37, 38, 39,
+	},
+	.oobfree = { {2, 6}, {40, 24} },
+};
+
+/* 4096-byte page size with 4-bit ECC */
+static struct nand_ecclayout oob_4096_ecc4 = {
+	.eccbytes = 64,
+	.eccpos = {
+		8, 9, 10, 11, 12, 13, 14, 15,
+		16, 17, 18, 19, 20, 21, 22, 23,
+		24, 25, 26, 27, 28, 29, 30, 31,
+		32, 33, 34, 35, 36, 37, 38, 39,
+		40, 41, 42, 43, 44, 45, 46, 47,
+		48, 49, 50, 51, 52, 53, 54, 55,
+		56, 57, 58, 59, 60, 61, 62, 63,
+		64, 65, 66, 67, 68, 69, 70, 71,
+	},
+	.oobfree = { {2, 6}, {72, 56} },
+};
+
+/* 4096-byte page size with 8-bit ECC -- requires 218-byte OOB */
+static struct nand_ecclayout oob_4096_ecc8 = {
+	.eccbytes = 128,
+	.eccpos = {
+		8, 9, 10, 11, 12, 13, 14, 15,
+		16, 17, 18, 19, 20, 21, 22, 23,
+		24, 25, 26, 27, 28, 29, 30, 31,
+		32, 33, 34, 35, 36, 37, 38, 39,
+		40, 41, 42, 43, 44, 45, 46, 47,
+		48, 49, 50, 51, 52, 53, 54, 55,
+		56, 57, 58, 59, 60, 61, 62, 63,
+		64, 65, 66, 67, 68, 69, 70, 71,
+		72, 73, 74, 75, 76, 77, 78, 79,
+		80, 81, 82, 83, 84, 85, 86, 87,
+		88, 89, 90, 91, 92, 93, 94, 95,
+		96, 97, 98, 99, 100, 101, 102, 103,
+		104, 105, 106, 107, 108, 109, 110, 111,
+		112, 113, 114, 115, 116, 117, 118, 119,
+		120, 121, 122, 123, 124, 125, 126, 127,
+		128, 129, 130, 131, 132, 133, 134, 135,
+	},
+	.oobfree = { {2, 6}, {136, 82} },
+};
+
+
+/*
+ * Generic flash bbt descriptors
+ */
+static u8 bbt_pattern[] = {'B', 'b', 't', '0' };
+static u8 mirror_pattern[] = {'1', 't', 'b', 'B' };
+
+static struct nand_bbt_descr bbt_main_descr = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
+		   NAND_BBT_2BIT | NAND_BBT_VERSION,
+	.offs =	2, /* 0 on 8-bit small page */
+	.len = 4,
+	.veroffs = 6,
+	.maxblocks = 4,
+	.pattern = bbt_pattern,
+};
+
+static struct nand_bbt_descr bbt_mirror_descr = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
+		   NAND_BBT_2BIT | NAND_BBT_VERSION,
+	.offs =	2, /* 0 on 8-bit small page */
+	.len = 4,
+	.veroffs = 6,
+	.maxblocks = 4,
+	.pattern = mirror_pattern,
+};
+
+/*
+ * Set up the IFC hardware block and page address fields, and the ifc nand
+ * structure addr field to point to the correct IFC buffer in memory
+ */
+static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
+	int buf_num;
+
+	ifc_nand_ctrl->page = page_addr;
+	/* Program ROW0/COL0 */
+	out_be32(&ifc->ifc_nand.row0, page_addr);
+	out_be32(&ifc->ifc_nand.col0, (oob ? IFC_NAND_COL_MS : 0) | column);
+
+	buf_num = page_addr & priv->bufnum_mask;
+
+	ifc_nand_ctrl->addr = priv->vbase + buf_num * (mtd->writesize * 2);
+	ifc_nand_ctrl->index = column;
+
+	/* for OOB data point to the second half of the buffer */
+	if (oob)
+		ifc_nand_ctrl->index += mtd->writesize;
+}
+
+static int is_blank(struct mtd_info *mtd, unsigned int bufnum)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_ifc_mtd *priv = chip->priv;
+	u8 __iomem *addr = priv->vbase + bufnum * (mtd->writesize * 2);
+	u32 __iomem *mainarea = (u32 *)addr;
+	u8 __iomem *oob = addr + mtd->writesize;
+	int i;
+
+	for (i = 0; i < mtd->writesize / 4; i++) {
+		if (__raw_readl(&mainarea[i]) != 0xffffffff)
+			return 0;
+	}
+
+	for (i = 0; i < chip->ecc.layout->eccbytes; i++) {
+		int pos = chip->ecc.layout->eccpos[i];
+
+		if (__raw_readb(&oob[pos]) != 0xff)
+			return 0;
+	}
+
+	return 1;
+}
+
+/* returns nonzero if entire page is blank */
+static int check_read_ecc(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
+			  u32 *eccstat, unsigned int bufnum)
+{
+	u32 reg = eccstat[bufnum / 4];
+	int errors;
+
+	errors = (reg >> ((3 - bufnum % 4) * 8)) & 15;
+
+	return errors;
+}
+
+/*
+ * execute IFC NAND command and wait for it to complete
+ */
+static void fsl_ifc_run_command(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl;
+	struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
+	u32 eccstat[4];
+	int i;
+
+	/* set the chip select for NAND Transaction */
+	out_be32(&ifc->ifc_nand.nand_csel, priv->bank << IFC_NAND_CSEL_SHIFT);
+
+	dev_vdbg(priv->dev,
+			"%s: fir0=%08x fcr0=%08x\n",
+			__func__,
+			in_be32(&ifc->ifc_nand.nand_fir0),
+			in_be32(&ifc->ifc_nand.nand_fcr0));
+
+	ctrl->nand_stat = 0;
+
+	/* start read/write seq */
+	out_be32(&ifc->ifc_nand.nandseq_strt, IFC_NAND_SEQ_STRT_FIR_STRT);
+
+	/* wait for command complete flag or timeout */
+	wait_event_timeout(ctrl->nand_wait, ctrl->nand_stat,
+			   IFC_TIMEOUT_MSECS * HZ/1000);
+
+	if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_FTOER)
+		dev_err(priv->dev, "NAND Flash Timeout Error\n");
+	if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_WPER)
+		dev_err(priv->dev, "NAND Flash Write Protect Error\n");
+
+	if (nctrl->eccread) {
+		int errors;
+		int bufnum = nctrl->page & priv->bufnum_mask;
+		int sector = bufnum * chip->ecc.steps;
+		int sector_end = sector + chip->ecc.steps - 1;
+
+		for (i = sector / 4; i <= sector_end / 4; i++)
+			eccstat[i] = in_be32(&ifc->ifc_nand.nand_eccstat[i]);
+
+		for (i = sector; i <= sector_end; i++) {
+			errors = check_read_ecc(mtd, ctrl, eccstat, i);
+
+			if (errors == 15) {
+				/*
+				 * Uncorrectable error.
+				 * OK only if the whole page is blank.
+				 *
+				 * We disable ECCER reporting due to...
+				 * erratum IFC-A002770 -- so report it now if we
+				 * see an uncorrectable error in ECCSTAT.
+				 */
+				if (!is_blank(mtd, bufnum))
+					ctrl->nand_stat |=
+						IFC_NAND_EVTER_STAT_ECCER;
+				break;
+			}
+
+			mtd->ecc_stats.corrected += errors;
+		}
+
+		nctrl->eccread = 0;
+	}
+}
+
+static void fsl_ifc_do_read(struct nand_chip *chip,
+			    int oob,
+			    struct mtd_info *mtd)
+{
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
+
+	/* Program FIR/IFC_NAND_FCR0 for Small/Large page */
+	if (mtd->writesize > 512) {
+		out_be32(&ifc->ifc_nand.nand_fir0,
+			 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+			 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+			 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
+			 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) |
+			 (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP4_SHIFT));
+		out_be32(&ifc->ifc_nand.nand_fir1, 0x0);
+
+		out_be32(&ifc->ifc_nand.nand_fcr0,
+			(NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) |
+			(NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT));
+	} else {
+		out_be32(&ifc->ifc_nand.nand_fir0,
+			 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+			 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+			 (IFC_FIR_OP_RA0  << IFC_NAND_FIR0_OP2_SHIFT) |
+			 (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP3_SHIFT));
+		out_be32(&ifc->ifc_nand.nand_fir1, 0x0);
+
+		if (oob)
+			out_be32(&ifc->ifc_nand.nand_fcr0,
+				 NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT);
+		else
+			out_be32(&ifc->ifc_nand.nand_fcr0,
+				NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
+	}
+}
+
+/* cmdfunc send commands to the IFC NAND Machine */
+static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
+			     int column, int page_addr) {
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
+
+	/* clear the read buffer */
+	ifc_nand_ctrl->read_bytes = 0;
+	if (command != NAND_CMD_PAGEPROG)
+		ifc_nand_ctrl->index = 0;
+
+	switch (command) {
+	/* READ0 read the entire buffer to use hardware ECC. */
+	case NAND_CMD_READ0:
+		out_be32(&ifc->ifc_nand.nand_fbcr, 0);
+		set_addr(mtd, 0, page_addr, 0);
+
+		ifc_nand_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+		ifc_nand_ctrl->index += column;
+
+		if (chip->ecc.mode == NAND_ECC_HW)
+			ifc_nand_ctrl->eccread = 1;
+
+		fsl_ifc_do_read(chip, 0, mtd);
+		fsl_ifc_run_command(mtd);
+		return;
+
+	/* READOOB reads only the OOB because no ECC is performed. */
+	case NAND_CMD_READOOB:
+		out_be32(&ifc->ifc_nand.nand_fbcr, mtd->oobsize - column);
+		set_addr(mtd, column, page_addr, 1);
+
+		ifc_nand_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+
+		fsl_ifc_do_read(chip, 1, mtd);
+		fsl_ifc_run_command(mtd);
+
+		return;
+
+	/* READID must read all 8 possible bytes */
+	case NAND_CMD_READID:
+		out_be32(&ifc->ifc_nand.nand_fir0,
+				(IFC_FIR_OP_CMD0 << IFC_NAND_FIR0_OP0_SHIFT) |
+				(IFC_FIR_OP_UA  << IFC_NAND_FIR0_OP1_SHIFT) |
+				(IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT));
+		out_be32(&ifc->ifc_nand.nand_fcr0,
+				NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT);
+		/* 8 bytes for manuf, device and exts */
+		out_be32(&ifc->ifc_nand.nand_fbcr, 8);
+		ifc_nand_ctrl->read_bytes = 8;
+
+		set_addr(mtd, 0, 0, 0);
+		fsl_ifc_run_command(mtd);
+		return;
+
+	/* ERASE1 stores the block and page address */
+	case NAND_CMD_ERASE1:
+		set_addr(mtd, 0, page_addr, 0);
+		return;
+
+	/* ERASE2 uses the block and page address from ERASE1 */
+	case NAND_CMD_ERASE2:
+		out_be32(&ifc->ifc_nand.nand_fir0,
+			 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+			 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+			 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP2_SHIFT));
+
+		out_be32(&ifc->ifc_nand.nand_fcr0,
+			 (NAND_CMD_ERASE1 << IFC_NAND_FCR0_CMD0_SHIFT) |
+			 (NAND_CMD_ERASE2 << IFC_NAND_FCR0_CMD1_SHIFT));
+
+		out_be32(&ifc->ifc_nand.nand_fbcr, 0);
+		ifc_nand_ctrl->read_bytes = 0;
+		fsl_ifc_run_command(mtd);
+		return;
+
+	/* SEQIN sets up the addr buffer and all registers except the length */
+	case NAND_CMD_SEQIN: {
+		u32 nand_fcr0;
+		ifc_nand_ctrl->column = column;
+		ifc_nand_ctrl->oob = 0;
+
+		if (mtd->writesize > 512) {
+			nand_fcr0 =
+				(NAND_CMD_SEQIN << IFC_NAND_FCR0_CMD0_SHIFT) |
+				(NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD1_SHIFT);
+
+			out_be32(&ifc->ifc_nand.nand_fir0,
+				 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+				 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+				 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
+				 (IFC_FIR_OP_WBCD  << IFC_NAND_FIR0_OP3_SHIFT) |
+				 (IFC_FIR_OP_CW1 << IFC_NAND_FIR0_OP4_SHIFT));
+		} else {
+			nand_fcr0 = ((NAND_CMD_PAGEPROG <<
+					IFC_NAND_FCR0_CMD1_SHIFT) |
+				    (NAND_CMD_SEQIN <<
+					IFC_NAND_FCR0_CMD2_SHIFT));
+
+			out_be32(&ifc->ifc_nand.nand_fir0,
+				 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+				 (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP1_SHIFT) |
+				 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP2_SHIFT) |
+				 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) |
+				 (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT));
+			out_be32(&ifc->ifc_nand.nand_fir1,
+				 (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT));
+
+			if (column >= mtd->writesize)
+				nand_fcr0 |=
+				NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT;
+			else
+				nand_fcr0 |=
+				NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT;
+		}
+
+		if (column >= mtd->writesize) {
+			/* OOB area --> READOOB */
+			column -= mtd->writesize;
+			ifc_nand_ctrl->oob = 1;
+		}
+		out_be32(&ifc->ifc_nand.nand_fcr0, nand_fcr0);
+		set_addr(mtd, column, page_addr, ifc_nand_ctrl->oob);
+		return;
+	}
+
+	/* PAGEPROG reuses all of the setup from SEQIN and adds the length */
+	case NAND_CMD_PAGEPROG: {
+		int full_page;
+		if (ifc_nand_ctrl->oob) {
+			out_be32(&ifc->ifc_nand.nand_fbcr,
+				ifc_nand_ctrl->index - ifc_nand_ctrl->column);
+			full_page = 0;
+		} else {
+			out_be32(&ifc->ifc_nand.nand_fbcr, 0);
+			full_page = 1;
+		}
+
+		fsl_ifc_run_command(mtd);
+		return;
+	}
+
+	case NAND_CMD_STATUS:
+		out_be32(&ifc->ifc_nand.nand_fir0,
+				(IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+				(IFC_FIR_OP_RB << IFC_NAND_FIR0_OP1_SHIFT));
+		out_be32(&ifc->ifc_nand.nand_fcr0,
+				NAND_CMD_STATUS << IFC_NAND_FCR0_CMD0_SHIFT);
+		out_be32(&ifc->ifc_nand.nand_fbcr, 1);
+		set_addr(mtd, 0, 0, 0);
+		ifc_nand_ctrl->read_bytes = 1;
+
+		fsl_ifc_run_command(mtd);
+
+		/*
+		 * The chip always seems to report that it is
+		 * write-protected, even when it is not.
+		 */
+		setbits8(ifc_nand_ctrl->addr, NAND_STATUS_WP);
+		return;
+
+	case NAND_CMD_RESET:
+		out_be32(&ifc->ifc_nand.nand_fir0,
+				IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT);
+		out_be32(&ifc->ifc_nand.nand_fcr0,
+				NAND_CMD_RESET << IFC_NAND_FCR0_CMD0_SHIFT);
+		fsl_ifc_run_command(mtd);
+		return;
+
+	default:
+		dev_err(priv->dev, "%s: error, unsupported command 0x%x.\n",
+					__func__, command);
+	}
+}
+
+static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
+{
+	/* The hardware does not seem to support multiple
+	 * chips per bank.
+	 */
+}
+
+/*
+ * Write buf to the IFC NAND Controller Data Buffer
+ */
+static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_ifc_mtd *priv = chip->priv;
+	unsigned int bufsize = mtd->writesize + mtd->oobsize;
+
+	if (len <= 0) {
+		dev_err(priv->dev, "%s: len %d bytes", __func__, len);
+		return;
+	}
+
+	if ((unsigned int)len > bufsize - ifc_nand_ctrl->index) {
+		dev_err(priv->dev,
+			"%s: beyond end of buffer (%d requested, %u available)\n",
+			__func__, len, bufsize - ifc_nand_ctrl->index);
+		len = bufsize - ifc_nand_ctrl->index;
+	}
+
+	memcpy_toio(&ifc_nand_ctrl->addr[ifc_nand_ctrl->index], buf, len);
+	ifc_nand_ctrl->index += len;
+}
+
+/*
+ * Read a byte from either the IFC hardware buffer
+ * read function for 8-bit buswidth
+ */
+static uint8_t fsl_ifc_read_byte(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_ifc_mtd *priv = chip->priv;
+
+	/*
+	 * If there are still bytes in the IFC buffer, then use the
+	 * next byte.
+	 */
+	if (ifc_nand_ctrl->index < ifc_nand_ctrl->read_bytes)
+		return in_8(&ifc_nand_ctrl->addr[ifc_nand_ctrl->index++]);
+
+	dev_err(priv->dev, "%s: beyond end of buffer\n", __func__);
+	return ERR_BYTE;
+}
+
+/*
+ * Read two bytes from the IFC hardware buffer
+ * read function for 16-bit buswith
+ */
+static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_ifc_mtd *priv = chip->priv;
+	uint16_t data;
+
+	/*
+	 * If there are still bytes in the IFC buffer, then use the
+	 * next byte.
+	 */
+	if (ifc_nand_ctrl->index < ifc_nand_ctrl->read_bytes) {
+		data = in_be16((uint16_t *)&ifc_nand_ctrl->
+					addr[ifc_nand_ctrl->index]);
+		ifc_nand_ctrl->index += 2;
+		return (uint8_t) data;
+	}
+
+	dev_err(priv->dev, "%s: beyond end of buffer\n", __func__);
+	return ERR_BYTE;
+}
+
+/*
+ * Read from the IFC Controller Data Buffer
+ */
+static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_ifc_mtd *priv = chip->priv;
+	int avail;
+
+	if (len < 0) {
+		dev_err(priv->dev, "%s: len %d bytes", __func__, len);
+		return;
+	}
+
+	avail = min((unsigned int)len,
+			ifc_nand_ctrl->read_bytes - ifc_nand_ctrl->index);
+	memcpy_fromio(buf, &ifc_nand_ctrl->addr[ifc_nand_ctrl->index], avail);
+	ifc_nand_ctrl->index += avail;
+
+	if (len > avail)
+		dev_err(priv->dev,
+			"%s: beyond end of buffer (%d requested, %d available)\n",
+			__func__, len, avail);
+}
+
+/*
+ * Verify buffer against the IFC Controller Data Buffer
+ */
+static int fsl_ifc_verify_buf(struct mtd_info *mtd,
+			       const u_char *buf, int len)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl;
+	int i;
+
+	if (len < 0) {
+		dev_err(priv->dev, "%s: write_buf of %d bytes", __func__, len);
+		return -EINVAL;
+	}
+
+	if ((unsigned int)len > nctrl->read_bytes - nctrl->index) {
+		dev_err(priv->dev,
+			"%s: beyond end of buffer (%d requested, %u available)\n",
+			__func__, len, nctrl->read_bytes - nctrl->index);
+
+		nctrl->index = nctrl->read_bytes;
+		return -EINVAL;
+	}
+
+	for (i = 0; i < len; i++)
+		if (in_8(&nctrl->addr[nctrl->index + i]) != buf[i])
+			break;
+
+	nctrl->index += len;
+
+	if (i != len)
+		return -EIO;
+	if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC)
+		return -EIO;
+
+	return 0;
+}
+
+/*
+ * This function is called after Program and Erase Operations to
+ * check for success or failure.
+ */
+static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
+{
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
+	u32 nand_fsr;
+
+	/* Use READ_STATUS command, but wait for the device to be ready */
+	out_be32(&ifc->ifc_nand.nand_fir0,
+		 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+		 (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR0_OP1_SHIFT));
+	out_be32(&ifc->ifc_nand.nand_fcr0, NAND_CMD_STATUS <<
+			IFC_NAND_FCR0_CMD0_SHIFT);
+	out_be32(&ifc->ifc_nand.nand_fbcr, 1);
+	set_addr(mtd, 0, 0, 0);
+	ifc_nand_ctrl->read_bytes = 1;
+
+	fsl_ifc_run_command(mtd);
+
+	nand_fsr = in_be32(&ifc->ifc_nand.nand_fsr);
+
+	/*
+	 * The chip always seems to report that it is
+	 * write-protected, even when it is not.
+	 */
+	return nand_fsr | NAND_STATUS_WP;
+}
+
+static int fsl_ifc_read_page(struct mtd_info *mtd,
+			      struct nand_chip *chip,
+			      uint8_t *buf, int page)
+{
+	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+
+	fsl_ifc_read_buf(mtd, buf, mtd->writesize);
+	fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+	if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC) {
+		dev_err(priv->dev, "NAND Flash Write Protect Error\n");
+		mtd->ecc_stats.failed++;
+	}
+
+	return 0;
+}
+
+/* ECC will be calculated automatically, and errors will be detected in
+ * waitfunc.
+ */
+static void fsl_ifc_write_page(struct mtd_info *mtd,
+				struct nand_chip *chip,
+				const uint8_t *buf)
+{
+	fsl_ifc_write_buf(mtd, buf, mtd->writesize);
+	fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
+}
+
+static int fsl_ifc_chip_init_tail(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_ifc_mtd *priv = chip->priv;
+
+	dev_dbg(priv->dev, "%s: nand->numchips = %d\n", __func__,
+							chip->numchips);
+	dev_dbg(priv->dev, "%s: nand->chipsize = %lld\n", __func__,
+							chip->chipsize);
+	dev_dbg(priv->dev, "%s: nand->pagemask = %8x\n", __func__,
+							chip->pagemask);
+	dev_dbg(priv->dev, "%s: nand->chip_delay = %d\n", __func__,
+							chip->chip_delay);
+	dev_dbg(priv->dev, "%s: nand->badblockpos = %d\n", __func__,
+							chip->badblockpos);
+	dev_dbg(priv->dev, "%s: nand->chip_shift = %d\n", __func__,
+							chip->chip_shift);
+	dev_dbg(priv->dev, "%s: nand->page_shift = %d\n", __func__,
+							chip->page_shift);
+	dev_dbg(priv->dev, "%s: nand->phys_erase_shift = %d\n", __func__,
+							chip->phys_erase_shift);
+	dev_dbg(priv->dev, "%s: nand->ecclayout = %p\n", __func__,
+							chip->ecclayout);
+	dev_dbg(priv->dev, "%s: nand->ecc.mode = %d\n", __func__,
+							chip->ecc.mode);
+	dev_dbg(priv->dev, "%s: nand->ecc.steps = %d\n", __func__,
+							chip->ecc.steps);
+	dev_dbg(priv->dev, "%s: nand->ecc.bytes = %d\n", __func__,
+							chip->ecc.bytes);
+	dev_dbg(priv->dev, "%s: nand->ecc.total = %d\n", __func__,
+							chip->ecc.total);
+	dev_dbg(priv->dev, "%s: nand->ecc.layout = %p\n", __func__,
+							chip->ecc.layout);
+	dev_dbg(priv->dev, "%s: mtd->flags = %08x\n", __func__, mtd->flags);
+	dev_dbg(priv->dev, "%s: mtd->size = %lld\n", __func__, mtd->size);
+	dev_dbg(priv->dev, "%s: mtd->erasesize = %d\n", __func__,
+							mtd->erasesize);
+	dev_dbg(priv->dev, "%s: mtd->writesize = %d\n", __func__,
+							mtd->writesize);
+	dev_dbg(priv->dev, "%s: mtd->oobsize = %d\n", __func__,
+							mtd->oobsize);
+
+	return 0;
+}
+
+static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
+{
+	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+	struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
+	struct nand_chip *chip = &priv->chip;
+	struct nand_ecclayout *layout;
+	u32 csor;
+
+	/* Fill in fsl_ifc_mtd structure */
+	priv->mtd.priv = chip;
+	priv->mtd.owner = THIS_MODULE;
+
+	/* fill in nand_chip structure */
+	/* set up function call table */
+	if ((in_be32(&ifc->cspr_cs[priv->bank].cspr)) & CSPR_PORT_SIZE_16)
+		chip->read_byte = fsl_ifc_read_byte16;
+	else
+		chip->read_byte = fsl_ifc_read_byte;
+
+	chip->write_buf = fsl_ifc_write_buf;
+	chip->read_buf = fsl_ifc_read_buf;
+	chip->verify_buf = fsl_ifc_verify_buf;
+	chip->select_chip = fsl_ifc_select_chip;
+	chip->cmdfunc = fsl_ifc_cmdfunc;
+	chip->waitfunc = fsl_ifc_wait;
+
+	chip->bbt_td = &bbt_main_descr;
+	chip->bbt_md = &bbt_mirror_descr;
+
+	out_be32(&ifc->ifc_nand.ncfgr, 0x0);
+
+	/* set up nand options */
+	chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR;
+	chip->bbt_options = NAND_BBT_USE_FLASH;
+
+
+	if (in_be32(&ifc->cspr_cs[priv->bank].cspr) & CSPR_PORT_SIZE_16) {
+		chip->read_byte = fsl_ifc_read_byte16;
+		chip->options |= NAND_BUSWIDTH_16;
+	} else {
+		chip->read_byte = fsl_ifc_read_byte;
+	}
+
+	chip->controller = &ifc_nand_ctrl->controller;
+	chip->priv = priv;
+
+	chip->ecc.read_page = fsl_ifc_read_page;
+	chip->ecc.write_page = fsl_ifc_write_page;
+
+	csor = in_be32(&ifc->csor_cs[priv->bank].csor);
+
+	/* Hardware generates ECC per 512 Bytes */
+	chip->ecc.size = 512;
+	chip->ecc.bytes = 8;
+
+	switch (csor & CSOR_NAND_PGS_MASK) {
+	case CSOR_NAND_PGS_512:
+		if (chip->options & NAND_BUSWIDTH_16) {
+			layout = &oob_512_16bit_ecc4;
+		} else {
+			layout = &oob_512_8bit_ecc4;
+
+			/* Avoid conflict with bad block marker */
+			bbt_main_descr.offs = 0;
+			bbt_mirror_descr.offs = 0;
+		}
+
+		priv->bufnum_mask = 15;
+		break;
+
+	case CSOR_NAND_PGS_2K:
+		layout = &oob_2048_ecc4;
+		priv->bufnum_mask = 3;
+		break;
+
+	case CSOR_NAND_PGS_4K:
+		if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
+		    CSOR_NAND_ECC_MODE_4) {
+			layout = &oob_4096_ecc4;
+		} else {
+			layout = &oob_4096_ecc8;
+			chip->ecc.bytes = 16;
+		}
+
+		priv->bufnum_mask = 1;
+		break;
+
+	default:
+		dev_err(priv->dev, "bad csor %#x: bad page size\n", csor);
+		return -ENODEV;
+	}
+
+	/* Must also set CSOR_NAND_ECC_ENC_EN if DEC_EN set */
+	if (csor & CSOR_NAND_ECC_DEC_EN) {
+		chip->ecc.mode = NAND_ECC_HW;
+		chip->ecc.layout = layout;
+	} else {
+		chip->ecc.mode = NAND_ECC_SOFT;
+	}
+
+	return 0;
+}
+
+static int fsl_ifc_chip_remove(struct fsl_ifc_mtd *priv)
+{
+	nand_release(&priv->mtd);
+
+	kfree(priv->mtd.name);
+
+	if (priv->vbase)
+		iounmap(priv->vbase);
+
+	ifc_nand_ctrl->chips[priv->bank] = NULL;
+	dev_set_drvdata(priv->dev, NULL);
+	kfree(priv);
+
+	return 0;
+}
+
+static int match_bank(struct fsl_ifc_regs __iomem *ifc, int bank,
+		      phys_addr_t addr)
+{
+	u32 cspr = in_be32(&ifc->cspr_cs[bank].cspr);
+
+	if (!(cspr & CSPR_V))
+		return 0;
+	if ((cspr & CSPR_MSEL) != CSPR_MSEL_NAND)
+		return 0;
+
+	return (cspr & CSPR_BA) == convert_ifc_address(addr);
+}
+
+static DEFINE_MUTEX(fsl_ifc_nand_mutex);
+
+static int __devinit fsl_ifc_nand_probe(struct platform_device *dev)
+{
+	struct fsl_ifc_regs __iomem *ifc;
+	struct fsl_ifc_mtd *priv;
+	struct resource res;
+	static const char *part_probe_types[]
+		= { "cmdlinepart", "RedBoot", "ofpart", NULL };
+	int ret;
+	int bank;
+	struct device_node *node = dev->dev.of_node;
+	struct mtd_part_parser_data ppdata;
+
+	ppdata.of_node = dev->dev.of_node;
+	if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->regs)
+		return -ENODEV;
+	ifc = fsl_ifc_ctrl_dev->regs;
+
+	/* get, allocate and map the memory resource */
+	ret = of_address_to_resource(node, 0, &res);
+	if (ret) {
+		dev_err(&dev->dev, "%s: failed to get resource\n", __func__);
+		return ret;
+	}
+
+	/* find which chip select it is connected to */
+	for (bank = 0; bank < FSL_IFC_BANK_COUNT; bank++) {
+		if (match_bank(ifc, bank, res.start))
+			break;
+	}
+
+	if (bank >= FSL_IFC_BANK_COUNT) {
+		dev_err(&dev->dev, "%s: address did not match any chip selects\n",
+			__func__);
+		return -ENODEV;
+	}
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	mutex_lock(&fsl_ifc_nand_mutex);
+	if (!fsl_ifc_ctrl_dev->nand) {
+		ifc_nand_ctrl = kzalloc(sizeof(*ifc_nand_ctrl), GFP_KERNEL);
+		if (!ifc_nand_ctrl) {
+			dev_err(&dev->dev, "failed to allocate memory\n");
+			mutex_unlock(&fsl_ifc_nand_mutex);
+			return -ENOMEM;
+		}
+
+		ifc_nand_ctrl->read_bytes = 0;
+		ifc_nand_ctrl->index = 0;
+		ifc_nand_ctrl->addr = NULL;
+		fsl_ifc_ctrl_dev->nand = ifc_nand_ctrl;
+
+		spin_lock_init(&ifc_nand_ctrl->controller.lock);
+		init_waitqueue_head(&ifc_nand_ctrl->controller.wq);
+	} else {
+		ifc_nand_ctrl = fsl_ifc_ctrl_dev->nand;
+	}
+	mutex_unlock(&fsl_ifc_nand_mutex);
+
+	ifc_nand_ctrl->chips[bank] = priv;
+	priv->bank = bank;
+	priv->ctrl = fsl_ifc_ctrl_dev;
+	priv->dev = &dev->dev;
+
+	priv->vbase = ioremap(res.start, resource_size(&res));
+	if (!priv->vbase) {
+		dev_err(priv->dev, "%s: failed to map chip region\n", __func__);
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	dev_set_drvdata(priv->dev, priv);
+
+	out_be32(&ifc->ifc_nand.nand_evter_en,
+			IFC_NAND_EVTER_EN_OPC_EN |
+			IFC_NAND_EVTER_EN_FTOER_EN |
+			IFC_NAND_EVTER_EN_WPER_EN);
+
+	/* enable NAND Machine Interrupts */
+	out_be32(&ifc->ifc_nand.nand_evter_intr_en,
+			IFC_NAND_EVTER_INTR_OPCIR_EN |
+			IFC_NAND_EVTER_INTR_FTOERIR_EN |
+			IFC_NAND_EVTER_INTR_WPERIR_EN);
+
+	priv->mtd.name = kasprintf(GFP_KERNEL, "%x.flash", (unsigned)res.start);
+	if (!priv->mtd.name) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	ret = fsl_ifc_chip_init(priv);
+	if (ret)
+		goto err;
+
+	ret = nand_scan_ident(&priv->mtd, 1, NULL);
+	if (ret)
+		goto err;
+
+	ret = fsl_ifc_chip_init_tail(&priv->mtd);
+	if (ret)
+		goto err;
+
+	ret = nand_scan_tail(&priv->mtd);
+	if (ret)
+		goto err;
+
+	/* First look for RedBoot table or partitions on the command
+	 * line, these take precedence over device tree information */
+	mtd_device_parse_register(&priv->mtd, part_probe_types, &ppdata,
+						NULL, 0);
+
+	dev_info(priv->dev, "IFC NAND device at 0x%llx, bank %d\n",
+		 (unsigned long long)res.start, priv->bank);
+	return 0;
+
+err:
+	fsl_ifc_chip_remove(priv);
+	return ret;
+}
+
+static int fsl_ifc_nand_remove(struct platform_device *dev)
+{
+	struct fsl_ifc_mtd *priv = dev_get_drvdata(&dev->dev);
+
+	fsl_ifc_chip_remove(priv);
+
+	mutex_lock(&fsl_ifc_nand_mutex);
+	ifc_nand_ctrl->counter--;
+	if (!ifc_nand_ctrl->counter) {
+		fsl_ifc_ctrl_dev->nand = NULL;
+		kfree(ifc_nand_ctrl);
+	}
+	mutex_unlock(&fsl_ifc_nand_mutex);
+
+	return 0;
+}
+
+static const struct of_device_id fsl_ifc_nand_match[] = {
+	{
+		.compatible = "fsl,ifc-nand",
+	},
+	{}
+};
+
+static struct platform_driver fsl_ifc_nand_driver = {
+	.driver = {
+		.name	= "fsl,ifc-nand",
+		.owner = THIS_MODULE,
+		.of_match_table = fsl_ifc_nand_match,
+	},
+	.probe       = fsl_ifc_nand_probe,
+	.remove      = fsl_ifc_nand_remove,
+};
+
+static int __init fsl_ifc_nand_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&fsl_ifc_nand_driver);
+	if (ret)
+		printk(KERN_ERR "fsl-ifc: Failed to register platform"
+				"driver\n");
+
+	return ret;
+}
+
+static void __exit fsl_ifc_nand_exit(void)
+{
+	platform_driver_unregister(&fsl_ifc_nand_driver);
+}
+
+module_init(fsl_ifc_nand_init);
+module_exit(fsl_ifc_nand_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Freescale");
+MODULE_DESCRIPTION("Freescale Integrated Flash Controller MTD NAND driver");
-- 
1.7.5.4

^ permalink raw reply related

* Re: linux-next: build failure after merge of the final tree
From: Deepthi Dharwar @ 2012-01-20  9:08 UTC (permalink / raw)
  To: Stephen Rothwell
  Cc: Trinabh Gupta, Arun R Bharadwaj, linux-kernel, linux-next,
	Paul Mackerras, linuxppc-dev
In-Reply-To: <20120120182117.01a6eb5d3cfb3f2bdfb32ae4@canb.auug.org.au>

On 01/20/2012 12:51 PM, Stephen Rothwell wrote:

> Hi all,
> 
> After merging the final tree, today's linux-next build (powerpc
> allmodconfig) failed like this:
> 
> arch/powerpc/platforms/pseries/processor_idle.c:35:6: error: redefinition of 'update_smt_snooze_delay'
> arch/powerpc/include/asm/system.h:230:20: note: previous definition of 'update_smt_snooze_delay' was here
> arch/powerpc/platforms/pseries/processor_idle.c:175:5: error: redefinition of 'pseries_notify_cpuidle_add_cpu'
> arch/powerpc/include/asm/system.h:231:19: note: previous definition of 'pseries_notify_cpuidle_add_cpu' was here
> 
> Caused by commit 707827f3387d ("powerpc/cpuidle: cpuidle driver for
> pSeries").  For this build, CONFIG_PSERIES_IDLE is "m".
> 
> 
> 
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev




Hi Stephen,

We had a discussion on this particular problem on ppcdev list a few
days back and concluded that it is best not have pseries_idle
as a module.

http://old.nabble.com/-PATCH--cpuidle%3A-Default-y-for-pseries-to33118294.html#a33127587

The following patch disables pseries cpuidle driver to be loaded as a
module as there are build problems reported when one is trying to do so.

arch/powerpc/platforms/pseries/processor_idle.c:35:6: error:
redefinition of 'update_smt_snooze_delay'
arch/powerpc/include/asm/system.h:230:20: note:
previous definition of 'update_smt_snooze_delay' was here
arch/powerpc/platforms/pseries/processor_idle.c:175:5:
error: redefinition of 'pseries_notify_cpuidle_add_cpu'
arch/powerpc/include/asm/system.h:231:19: note:
previous definition of 'pseries_notify_cpuidle_add_cpu' was here

Since the above two functions
are used in core power architecture functions (store_smt_snooze_delay
at kernel/sysfs.c and smp_xics_setup_cpu at platforms/pseries/smp.c),
this requires some rework in these interactions. For now please
disable PSERIES_IDLE to be built as a module for now.

Signed-off-by: Deepthi Dharwar <deepthi@linux.vnet.ibm.com>
---
 arch/powerpc/platforms/pseries/Kconfig |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/Kconfig
b/arch/powerpc/platforms/pseries/Kconfig
index ae7b6d4..31f22c1 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -122,7 +122,7 @@ config DTL
 	  Say N if you are unsure.

 config PSERIES_IDLE
-	tristate "Cpuidle driver for pSeries platforms"
+	bool "Cpuidle driver for pSeries platforms"
 	depends on CPU_IDLE
 	depends on PPC_PSERIES
 	default y

Regards,
Deepthi

^ permalink raw reply related

* linux-next: build failure after merge of the final tree
From: Stephen Rothwell @ 2012-01-20  7:21 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Paul Mackerras, linuxppc-dev
  Cc: Deepthi Dharwar, Arun R Bharadwaj, linux-next, linux-kernel,
	Trinabh Gupta

[-- Attachment #1: Type: text/plain, Size: 750 bytes --]

Hi all,

After merging the final tree, today's linux-next build (powerpc
allmodconfig) failed like this:

arch/powerpc/platforms/pseries/processor_idle.c:35:6: error: redefinition of 'update_smt_snooze_delay'
arch/powerpc/include/asm/system.h:230:20: note: previous definition of 'update_smt_snooze_delay' was here
arch/powerpc/platforms/pseries/processor_idle.c:175:5: error: redefinition of 'pseries_notify_cpuidle_add_cpu'
arch/powerpc/include/asm/system.h:231:19: note: previous definition of 'pseries_notify_cpuidle_add_cpu' was here

Caused by commit 707827f3387d ("powerpc/cpuidle: cpuidle driver for
pSeries").  For this build, CONFIG_PSERIES_IDLE is "m".

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* [PATCH 1/2] P1025RDB: add Quicc Engine support
From: Zhicheng Fan @ 2012-01-20  5:00 UTC (permalink / raw)
  To: galak, linuxppc-dev; +Cc: Fanzc

From: Fanzc <b32736@freeescale.com>

Signed-off-by: Fanzc <b32736@freeescale.com>
---
 arch/powerpc/platforms/85xx/mpc85xx_rdb.c |   79 ++++++++++++++++++++++++++++-
 1 files changed, 78 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
index 1950076..1ba67aa 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
@@ -26,6 +26,9 @@
 #include <asm/prom.h>
 #include <asm/udbg.h>
 #include <asm/mpic.h>
+#include <asm/qe.h>
+#include <asm/qe_ic.h>
+#include <asm/fsl_guts.h>
 
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
@@ -47,6 +50,10 @@ void __init mpc85xx_rdb_pic_init(void)
 	struct mpic *mpic;
 	unsigned long root = of_get_flat_dt_root();
 
+#ifdef CONFIG_QUICC_ENGINE
+	struct device_node *np;
+#endif
+
 	if (of_flat_dt_is_compatible(root, "fsl,MPC85XXRDB-CAMP")) {
 		mpic = mpic_alloc(NULL, 0,
 			MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS |
@@ -62,6 +69,18 @@ void __init mpc85xx_rdb_pic_init(void)
 
 	BUG_ON(mpic == NULL);
 	mpic_init(mpic);
+
+#ifdef CONFIG_QUICC_ENGINE
+	np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
+	if (np) {
+		qe_ic_init(np, 0, qe_ic_cascade_low_mpic,
+				qe_ic_cascade_high_mpic);
+		of_node_put(np);
+
+	} else
+		printk(KERN_ERR "Could not find qe-ic node\n");
+#endif
+
 }
 
 /*
@@ -69,7 +88,7 @@ void __init mpc85xx_rdb_pic_init(void)
  */
 static void __init mpc85xx_rdb_setup_arch(void)
 {
-#ifdef CONFIG_PCI
+#if defined(CONFIG_PCI) || defined(CONFIG_QUICC_ENGINE)
 	struct device_node *np;
 #endif
 
@@ -85,6 +104,64 @@ static void __init mpc85xx_rdb_setup_arch(void)
 #endif
 
 	mpc85xx_smp_init();
+
+#ifdef CONFIG_QUICC_ENGINE
+	np = of_find_compatible_node(NULL, NULL, "fsl,qe");
+	if (!np) {
+		printk(KERN_ERR "Could not find Quicc Engine node\n");
+		goto qe_fail;
+	}
+
+	qe_reset();
+	of_node_put(np);
+
+	np = of_find_node_by_name(NULL, "par_io");
+	if (np) {
+		struct device_node *ucc;
+
+		par_io_init(np);
+		of_node_put(np);
+
+		for_each_node_by_name(ucc, "ucc")
+			par_io_of_config(ucc);
+
+	}
+	if (machine_is(p1025_rdb)) {
+
+		__be32 __iomem *pmuxcr;
+
+		np = of_find_node_by_name(NULL, "global-utilities");
+
+		if (np) {
+			pmuxcr = of_iomap(np, 0) + MPC85xx_PMUXCR_OFFSET;
+
+			if (!pmuxcr)
+				pr_err(KERN_EMERG "Error: Alternate function"
+					" signal multiplex control register not"
+					" mapped!\n");
+			else {
+#if defined(CONFIG_UCC_GETH) || defined(CONFIG_SERIAL_QE)
+			/* P1025 has pins muxed for QE and other functions. To
+			* enable QE UEC mode, we need to set bit QE0 for UCC1
+			* in Eth mode, QE0 and QE3 for UCC5 in Eth mode, QE9
+			* and QE12 for QE MII management singals in PMUXCR
+			* register.
+			*/
+				setbits32(pmuxcr, MPC85xx_PMUXCR_QE0 |
+						MPC85xx_PMUXCR_QE3 |
+						MPC85xx_PMUXCR_QE9 |
+						MPC85xx_PMUXCR_QE12);
+#endif
+			}
+
+			of_node_put(np);
+		}
+
+	}
+
+qe_fail:
+#endif	/* CONFIG_QUICC_ENGINE */
+
 	printk(KERN_INFO "MPC85xx RDB board from Freescale Semiconductor\n");
 }
 
-- 
1.7.0.4

^ permalink raw reply related

* [PATCH 2/2] powerpc: Abstract common define of signal multiplex control for qe
From: Zhicheng Fan @ 2012-01-20  5:00 UTC (permalink / raw)
  To: galak, linuxppc-dev; +Cc: Fanzc
In-Reply-To: <1327035611-22794-1-git-send-email-B32736@freescale.com>

From: Fanzc <b32736@freeescale.com>

The mpc85xx_rdb and mpc85xx_mds have commom define of signal multiplex for qe ,so
they need to go in common header, the patch abstract them to fsl_guts.h

Signed-off-by: Fanzc <b32736@freeescale.com>
---
 arch/powerpc/include/asm/fsl_guts.h       |   19 +++++++++++++++++++
 arch/powerpc/platforms/85xx/mpc85xx_mds.c |    7 ++-----
 2 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h
index bebd124..efacfe3 100644
--- a/arch/powerpc/include/asm/fsl_guts.h
+++ b/arch/powerpc/include/asm/fsl_guts.h
@@ -114,6 +114,25 @@ struct ccsr_guts_86xx {
 	__be32	srds2cr1;	/* 0x.0f44 - SerDes2 Control Register 0 */
 } __attribute__ ((packed));
 
+#ifdef CONFIG_PPC_85xx
+
+/* Alternate function signal multiplex control */
+#define MPC85xx_PMUXCR_OFFSET           0x60
+#define MPC85xx_PMUXCR_QE0              0x00008000
+#define MPC85xx_PMUXCR_QE2              0x00002000
+#define MPC85xx_PMUXCR_QE3              0x00001000
+#define MPC85xx_PMUXCR_QE4              0x00000800
+#define MPC85xx_PMUXCR_QE5              0x00000400
+#define MPC85xx_PMUXCR_QE6              0x00000200
+#define MPC85xx_PMUXCR_QE7              0x00000100
+#define MPC85xx_PMUXCR_QE8              0x00000080
+#define MPC85xx_PMUXCR_QE9              0x00000040
+#define MPC85xx_PMUXCR_QE10             0x00000020
+#define MPC85xx_PMUXCR_QE11             0x00000010
+#define MPC85xx_PMUXCR_QE12             0x00000008
+
+#endif
+
 #ifdef CONFIG_PPC_86xx
 
 #define CCSR_GUTS_DMACR_DEV_SSI	0	/* DMA controller/channel set to SSI */
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 1d15a0c..1bd339a 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -51,6 +51,7 @@
 #include <asm/qe_ic.h>
 #include <asm/mpic.h>
 #include <asm/swiotlb.h>
+#include <asm/fsl_guts.h>
 #include "smp.h"
 
 #include "mpc85xx.h"
@@ -268,11 +269,7 @@ static void __init mpc85xx_mds_qe_init(void)
 	mpc85xx_mds_reset_ucc_phys();
 
 	if (machine_is(p1021_mds)) {
-#define MPC85xx_PMUXCR_OFFSET           0x60
-#define MPC85xx_PMUXCR_QE0              0x00008000
-#define MPC85xx_PMUXCR_QE3              0x00001000
-#define MPC85xx_PMUXCR_QE9              0x00000040
-#define MPC85xx_PMUXCR_QE12             0x00000008
+
 		static __be32 __iomem *pmuxcr;
 
 		np = of_find_node_by_name(NULL, "global-utilities");
-- 
1.7.0.4

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox