* Re: [alsa-devel] [PATCH 1/2] powerpc: add platform registration for ALSA SoC drivers
From: Benjamin Herrenschmidt @ 2010-04-29 0:50 UTC (permalink / raw)
To: Timur Tabi; +Cc: alsa-devel, kumar.gala, Mark Brown, linuxppc-dev, lrg
In-Reply-To: <j2qed82fe3e1004281335h4076b050jc2894d4c4d6eac65@mail.gmail.com>
On Wed, 2010-04-28 at 15:35 -0500, Timur Tabi wrote:
> Second, how about this binding for the virtual sound node? It would
> be a root-level node.
>
> sound-devices {
> sound0 {
> ssi = &ssi0;
> playback-dma = &dma00;
> capture-dma = &dma01;
> codec = &cs4270;
> }
> };
Make sure you also have a "compatible" property to uniquely identify the
design. You could use the toplevel board one but I'd rather keep a
separate one here. I've seen case where the exact same base board may
have different sound components (because they are dautherboards for
example, but there's a few other cases).
Cheers,
Ben.
^ permalink raw reply
* PowerPC ftrace function trace optimisation
From: Anton Blanchard @ 2010-04-29 0:51 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus, imunsie, rostedt, amodra
Hi,
Alan Modra pointed out that he added an option to PowerPC gcc years ago
specifically for us to do lightweight mcount profiling.
The normal PowerPC gcc mcount stuff forces a stack spill and gets itself
tangled up in the function prolog, making it impossible to nop out easily:
# gcc -pg:
0000000000000000 <.foo>:
0: 7c 08 02 a6 mflr r0 <--- shared stack spill code
4: f8 01 00 10 std r0,16(r1) <--|
8: f8 21 ff 91 stdu r1,-112(r1) <--+
c: 48 00 00 01 bl c <.foo+0xc> <--- call to mcount
10: 60 00 00 00 nop
14: e9 22 00 00 ld r9,0(r2)
18: e8 69 00 02 lwa r3,0(r9)
1c: 38 21 00 70 addi r1,r1,112
20: e8 01 00 10 ld r0,16(r1)
24: 7c 08 03 a6 mtlr r0
28: 4e 80 00 20 blr
The option Alan added reduces the footprint to 3 instructions which can
be noped out completely. The rest of the function does not rely on the first
three instructions. No stack spill is forced either:
# gcc -pg -mprofile-kernel
0000000000000000 <.foo>:
0: 7c 08 02 a6 mflr r0
4: f8 01 00 10 std r0,16(r1)
8: 48 00 00 01 bl 8 <.foo+0x8> <--- call to mcount
c: 7c 08 02 a6 mflr r0
10: f8 01 00 10 std r0,16(r1)
14: f8 21 ff d1 stdu r1,-48(r1)
18: e9 22 00 00 ld r9,0(r2)
1c: e8 69 00 02 lwa r3,0(r9)
20: 38 21 00 30 addi r1,r1,48
24: e8 01 00 10 ld r0,16(r1)
28: 7c 08 03 a6 mtlr r0
2c: 4e 80 00 20 blr
This mean we could support ftrace function trace with very little overhead.
In fact if we are careful when switching to the new mcount ABI and don't
rely on the store of r0, we could probably optimise this even further in a
future gcc and remove the store completely. mcount would be 2 instructions:
mflr r0
bl 8 <.foo+0x8>
Anton
^ permalink raw reply
* Re: [alsa-devel] [PATCH 1/2] powerpc: add platform registration for ALSA SoC drivers
From: Benjamin Herrenschmidt @ 2010-04-29 0:52 UTC (permalink / raw)
To: Timur Tabi
Cc: alsa-devel, kumar.gala, Mark Brown, linuxppc-dev,
devicetree-discuss, lrg
In-Reply-To: <r2oed82fe3e1004281513k23b54b56v7904a4a34750c90b@mail.gmail.com>
On Wed, 2010-04-28 at 17:13 -0500, Timur Tabi wrote:
> On Wed, Apr 28, 2010 at 4:58 PM, Grant Likely <grant.likely@secretlab.ca> wrote:
>
> > The sound0 node needs a compatible value,
>
> I knew I was forgetting something
>
> > the sound-device node should
> > probably have one too.
>
> The aliases, cpus, and memory node don't have a compatible property,
> and I was modeling the design after the aliases node.
aliases is a bad choice, it's very very special and is neither a device
nor a virtual device, like chosen.
cpus is more of a match in your case.
In any case, I agree, you may not really need a compatible prop for the
virtual device. In fact, Grant, do we really need an enclosing node like
that ? In any case, it's no big deal and shouldn't have much impact on
the design.
Cheers,
Ben.
> > The sound0 node should have something board specific like
> > "fsl,mpc8610hpcd-sound" to make it clear that the binding really only
> > applies to this particular board. It would also be a good idea to
> > prefix all of the property names with 'fsl,' to avoid conflicting with
> > any future common bindings or conventions. Other boards can use the
> > same binding, but they would get a different compatible value (the
> > driver could bind on both).
>
> The aliases node doesn't have an fsl, prefix. I understand the need
> for the prefix, but I wonder why we don't do that for the aliases
> node.
>
> > I'm not a huge fan of the name "sound-devices" for the parent node.
> > There are other sorts of things that we need 'virtual' device nodes to
> > describe. It would be nice to have a single place for collecting
> > nodes for stuff like this. Perhaps this:
> >
> > system {
> > compatible = "system-devices";
> > sound0 {
> > compatible = "fsl,mpc8610hpcd-sound";
> > fsl,ssi = &ssi0;
> > fsl,playback-dma = &dma00;
> > fsl,capture-dma = &dma01;
> > fsl,codec = &cs4270;
> > };
> > };
>
> I like that.
>
^ permalink raw reply
* Re: PowerPC ftrace function trace optimisation
From: Benjamin Herrenschmidt @ 2010-04-29 1:02 UTC (permalink / raw)
To: Anton Blanchard; +Cc: linuxppc-dev, paulus, imunsie, rostedt, amodra
In-Reply-To: <20100429005117.GA4622@kryten>
> The option Alan added reduces the footprint to 3 instructions which can
> be noped out completely. The rest of the function does not rely on the first
> three instructions. No stack spill is forced either:
>
> # gcc -pg -mprofile-kernel
>From a quick test it appears that this only works with -m64, not -m32.
Alan is that correct ? Any chance you can fix that in future gcc
versions ?
Also should we implement support for both type of mcounts or just only
allow enabling of ftrace with gcc's that support this ?
Cheers,
Ben.
> 0000000000000000 <.foo>:
> 0: 7c 08 02 a6 mflr r0
> 4: f8 01 00 10 std r0,16(r1)
> 8: 48 00 00 01 bl 8 <.foo+0x8> <--- call to mcount
>
> c: 7c 08 02 a6 mflr r0
> 10: f8 01 00 10 std r0,16(r1)
> 14: f8 21 ff d1 stdu r1,-48(r1)
> 18: e9 22 00 00 ld r9,0(r2)
> 1c: e8 69 00 02 lwa r3,0(r9)
> 20: 38 21 00 30 addi r1,r1,48
> 24: e8 01 00 10 ld r0,16(r1)
> 28: 7c 08 03 a6 mtlr r0
> 2c: 4e 80 00 20 blr
>
>
> This mean we could support ftrace function trace with very little overhead.
>
> In fact if we are careful when switching to the new mcount ABI and don't
> rely on the store of r0, we could probably optimise this even further in a
> future gcc and remove the store completely. mcount would be 2 instructions:
>
> mflr r0
> bl 8 <.foo+0x8>
>
> Anton
^ permalink raw reply
* Re: PowerPC ftrace function trace optimisation
From: Benjamin Herrenschmidt @ 2010-04-29 1:08 UTC (permalink / raw)
To: Anton Blanchard; +Cc: linuxppc-dev, paulus, imunsie, rostedt, amodra
In-Reply-To: <1272502967.24542.137.camel@pasglop>
On Thu, 2010-04-29 at 11:02 +1000, Benjamin Herrenschmidt wrote:
> > The option Alan added reduces the footprint to 3 instructions which can
> > be noped out completely. The rest of the function does not rely on the first
> > three instructions. No stack spill is forced either:
> >
> > # gcc -pg -mprofile-kernel
>
> >From a quick test it appears that this only works with -m64, not -m32.
> Alan is that correct ? Any chance you can fix that in future gcc
> versions ?
>
> Also should we implement support for both type of mcounts or just only
> allow enabling of ftrace with gcc's that support this ?
Also, Anton noticed :
> Cheers,
> Ben.
>
> > 0000000000000000 <.foo>:
> > 0: 7c 08 02 a6 mflr r0
> > 4: f8 01 00 10 std r0,16(r1)
The std is not useful here. We can do it inside mcount.
> > 8: 48 00 00 01 bl 8 <.foo+0x8> <--- call to mcount
And I noticed:
> > c: 7c 08 02 a6 mflr r0
I'm happy to guarantee that mcount does the above.
> > 10: f8 01 00 10 std r0,16(r1)
And maybe that one too.
However I understand if it's easier not to change the prolog codegen
(the 2 insn above) and just stick to adding a 2 or 3 instructions
boilerplate at the top.
Cheers,
Ben.
> > 14: f8 21 ff d1 stdu r1,-48(r1)
> > 18: e9 22 00 00 ld r9,0(r2)
> > 1c: e8 69 00 02 lwa r3,0(r9)
> > 20: 38 21 00 30 addi r1,r1,48
> > 24: e8 01 00 10 ld r0,16(r1)
> > 28: 7c 08 03 a6 mtlr r0
> > 2c: 4e 80 00 20 blr
> >
> >
> > This mean we could support ftrace function trace with very little overhead.
> >
> > In fact if we are careful when switching to the new mcount ABI and don't
> > rely on the store of r0, we could probably optimise this even further in a
> > future gcc and remove the store completely. mcount would be 2 instructions:
> >
> > mflr r0
> > bl 8 <.foo+0x8>
> >
> > Anton
>
^ permalink raw reply
* Re: PowerPC ftrace function trace optimisation
From: Alan Modra @ 2010-04-29 1:22 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: linuxppc-dev, paulus, Anton Blanchard, rostedt, imunsie
In-Reply-To: <1272502967.24542.137.camel@pasglop>
On Thu, Apr 29, 2010 at 11:02:47AM +1000, Benjamin Herrenschmidt wrote:
> From a quick test it appears that this only works with -m64, not -m32.
> Alan is that correct ?
Yes.
> Any chance you can fix that in future gcc versions ?
No need really. 32-bit _mcount calls happen before the prologue
anyway.
> > In fact if we are careful when switching to the new mcount ABI and don't
> > rely on the store of r0, we could probably optimise this even further in a
> > future gcc and remove the store completely. mcount would be 2 instructions:
> >
> > mflr r0
> > bl 8 <.foo+0x8>
Yeah. Also, I should have used a different name for this mcount from
the standard 64-bit mcount.
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply
* Re: PowerPC ftrace function trace optimisation
From: Steven Rostedt @ 2010-04-29 1:55 UTC (permalink / raw)
To: Anton Blanchard; +Cc: linuxppc-dev, imunsie, paulus, amodra
In-Reply-To: <20100429005117.GA4622@kryten>
On Thu, 2010-04-29 at 10:51 +1000, Anton Blanchard wrote:
> Hi,
> # gcc -pg -mprofile-kernel
>
> 0000000000000000 <.foo>:
> 0: 7c 08 02 a6 mflr r0
> 4: f8 01 00 10 std r0,16(r1)
> 8: 48 00 00 01 bl 8 <.foo+0x8> <--- call to mcount
>
> c: 7c 08 02 a6 mflr r0
Why the extra mflr? Can't we just make it a requirement that mcount
returns with r0 back to what it was?
-- Steve
> 10: f8 01 00 10 std r0,16(r1)
> 14: f8 21 ff d1 stdu r1,-48(r1)
> 18: e9 22 00 00 ld r9,0(r2)
> 1c: e8 69 00 02 lwa r3,0(r9)
> 20: 38 21 00 30 addi r1,r1,48
> 24: e8 01 00 10 ld r0,16(r1)
> 28: 7c 08 03 a6 mtlr r0
> 2c: 4e 80 00 20 blr
>
>
> This mean we could support ftrace function trace with very little overhead.
>
> In fact if we are careful when switching to the new mcount ABI and don't
> rely on the store of r0, we could probably optimise this even further in a
> future gcc and remove the store completely. mcount would be 2 instructions:
>
> mflr r0
> bl 8 <.foo+0x8>
>
> Anton
^ permalink raw reply
* Re: PowerPC ftrace function trace optimisation
From: Benjamin Herrenschmidt @ 2010-04-29 2:10 UTC (permalink / raw)
To: rostedt; +Cc: linuxppc-dev, paulus, Anton Blanchard, imunsie, amodra
In-Reply-To: <1272506103.9739.112.camel@gandalf.stny.rr.com>
On Wed, 2010-04-28 at 21:55 -0400, Steven Rostedt wrote:
> On Thu, 2010-04-29 at 10:51 +1000, Anton Blanchard wrote:
> > Hi,
>
> > # gcc -pg -mprofile-kernel
> >
> > 0000000000000000 <.foo>:
> > 0: 7c 08 02 a6 mflr r0
> > 4: f8 01 00 10 std r0,16(r1)
> > 8: 48 00 00 01 bl 8 <.foo+0x8> <--- call to mcount
> >
> > c: 7c 08 02 a6 mflr r0
>
> Why the extra mflr? Can't we just make it a requirement that mcount
> returns with r0 back to what it was?
Well, we can't just change that now, it's been in for long enough.
We might be able to get a new option later on that makes it more
efficient tho (for example removing the std), but let's see what we can
do with what we have.
The extra mflr makes sense if you consider that the option just
pre-pends a pre-canned set of instructions and doesn't actually touch
anything to the prolog generation. It might be possible to do a hack to
make the prolog aware that LR is already in r0 but let's look at that
after we've verified we can get the existing stuff working :-)
Another idea Alan had is that if we could have a list of call sites,
instead of NOP'ing we could instead change the branches of all call
sites to skip the 3 instruction mcount prolog :-)
Now, we do store the relocs with the kernel image when using
CONFIG_RELOCATABLE, though we might want to 'sort' them a bit to easily
find callers from call sites, but it's something to also consider.
Cheers,
Ben.
> -- Steve
>
> > 10: f8 01 00 10 std r0,16(r1)
> > 14: f8 21 ff d1 stdu r1,-48(r1)
> > 18: e9 22 00 00 ld r9,0(r2)
> > 1c: e8 69 00 02 lwa r3,0(r9)
> > 20: 38 21 00 30 addi r1,r1,48
> > 24: e8 01 00 10 ld r0,16(r1)
> > 28: 7c 08 03 a6 mtlr r0
> > 2c: 4e 80 00 20 blr
> >
> >
> > This mean we could support ftrace function trace with very little overhead.
> >
> > In fact if we are careful when switching to the new mcount ABI and don't
> > rely on the store of r0, we could probably optimise this even further in a
> > future gcc and remove the store completely. mcount would be 2 instructions:
> >
> > mflr r0
> > bl 8 <.foo+0x8>
> >
> > Anton
>
^ permalink raw reply
* Re: [alsa-devel] [PATCH 1/2] powerpc: add platform registration for ALSA SoC drivers
From: Grant Likely @ 2010-04-29 3:43 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: alsa-devel, kumar.gala, Mark Brown, linuxppc-dev, Timur Tabi,
Liam Girdwood
In-Reply-To: <1272501411.24542.125.camel@pasglop>
On Wed, Apr 28, 2010 at 6:36 PM, Benjamin Herrenschmidt
<benh@kernel.crashing.org> wrote:
> On Wed, 2010-04-28 at 13:07 +0100, Mark Brown wrote:
>> > The device-tree helps keep the platform .c file simple and devoid of too
>> > horrible hacks, it allows to easily pass various configuration data to
>> > leaf drivers such as i2c thingies, PHY devices etc... without gross
>> > hooks between these and the platform, but the platform code still has
>> > the upper hand for doing ad-hoc bits and pieces (or overwriting the
>> > device-tree based behaviour) if necessary.
>>
>> Once again, if you can get the device tree guys to buy into this and
>> stick with it that sounds good but my experience has been that this
>> isn't where any of these discussions end up.
>
> Well, as the person who came up with the flattened device-tree format in
> the first place I suppose I qualify as a "device-tree" guy here :-)
>
> At the moment, I'd say Grant (and to some extent Jeremy Kerr) are the
> guys in charge though, but yes, I agree with you, there's a tendency to
> be too over-exited and to want to do "too much" with the DT and that is
> counter productive. It's a good tool but it's not going to solve world
> hunger and in some places an ad-hoc bit of C code is a better option :)
>
> Now, I don't think Grant is totally off the tracks here but I must admit
> I haven't taken the time to ensure I understand perfectly everybody's
> position in that debate. At least I made mine clear, hope this helps :-)
After an IRC conversation with Timur, I think we've pretty much sorted
out the best way to handle the mpc8610 use case that allows the
ssi/dma/codec drivers to remain blissfully ignorant and bind in the
appropriate ASoC machine driver for the board.
g.
^ permalink raw reply
* Re: [alsa-devel] [PATCH 1/2] powerpc: add platform registration for ALSA SoC drivers
From: Grant Likely @ 2010-04-29 3:44 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: alsa-devel, kumar.gala, Mark Brown, linuxppc-dev, Timur Tabi,
devicetree-discuss, lrg
In-Reply-To: <1272502322.24542.135.camel@pasglop>
On Wed, Apr 28, 2010 at 6:52 PM, Benjamin Herrenschmidt
<benh@kernel.crashing.org> wrote:
> On Wed, 2010-04-28 at 17:13 -0500, Timur Tabi wrote:
>> On Wed, Apr 28, 2010 at 4:58 PM, Grant Likely <grant.likely@secretlab.ca> wrote:
>>
>> > The sound0 node needs a compatible value,
>>
>> I knew I was forgetting something
>>
>> > the sound-device node should
>> > probably have one too.
>>
>> The aliases, cpus, and memory node don't have a compatible property,
>> and I was modeling the design after the aliases node.
>
> aliases is a bad choice, it's very very special and is neither a device
> nor a virtual device, like chosen.
>
> cpus is more of a match in your case.
>
> In any case, I agree, you may not really need a compatible prop for the
> virtual device. In fact, Grant, do we really need an enclosing node like
> that ?
Mostly I'm concerned about 'polluting' the root node in a way that
we'd regret later; but perhaps I'm being overly conservative. The
sound node will still be uniquely identified by it's compatible
property, so perhaps I'm fretting over nothing.
> In any case, it's no big deal and shouldn't have much impact on
> the design.
Right, the point has been reached of quibbling over trivialities.
g.
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: [PATCH 1/5] sched: fix capacity calculations for SMT4
From: Michael Neuling @ 2010-04-29 6:55 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Suresh Siddha, Gautham R Shenoy, linux-kernel, linuxppc-dev,
Ingo Molnar
In-Reply-To: <1271426308.1674.429.camel@laptop>
In message <1271426308.1674.429.camel@laptop> you wrote:
> On Wed, 2010-04-14 at 14:28 +1000, Michael Neuling wrote:
>
> > > Right, so I suspect this will indeed break some things.
> > >
> > > We initially allowed 0 capacity for when a cpu is consumed by an RT task
> > > and there simply isn't much capacity left, in that case you really want
> > > to try and move load to your sibling cpus if possible.
> >
> > Changing the CPU power based on what tasks are running on them seems a
> > bit wrong to me. Shouldn't we keep those concepts separate?
>
> Well the thing cpu_power represents is a ratio of compute capacity
> available to this cpu as compared to other cpus. By normalizing the
> runqueue weights with this we end up with a fair balance.
>
> The thing to realize here is that this is solely about SCHED_NORMAL
> tasks, SCHED_FIFO/RR (or the proposed DEADLINE) tasks do not care about
> fairness and available compute capacity.
>
> So if we were to ignore RT tasks, you'd end up with a situation where,
> assuming 2 cpus and 4 equally weighted NORMAL tasks, and 1 RT task, the
> load-balancer would give each cpu 2 NORMAL tasks, but the tasks that
> would end up on the cpu the RT tasks would be running on would not run
> as fast -- is that fair?
>
> Since RT tasks do not have a weight (FIFO/RR have no limit at all,
> DEADLINE would have something equivalent to a max weight), it is
> impossible to account them in the normal weight sense.
>
> Therefore the current model takes them into account by lowering the
> compute capacity according to their (avg) cpu usage. So if the RT task
> would consume 66% cputime, we'd end up with a situation where the cpu
> running the RT task would get 1 NORMAL task, and other cpu would have
> the remaining 3, that way they'd all get 33% cpu.
>
> > > However you're right that this goes awry in your case.
> > >
> > > One thing to look at is if that 15% increase is indeed representative
> > > for the power7 cpu, it having 4 SMT threads seems to suggest there was
> > > significant gains, otherwise they'd not have wasted the silicon.
> >
> > There are certainly, for most workloads, per core gains for SMT4 over
> > SMT2 on P7. My kernels certainly compile faster and that's the only
> > workload anyone who matters cares about.... ;-)
>
> For sure ;-)
>
> Are there any numbers available on how much they gain? It might be worth
> to stick in real numbers instead of this alleged 15%.
>
> > > One thing we could look at is using the cpu base power to compute
> > > capacity from. We'd have to add another field to sched_group and store
> > > power before we do the scale_rt_power() stuff.
> >
> > Separating capacity from what RT tasks are running seems like a good
> > idea to me.
>
> Well, per the above we cannot fully separate them.
>
> > This would fix the RT issue, but it's not clear to me how you are
> > suggesting fixing the rounding down to 0 SMT4 issue. Are you suggesting
> > we bump smt_gain to say 2048 + 15%? Or are you suggesting we separate
> > the RT tasks out from capacity and keep the max(1, capacity) that I've
> > added? Or something else?
>
> I would think that 4 SMT threads are still slower than two full cores,
> right? So cpu_power=2048 would not be appropriate.
>
> > Would another possibility be changing capacity a scaled value (like
> > cpu_power is now) rather than a small integer as it is now. For
> > example, a scaled capacity of 1024 would be equivalent to a capacity of
> > 1 now. This might enable us to handle partial capacities better? We'd
> > probably have to scale a bunch of nr_running too.
>
> Right, so my proposal was to scale down the capacity divider (currently
> 1024) to whatever would be the base capacity for that cpu. Trouble seems
> to be that that makes group capacity a lot more complex, as you would
> end up needing to average all the cpu's their base capacity.
>
>
> Hrmm, my brain seems muddled but I might have another solution, let me
> ponder this for a bit..
>
Peter,
Did you manage to get anywhere on this capacity issue?
Mikey
^ permalink raw reply
* Re: [PATCH] add icswx support
From: Mike Kravetz @ 2010-04-29 17:11 UTC (permalink / raw)
To: Tseng-Hui (Frank) Lin; +Cc: linuxppc-dev
In-Reply-To: <1272060275.6329.13.camel@flin.austin.ibm.com>
On Fri, Apr 23, 2010 at 05:04:35PM -0500, Tseng-Hui (Frank) Lin wrote:
> Add Power7 icswx co-processor instruction support.
Silly question perhaps, but
Do we want this code to be enabled/exist for all processors? I don't
see any checks for Power7 processors. Or, will it be the responsibility
of the caller to ensure that they are running on P7?
--
Mike
> Signed-off-by: Sonny Rao <sonnyrao@linux.vnet.ibm.com>
> Signed-off-by: Tseng-Hui (Frank) Lin <thlin@linux.vnet.ibm.com>
> ---
> arch/powerpc/include/asm/mmu-hash64.h | 3 +
> arch/powerpc/include/asm/mmu_context.h | 4 ++
> arch/powerpc/include/asm/reg.h | 3 +
> arch/powerpc/mm/mmu_context_hash64.c | 79
> ++++++++++++++++++++++++++++++++
> 4 files changed, 89 insertions(+), 0 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/mmu-hash64.h
> b/arch/powerpc/include/asm/mmu-hash64.h
> index 2102b21..ba5727d 100644
> --- a/arch/powerpc/include/asm/mmu-hash64.h
> +++ b/arch/powerpc/include/asm/mmu-hash64.h
> @@ -421,6 +421,9 @@ typedef struct {
> #ifdef CONFIG_PPC_SUBPAGE_PROT
> struct subpage_prot_table spt;
> #endif /* CONFIG_PPC_SUBPAGE_PROT */
> + unsigned long acop;
> +#define HASH64_MAX_PID (0xFFFF)
> + unsigned int pid;
> } mm_context_t;
>
>
> diff --git a/arch/powerpc/include/asm/mmu_context.h
> b/arch/powerpc/include/asm/mmu_context.h
> index 26383e0..d6c8841 100644
> --- a/arch/powerpc/include/asm/mmu_context.h
> +++ b/arch/powerpc/include/asm/mmu_context.h
> @@ -78,6 +78,10 @@ static inline void switch_mm(struct mm_struct *prev,
> struct mm_struct *next,
>
> #define deactivate_mm(tsk,mm) do { } while (0)
>
> +extern void switch_cop(struct mm_struct *next);
> +extern int use_cop(unsigned long acop, struct task_struct *task);
> +extern void disuse_cop(unsigned long acop, struct mm_struct *mm);
> +
> /*
> * After we have set current->mm to a new value, this activates
> * the context for the new mm so we see the new mappings.
> diff --git a/arch/powerpc/include/asm/reg.h
> b/arch/powerpc/include/asm/reg.h
> index 5572e86..30503f8 100644
> --- a/arch/powerpc/include/asm/reg.h
> +++ b/arch/powerpc/include/asm/reg.h
> @@ -516,6 +516,9 @@
> #define SPRN_SIAR 780
> #define SPRN_SDAR 781
>
> +#define SPRN_ACOP 31
> +#define SPRN_PID 48
> +
> #define SPRN_PA6T_MMCR0 795
> #define PA6T_MMCR0_EN0 0x0000000000000001UL
> #define PA6T_MMCR0_EN1 0x0000000000000002UL
> diff --git a/arch/powerpc/mm/mmu_context_hash64.c
> b/arch/powerpc/mm/mmu_context_hash64.c
> index 2535828..d0a79f6 100644
> --- a/arch/powerpc/mm/mmu_context_hash64.c
> +++ b/arch/powerpc/mm/mmu_context_hash64.c
> @@ -18,6 +18,7 @@
> #include <linux/mm.h>
> #include <linux/spinlock.h>
> #include <linux/idr.h>
> +#include <linux/percpu.h>
> #include <linux/module.h>
> #include <linux/gfp.h>
>
> @@ -25,6 +26,82 @@
>
> static DEFINE_SPINLOCK(mmu_context_lock);
> static DEFINE_IDA(mmu_context_ida);
> +static DEFINE_IDA(cop_ida);
> +
> +/* Lazy switch the ACOP register */
> +static DEFINE_PER_CPU(unsigned long, acop_reg);
> +
> +void switch_cop(struct mm_struct *next)
> +{
> + mtspr(SPRN_PID, next->context.pid);
> + if (next->context.pid &&
> + __get_cpu_var(acop_reg) != next->context.acop) {
> + mtspr(SPRN_ACOP, next->context.acop);
> + __get_cpu_var(acop_reg) = next->context.acop;
> + }
> +}
> +
> +int use_cop(unsigned long acop, struct task_struct *task)
> +{
> + int pid;
> + int err;
> + struct mm_struct *mm = get_task_mm(task);
> +
> + if (!mm)
> + return -EINVAL;
> +
> + if (!mm->context.pid) {
> + if (!ida_pre_get(&cop_ida, GFP_KERNEL))
> + return -ENOMEM;
> +again:
> + spin_lock(&mmu_context_lock);
> + err = ida_get_new_above(&cop_ida, 1, &pid);
> + spin_unlock(&mmu_context_lock);
> +
> + if (err == -EAGAIN)
> + goto again;
> + else if (err)
> + return err;
> +
> + if (pid > HASH64_MAX_PID) {
> + spin_lock(&mmu_context_lock);
> + ida_remove(&cop_ida, pid);
> + spin_unlock(&mmu_context_lock);
> + return -EBUSY;
> + }
> + mm->context.pid = pid;
> + mtspr(SPRN_PID, mm->context.pid);
> + }
> + mm->context.acop |= acop;
> +
> + get_cpu_var(acop_reg) = mm->context.acop;
> + mtspr(SPRN_ACOP, mm->context.acop);
> + put_cpu_var(acop_reg);
> +
> + return mm->context.pid;
> +}
> +EXPORT_SYMBOL(use_cop);
> +
> +void disuse_cop(unsigned long acop, struct mm_struct *mm)
> +{
> + if (WARN_ON(!mm))
> + return;
> +
> + mm->context.acop &= ~acop;
> + if (!mm->context.acop) {
> + spin_lock(&mmu_context_lock);
> + ida_remove(&cop_ida, mm->context.pid);
> + spin_unlock(&mmu_context_lock);
> + mm->context.pid = 0;
> + mtspr(SPRN_PID, 0);
> + } else {
> + get_cpu_var(acop_reg) = mm->context.acop;
> + mtspr(SPRN_ACOP, mm->context.acop);
> + put_cpu_var(acop_reg);
> + }
> + mmput(mm);
> +}
> +EXPORT_SYMBOL(disuse_cop);
>
> /*
> * The proto-VSID space has 2^35 - 1 segments available for user
> mappings.
> @@ -94,6 +171,8 @@ EXPORT_SYMBOL_GPL(__destroy_context);
> void destroy_context(struct mm_struct *mm)
> {
> __destroy_context(mm->context.id);
> + if (mm->context.pid)
> + ida_remove(&cop_ida, mm->context.pid);
> subpage_prot_free(mm);
> mm->context.id = NO_CONTEXT;
> }
>
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH] add icswx support
From: Benjamin Herrenschmidt @ 2010-04-29 22:50 UTC (permalink / raw)
To: Mike Kravetz; +Cc: linuxppc-dev, Tseng-Hui (Frank) Lin
In-Reply-To: <20100429171118.GB3411@monkey.beaverton.ibm.com>
On Thu, 2010-04-29 at 10:11 -0700, Mike Kravetz wrote:
> On Fri, Apr 23, 2010 at 05:04:35PM -0500, Tseng-Hui (Frank) Lin wrote:
> > Add Power7 icswx co-processor instruction support.
>
> Silly question perhaps, but
>
> Do we want this code to be enabled/exist for all processors? I don't
> see any checks for Power7 processors. Or, will it be the responsibility
> of the caller to ensure that they are running on P7?
Well, this is a good point, there should be at least a CPU feature here,
especially since some of that code needs to be called from the context
switch routine (though that bit seems to be missing at the moment).
Cheers,
Ben.
> --
> Mike
>
>
> > Signed-off-by: Sonny Rao <sonnyrao@linux.vnet.ibm.com>
> > Signed-off-by: Tseng-Hui (Frank) Lin <thlin@linux.vnet.ibm.com>
> > ---
> > arch/powerpc/include/asm/mmu-hash64.h | 3 +
> > arch/powerpc/include/asm/mmu_context.h | 4 ++
> > arch/powerpc/include/asm/reg.h | 3 +
> > arch/powerpc/mm/mmu_context_hash64.c | 79
> > ++++++++++++++++++++++++++++++++
> > 4 files changed, 89 insertions(+), 0 deletions(-)
> >
> > diff --git a/arch/powerpc/include/asm/mmu-hash64.h
> > b/arch/powerpc/include/asm/mmu-hash64.h
> > index 2102b21..ba5727d 100644
> > --- a/arch/powerpc/include/asm/mmu-hash64.h
> > +++ b/arch/powerpc/include/asm/mmu-hash64.h
> > @@ -421,6 +421,9 @@ typedef struct {
> > #ifdef CONFIG_PPC_SUBPAGE_PROT
> > struct subpage_prot_table spt;
> > #endif /* CONFIG_PPC_SUBPAGE_PROT */
> > + unsigned long acop;
> > +#define HASH64_MAX_PID (0xFFFF)
> > + unsigned int pid;
> > } mm_context_t;
> >
> >
> > diff --git a/arch/powerpc/include/asm/mmu_context.h
> > b/arch/powerpc/include/asm/mmu_context.h
> > index 26383e0..d6c8841 100644
> > --- a/arch/powerpc/include/asm/mmu_context.h
> > +++ b/arch/powerpc/include/asm/mmu_context.h
> > @@ -78,6 +78,10 @@ static inline void switch_mm(struct mm_struct *prev,
> > struct mm_struct *next,
> >
> > #define deactivate_mm(tsk,mm) do { } while (0)
> >
> > +extern void switch_cop(struct mm_struct *next);
> > +extern int use_cop(unsigned long acop, struct task_struct *task);
> > +extern void disuse_cop(unsigned long acop, struct mm_struct *mm);
> > +
> > /*
> > * After we have set current->mm to a new value, this activates
> > * the context for the new mm so we see the new mappings.
> > diff --git a/arch/powerpc/include/asm/reg.h
> > b/arch/powerpc/include/asm/reg.h
> > index 5572e86..30503f8 100644
> > --- a/arch/powerpc/include/asm/reg.h
> > +++ b/arch/powerpc/include/asm/reg.h
> > @@ -516,6 +516,9 @@
> > #define SPRN_SIAR 780
> > #define SPRN_SDAR 781
> >
> > +#define SPRN_ACOP 31
> > +#define SPRN_PID 48
> > +
> > #define SPRN_PA6T_MMCR0 795
> > #define PA6T_MMCR0_EN0 0x0000000000000001UL
> > #define PA6T_MMCR0_EN1 0x0000000000000002UL
> > diff --git a/arch/powerpc/mm/mmu_context_hash64.c
> > b/arch/powerpc/mm/mmu_context_hash64.c
> > index 2535828..d0a79f6 100644
> > --- a/arch/powerpc/mm/mmu_context_hash64.c
> > +++ b/arch/powerpc/mm/mmu_context_hash64.c
> > @@ -18,6 +18,7 @@
> > #include <linux/mm.h>
> > #include <linux/spinlock.h>
> > #include <linux/idr.h>
> > +#include <linux/percpu.h>
> > #include <linux/module.h>
> > #include <linux/gfp.h>
> >
> > @@ -25,6 +26,82 @@
> >
> > static DEFINE_SPINLOCK(mmu_context_lock);
> > static DEFINE_IDA(mmu_context_ida);
> > +static DEFINE_IDA(cop_ida);
> > +
> > +/* Lazy switch the ACOP register */
> > +static DEFINE_PER_CPU(unsigned long, acop_reg);
> > +
> > +void switch_cop(struct mm_struct *next)
> > +{
> > + mtspr(SPRN_PID, next->context.pid);
> > + if (next->context.pid &&
> > + __get_cpu_var(acop_reg) != next->context.acop) {
> > + mtspr(SPRN_ACOP, next->context.acop);
> > + __get_cpu_var(acop_reg) = next->context.acop;
> > + }
> > +}
> > +
> > +int use_cop(unsigned long acop, struct task_struct *task)
> > +{
> > + int pid;
> > + int err;
> > + struct mm_struct *mm = get_task_mm(task);
> > +
> > + if (!mm)
> > + return -EINVAL;
> > +
> > + if (!mm->context.pid) {
> > + if (!ida_pre_get(&cop_ida, GFP_KERNEL))
> > + return -ENOMEM;
> > +again:
> > + spin_lock(&mmu_context_lock);
> > + err = ida_get_new_above(&cop_ida, 1, &pid);
> > + spin_unlock(&mmu_context_lock);
> > +
> > + if (err == -EAGAIN)
> > + goto again;
> > + else if (err)
> > + return err;
> > +
> > + if (pid > HASH64_MAX_PID) {
> > + spin_lock(&mmu_context_lock);
> > + ida_remove(&cop_ida, pid);
> > + spin_unlock(&mmu_context_lock);
> > + return -EBUSY;
> > + }
> > + mm->context.pid = pid;
> > + mtspr(SPRN_PID, mm->context.pid);
> > + }
> > + mm->context.acop |= acop;
> > +
> > + get_cpu_var(acop_reg) = mm->context.acop;
> > + mtspr(SPRN_ACOP, mm->context.acop);
> > + put_cpu_var(acop_reg);
> > +
> > + return mm->context.pid;
> > +}
> > +EXPORT_SYMBOL(use_cop);
> > +
> > +void disuse_cop(unsigned long acop, struct mm_struct *mm)
> > +{
> > + if (WARN_ON(!mm))
> > + return;
> > +
> > + mm->context.acop &= ~acop;
> > + if (!mm->context.acop) {
> > + spin_lock(&mmu_context_lock);
> > + ida_remove(&cop_ida, mm->context.pid);
> > + spin_unlock(&mmu_context_lock);
> > + mm->context.pid = 0;
> > + mtspr(SPRN_PID, 0);
> > + } else {
> > + get_cpu_var(acop_reg) = mm->context.acop;
> > + mtspr(SPRN_ACOP, mm->context.acop);
> > + put_cpu_var(acop_reg);
> > + }
> > + mmput(mm);
> > +}
> > +EXPORT_SYMBOL(disuse_cop);
> >
> > /*
> > * The proto-VSID space has 2^35 - 1 segments available for user
> > mappings.
> > @@ -94,6 +171,8 @@ EXPORT_SYMBOL_GPL(__destroy_context);
> > void destroy_context(struct mm_struct *mm)
> > {
> > __destroy_context(mm->context.id);
> > + if (mm->context.pid)
> > + ida_remove(&cop_ida, mm->context.pid);
> > subpage_prot_free(mm);
> > mm->context.id = NO_CONTEXT;
> > }
> >
> >
> > _______________________________________________
> > Linuxppc-dev mailing list
> > Linuxppc-dev@lists.ozlabs.org
> > https://lists.ozlabs.org/listinfo/linuxppc-dev
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
^ permalink raw reply
* [PATCH 1/5] fsl-diu-fb: fix issue with re-enabling DIU area descriptor on MPC5121
From: Anatolij Gustschin @ 2010-04-29 23:49 UTC (permalink / raw)
To: linuxppc-dev; +Cc: linux-fbdev, wd, dzu, devicetree-discuss, yorksun
In-Reply-To: <1272584978-19063-1-git-send-email-agust@denx.de>
On MPC5121 re-configuring the DIU area descriptor by writing
new descriptor address doesn't work. As a result, DIU continues
to display using old area descriptor even if the new one has
been set.
Disabling the DIU before setting the new descriptor and
subsequently enabling it fixes the problem.
Signed-off-by: Anatolij Gustschin <agust@denx.de>
---
drivers/video/fsl-diu-fb.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index 994358a..ee15a99 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -329,8 +329,11 @@ static int fsl_diu_enable_panel(struct fb_info *info)
if (mfbi->type != MFB_TYPE_OFF) {
switch (mfbi->index) {
case 0: /* plane 0 */
- if (hw->desc[0] != ad->paddr)
+ if (hw->desc[0] != ad->paddr) {
+ out_be32(&dr.diu_reg->diu_mode, MFB_MODE0);
out_be32(&hw->desc[0], ad->paddr);
+ out_be32(&dr.diu_reg->diu_mode, MFB_MODE1);
+ }
break;
case 1: /* plane 1 AOI 0 */
cmfbi = machine_data->fsl_diu_info[2]->par;
--
1.6.3.3
^ permalink raw reply related
* [PATCH 2/5] fsl-diu-fb: move fsl-diu-fb.h to include/linux
From: Anatolij Gustschin @ 2010-04-29 23:49 UTC (permalink / raw)
To: linuxppc-dev; +Cc: linux-fbdev, wd, dzu, devicetree-discuss, yorksun
In-Reply-To: <1272584978-19063-1-git-send-email-agust@denx.de>
Some DIU structures will be used in platform code in
subsequent MPC5121 DIU patch, so we move this header
to be able to include it elsewhere.
Signed-off-by: Anatolij Gustschin <agust@denx.de>
---
drivers/video/fsl-diu-fb.c | 2 +-
{drivers/video => include/linux}/fsl-diu-fb.h | 0
2 files changed, 1 insertions(+), 1 deletions(-)
rename {drivers/video => include/linux}/fsl-diu-fb.h (100%)
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index ee15a99..7acdc09 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -34,7 +34,7 @@
#include <linux/of_platform.h>
#include <sysdev/fsl_soc.h>
-#include "fsl-diu-fb.h"
+#include <linux/fsl-diu-fb.h>
/*
* These parameters give default parameters
diff --git a/drivers/video/fsl-diu-fb.h b/include/linux/fsl-diu-fb.h
similarity index 100%
rename from drivers/video/fsl-diu-fb.h
rename to include/linux/fsl-diu-fb.h
--
1.6.3.3
^ permalink raw reply related
* [PATCH 0/5] Rework MPC5121 DIU support (for 2.6.35)
From: Anatolij Gustschin @ 2010-04-29 23:49 UTC (permalink / raw)
To: linuxppc-dev; +Cc: linux-fbdev, wd, dzu, devicetree-discuss, yorksun
This patch series rework DIU support patches submitted
previously. Comments to the previos patch series have
been addressed, not related changes are dropped and some
changes are split out to separate patches to simplify
review. Furthermore a patch has been added to support
setting display mode using EDID block in the device tree.
Anatolij Gustschin (5):
fsl-diu-fb: fix issue with re-enabling DIU area descriptor on MPC5121
fsl-diu-fb: move fsl-diu-fb.h to include/linux
powerpc/mpc5121: shared DIU framebuffer support
powerpc: doc/dts-bindings: update doc of FSL DIU bindings
fsl-diu-fb: Support setting display mode using EDID
Documentation/powerpc/dts-bindings/fsl/diu.txt | 20 ++-
arch/powerpc/platforms/512x/mpc5121_ads.c | 7 +
arch/powerpc/platforms/512x/mpc5121_generic.c | 12 +
arch/powerpc/platforms/512x/mpc512x.h | 2 +
arch/powerpc/platforms/512x/mpc512x_shared.c | 284 ++++++++++++++++++++++++
arch/powerpc/sysdev/fsl_soc.h | 1 +
drivers/video/Kconfig | 1 +
drivers/video/fsl-diu-fb.c | 104 ++++++++-
{drivers/video => include/linux}/fsl-diu-fb.h | 0
9 files changed, 419 insertions(+), 12 deletions(-)
rename {drivers/video => include/linux}/fsl-diu-fb.h (100%)
^ permalink raw reply
* [PATCH 4/5] powerpc: doc/dts-bindings: update doc of FSL DIU bindings
From: Anatolij Gustschin @ 2010-04-29 23:49 UTC (permalink / raw)
To: linuxppc-dev; +Cc: linux-fbdev, wd, dzu, devicetree-discuss, yorksun
In-Reply-To: <1272584978-19063-1-git-send-email-agust@denx.de>
Update compatible and interrupt properties description.
Furthermore an example for the MPC5121 has been added.
Signed-off-by: Anatolij Gustschin <agust@denx.de>
---
Documentation/powerpc/dts-bindings/fsl/diu.txt | 14 ++++++++++++--
1 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/Documentation/powerpc/dts-bindings/fsl/diu.txt b/Documentation/powerpc/dts-bindings/fsl/diu.txt
index deb35de..326cddf 100644
--- a/Documentation/powerpc/dts-bindings/fsl/diu.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/diu.txt
@@ -4,10 +4,12 @@ The Freescale DIU is a LCD controller, with proper hardware, it can also
drive DVI monitors.
Required properties:
-- compatible : should be "fsl-diu".
+- compatible : should be "fsl,diu" or "fsl,mpc5121-diu".
- reg : should contain at least address and length of the DIU register
set.
-- Interrupts : one DIU interrupt should be describe here.
+- interrupts : one DIU interrupt should be described here.
+- interrupt-parent : the phandle for the interrupt controller that
+ services interrupts for this device.
Example (MPC8610HPCD):
display@2c000 {
@@ -16,3 +18,11 @@ Example (MPC8610HPCD):
interrupts = <72 2>;
interrupt-parent = <&mpic>;
};
+
+Example for MPC5121:
+ display@2100 {
+ compatible = "fsl,mpc5121-diu";
+ reg = <0x2100 0x100>;
+ interrupts = <64 0x8>;
+ interrupt-parent = <&ipic>;
+ };
--
1.6.3.3
^ permalink raw reply related
* [PATCH 5/5] fsl-diu-fb: Support setting display mode using EDID
From: Anatolij Gustschin @ 2010-04-29 23:49 UTC (permalink / raw)
To: linuxppc-dev; +Cc: linux-fbdev, wd, dzu, devicetree-discuss, yorksun
In-Reply-To: <1272584978-19063-1-git-send-email-agust@denx.de>
Adds support for encoding display mode information
in the device tree using verbatim EDID block.
If the EDID entry in the DIU node is present, the
driver will build mode database using EDID data
and allow setting the display modes from this database.
Otherwise display mode will be set using mode
entries from driver's internal database as usual.
This patch also updates device tree bindings.
Signed-off-by: Anatolij Gustschin <agust@denx.de>
---
Documentation/powerpc/dts-bindings/fsl/diu.txt | 6 ++
drivers/video/Kconfig | 1 +
drivers/video/fsl-diu-fb.c | 80 ++++++++++++++++++++++--
3 files changed, 81 insertions(+), 6 deletions(-)
diff --git a/Documentation/powerpc/dts-bindings/fsl/diu.txt b/Documentation/powerpc/dts-bindings/fsl/diu.txt
index 326cddf..47e777e 100644
--- a/Documentation/powerpc/dts-bindings/fsl/diu.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/diu.txt
@@ -11,6 +11,11 @@ Required properties:
- interrupt-parent : the phandle for the interrupt controller that
services interrupts for this device.
+Optional properties:
+- EDID : verbatim EDID data block describing attached display.
+ Data from the detailed timing descriptor will be used to
+ program the display controller.
+
Example (MPC8610HPCD):
display@2c000 {
compatible = "fsl,diu";
@@ -25,4 +30,5 @@ Example for MPC5121:
reg = <0x2100 0x100>;
interrupts = <64 0x8>;
interrupt-parent = <&ipic>;
+ EDID = [edid-data];
};
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 6e16244..eca1e49 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1855,6 +1855,7 @@ config FB_MBX_DEBUG
config FB_FSL_DIU
tristate "Freescale DIU framebuffer support"
depends on FB && FSL_SOC
+ select FB_MODE_HELPERS
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index 81dec09..2b99f29 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -35,6 +35,7 @@
#include <sysdev/fsl_soc.h>
#include <linux/fsl-diu-fb.h>
+#include "edid.h"
/*
* These parameters give default parameters
@@ -217,6 +218,7 @@ struct mfb_info {
int x_aoi_d; /* aoi display x offset to physical screen */
int y_aoi_d; /* aoi display y offset to physical screen */
struct fsl_diu_data *parent;
+ char *edid_data;
};
@@ -1180,18 +1182,30 @@ static int __devinit install_fb(struct fb_info *info)
int rc;
struct mfb_info *mfbi = info->par;
const char *aoi_mode, *init_aoi_mode = "320x240";
+ struct fb_videomode *db = fsl_diu_mode_db;
+ unsigned int dbsize = ARRAY_SIZE(fsl_diu_mode_db);
+ int has_default_mode = 1;
if (init_fbinfo(info))
return -EINVAL;
- if (mfbi->index == 0) /* plane 0 */
+ if (mfbi->index == 0) { /* plane 0 */
+ if (mfbi->edid_data) {
+ /* Now build modedb from EDID */
+ fb_edid_to_monspecs(mfbi->edid_data, &info->monspecs);
+ fb_videomode_to_modelist(info->monspecs.modedb,
+ info->monspecs.modedb_len,
+ &info->modelist);
+ db = info->monspecs.modedb;
+ dbsize = info->monspecs.modedb_len;
+ }
aoi_mode = fb_mode;
- else
+ } else {
aoi_mode = init_aoi_mode;
+ }
pr_debug("mode used = %s\n", aoi_mode);
- rc = fb_find_mode(&info->var, info, aoi_mode, fsl_diu_mode_db,
- ARRAY_SIZE(fsl_diu_mode_db), &fsl_diu_default_mode, default_bpp);
-
+ rc = fb_find_mode(&info->var, info, aoi_mode, db, dbsize,
+ &fsl_diu_default_mode, default_bpp);
switch (rc) {
case 1:
pr_debug("using mode specified in @mode\n");
@@ -1209,10 +1223,50 @@ static int __devinit install_fb(struct fb_info *info)
default:
pr_debug("rc = %d\n", rc);
pr_debug("failed to find mode\n");
- return -EINVAL;
+ /*
+ * For plane 0 we continue and look into
+ * driver's internal modedb.
+ */
+ if (mfbi->index == 0 && mfbi->edid_data)
+ has_default_mode = 0;
+ else
+ return -EINVAL;
break;
}
+ if (!has_default_mode) {
+ rc = fb_find_mode(&info->var, info, aoi_mode, fsl_diu_mode_db,
+ ARRAY_SIZE(fsl_diu_mode_db),
+ &fsl_diu_default_mode,
+ default_bpp);
+ if (rc > 0 && rc < 5)
+ has_default_mode = 1;
+ }
+
+ /* Still not found, use preferred mode from database if any */
+ if (!has_default_mode && info->monspecs.modedb != NULL) {
+ struct fb_monspecs *specs = &info->monspecs;
+ struct fb_videomode *modedb = &specs->modedb[0];
+
+ /*
+ * Get preferred timing. If not found,
+ * first mode in database will be used.
+ */
+ if (specs->misc & FB_MISC_1ST_DETAIL) {
+ int i;
+
+ for (i = 0; i < specs->modedb_len; i++) {
+ if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
+ modedb = &specs->modedb[i];
+ break;
+ }
+ }
+ }
+
+ info->var.bits_per_pixel = default_bpp;
+ fb_videomode_to_var(&info->var, modedb);
+ }
+
pr_debug("xres_virtual %d\n", info->var.xres_virtual);
pr_debug("bits_per_pixel %d\n", info->var.bits_per_pixel);
@@ -1251,6 +1305,9 @@ static void uninstall_fb(struct fb_info *info)
if (!mfbi->registered)
return;
+ if (mfbi->index == 0)
+ kfree(mfbi->edid_data);
+
unregister_framebuffer(info);
unmap_video_memory(info);
if (&info->cmap)
@@ -1451,6 +1508,17 @@ static int __devinit fsl_diu_probe(struct of_device *ofdev,
mfbi = machine_data->fsl_diu_info[i]->par;
memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info));
mfbi->parent = machine_data;
+
+ if (mfbi->index == 0) {
+ const u8 *prop;
+ int len;
+
+ /* Get EDID */
+ prop = of_get_property(np, "EDID", &len);
+ if (prop && len == EDID_LENGTH)
+ mfbi->edid_data = kmemdup(prop, EDID_LENGTH,
+ GFP_KERNEL);
+ }
}
ret = of_address_to_resource(np, 0, &res);
--
1.6.3.3
^ permalink raw reply related
* [PATCH 3/5] powerpc/mpc5121: shared DIU framebuffer support
From: Anatolij Gustschin @ 2010-04-29 23:49 UTC (permalink / raw)
To: linuxppc-dev
Cc: linux-fbdev, wd, dzu, John Rigby, devicetree-discuss, yorksun
In-Reply-To: <1272584978-19063-1-git-send-email-agust@denx.de>
MPC5121 DIU configuration/setup as initialized by the boot
loader currently will get lost while booting Linux. As a
result displaying the boot splash is not possible through
the boot process.
To prevent this we reserve configured DIU frame buffer
address range while booting and preserve AOI descriptor
and gamma table so that DIU continues displaying through
the whole boot process. On first open from user space
DIU frame buffer driver releases the reserved frame
buffer area and continues to operate as usual.
Signed-off-by: John Rigby <jrigby@gmail.com>
Signed-off-by: Anatolij Gustschin <agust@denx.de>
Cc: Grant Likely <grant.likely@secretlab.ca>
---
Changes since previous patch version:
- split out moving fsl-diu-fb.h file to separate patch
- drop unrelated changes
- remove __init annotations in header file
- drop unneeded code
- don't hardcode default busfreq, error out
forcing users to supply a valid tree
- simplify pixelclock calculation
arch/powerpc/platforms/512x/mpc5121_ads.c | 7 +
arch/powerpc/platforms/512x/mpc5121_generic.c | 12 +
arch/powerpc/platforms/512x/mpc512x.h | 2 +
arch/powerpc/platforms/512x/mpc512x_shared.c | 284 +++++++++++++++++++++++++
arch/powerpc/sysdev/fsl_soc.h | 1 +
drivers/video/fsl-diu-fb.c | 17 ++-
6 files changed, 321 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/platforms/512x/mpc5121_ads.c b/arch/powerpc/platforms/512x/mpc5121_ads.c
index ee6ae12..aa4d5a8 100644
--- a/arch/powerpc/platforms/512x/mpc5121_ads.c
+++ b/arch/powerpc/platforms/512x/mpc5121_ads.c
@@ -42,6 +42,7 @@ static void __init mpc5121_ads_setup_arch(void)
for_each_compatible_node(np, "pci", "fsl,mpc5121-pci")
mpc83xx_add_bridge(np);
#endif
+ mpc512x_setup_diu();
}
static void __init mpc5121_ads_init_IRQ(void)
@@ -60,11 +61,17 @@ static int __init mpc5121_ads_probe(void)
return of_flat_dt_is_compatible(root, "fsl,mpc5121ads");
}
+void __init mpc5121_ads_init_early(void)
+{
+ mpc512x_init_diu();
+}
+
define_machine(mpc5121_ads) {
.name = "MPC5121 ADS",
.probe = mpc5121_ads_probe,
.setup_arch = mpc5121_ads_setup_arch,
.init = mpc512x_init,
+ .init_early = mpc5121_ads_init_early,
.init_IRQ = mpc5121_ads_init_IRQ,
.get_irq = ipic_get_irq,
.calibrate_decr = generic_calibrate_decr,
diff --git a/arch/powerpc/platforms/512x/mpc5121_generic.c b/arch/powerpc/platforms/512x/mpc5121_generic.c
index a6c0e3a..c5ecb3d 100644
--- a/arch/powerpc/platforms/512x/mpc5121_generic.c
+++ b/arch/powerpc/platforms/512x/mpc5121_generic.c
@@ -48,10 +48,22 @@ static int __init mpc5121_generic_probe(void)
return board[i] != NULL;
}
+void __init mpc512x_generic_init_early(void)
+{
+ mpc512x_init_diu();
+}
+
+void __init mpc512x_generic_setup_arch(void)
+{
+ mpc512x_setup_diu();
+}
+
define_machine(mpc5121_generic) {
.name = "MPC5121 generic",
.probe = mpc5121_generic_probe,
.init = mpc512x_init,
+ .init_early = mpc512x_generic_init_early,
+ .setup_arch = mpc512x_generic_setup_arch,
.init_IRQ = mpc512x_init_IRQ,
.get_irq = ipic_get_irq,
.calibrate_decr = generic_calibrate_decr,
diff --git a/arch/powerpc/platforms/512x/mpc512x.h b/arch/powerpc/platforms/512x/mpc512x.h
index b2daca0..1ab6d11 100644
--- a/arch/powerpc/platforms/512x/mpc512x.h
+++ b/arch/powerpc/platforms/512x/mpc512x.h
@@ -16,4 +16,6 @@ extern void __init mpc512x_init(void);
extern int __init mpc5121_clk_init(void);
void __init mpc512x_declare_of_platform_devices(void);
extern void mpc512x_restart(char *cmd);
+extern void mpc512x_init_diu(void);
+extern void mpc512x_setup_diu(void);
#endif /* __MPC512X_H__ */
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index b7f518a..8e297fa 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -16,7 +16,11 @@
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/of_platform.h>
+#include <linux/fsl-diu-fb.h>
+#include <linux/bootmem.h>
+#include <sysdev/fsl_soc.h>
+#include <asm/cacheflush.h>
#include <asm/machdep.h>
#include <asm/ipic.h>
#include <asm/prom.h>
@@ -53,6 +57,286 @@ void mpc512x_restart(char *cmd)
;
}
+struct fsl_diu_shared_fb {
+ char gamma[0x300]; /* 32-bit aligned! */
+ struct diu_ad ad0; /* 32-bit aligned! */
+ phys_addr_t fb_phys;
+ size_t fb_len;
+ bool in_use;
+};
+
+unsigned int mpc512x_get_pixel_format(unsigned int bits_per_pixel,
+ int monitor_port)
+{
+ unsigned int pix_fmt;
+
+ switch (bits_per_pixel) {
+ case 32:
+ pix_fmt = 0x88883316;
+ break;
+ case 24:
+ pix_fmt = 0x88082219;
+ break;
+ case 16:
+ pix_fmt = 0x65053118;
+ break;
+ default:
+ pix_fmt = 0x00000400;
+ }
+ return pix_fmt;
+}
+
+void mpc512x_set_gamma_table(int monitor_port, char *gamma_table_base)
+{
+}
+
+void mpc512x_set_monitor_port(int monitor_port)
+{
+}
+
+#define CCM_SCFR1 0x0000000c
+#define DIU_DIV_MASK 0x000000ff
+void mpc512x_set_pixel_clock(unsigned int pixclock)
+{
+ unsigned long bestval, bestfreq, speed_ccb, busfreq;
+ unsigned long minpixclock, maxpixclock, pixval;
+ struct device_node *np;
+ void __iomem *ccm;
+ u32 temp;
+ long err;
+ int i;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+ if (!np) {
+ pr_err("Can't find clock control module.\n");
+ return;
+ }
+
+ ccm = of_iomap(np, 0);
+ if (!ccm) {
+ pr_err("Can't map clock control module reg.\n");
+ of_node_put(np);
+ return;
+ }
+ of_node_put(np);
+
+ np = of_find_node_by_type(NULL, "cpu");
+ if (np) {
+ unsigned int size;
+ const unsigned int *prop =
+ of_get_property(np, "bus-frequency", &size);
+
+ of_node_put(np);
+ if (prop) {
+ busfreq = *prop;
+ } else {
+ pr_err("Can't get bus-frequency property\n");
+ return;
+ }
+ } else {
+ pr_err("Can't find \"cpu\" node.\n");
+ return;
+ }
+
+ /* Pixel Clock configuration */
+ pr_debug("DIU: Bus Frequency = %lu\n", busfreq);
+ speed_ccb = busfreq * 4;
+
+ /* Calculate the pixel clock with the smallest error */
+ /* calculate the following in steps to avoid overflow */
+ pr_debug("DIU pixclock in ps - %d\n", pixclock);
+ temp = (1000000000 / pixclock) * 1000;
+ pixclock = temp;
+ pr_debug("DIU pixclock freq - %u\n", pixclock);
+
+ temp = (temp * 5) / 100; /* pixclock * 0.05 */
+ pr_debug("deviation = %d\n", temp);
+ minpixclock = pixclock - temp;
+ maxpixclock = pixclock + temp;
+ pr_debug("DIU minpixclock - %lu\n", minpixclock);
+ pr_debug("DIU maxpixclock - %lu\n", maxpixclock);
+ pixval = speed_ccb/pixclock;
+ pr_debug("DIU pixval = %lu\n", pixval);
+
+ err = 100000000;
+ bestval = pixval;
+ pr_debug("DIU bestval = %lu\n", bestval);
+
+ bestfreq = 0;
+ for (i = -1; i <= 1; i++) {
+ temp = speed_ccb / (pixval+i);
+ pr_debug("DIU test pixval i=%d, pixval=%lu, temp freq. = %u\n",
+ i, pixval, temp);
+ if ((temp < minpixclock) || (temp > maxpixclock))
+ pr_debug("DIU exceeds monitor range (%lu to %lu)\n",
+ minpixclock, maxpixclock);
+ else if (abs(temp - pixclock) < err) {
+ pr_debug("Entered the else if block %d\n", i);
+ err = abs(temp - pixclock);
+ bestval = pixval + i;
+ bestfreq = temp;
+ }
+ }
+
+ pr_debug("DIU chose = %lx\n", bestval);
+ pr_debug("DIU error = %ld\n NomPixClk ", err);
+ pr_debug("DIU: Best Freq = %lx\n", bestfreq);
+ /* Modify DIU_DIV in CCM SCFR1 */
+ temp = in_be32(ccm + CCM_SCFR1);
+ pr_debug("DIU: Current value of SCFR1: 0x%08x\n", temp);
+ temp &= ~DIU_DIV_MASK;
+ temp |= (bestval & DIU_DIV_MASK);
+ out_be32(ccm + CCM_SCFR1, temp);
+ pr_debug("DIU: Modified value of SCFR1: 0x%08x\n", temp);
+ iounmap(ccm);
+}
+
+ssize_t mpc512x_show_monitor_port(int monitor_port, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "0 - 5121 LCD\n");
+}
+
+int mpc512x_set_sysfs_monitor_port(int val)
+{
+ return 0;
+}
+
+static struct fsl_diu_shared_fb __attribute__ ((__aligned__(8))) diu_shared_fb;
+
+#if defined(CONFIG_FB_FSL_DIU) || \
+ defined(CONFIG_FB_FSL_DIU_MODULE)
+static inline void mpc512x_free_bootmem(struct page *page)
+{
+ __ClearPageReserved(page);
+ BUG_ON(PageTail(page));
+ BUG_ON(atomic_read(&page->_count) > 1);
+ atomic_set(&page->_count, 1);
+ __free_page(page);
+ totalram_pages++;
+}
+
+void mpc512x_release_bootmem(void)
+{
+ unsigned long addr = diu_shared_fb.fb_phys & PAGE_MASK;
+ unsigned long size = diu_shared_fb.fb_len;
+ unsigned long start, end;
+
+ if (diu_shared_fb.in_use) {
+ start = PFN_UP(addr);
+ end = PFN_DOWN(addr + size);
+
+ for (; start < end; start++)
+ mpc512x_free_bootmem(pfn_to_page(start));
+
+ diu_shared_fb.in_use = false;
+ }
+ diu_ops.release_bootmem = NULL;
+}
+#endif
+
+/*
+ * Check if DIU was pre-initialized. If so, perform steps
+ * needed to continue displaying through the whole boot process.
+ * Move area descriptor and gamma table elsewhere, they are
+ * destroyed by bootmem allocator otherwise. The frame buffer
+ * address range will be reserved in setup_arch() after bootmem
+ * allocator is up.
+ */
+void __init mpc512x_init_diu(void)
+{
+ struct device_node *np;
+ void __iomem *diu_reg;
+ phys_addr_t desc;
+ void __iomem *vaddr;
+ unsigned long mode, pix_fmt, res, bpp;
+ unsigned long dst;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-diu");
+ if (!np) {
+ pr_err("No DIU node\n");
+ return;
+ }
+
+ diu_reg = of_iomap(np, 0);
+ of_node_put(np);
+ if (!diu_reg) {
+ pr_err("Can't map DIU\n");
+ return;
+ }
+
+ mode = in_be32(diu_reg + 0x1c);
+ if (mode != 1) {
+ pr_info("%s: DIU OFF\n", __func__);
+ goto out;
+ }
+
+ desc = in_be32(diu_reg);
+ vaddr = ioremap(desc, sizeof(struct diu_ad));
+ if (!vaddr) {
+ pr_err("Can't map DIU area desc.\n");
+ goto out;
+ }
+ memcpy(&diu_shared_fb.ad0, vaddr, sizeof(struct diu_ad));
+ /* flush fb area descriptor */
+ dst = (unsigned long)&diu_shared_fb.ad0;
+ flush_dcache_range(dst, dst + sizeof(struct diu_ad) - 1);
+
+ res = in_be32(diu_reg + 0x28);
+ pix_fmt = in_le32(vaddr);
+ bpp = ((pix_fmt >> 16) & 0x3) + 1;
+ diu_shared_fb.fb_phys = in_le32(vaddr + 4);
+ diu_shared_fb.fb_len = ((res & 0xfff0000) >> 16) * (res & 0xfff) * bpp;
+ diu_shared_fb.in_use = true;
+ iounmap(vaddr);
+
+ desc = in_be32(diu_reg + 0xc);
+ vaddr = ioremap(desc, sizeof(diu_shared_fb.gamma));
+ if (!vaddr) {
+ pr_err("Can't map DIU area desc.\n");
+ diu_shared_fb.in_use = false;
+ goto out;
+ }
+ memcpy(&diu_shared_fb.gamma, vaddr, sizeof(diu_shared_fb.gamma));
+ /* flush gamma table */
+ dst = (unsigned long)&diu_shared_fb.gamma;
+ flush_dcache_range(dst, dst + sizeof(diu_shared_fb.gamma) - 1);
+
+ iounmap(vaddr);
+ out_be32(diu_reg + 0xc, virt_to_phys(&diu_shared_fb.gamma));
+ out_be32(diu_reg + 4, 0);
+ out_be32(diu_reg + 8, 0);
+ out_be32(diu_reg, virt_to_phys(&diu_shared_fb.ad0));
+
+out:
+ iounmap(diu_reg);
+}
+
+void __init mpc512x_setup_diu(void)
+{
+ int ret;
+
+ if (diu_shared_fb.in_use) {
+ ret = reserve_bootmem(diu_shared_fb.fb_phys,
+ diu_shared_fb.fb_len,
+ BOOTMEM_EXCLUSIVE);
+ if (ret) {
+ pr_err("%s: reserve bootmem failed\n", __func__);
+ diu_shared_fb.in_use = false;
+ }
+ }
+
+#if defined(CONFIG_FB_FSL_DIU) || \
+ defined(CONFIG_FB_FSL_DIU_MODULE)
+ diu_ops.get_pixel_format = mpc512x_get_pixel_format;
+ diu_ops.set_gamma_table = mpc512x_set_gamma_table;
+ diu_ops.set_monitor_port = mpc512x_set_monitor_port;
+ diu_ops.set_pixel_clock = mpc512x_set_pixel_clock;
+ diu_ops.show_monitor_port = mpc512x_show_monitor_port;
+ diu_ops.set_sysfs_monitor_port = mpc512x_set_sysfs_monitor_port;
+ diu_ops.release_bootmem = mpc512x_release_bootmem;
+#endif
+}
+
void __init mpc512x_init_IRQ(void)
{
struct device_node *np;
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index 42381bb..5360948 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -30,6 +30,7 @@ struct platform_diu_data_ops {
void (*set_pixel_clock) (unsigned int pixclock);
ssize_t (*show_monitor_port) (int monitor_port, char *buf);
int (*set_sysfs_monitor_port) (int val);
+ void (*release_bootmem) (void);
};
extern struct platform_diu_data_ops diu_ops;
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index 7acdc09..81dec09 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -1103,6 +1103,10 @@ static int fsl_diu_open(struct fb_info *info, int user)
struct mfb_info *mfbi = info->par;
int res = 0;
+ /* free boot splash memory on first /dev/fb0 open */
+ if (!mfbi->index && diu_ops.release_bootmem)
+ diu_ops.release_bootmem();
+
spin_lock(&diu_lock);
mfbi->count++;
if (mfbi->count == 1) {
@@ -1430,6 +1434,7 @@ static int __devinit fsl_diu_probe(struct of_device *ofdev,
int ret, i, error = 0;
struct resource res;
struct fsl_diu_data *machine_data;
+ int diu_mode;
machine_data = kzalloc(sizeof(struct fsl_diu_data), GFP_KERNEL);
if (!machine_data)
@@ -1466,7 +1471,9 @@ static int __devinit fsl_diu_probe(struct of_device *ofdev,
goto error2;
}
- out_be32(&dr.diu_reg->diu_mode, 0); /* disable DIU anyway*/
+ diu_mode = in_be32(&dr.diu_reg->diu_mode);
+ if (diu_mode != MFB_MODE1)
+ out_be32(&dr.diu_reg->diu_mode, 0); /* disable DIU */
/* Get the IRQ of the DIU */
machine_data->irq = irq_of_parse_and_map(np, 0);
@@ -1514,7 +1521,13 @@ static int __devinit fsl_diu_probe(struct of_device *ofdev,
machine_data->dummy_ad->offset_xyd = 0;
machine_data->dummy_ad->next_ad = 0;
- out_be32(&dr.diu_reg->desc[0], machine_data->dummy_ad->paddr);
+ /*
+ * Let DIU display splash screen if it was pre-initialized
+ * by the bootloader, set dummy area descriptor otherwise.
+ */
+ if (diu_mode != MFB_MODE1)
+ out_be32(&dr.diu_reg->desc[0], machine_data->dummy_ad->paddr);
+
out_be32(&dr.diu_reg->desc[1], machine_data->dummy_ad->paddr);
out_be32(&dr.diu_reg->desc[2], machine_data->dummy_ad->paddr);
--
1.6.3.3
^ permalink raw reply related
* how do I increase default kernel stack size for my MPC8548 board?
From: hank peng @ 2010-04-30 0:43 UTC (permalink / raw)
To: linuxppc-dev
In kernel source, default kernel stack size for PPC32 is as follows:
#if defined(CONFIG_PPC64)
#define THREAD_SHIFT 14
#elif defined(CONFIG_PPC_256K_PAGES)
#define THREAD_SHIFT 15
#else
#define THREAD_SHIFT 13
#endif
#define THREAD_SIZE (1 << THREAD_SHIFT)
So, default value is 8K, but now I want to increase it to 16K, is it
OK just to change THREAD_SHIFT to 14? or is there some patch needed?
--
The simplest is not all best but the best is surely the simplest!
^ permalink raw reply
* Re: [PATCH 0/5] Rework MPC5121 DIU support (for 2.6.35)
From: Timur Tabi @ 2010-04-30 1:39 UTC (permalink / raw)
To: Anatolij Gustschin
Cc: linux-fbdev, wd, dzu, devicetree-discuss, linuxppc-dev, yorksun
In-Reply-To: <1272584978-19063-1-git-send-email-agust@denx.de>
On Thu, Apr 29, 2010 at 6:49 PM, Anatolij Gustschin <agust@denx.de> wrote:
> This patch series rework DIU support patches submitted
> previously. Comments to the previos patch series have
> been addressed, not related changes are dropped and some
> changes are split out to separate patches to simplify
> review. Furthermore a patch has been added to support
> setting display mode using EDID block in the device tree.
Have you tested these changes on an MPC8610 HPCD? If not, do you
think your changes will break that platform?
I have an 8610 in-house, but I'm currently working on another issue on
that board, so I can't test these patches for you just yet.
--
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply
* Re: [PATCH 5/5] fsl-diu-fb: Support setting display mode using EDID
From: Timur Tabi @ 2010-04-30 1:44 UTC (permalink / raw)
To: Anatolij Gustschin
Cc: linux-fbdev, wd, dzu, devicetree-discuss, linuxppc-dev, yorksun
In-Reply-To: <1272584978-19063-6-git-send-email-agust@denx.de>
On Thu, Apr 29, 2010 at 6:49 PM, Anatolij Gustschin <agust@denx.de> wrote:
> +Optional properties:
> +- EDID : verbatim EDID data block describing attached display.
> + =A0Data from the detailed timing descriptor will be used to
> + =A0program the display controller.
The property name should be lower-case.
> =A0/*
> =A0* These parameters give default parameters
> @@ -217,6 +218,7 @@ struct mfb_info {
> =A0 =A0 =A0 =A0int x_aoi_d; =A0 =A0 =A0 =A0 =A0 =A0/* aoi display x offse=
t to physical screen */
> =A0 =A0 =A0 =A0int y_aoi_d; =A0 =A0 =A0 =A0 =A0 =A0/* aoi display y offse=
t to physical screen */
> =A0 =A0 =A0 =A0struct fsl_diu_data *parent;
> + =A0 =A0 =A0 char *edid_data;
edid_data should be "u8 *". "char *" is should be used only for
strings or arrays of characters.
> + =A0 =A0 =A0 /* Still not found, use preferred mode from database if any=
*/
> + =A0 =A0 =A0 if (!has_default_mode && info->monspecs.modedb !=3D NULL) {
No need for the "!=3D NULL"
--=20
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply
* Re: [PATCH 3/5] powerpc/mpc5121: shared DIU framebuffer support
From: Timur Tabi @ 2010-04-30 2:05 UTC (permalink / raw)
To: Anatolij Gustschin
Cc: linux-fbdev, wd, dzu, John Rigby, devicetree-discuss,
linuxppc-dev, yorksun
In-Reply-To: <1272584978-19063-4-git-send-email-agust@denx.de>
On Thu, Apr 29, 2010 at 6:49 PM, Anatolij Gustschin <agust@denx.de> wrote:
> +void __init mpc5121_ads_init_early(void)
> +{
> + =A0 =A0 =A0 mpc512x_init_diu();
> +}
> +
> =A0define_machine(mpc5121_ads) {
> =A0 =A0 =A0 =A0.name =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =3D "MPC5121 ADS=
",
> =A0 =A0 =A0 =A0.probe =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=3D mpc5121_ads_=
probe,
> =A0 =A0 =A0 =A0.setup_arch =A0 =A0 =A0 =A0 =A0 =A0 =3D mpc5121_ads_setup_=
arch,
> =A0 =A0 =A0 =A0.init =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =3D mpc512x_init=
,
> + =A0 =A0 =A0 .init_early =A0 =A0 =A0 =A0 =A0 =A0 =3D mpc5121_ads_init_ea=
rly,
How about just doing this?
.init_early =3D mpc512x_init_diu,
> +void __init mpc512x_generic_init_early(void)
> +{
> + =A0 =A0 =A0 mpc512x_init_diu();
> +}
> +
> +void __init mpc512x_generic_setup_arch(void)
> +{
> + =A0 =A0 =A0 mpc512x_setup_diu();
> +}
> +
> =A0define_machine(mpc5121_generic) {
> =A0 =A0 =A0 =A0.name =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =3D "MPC5121 gen=
eric",
> =A0 =A0 =A0 =A0.probe =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=3D mpc5121_gene=
ric_probe,
> =A0 =A0 =A0 =A0.init =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =3D mpc512x_init=
,
> + =A0 =A0 =A0 .init_early =A0 =A0 =A0 =A0 =A0 =A0 =3D mpc512x_generic_ini=
t_early,
> + =A0 =A0 =A0 .setup_arch =A0 =A0 =A0 =A0 =A0 =A0 =3D mpc512x_generic_set=
up_arch,
And a similar change here.
> =A0 =A0 =A0 =A0.init_IRQ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =3D mpc512x_init_IRQ=
,
> =A0 =A0 =A0 =A0.get_irq =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=3D ipic_get_irq,
> =A0 =A0 =A0 =A0.calibrate_decr =A0 =A0 =A0 =A0 =3D generic_calibrate_decr=
,
> diff --git a/arch/powerpc/platforms/512x/mpc512x.h b/arch/powerpc/platfor=
ms/512x/mpc512x.h
> index b2daca0..1ab6d11 100644
> --- a/arch/powerpc/platforms/512x/mpc512x.h
> +++ b/arch/powerpc/platforms/512x/mpc512x.h
> @@ -16,4 +16,6 @@ extern void __init mpc512x_init(void);
> =A0extern int __init mpc5121_clk_init(void);
> =A0void __init mpc512x_declare_of_platform_devices(void);
> =A0extern void mpc512x_restart(char *cmd);
> +extern void mpc512x_init_diu(void);
> +extern void mpc512x_setup_diu(void);
> =A0#endif =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* __MPC512X_H_=
_ */
> diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/=
platforms/512x/mpc512x_shared.c
> index b7f518a..8e297fa 100644
> --- a/arch/powerpc/platforms/512x/mpc512x_shared.c
> +++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
> @@ -16,7 +16,11 @@
> =A0#include <linux/io.h>
> =A0#include <linux/irq.h>
> =A0#include <linux/of_platform.h>
> +#include <linux/fsl-diu-fb.h>
> +#include <linux/bootmem.h>
> +#include <sysdev/fsl_soc.h>
>
> +#include <asm/cacheflush.h>
> =A0#include <asm/machdep.h>
> =A0#include <asm/ipic.h>
> =A0#include <asm/prom.h>
> @@ -53,6 +57,286 @@ void mpc512x_restart(char *cmd)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0;
> =A0}
>
> +struct fsl_diu_shared_fb {
> + =A0 =A0 =A0 char =A0 =A0 =A0 =A0 =A0 =A0gamma[0x300]; =A0 /* 32-bit ali=
gned! */
char or u8?
> + =A0 =A0 =A0 struct diu_ad =A0 ad0; =A0 =A0 =A0 =A0 =A0 =A0/* 32-bit ali=
gned! */
> + =A0 =A0 =A0 phys_addr_t =A0 =A0 fb_phys;
> + =A0 =A0 =A0 size_t =A0 =A0 =A0 =A0 =A0fb_len;
> + =A0 =A0 =A0 bool =A0 =A0 =A0 =A0 =A0 =A0in_use;
> +};
Where did "bool" come from? Use "int" instead.
> +unsigned int mpc512x_get_pixel_format(unsigned int bits_per_pixel,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
int monitor_port)
> +{
> + =A0 =A0 =A0 unsigned int pix_fmt;
> +
> + =A0 =A0 =A0 switch (bits_per_pixel) {
> + =A0 =A0 =A0 case 32:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pix_fmt =3D 0x88883316;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case 24:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pix_fmt =3D 0x88082219;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 case 16:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pix_fmt =3D 0x65053118;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 default:
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pix_fmt =3D 0x00000400;
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 return pix_fmt;
> +}
This is simpler:
switch (bits_per_pixel) {
case 32:
return 0x88883316;
case 24:
return 0x88082219;
case 16:
return =3D 0x65053118;
}
return 0x00000400;
}
> + =A0 =A0 =A0 ccm =3D of_iomap(np, 0);
> + =A0 =A0 =A0 if (!ccm) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pr_err("Can't map clock control module reg.=
\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 of_node_put(np);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return;
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 of_node_put(np);
This is simpler:
ccm =3D of_iomap(np, 0);
of_node_put(np);
if (!ccm) {
pr_err("Can't map clock control module reg.\n");
return;
}
> + =A0 =A0 =A0 np =3D of_find_node_by_type(NULL, "cpu");
> + =A0 =A0 =A0 if (np) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 unsigned int size;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 const unsigned int *prop =3D
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 of_get_property(np, "bus-fr=
equency", &size);
Since you don't use 'size', you can skip it:
const unsigned int *prop =3D
of_get_property(np, "bus-frequency", NULL);
> + =A0 =A0 =A0 } else {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pr_err("Can't find \"cpu\" node.\n");
'cpu' is simpler than \"cpu\"
> + =A0 =A0 =A0 /* Calculate the pixel clock with the smallest error */
> + =A0 =A0 =A0 /* calculate the following in steps to avoid overflow */
> + =A0 =A0 =A0 pr_debug("DIU pixclock in ps - %d\n", pixclock);
> + =A0 =A0 =A0 temp =3D (1000000000 / pixclock) * 1000;
I'm pretty sure the compiler will optimize this to:
temp =3D (1000000000000UL / pixclock);
so you may as well do it that way.
> + =A0 =A0 =A0 pixclock =3D temp;
> + =A0 =A0 =A0 pr_debug("DIU pixclock freq - %u\n", pixclock);
> +
> + =A0 =A0 =A0 temp =3D (temp * 5) / 100; /* pixclock * 0.05 */
The compiler will optimize this to:
temp /=3D 20;
> + =A0 =A0 =A0 pr_debug("deviation =3D %d\n", temp);
> + =A0 =A0 =A0 minpixclock =3D pixclock - temp;
> + =A0 =A0 =A0 maxpixclock =3D pixclock + temp;
> + =A0 =A0 =A0 pr_debug("DIU minpixclock - %lu\n", minpixclock);
> + =A0 =A0 =A0 pr_debug("DIU maxpixclock - %lu\n", maxpixclock);
> + =A0 =A0 =A0 pixval =3D speed_ccb/pixclock;
> + =A0 =A0 =A0 pr_debug("DIU pixval =3D %lu\n", pixval);
> +
> + =A0 =A0 =A0 err =3D 100000000;
Why do you assign err to this arbitrary value?
> + =A0 =A0 =A0 bestval =3D pixval;
> + =A0 =A0 =A0 pr_debug("DIU bestval =3D %lu\n", bestval);
> +
> + =A0 =A0 =A0 bestfreq =3D 0;
> + =A0 =A0 =A0 for (i =3D -1; i <=3D 1; i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 temp =3D speed_ccb / (pixval+i);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pr_debug("DIU test pixval i=3D%d, pixval=3D=
%lu, temp freq. =3D %u\n",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 i, pixval, temp);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if ((temp < minpixclock) || (temp > maxpixc=
lock))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pr_debug("DIU exceeds monit=
or range (%lu to %lu)\n",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 minpixclock=
, maxpixclock);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 else if (abs(temp - pixclock) < err) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pr_debug("Entered the else =
if block %d\n", i);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 err =3D abs(temp - pixclock=
);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 bestval =3D pixval + i;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 bestfreq =3D temp;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 pr_debug("DIU chose =3D %lx\n", bestval);
> + =A0 =A0 =A0 pr_debug("DIU error =3D %ld\n NomPixClk ", err);
> + =A0 =A0 =A0 pr_debug("DIU: Best Freq =3D %lx\n", bestfreq);
> + =A0 =A0 =A0 /* Modify DIU_DIV in CCM SCFR1 */
> + =A0 =A0 =A0 temp =3D in_be32(ccm + CCM_SCFR1);
Don't use offsets like + CCM_SCFR1. Create a structure and use that instea=
d.
> + =A0 =A0 =A0 pr_debug("DIU: Current value of SCFR1: 0x%08x\n", temp);
> + =A0 =A0 =A0 temp &=3D ~DIU_DIV_MASK;
> + =A0 =A0 =A0 temp |=3D (bestval & DIU_DIV_MASK);
> + =A0 =A0 =A0 out_be32(ccm + CCM_SCFR1, temp);
> + =A0 =A0 =A0 pr_debug("DIU: Modified value of SCFR1: 0x%08x\n", temp);
> + =A0 =A0 =A0 iounmap(ccm);
> +}
> +
> +ssize_t mpc512x_show_monitor_port(int monitor_port, char *buf)
> +{
> + =A0 =A0 =A0 return snprintf(buf, PAGE_SIZE, "0 - 5121 LCD\n");
There's no point in using snprintf since you're printing a string
literal. You can use sprintf.
> +}
> +
> +int mpc512x_set_sysfs_monitor_port(int val)
> +{
> + =A0 =A0 =A0 return 0;
> +}
> +
> +static struct fsl_diu_shared_fb __attribute__ ((__aligned__(8))) diu_sha=
red_fb;
> +
> +#if defined(CONFIG_FB_FSL_DIU) || \
> + =A0 =A0defined(CONFIG_FB_FSL_DIU_MODULE)
> +static inline void mpc512x_free_bootmem(struct page *page)
> +{
> + =A0 =A0 =A0 __ClearPageReserved(page);
> + =A0 =A0 =A0 BUG_ON(PageTail(page));
> + =A0 =A0 =A0 BUG_ON(atomic_read(&page->_count) > 1);
> + =A0 =A0 =A0 atomic_set(&page->_count, 1);
> + =A0 =A0 =A0 __free_page(page);
> + =A0 =A0 =A0 totalram_pages++;
> +}
> +
> +void mpc512x_release_bootmem(void)
> +{
> + =A0 =A0 =A0 unsigned long addr =3D diu_shared_fb.fb_phys & PAGE_MASK;
> + =A0 =A0 =A0 unsigned long size =3D diu_shared_fb.fb_len;
> + =A0 =A0 =A0 unsigned long start, end;
> +
> + =A0 =A0 =A0 if (diu_shared_fb.in_use) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 start =3D PFN_UP(addr);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 end =3D PFN_DOWN(addr + size);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 for (; start < end; start++)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 mpc512x_free_bootmem(pfn_to=
_page(start));
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 diu_shared_fb.in_use =3D false;
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 diu_ops.release_bootmem =3D NULL;
> +}
> +#endif
Do you really need to use reserve_bootmem? Have you tried kmalloc or
alloc_pages_exact()?
> +
> +/*
> + * Check if DIU was pre-initialized. If so, perform steps
> + * needed to continue displaying through the whole boot process.
> + * Move area descriptor and gamma table elsewhere, they are
> + * destroyed by bootmem allocator otherwise. The frame buffer
> + * address range will be reserved in setup_arch() after bootmem
> + * allocator is up.
> + */
> +void __init mpc512x_init_diu(void)
> +{
> + =A0 =A0 =A0 struct device_node *np;
> + =A0 =A0 =A0 void __iomem *diu_reg;
> + =A0 =A0 =A0 phys_addr_t desc;
> + =A0 =A0 =A0 void __iomem *vaddr;
> + =A0 =A0 =A0 unsigned long mode, pix_fmt, res, bpp;
> + =A0 =A0 =A0 unsigned long dst;
> +
> + =A0 =A0 =A0 np =3D of_find_compatible_node(NULL, NULL, "fsl,mpc5121-diu=
");
> + =A0 =A0 =A0 if (!np) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pr_err("No DIU node\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return;
> + =A0 =A0 =A0 }
Shouldn't you be probing as an OF driver instead of manually searching
for the DIU node?
> +
> + =A0 =A0 =A0 diu_reg =3D of_iomap(np, 0);
> + =A0 =A0 =A0 of_node_put(np);
> + =A0 =A0 =A0 if (!diu_reg) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pr_err("Can't map DIU\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 mode =3D in_be32(diu_reg + 0x1c);
> + =A0 =A0 =A0 if (mode !=3D 1) {
How can in_be32() return a -1?
--=20
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply
* [PATCH 1/3] powerpc: Set a smaller value for RECLAIM_DISTANCE to enable zone reclaim
From: Anton Blanchard @ 2010-04-30 4:33 UTC (permalink / raw)
To: benh; +Cc: linuxppc-dev
I noticed /proc/sys/vm/zone_reclaim_mode was 0 on a ppc64 NUMA box. It gets
enabled via this:
/*
* If another node is sufficiently far away then it is better
* to reclaim pages in a zone before going off node.
*/
if (distance > RECLAIM_DISTANCE)
zone_reclaim_mode = 1;
Since we use the default value of 20 for REMOTE_DISTANCE and 20 for
RECLAIM_DISTANCE it never kicks in.
The local to remote bandwidth ratios can be quite large on System p
machines so it makes sense for us to reclaim clean pagecache locally before
going off node.
The patch below sets a smaller value for RECLAIM_DISTANCE and thus enables
zone reclaim.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: powerpc.git/arch/powerpc/include/asm/topology.h
===================================================================
--- powerpc.git.orig/arch/powerpc/include/asm/topology.h 2010-02-18 14:26:45.736821967 +1100
+++ powerpc.git/arch/powerpc/include/asm/topology.h 2010-02-18 14:51:24.793071748 +1100
@@ -8,6 +8,16 @@ struct device_node;
#ifdef CONFIG_NUMA
+/*
+ * Before going off node we want the VM to try and reclaim from the local
+ * node. It does this if the remote distance is larger than RECLAIM_DISTANCE.
+ * With the default REMOTE_DISTANCE of 20 and the default RECLAIM_DISTANCE of
+ * 20, we never reclaim and go off node straight away.
+ *
+ * To fix this we choose a smaller value of RECLAIM_DISTANCE.
+ */
+#define RECLAIM_DISTANCE 10
+
#include <asm/mmzone.h>
static inline int cpu_to_node(int cpu)
^ permalink raw reply
* [PATCH 2/3] powerpc: Add form 1 NUMA affinity
From: Anton Blanchard @ 2010-04-30 4:34 UTC (permalink / raw)
To: benh; +Cc: linuxppc-dev
In-Reply-To: <20100430043324.GB4622@kryten>
Firmware changed the way it represents memory and cpu affinity on POWER7.
Unfortunately the old method now caps the topology to work around issues
with legacy operating systems. For Linux to get the correct topology we
need to use the new form 1 affinity information.
We set the form 1 field in the client architecture, and if we see "1" in the
ibm,associativity-form property firmware supports form 1 affinity and
we should look at the first field in the ibm,associativity-reference-points
array. If not we use the second field as we always have.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: linux-2.6.34-rc3/arch/powerpc/kernel/prom_init.c
===================================================================
--- linux-2.6.34-rc3.orig/arch/powerpc/kernel/prom_init.c 2010-04-02 07:52:10.000000000 -0500
+++ linux-2.6.34-rc3/arch/powerpc/kernel/prom_init.c 2010-04-07 07:06:45.000000000 -0500
@@ -653,6 +653,7 @@
#else
#define OV5_CMO 0x00
#endif
+#define OV5_TYPE1_AFFINITY 0x80 /* Type 1 NUMA affinity */
/* Option Vector 6: IBM PAPR hints */
#define OV6_LINUX 0x02 /* Linux is our OS */
@@ -706,7 +707,7 @@
OV5_DONATE_DEDICATE_CPU | OV5_MSI,
0,
OV5_CMO,
- 0,
+ OV5_TYPE1_AFFINITY,
0,
0,
0,
Index: linux-2.6.34-rc3/arch/powerpc/mm/numa.c
===================================================================
--- linux-2.6.34-rc3.orig/arch/powerpc/mm/numa.c 2010-04-07 07:06:32.000000000 -0500
+++ linux-2.6.34-rc3/arch/powerpc/mm/numa.c 2010-04-07 09:43:48.000000000 -0500
@@ -242,10 +243,11 @@
*/
static int __init find_min_common_depth(void)
{
- int depth;
+ int depth, index;
const unsigned int *ref_points;
struct device_node *rtas_root;
unsigned int len;
+ struct device_node *options;
rtas_root = of_find_node_by_path("/rtas");
@@ -258,11 +260,23 @@
* configuration (should be all 0's) and the second is for a normal
* NUMA configuration.
*/
+ index = 1;
ref_points = of_get_property(rtas_root,
"ibm,associativity-reference-points", &len);
+ /*
+ * For type 1 affinity information we want the first field
+ */
+ options = of_find_node_by_path("/options");
+ if (options) {
+ const char *str;
+ str = of_get_property(options, "ibm,associativity-form", NULL);
+ if (str && !strcmp(str, "1"))
+ index = 0;
+ }
+
if ((len >= 2 * sizeof(unsigned int)) && ref_points) {
- depth = ref_points[1];
+ depth = ref_points[index];
} else {
dbg("NUMA: ibm,associativity-reference-points not found.\n");
depth = -1;
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox