LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: Merge dtc
From: Josh Boyer @ 2007-12-04 15:26 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: linuxppc-dev, Paul, David Woodhouse, Mackerras, David Gibson
In-Reply-To: <E1IzXmf-0005RJ-27@jdl.com>

On Tue, 04 Dec 2007 07:25:57 -0600
Jon Loeliger <jdl@jdl.com> wrote:

> So, like, the other day David Woodhouse mumbled:
> > 
> > I think this is a bad idea -- it's hardly a difficult for those people
> > who _do_ need dts to obtain it separately.
> > 
> > We shouldn't be merging _more_ stuff in.
> 
> Thanks for chiming in here, David W.  As far as I can tell
> so far, the only two people who have voiced an opinion on
> this issue are Dave G, submitting patches, and me disagreeing
> with the approach.  :-)
> 
> Anyone else?

I don't see an overwhelmingly great reason to merge it.  It might help
test people who do automated rebuilds, etc and aren't used to dealing
with powerpc and it's requirements.  Outside of that, I see it as
dual-maintenance.

But I'm not doing the maintenance, and it doesn't effect me too much.
I only ask that a decision is made and executed on soon so we can move
on.

josh

^ permalink raw reply

* Re: [BUG] 2.6.24-rc3-git2 softlockup detected
From: Kamalesh Babulal @ 2007-12-04 14:57 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Rafael J. Wysocki, linux-scsi, Matthew Wilcox, LKML,
	Kyle McMartin, linuxppc-dev, Andrew Morton, Balbir Singh
In-Reply-To: <20071204122005.GA27286@elte.hu>

Ingo Molnar wrote:
> * Kamalesh Babulal <kamalesh@linux.vnet.ibm.com> wrote:
> 
>>> So 2.6.24-rc3 was OK and 2.6.24-rc3-git2 is not?
>> Yes, the 2.6.24-rc3 was Ok and this is seen from 2.6.24-rc3-git2/3/4.
> 
> just to make sure: this is a real lockup and failed bootup (or device 
> init), not just a message, right?
> 
> 	Ingo
> --

Hi Ingo,

This softlockup is seen in the 2.6.24-rc4 either and looks like a message because 
this is seen while running tbench and machine continues running other test's after 
the softlockup messages and some times seen with the bootup, but the machines reaches the 
login prompt and able to continue running tests.

-- 
Thanks & Regards,
Kamalesh Babulal,
Linux Technology Center,
IBM, ISTL.

^ permalink raw reply

* Re: [PATCH v2 2/2] [POWERPC] Use new machine_xxx_initcall hooks in platform code
From: Grant Likely @ 2007-12-04 14:21 UTC (permalink / raw)
  To: Geert Uytterhoeven; +Cc: linuxppc-dev, olof
In-Reply-To: <fa686aa40712040536h18bd60d3xf89af1f89f6a92ad@mail.gmail.com>

On 12/4/07, Grant Likely <grant.likely@secretlab.ca> wrote:
> On 12/4/07, Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com> wrote:
> > On Sat, 1 Dec 2007, Grant Likely wrote:
> > > From: Grant Likely <grant.likely@secretlab.ca>
> > >
> > > This patch makes the platform code use the new machine-specific initcall
> > > hooks.  This has the advantage of not needing to explicitly test
> > > machine_is() at the top of every initcall function.
> >
> > You seem to have missed the PS3 *_initcall()s.
> > Probably because they test for firmware_has_feature(FW_FEATURE_PS3_LV1) instead
> > of machine_is(ps3).
>
> That's exactly why; I didn't know if 'machine_is(ps3)' was a suitable
> substitute so I left it alone.

On that topic; I left some pseries and iseries stuff alone also for
the same reason.

Cheers,
g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195

^ permalink raw reply

* Re: dtc: Add may const qualifications
From: Jon Loeliger @ 2007-12-04 13:56 UTC (permalink / raw)
  To: David Gibson; +Cc: linuxppc-dev
In-Reply-To: <20071204032615.GK32577@localhost.localdomain>

So, like, the other day David Gibson mumbled:
> This adds 'const' qualifiers to many variables and functions.  In
> particular it's now used for passing names to the tree accesor
> functions.
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>


Typo fixed, rebased and applied.

Thanks,
jdl

^ permalink raw reply

* Re: [PATCH v2 2/2] [POWERPC] Use new machine_xxx_initcall hooks in platform code
From: Geert Uytterhoeven @ 2007-12-04 13:43 UTC (permalink / raw)
  To: Grant Likely, Geoff Levand; +Cc: olof, Linux/PPC Development
In-Reply-To: <fa686aa40712040536h18bd60d3xf89af1f89f6a92ad@mail.gmail.com>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1414 bytes --]

On Tue, 4 Dec 2007, Grant Likely wrote:
> On 12/4/07, Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com> wrote:
> > On Sat, 1 Dec 2007, Grant Likely wrote:
> > > From: Grant Likely <grant.likely@secretlab.ca>
> > >
> > > This patch makes the platform code use the new machine-specific initcall
> > > hooks.  This has the advantage of not needing to explicitly test
> > > machine_is() at the top of every initcall function.
> >
> > You seem to have missed the PS3 *_initcall()s.
> > Probably because they test for firmware_has_feature(FW_FEATURE_PS3_LV1) instead
> > of machine_is(ps3).
> 
> That's exactly why; I didn't know if 'machine_is(ps3)' was a suitable
> substitute so I left it alone.

I think it's OK. But...

Geoff: is there any specific reason why you used
firmware_has_feature(FW_FEATURE_PS3_LV1)?

With kind regards,
 
Geert Uytterhoeven
Software Architect

Sony Network and Software Technology Center Europe
The Corporate Village · Da Vincilaan 7-D1 · B-1935 Zaventem · Belgium
 
Phone:    +32 (0)2 700 8453	
Fax:      +32 (0)2 700 8622	
E-mail:   Geert.Uytterhoeven@sonycom.com	
Internet: http://www.sony-europe.com/
 	
Sony Network and Software Technology Center Europe	
A division of Sony Service Centre (Europe) N.V.	
Registered office: Technologielaan 7 · B-1840 Londerzeel · Belgium	
VAT BE 0413.825.160 · RPR Brussels	
Fortis Bank Zaventem · Swift GEBABEBB08A · IBAN BE39001382358619

^ permalink raw reply

* Re: [PATCH v2 2/2] [POWERPC] Use new machine_xxx_initcall hooks in platform code
From: Grant Likely @ 2007-12-04 13:36 UTC (permalink / raw)
  To: Geert Uytterhoeven; +Cc: linuxppc-dev, olof
In-Reply-To: <Pine.LNX.4.62.0712041320250.12181@pademelon.sonytel.be>

On 12/4/07, Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com> wrote:
> On Sat, 1 Dec 2007, Grant Likely wrote:
> > From: Grant Likely <grant.likely@secretlab.ca>
> >
> > This patch makes the platform code use the new machine-specific initcall
> > hooks.  This has the advantage of not needing to explicitly test
> > machine_is() at the top of every initcall function.
>
> You seem to have missed the PS3 *_initcall()s.
> Probably because they test for firmware_has_feature(FW_FEATURE_PS3_LV1) instead
> of machine_is(ps3).

That's exactly why; I didn't know if 'machine_is(ps3)' was a suitable
substitute so I left it alone.

Cheers,
g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195

^ permalink raw reply

* Re: [PATCH 2/2] [POWERPC] pasemi: Register i2c_board_info
From: David Woodhouse @ 2007-12-04 13:28 UTC (permalink / raw)
  To: Olof Johansson; +Cc: linuxppc-dev
In-Reply-To: <20071130032923.GB25580@lixom.net>


On Thu, 2007-11-29 at 21:29 -0600, Olof Johansson wrote:
> +                               continue;
> +
> +                       info.addr = *addr;
> +
> +                       i2c_register_board_info(PCI_FUNC(pdev->devfn),
> &info,
> +                                               1);
> +               }
> +       }

+       /* Ensure that buses up to 2 are reserved */
+       i2c_register_board_info(2, NULL, 0);
+


> +       return 0;
> +}
> +device_initcall(pasemi_register_i2c_devices);
> +#endif


Otherwise when you make i2c-pasemi use i2c_add_numbered_adapter(), it
might fail to register the third bus -- because there were no devices
preregistered on it, so something else might have stolen that bus number
already.

You might want to add the patch to use i2c_add_numbered_adapter() to
your tree, btw.

-- 
dwmw2

^ permalink raw reply

* Re: dtc: Fix uninitialized use of structure_ok
From: Jon Loeliger @ 2007-12-04 13:28 UTC (permalink / raw)
  To: David Gibson; +Cc: linuxppc-dev
In-Reply-To: <20071204004943.GD32577@localhost.localdomain>

So, like, the other day David Gibson mumbled:
> My rework of the tree checking code introduced a potentially nasty bug
> - it uses the structure_ok variable uninitialized.  This patch fixes
> the problem.  It's a fairly ugly bandaid approach, but the ugly will
> disappear once future patches have folded the semantic checks into the
> new framework.
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

Applied.

Thanks!
jdl

^ permalink raw reply

* Re: [PATCH][DTC] Add an option to pad the blob that is generated
From: Jon Loeliger @ 2007-12-04 13:27 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <Pine.LNX.4.64.0711281020240.5095@blarg.am.freescale.net>

So, like, the other day Kumar Gala mumbled:
> There are times when we need extra space in the blob and just want
> to have it added on w/o know the exact size to make it.
> 
> The padding and min size options are mutually exclusive.
> 
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>

Applied.

Thanks,
jdl

^ permalink raw reply

* Re: Merge dtc
From: Jon Loeliger @ 2007-12-04 13:25 UTC (permalink / raw)
  To: David Woodhouse; +Cc: linuxppc-dev, Paul Mackerras, David Gibson
In-Reply-To: <1196733544.13978.201.camel@pmac.infradead.org>

So, like, the other day David Woodhouse mumbled:
> 
> I think this is a bad idea -- it's hardly a difficult for those people
> who _do_ need dts to obtain it separately.
> 
> We shouldn't be merging _more_ stuff in.

Thanks for chiming in here, David W.  As far as I can tell
so far, the only two people who have voiced an opinion on
this issue are Dave G, submitting patches, and me disagreeing
with the approach.  :-)

Anyone else?

jdl

^ permalink raw reply

* Re: [PATCH 2/3] celleb: add supporting for native CBE
From: Arnd Bergmann @ 2007-12-04 13:21 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: paulus
In-Reply-To: <20071204.173824.-1350527485.kouish@swc.toshiba.co.jp>

On Tuesday 04 December 2007, Ishizaki Kou wrote:
> This patch adds supporting for native CBE on Celleb. =A0Many codes in
> platforms/cell/ are used when native CBE environment.
>=20
> Signed-off-by: Kou Ishizaki <Kou.Ishizaki@toshiba.co.jp>

Ah, excellent to hear that this is now working!

