* gdb & kgdb in MPC85xx
From: Charles Krinke @ 2007-04-15 16:32 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <3C02138692C13C4BB675FE7EA24095293284D7@bluefin.Soneticom.local>
I have a question relating to stepping with gdb connected to a remote =
target. I can connect to the target with its ttyS1 and 'list', 'break' =
just fine. This is with a Linux-2.6.17.11 kernel and gdb 6.5.
=20
A 'cont' begets a message, and a step fails to return. I am hoping =
someone can offer a suggestion or two.
As an example, I start from uboot with the kernel command line =
containing 'kgdbwait kgdb=3DttyS1,115200' and the target stops at =
'setup_arch: kgdb breakpoint' as I would expect. I am using a USB serial =
dongle, which has worked well for this type of debugging on other =
targets.
=20
$ .../linux
$ ppc-gdb vmlinux [its version 6.5 cross from ultsol]
(gdb) show architeture [its powerpc:common]
(gdb) show verbose [its on]=20
(gdb) target remote /dev/ttyUSB0=20
(gdb) list [works fine]=20
(gdb) break do_fork [sets fine]=20
(gdb) cont
[some problem here as gdb says=20
"Can't send signals to this remote system. SIGILL not sent."
but the breakpoint is taken and the target stops at the beginning of =
do_fork]
(gdb) step
[big problem now as the step never returns]
=20
=20
Charles Krinke
^ permalink raw reply
* Re: [PATCH dtc take 2] Fix reserve map output for asm format.
From: Milton Miller @ 2007-04-15 19:59 UTC (permalink / raw)
To: Jerry Van Baren, Jon Loeliger; +Cc: linuxppc-dev, David Gibson
In-Reply-To: <20070415022914.GA5628@dellserver.lan>
Sometime around Sun Apr 15 12:29:14 EST 2007, Jerry Van Baren wrote:
> Add extra reserve map slots output for asm format (previously done for
> dtb
> output).
>
> Signed-off-by: Gerald Van Baren <vanbaren at cideas.com>
> ---
>
> Hi Jon, David,
>
> Here is a patch that fixes the asm output without the (unnecessary)
> calloc change.
>
> Best regards,
> gvb
The previous description had
> Use cmalloc to pre-zero memory (for dtb input) and handle dtb (binary)
> input being shorter than the total blob length (result of putting
> extra space in the blob).
Which at least said in the description the unrelated things it was
doing.
> while (sizeleft) {
> - if (feof(f))
> - die("EOF before reading %d bytes of DT blob\n",
> - totalsize);
> + if (feof(f)) {
> + WARNMSG("EOF after reading %d of %d bytes of
> DT blob, assuming there is extra space in the blob.\n",
> + totalsize - sizeleft, totalsize);
> + break;
> + }
I thnk the above should be an ERROR and cause failure without
the -f (force) option.
The total_size says how much data should be copied. Anything
less and there is data missing. Assuming zeros is wrong for
most sections (the exception being the memory reserve list
that had a terminating 0 entry within the read portion).
milton
^ permalink raw reply
* Re: [PATCH dtc take 2] Fix reserve map output for asm format.
From: Jerry Van Baren @ 2007-04-16 0:24 UTC (permalink / raw)
To: Milton Miller; +Cc: linuxppc-dev, Jon Loeliger
In-Reply-To: <aa6a7bd73be20ea11e3e98f87a66e478@bga.com>
Milton Miller wrote:
> Sometime around Sun Apr 15 12:29:14 EST 2007, Jerry Van Baren wrote:
>> Add extra reserve map slots output for asm format (previously done for
>> dtb
>> output).
>>
>> Signed-off-by: Gerald Van Baren <vanbaren at cideas.com>
>> ---
>>
>> Hi Jon, David,
>>
>> Here is a patch that fixes the asm output without the (unnecessary)
>> calloc change.
>>
>> Best regards,
>> gvb
>
>
> The previous description had
>> Use cmalloc to pre-zero memory (for dtb input) and handle dtb (binary)
>> input being shorter than the total blob length (result of putting
>> extra space in the blob).
>
>
> Which at least said in the description the unrelated things it was
> doing.
That was my added comment WRT the change from malloc to cmalloc. David
wasn't wild about using cmalloc, so I removed it. Using cmalloc is not
necessary.
>> while (sizeleft) {
>> - if (feof(f))
>> - die("EOF before reading %d bytes of DT blob\n",
>> - totalsize);
>> + if (feof(f)) {
>> + WARNMSG("EOF after reading %d of %d bytes of
>> DT blob, assuming there is extra space in the blob.\n",
>> + totalsize - sizeleft, totalsize);
>> + break;
>> + }
>
> I thnk the above should be an ERROR and cause failure without
> the -f (force) option.
>
> The total_size says how much data should be copied. Anything
> less and there is data missing. Assuming zeros is wrong for
> most sections (the exception being the memory reserve list
> that had a terminating 0 entry within the read portion).
>
> milton
The reason total_size is bigger than the actual size is because I
created the blob with extra space using the -S parameter. It is
intentionally bigger. The extra space is ignored by dtc when creating a
dts/asm format output which is why cmalloc() is unnecessary.
I suppose we could require a -f force but I'm not wild about creating a
nanny program. There is nothing wrong with the blob - it parses just
fine. If there were problems with the blob contents, other errors would
be raised.
Best regards,
gvb
^ permalink raw reply
* Re: [PATCH dtc take 2] Fix reserve map output for asm format.
From: David Gibson @ 2007-04-16 0:51 UTC (permalink / raw)
To: Jerry Van Baren; +Cc: linuxppc-dev, Jon Loeliger, Milton Miller
In-Reply-To: <4622C226.1070304@gmail.com>
On Sun, Apr 15, 2007 at 08:24:06PM -0400, Jerry Van Baren wrote:
> Milton Miller wrote:
> > Sometime around Sun Apr 15 12:29:14 EST 2007, Jerry Van Baren wrote:
> >> Add extra reserve map slots output for asm format (previously done for
> >> dtb
> >> output).
> >>
> >> Signed-off-by: Gerald Van Baren <vanbaren at cideas.com>
> >> ---
> >>
> >> Hi Jon, David,
> >>
> >> Here is a patch that fixes the asm output without the (unnecessary)
> >> calloc change.
> >>
> >> Best regards,
> >> gvb
> >
> >
> > The previous description had
> >> Use cmalloc to pre-zero memory (for dtb input) and handle dtb (binary)
> >> input being shorter than the total blob length (result of putting
> >> extra space in the blob).
> >
> >
> > Which at least said in the description the unrelated things it was
> > doing.
>
> That was my added comment WRT the change from malloc to cmalloc. David
> wasn't wild about using cmalloc, so I removed it. Using cmalloc is not
> necessary.
>
> >> while (sizeleft) {
> >> - if (feof(f))
> >> - die("EOF before reading %d bytes of DT blob\n",
> >> - totalsize);
> >> + if (feof(f)) {
> >> + WARNMSG("EOF after reading %d of %d bytes of
> >> DT blob, assuming there is extra space in the blob.\n",
> >> + totalsize - sizeleft, totalsize);
> >> + break;
> >> + }
> >
> > I thnk the above should be an ERROR and cause failure without
> > the -f (force) option.
> >
> > The total_size says how much data should be copied. Anything
> > less and there is data missing. Assuming zeros is wrong for
> > most sections (the exception being the memory reserve list
> > that had a terminating 0 entry within the read portion).
> >
> > milton
>
> The reason total_size is bigger than the actual size is because I
> created the blob with extra space using the -S parameter. It is
> intentionally bigger. The extra space is ignored by dtc when creating a
> dts/asm format output which is why cmalloc() is unnecessary.
>
> I suppose we could require a -f force but I'm not wild about creating a
> nanny program. There is nothing wrong with the blob - it parses just
> fine. If there were problems with the blob contents, other errors would
> be raised.
I think the warning is fine, but not for exactly the reasons you
state. Several points:
- At least with v17 input, where it's possible, we probably *should*
check that an input blob isn't truncated in the middle of the strings
or structure sections. That should be more than a warning.
- Milton, saying totalsize indicates the amount of data to be copied
is misleading in this context. That's a good philosphy for things
that just read and/or slightly tweak the tree - data outside the known
sections which it can't interpret should be left unaltered wherever
possible. dtc, however, *always* fully interprets and re-emits the
tree. Any data outside the known and understood sections is *always*
discarded, so I don't think there's any problem assuming it to be
zero.
- That said, I think when using -S, at least the default behaviour
should emit extra zero bytes in addition to changing the totalsize
header. Then at least in the simplest case of feeding dtc's dtb
output back into dtc, the warning will not occur.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [PATCH dtc take 2] Fix reserve map output for asm format.
From: Jerry Van Baren @ 2007-04-16 1:20 UTC (permalink / raw)
To: Milton Miller, linuxppc-dev, Jon Loeliger
In-Reply-To: <20070416005145.GA19270@localhost.localdomain>
David Gibson wrote:
> On Sun, Apr 15, 2007 at 08:24:06PM -0400, Jerry Van Baren wrote:
>> Milton Miller wrote:
>>> Sometime around Sun Apr 15 12:29:14 EST 2007, Jerry Van Baren wrote:
>>>> Add extra reserve map slots output for asm format (previously done for
>>>> dtb
>>>> output).
>>>>
>>>> Signed-off-by: Gerald Van Baren <vanbaren at cideas.com>
>>>> ---
>>>>
>>>> Hi Jon, David,
>>>>
>>>> Here is a patch that fixes the asm output without the (unnecessary)
>>>> calloc change.
>>>>
>>>> Best regards,
>>>> gvb
>>>
>>> The previous description had
>>>> Use cmalloc to pre-zero memory (for dtb input) and handle dtb (binary)
>>>> input being shorter than the total blob length (result of putting
>>>> extra space in the blob).
>>>
>>> Which at least said in the description the unrelated things it was
>>> doing.
>> That was my added comment WRT the change from malloc to cmalloc. David
>> wasn't wild about using cmalloc, so I removed it. Using cmalloc is not
>> necessary.
>>
>>>> while (sizeleft) {
>>>> - if (feof(f))
>>>> - die("EOF before reading %d bytes of DT blob\n",
>>>> - totalsize);
>>>> + if (feof(f)) {
>>>> + WARNMSG("EOF after reading %d of %d bytes of
>>>> DT blob, assuming there is extra space in the blob.\n",
>>>> + totalsize - sizeleft, totalsize);
>>>> + break;
>>>> + }
>>> I thnk the above should be an ERROR and cause failure without
>>> the -f (force) option.
>>>
>>> The total_size says how much data should be copied. Anything
>>> less and there is data missing. Assuming zeros is wrong for
>>> most sections (the exception being the memory reserve list
>>> that had a terminating 0 entry within the read portion).
>>>
>>> milton
>> The reason total_size is bigger than the actual size is because I
>> created the blob with extra space using the -S parameter. It is
>> intentionally bigger. The extra space is ignored by dtc when creating a
>> dts/asm format output which is why cmalloc() is unnecessary.
>>
>> I suppose we could require a -f force but I'm not wild about creating a
>> nanny program. There is nothing wrong with the blob - it parses just
>> fine. If there were problems with the blob contents, other errors would
>> be raised.
>
> I think the warning is fine, but not for exactly the reasons you
> state. Several points:
>
> - At least with v17 input, where it's possible, we probably *should*
> check that an input blob isn't truncated in the middle of the strings
> or structure sections. That should be more than a warning.
>
> - Milton, saying totalsize indicates the amount of data to be copied
> is misleading in this context. That's a good philosphy for things
> that just read and/or slightly tweak the tree - data outside the known
> sections which it can't interpret should be left unaltered wherever
> possible. dtc, however, *always* fully interprets and re-emits the
> tree. Any data outside the known and understood sections is *always*
> discarded, so I don't think there's any problem assuming it to be
> zero.
>
> - That said, I think when using -S, at least the default behaviour
> should emit extra zero bytes in addition to changing the totalsize
> header. Then at least in the simplest case of feeding dtc's dtb
> output back into dtc, the warning will not occur.
Hi David,
Yes, emitting zeros (or asm equiv) for the extra space makes sense.
That would be a better way to fix the read problem.
I'm thinking about a fill/nofill and/or specifying the value for the
fill bytes, but I cannot think of a reason that would be useful (my
first thought was filling with 0xFF for flash, but I think most or all
fdt writes need to modify some existing values so being able to modify
the extra space in-place doesn't help because the existing values cannot
be modified in-place in flash).
Now to find some time to implement it...
Best regards,
gvb
^ permalink raw reply
* Re: [PATCH dtc take 2] Fix reserve map output for asm format.
From: Milton Miller @ 2007-04-16 3:49 UTC (permalink / raw)
To: David Gibson; +Cc: linuxppc-dev, Jon Loeliger
In-Reply-To: <20070416005145.GA19270@localhost.localdomain>
On Apr 15, 2007, at 7:51 PM, David Gibson wrote:
> On Sun, Apr 15, 2007 at 08:24:06PM -0400, Jerry Van Baren wrote:
>> Milton Miller wrote:
>>> Sometime around Sun Apr 15 12:29:14 EST 2007, Jerry Van Baren wrote:
>>>> Add extra reserve map slots output for asm format (previously done
>>>> for
>>>> dtb
>>>> output).
>>>>
>>>> Signed-off-by: Gerald Van Baren <vanbaren at cideas.com>
>>>> ---
>>>>
>>>> Hi Jon, David,
>>>>
>>>> Here is a patch that fixes the asm output without the (unnecessary)
>>>> calloc change.
>>>>
>>>> Best regards,
>>>> gvb
>>>
>>>
>>> The previous description had
>>>> Use cmalloc to pre-zero memory (for dtb input) and handle dtb
>>>> (binary)
>>>> input being shorter than the total blob length (result of putting
>>>> extra space in the blob).
>>>
>>>
>>> Which at least said in the description the unrelated things it was
>>> doing.
>>
>> That was my added comment WRT the change from malloc to cmalloc.
>> David
>> wasn't wild about using cmalloc, so I removed it. Using cmalloc is
>> not
>> necessary.
Jerry,
>>>> and handle dtb (binary)
>>>> input being shorter than the total blob length (result of putting
>>>> extra space in the blob).
That part is still in this patch.
And I think it should be a separate patch. Its unrelated to filling
in .long 0 for the memory reserve map.
That said, one could use .space there I suppose. Its fine the way it
is.
>>>> while (sizeleft) {
>>>> - if (feof(f))
>>>> - die("EOF before reading %d bytes of DT
>>>> blob\n",
>>>> - totalsize);
>>>> + if (feof(f)) {
>>>> + WARNMSG("EOF after reading %d of %d bytes of
>>>> DT blob, assuming there is extra space in the blob.\n",
>>>> + totalsize - sizeleft, totalsize);
>>>> + break;
>>>> + }
>>>
>>> I thnk the above should be an ERROR and cause failure without
>>> the -f (force) option.
>>>
>>> The total_size says how much data should be copied. Anything
>>> less and there is data missing. Assuming zeros is wrong for
>>> most sections (the exception being the memory reserve list
>>> that had a terminating 0 entry within the read portion).
>>>
>>> milton
>>
>> The reason total_size is bigger than the actual size is because I
>> created the blob with extra space using the -S parameter. It is
>> intentionally bigger. The extra space is ignored by dtc when
>> creating a
>> dts/asm format output which is why cmalloc() is unnecessary.
If this is a case of reading in the files it creates, then its wrong
to have the size created less than total_size. The space needs to be
in the output file. To have it not be in the output is wrong. For
instance it will not be allocated by objcopy nor the linker when its
inserted into the dtb section of the zImage wrapper, which would lead to
scribbling on memory belonging to something else, or at least
unallocated.
Similar for a firmware that treats the dt_struct as binary data. It
might be loaded just before the initrd for instance.
>> I suppose we could require a -f force but I'm not wild about creating
>> a
>> nanny program. There is nothing wrong with the blob - it parses just
>> fine. If there were problems with the blob contents, other errors
>> would
>> be raised.
>
> I think the warning is fine, but not for exactly the reasons you
> state. Several points:
>
> - At least with v17 input, where it's possible, we probably *should*
> check that an input blob isn't truncated in the middle of the strings
> or structure sections. That should be more than a warning.
Or check that (1) the memory reserve list is terminated before this
point, (2) the dt_struct has matching node begin and end count and
ends with tree end, and (3) all strings referenced by dt_struct are
before the read size.
> - Milton, saying totalsize indicates the amount of data to be copied
> is misleading in this context. That's a good philosphy for things
> that just read and/or slightly tweak the tree - data outside the known
> sections which it can't interpret should be left unaltered wherever
> possible.
Actually, I think anything modifiny a tree with a higher revision
than it understands, that has to move sections to increase the
space, must downgrade the tree to the revision that it understands.
It just doesn't know what the new structure revison means, and that
its safe to claim it still meets the new revision.
> dtc, however, *always* fully interprets and re-emits the
> tree. Any data outside the known and understood sections is *always*
> discarded, so I don't think there's any problem assuming it to be
> zero.
I haven't looked at the code, but it appears that this is just reading
the blob into memory. I'd be fine with short file handling if it was
parsing the structure as it was reading.
If you want to make it not an error, then it should be confirmed that
the missing information is not accessed. That can be done by parsing
the structure and verifying one doesn't read beyond what was read, or
by moving it to but up against unmapped pages for all I care. For
that matter, I don't care if any section is truncated as long
as the parse shows all data was read before the end.
Regardless, this is unrelated to properly allocating the requested
space for extra memory reserve slots in asm output, which is the
subject of this patch.
> - That said, I think when using -S, at least the default behaviour
> should emit extra zero bytes in addition to changing the totalsize
> header. Then at least in the simplest case of feeding dtc's dtb
> output back into dtc, the warning will not occur.
Change default behavior to only behavior and I agree. And its
the real fix for the problem.
milton
^ permalink raw reply
* Re: [PATCH dtc take 2] Fix reserve map output for asm format.
From: David Gibson @ 2007-04-16 4:16 UTC (permalink / raw)
To: Milton Miller; +Cc: linuxppc-dev, Jon Loeliger
In-Reply-To: <ae5a6dc4dd96c8459b58b4916e35f7f7@bga.com>
On Sun, Apr 15, 2007 at 10:49:57PM -0500, Milton Miller wrote:
> On Apr 15, 2007, at 7:51 PM, David Gibson wrote:
> > On Sun, Apr 15, 2007 at 08:24:06PM -0400, Jerry Van Baren wrote:
> >> Milton Miller wrote:
> >>> Sometime around Sun Apr 15 12:29:14 EST 2007, Jerry Van Baren wrote:
> >>>> Add extra reserve map slots output for asm format (previously done
> >>>> for
> >>>> dtb
> >>>> output).
> >>>>
> >>>> Signed-off-by: Gerald Van Baren <vanbaren at cideas.com>
> >>>> ---
> >>>>
> >>>> Hi Jon, David,
> >>>>
> >>>> Here is a patch that fixes the asm output without the (unnecessary)
> >>>> calloc change.
> >>>>
> >>>> Best regards,
> >>>> gvb
> >>>
> >>>
> >>> The previous description had
> >>>> Use cmalloc to pre-zero memory (for dtb input) and handle dtb
> >>>> (binary)
> >>>> input being shorter than the total blob length (result of putting
> >>>> extra space in the blob).
> >>>
> >>>
> >>> Which at least said in the description the unrelated things it was
> >>> doing.
> >>
> >> That was my added comment WRT the change from malloc to cmalloc.
> >> David
> >> wasn't wild about using cmalloc, so I removed it. Using cmalloc is
> >> not
> >> necessary.
>
> Jerry,
>
> >>>> and handle dtb (binary)
> >>>> input being shorter than the total blob length (result of putting
> >>>> extra space in the blob).
>
> That part is still in this patch.
>
> And I think it should be a separate patch. Its unrelated to filling
> in .long 0 for the memory reserve map.
Yes.
> That said, one could use .space there I suppose. Its fine the way it
> is.
I think .space would be the preferred method for adding the padding
space at the end in asm format.
> >>>> while (sizeleft) {
> >>>> - if (feof(f))
> >>>> - die("EOF before reading %d bytes of DT
> >>>> blob\n",
> >>>> - totalsize);
> >>>> + if (feof(f)) {
> >>>> + WARNMSG("EOF after reading %d of %d bytes of
> >>>> DT blob, assuming there is extra space in the blob.\n",
> >>>> + totalsize - sizeleft, totalsize);
> >>>> + break;
> >>>> + }
> >>>
> >>> I thnk the above should be an ERROR and cause failure without
> >>> the -f (force) option.
> >>>
> >>> The total_size says how much data should be copied. Anything
> >>> less and there is data missing. Assuming zeros is wrong for
> >>> most sections (the exception being the memory reserve list
> >>> that had a terminating 0 entry within the read portion).
> >>>
> >>> milton
> >>
> >> The reason total_size is bigger than the actual size is because I
> >> created the blob with extra space using the -S parameter. It is
> >> intentionally bigger. The extra space is ignored by dtc when
> >> creating a
> >> dts/asm format output which is why cmalloc() is unnecessary.
>
> If this is a case of reading in the files it creates, then its wrong
> to have the size created less than total_size. The space needs to be
> in the output file. To have it not be in the output is wrong. For
> instance it will not be allocated by objcopy nor the linker when its
> inserted into the dtb section of the zImage wrapper, which would lead to
> scribbling on memory belonging to something else, or at least
> unallocated.
> Similar for a firmware that treats the dt_struct as binary data. It
> might be loaded just before the initrd for instance.
Well, I can see specialized case uses for totalsize greater than
stored size: where you know the blob is going to be copied into
another staging area with more space, for example.
> >> I suppose we could require a -f force but I'm not wild about creating
> >> a
> >> nanny program. There is nothing wrong with the blob - it parses just
> >> fine. If there were problems with the blob contents, other errors
> >> would
> >> be raised.
> >
> > I think the warning is fine, but not for exactly the reasons you
> > state. Several points:
> >
> > - At least with v17 input, where it's possible, we probably *should*
> > check that an input blob isn't truncated in the middle of the strings
> > or structure sections. That should be more than a warning.
>
> Or check that (1) the memory reserve list is terminated before this
> point, (2) the dt_struct has matching node begin and end count and
> ends with tree end, and (3) all strings referenced by dt_struct are
> before the read size.
I think just checking the header lengths of the sub-blocks should be
sufficient at this point. Checking that the begin/end count matches
in the structure block and that all the string references are valid
can, I think, be correctly delayed until we actually parse the
structure block.
> > - Milton, saying totalsize indicates the amount of data to be copied
> > is misleading in this context. That's a good philosphy for things
> > that just read and/or slightly tweak the tree - data outside the known
> > sections which it can't interpret should be left unaltered wherever
> > possible.
>
> Actually, I think anything modifiny a tree with a higher revision
> than it understands, that has to move sections to increase the
> space, must downgrade the tree to the revision that it understands.
> It just doesn't know what the new structure revison means, and that
> its safe to claim it still meets the new revision.
Oh, absolutely the version should be downgraded on writes. I wasn't
really thinking of new format revisions adding extra data - I was
thinking of hacks like programs stuffing some extra, runtime-use data
into the "gaps" in the device tree blob. Clearly any such approach is
always going to be risky to combine with r/w tree access, but it could
be useful in some circumstances, so it doesn't hurt to be robust
against it when we can.
> > dtc, however, *always* fully interprets and re-emits the
> > tree. Any data outside the known and understood sections is *always*
> > discarded, so I don't think there's any problem assuming it to be
> > zero.
>
> I haven't looked at the code, but it appears that this is just reading
> the blob into memory. I'd be fine with short file handling if it was
> parsing the structure as it was reading.
>
> If you want to make it not an error, then it should be confirmed that
> the missing information is not accessed. That can be done by parsing
> the structure and verifying one doesn't read beyond what was read, or
> by moving it to but up against unmapped pages for all I care. For
> that matter, I don't care if any section is truncated as long
> as the parse shows all data was read before the end.
Again just checking that the truncation doesn't occur in the middle of
one of the data blocks as described by the header I think is
sufficient here. More detailed checks happen when we parse the
subsections.
> Regardless, this is unrelated to properly allocating the requested
> space for extra memory reserve slots in asm output, which is the
> subject of this patch.
>
> > - That said, I think when using -S, at least the default behaviour
> > should emit extra zero bytes in addition to changing the totalsize
> > header. Then at least in the simplest case of feeding dtc's dtb
> > output back into dtc, the warning will not occur.
>
> Change default behavior to only behavior and I agree. And its
> the real fix for the problem.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [PATCH] icecube/lite5200b: wakeup from low-power support
From: Grant Likely @ 2007-04-16 4:45 UTC (permalink / raw)
To: Domen Puncer, Stefan Roese; +Cc: u-boot-users, linuxppc-embedded
In-Reply-To: <20070403084649.GA9163@nd47.coderock.org>
On 4/3/07, Domen Puncer <domen.puncer@telargo.com> wrote:
> U-Boot part of Lite5200b low power mode support.
> Puts SDRAM out of self-refresh and transfers control to
> address saved at physical 0x0.
Looks good; almost there. Only one thing missing... you need to add
your "Signed-off-by" line. :-) See Documentation/SubmittingPatches
in the Linux source tree. (You can just reply to this message, and
whoever merges the patch will add the line to the commit message)
Acked-by: Grant Likely <grant.likely@secretlab.ca>
Stefan; since there is no 5200 custodian, can you please pick up this
patch once Domen sends a Signed-of-by replay?
Cheers,
g.
>
>
> ---
> On 26/03/07 10:08 -0600, Grant Likely wrote:
> > On 3/15/07, Domen Puncer <domen.puncer@telargo.com> wrote:
> > >U-Boot part of Lite5200b low power mode support.
> > >Puts SDRAM out of self-refresh and transfers control to
> > >address saved at physical 0x0.
> >
> > This looks pretty straight forward.
> >
> > My only comment is that psc2_4 is probably used as GPIO instead of
> > power control by some users (The lite5200 is an eval board after all).
> > Maybe wrap the code with #ifdef CONFIG_LITE5200B_PM (instead of
> > CONFIG_LITE5200B) so that it can be easily compiled out.
> >
> > Also, '//' style comments should be changed to '/* */'
> >
> > Otherwise;
> > Acked-by: Grant Likely <grant.likely@secretlab.ca>
> >
>
> OK. This one should be better:
>
> Makefile | 5 ++++
> board/icecube/icecube.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 54 insertions(+)
>
> Index: u-boot.git/board/icecube/icecube.c
> ===================================================================
> --- u-boot.git.orig/board/icecube/icecube.c
> +++ u-boot.git/board/icecube/icecube.c
> @@ -42,6 +42,53 @@
> #include "mt48lc16m16a2-75.h"
> # endif
> #endif
> +
> +#ifdef CONFIG_LITE5200B_PM
> +/* u-boot part of low-power mode implementation */
> +#define SAVED_ADDR (*(void **)0x00000000)
> +#define PSC2_4 0x02
> +
> +void lite5200b_wakeup(void)
> +{
> + unsigned char wakeup_pin;
> + void (*linux_wakeup)(void);
> +
> + /* check PSC2_4, if it's down "QT" is signaling we have a wakeup
> + * from low power mode */
> + *(vu_char *)MPC5XXX_WU_GPIO_ENABLE = PSC2_4;
> + __asm__ volatile ("sync");
> +
> + wakeup_pin = *(vu_char *)MPC5XXX_WU_GPIO_DATA_I;
> + if (wakeup_pin & PSC2_4)
> + return;
> +
> + /* acknowledge to "QT"
> + * by holding pin at 1 for 10 uS */
> + *(vu_char *)MPC5XXX_WU_GPIO_DIR = PSC2_4;
> + __asm__ volatile ("sync");
> + *(vu_char *)MPC5XXX_WU_GPIO_DATA_O = PSC2_4;
> + __asm__ volatile ("sync");
> + udelay(10);
> +
> + /* put ram out of self-refresh */
> + *(vu_long *)MPC5XXX_SDRAM_CTRL |= 0x80000000; /* mode_en */
> + __asm__ volatile ("sync");
> + *(vu_long *)MPC5XXX_SDRAM_CTRL |= 0x50000000; /* cke ref_en */
> + __asm__ volatile ("sync");
> + *(vu_long *)MPC5XXX_SDRAM_CTRL &= ~0x80000000; /* !mode_en */
> + __asm__ volatile ("sync");
> + udelay(10); /* wait a bit */
> +
> + /* jump back to linux kernel code */
> + linux_wakeup = SAVED_ADDR;
> + printf("\n\nLooks like we just woke, transferring control to 0x%08lx\n",
> + linux_wakeup);
> + linux_wakeup();
> +}
> +#else
> +#define lite5200b_wakeup()
> +#endif
> +
> #ifndef CFG_RAMBOOT
> static void sdram_start (int hi_addr)
> {
> @@ -208,6 +255,8 @@ long int initdram (int board_type)
> __asm__ volatile ("sync");
> }
>
> + lite5200b_wakeup();
> +
> return dramsize + dramsize2;
> }
>
> Index: u-boot.git/Makefile
> ===================================================================
> --- u-boot.git.orig/Makefile
> +++ u-boot.git/Makefile
> @@ -430,6 +430,7 @@ inka4x0_config: unconfig
> @$(MKCONFIG) inka4x0 ppc mpc5xxx inka4x0
>
> lite5200b_config \
> +lite5200b_PM_config \
> lite5200b_LOWBOOT_config: unconfig
> @mkdir -p $(obj)include
> @mkdir -p $(obj)board/icecube
> @@ -438,6 +439,10 @@ lite5200b_LOWBOOT_config: unconfig
> @ echo "... DDR memory revision"
> @ echo "#define CONFIG_MPC5200" >>$(obj)include/config.h
> @ echo "#define CONFIG_LITE5200B" >>$(obj)include/config.h
> + @[ -z "$(findstring _PM_,$@)" ] || \
> + { echo "#define CONFIG_LITE5200B_PM" >>$(obj)include/config.h ; \
> + echo "... with power management (low-power mode) support" ; \
> + }
> @[ -z "$(findstring LOWBOOT_,$@)" ] || \
> { echo "TEXT_BASE = 0xFF000000" >$(obj)board/icecube/config.tmp ; \
> echo "... with LOWBOOT configuration" ; \
>
--
Grant Likely, B.Sc. P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195
^ permalink raw reply
* Re: [PATCH dtc take 2] Fix reserve map output for asm format.
From: Milton Miller @ 2007-04-16 5:08 UTC (permalink / raw)
To: David Gibson; +Cc: linuxppc-dev, Jon Loeliger
In-Reply-To: <20070416041651.GA20274@localhost.localdomain>
On Apr 15, 2007, at 11:16 PM, David Gibson wrote:
> On Sun, Apr 15, 2007 at 10:49:57PM -0500, Milton Miller wrote:
>> On Apr 15, 2007, at 7:51 PM, David Gibson wrote:
>>> On Sun, Apr 15, 2007 at 08:24:06PM -0400, Jerry Van Baren wrote:
>>>> Milton Miller wrote:
>>>>> Sometime around Sun Apr 15 12:29:14 EST 2007, Jerry Van Baren
>>>>> wrote:
>>>>>> Add extra reserve map slots output for asm format (previously done
>>>>>> for
>>>>>> dtb
>>>>>> output).
>>>>>> and handle dtb (binary)
>>>>>> input being shorter than the total blob length (result of
>>>>>> putting
>>>>>> extra space in the blob).
>>
>> That part is still in this patch.
>>
>> And I think it should be a separate patch. Its unrelated to filling
>> in .long 0 for the memory reserve map.
>
> Yes.
>> That said, one could use .space there I suppose. Its fine the way it
>> is.
>
> I think .space would be the preferred method for adding the padding
> space at the end in asm format.
For the space at the end, I agree. Or use .org 99b+size with 99: at the
begining of the struct. The .long 0 was more for memory reserve, where
the entries might be replaced before assembly.
>>>>> The total_size says how much data should be copied. Anything
>>>>> less and there is data missing. Assuming zeros is wrong for
>>>>> most sections (the exception being the memory reserve list
>>>>> that had a terminating 0 entry within the read portion).
>>>>>
>>>>> milton
>>>>
>>>> The reason total_size is bigger than the actual size is because I
>>>> created the blob with extra space using the -S parameter. It is
>>>> intentionally bigger. The extra space is ignored by dtc when
>>>> creating a
>>>> dts/asm format output which is why cmalloc() is unnecessary.
>>
>> If this is a case of reading in the files it creates, then its wrong
>> to have the size created less than total_size. The space needs to be
>> in the output file. To have it not be in the output is wrong. For
>> instance it will not be allocated by objcopy nor the linker when its
>> inserted into the dtb section of the zImage wrapper, which would lead
>> to
>> scribbling on memory belonging to something else, or at least
>> unallocated.
>> Similar for a firmware that treats the dt_struct as binary data. It
>> might be loaded just before the initrd for instance.
>
> Well, I can see specialized case uses for totalsize greater than
> stored size: where you know the blob is going to be copied into
> another staging area with more space, for example.
That can either be done with your embedding script processing and
noticing
the zeros at the end or by a special option I guess.
>>>> I suppose we could require a -f force but I'm not wild about
>>>> creating
>>>> a
>>>> nanny program. There is nothing wrong with the blob - it parses
>>>> just
>>>> fine. If there were problems with the blob contents, other errors
>>>> would
>>>> be raised.
You mean like not creating output for -I fs -O dts when there are
expected properties (files) missing? :-) The kernel booted just
fine, it was processing /proc/device-tree after all.
Its probably wrong to check for expected properties when the output
is dts. At least the checks should not be more than a warning (that
you may have selected a subtree).
>>> I think the warning is fine, but not for exactly the reasons you
>>> state. Several points:
>>>
>>> - At least with v17 input, where it's possible, we probably *should*
>>> check that an input blob isn't truncated in the middle of the strings
>>> or structure sections. That should be more than a warning.
>>
>> Or check that (1) the memory reserve list is terminated before this
>> point, (2) the dt_struct has matching node begin and end count and
>> ends with tree end, and (3) all strings referenced by dt_struct are
>> before the read size.
>
> I think just checking the header lengths of the sub-blocks should be
> sufficient at this point. Checking that the begin/end count matches
> in the structure block and that all the string references are valid
> can, I think, be correctly delayed until we actually parse the
> structure block.
Checking the sublock lengths is sufficient, but actually more
restrictive that what I said. And mine works on older formats
without the size fields. But yes, yours is simpler when the fields
exist.
Or just leave it an error, fix the output, and make the user fix the
input. If you took off the zeros, you can add padding from /dev/zero
or /dev/random or /etc/motd, as you said the data should not be used.
milton
^ permalink raw reply
* PROBLEM: kernel 2.6.20.6 build failed for ppc board chestnut(ibm ppc 750GX/FX)
From: Wang, Baojun @ 2007-04-16 5:13 UTC (permalink / raw)
To: linux-kernel; +Cc: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 2969 bytes --]
PROBLEM: linux kernel 2.6.20.6 build failed for ppc board chestnut(ibm ppc
750GX/FX)
STEPS I followed:
1) make ARCH=ppc CROSS_COMPILE=ppc_4xx- chestnut_defconfig # toolchain from
eldk 4.1
2) make ARCH=ppc CROSS_COMPILE=ppc_4xx- V=1
...
make -f scripts/Makefile.build obj=arch/ppc/platforms
ppc_4xx-gcc -m32 -Wp,-MD,arch/ppc/platforms/.chestnut.o.d -nostdinc -isystem /opt/eldk/usr/bin/../lib/gcc/powerpc-linux/4.0.0/include -D__KERNEL__ -Iinclude -include
include/linux/autoconf.h -Iarch/ppc -Iarch/ppc/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -O2 -Iarch/ppc -msoft-float -pipe -ffixed-r2 -mmultiple -mno-altivec -mstring -Wa,-maltivec -fomit-frame-pointer -Wdeclaration-after-statement -Wno-pointer-sign -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(chestnut)" -D"KBUILD_MODNAME=KBUILD_STR(chestnut)" -c -o
arch/ppc/platforms/chestnut.o arch/ppc/platforms/chestnut.c
arch/ppc/platforms/chestnut.c: In function 'chestnut_setup_mtd':
arch/ppc/platforms/chestnut.c:435: error: 'physmap_map' undeclared (first use
in this function)
arch/ppc/platforms/chestnut.c:435: error: (Each undeclared identifier is
reported only once
arch/ppc/platforms/chestnut.c:435: error: for each function it appears in.)
make[1]: *** [arch/ppc/platforms/chestnut.o] Error 1
make: *** [arch/ppc/platforms] Error 2
This PROBLEM should also affect these boards:
find -name '*.[chS]' -exec grep physmap_map {} \; -print
physmap_map.size = CHESTNUT_32BIT_SIZE;
./arch/ppc/platforms/chestnut.c
physmap_map.size = size;
./arch/ppc/platforms/ev64360.c
physmap_map.size = size;
./arch/ppc/platforms/katana.c
I've veryfied 2.6.15, 2.6.19.2 2.6.20.1 2.6.20.6
ONLY 2.6.15 can build successfully. sounds like the problem is caused by the
interface change of mtd.
this brute force patch sould solve the problem:
diff -Nru /tmp/linux-2.6.20.6/arch/ppc/platforms/chestnut.c \
linux-2.6.20.6/arch/ppc/platforms/chestnut.c
--- /tmp/linux-2.6.20.6/arch/ppc/platforms/chestnut.c 2007-04-07
04:02:48.000000000 +0800
+++ linux-2.6.20.6/arch/ppc/platforms/chestnut.c 2007-04-13
17:09:03.000000000 +0800
@@ -432,7 +432,9 @@
ptbl.name = "User FS";
ptbl.size = CHESTNUT_32BIT_SIZE;
- physmap_map.size = CHESTNUT_32BIT_SIZE;
+ // physmap_map.size = CHESTNUT_32BIT_SIZE;
+ physmap_configure(CHESTNUT_32BIT_BASE, CHESTNUT_32BIT_SIZE,
CONFIG_MTD_PHYSMAP_BANKWIDTH, NULL);
+
physmap_set_partitions(&ptbl, 1);
return 0;
}
--
Wang, Baojun Lanzhou University
Distributed & Embedded System Lab http://dslab.lzu.edu.cn
School of Information Science and Engeneering wangbj@lzu.edu.cn
Tianshui South Road 222. Lanzhou 730000 .P.R.China
Tel:+86-931-8912025 Fax:+86-931-8912022
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [RFC] Xilinx SystemACE device driver
From: Stefan Roese @ 2007-04-16 5:28 UTC (permalink / raw)
To: Grant Likely
Cc: Peter Korsgaard, Andrei Konovalov, Rick Moleres,
linuxppc-embedded
In-Reply-To: <1176600194262-git-send-email-grant.likely@secretlab.ca>
Hi Grant,
On Sunday 15 April 2007 03:23, Grant Likely wrote:
> Add support for block device access to the Xilinx SystemACE Compact
> flash interface
>
> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> ---
> I think this driver is in pretty good shape. I've got a few things to
> clean up a bit. Specifically, I'm still working on error handling and
> making sure that the state machine is sane at all times.
I tested the driver on my system (Katmai 440SPe). Both CF's work correctly
regarding reading and writing. No problems so far.
> I would appreciate any review/comments. One area where I am undecided is
> the format of the state machine. The current code uses one big function
> with a large switch() statment for each state. I'm considering breaking
> this up into a seperate function for each state, and adding a static
> state table with pointers to each state function.
I have no real preference here. I don't mind if the code stays in this large
switch statement. It's not that much code.
Two small issues though:
> +config XILINX_SYSACE
> + tristate "Xilinx SystemACE support"
> + depends on XILINX_VIRTEX
> + help
> + Include support for the Xilinx SystemACE CompactFlash interface
Please remove the XILINX_VIRTEX dependency here. It makes it impossible to use
the driver on my 440SPe system.
> +/* register access macros */
> +#if 1 /* Little endian 16-bit regs */
> +#define ace_reg_read8(ace, reg) in_8(ace->baseaddr + reg)
> +#define ace_reg_read16(ace, reg) in_le16(ace->baseaddr + reg)
> +#define ace_reg_readdata(ace, reg) in_be16(ace->baseaddr + reg)
> +#define ace_reg_read32(ace, reg) ((in_le16(ace->baseaddr + reg+2) << 16) |
> \ + (in_le16(ace->baseaddr + reg)))
> +#define ace_reg_write16(ace, reg, val) out_le16(ace->baseaddr + reg, val)
> +#define ace_reg_writedata(ace, reg, val) out_be16(ace->baseaddr + reg,
> val) +#define ace_reg_write32(ace, reg, val) { \
> + out_le16(ace->baseaddr + reg+2, (val) >> 16); \
> + out_le16(ace->baseaddr + reg, val); \
> + }
> +#else /* Big endian 16-bit regs */
> +#define ace_reg_read8(ace, reg) in_8(ace->baseaddr + reg)
> +#define ace_reg_read16(ace, reg) in_be16(ace->baseaddr + reg)
> +#define ace_reg_readdata(ace, reg) in_le16(ace->baseaddr + reg)
> +#define ace_reg_read32(ace, reg) ((in_be16(ace->baseaddr + reg+2) << 16) |
> \ + (in_be16(ace->baseaddr + reg)))
> +#define ace_reg_write16(ace, reg, val) out_be16(ace->baseaddr + reg, val)
> +#define ace_reg_writedata(ace, reg, val) out_le16(ace->baseaddr + reg,
> val) +#define ace_reg_write32(ace, reg, val) { \
> + out_be16(ace->baseaddr + reg+2, (val) >> 16); \
> + out_be16(ace->baseaddr + reg, val); \
> + }
> +#endif
We should make the endianess selectable (I need big endian). You talked about
autodetecting the endianess once, but that would add extra code on every
register access. So I suggest to just add a configuration option for the
endianess selection.
> I feel this driver is pretty close to done, and I'd like to get it into
> mainline for the 2.6.22 timeframe.
Yes, please.
Best regards,
Stefan
^ permalink raw reply
* Re: PROBLEM: kernel 2.6.20.6 build failed for ppc board chestnut(ibm ppc 750GX/FX)
From: gshan @ 2007-04-16 5:28 UTC (permalink / raw)
To: Wang, Baojun; +Cc: linux-kernel, linuxppc-embedded
In-Reply-To: <376700739.05606@lzu.edu.cn>
I'm using eldk4, there are no problems.
Wang, Baojun wrote:
> PROBLEM: linux kernel 2.6.20.6 build failed for ppc board chestnut(ibm ppc
> 750GX/FX)
>
> STEPS I followed:
> 1) make ARCH=ppc CROSS_COMPILE=ppc_4xx- chestnut_defconfig # toolchain from
> eldk 4.1
>
> 2) make ARCH=ppc CROSS_COMPILE=ppc_4xx- V=1
>
> ...
>
> make -f scripts/Makefile.build obj=arch/ppc/platforms
>
> ppc_4xx-gcc -m32 -Wp,-MD,arch/ppc/platforms/.chestnut.o.d -nostdinc -isystem /opt/eldk/usr/bin/../lib/gcc/powerpc-linux/4.0.0/include -D__KERNEL__ -Iinclude -include
> include/linux/autoconf.h -Iarch/ppc -Iarch/ppc/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -O2 -Iarch/ppc -msoft-float -pipe -ffixed-r2 -mmultiple -mno-altivec -mstring -Wa,-maltivec -fomit-frame-pointer -Wdeclaration-after-statement -Wno-pointer-sign -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(chestnut)" -D"KBUILD_MODNAME=KBUILD_STR(chestnut)" -c -o
> arch/ppc/platforms/chestnut.o arch/ppc/platforms/chestnut.c
> arch/ppc/platforms/chestnut.c: In function 'chestnut_setup_mtd':
> arch/ppc/platforms/chestnut.c:435: error: 'physmap_map' undeclared (first use
> in this function)
> arch/ppc/platforms/chestnut.c:435: error: (Each undeclared identifier is
> reported only once
> arch/ppc/platforms/chestnut.c:435: error: for each function it appears in.)
> make[1]: *** [arch/ppc/platforms/chestnut.o] Error 1
> make: *** [arch/ppc/platforms] Error 2
>
>
> This PROBLEM should also affect these boards:
> find -name '*.[chS]' -exec grep physmap_map {} \; -print
> physmap_map.size = CHESTNUT_32BIT_SIZE;
> ./arch/ppc/platforms/chestnut.c
> physmap_map.size = size;
> ./arch/ppc/platforms/ev64360.c
> physmap_map.size = size;
> ./arch/ppc/platforms/katana.c
>
> I've veryfied 2.6.15, 2.6.19.2 2.6.20.1 2.6.20.6
>
> ONLY 2.6.15 can build successfully. sounds like the problem is caused by the
> interface change of mtd.
>
>
> this brute force patch sould solve the problem:
>
> diff -Nru /tmp/linux-2.6.20.6/arch/ppc/platforms/chestnut.c \
> linux-2.6.20.6/arch/ppc/platforms/chestnut.c
>
> --- /tmp/linux-2.6.20.6/arch/ppc/platforms/chestnut.c 2007-04-07
> 04:02:48.000000000 +0800
> +++ linux-2.6.20.6/arch/ppc/platforms/chestnut.c 2007-04-13
> 17:09:03.000000000 +0800
> @@ -432,7 +432,9 @@
> ptbl.name = "User FS";
> ptbl.size = CHESTNUT_32BIT_SIZE;
>
> - physmap_map.size = CHESTNUT_32BIT_SIZE;
> + // physmap_map.size = CHESTNUT_32BIT_SIZE;
> + physmap_configure(CHESTNUT_32BIT_BASE, CHESTNUT_32BIT_SIZE,
> CONFIG_MTD_PHYSMAP_BANKWIDTH, NULL);
> +
> physmap_set_partitions(&ptbl, 1);
> return 0;
> }
>
>
^ permalink raw reply
* Re: [PATCH 4/5] mpc52xx suspend: deep-sleep
From: Grant Likely @ 2007-04-16 5:40 UTC (permalink / raw)
To: Domen Puncer; +Cc: linuxppc-embedded
In-Reply-To: <20070404073755.GE18236@moe.telargo.com>
On 4/4/07, Domen Puncer <domen.puncer@telargo.com> wrote:
> Hi!
>
> How about something like the following.
> Changes:
> - lots of code moved from asm to C
> - add compatible "mpc5200" to lite5200x soc (already is this
> way on efika). And change Efika's soc device_type to "soc".
> - add wakeup supported with RTC (1 to 24*60-1 minutes)
> - each board now configures it's wakeup mode and possibly
> board suspend and resume functions it needs to call (USB on lite)
Sorry it took so long for me to review and get back to you on this
patch. I got wrapped up in other tasks.
I mostly like the approach that you're taking here to allow each board
to select it's own wakeup method, but I think it should be taken a
step farther. Instead of providing a set of stock
mpc52xx_set_wakeup_*() functions, I think it would make for simpler
and more flexible code if each board takes care of its own wakeup
configuration in the board_suspend_prepare hook. In fact, the
mpc52xx_set_wakeup_*() functions themselves make a lot of sense, and
are useful utility functions. But rather than trying to codify which
pins/rtc to configure for wakeup via the .mask, .level, .pin and
.delay items, those functions should be called directly by
lite5200_suspend_prepare() and efika_suspend_prepare(). Doing this
will drop 19 lines of common code in exchange for adding 2 lines to
each board port.
As an added bonus, doing it this way allows multiple pins to be used
for wakeup. :-)
> This code survived > 70k suspend/resume cycles :-)
That's pretty good evidence. :-)
> Comments?
A few more comments below
> --- /dev/null
> +++ grant.git/arch/powerpc/platforms/52xx/mpc52xx_pm.c
<snip>
> +extern void mpc52xx_ds_sram(void);
> +extern const long mpc52xx_ds_sram_size;
> +extern void mpc52xx_ds_cached(void);
> +extern const long mpc52xx_ds_cached_size;
This *looks* like dangerous code (function prototypes not in a shared
header). You should add a big comment here to the fact that these are
assembly functions that are only ever referenced in this file.
===================================================================
> --- grant.git.orig/arch/powerpc/boot/dts/lite5200.dts
> +++ grant.git/arch/powerpc/boot/dts/lite5200.dts
> @@ -49,6 +49,7 @@
>
> soc5200@f0000000 {
> model = "fsl,mpc5200";
> + compatible = "mpc5200";
> revision = "" // from bootloader
> #interrupt-cells = <3>;
> device_type = "soc";
> Index: grant.git/arch/powerpc/boot/dts/lite5200b.dts
> ===================================================================
> --- grant.git.orig/arch/powerpc/boot/dts/lite5200b.dts
> +++ grant.git/arch/powerpc/boot/dts/lite5200b.dts
> @@ -49,6 +49,7 @@
>
> soc5200@f0000000 {
> model = "fsl,mpc5200b";
> + compatible = "mpc5200";
> revision = ""; // from bootloader
> #interrupt-cells = <3>;
> device_type = "soc";
Put these two changes in a seperate patch, and I'll ACK them right away
===================================================================
> --- grant.git.orig/arch/powerpc/kernel/prom_init.c
> +++ grant.git/arch/powerpc/kernel/prom_init.c
> @@ -2142,7 +2142,7 @@ static void __init fixup_device_tree_efi
> 3,12,0, 3,13,0, 3,14,0, 3,15,0 };
> struct subst_entry efika_subst_table[] = {
> { "/", "device_type", prop_cstr("efika") },
> - { "/builtin", "compatible", prop_cstr("soc") },
> + { "/builtin", "device_type", prop_cstr("soc") },
> { "/builtin/ata", "compatible", prop_cstr("mpc5200b-ata\0mpc5200-ata"), },
> { "/builtin/bestcomm", "compatible", prop_cstr("mpc5200b-bestcomm\0mpc5200-bestcomm") },
> { "/builtin/bestcomm", "interrupts", prop_bcomm_irq, sizeof(prop_bcomm_irq) },
>
This should also be a seperate patch.
Cheers,
g.
--
Grant Likely, B.Sc. P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195
^ permalink raw reply
* [PATCH] [0/4] pasemi_mac: fixes and enhancements
From: Olof Johansson @ 2007-04-16 6:16 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
Hi,
The four following patches contain a number of fixes and improvements
of the pasemi_mac driver:
1/4: A couple of minor bugfixes.
2/4: Move the IRQ mapping from the PCI layer under our platform, to
the driver.
3/4: A rather large patch with various NAPI/performance-related fixes
and enhancements.
4/4: phy support
-Olof
^ permalink raw reply
* [PATCH] [1/4] pasemi_mac: minor bugfixes
From: Olof Johansson @ 2007-04-16 6:17 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20070416061654.GB19783@lixom.net>
Ethernet bugfixes:
* Move the was_full/wake_queue logic from tx_intr to clean_tx
* Fix polarity in checks in pasemi_mac_close
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: linux-2.6/drivers/net/pasemi_mac.c
===================================================================
--- linux-2.6.orig/drivers/net/pasemi_mac.c
+++ linux-2.6/drivers/net/pasemi_mac.c
@@ -451,9 +451,12 @@ static int pasemi_mac_clean_tx(struct pa
struct pas_dma_xct_descr *dp;
int start, count;
int flags;
+ int was_full;
spin_lock_irqsave(&mac->tx->lock, flags);
+ was_full = mac->tx->next_to_clean - mac->tx->next_to_use == TX_RING_SIZE;
+
start = mac->tx->next_to_clean;
count = 0;
@@ -478,6 +481,9 @@ static int pasemi_mac_clean_tx(struct pa
mac->tx->next_to_clean += count;
spin_unlock_irqrestore(&mac->tx->lock, flags);
+ if (was_full)
+ netif_wake_queue(mac->netdev);
+
return count;
}
@@ -512,9 +518,6 @@ static irqreturn_t pasemi_mac_tx_intr(in
struct net_device *dev = data;
struct pasemi_mac *mac = netdev_priv(dev);
unsigned int reg;
- int was_full;
-
- was_full = mac->tx->next_to_clean - mac->tx->next_to_use == TX_RING_SIZE;
if (!(*mac->tx_status & PAS_STATUS_INT))
return IRQ_NONE;
@@ -528,9 +531,6 @@ static irqreturn_t pasemi_mac_tx_intr(in
pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_TXCH_RESET(mac->dma_txch),
reg);
- if (was_full)
- netif_wake_queue(dev);
-
return IRQ_HANDLED;
}
@@ -662,40 +665,37 @@ static int pasemi_mac_close(struct net_d
pci_read_config_dword(mac->dma_pdev,
PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch),
&stat);
- if (stat & PAS_DMA_TXCHAN_TCMDSTA_ACT)
+ if (!(stat & PAS_DMA_TXCHAN_TCMDSTA_ACT))
break;
cond_resched();
}
- if (!(stat & PAS_DMA_TXCHAN_TCMDSTA_ACT)) {
+ if (stat & PAS_DMA_TXCHAN_TCMDSTA_ACT)
dev_err(&mac->dma_pdev->dev, "Failed to stop tx channel\n");
- }
for (retries = 0; retries < MAX_RETRIES; retries++) {
pci_read_config_dword(mac->dma_pdev,
PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch),
&stat);
- if (stat & PAS_DMA_RXCHAN_CCMDSTA_ACT)
+ if (!(stat & PAS_DMA_RXCHAN_CCMDSTA_ACT))
break;
cond_resched();
}
- if (!(stat & PAS_DMA_RXCHAN_CCMDSTA_ACT)) {
+ if (stat & PAS_DMA_RXCHAN_CCMDSTA_ACT)
dev_err(&mac->dma_pdev->dev, "Failed to stop rx channel\n");
- }
for (retries = 0; retries < MAX_RETRIES; retries++) {
pci_read_config_dword(mac->dma_pdev,
PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
&stat);
- if (stat & PAS_DMA_RXINT_RCMDSTA_ACT)
+ if (!(stat & PAS_DMA_RXINT_RCMDSTA_ACT))
break;
cond_resched();
}
- if (!(stat & PAS_DMA_RXINT_RCMDSTA_ACT)) {
+ if (stat & PAS_DMA_RXINT_RCMDSTA_ACT)
dev_err(&mac->dma_pdev->dev, "Failed to stop rx interface\n");
- }
/* Then, disable the channel. This must be done separately from
* stopping, since you can't disable when active.
^ permalink raw reply
* Re: linux 2.6 on xilinx ml403
From: Grant Likely @ 2007-04-16 5:59 UTC (permalink / raw)
To: Miroslaw Dach; +Cc: linuxppc-dev
In-Reply-To: <Pine.LNX.4.44.0704101337030.26940-100000@slslc02.psi.ch>
On 4/10/07, Miroslaw Dach <miroslaw.dach@psi.ch> wrote:
> Hi All,
>
> I am new in the linux powerpc linux. I have the Avnet evaluation
> board which contains xilinx ml403 (Virtex-4 FX family). The challenge I
> have is to build linux (most preferable 2.6) with suitable drivers.
>
> On the net I have found much information how to build linuxppc 2.4 for
> xilinx ml300/ml301. I did not found however any good reference which
> refers to kernel 2.6 and suitable patches for powerpc 405 which is
> included in the ml403.
>
> I would appreciate very much if someone could provide me with some good
> reference links referring kernel 2.6 for PPC 405 on xilinx ml403.
> I have found the place to download the linuxppc_2_4_devel on BitKeper page
> but there is no equivalent like linuxppc_2_6_devel.
The mainline tree has ml403 support, but it's not complete. I just
posted a set of patches that clean up a bunch of stuff and add some
support. Also, if you look through the mailing list archive, you can
find a copy of the adapter.c file needed to make the Xilinx TEMAC
driver work with Linux.
I'm also planing to publish my git tree tomorrow where I've integrated
all the patches I need to get Linux in a useful state for the ml403.
The git tree will show up on http://git.secretlab.ca. You might find
it easier to grab my tree and use that as your starting point.
Cheers,
g.
--
Grant Likely, B.Sc. P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195
^ permalink raw reply
* [PATCH] [2/4] pasemi_mac: irq mapping changes
From: Olof Johansson @ 2007-04-16 6:18 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20070416061654.GB19783@lixom.net>
Fixes for ethernet IRQ mapping, to move it to the driver instead of in
the platform setup code.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: powerpc/arch/powerpc/platforms/pasemi/pci.c
===================================================================
--- powerpc.orig/arch/powerpc/platforms/pasemi/pci.c
+++ powerpc/arch/powerpc/platforms/pasemi/pci.c
@@ -163,19 +163,6 @@ static void __init pas_fixup_phb_resourc
}
-void __devinit pas_pci_irq_fixup(struct pci_dev *dev)
-{
- /* DMA is special, 84 interrupts (128 -> 211), all but 128
- * need to be mapped by hand here.
- */
- if (dev->vendor == 0x1959 && dev->device == 0xa007) {
- int i;
- for (i = 129; i < 212; i++)
- irq_create_mapping(NULL, i);
- }
-}
-
-
void __init pas_pci_init(void)
{
struct device_node *np, *root;
Index: powerpc/arch/powerpc/platforms/pasemi/setup.c
===================================================================
--- powerpc.orig/arch/powerpc/platforms/pasemi/setup.c
+++ powerpc/arch/powerpc/platforms/pasemi/setup.c
@@ -240,5 +240,4 @@ define_machine(pas) {
.check_legacy_ioport = pas_check_legacy_ioport,
.progress = pas_progress,
.machine_check_exception = pas_machine_check_handler,
- .pci_irq_fixup = pas_pci_irq_fixup,
};
Index: powerpc/drivers/net/pasemi_mac.c
===================================================================
--- powerpc.orig/drivers/net/pasemi_mac.c
+++ powerpc/drivers/net/pasemi_mac.c
@@ -537,6 +537,9 @@ static irqreturn_t pasemi_mac_tx_intr(in
static int pasemi_mac_open(struct net_device *dev)
{
struct pasemi_mac *mac = netdev_priv(dev);
+ struct device_node *dma_dn = pci_device_to_OF_node(mac->dma_pdev);
+ const unsigned int *prop;
+ int base_irq;
unsigned int flags;
int ret;
@@ -600,8 +603,24 @@ static int pasemi_mac_open(struct net_de
netif_start_queue(dev);
netif_poll_enable(dev);
- ret = request_irq(mac->dma_pdev->irq + mac->dma_txch,
- &pasemi_mac_tx_intr, IRQF_DISABLED,
+ /* Interrupts are a bit different for our DMA controller: While
+ * it's got one a regular PCI device header, the interrupt there
+ * is really the base of the range it's using. Each tx and rx
+ * channel has it's own interrupt source.
+ *
+ * The only way to get to the actual hardware interrupt is by
+ * getting it from the device tree, since the kernel has done
+ * virtual remapping of the sources by the time we can get them
+ * from the PCI device.
+ */
+
+ prop = of_get_property(dma_dn, "interrupts", NULL);
+ base_irq = *prop;
+
+ mac->tx_irq = irq_create_mapping(NULL, base_irq + mac->dma_txch);
+ mac->rx_irq = irq_create_mapping(NULL, base_irq + 20 + mac->dma_txch);
+
+ ret = request_irq(mac->tx_irq, &pasemi_mac_tx_intr, IRQF_DISABLED,
mac->tx->irq_name, dev);
if (ret) {
dev_err(&mac->pdev->dev, "request_irq of irq %d failed: %d\n",
@@ -609,8 +628,7 @@ static int pasemi_mac_open(struct net_de
goto out_tx_int;
}
- ret = request_irq(mac->dma_pdev->irq + 20 + mac->dma_rxch,
- &pasemi_mac_rx_intr, IRQF_DISABLED,
+ ret = request_irq(mac->rx_irq, &pasemi_mac_rx_intr, IRQF_DISABLED,
mac->rx->irq_name, dev);
if (ret) {
dev_err(&mac->pdev->dev, "request_irq of irq %d failed: %d\n",
@@ -621,7 +639,7 @@ static int pasemi_mac_open(struct net_de
return 0;
out_rx_int:
- free_irq(mac->dma_pdev->irq + mac->dma_txch, dev);
+ free_irq(mac->tx_irq, dev);
out_tx_int:
netif_poll_disable(dev);
netif_stop_queue(dev);
@@ -705,8 +723,8 @@ static int pasemi_mac_close(struct net_d
pci_write_config_dword(mac->dma_pdev,
PAS_DMA_RXINT_RCMDSTA(mac->dma_if), 0);
- free_irq(mac->dma_pdev->irq + mac->dma_txch, dev);
- free_irq(mac->dma_pdev->irq + 20 + mac->dma_rxch, dev);
+ free_irq(mac->tx_irq, dev);
+ free_irq(mac->rx_irq, dev);
/* Free resources */
pasemi_mac_free_rx_resources(dev);
Index: powerpc/drivers/net/pasemi_mac.h
===================================================================
--- powerpc.orig/drivers/net/pasemi_mac.h
+++ powerpc/drivers/net/pasemi_mac.h
@@ -73,6 +73,8 @@ struct pasemi_mac {
struct pasemi_mac_txring *tx;
struct pasemi_mac_rxring *rx;
+ unsigned long tx_irq;
+ unsigned long rx_irq;
};
/* Software status descriptor (desc_info) */
^ permalink raw reply
* [PATCH] [3/4] pasemi_mac: cleanups and rx performance improvements
From: Olof Johansson @ 2007-04-16 6:19 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20070416061654.GB19783@lixom.net>
NAPI fixes and cleanups for pasemi_mac:
* Timer changes/fixes
* Abstract out the rx intr restart to a separate function
* Similar function for tx intr to reset to a known clear state even if
firmware used the same interface
* Add a copy-break and recycle the SKB in the driver for small
packets
* Other cleanups to rx path
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: powerpc/drivers/net/pasemi_mac.c
===================================================================
--- powerpc.orig/drivers/net/pasemi_mac.c
+++ powerpc/drivers/net/pasemi_mac.c
@@ -59,12 +59,6 @@
#define BUF_SIZE 1646 /* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
-/* XXXOJN these should come out of the device tree some day */
-#define PAS_DMA_CAP_BASE 0xe00d0040
-#define PAS_DMA_CAP_SIZE 0x100
-#define PAS_DMA_COM_BASE 0xe00d0100
-#define PAS_DMA_COM_SIZE 0x100
-
static struct pasdma_status *dma_status;
static int pasemi_get_mac_addr(struct pasemi_mac *mac)
@@ -277,8 +271,8 @@ static void pasemi_mac_free_rx_resources
for (i = 0; i < RX_RING_SIZE; i++) {
info = &RX_DESC_INFO(mac, i);
dp = &RX_DESC(mac, i);
- if (info->dma) {
- if (info->skb) {
+ if (info->skb) {
+ if (info->dma) {
pci_unmap_single(mac->dma_pdev,
info->dma,
info->skb->len,
@@ -309,84 +303,122 @@ static void pasemi_mac_replenish_rx_ring
struct pasemi_mac *mac = netdev_priv(dev);
unsigned int i;
int start = mac->rx->next_to_fill;
- unsigned int count;
+ unsigned int limit, count;
- count = (mac->rx->next_to_clean + RX_RING_SIZE -
+ limit = (mac->rx->next_to_clean + RX_RING_SIZE -
mac->rx->next_to_fill) & (RX_RING_SIZE - 1);
/* Check to see if we're doing first-time setup */
if (unlikely(mac->rx->next_to_clean == 0 && mac->rx->next_to_fill == 0))
- count = RX_RING_SIZE;
+ limit = RX_RING_SIZE;
- if (count <= 0)
+ if (limit <= 0)
return;
- for (i = start; i < start + count; i++) {
+ i = start;
+
+ for (count = limit; count; count--) {
struct pasemi_mac_buffer *info = &RX_DESC_INFO(mac, i);
u64 *buff = &RX_BUFF(mac, i);
struct sk_buff *skb;
dma_addr_t dma;
- skb = dev_alloc_skb(BUF_SIZE);
+ /* skb might still be in there for recycle on short receives */
+ if (info->skb)
+ skb = info->skb;
+ else
+ skb = dev_alloc_skb(BUF_SIZE);
- if (!skb) {
- count = i - start;
+ if (unlikely(!skb))
break;
- }
skb->dev = dev;
dma = pci_map_single(mac->dma_pdev, skb->data, skb->len,
PCI_DMA_FROMDEVICE);
- if (dma_mapping_error(dma)) {
+ if (unlikely(dma_mapping_error(dma))) {
dev_kfree_skb_irq(info->skb);
- count = i - start;
break;
}
info->skb = skb;
info->dma = dma;
*buff = XCT_RXB_LEN(BUF_SIZE) | XCT_RXB_ADDR(dma);
+ i++;
}
wmb();
pci_write_config_dword(mac->dma_pdev,
PAS_DMA_RXCHAN_INCR(mac->dma_rxch),
- count);
+ limit - count);
pci_write_config_dword(mac->dma_pdev,
PAS_DMA_RXINT_INCR(mac->dma_if),
- count);
+ limit - count);
+
+ mac->rx->next_to_fill += limit - count;
+}
+
+static void pasemi_mac_restart_rx_intr(struct pasemi_mac *mac)
+{
+ unsigned int reg, stat;
+ /* Re-enable packet count interrupts: finally
+ * ack the packet count interrupt we got in rx_intr.
+ */
+
+ pci_read_config_dword(mac->iob_pdev,
+ PAS_IOB_DMA_RXCH_STAT(mac->dma_rxch),
+ &stat);
+
+ reg = PAS_IOB_DMA_RXCH_RESET_PCNT(stat & PAS_IOB_DMA_RXCH_STAT_CNTDEL_M) |
+ PAS_IOB_DMA_RXCH_RESET_PINTC;
+
+ pci_write_config_dword(mac->iob_pdev,
+ PAS_IOB_DMA_RXCH_RESET(mac->dma_rxch),
+ reg);
+}
+
+static void pasemi_mac_restart_tx_intr(struct pasemi_mac *mac)
+{
+ unsigned int reg, stat;
- mac->rx->next_to_fill += count;
+ /* Re-enable packet count interrupts */
+ pci_read_config_dword(mac->iob_pdev,
+ PAS_IOB_DMA_TXCH_STAT(mac->dma_txch), &stat);
+
+ reg = PAS_IOB_DMA_TXCH_RESET_PCNT(stat & PAS_IOB_DMA_TXCH_STAT_CNTDEL_M) |
+ PAS_IOB_DMA_TXCH_RESET_PINTC;
+
+ pci_write_config_dword(mac->iob_pdev,
+ PAS_IOB_DMA_TXCH_RESET(mac->dma_txch), reg);
}
+
static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
{
- unsigned int i;
- int start, count;
+ unsigned int n;
+ int count;
+ struct pas_dma_xct_descr *dp;
+ struct pasemi_mac_buffer *info;
+ struct sk_buff *skb;
+ unsigned int i, len;
+ u64 macrx;
+ dma_addr_t dma;
spin_lock(&mac->rx->lock);
- start = mac->rx->next_to_clean;
- count = 0;
-
- for (i = start; i < (start + RX_RING_SIZE) && count < limit; i++) {
- struct pas_dma_xct_descr *dp;
- struct pasemi_mac_buffer *info;
- struct sk_buff *skb;
- unsigned int j, len;
- dma_addr_t dma;
+ n = mac->rx->next_to_clean;
+ for (count = limit; count; count--) {
rmb();
- dp = &RX_DESC(mac, i);
+ dp = &RX_DESC(mac, n);
- if (!(dp->macrx & XCT_MACRX_O))
- break;
+ macrx = dp->macrx;
- count++;
+ if (!(macrx & XCT_MACRX_O))
+ break;
info = NULL;
@@ -398,29 +430,42 @@ static int pasemi_mac_clean_rx(struct pa
*/
dma = (dp->ptr & XCT_PTR_ADDR_M);
- for (j = start; j < (start + RX_RING_SIZE); j++) {
- info = &RX_DESC_INFO(mac, j);
+ for (i = n; i < (n + RX_RING_SIZE); i++) {
+ info = &RX_DESC_INFO(mac, i);
if (info->dma == dma)
break;
}
- BUG_ON(!info);
- BUG_ON(info->dma != dma);
+ skb = info->skb;
+ info->dma = 0;
- pci_unmap_single(mac->dma_pdev, info->dma, info->skb->len,
+ pci_unmap_single(mac->dma_pdev, dma, skb->len,
PCI_DMA_FROMDEVICE);
- skb = info->skb;
+ len = (macrx & XCT_MACRX_LLEN_M) >> XCT_MACRX_LLEN_S;
- len = (dp->macrx & XCT_MACRX_LLEN_M) >> XCT_MACRX_LLEN_S;
+ if (len < 256) {
+ struct sk_buff *new_skb =
+ netdev_alloc_skb(mac->netdev, len + NET_IP_ALIGN);
+ if (new_skb) {
+ skb_reserve(new_skb, NET_IP_ALIGN);
+ memcpy(new_skb->data - NET_IP_ALIGN,
+ skb->data - NET_IP_ALIGN,
+ len + NET_IP_ALIGN);
+ /* save the skb in buffer_info as good */
+ skb = new_skb;
+ }
+ /* else just continue with the old one */
+ } else
+ info->skb = NULL;
skb_put(skb, len);
skb->protocol = eth_type_trans(skb, mac->netdev);
- if ((dp->macrx & XCT_MACRX_HTY_M) == XCT_MACRX_HTY_IPV4_OK) {
+ if ((macrx & XCT_MACRX_HTY_M) == XCT_MACRX_HTY_IPV4_OK) {
skb->ip_summed = CHECKSUM_COMPLETE;
- skb->csum = (dp->macrx & XCT_MACRX_CSUM_M) >>
+ skb->csum = (macrx & XCT_MACRX_CSUM_M) >>
XCT_MACRX_CSUM_S;
} else
skb->ip_summed = CHECKSUM_NONE;
@@ -430,13 +475,13 @@ static int pasemi_mac_clean_rx(struct pa
netif_receive_skb(skb);
- info->dma = 0;
- info->skb = NULL;
dp->ptr = 0;
dp->macrx = 0;
+
+ n++;
}
- mac->rx->next_to_clean += count;
+ mac->rx->next_to_clean += limit - count;
pasemi_mac_replenish_rx_ring(mac->netdev);
spin_unlock(&mac->rx->lock);
@@ -494,18 +539,28 @@ static irqreturn_t pasemi_mac_rx_intr(in
struct pasemi_mac *mac = netdev_priv(dev);
unsigned int reg;
- if (!(*mac->rx_status & PAS_STATUS_INT))
+ if (!(*mac->rx_status & PAS_STATUS_CAUSE_M))
return IRQ_NONE;
- netif_rx_schedule(dev);
- pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_COM_TIMEOUTCFG,
- PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0));
+ if (*mac->rx_status & PAS_STATUS_ERROR)
+ printk("rx_status reported error\n");
- reg = PAS_IOB_DMA_RXCH_RESET_PINTC | PAS_IOB_DMA_RXCH_RESET_SINTC |
- PAS_IOB_DMA_RXCH_RESET_DINTC;
+ /* Don't reset packet count so it won't fire again but clear
+ * all others.
+ */
+
+ pci_read_config_dword(mac->dma_pdev, PAS_DMA_RXINT_RCMDSTA(mac->dma_if), ®);
+
+ reg = 0;
+ if (*mac->rx_status & PAS_STATUS_SOFT)
+ reg |= PAS_IOB_DMA_RXCH_RESET_SINTC;
+ if (*mac->rx_status & PAS_STATUS_ERROR)
+ reg |= PAS_IOB_DMA_RXCH_RESET_DINTC;
if (*mac->rx_status & PAS_STATUS_TIMER)
reg |= PAS_IOB_DMA_RXCH_RESET_TINTC;
+ netif_rx_schedule(dev);
+
pci_write_config_dword(mac->iob_pdev,
PAS_IOB_DMA_RXCH_RESET(mac->dma_rxch), reg);
@@ -519,14 +574,17 @@ static irqreturn_t pasemi_mac_tx_intr(in
struct pasemi_mac *mac = netdev_priv(dev);
unsigned int reg;
- if (!(*mac->tx_status & PAS_STATUS_INT))
+ if (!(*mac->tx_status & PAS_STATUS_CAUSE_M))
return IRQ_NONE;
pasemi_mac_clean_tx(mac);
- reg = PAS_IOB_DMA_TXCH_RESET_PINTC | PAS_IOB_DMA_TXCH_RESET_SINTC;
- if (*mac->tx_status & PAS_STATUS_TIMER)
- reg |= PAS_IOB_DMA_TXCH_RESET_TINTC;
+ reg = PAS_IOB_DMA_TXCH_RESET_PINTC;
+
+ if (*mac->tx_status & PAS_STATUS_SOFT)
+ reg |= PAS_IOB_DMA_TXCH_RESET_SINTC;
+ if (*mac->tx_status & PAS_STATUS_ERROR)
+ reg |= PAS_IOB_DMA_TXCH_RESET_DINTC;
pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_TXCH_RESET(mac->dma_txch),
reg);
@@ -563,10 +621,18 @@ static int pasemi_mac_open(struct net_de
flags |= PAS_MAC_CFG_PCFG_TSR_1G | PAS_MAC_CFG_PCFG_SPD_1G;
pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_RXCH_CFG(mac->dma_rxch),
- PAS_IOB_DMA_RXCH_CFG_CNTTH(30));
+ PAS_IOB_DMA_RXCH_CFG_CNTTH(1));
+
+ pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_TXCH_CFG(mac->dma_txch),
+ PAS_IOB_DMA_TXCH_CFG_CNTTH(32));
+ /* Clear out any residual packet count state from firmware */
+ pasemi_mac_restart_rx_intr(mac);
+ pasemi_mac_restart_tx_intr(mac);
+
+ /* 0xffffff is max value, about 16ms */
pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_COM_TIMEOUTCFG,
- PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(1000000));
+ PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0xffffff));
pci_write_config_dword(mac->pdev, PAS_MAC_CFG_PCFG, flags);
@@ -585,7 +651,7 @@ static int pasemi_mac_open(struct net_de
/* enable rx if */
pci_write_config_dword(mac->dma_pdev,
PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
- PAS_DMA_RXINT_RCMDSTA_EN);
+ PAS_DMA_RXINT_RCMDSTA_EN|PAS_DMA_RXINT_RCMDSTA_MBT);
/* enable rx channel */
pci_write_config_dword(mac->dma_pdev,
@@ -838,18 +904,18 @@ static int pasemi_mac_poll(struct net_de
pkts = pasemi_mac_clean_rx(mac, limit);
+ dev->quota -= pkts;
+ *budget -= pkts;
+
if (pkts < limit) {
/* all done, no more packets present */
netif_rx_complete(dev);
- /* re-enable receive interrupts */
- pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_COM_TIMEOUTCFG,
- PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(1000000));
+ pasemi_mac_restart_rx_intr(mac);
+
return 0;
} else {
/* used up our quantum, so reschedule */
- dev->quota -= pkts;
- *budget -= pkts;
return 1;
}
}
Index: powerpc/drivers/net/pasemi_mac.h
===================================================================
--- powerpc.orig/drivers/net/pasemi_mac.h
+++ powerpc/drivers/net/pasemi_mac.h
@@ -195,11 +195,15 @@ enum {
#define PAS_DMA_RXINT_RCMDSTA(i) (0x200+(i)*_PAS_DMA_RXINT_STRIDE)
#define PAS_DMA_RXINT_RCMDSTA_EN 0x00000001
#define PAS_DMA_RXINT_RCMDSTA_ST 0x00000002
-#define PAS_DMA_RXINT_RCMDSTA_OO 0x00000100
-#define PAS_DMA_RXINT_RCMDSTA_BP 0x00000200
-#define PAS_DMA_RXINT_RCMDSTA_DR 0x00000400
+#define PAS_DMA_RXINT_RCMDSTA_MBT 0x00000008
+#define PAS_DMA_RXINT_RCMDSTA_MDR 0x00000010
+#define PAS_DMA_RXINT_RCMDSTA_MOO 0x00000020
+#define PAS_DMA_RXINT_RCMDSTA_MBP 0x00000040
#define PAS_DMA_RXINT_RCMDSTA_BT 0x00000800
-#define PAS_DMA_RXINT_RCMDSTA_TB 0x00001000
+#define PAS_DMA_RXINT_RCMDSTA_DR 0x00001000
+#define PAS_DMA_RXINT_RCMDSTA_OO 0x00002000
+#define PAS_DMA_RXINT_RCMDSTA_BP 0x00004000
+#define PAS_DMA_RXINT_RCMDSTA_TB 0x00008000
#define PAS_DMA_RXINT_RCMDSTA_ACT 0x00010000
#define PAS_DMA_RXINT_RCMDSTA_DROPS_M 0xfffe0000
#define PAS_DMA_RXINT_RCMDSTA_DROPS_S 17
@@ -299,6 +303,7 @@ enum {
#define PAS_STATUS_DCNT_S 16
#define PAS_STATUS_BPCNT_M 0x0000ffff00000000ull
#define PAS_STATUS_BPCNT_S 32
+#define PAS_STATUS_CAUSE_M 0xf000000000000000ull
#define PAS_STATUS_TIMER 0x1000000000000000ull
#define PAS_STATUS_ERROR 0x2000000000000000ull
#define PAS_STATUS_SOFT 0x4000000000000000ull
^ permalink raw reply
* [PATCH] [4/4] pasemi_mac: phy support
From: Olof Johansson @ 2007-04-16 6:20 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20070416061654.GB19783@lixom.net>
PHY support for pasemi_mac. Also add msg_enable flags for future
disablement of the link messages.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: powerpc/drivers/net/pasemi_mac.c
===================================================================
--- powerpc.orig/drivers/net/pasemi_mac.c
+++ powerpc/drivers/net/pasemi_mac.c
@@ -40,13 +40,11 @@
*
* - Get rid of pci_{read,write}_config(), map registers with ioremap
* for performance
- * - PHY support
* - Multicast support
* - Large MTU support
* - Other performance improvements
*/
-
/* Must be a power of two */
#define RX_RING_SIZE 512
#define TX_RING_SIZE 512
@@ -592,6 +590,110 @@ static irqreturn_t pasemi_mac_tx_intr(in
return IRQ_HANDLED;
}
+static void pasemi_adjust_link(struct net_device *dev)
+{
+ struct pasemi_mac *mac = netdev_priv(dev);
+ int msg;
+ unsigned int flags;
+ unsigned int new_flags;
+
+ if (!mac->phydev->link) {
+ /* If no link, MAC speed settings don't matter. Just report
+ * link down and return.
+ */
+ if (mac->link && netif_msg_link(mac))
+ printk(KERN_INFO "%s: Link is down.\n", dev->name);
+
+ netif_carrier_off(dev);
+ mac->link = 0;
+
+ return;
+ } else
+ netif_carrier_on(dev);
+
+ pci_read_config_dword(mac->pdev, PAS_MAC_CFG_PCFG, &flags);
+ new_flags = flags & ~(PAS_MAC_CFG_PCFG_HD | PAS_MAC_CFG_PCFG_SPD_M);
+
+ if (!mac->phydev->duplex)
+ new_flags |= PAS_MAC_CFG_PCFG_HD;
+
+ switch (mac->phydev->speed) {
+ case 1000:
+ new_flags |= PAS_MAC_CFG_PCFG_SPD_1G;
+ break;
+ case 100:
+ new_flags |= PAS_MAC_CFG_PCFG_SPD_100M;
+ break;
+ case 10:
+ new_flags |= PAS_MAC_CFG_PCFG_SPD_10M;
+ break;
+ default:
+ printk("Unsupported speed %d\n", mac->phydev->speed);
+ }
+
+ /* Print on link or speed/duplex change */
+ msg = mac->link != mac->phydev->link || flags != new_flags;
+
+ mac->duplex = mac->phydev->duplex;
+ mac->speed = mac->phydev->speed;
+ mac->link = mac->phydev->link;
+
+ if (new_flags != flags)
+ pci_write_config_dword(mac->pdev, PAS_MAC_CFG_PCFG, new_flags);
+
+ if (msg && netif_msg_link(mac))
+ printk(KERN_INFO "%s: Link is up at %d Mbps, %s duplex.\n",
+ dev->name, mac->speed, mac->duplex ? "full" : "half");
+}
+
+static int pasemi_mac_phy_init(struct net_device *dev)
+{
+ struct pasemi_mac *mac = netdev_priv(dev);
+ struct device_node *dn, *phy_dn;
+ struct phy_device *phydev;
+ unsigned int phy_id;
+ const phandle *ph;
+ const unsigned int *prop;
+ struct resource r;
+ int ret;
+
+ dn = pci_device_to_OF_node(mac->pdev);
+ ph = get_property(dn, "phy-handle", NULL);
+ if (!ph)
+ return -ENODEV;
+ phy_dn = of_find_node_by_phandle(*ph);
+
+ prop = get_property(phy_dn, "reg", NULL);
+ ret = of_address_to_resource(phy_dn->parent, 0, &r);
+ if (ret)
+ goto err;
+
+ phy_id = *prop;
+ snprintf(mac->phy_id, BUS_ID_SIZE, PHY_ID_FMT, (int)r.start, phy_id);
+
+ of_node_put(phy_dn);
+
+ mac->link = 0;
+ mac->speed = 0;
+ mac->duplex = -1;
+
+ phydev = phy_connect(dev, mac->phy_id, &pasemi_adjust_link, 0, PHY_INTERFACE_MODE_SGMII);
+
+ if (IS_ERR(phydev)) {
+ printk(KERN_ERR "%s: Could not attach to phy\n", dev->name);
+ return PTR_ERR(phydev);
+ }
+
+ mac->phydev = phydev;
+
+ return 0;
+
+err:
+ of_node_put(phy_dn);
+ return -ENODEV;
+}
+
+
static int pasemi_mac_open(struct net_device *dev)
{
struct pasemi_mac *mac = netdev_priv(dev);
@@ -666,6 +768,13 @@ static int pasemi_mac_open(struct net_de
pasemi_mac_replenish_rx_ring(dev);
+ ret = pasemi_mac_phy_init(dev);
+ /* Some configs don't have PHYs (XAUI etc), so don't complain about
+ * failed init due to -ENODEV.
+ */
+ if (ret && ret != -ENODEV)
+ dev_warn(&mac->pdev->dev, "phy init failed: %d\n", ret);
+
netif_start_queue(dev);
netif_poll_enable(dev);
@@ -699,6 +808,9 @@ static int pasemi_mac_open(struct net_de
goto out_rx_int;
}
+ if (mac->phydev)
+ phy_start(mac->phydev);
+
return 0;
out_rx_int:
@@ -722,6 +834,11 @@ static int pasemi_mac_close(struct net_d
unsigned int stat;
int retries;
+ if (mac->phydev) {
+ phy_stop(mac->phydev);
+ phy_disconnect(mac->phydev);
+ }
+
netif_stop_queue(dev);
/* Clean out any pending buffers */
@@ -1015,6 +1132,9 @@ pasemi_mac_probe(struct pci_dev *pdev, c
mac->rx_status = &dma_status->rx_sta[mac->dma_rxch];
mac->tx_status = &dma_status->tx_sta[mac->dma_txch];
+ /* Enable most messages by default */
+ mac->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1;
+
err = register_netdev(dev);
if (err) {
Index: powerpc/drivers/net/pasemi_mac.h
===================================================================
--- powerpc.orig/drivers/net/pasemi_mac.h
+++ powerpc/drivers/net/pasemi_mac.h
@@ -24,6 +24,7 @@
#include <linux/ethtool.h>
#include <linux/netdevice.h>
#include <linux/spinlock.h>
+#include <linux/phy.h>
struct pasemi_mac_txring {
spinlock_t lock;
@@ -54,6 +55,7 @@ struct pasemi_mac {
struct pci_dev *pdev;
struct pci_dev *dma_pdev;
struct pci_dev *iob_pdev;
+ struct phy_device *phydev;
struct net_device_stats stats;
/* Pointer to the cacheable per-channel status registers */
@@ -75,6 +77,12 @@ struct pasemi_mac {
struct pasemi_mac_rxring *rx;
unsigned long tx_irq;
unsigned long rx_irq;
+ int link;
+ int speed;
+ int duplex;
+
+ unsigned int msg_enable;
+ char phy_id[BUS_ID_SIZE];
};
/* Software status descriptor (desc_info) */
Index: powerpc/drivers/net/Kconfig
===================================================================
--- powerpc.orig/drivers/net/Kconfig
+++ powerpc/drivers/net/Kconfig
@@ -2490,6 +2490,7 @@ config NETXEN_NIC
config PASEMI_MAC
tristate "PA Semi 1/10Gbit MAC"
depends on PPC64 && PCI
+ select PHYLIB
help
This driver supports the on-chip 1/10Gbit Ethernet controller on
PA Semi's PWRficient line of chips.
^ permalink raw reply
* [PATCH] powerpc: save trap number in bad_stack
From: Olof Johansson @ 2007-04-16 6:23 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev, anton
Save the trap number in the case of getting a bad stack in an exception
handler. It is sometimes useful to know what exception it was that caused
this to happen. Without this, no trap is reported.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: linux-2.6/arch/powerpc/kernel/asm-offsets.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/asm-offsets.c
+++ linux-2.6/arch/powerpc/kernel/asm-offsets.c
@@ -139,6 +139,7 @@ int main(void)
DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time));
DEFINE(PACA_SLBSHADOWPTR, offsetof(struct paca_struct, slb_shadow_ptr));
DEFINE(PACA_DATA_OFFSET, offsetof(struct paca_struct, data_offset));
+ DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save));
DEFINE(SLBSHADOW_STACKVSID,
offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].vsid));
Index: linux-2.6/include/asm-powerpc/paca.h
===================================================================
--- linux-2.6.orig/include/asm-powerpc/paca.h
+++ linux-2.6/include/asm-powerpc/paca.h
@@ -81,6 +81,8 @@ struct paca_struct {
u64 exslb[10]; /* used for SLB/segment table misses
* on the linear mapping */
+ u64 trap_save; /* Used when bad stack is encountered */
+
mm_context_t context;
u16 vmalloc_sllp;
u16 slb_cache[SLB_CACHE_ENTRIES];
Index: linux-2.6/arch/powerpc/kernel/head_64.S
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/head_64.S
+++ linux-2.6/arch/powerpc/kernel/head_64.S
@@ -278,8 +278,12 @@ exception_marker:
beq- 1f; \
ld r1,PACAKSAVE(r13); /* kernel stack to use */ \
1: cmpdi cr1,r1,0; /* check if r1 is in userspace */ \
- bge- cr1,bad_stack; /* abort if it is */ \
- std r9,_CCR(r1); /* save CR in stackframe */ \
+ bge- cr1,2f; /* abort if it is */ \
+ b 3f; \
+2: li r1,(n); /* will be reloaded later */ \
+ std r1,PACA_TRAP_SAVE(r13); \
+ b bad_stack; \
+3: std r9,_CCR(r1); /* save CR in stackframe */ \
std r11,_NIP(r1); /* save SRR0 in stackframe */ \
std r12,_MSR(r1); /* save SRR1 in stackframe */ \
std r10,0(r1); /* make stack chain pointer */ \
@@ -940,6 +944,8 @@ bad_stack:
SAVE_2GPRS(7,r1)
SAVE_10GPRS(12,r1)
SAVE_10GPRS(22,r1)
+ ld r12,PACA_TRAP_SAVE(r13)
+ std r12,_TRAP(r1)
addi r11,r1,INT_FRAME_SIZE
std r11,0(r1)
li r12,0
^ permalink raw reply
* [PATCH] [1/5] pasemi: allow 8KB config space for I/O bridge
From: Olof Johansson @ 2007-04-16 6:26 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
Device 0 function 0 on the root bus is really a two-function bus agent,
but only the first function is visible. Because of this, we need to
allow config accesses into the second range. Modify the check for valid
offsets accordingly.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: linux-2.6/arch/powerpc/platforms/pasemi/pci.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/pasemi/pci.c
+++ linux-2.6/arch/powerpc/platforms/pasemi/pci.c
@@ -33,7 +33,17 @@
#define PA_PXP_CFA(bus, devfn, off) (((bus) << 20) | ((devfn) << 12) | (off))
-#define CONFIG_OFFSET_VALID(off) ((off) < 4096)
+static inline int pa_pxp_offset_valid(u8 bus, u8 devfn, int offset)
+{
+ /* Device 0 Function 0 is special: It's config space spans function 1 as
+ * well, so allow larger offset. It's really a two-function device but the
+ * second function does not probe.
+ */
+ if (bus == 0 && devfn == 0)
+ return offset < 8192;
+ else
+ return offset < 4096;
+}
static void volatile __iomem *pa_pxp_cfg_addr(struct pci_controller *hose,
u8 bus, u8 devfn, int offset)
@@ -51,7 +61,7 @@ static int pa_pxp_read_config(struct pci
if (!hose)
return PCIBIOS_DEVICE_NOT_FOUND;
- if (!CONFIG_OFFSET_VALID(offset))
+ if (!pa_pxp_offset_valid(bus->number, devfn, offset))
return PCIBIOS_BAD_REGISTER_NUMBER;
addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset);
@@ -85,7 +95,7 @@ static int pa_pxp_write_config(struct pc
if (!hose)
return PCIBIOS_DEVICE_NOT_FOUND;
- if (!CONFIG_OFFSET_VALID(offset))
+ if (!pa_pxp_offset_valid(bus->number, devfn, offset))
return PCIBIOS_BAD_REGISTER_NUMBER;
addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset);
^ permalink raw reply
* [PATCH] [2/5] pasemi: enable one more hid bit
From: Olof Johansson @ 2007-04-16 6:27 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20070416062634.GB20196@lixom.net>
Minor HID change. Firmware can't know that we want this set so we have
to set it in the kernel.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: linux-2.6/arch/powerpc/kernel/cpu_setup_pa6t.S
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/cpu_setup_pa6t.S
+++ linux-2.6/arch/powerpc/kernel/cpu_setup_pa6t.S
@@ -34,7 +34,7 @@ _GLOBAL(__setup_cpu_pa6t)
beqlr
mfspr r0,SPRN_HID5
- ori r0,r0,0x30
+ ori r0,r0,0x38
mtspr SPRN_HID5,r0
mfspr r0,SPRN_LPCR
^ permalink raw reply
* [PATCH] [3/5] pasemi: reset mpic on boot
From: Olof Johansson @ 2007-04-16 6:28 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20070416062634.GB20196@lixom.net>
Reset MPIC on boot to clear some timer state that firmware might
leave configured.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: linux-2.6/arch/powerpc/platforms/pasemi/setup.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/pasemi/setup.c
+++ linux-2.6/arch/powerpc/platforms/pasemi/setup.c
@@ -147,7 +147,7 @@ static __init void pas_init_IRQ(void)
printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr);
mpic = mpic_alloc(mpic_node, openpic_addr,
- MPIC_PRIMARY|MPIC_LARGE_VECTORS,
+ MPIC_PRIMARY|MPIC_LARGE_VECTORS|MPIC_WANTS_RESET,
0, 0, " PAS-OPIC ");
BUG_ON(!mpic);
^ permalink raw reply
* [PATCH] [4/5] pasemi: PA6T oprofile support
From: Olof Johansson @ 2007-04-16 6:30 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev, anton
In-Reply-To: <20070416062634.GB20196@lixom.net>
Oprofile support for PA6T, kernel side.
Also rename the PA6T_SPRN.* defines to SPRN_PA6T.*.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: linux-2.6/arch/powerpc/kernel/cputable.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/cputable.c
+++ linux-2.6/arch/powerpc/kernel/cputable.c
@@ -373,6 +373,8 @@ static struct cpu_spec cpu_specs[] = {
.pmc_type = PPC_PMC_PA6T,
.cpu_setup = __setup_cpu_pa6t,
.cpu_restore = __restore_cpu_pa6t,
+ .oprofile_cpu_type = "ppc64/pa6t",
+ .oprofile_type = PPC_OPROFILE_PA6T,
.platform = "pa6t",
},
{ /* default match */
Index: linux-2.6/arch/powerpc/kernel/sysfs.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/sysfs.c
+++ linux-2.6/arch/powerpc/kernel/sysfs.c
@@ -189,12 +189,12 @@ SYSFS_PMCSETUP(purr, SPRN_PURR);
SYSFS_PMCSETUP(spurr, SPRN_SPURR);
SYSFS_PMCSETUP(dscr, SPRN_DSCR);
-SYSFS_PMCSETUP(pa6t_pmc0, PA6T_SPRN_PMC0);
-SYSFS_PMCSETUP(pa6t_pmc1, PA6T_SPRN_PMC1);
-SYSFS_PMCSETUP(pa6t_pmc2, PA6T_SPRN_PMC2);
-SYSFS_PMCSETUP(pa6t_pmc3, PA6T_SPRN_PMC3);
-SYSFS_PMCSETUP(pa6t_pmc4, PA6T_SPRN_PMC4);
-SYSFS_PMCSETUP(pa6t_pmc5, PA6T_SPRN_PMC5);
+SYSFS_PMCSETUP(pa6t_pmc0, SPRN_PA6T_PMC0);
+SYSFS_PMCSETUP(pa6t_pmc1, SPRN_PA6T_PMC1);
+SYSFS_PMCSETUP(pa6t_pmc2, SPRN_PA6T_PMC2);
+SYSFS_PMCSETUP(pa6t_pmc3, SPRN_PA6T_PMC3);
+SYSFS_PMCSETUP(pa6t_pmc4, SPRN_PA6T_PMC4);
+SYSFS_PMCSETUP(pa6t_pmc5, SPRN_PA6T_PMC5);
static SYSDEV_ATTR(mmcra, 0600, show_mmcra, store_mmcra);
Index: linux-2.6/arch/powerpc/oprofile/op_model_pa6t.c
===================================================================
--- /dev/null
+++ linux-2.6/arch/powerpc/oprofile/op_model_pa6t.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2006-2007 PA Semi, Inc
+ *
+ * Author: Shashi Rao, PA Semi
+ *
+ * Maintained by: Olof Johansson <olof@lixom.net>
+ *
+ * Based on arch/powerpc/oprofile/op_model_power4.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/oprofile.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/percpu.h>
+#include <asm/processor.h>
+#include <asm/cputable.h>
+#include <asm/oprofile_impl.h>
+#include <asm/reg.h>
+
+static unsigned char oprofile_running;
+
+/* mmcr values are set in pa6t_reg_setup, used in pa6t_cpu_setup */
+static u64 mmcr0_val;
+static u64 mmcr1_val;
+
+/* inited in pa6t_reg_setup */
+static u64 reset_value[OP_MAX_COUNTER];
+
+static inline u64 ctr_read(unsigned int i)
+{
+ switch (i) {
+ case 0:
+ return mfspr(SPRN_PA6T_PMC0);
+ case 1:
+ return mfspr(SPRN_PA6T_PMC1);
+ case 2:
+ return mfspr(SPRN_PA6T_PMC2);
+ case 3:
+ return mfspr(SPRN_PA6T_PMC3);
+ case 4:
+ return mfspr(SPRN_PA6T_PMC4);
+ case 5:
+ return mfspr(SPRN_PA6T_PMC5);
+ default:
+ printk(KERN_ERR "ctr_read called with bad arg %u\n", i);
+ return 0;
+ }
+}
+
+static inline void ctr_write(unsigned int i, u64 val)
+{
+ switch (i) {
+ case 0:
+ mtspr(SPRN_PA6T_PMC0, val);
+ break;
+ case 1:
+ mtspr(SPRN_PA6T_PMC1, val);
+ break;
+ case 2:
+ mtspr(SPRN_PA6T_PMC2, val);
+ break;
+ case 3:
+ mtspr(SPRN_PA6T_PMC3, val);
+ break;
+ case 4:
+ mtspr(SPRN_PA6T_PMC4, val);
+ break;
+ case 5:
+ mtspr(SPRN_PA6T_PMC5, val);
+ break;
+ default:
+ printk(KERN_ERR "ctr_write called with bad arg %u\n", i);
+ break;
+ }
+}
+
+
+/* precompute the values to stuff in the hardware registers */
+static void pa6t_reg_setup(struct op_counter_config *ctr,
+ struct op_system_config *sys,
+ int num_ctrs)
+{
+ int pmc;
+
+ /*
+ * adjust the mmcr0.en[0-5] and mmcr0.inten[0-5] values obtained from the
+ * event_mappings file by turning off the counters that the user doesn't
+ * care about
+ *
+ * setup user and kernel profiling
+ */
+ for (pmc = 0; pmc < cur_cpu_spec->num_pmcs; pmc++)
+ if (!ctr[pmc].enabled) {
+ sys->mmcr0 &= ~(0x1UL << pmc);
+ sys->mmcr0 &= ~(0x1UL << (pmc+12));
+ pr_debug("turned off counter %u\n", pmc);
+ }
+
+ if (sys->enable_kernel)
+ sys->mmcr0 |= PA6T_MMCR0_SUPEN | PA6T_MMCR0_HYPEN;
+ else
+ sys->mmcr0 &= ~(PA6T_MMCR0_SUPEN | PA6T_MMCR0_HYPEN);
+
+ if (sys->enable_user)
+ sys->mmcr0 |= PA6T_MMCR0_PREN;
+ else
+ sys->mmcr0 &= ~PA6T_MMCR0_PREN;
+
+ /*
+ * The performance counter event settings are given in the mmcr0 and
+ * mmcr1 values passed from the user in the op_system_config
+ * structure (sys variable).
+ */
+ mmcr0_val = sys->mmcr0;
+ mmcr1_val = sys->mmcr1;
+ pr_debug("mmcr0_val inited to %016lx\n", sys->mmcr0);
+ pr_debug("mmcr1_val inited to %016lx\n", sys->mmcr1);
+
+ for (pmc = 0; pmc < cur_cpu_spec->num_pmcs; pmc++) {
+ /* counters are 40 bit. Move to cputable at some point? */
+ reset_value[pmc] = (0x1UL << 39) - ctr[pmc].count;
+ pr_debug("reset_value for pmc%u inited to 0x%lx\n",
+ pmc, reset_value[pmc]);
+ }
+}
+
+/* configure registers on this cpu */
+static void pa6t_cpu_setup(struct op_counter_config *ctr)
+{
+ u64 mmcr0 = mmcr0_val;
+ u64 mmcr1 = mmcr1_val;
+
+ /* Default is all PMCs off */
+ mmcr0 &= ~(0x3FUL);
+ mtspr(SPRN_PA6T_MMCR0, mmcr0);
+
+ /* program selected programmable events in */
+ mtspr(SPRN_PA6T_MMCR1, mmcr1);
+
+ pr_debug("setup on cpu %d, mmcr0 %016lx\n", smp_processor_id(),
+ mfspr(SPRN_PA6T_MMCR0));
+ pr_debug("setup on cpu %d, mmcr1 %016lx\n", smp_processor_id(),
+ mfspr(SPRN_PA6T_MMCR1));
+}
+
+static void pa6t_start(struct op_counter_config *ctr)
+{
+ int i;
+
+ /* Hold off event counting until rfid */
+ u64 mmcr0 = mmcr0_val | PA6T_MMCR0_HANDDIS;
+
+ for (i = 0; i < cur_cpu_spec->num_pmcs; i++)
+ if (ctr[i].enabled)
+ ctr_write(i, reset_value[i]);
+ else
+ ctr_write(i, 0UL);
+
+ mtspr(SPRN_PA6T_MMCR0, mmcr0);
+
+ oprofile_running = 1;
+
+ pr_debug("start on cpu %d, mmcr0 %lx\n", smp_processor_id(), mmcr0);
+}
+
+static void pa6t_stop(void)
+{
+ u64 mmcr0;
+
+ /* freeze counters */
+ mmcr0 = mfspr(SPRN_PA6T_MMCR0);
+ mmcr0 |= PA6T_MMCR0_FCM0;
+ mtspr(SPRN_PA6T_MMCR0, mmcr0);
+
+ oprofile_running = 0;
+
+ pr_debug("stop on cpu %d, mmcr0 %lx\n", smp_processor_id(), mmcr0);
+}
+
+/* handle the perfmon overflow vector */
+static void pa6t_handle_interrupt(struct pt_regs *regs,
+ struct op_counter_config *ctr)
+{
+ unsigned long pc = mfspr(SPRN_PA6T_SIAR);
+ int is_kernel = is_kernel_addr(pc);
+ u64 val;
+ int i;
+ u64 mmcr0;
+
+ /* disable perfmon counting until rfid */
+ mmcr0 = mfspr(SPRN_PA6T_MMCR0);
+ mtspr(SPRN_PA6T_MMCR0, mmcr0 | PA6T_MMCR0_HANDDIS);
+
+ /* Record samples. We've got one global bit for whether a sample
+ * was taken, so add it for any counter that triggered overflow.
+ */
+ for (i = 0; i < cur_cpu_spec->num_pmcs; i++) {
+ val = ctr_read(i);
+ if (val & (0x1UL << 39)) { /* Overflow bit set */
+ if (oprofile_running && ctr[i].enabled) {
+ if (mmcr0 & PA6T_MMCR0_SIARLOG)
+ oprofile_add_ext_sample(pc, regs, i, is_kernel);
+ ctr_write(i, reset_value[i]);
+ } else {
+ ctr_write(i, 0UL);
+ }
+ }
+ }
+
+ /* Restore mmcr0 to a good known value since the PMI changes it */
+ mmcr0 = mmcr0_val | PA6T_MMCR0_HANDDIS;
+ mtspr(SPRN_PA6T_MMCR0, mmcr0);
+}
+
+struct op_powerpc_model op_model_pa6t = {
+ .reg_setup = pa6t_reg_setup,
+ .cpu_setup = pa6t_cpu_setup,
+ .start = pa6t_start,
+ .stop = pa6t_stop,
+ .handle_interrupt = pa6t_handle_interrupt,
+};
Index: linux-2.6/arch/powerpc/platforms/pasemi/setup.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/pasemi/setup.c
+++ linux-2.6/arch/powerpc/platforms/pasemi/setup.c
@@ -28,6 +28,7 @@
#include <linux/console.h>
#include <linux/pci.h>
+#include <asm/pmc.h>
#include <asm/prom.h>
#include <asm/system.h>
#include <asm/iommu.h>
Index: linux-2.6/include/asm-powerpc/cputable.h
===================================================================
--- linux-2.6.orig/include/asm-powerpc/cputable.h
+++ linux-2.6/include/asm-powerpc/cputable.h
@@ -48,6 +48,7 @@ enum powerpc_oprofile_type {
PPC_OPROFILE_G4 = 3,
PPC_OPROFILE_BOOKE = 4,
PPC_OPROFILE_CELL = 5,
+ PPC_OPROFILE_PA6T = 6,
};
enum powerpc_pmc_type {
Index: linux-2.6/include/asm-powerpc/reg.h
===================================================================
--- linux-2.6.orig/include/asm-powerpc/reg.h
+++ linux-2.6/include/asm-powerpc/reg.h
@@ -469,12 +469,77 @@
#define SPRN_SIAR 780
#define SPRN_SDAR 781
-#define PA6T_SPRN_PMC0 787
-#define PA6T_SPRN_PMC1 788
-#define PA6T_SPRN_PMC2 789
-#define PA6T_SPRN_PMC3 790
-#define PA6T_SPRN_PMC4 791
-#define PA6T_SPRN_PMC5 792
+#define SPRN_PA6T_PMC0 787
+#define SPRN_PA6T_PMC1 788
+#define SPRN_PA6T_PMC2 789
+#define SPRN_PA6T_PMC3 790
+#define SPRN_PA6T_PMC4 791
+#define SPRN_PA6T_PMC5 792
+
+#define PA6T_BITPOS(x) (0x1UL << (63 - x))
+
+#define SPRN_PA6T_MMCR0 795
+#define PA6T_MMCR0_EN0 0x0000000000000001UL
+#define PA6T_MMCR0_EN1 0x0000000000000002UL
+#define PA6T_MMCR0_EN2 0x0000000000000004UL
+#define PA6T_MMCR0_EN3 0x0000000000000008UL
+#define PA6T_MMCR0_EN4 0x0000000000000010UL
+#define PA6T_MMCR0_EN5 0x0000000000000020UL
+#define PA6T_MMCR0_SUPEN 0x0000000000000040UL
+#define PA6T_MMCR0_PREN 0x0000000000000080UL
+#define PA6T_MMCR0_HYPEN 0x0000000000000100UL
+#define PA6T_MMCR0_FCM0 0x0000000000000200UL
+#define PA6T_MMCR0_FCM1 0x0000000000000400UL
+#define PA6T_MMCR0_INTGEN 0x0000000000000800UL
+#define PA6T_MMCR0_INTEN0 0x0000000000001000UL
+#define PA6T_MMCR0_INTEN1 0x0000000000002000UL
+#define PA6T_MMCR0_INTEN2 0x0000000000004000UL
+#define PA6T_MMCR0_INTEN3 0x0000000000008000UL
+#define PA6T_MMCR0_INTEN4 0x0000000000010000UL
+#define PA6T_MMCR0_INTEN5 0x0000000000020000UL
+#define PA6T_MMCR0_DISCNT 0x0000000000040000UL
+#define PA6T_MMCR0_UOP 0x0000000000080000UL
+#define PA6T_MMCR0_TRG 0x0000000000100000UL
+#define PA6T_MMCR0_TRGEN 0x0000000000200000UL
+#define PA6T_MMCR0_TRGREG 0x0000000001600000UL
+#define PA6T_MMCR0_SIARLOG 0x0000000002000000UL
+#define PA6T_MMCR0_SDARLOG 0x0000000004000000UL
+#define PA6T_MMCR0_PROEN 0x0000000008000000UL
+#define PA6T_MMCR0_PROLOG 0x0000000010000000UL
+#define PA6T_MMCR0_DAMEN2 0x0000000020000000UL
+#define PA6T_MMCR0_DAMEN3 0x0000000040000000UL
+#define PA6T_MMCR0_DAMEN4 0x0000000080000000UL
+#define PA6T_MMCR0_DAMEN5 0x0000000100000000UL
+#define PA6T_MMCR0_DAMSEL2 0x0000000200000000UL
+#define PA6T_MMCR0_DAMSEL3 0x0000000400000000UL
+#define PA6T_MMCR0_DAMSEL4 0x0000000800000000UL
+#define PA6T_MMCR0_DAMSEL5 0x0000001000000000UL
+#define PA6T_MMCR0_HANDDIS 0x0000002000000000UL
+#define PA6T_MMCR0_PCTEN 0x0000004000000000UL
+#define PA6T_MMCR0_SOCEN 0x0000008000000000UL
+#define PA6T_MMCR0_SOCMOD 0x0000010000000000UL
+
+#define SPRN_PA6T_MMCR1 798
+#define PA6T_MMCR1_ES2 0x00000000000000ffUL
+#define PA6T_MMCR1_ES3 0x000000000000ff00UL
+#define PA6T_MMCR1_ES4 0x0000000000ff0000UL
+#define PA6T_MMCR1_ES5 0x00000000ff000000UL
+
+#define SPRN_PA6T_SIAR 780
+#define SPRN_PA6T_UPMC0 771
+#define SPRN_PA6T_UPMC1 772
+#define SPRN_PA6T_UPMC2 773
+#define SPRN_PA6T_UPMC3 774
+#define SPRN_PA6T_UPMC4 775
+#define SPRN_PA6T_UPMC5 776
+#define SPRN_PA6T_UMMCR0 779
+#define SPRN_PA6T_UMMCR1 782
+#define SPRN_PA6T_PMC0 787
+#define SPRN_PA6T_PMC1 788
+#define SPRN_PA6T_PMC2 789
+#define SPRN_PA6T_PMC3 790
+#define SPRN_PA6T_PMC4 791
+#define SPRN_PA6T_PMC5 792
#else /* 32-bit */
#define SPRN_MMCR0 952 /* Monitor Mode Control Register 0 */
Index: linux-2.6/include/asm-powerpc/pmc.h
===================================================================
--- linux-2.6.orig/include/asm-powerpc/pmc.h
+++ linux-2.6/include/asm-powerpc/pmc.h
@@ -30,6 +30,7 @@ void release_pmc_hardware(void);
#ifdef CONFIG_PPC64
void power4_enable_pmcs(void);
+void pasemi_enable_pmcs(void);
#endif
#endif /* __KERNEL__ */
Index: linux-2.6/arch/powerpc/oprofile/common.c
===================================================================
--- linux-2.6.orig/arch/powerpc/oprofile/common.c
+++ linux-2.6/arch/powerpc/oprofile/common.c
@@ -160,6 +160,9 @@ int __init oprofile_arch_init(struct opr
case PPC_OPROFILE_POWER4:
model = &op_model_power4;
break;
+ case PPC_OPROFILE_PA6T:
+ model = &op_model_pa6t;
+ break;
#endif
#ifdef CONFIG_6xx
case PPC_OPROFILE_G4:
Index: linux-2.6/arch/powerpc/oprofile/Makefile
===================================================================
--- linux-2.6.orig/arch/powerpc/oprofile/Makefile
+++ linux-2.6/arch/powerpc/oprofile/Makefile
@@ -12,6 +12,6 @@ DRIVER_OBJS := $(addprefix ../../../driv
oprofile-y := $(DRIVER_OBJS) common.o backtrace.o
oprofile-$(CONFIG_PPC_CELL_NATIVE) += op_model_cell.o
-oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o
+oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o op_model_pa6t.o
oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o
oprofile-$(CONFIG_6xx) += op_model_7450.o
Index: linux-2.6/include/asm-powerpc/oprofile_impl.h
===================================================================
--- linux-2.6.orig/include/asm-powerpc/oprofile_impl.h
+++ linux-2.6/include/asm-powerpc/oprofile_impl.h
@@ -57,6 +57,8 @@ extern struct op_powerpc_model op_model_
extern struct op_powerpc_model op_model_power4;
extern struct op_powerpc_model op_model_7450;
extern struct op_powerpc_model op_model_cell;
+extern struct op_powerpc_model op_model_pa6t;
+
/* All the classic PPC parts use these */
static inline unsigned int classic_ctr_read(unsigned int i)
^ permalink raw reply
* [PATCH] [5/5] pasemi: GPIO MDIO of_platform driver
From: Olof Johansson @ 2007-04-16 6:31 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20070416062634.GB20196@lixom.net>
MDIO driver for PHY's connected via GPIO as on the PA Semi Electra
eval board.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: powerpc/arch/powerpc/platforms/pasemi/gpio_mdio.c
===================================================================
--- /dev/null
+++ powerpc/arch/powerpc/platforms/pasemi/gpio_mdio.c
@@ -0,0 +1,349 @@
+/*
+ * Copyright (C) 2006-2007 PA Semi, Inc
+ *
+ * Author: Olof Johansson, PA Semi
+ *
+ * Maintained by: Olof Johansson <olof@lixom.net>
+ *
+ * Based on drivers/net/fs_enet/mii-bitbang.c.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <asm/of_platform.h>
+
+#define DELAY 1
+
+static void __iomem *gpio_regs;
+
+struct gpio_priv {
+ int mdc_pin;
+ int mdio_pin;
+};
+
+#define MDC_PIN(bus) (((struct gpio_priv *)bus->priv)->mdc_pin)
+#define MDIO_PIN(bus) (((struct gpio_priv *)bus->priv)->mdio_pin)
+
+static inline void mdio_lo(struct mii_bus *bus)
+{
+ out_le32(gpio_regs+0x10, 1 << MDIO_PIN(bus));
+}
+
+static inline void mdio_hi(struct mii_bus *bus)
+{
+ out_le32(gpio_regs, 1 << MDIO_PIN(bus));
+}
+
+static inline void mdc_lo(struct mii_bus *bus)
+{
+ out_le32(gpio_regs+0x10, 1 << MDC_PIN(bus));
+}
+
+static inline void mdc_hi(struct mii_bus *bus)
+{
+ out_le32(gpio_regs, 1 << MDC_PIN(bus));
+}
+
+static inline void mdio_active(struct mii_bus *bus)
+{
+ out_le32(gpio_regs+0x20, (1 << MDC_PIN(bus)) | (1 << MDIO_PIN(bus)));
+}
+
+static inline void mdio_tristate(struct mii_bus *bus)
+{
+ out_le32(gpio_regs+0x30, (1 << MDIO_PIN(bus)));
+}
+
+static inline int mdio_read(struct mii_bus *bus)
+{
+ return !!(in_le32(gpio_regs+0x40) & (1 << MDIO_PIN(bus)));
+}
+
+static void clock_out(struct mii_bus *bus, int bit)
+{
+ if (bit)
+ mdio_hi(bus);
+ else
+ mdio_lo(bus);
+ udelay(DELAY);
+ mdc_hi(bus);
+ udelay(DELAY);
+ mdc_lo(bus);
+}
+
+/* Utility to send the preamble, address, and register (common to read and write). */
+static void bitbang_pre(struct mii_bus *bus, int read, u8 addr, u8 reg)
+{
+ int i;
+
+ /* CFE uses a really long preamble (40 bits). We'll do the same. */
+ mdio_active(bus);
+ for (i = 0; i < 40; i++) {
+ clock_out(bus, 1);
+ }
+
+ /* send the start bit (01) and the read opcode (10) or write (10) */
+ clock_out(bus, 0);
+ clock_out(bus, 1);
+
+ clock_out(bus, read);
+ clock_out(bus, !read);
+
+ /* send the PHY address */
+ for (i = 0; i < 5; i++) {
+ clock_out(bus, (addr & 0x10) != 0);
+ addr <<= 1;
+ }
+
+ /* send the register address */
+ for (i = 0; i < 5; i++) {
+ clock_out(bus, (reg & 0x10) != 0);
+ reg <<= 1;
+ }
+}
+
+static int gpio_mdio_read(struct mii_bus *bus, int phy_id, int location)
+{
+ u16 rdreg;
+ int ret, i;
+ u8 addr = phy_id & 0xff;
+ u8 reg = location & 0xff;
+
+ bitbang_pre(bus, 1, addr, reg);
+
+ /* tri-state our MDIO I/O pin so we can read */
+ mdio_tristate(bus);
+ udelay(DELAY);
+ mdc_hi(bus);
+ udelay(DELAY);
+ mdc_lo(bus);
+
+ /* read 16 bits of register data, MSB first */
+ rdreg = 0;
+ for (i = 0; i < 16; i++) {
+ mdc_lo(bus);
+ udelay(DELAY);
+ mdc_hi(bus);
+ udelay(DELAY);
+ mdc_lo(bus);
+ udelay(DELAY);
+ rdreg <<= 1;
+ rdreg |= mdio_read(bus);
+ }
+
+ mdc_hi(bus);
+ udelay(DELAY);
+ mdc_lo(bus);
+ udelay(DELAY);
+
+ ret = rdreg;
+
+ return ret;
+}
+
+static int gpio_mdio_write(struct mii_bus *bus, int phy_id, int location, u16 val)
+{
+ int i;
+
+ u8 addr = phy_id & 0xff;
+ u8 reg = location & 0xff;
+ u16 value = val & 0xffff;
+
+ bitbang_pre(bus, 0, addr, reg);
+
+ /* send the turnaround (10) */
+ mdc_lo(bus);
+ mdio_hi(bus);
+ udelay(DELAY);
+ mdc_hi(bus);
+ udelay(DELAY);
+ mdc_lo(bus);
+ mdio_lo(bus);
+ udelay(DELAY);
+ mdc_hi(bus);
+ udelay(DELAY);
+
+ /* write 16 bits of register data, MSB first */
+ for (i = 0; i < 16; i++) {
+ mdc_lo(bus);
+ if (value & 0x8000)
+ mdio_hi(bus);
+ else
+ mdio_lo(bus);
+ udelay(DELAY);
+ mdc_hi(bus);
+ udelay(DELAY);
+ value <<= 1;
+ }
+
+ /*
+ * Tri-state the MDIO line.
+ */
+ mdio_tristate(bus);
+ mdc_lo(bus);
+ udelay(DELAY);
+ mdc_hi(bus);
+ udelay(DELAY);
+ return 0;
+}
+
+static int gpio_mdio_reset(struct mii_bus *bus)
+{
+ /*nothing here - dunno how to reset it*/
+ return 0;
+}
+
+
+static int __devinit gpio_mdio_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ struct device *dev = &ofdev->dev;
+ struct device_node *np = ofdev->node;
+ struct device_node *gpio_np;
+ struct mii_bus *new_bus;
+ struct resource res;
+ struct gpio_priv *priv;
+ const unsigned int *prop;
+ int err = 0;
+ int i;
+
+ gpio_np = of_find_compatible_node(NULL, "gpio", "1682m-gpio");
+
+ if (!gpio_np)
+ return -ENODEV;
+
+ err = of_address_to_resource(gpio_np, 0, &res);
+ of_node_put(gpio_np);
+
+ if (err)
+ return -EINVAL;
+
+ if (!gpio_regs)
+ gpio_regs = ioremap(res.start, 0x100);
+
+ if (!gpio_regs)
+ return -EPERM;
+
+ priv = kzalloc(sizeof(struct gpio_priv), GFP_KERNEL);
+ if (priv == NULL)
+ return -ENOMEM;
+
+ new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
+
+ if (new_bus == NULL)
+ return -ENOMEM;
+
+ new_bus->name = "pasemi gpio mdio bus",
+ new_bus->read = &gpio_mdio_read,
+ new_bus->write = &gpio_mdio_write,
+ new_bus->reset = &gpio_mdio_reset,
+
+ prop = get_property(np, "reg", NULL);
+ new_bus->id = *prop;
+ new_bus->priv = priv;
+
+ new_bus->phy_mask = 0;
+
+ new_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+ for(i = 0; i < PHY_MAX_ADDR; ++i)
+ new_bus->irq[i] = irq_create_mapping(NULL, 10);
+
+
+ prop = get_property(np, "mdc-pin", NULL);
+ priv->mdc_pin = *prop;
+
+ prop = get_property(np, "mdio-pin", NULL);
+ priv->mdio_pin = *prop;
+
+ new_bus->dev = dev;
+ dev_set_drvdata(dev, new_bus);
+
+ err = mdiobus_register(new_bus);
+
+ if (0 != err) {
+ printk(KERN_ERR "%s: Cannot register as MDIO bus, err %d\n",
+ new_bus->name, err);
+ goto bus_register_fail;
+ }
+
+ return 0;
+
+bus_register_fail:
+ kfree(new_bus);
+
+ return err;
+}
+
+
+static int gpio_mdio_remove(struct of_device *dev)
+{
+ struct mii_bus *bus = dev_get_drvdata(&dev->dev);
+
+ mdiobus_unregister(bus);
+
+ dev_set_drvdata(&dev->dev, NULL);
+
+ kfree(bus->priv);
+ bus->priv = NULL;
+ kfree(bus);
+
+ return 0;
+}
+
+static struct of_device_id gpio_mdio_match[] =
+{
+ {
+ .compatible = "gpio-mdio",
+ },
+ {},
+};
+
+static struct of_platform_driver gpio_mdio_driver =
+{
+ .name = "gpio-mdio-bitbang",
+ .match_table = gpio_mdio_match,
+ .probe = gpio_mdio_probe,
+ .remove = gpio_mdio_remove,
+};
+
+int gpio_mdio_init(void)
+{
+ return of_register_platform_driver(&gpio_mdio_driver);
+}
+
+void gpio_mdio_exit(void)
+{
+ of_unregister_platform_driver(&gpio_mdio_driver);
+}
+
+device_initcall(gpio_mdio_init);
+
+static int __devinit hack_init(void)
+{
+ struct platform_device *pdev;
+
+ pdev = platform_device_register_simple("gpio-mdio-bitbang", 0, NULL, 0);
+
+ return 0;
+}
+late_initcall(hack_init);
Index: powerpc/arch/powerpc/platforms/pasemi/Makefile
===================================================================
--- powerpc.orig/arch/powerpc/platforms/pasemi/Makefile
+++ powerpc/arch/powerpc/platforms/pasemi/Makefile
@@ -1,3 +1,3 @@
-obj-y += setup.o pci.o time.o idle.o powersave.o iommu.o
+obj-y += setup.o pci.o time.o idle.o powersave.o iommu.o gpio_mdio.o
obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += cpufreq.o
^ 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