I'd suggest doing the initialization in a different way, so that you don't
need to decide on so many attributes dynamically. The easiest way would
probably be to have two separate define_machine() calls in the celleb
definition, like

define_machine(celleb_beat) {
        .probe                  =3D celleb_probe_beat,
        .setup_arch             =3D celleb_setup_arch_native,
        .show_cpuinfo           =3D celleb_show_cpuinfo,
        .restart                =3D beat_restart,
        .power_off              =3D beat_power_off,
        .halt                   =3D beat_halt,
        .get_rtc_time           =3D beat_get_rtc_time,
        .set_rtc_time           =3D beat_set_rtc_time,
        .calibrate_decr         =3D generic_calibrate_decr,
        .progress               =3D celleb_progress,
        .power_save             =3D beat_power_save,
        .nvram_size             =3D beat_nvram_get_size,
        .nvram_read             =3D beat_nvram_read,
        .nvram_write            =3D beat_nvram_write,
        .set_dabr               =3D beat_set_xdabr,
        .init_IRQ               =3D beatic_init_IRQ,
        .get_irq                =3D beatic_get_irq,
        .pci_probe_mode         =3D celleb_pci_probe_mode,
        .pci_setup_phb          =3D celleb_setup_phb,
	...
};

define_machine(celleb_native) {
        .probe                  =3D celleb_probe_native,
        .setup_arch             =3D celleb_setup_arch_native,
        .show_cpuinfo           =3D celleb_show_cpuinfo,
        .restart                =3D rtas_restart,
        .power_off              =3D rtas_power_off,
        .halt                   =3D rtas_halt,
        .get_rtc_time           =3D rtas_get_rtc_time,
        .set_rtc_time           =3D rtas_set_rtc_time,
        .calibrate_decr         =3D generic_calibrate_decr,
        .progress               =3D celleb_progress,
        .init_IRQ               =3D celleb_init_IRQ_native,
        .get_irq                =3D celleb_get_irq_native,
        .pci_probe_mode         =3D celleb_pci_probe_mode,
        .pci_setup_phb          =3D celleb_setup_phb,
	...
};

=46or this, you can either have the two machine definitions in the
same celleb/setup.c, or split setup.c into machine specific files,
depending on how much ends up being shared in the end.

An interesting question still is how close the native celleb machine
definition is to the one from platforms/cell/setup.c. Maybe it's best
to have a common machine definition for these two in the end.

	Arnd <><

^ permalink raw reply

* Re: [PATCH 1/5] PowerPC 74xx: Katana Qp device tree
From: Jon Loeliger @ 2007-12-04 13:14 UTC (permalink / raw)
  To: Jon Loeliger, linuxppc-dev@ozlabs.org
In-Reply-To: <20071204003354.GB32577@localhost.localdomain>

David Gibson wrote:
> On Mon, Dec 03, 2007 at 01:26:34PM -0600, Jon Loeliger wrote:
>> On Sun, 2007-12-02 at 19:50, David Gibson wrote:
>>
>>>> +		clock-frequency = <7f28155>;		/* 133.333333 MHz */
>>> You can use <d# 133333333> to avoid the ugly hex.
>> Better still, blaze a new trail, convert it to /dts-v1/ and
>> use clock-frequency = <133333333> straight up!
> 
> Hrm.. probably best to wait for dtc to go into the kernel for that.
> 

I disagree.

jdl

^ permalink raw reply

* Re: [PATCH] Add IPIC MSI interrupt support
From: Scott Wood @ 2007-12-04 13:13 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: linuxppc-dev, Gala Kumar, Li Tony
In-Reply-To: <1196769858.32524.8.camel@concordia>

On Tue, Dec 04, 2007 at 11:04:18PM +1100, Michael Ellerman wrote:
> On Tue, 2007-12-04 at 18:34 +0800, Li Tony wrote:
> > I am not very sure about spin_lock influence.
> > But maybe somebody will change the virq_to_hw implementation.
> > I will take virq_to_hw instead. 
> 
> I mean the time to take the function call should be pretty small
> compared to taking and releasing a spinlock - but if you have
> performance numbers to prove otherwise let me know :)

I don't think the IPIC is used on any SMP platforms at the moment, so
there's no spinlock overhead other than disabling interrupts...

That said, it's not worth reimplementing to avoid a function call.

-Scott

^ permalink raw reply

* Re: [PATCH 1/3] cell: fix undefined reference to mmio_nvram_init
From: Arnd Bergmann @ 2007-12-04 13:10 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: paulus
In-Reply-To: <20071204.173453.-1300514021.kouish@swc.toshiba.co.jp>

On Tuesday 04 December 2007, Ishizaki Kou wrote:
>=20
> +#ifdef CONFIG_MMIO_NVRAM
> =A0=A0=A0=A0=A0=A0=A0=A0mmio_nvram_init();
> +#endif
> =A0}

The patch is technically correct, but the preferred way of doing this is
to define a conditional inline function in the header, like:

#ifdef CONFIG_MMIO_NVRAM
extern int mmio_nvram_init(void);
#else
static inline int mmio_nvram_init(void)
{
	return 0;
}
#endif

so that the caller does not need to know about it.

	Arnd <><

^ permalink raw reply

* Re: OT: Re: solved: Re: [rtc-linux] Re: DS1337 RTC on I2C broken.
From: Scott Wood @ 2007-12-04 13:08 UTC (permalink / raw)
  To: Clemens Koller; +Cc: Alessandro Zummo, rtc-linux, linuxppc-embedded
In-Reply-To: <47553D31.4080306@anagramm.de>

On Tue, Dec 04, 2007 at 12:42:41PM +0100, Clemens Koller wrote:
> Scott Wood schrieb:
>> That's precisely what we do, via the device tree.  It is not practical to
>> do it with kconfig.
>
> It's propably not practical to do it with kconfig right now,

It's not practical at all.  It forces you to support one and only one target
per kernel image, and the basic structure of it is not nearly flexible
enough.

> but creating a separate configuration repository with strong relation to
> the kernel config is IMO the wrong way to do it.

It has a weak relation to the kernel config, not a strong one.

> > Again putting aside multiplatform kernels for the moment,
>> what would you do in kconfig to describe the addresses of multiple chips
>> without having a fixed-size list of possibilities?
>
> I don't see

?

> > How would you tell the
>> kernel, using kconfig, that there's a "foo" chip at address 0x68 on i2c 
>> bus
>> 0, and a "bar" chip at address 0x68 on i2c bus 1?
>
> I would prefer to not tell the driver for 'foo' that it should attach to 
> 0-0068
> because it should attach to the first i2c bus (0) it finds per default.

Absolutely wrong.  What if foo is on bus 1?

> Then I would need to tell 'bar' to attach to 1-0068. Where is the problem?

OK, now say there's another foo on bus 2, and a pair of bars on buses 3 and
4?

> The 0068 is already redundant in the case of these RTCs because they are 
> fixed.

How do you know I'm even talking about RTCs?  Those chips at 0x68 could be
anything.  There are many chips that don't have a single fixed address.

> There is already an example in the kernel for a very similar configuration
> issue: see CONFIG_RTC_HCTOSYS_DEVICE.

That's not remotely the same.  That's telling a kernel init procedure what
kernel device to use, not describing the layout of hardware.

> The structure for this already present in kconfig, 

It is not.

> and I don't see any road block not to be able to use it. If later on, we
> want to have OF to be able to reconfigure it in the form of a DT
> structure, we could still feed a tool like the dtc with the .config and
> generate one.

Please, feel free to make a patch that does this.  You may find it to be a
bit more difficult than you thought. :-)

And again, there's the multiplatform issue.

> Just let me make the point clear, why I got so upset here: Having two
> different non-independent repositories make the configuration much more
> error-prone, especially if the second one (the DT) is partially redundant
> and not sufficiently documented.

The device tree is not a configuration repository, it is a description of
the hardware.

> Example:
> I need to use the PCF8563 on the MPC8540' I2C as well (*) - it
> was just working in 2.6.22. Now, somebody
>
> a) has to enable it in the kernel config
> b) then add it to the i2c_driver_device struct in fsl_soc.c
> c) then add it to the DTS.
>
> Step b and c are not difficult at all, but completely non-obvious
> and undocumented for non-developers. You actually have to dig in
> the code to find out that you need it and this s****.

Step b is something that only needs to be done once per chip, and step c is
something that only needs to be done once per board.  Why is it unreasonable
for it to be done by a developer?

We really should try to get the table populated with names for all of the
new-style drivers in the kernel, though.

> linux-2.6/Documentation/powerpc$ grep "rtc" *
> only gives on hit in the mpc52xx-device-tree-bindings.txt (from Grant, 
> btw.).
> which could give a clue what's going on here.
> linux-2.6/Documentation/powerpc$ grep "fsl_soc" *
> - nothing -

Uh, did you try grepping for "i2c"?

> The configuration process is away from KISS - I would simply
> state: it's broken - or - it's a regression from 2.6.22.

The transition could have been done more smoothly if the i2c driver model
allowed a driver to be both new-style and old-style at the same time
(subject to a config option to shut off old-style if it's screwing things
up), I'll agree with that much.  But please, try to understand that the
device tree really does help.

-Scott

^ permalink raw reply

* Re: [PATCH] pci: Fix bus resource assignment on 32 bits with 64b resources
From: Geert Uytterhoeven @ 2007-12-04 12:39 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Greg Kroah-Hartman, linux-pci, linux-kernel, linuxppc-dev
In-Reply-To: <20071204060911.EA82BDDE19@ozlabs.org>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 2306 bytes --]

On Tue, 4 Dec 2007, Benjamin Herrenschmidt wrote:
> The current pci_assign_unassigned_resources() code doesn't work properly
> on 32 bits platforms with 64 bits resources. The main reason is the use
> of unsigned long in various places instead of resource_size_t.
> 
> This fixes it, along with some tricks to avoid casting to 64 bits on
> platforms that don't need it in every printk around.
> 
> This is a pre-requisite for making powerpc use the generic code instead of
> its own half-useful implementation.
> 
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> ---
> 
>  drivers/pci/pci.h       |   11 +++++++++++
>  drivers/pci/setup-bus.c |   32 +++++++++++++++++---------------
>  drivers/pci/setup-res.c |    5 ++---
>  include/linux/pci.h     |    4 ++--
>  4 files changed, 32 insertions(+), 20 deletions(-)
> 
> Index: linux-work/drivers/pci/pci.h
> ===================================================================
> --- linux-work.orig/drivers/pci/pci.h	2007-12-04 17:00:43.000000000 +1100
> +++ linux-work/drivers/pci/pci.h	2007-12-04 17:02:11.000000000 +1100
> @@ -91,3 +91,14 @@ pci_match_one_device(const struct pci_de
>  }
>  
>  struct pci_dev *pci_find_upstream_pcie_bridge(struct pci_dev *pdev);
> +
> +#ifdef CONFIG_RESOURCES_64BIT
> +#define RESOURCE_ORDER(order)	(1ULL << (order))
> +#define RES_PR			"%016llx"
> +#else
> +#define RESOURCE_ORDER(order)	(1UL << (order))
> +#define RES_PR			"%08lx"
> +#endif
> +
> +#define RANGE_PR		RES_PR "-" RES_PR

Can we please have them in <linux/ioport.h>? They look very useful to me
elsewhere (other bus drivers, device drivers), too.

What about naming the printf format specifier macros more like in C99, e.g.
PRI*?

With kind regards,
 
Geert Uytterhoeven
Software Architect

Sony Network and Software Technology Center Europe
The Corporate Village · Da Vincilaan 7-D1 · B-1935 Zaventem · Belgium
 
Phone:    +32 (0)2 700 8453	
Fax:      +32 (0)2 700 8622	
E-mail:   Geert.Uytterhoeven@sonycom.com	
Internet: http://www.sony-europe.com/
 	
Sony Network and Software Technology Center Europe	
A division of Sony Service Centre (Europe) N.V.	
Registered office: Technologielaan 7 · B-1840 Londerzeel · Belgium	
VAT BE 0413.825.160 · RPR Brussels	
Fortis Bank Zaventem · Swift GEBABEBB08A · IBAN BE39001382358619

^ permalink raw reply

* Re: [PATCH v2 2/2] [POWERPC] Use new machine_xxx_initcall hooks in platform code
From: Geert Uytterhoeven @ 2007-12-04 12:23 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-dev, olof
In-Reply-To: <20071202061033.21193.64818.stgit@trillian.secretlab.ca>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1038 bytes --]

On Sat, 1 Dec 2007, Grant Likely wrote:
> From: Grant Likely <grant.likely@secretlab.ca>
> 
> This patch makes the platform code use the new machine-specific initcall
> hooks.  This has the advantage of not needing to explicitly test
> machine_is() at the top of every initcall function.

You seem to have missed the PS3 *_initcall()s.
Probably because they test for firmware_has_feature(FW_FEATURE_PS3_LV1) instead
of machine_is(ps3).

With kind regards,
 
Geert Uytterhoeven
Software Architect

Sony Network and Software Technology Center Europe
The Corporate Village · Da Vincilaan 7-D1 · B-1935 Zaventem · Belgium
 
Phone:    +32 (0)2 700 8453	
Fax:      +32 (0)2 700 8622	
E-mail:   Geert.Uytterhoeven@sonycom.com	
Internet: http://www.sony-europe.com/
 	
Sony Network and Software Technology Center Europe	
A division of Sony Service Centre (Europe) N.V.	
Registered office: Technologielaan 7 · B-1840 Londerzeel · Belgium	
VAT BE 0413.825.160 · RPR Brussels	
Fortis Bank Zaventem · Swift GEBABEBB08A · IBAN BE39001382358619

^ permalink raw reply

* Re: [BUG] 2.6.24-rc3-git2 softlockup detected
From: Ingo Molnar @ 2007-12-04 12:20 UTC (permalink / raw)
  To: Kamalesh Babulal
  Cc: Rafael J. Wysocki, linux-scsi, Matthew Wilcox, LKML,
	Kyle McMartin, linuxppc-dev, Andrew Morton, Balbir Singh
In-Reply-To: <474FBB86.5000004@linux.vnet.ibm.com>


* Kamalesh Babulal <kamalesh@linux.vnet.ibm.com> wrote:

> > So 2.6.24-rc3 was OK and 2.6.24-rc3-git2 is not?
> 
> Yes, the 2.6.24-rc3 was Ok and this is seen from 2.6.24-rc3-git2/3/4.

just to make sure: this is a real lockup and failed bootup (or device 
init), not just a message, right?

	Ingo

^ permalink raw reply

* RE: [PATCH] Add IPIC MSI interrupt support
From: Michael Ellerman @ 2007-12-04 12:04 UTC (permalink / raw)
  To: Li Tony; +Cc: linuxppc-dev, Gala Kumar
In-Reply-To: <995B09A8299C2C44B59866F6391D2635D75588@zch01exm21.fsl.freescale.net>

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

On Tue, 2007-12-04 at 18:34 +0800, Li Tony wrote:
> > From: Michael Ellerman [mailto:michael@ellerman.id.au] 
> > Sent: 2007年12月4日 13:38
> > To: Li Tony
> > Cc: Li Tony; Gala Kumar; linuxppc-dev
> > Subject: Re: [PATCH] Add IPIC MSI interrupt support
> > 
> > On Mon, 2007-12-03 at 17:07 +0800, Li Li wrote:
> > > Hi Michael,
> > > 
> > > I emulate mpic to write this IPIC MSI routines. :)
> > > 
> > > 
> > > > > diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c 
> > > > > b/arch/powerpc/platforms/83xx/mpc837x_mds.c
> > > > > index 6048f1b..dbea34b 100644
> > > > > --- a/arch/powerpc/platforms/83xx/mpc837x_mds.c
> > > > > +++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c
> > 
> > > > > +
> > > > > +#define	ipic_msi_irq_to_hw(virq)	
> > ((unsigned int)irq_map[virq].hwirq)
> > > > 
> > > > What's wrong with virq_to_hw() ?
> > > > 
> > > 
> > > viqr_to_hw is not __inline__.
> > 
> > Hmm, ok. The three places you use it you also take a spin 
> > lock, so I'm not sure the function call's really going to 
> > kill you performance wise.
> > 
> 
> I am not very sure about spin_lock influence.
> But maybe somebody will change the virq_to_hw implementation.
> I will take virq_to_hw instead. 

I mean the time to take the function call should be pretty small
compared to taking and releasing a spinlock - but if you have
performance numbers to prove otherwise let me know :)

> I see that the virq_to_hw is do inline in 2.6.22.
> Why remove it?

It was made non-inline because modules want to use it, and we didn't
want to export the irq_map to modules as well.

cheers

-- 
Michael Ellerman
OzLabs, IBM Australia Development Lab

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* RE: [PATCH 2/2] powerpc: Add IPIC MSI support
From: Michael Ellerman @ 2007-12-04 11:59 UTC (permalink / raw)
  To: Li Yang; +Cc: linuxppc-dev, Gala Kumar, Phillips Kim, Li Tony
In-Reply-To: <989B956029373F45A0B8AF029708189001B4D395@zch01exm26.fsl.freescale.net>

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

On Tue, 2007-12-04 at 18:57 +0800, Li Yang wrote:
> > -----Original Message-----
> > From: linuxppc-dev-bounces+leoli=freescale.com@ozlabs.org 
> > [mailto:linuxppc-dev-bounces+leoli=freescale.com@ozlabs.org] 
> > On Behalf Of Li Tony
> > Sent: Tuesday, December 04, 2007 6:39 PM
> > To: Gala Kumar; Phillips Kim; michael@ellerman.id.au; linuxppc-dev
> > Subject: [PATCH 2/2] powerpc: Add IPIC MSI support
> > 
> > Modified based on discussion on list.
> > 
> > 1. Adopt virq_to_hw routine
> > 2. Correct a legacy bug
> 
> The above lines should probably be placed after the "---" below.
> 
> > 
> > Implements the IPIC MSI as two level interrupt controller.
> > 
> > Signed-off-by: Tony Li <tony.li@freescale.com>

The change log is a bit short in general for my liking.

Still, MSI bits ..

Acked-by: Michael Ellerman <michael@ellerman.id.au>

cheers

-- 
Michael Ellerman
OzLabs, IBM Australia Development Lab

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: OT: Re: solved: Re: [rtc-linux] Re: DS1337 RTC on I2C broken.
From: Clemens Koller @ 2007-12-04 11:42 UTC (permalink / raw)
  To: Scott Wood; +Cc: Alessandro Zummo, rtc-linux, linuxppc-embedded
In-Reply-To: <20071203204652.GB4850@loki.buserror.net>

Hi, Scott!

Scott Wood schrieb:
> On Mon, Dec 03, 2007 at 08:35:29PM +0100, Clemens Koller wrote:
>> Even if I have an eeprom which can have varying addresses,
>> I can simply tell the driver/the kernel .config what address
>> it should use...
> 
> That's precisely what we do, via the device tree.  It is not practical to do
> it with kconfig.

It's propably not practical to do it with kconfig right now, but
creating a separate configuration repository with strong relation
to the kernel config is IMO the wrong way to do it.

 > Again putting aside multiplatform kernels for the moment,
> what would you do in kconfig to describe the addresses of multiple chips
> without having a fixed-size list of possibilities?

I don't see

 > How would you tell the
> kernel, using kconfig, that there's a "foo" chip at address 0x68 on i2c bus
> 0, and a "bar" chip at address 0x68 on i2c bus 1?

I would prefer to not tell the driver for 'foo' that it should attach to 0-0068
because it should attach to the first i2c bus (0) it finds per default.
Then I would need to tell 'bar' to attach to 1-0068. Where is the problem?
The 0068 is already redundant in the case of these RTCs because they are fixed.

There is already an example in the kernel for a very similar configuration
issue: see CONFIG_RTC_HCTOSYS_DEVICE.

The structure for this already present in kconfig, and I don't see any
road block not to be able to use it. If later on, we want to have OF to
be able to reconfigure it in the form of a DT structure, we could
still feed a tool like the dtc with the .config and generate one.

Just let me make the point clear, why I got so upset here:
Having two different non-independent repositories make the
configuration much more error-prone, especially if the second
one (the DT) is partially redundant and not sufficiently documented.

Example:
I need to use the PCF8563 on the MPC8540' I2C as well (*) - it
was just working in 2.6.22. Now, somebody

a) has to enable it in the kernel config
b) then add it to the i2c_driver_device struct in fsl_soc.c
c) then add it to the DTS.

Step b and c are not difficult at all, but completely non-obvious
and undocumented for non-developers. You actually have to dig in
the code to find out that you need it and this s****.

linux-2.6/Documentation/powerpc$ grep "rtc" *
only gives on hit in the mpc52xx-device-tree-bindings.txt (from Grant, btw.).
which could give a clue what's going on here.
linux-2.6/Documentation/powerpc$ grep "fsl_soc" *
- nothing -

The configuration process is away from KISS - I would simply
state: it's broken - or - it's a regression from 2.6.22.

(*) Patch will follow, let me see if I guess it right. :-)

Regards,
-- 
Clemens Koller
__________________________________
R&D Imaging Devices
Anagramm GmbH
Rupert-Mayer-Straße 45/1
Linhof Werksgelände
D-81379 München
Tel.089-741518-50
Fax 089-741518-19
http://www.anagramm-technology.com

^ permalink raw reply

* RE: [PATCH 2/2] powerpc: Add IPIC MSI support
From: Li Yang @ 2007-12-04 10:57 UTC (permalink / raw)
  To: Li Tony, Gala Kumar, Phillips Kim, michael, linuxppc-dev
In-Reply-To: <1196764760.2573.10.camel@Guyver>

> -----Original Message-----
> From: linuxppc-dev-bounces+leoli=3Dfreescale.com@ozlabs.org=20
> [mailto:linuxppc-dev-bounces+leoli=3Dfreescale.com@ozlabs.org]=20
> On Behalf Of Li Tony
> Sent: Tuesday, December 04, 2007 6:39 PM
> To: Gala Kumar; Phillips Kim; michael@ellerman.id.au; linuxppc-dev
> Subject: [PATCH 2/2] powerpc: Add IPIC MSI support
>=20
> Modified based on discussion on list.
>=20
> 1. Adopt virq_to_hw routine
> 2. Correct a legacy bug

The above lines should probably be placed after the "---" below.

>=20
> Implements the IPIC MSI as two level interrupt controller.
>=20
> Signed-off-by: Tony Li <tony.li@freescale.com>
> ---

- Leo

^ permalink raw reply

* [PATCH] ipic: ack only for edge interrupts
From: Li Yang @ 2007-12-04 11:01 UTC (permalink / raw)
  To: galak, linuxppc-dev; +Cc: Li Yang

Only external interrupts in edge detect mode support ack operation.
Therefore, in most cases ack is not needed.  The patch makes ipic
ack only when it's needed.  This could boost over all system performance.

Signed-off-by: Li Yang <leoli@freescale.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
Update to use different irq_chip for level and edge interrupts as Ben
suggested.
Supercedes [PATCH] ipic: change ack operation that register is accessed
only when needed

 arch/powerpc/sysdev/ipic.c |  113 +++++++++++++++++---------------------------
 arch/powerpc/sysdev/ipic.h |    6 +--
 2 files changed, 45 insertions(+), 74 deletions(-)

diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index 7168b03..7274750 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -30,11 +30,11 @@
 #include "ipic.h"
 
 static struct ipic * primary_ipic;
+static struct irq_chip ipic_level_irq_chip, ipic_edge_irq_chip;
 static DEFINE_SPINLOCK(ipic_lock);
 
 static struct ipic_info ipic_info[] = {
 	[1] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_C,
 		.force	= IPIC_SIFCR_H,
@@ -42,7 +42,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 0,
 	},
 	[2] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_C,
 		.force	= IPIC_SIFCR_H,
@@ -50,7 +49,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 1,
 	},
 	[4] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_C,
 		.force	= IPIC_SIFCR_H,
@@ -58,7 +56,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 3,
 	},
 	[9] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_D,
 		.force	= IPIC_SIFCR_H,
@@ -66,7 +63,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 0,
 	},
 	[10] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_D,
 		.force	= IPIC_SIFCR_H,
@@ -74,7 +70,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 1,
 	},
 	[11] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_D,
 		.force	= IPIC_SIFCR_H,
@@ -82,7 +77,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 2,
 	},
 	[12] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_D,
 		.force	= IPIC_SIFCR_H,
@@ -90,7 +84,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 3,
 	},
 	[13] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_D,
 		.force	= IPIC_SIFCR_H,
@@ -98,7 +91,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 4,
 	},
 	[14] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_D,
 		.force	= IPIC_SIFCR_H,
@@ -106,7 +98,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 5,
 	},
 	[15] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_D,
 		.force	= IPIC_SIFCR_H,
@@ -114,7 +105,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 6,
 	},
 	[16] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_D,
 		.force	= IPIC_SIFCR_H,
@@ -122,7 +112,7 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 7,
 	},
 	[17] = {
-		.pend	= IPIC_SEPNR,
+		.ack	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SEFCR,
@@ -130,7 +120,7 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 5,
 	},
 	[18] = {
-		.pend	= IPIC_SEPNR,
+		.ack	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SEFCR,
@@ -138,7 +128,7 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 6,
 	},
 	[19] = {
-		.pend	= IPIC_SEPNR,
+		.ack	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SEFCR,
@@ -146,7 +136,7 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 7,
 	},
 	[20] = {
-		.pend	= IPIC_SEPNR,
+		.ack	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SEFCR,
@@ -154,7 +144,7 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 4,
 	},
 	[21] = {
-		.pend	= IPIC_SEPNR,
+		.ack	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SEFCR,
@@ -162,7 +152,7 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 5,
 	},
 	[22] = {
-		.pend	= IPIC_SEPNR,
+		.ack	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SEFCR,
@@ -170,7 +160,7 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 6,
 	},
 	[23] = {
-		.pend	= IPIC_SEPNR,
+		.ack	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SEFCR,
@@ -178,7 +168,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 7,
 	},
 	[32] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_A,
 		.force	= IPIC_SIFCR_H,
@@ -186,7 +175,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 0,
 	},
 	[33] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_A,
 		.force	= IPIC_SIFCR_H,
@@ -194,7 +182,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 1,
 	},
 	[34] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_A,
 		.force	= IPIC_SIFCR_H,
@@ -202,7 +189,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 2,
 	},
 	[35] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_A,
 		.force	= IPIC_SIFCR_H,
@@ -210,7 +196,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 3,
 	},
 	[36] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_A,
 		.force	= IPIC_SIFCR_H,
@@ -218,7 +203,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 4,
 	},
 	[37] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_A,
 		.force	= IPIC_SIFCR_H,
@@ -226,7 +210,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 5,
 	},
 	[38] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_A,
 		.force	= IPIC_SIFCR_H,
@@ -234,7 +217,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 6,
 	},
 	[39] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_A,
 		.force	= IPIC_SIFCR_H,
@@ -242,7 +224,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 7,
 	},
 	[42] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_B,
 		.force	= IPIC_SIFCR_H,
@@ -250,7 +231,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 2,
 	},
 	[44] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_B,
 		.force	= IPIC_SIFCR_H,
@@ -258,7 +238,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 4,
 	},
 	[45] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_B,
 		.force	= IPIC_SIFCR_H,
@@ -266,7 +245,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 5,
 	},
 	[46] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_B,
 		.force	= IPIC_SIFCR_H,
@@ -274,7 +252,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 6,
 	},
 	[47] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_B,
 		.force	= IPIC_SIFCR_H,
@@ -282,7 +259,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 7,
 	},
 	[48] = {
-		.pend	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SEFCR,
@@ -290,7 +266,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 4,
 	},
 	[64] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SIFCR_L,
@@ -298,7 +273,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 0,
 	},
 	[65] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SIFCR_L,
@@ -306,7 +280,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 1,
 	},
 	[66] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SIFCR_L,
@@ -314,7 +287,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 2,
 	},
 	[67] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SIFCR_L,
@@ -322,7 +294,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 3,
 	},
 	[68] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SIFCR_L,
@@ -330,7 +301,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 0,
 	},
 	[69] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SIFCR_L,
@@ -338,7 +308,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 1,
 	},
 	[70] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SIFCR_L,
@@ -346,7 +315,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 2,
 	},
 	[71] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SIFCR_L,
@@ -354,133 +322,114 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 3,
 	},
 	[72] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 8,
 	},
 	[73] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 9,
 	},
 	[74] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 10,
 	},
 	[75] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 11,
 	},
 	[76] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 12,
 	},
 	[77] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 13,
 	},
 	[78] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 14,
 	},
 	[79] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 15,
 	},
 	[80] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 16,
 	},
 	[81] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 17,
 	},
 	[82] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 18,
 	},
 	[84] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 20,
 	},
 	[85] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 21,
 	},
 	[86] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 22,
 	},
 	[87] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 23,
 	},
 	[88] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 24,
 	},
 	[89] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 25,
 	},
 	[90] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 26,
 	},
 	[91] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
@@ -534,6 +483,10 @@ static void ipic_mask_irq(unsigned int virq)
 	temp &= ~(1 << (31 - ipic_info[src].bit));
 	ipic_write(ipic->regs, ipic_info[src].mask, temp);
 
+	/* mb() can't guarantee that masking is finished.  But it does finish
+	 * for nearly all cases. */
+	mb();
+
 	spin_unlock_irqrestore(&ipic_lock, flags);
 }
 
@@ -546,9 +499,13 @@ static void ipic_ack_irq(unsigned int virq)
 
 	spin_lock_irqsave(&ipic_lock, flags);
 
-	temp = ipic_read(ipic->regs, ipic_info[src].pend);
+	temp = ipic_read(ipic->regs, ipic_info[src].ack);
 	temp |= (1 << (31 - ipic_info[src].bit));
-	ipic_write(ipic->regs, ipic_info[src].pend, temp);
+	ipic_write(ipic->regs, ipic_info[src].ack, temp);
+
+	/* mb() can't guarantee that ack is finished.  But it does finish
+	 * for nearly all cases. */
+	mb();
 
 	spin_unlock_irqrestore(&ipic_lock, flags);
 }
@@ -566,9 +523,13 @@ static void ipic_mask_irq_and_ack(unsigned int virq)
 	temp &= ~(1 << (31 - ipic_info[src].bit));
 	ipic_write(ipic->regs, ipic_info[src].mask, temp);
 
-	temp = ipic_read(ipic->regs, ipic_info[src].pend);
+	temp = ipic_read(ipic->regs, ipic_info[src].ack);
 	temp |= (1 << (31 - ipic_info[src].bit));
-	ipic_write(ipic->regs, ipic_info[src].pend, temp);
+	ipic_write(ipic->regs, ipic_info[src].ack, temp);
+
+	/* mb() can't guarantee that ack is finished.  But it does finish
+	 * for nearly all cases. */
+	mb();
 
 	spin_unlock_irqrestore(&ipic_lock, flags);
 }
@@ -590,14 +551,22 @@ static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
 			flow_type);
 		return -EINVAL;
 	}
+	/* ipic supports only edge mode on external interrupts */
+	if ((flow_type & IRQ_TYPE_EDGE_FALLING) && !ipic_info[src].ack) {
+		printk(KERN_ERR "ipic: edge sense not supported on internal "
+				"interrupts\n");
+		return -EINVAL;
+	}
 
 	desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
 	desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
 	if (flow_type & IRQ_TYPE_LEVEL_LOW)  {
 		desc->status |= IRQ_LEVEL;
 		desc->handle_irq = handle_level_irq;
+		desc->chip = &ipic_level_irq_chip;
 	} else {
 		desc->handle_irq = handle_edge_irq;
+		desc->chip = &ipic_edge_irq_chip;
 	}
 
 	/* only EXT IRQ senses are programmable on ipic
@@ -622,7 +591,16 @@ static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
 	return 0;
 }
 
-static struct irq_chip ipic_irq_chip = {
+/* level interrupts and edge interrupts have different ack operations */
+static struct irq_chip ipic_level_irq_chip = {
+	.typename	= " IPIC  ",
+	.unmask		= ipic_unmask_irq,
+	.mask		= ipic_mask_irq,
+	.mask_ack	= ipic_mask_irq,
+	.set_type	= ipic_set_irq_type,
+};
+
+static struct irq_chip ipic_edge_irq_chip = {
 	.typename	= " IPIC  ",
 	.unmask		= ipic_unmask_irq,
 	.mask		= ipic_mask_irq,
@@ -641,13 +619,9 @@ static int ipic_host_map(struct irq_host *h, unsigned int virq,
 			 irq_hw_number_t hw)
 {
 	struct ipic *ipic = h->host_data;
-	struct irq_chip *chip;
-
-	/* Default chip */
-	chip = &ipic->hc_irq;
 
 	set_irq_chip_data(virq, ipic);
-	set_irq_chip_and_handler(virq, chip, handle_level_irq);
+	set_irq_chip_and_handler(virq, &ipic_level_irq_chip, handle_level_irq);
 
 	/* Set default irq type */
 	set_irq_type(virq, IRQ_TYPE_NONE);
@@ -706,7 +680,6 @@ struct ipic * __init ipic_init(struct device_node *node, unsigned int flags)
 	ipic->regs = ioremap(res.start, res.end - res.start + 1);
 
 	ipic->irqhost->host_data = ipic;
-	ipic->hc_irq = ipic_irq_chip;
 
 	/* init hw */
 	ipic_write(ipic->regs, IPIC_SICNR, 0x0);
diff --git a/arch/powerpc/sysdev/ipic.h b/arch/powerpc/sysdev/ipic.h
index 1158b8f..9391c57 100644
--- a/arch/powerpc/sysdev/ipic.h
+++ b/arch/powerpc/sysdev/ipic.h
@@ -44,13 +44,11 @@ struct ipic {
 
 	/* The remapper for this IPIC */
 	struct irq_host		*irqhost;
-
-	/* The "linux" controller struct */
-	struct irq_chip		hc_irq;
 };
 
 struct ipic_info {
-	u8	pend;		/* pending register offset from base */
+	u8	ack;		/* pending register offset from base if the irq
+				   supports ack operation */
 	u8	mask;		/* mask register offset from base */
 	u8	prio;		/* priority register offset from base */
 	u8	force;		/* force register offset from base */
-- 
1.5.3.5.643.g40e25

^ permalink raw reply related

* [PATCH 2/2] powerpc: Add IPIC MSI support
From: Li Li @ 2007-12-04 10:39 UTC (permalink / raw)
  To: Kumar Gala, kim phillips, michael, linuxppc-dev

Modified based on discussion on list.

1. Adopt virq_to_hw routine
2. Correct a legacy bug

Implements the IPIC MSI as two level interrupt controller.

Signed-off-by: Tony Li <tony.li@freescale.com>
---
 arch/powerpc/boot/dts/mpc8377_mds.dts     |   14 ++
 arch/powerpc/boot/dts/mpc8378_mds.dts     |   14 ++
 arch/powerpc/boot/dts/mpc8379_mds.dts     |   14 ++
 arch/powerpc/platforms/83xx/Kconfig       |    6 +
 arch/powerpc/platforms/83xx/mpc837x_mds.c |    7 +
 arch/powerpc/sysdev/Makefile              |    1 +
 arch/powerpc/sysdev/ipic_msi.c            |  359 +++++++++++++++++++++++++++++
 include/asm-powerpc/ipic_msi.h            |   66 ++++++
 8 files changed, 481 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/sysdev/ipic_msi.c
 create mode 100644 include/asm-powerpc/ipic_msi.h

diff --git a/arch/powerpc/boot/dts/mpc8377_mds.dts b/arch/powerpc/boot/dts/mpc8377_mds.dts
index 8f54349..c11e529 100644
--- a/arch/powerpc/boot/dts/mpc8377_mds.dts
+++ b/arch/powerpc/boot/dts/mpc8377_mds.dts
@@ -210,6 +210,20 @@
 			#interrupt-cells = <2>;
 			reg = <700 100>;
 		};
+
+		ipic-msi@7c0 {
+			compatible = "fsl,ipic-msi";
+			reg = <7c0 40>;
+			interrupts = < 43 8
+				       4  8
+				       51 8
+				       52 8
+				       56 8
+				       57 8
+				       58 8
+				       59 8 >;
+			interrupt-parent = < &ipic >;
+		};
 	};
 
 	pci@e0008500 {
diff --git a/arch/powerpc/boot/dts/mpc8378_mds.dts b/arch/powerpc/boot/dts/mpc8378_mds.dts
index e09b0c5..7b0bf1b 100644
--- a/arch/powerpc/boot/dts/mpc8378_mds.dts
+++ b/arch/powerpc/boot/dts/mpc8378_mds.dts
@@ -192,6 +192,20 @@
 			#interrupt-cells = <2>;
 			reg = <700 100>;
 		};
+
+		ipic-msi@7c0 {
+			compatible = "fsl,ipic-msi";
+			reg = <7c0 40>;
+			interrupts = < 43 8
+				       4  8
+				       51 8
+				       52 8
+				       56 8
+				       57 8
+				       58 8
+				       59 8 >;
+			interrupt-parent = < &ipic >;
+		};
 	};
 
 	pci@e0008500 {
diff --git a/arch/powerpc/boot/dts/mpc8379_mds.dts b/arch/powerpc/boot/dts/mpc8379_mds.dts
index cdb4426..9fe4bd2 100644
--- a/arch/powerpc/boot/dts/mpc8379_mds.dts
+++ b/arch/powerpc/boot/dts/mpc8379_mds.dts
@@ -236,6 +236,20 @@
 			#interrupt-cells = <2>;
 			reg = <700 100>;
 		};
+
+		ipic-msi@7c0 {
+			compatible = "fsl,ipic-msi";
+			reg = <7c0 40>;
+			interrupts = < 43 8
+				       4  8
+				       51 8
+				       52 8
+				       56 8
+				       57 8
+				       58 8
+				       59 8 >;
+			interrupt-parent = < &ipic >;
+		};
 	};
 
 	pci@e0008500 {
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index 00154c5..4c51f78 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -88,6 +88,12 @@ config PPC_MPC837x
 	select FSL_SERDES
 	default y if MPC837x_MDS
 
+config IPIC_MSI
+	bool
+	depends on PCI_MSI
+	default y if PPC_MPC837x
+	default n
+
 config PPC_MPC83XX_PCIE
 	bool "MPC837X PCI Express support"
 	depends on PCIEPORTBUS && PPC_MPC837x
diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c
index b1d3570..f68a7e9 100644
--- a/arch/powerpc/platforms/83xx/mpc837x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c
@@ -17,6 +17,7 @@
 
 #include <asm/time.h>
 #include <asm/ipic.h>
+#include <asm/ipic_msi.h>
 #include <asm/udbg.h>
 #include <asm/prom.h>
 
@@ -94,6 +95,12 @@ static void __init mpc837x_mds_init_IRQ(void)
 	 * in case the boot rom changed something on us.
 	 */
 	ipic_set_default_priority();
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,ipic-msi");
+	if (!np)
+		return;
+
+	ipic_msi_init(np, ipic_msi_cascade);
 }
 
 /*
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 99a77d7..5946b6a 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -25,6 +25,7 @@ ifeq ($(CONFIG_PPC_MERGE),y)
 obj-$(CONFIG_PPC_INDIRECT_PCI)	+= indirect_pci.o
 obj-$(CONFIG_PPC_I8259)		+= i8259.o
 obj-$(CONFIG_PPC_83xx)		+= ipic.o
+obj-$(CONFIG_IPIC_MSI)		+= ipic_msi.o
 obj-$(CONFIG_4xx)		+= uic.o
 obj-$(CONFIG_XILINX_VIRTEX)	+= xilinx_intc.o
 endif
diff --git a/arch/powerpc/sysdev/ipic_msi.c b/arch/powerpc/sysdev/ipic_msi.c
new file mode 100644
index 0000000..6c54f50
--- /dev/null
+++ b/arch/powerpc/sysdev/ipic_msi.c
@@ -0,0 +1,359 @@
+/*
+ * arch/powerpc/sysdev/ipic_msi.c
+ *
+ * IPIC MSI routines implementations.
+ *
+ * Auther: Tony Li <tony.li@freescale.com>
+ *
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ */
+
+
+#include <linux/pci.h>
+#include <linux/msi.h>
+#include <linux/irq.h>
+
+#include <asm/ipic_msi.h>
+
+#define MSIR0	0x43
+#define MSIR1	0x4
+#define MSIR2	0x51
+#define MSIR3	0x52
+#define MSIR4	0x56
+#define MSIR5	0x57
+#define MSIR6	0x58
+#define MSIR7	0x59
+
+
+static struct ipic_msi *ipic_msi;
+static DEFINE_SPINLOCK(ipic_msi_lock);
+static DEFINE_SPINLOCK(ipic_msi_bitmap_lock);
+
+static inline u32 ipic_msi_read(volatile u32 __iomem *base, unsigned int reg)
+{
+	return in_be32(base + (reg >> 2));
+}
+
+static inline void ipic_msi_write(volatile u32 __iomem *base,
+					unsigned int reg, u32 value)
+{
+	out_be32(base + (reg >> 2), value);
+}
+
+static struct ipic_msi * ipic_msi_from_irq(unsigned int virq)
+{
+	return ipic_msi;
+}
+
+#define	ipic_msi_irq_to_hw(virq)	virq_to_hw(virq)
+static void ipic_msi_unmask(unsigned int virq)
+{
+	struct ipic_msi *msi = ipic_msi_from_irq(virq);
+	unsigned int src = ipic_msi_irq_to_hw(virq);
+	unsigned long flags;
+	u32 temp;
+
+	spin_lock_irqsave(&ipic_msi_lock, flags);
+	temp = ipic_msi_read(msi->regs, IPIC_MSIMR);
+	ipic_msi_write(msi->regs, IPIC_MSIMR,
+		temp & ~(1 << (src / msi->int_per_msir)));
+
+	spin_unlock_irqrestore(&ipic_msi_lock, flags);
+}
+
+static void ipic_msi_mask(unsigned int virq)
+{
+	struct ipic_msi *msi = ipic_msi_from_irq(virq);
+	unsigned int src = ipic_msi_irq_to_hw(virq);
+	unsigned long flags;
+	u32 temp;
+
+	spin_lock_irqsave(&ipic_msi_lock, flags);
+
+	temp = ipic_msi_read(msi->regs, IPIC_MSIMR);
+	ipic_msi_write(msi->regs, IPIC_MSIMR,
+		temp | (1 << (src / msi->int_per_msir)));
+
+	spin_unlock_irqrestore(&ipic_msi_lock, flags);
+}
+/*
+ * We do not need this actually. The MSIR register has been read once
+ * in ipic_msi_get_irq. So, this MSI interrupt has been acked
+ */
+static void ipic_msi_ack(unsigned int virq)
+{
+	struct ipic_msi *msi = ipic_msi_from_irq(virq);
+	unsigned int src = ipic_msi_irq_to_hw(virq);
+	unsigned long flags;
+
+	spin_lock_irqsave(&ipic_msi_lock, flags);
+
+	ipic_msi_read(msi->regs, IPIC_MSIR0 + (4 * (src / msi->int_per_msir)));
+
+	spin_unlock_irqrestore(&ipic_msi_lock,flags);
+}
+
+static struct irq_chip ipic_msi_chip = {
+	.typename = " IPIC MSI ",
+	.unmask = ipic_msi_unmask,
+	.mask = ipic_msi_mask,
+	.ack = ipic_msi_ack,
+};
+
+static int ipic_msi_host_map(struct irq_host *h, unsigned int virq,
+				irq_hw_number_t hw)
+{
+	struct ipic_msi *msi = h->host_data;
+	struct irq_chip *chip = msi->hc_irq;
+
+	set_irq_chip_data(virq, msi);
+	get_irq_desc(virq)->status |= IRQ_TYPE_EDGE_FALLING;
+
+	set_irq_chip_and_handler(virq, chip, handle_edge_irq);
+	return 0;
+}
+
+static struct irq_host_ops ipic_msi_host_ops = {
+	.map = ipic_msi_host_map,
+};
+
+irq_hw_number_t ipic_msi_alloc_hwirqs(struct ipic_msi *msi, int num)
+{
+	unsigned long flags;
+	int offset, order = get_count_order(num);
+
+	spin_lock_irqsave(&ipic_msi_bitmap_lock, flags);
+
+	offset = bitmap_find_free_region(msi->ipic_msi_bitmap,
+			msi->nr_msir * msi->int_per_msir, order);
+
+	spin_unlock_irqrestore(&ipic_msi_bitmap_lock, flags);
+
+	pr_debug("%s: allocated 0x%x (2^%d) at offset 0x%x\n",
+		__FUNCTION__, num, order, offset);
+
+	return offset;
+}
+
+void ipic_msi_free_hwirqs(struct ipic_msi *msi, int offset, int num)
+{
+	unsigned long flags;
+	int order = get_count_order(num);
+
+	pr_debug("%s: freeing 0x%x (2^%d) at offset 0x%x\n",
+		__FUNCTION__, num, order, offset);
+
+	spin_lock_irqsave(&ipic_msi_bitmap_lock, flags);
+	bitmap_release_region(msi->ipic_msi_bitmap, offset, order);
+	spin_unlock_irqrestore(&ipic_msi_bitmap_lock, flags);
+}
+
+static int ipic_msi_init_allocator(struct ipic_msi *msi)
+{
+	int size;
+
+	size = BITS_TO_LONGS(msi->nr_msir * msi->int_per_msir) * sizeof(long);
+	msi->ipic_msi_bitmap = alloc_maybe_bootmem(size, GFP_KERNEL);
+
+	if (msi->ipic_msi_bitmap == NULL) {
+		pr_debug("%s: ENOMEM allocating allocator bitmap!\n",
+				__FUNCTION__);
+		return -ENOMEM;
+	}
+	memset(msi->ipic_msi_bitmap, 0, size);
+
+	return 0;
+}
+
+static void ipic_msi_compose_msg(struct ipic_msi *msi, int hwirq,
+						struct msi_msg *msg)
+{
+	unsigned int srs;
+	unsigned int ibs;
+
+	srs = hwirq / msi->int_per_msir;
+	ibs = hwirq - srs * msi->int_per_msir;
+
+	msg->address_lo = msi->msi_addr_lo;
+	msg->address_hi = msi->msi_addr_hi;
+	msg->data = (srs << 5) | (ibs & 0x1F);
+
+	pr_debug("%s: allocated srs: %d, ibs: %d\n",
+		__FUNCTION__, srs, ibs);
+
+}
+
+static int ipic_msi_setup_irqs(struct pci_dev *pdev, int nvec, int type)
+{
+	struct ipic_msi *msi = ipic_msi;
+	irq_hw_number_t hwirq;
+	unsigned int virq;
+	struct msi_desc *entry;
+	struct msi_msg msg;
+
+	list_for_each_entry(entry, &pdev->msi_list, list) {
+		hwirq = ipic_msi_alloc_hwirqs(msi, 1);
+		if (hwirq < 0) {
+			pr_debug("%s: fail allocating msi interrupt\n",
+					__FUNCTION__);
+			return hwirq;
+		}
+
+		/* This hwirq belongs to the irq_host other than irq_host of IPIC
+ 		 * So, it is independent to hwirq of IPIC */
+		virq = irq_create_mapping(msi->irqhost, hwirq);
+		if (virq == NO_IRQ) {
+			pr_debug("%s: fail mapping hwirq 0x%lx\n",
+					__FUNCTION__, hwirq);
+			ipic_msi_free_hwirqs(msi, hwirq, 1);
+			return -ENOSPC;
+		}
+		set_irq_msi(virq, entry);
+		ipic_msi_compose_msg(msi, hwirq, &msg);
+		write_msi_msg(virq, &msg);
+	}
+
+	return 0;
+}
+
+static void ipic_msi_teardown_irqs(struct pci_dev *pdev)
+{
+	struct msi_desc *entry;
+	struct ipic_msi *msi = ipic_msi;
+
+	list_for_each_entry(entry, &pdev->msi_list, list) {
+		if (entry->irq == NO_IRQ)
+			continue;
+		set_irq_msi(entry->irq, NULL);
+		ipic_msi_free_hwirqs(msi, virq_to_hw(entry->irq), 1);
+		irq_dispose_mapping(entry->irq);
+	}
+
+	return;
+}
+
+void __init ipic_msi_init(struct device_node *node,
+			void (*handler)(unsigned int irq, struct irq_desc *desc))
+{
+	struct ipic_msi *msi;
+	struct resource res;
+	int i;
+	int rc = 0;
+
+	msi = alloc_maybe_bootmem(sizeof(*msi), GFP_KERNEL);
+	if (msi == NULL)
+		return;
+
+	memset(msi, 0, sizeof(*msi));
+
+
+	msi->irqhost = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LINEAR,
+					NR_MSIR, &ipic_msi_host_ops, 0);
+	if (msi->irqhost == NULL) {
+		of_node_put(node);
+		goto out;
+	}
+
+	rc = of_address_to_resource(node, 0, &res);
+	if (rc) {
+		of_node_put(node);
+		goto out;
+	}
+
+	msi->regs = ioremap(res.start, res.end - res.start + 1);
+	msi->irqhost->host_data = msi;
+	msi->hc_irq = &ipic_msi_chip;
+
+	msi->msi_addr_lo = 0xE00007F8;
+	msi->msi_addr_hi = 0;
+	msi->nr_msir = ARRAY_SIZE(msi->msir);
+	msi->int_per_msir = 32;
+	for (i = 0; i < msi->nr_msir; i++) {
+		unsigned int virt_msir = irq_of_parse_and_map(node, i);
+		if (virt_msir != NO_IRQ) {
+			set_irq_data(virt_msir, msi);
+			set_irq_chained_handler(virt_msir, handler);
+			msi->msir[i] = virt_msir;
+		} else
+			msi->msir[i] = NO_IRQ;
+	}
+
+	rc = ipic_msi_init_allocator(msi);
+	if (rc)
+		goto out;
+
+	ipic_msi = msi;
+
+	WARN_ON(ppc_md.setup_msi_irqs);
+	ppc_md.setup_msi_irqs = ipic_msi_setup_irqs;
+	ppc_md.teardown_msi_irqs = ipic_msi_teardown_irqs;
+
+	return;
+
+out:
+	if (mem_init_done)
+		kfree(msi);
+
+	return;
+}
+
+static int ipic_msi_get_irq(struct ipic_msi *msi, int virt_msir)
+{
+	int msir = -1;
+	unsigned int temp;
+	unsigned int offset;
+	int i;
+
+	for (i = 0; i < msi->nr_msir; i++)
+		if (virt_msir == msi->msir[i]) {
+			msir = i;
+			break;
+		}
+
+	if (i >= msi->nr_msir)
+		return NO_IRQ;
+
+	temp = ipic_msi_read(msi->regs, IPIC_MSIR0 + (i * 4));
+	offset = ffs(temp) - 1;
+
+	return irq_linear_revmap(msi->irqhost, (msir * msi->int_per_msir + offset));
+}
+
+void ipic_msi_cascade(unsigned int irq, struct irq_desc *desc)
+{
+	struct ipic_msi *msi;
+	unsigned int cascade_irq;
+
+	spin_lock(&desc->lock);
+	if (desc->chip->mask_ack)
+		desc->chip->mask_ack(irq);
+	else {
+		desc->chip->mask(irq);
+		desc->chip->ack(irq);
+	}
+
+	if (unlikely(desc->status & IRQ_INPROGRESS))
+		goto unlock;
+
+	desc->status |= IRQ_INPROGRESS;
+	msi = desc->handler_data;
+	cascade_irq = ipic_msi_get_irq(msi, irq);
+
+	spin_unlock(&desc->lock);
+
+	if (cascade_irq != NO_IRQ)
+		generic_handle_irq(cascade_irq);
+
+	spin_lock(&desc->lock);
+	desc->status &= ~IRQ_INPROGRESS;
+	if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
+		desc->chip->unmask(irq);
+
+unlock:
+	spin_unlock(&desc->lock);
+}
diff --git a/include/asm-powerpc/ipic_msi.h b/include/asm-powerpc/ipic_msi.h
new file mode 100644
index 0000000..2f578da
--- /dev/null
+++ b/include/asm-powerpc/ipic_msi.h
@@ -0,0 +1,66 @@
+/*
+ * include/asm-powerpc/ipic_msi.h
+ *
+ * IPIC MSI structure.
+ *
+ * Author: Tony Li <tony.li@freescale.com>
+ *
+ * Copyright (c) 2007 Freescale Semiconductor, Inc
+ *
+ * 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.
+ */
+#ifndef _ASM_POWERPC_IPIC_MSI_H
+#define _ASM_POWERPC_IPIC_MSI_H
+
+#define NR_MSIR	8
+/* MSI interrupt register offset compared to MSI base address (0xc0) */
+#define IPIC_MSIR0	0x0	/* MSI Interrupt Reg 0 */
+#define IPIC_MSIR1	0x4	/* MSI Interrupt Reg 1 */
+#define IPIC_MSIR2	0x8	/* MSI Interrupt Reg 2 */
+#define IPIC_MSIR3	0xC	/* MSI Interrupt Reg 3 */
+#define IPIC_MSIR4	0x10	/* MSI Interrupt Reg 4 */
+#define IPIC_MSIR5	0x14	/* MSI Interrupt Reg 5 */
+#define IPIC_MSIR6	0x18	/* MSI Interrupt Reg 6 */
+#define IPIC_MSIR7	0x1C	/* MSI Interrupt Reg 7 */
+#define IPIC_MSIMR	0x30	/* MSI Interrupt Mask Reg */
+#define IPIC_MSISR	0x34	/* MSI Interrupt Status Reg */
+#define IPIC_MSIIR	0x38	/* MSI Interrupt Index Reg */
+
+struct ipic_msi {
+	volatile u32 __iomem *regs;
+
+	struct irq_host *irqhost;
+	struct irq_chip *hc_irq;
+
+	unsigned long cascade_irq;
+	unsigned int msir[8];
+
+	u32 msi_addr_lo;
+	u32 msi_addr_hi;
+
+	int nr_msir;
+	int int_per_msir;
+
+	void *ipic_msi_bitmap;
+};
+
+#ifdef CONFIG_IPIC_MSI
+extern void ipic_msi_cascade(unsigned int irq, struct irq_desc *desc);
+extern void __init ipic_msi_init(struct device_node *node,
+		void (*handler)(unsigned int irq, struct irq_desc *desc));
+#else
+void __inline__ ipic_msi_cascade(unsigned int irq, struct irq_desc *desc)
+{
+	return;
+}
+void __inline__ __init ipic_msi_init(struct device_node *node,
+		void (*handler)(unsigned int irq, struct irq_desc *desc))
+{
+	return;
+}
+#endif
+
+#endif /* _ASM_POWERPC_IPIC_MSI_H */
-- 
1.5.2

^ permalink raw reply related

* [PATCH 1/2] powerpc: Add MPC837xE MDS PCIE RC mode support
From: Li Li @ 2007-12-04 10:35 UTC (permalink / raw)
  To: Kumar Gala, kim phillips, linuxppc-dev

Modified based on discussion in list.

1.Change the device node to pcie
2.Add PPC_83XX_PCI_PRIMARY flag
3.Rearrange the codes

The PCIE controller is initiated in u-boot.

Signed-off-by: Tony Li <tony.li@freescale.com>
---
 arch/powerpc/boot/dts/mpc8377_mds.dts     |   54 ++++++++--
 arch/powerpc/boot/dts/mpc8378_mds.dts     |   54 ++++++++--
 arch/powerpc/platforms/83xx/Kconfig       |    7 +
 arch/powerpc/platforms/83xx/mpc8313_rdb.c |   10 ++-
 arch/powerpc/platforms/83xx/mpc832x_mds.c |   12 ++-
 arch/powerpc/platforms/83xx/mpc832x_rdb.c |   10 ++-
 arch/powerpc/platforms/83xx/mpc834x_itx.c |   10 ++-
 arch/powerpc/platforms/83xx/mpc834x_mds.c |   10 ++-
 arch/powerpc/platforms/83xx/mpc836x_mds.c |   12 ++-
 arch/powerpc/platforms/83xx/mpc837x_mds.c |   19 +++-
 arch/powerpc/platforms/83xx/mpc83xx.h     |    6 +-
 arch/powerpc/platforms/83xx/pci.c         |  174 +++++++++++++++++++++++++++--
 12 files changed, 338 insertions(+), 40 deletions(-)

diff --git a/arch/powerpc/boot/dts/mpc8377_mds.dts b/arch/powerpc/boot/dts/mpc8377_mds.dts
index 4402e39..8f54349 100644
--- a/arch/powerpc/boot/dts/mpc8377_mds.dts
+++ b/arch/powerpc/boot/dts/mpc8377_mds.dts
@@ -197,14 +197,6 @@
 			clock = <d#100>;
 		};
 
-		serdes2:serdes@e3100 {
-			compatible = "fsl,serdes";
-			reg = <e3100 100>;
-			vdd-1v;
-			protocol = "pcie";
-			clock = <d#100>;
-		};
-
 		/* IPIC
 		 * interrupts cell = <intr #, sense>
 		 * sense values match linux IORESOURCE_IRQ_* defines:
@@ -279,4 +271,50 @@
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};
+
+	pcie@e0009000 {
+		interrupt-map-mask = <f800 0 0 7>;
+		interrupt-map = <
+			0000 0 0 1 &ipic 1 8
+			0000 0 0 2 &ipic 1 8
+			0000 0 0 3 &ipic 1 8
+			0000 0 0 4 &ipic 1 8
+		>;
+		interrupt-parent = < &ipic >;
+		interrupts = <1 8>;
+		bus-range = <0 0>;
+		ranges = <02000000 0 A8000000 A8000000 0 10000000
+		          01000000 0 00000000 B8000000 0 00800000>;
+		clock-frequency = <0>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <e0009000 00001000
+		       a0000000 08000000>;
+		compatible = "fsl,mpc8377-pcie";
+		device_type = "pci";
+	};
+
+	pcie@e000a000 {
+		interrupt-map-mask = <f800 0 0 7>;
+		interrupt-map = <
+			0000 0 0 1 &ipic 2 8
+			0000 0 0 2 &ipic 2 8
+			0000 0 0 3 &ipic 2 8
+			0000 0 0 4 &ipic 2 8
+		>;
+		interrupt-parent = < &ipic >;
+		interrupts = <2 8>;
+		bus-range = <0 0>;
+		ranges = <02000000 0 C8000000 C8000000 0 10000000
+			  01000000 0 00000000 D8000000 0 00800000>;
+		clock-frequency = <0>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <e000a000 00001000
+		       c0000000 08000000>;
+		compatible = "fsl,mpc8377-pcie";
+		device_type = "pci";
+	};
 };
diff --git a/arch/powerpc/boot/dts/mpc8378_mds.dts b/arch/powerpc/boot/dts/mpc8378_mds.dts
index 54171f4..e09b0c5 100644
--- a/arch/powerpc/boot/dts/mpc8378_mds.dts
+++ b/arch/powerpc/boot/dts/mpc8378_mds.dts
@@ -179,14 +179,6 @@
 			clock = <d#100>;
 		};
 
-		serdes2:serdes@e3100 {
-			compatible = "fsl,serdes";
-			reg = <e3100 100>;
-			vdd-1v;
-			protocol = "pcie";
-			clock = <d#100>;
-		};
-
 		/* IPIC
 		 * interrupts cell = <intr #, sense>
 		 * sense values match linux IORESOURCE_IRQ_* defines:
@@ -261,4 +253,50 @@
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};
+
+	pcie@e0009000 {
+		interrupt-map-mask = <f800 0 0 7>;
+		interrupt-map = <
+			0000 0 0 1 &ipic 1 8
+			0000 0 0 2 &ipic 1 8
+			0000 0 0 3 &ipic 1 8
+			0000 0 0 4 &ipic 1 8
+		>;
+		interrupt-parent = < &ipic >;
+		interrupts = <1 8>;
+		bus-range = <0 0>;
+		ranges = <02000000 0 A8000000 A8000000 0 10000000
+		          01000000 0 00000000 B8000000 0 00800000>;
+		clock-frequency = <0>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <e0009000 00001000
+		       a0000000 08000000>;
+		compatible = "fsl,mpc8377-pcie";
+		device_type = "pci";
+	};
+
+	pcie@e000a000 {
+		interrupt-map-mask = <f800 0 0 7>;
+		interrupt-map = <
+			0000 0 0 1 &ipic 2 8
+			0000 0 0 2 &ipic 2 8
+			0000 0 0 3 &ipic 2 8
+			0000 0 0 4 &ipic 2 8
+		>;
+		interrupt-parent = < &ipic >;
+		interrupts = <2 8>;
+		bus-range = <0 0>;
+		ranges = <02000000 0 C8000000 C8000000 0 10000000
+			  01000000 0 00000000 D8000000 0 00800000>;
+		clock-frequency = <0>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <e000a000 00001000
+		       c0000000 08000000>;
+		compatible = "fsl,mpc8377-pcie";
+		device_type = "pci";
+	};
 };
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index 0c61e7a..00154c5 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -87,3 +87,10 @@ config PPC_MPC837x
 	select PPC_INDIRECT_PCI
 	select FSL_SERDES
 	default y if MPC837x_MDS
+
+config PPC_MPC83XX_PCIE
+	bool "MPC837X PCI Express support"
+	depends on PCIEPORTBUS && PPC_MPC837x
+	default n
+	help
+	  Enables MPC837x PCI express RC mode
diff --git a/arch/powerpc/platforms/83xx/mpc8313_rdb.c b/arch/powerpc/platforms/83xx/mpc8313_rdb.c
index 33766b8..25d8df4 100644
--- a/arch/powerpc/platforms/83xx/mpc8313_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc8313_rdb.c
@@ -37,14 +37,20 @@ static void __init mpc8313_rdb_setup_arch(void)
 {
 #ifdef CONFIG_PCI
 	struct device_node *np;
+	int primary_pci_bus = 1;
 #endif
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc8313_rdb_setup_arch()", 0);
 
 #ifdef CONFIG_PCI
-	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
-		mpc83xx_add_bridge(np);
+	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
+		if (primary_pci_bus) {
+			mpc83xx_add_bridge(np, PPC_83XX_PCI | PPC_83XX_PCI_PRIMARY);
+			primary_pci_bus = 0;
+		} else
+			mpc83xx_add_bridge(np, PPC_83XX_PCI);
+	}
 #endif
 	mpc831x_usb_cfg();
 }
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c
index 972fa85..ddb0b2e 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c
@@ -58,6 +58,9 @@ static u8 *bcsr_regs = NULL;
 static void __init mpc832x_sys_setup_arch(void)
 {
 	struct device_node *np;
+#ifdef CONFIG_PCI
+	int primary_pci_bus = 1;
+#endif
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc832x_sys_setup_arch()", 0);
@@ -73,8 +76,13 @@ static void __init mpc832x_sys_setup_arch(void)
 	}
 
 #ifdef CONFIG_PCI
-	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
-		mpc83xx_add_bridge(np);
+	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
+		if (primary_pci_bus) {
+			mpc83xx_add_bridge(np, PPC_83XX_PCI | PPC_83XX_PCI_PRIMARY);
+			primary_pci_bus = 0;
+		} else
+			mpc83xx_add_bridge(np, PPC_83XX_PCI);
+	}
 #endif
 
 #ifdef CONFIG_QUICC_ENGINE
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
index fbca336..aef35f5 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
@@ -87,14 +87,20 @@ static void __init mpc832x_rdb_setup_arch(void)
 {
 #if defined(CONFIG_PCI) || defined(CONFIG_QUICC_ENGINE)
 	struct device_node *np;
+	int primary_pci_bus = 1;
 #endif
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc832x_rdb_setup_arch()", 0);
 
 #ifdef CONFIG_PCI
-	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
-		mpc83xx_add_bridge(np);
+	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
+		if (primary_pci_bus) {
+			mpc83xx_add_bridge(np, PPC_83XX_PCI | PPC_83XX_PCI_PRIMARY);
+			primary_pci_bus = 0;
+		} else
+			mpc83xx_add_bridge(np, PPC_83XX_PCI);
+	}
 #endif
 
 #ifdef CONFIG_QUICC_ENGINE
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index aa76819..c428f62 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -46,14 +46,20 @@ static void __init mpc834x_itx_setup_arch(void)
 {
 #ifdef CONFIG_PCI
 	struct device_node *np;
+	int primary_pci_bus = 1;
 #endif
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc834x_itx_setup_arch()", 0);
 
 #ifdef CONFIG_PCI
-	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
-		mpc83xx_add_bridge(np);
+	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
+		if (primary_pci_bus) {
+			mpc83xx_add_bridge(np, PPC_83XX_PCI | PPC_83XX_PCI_PRIMARY);
+			primary_pci_bus = 0;
+		} else
+			mpc83xx_add_bridge(np, PPC_83XX_PCI);
+	}
 #endif
 
 	mpc834x_usb_cfg();
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c
index 00aed7c..e86dce8 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c
@@ -77,14 +77,20 @@ static void __init mpc834x_mds_setup_arch(void)
 {
 #ifdef CONFIG_PCI
 	struct device_node *np;
+	int primary_pci_bus = 1;
 #endif
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc834x_mds_setup_arch()", 0);
 
 #ifdef CONFIG_PCI
-	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
-		mpc83xx_add_bridge(np);
+	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
+		if (primary_pci_bus) {
+			mpc83xx_add_bridge(np, PPC_83XX_PCI | PPC_83XX_PCI_PRIMARY);
+			primary_pci_bus = 0;
+		} else
+			mpc83xx_add_bridge(np, PPC_83XX_PCI);
+	}
 #endif
 
 	mpc834xemds_usb_cfg();
diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c
index 0f3855c..6e6670c 100644
--- a/arch/powerpc/platforms/83xx/mpc836x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c
@@ -64,6 +64,9 @@ static u8 *bcsr_regs = NULL;
 static void __init mpc836x_mds_setup_arch(void)
 {
 	struct device_node *np;
+#ifdef CONFIG_PCI
+	int primary_pci_bus = 1;
+#endif
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc836x_mds_setup_arch()", 0);
@@ -79,8 +82,13 @@ static void __init mpc836x_mds_setup_arch(void)
 	}
 
 #ifdef CONFIG_PCI
-	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
-		mpc83xx_add_bridge(np);
+	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
+		if (primary_pci_bus) {
+			mpc83xx_add_bridge(np, PPC_83XX_PCI | PPC_83XX_PCI_PRIMARY);
+			primary_pci_bus = 0;
+		} else
+			mpc83xx_add_bridge(np, PPC_83XX_PCI);
+	}
 #endif
 
 #ifdef CONFIG_QUICC_ENGINE
diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c
index 166c111..b1d3570 100644
--- a/arch/powerpc/platforms/83xx/mpc837x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c
@@ -36,14 +36,29 @@ static void __init mpc837x_mds_setup_arch(void)
 {
 #ifdef CONFIG_PCI
 	struct device_node *np;
+	int primary_pci_bus = 1;
 #endif
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc837x_mds_setup_arch()", 0);
 
 #ifdef CONFIG_PCI
-	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
-		mpc83xx_add_bridge(np);
+	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
+		if (primary_pci_bus) {
+			mpc83xx_add_bridge(np, PPC_83XX_PCI | PPC_83XX_PCI_PRIMARY);
+			primary_pci_bus = 0;
+		} else
+			mpc83xx_add_bridge(np, PPC_83XX_PCI);
+	}
+#endif
+#ifdef CONFIG_PPC_MPC83XX_PCIE
+	for_each_compatible_node(np, "pci", "fsl,mpc8377-pcie") {
+		if (primary_pci_bus) {
+			mpc83xx_add_bridge(np, PPC_83XX_PCIE | PPC_83XX_PCI_PRIMARY);
+			primary_pci_bus = 0;
+		} else
+			mpc83xx_add_bridge(np, PPC_83XX_PCIE);
+	}
 #endif
 }
 
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h
index b778cb4..552e9bf 100644
--- a/arch/powerpc/platforms/83xx/mpc83xx.h
+++ b/arch/powerpc/platforms/83xx/mpc83xx.h
@@ -47,8 +47,10 @@
  * Declaration for the various functions exported by the
  * mpc83xx_* files. Mostly for use by mpc83xx_setup
  */
-
-extern int mpc83xx_add_bridge(struct device_node *dev);
+#define PPC_83XX_PCI_PRIMARY	0x1
+#define PPC_83XX_PCI		0x2
+#define PPC_83XX_PCIE		0x4
+extern int mpc83xx_add_bridge(struct device_node *dev, int flags);
 extern void mpc83xx_restart(char *cmd);
 extern long mpc83xx_time_init(void);
 extern int mpc834x_usb_cfg(void);
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c
index 80425d7..9004140 100644
--- a/arch/powerpc/platforms/83xx/pci.c
+++ b/arch/powerpc/platforms/83xx/pci.c
@@ -25,6 +25,8 @@
 #include <asm/prom.h>
 #include <sysdev/fsl_soc.h>
 
+#include "mpc83xx.h"
+
 #undef DEBUG
 
 #ifdef DEBUG
@@ -33,13 +35,159 @@
 #define DBG(x...)
 #endif
 
-int __init mpc83xx_add_bridge(struct device_node *dev)
+#if defined(CONFIG_PPC_MPC83XX_PCIE)
+
+/* PCIE Registers */
+#define PEX_LTSSM_STAT		0x404
+#define PEX_LTSSM_STAT_L0	0x16
+#define PEX_GCLK_RATIO		0x440
+
+/* PCIE config space Read/Write routines */
+static int direct_read_config_pcie(struct pci_bus *bus,
+			uint devfn, int offset, int len, u32 *val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	void __iomem *cfg_addr;
+	u32 bus_no;
+
+	if (hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if (ppc_md.pci_exclude_device)
+		if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
+			return PCIBIOS_DEVICE_NOT_FOUND;
+
+	switch (len) {
+	case 2:
+		if (offset & 1)
+			return -EINVAL;
+		break;
+	case 4:
+	if (offset & 3)
+		return -EINVAL;
+		break;
+	}
+
+	pr_debug("_read_cfg_pcie: bus=%d devfn=%x off=%x len=%x\n",
+		bus->number, devfn, offset, len);
+
+	if (bus->number == hose->first_busno) {
+		/*
+		 * The PCIE can only link one device.
+		 * It`s device number must be 0
+		 */
+		if (devfn & 0xf8)
+			return PCIBIOS_DEVICE_NOT_FOUND;
+		bus_no = hose->self_busno;
+	} else
+		bus_no = bus->number;
+
+	cfg_addr = (void __iomem *)((ulong) hose->cfg_addr +
+		((bus_no << 20) | (devfn << 12) | (offset & 0xfff)));
+
+	switch (len) {
+	case 1:
+		*val = in_8(cfg_addr);
+		break;
+	case 2:
+		*val = in_le16(cfg_addr);
+		break;
+	default:
+		*val = in_le32(cfg_addr);
+		break;
+	}
+	pr_debug("_read_cfg_pcie: val=%x cfg_addr=%p\n", *val, cfg_addr);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int direct_write_config_pcie(struct pci_bus *bus,
+			uint devfn, int offset, int len, u32 val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	void __iomem *cfg_addr;
+	u32 bus_no;
+
+	if (hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if (ppc_md.pci_exclude_device)
+		if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
+			return PCIBIOS_DEVICE_NOT_FOUND;
+
+	switch (len) {
+	case 2:
+		if (offset & 1)
+			return -EINVAL;
+		break;
+	case 4:
+		if (offset & 3)
+			return -EINVAL;
+		break;
+	}
+
+	if (bus->number == hose->first_busno) {
+		/*
+		 * The PCIE can only link one device.
+		 * It`s device number must be 0
+		 */
+		if (devfn & 0xf8)
+			return PCIBIOS_DEVICE_NOT_FOUND;
+		bus_no = hose->self_busno;
+	} else
+		bus_no = bus->number;
+
+	cfg_addr = (void __iomem *)((ulong) hose->cfg_addr +
+		((bus_no << 20) | (devfn << 12) | (offset & 0xfff)));
+
+	switch (len) {
+	case 1:
+		out_8(cfg_addr, val);
+		break;
+	case 2:
+		out_le16(cfg_addr, val);
+		break;
+	default:
+		out_le32(cfg_addr, val);
+		break;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops direct_pcie_ops = {
+	direct_read_config_pcie,
+	direct_write_config_pcie
+};
+
+static void __init mpc83xx_setup_pcie(struct pci_controller *hose,
+			struct resource *reg, struct resource *cfg_space)
+{
+	void __iomem *hose_cfg_base, *mbase;
+	u32 val;
+
+	hose_cfg_base = ioremap(reg->start, reg->end - reg->start + 1);
+
+	val = in_le32(hose_cfg_base + PEX_LTSSM_STAT);
+	if (val < PEX_LTSSM_STAT_L0)
+		hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
+
+	mbase = ioremap(cfg_space->start & PAGE_MASK, cfg_space->end - cfg_space->start + 1);
+	hose->cfg_addr = mbase + (cfg_space->start & ~PAGE_MASK);
+	hose->ops = &direct_pcie_ops;
+}
+#endif /* CONFIG_PPC_MPC83XX_PCIE */
+
+int __init mpc83xx_add_bridge(struct device_node *dev, int flags)
 {
 	int len;
 	struct pci_controller *hose;
 	struct resource rsrc;
+#if defined(CONFIG_PPC_MPC83XX_PCIE)
+	struct resource cfg_space;
+#endif
 	const int *bus_range;
-	int primary = 1, has_address = 0;
+	int has_address = 0;
 	phys_addr_t immr = get_immrbase();
 
 	DBG("Adding PCI host bridge %s\n", dev->full_name);
@@ -63,17 +211,24 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
 	hose->last_busno = bus_range ? bus_range[1] : 0xff;
 
 	/* MPC83xx supports up to two host controllers one at 0x8500 from immrbar
-	 * the other at 0x8600, we consider the 0x8500 the primary controller
+	 * the other at 0x8600.
 	 */
 	/* PCI 1 */
-	if ((rsrc.start & 0xfffff) == 0x8500) {
+	if ((rsrc.start & 0xfffff) == 0x8500)
 		setup_indirect_pci(hose, immr + 0x8300, immr + 0x8304, 0);
-	}
 	/* PCI 2 */
-	if ((rsrc.start & 0xfffff) == 0x8600) {
+	if ((rsrc.start & 0xfffff) == 0x8600)
 		setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384, 0);
-		primary = 0;
+
+#if defined(CONFIG_PPC_MPC83XX_PCIE)
+	if (flags & PPC_83XX_PCIE) {
+		if (of_address_to_resource(dev, 1, &cfg_space)) {
+			printk("PCIE RC losts configure space. Skip it\n");
+			return 1;
+		}
+		mpc83xx_setup_pcie(hose, &rsrc, &cfg_space);
 	}
+#endif
 
 	printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%016llx. "
 	       "Firmware bus number: %d->%d\n",
@@ -85,7 +240,10 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
 
 	/* Interpret the "ranges" property */
 	/* This also maps the I/O region and sets isa_io/mem_base */
-	pci_process_bridge_OF_ranges(hose, dev, primary);
+	if (flags & PPC_83XX_PCI_PRIMARY)
+		pci_process_bridge_OF_ranges(hose, dev, 1);
+	else
+		pci_process_bridge_OF_ranges(hose, dev, 0);
 
 	return 0;
 }
-- 
1.5.2

^ 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