* Re: [PATCH] Fix USB suspend/resume crasher
From: Rafael J. Wysocki @ 2005-11-24 0:22 UTC (permalink / raw)
To: linux-kernel
Cc: Andrew Morton, David Brownell, linuxppc-dev list, Greg KH,
Alan Stern
In-Reply-To: <1132715288.26560.262.camel@gaston>
[-- Attachment #1: Type: text/plain, Size: 5195 bytes --]
Hi,
On Wednesday, 23 of November 2005 04:08, Benjamin Herrenschmidt wrote:
> This is my latest patch against current linus -git, it closes the IRQ
> race and makes various other OHCI & EHCI code path safer vs.
> suspend/resume. I've been able to (finally !) successfully suspend and
> resume various Mac models, with or without USB mouse plugged, or
> plugging while asleep, or unplugging while asleep etc... all without a
> crash. There are still some races here or there in the USB code, but at
> least the main cause of crash is now fixes by this patch (access to a
> controller that has been suspended, due to either shared interrupts or
> other code path).
>
> I haven't fixed UHCI as I don't have any HW to test, though I hope I
> haven't broken it neither. Alan, I would appreciate if you could have a
> look.
>
> This patch applies on top of the patch that moves the PowerMac specific
> code out of ohci-pci.c to hcd-pci.c where it belongs. This patch isn't
> upstream yet for reasons I don't fully understand (why does USB stuffs
> has such a high latency for going upstream ?), I'm sending it as a reply
> to this email for completeness.
>
> Without this patch, you cannot reliably sleep/wakeup any recent Mac, and
> I suspect PCs have some more sneaky issues too (they don't frankly crash
> with machine checks because x86 tend to silently swallow PCI errors but
> that won't last afaik, at least PCI Express will blow up in those
> situations, but the USB code may still misbehave).
Unfortunately with this patch the EHCI controller in my box (Asus L5D,
x86-64 kernel) does not resume from suspend. Appended is the relevant
snippet from the serial console log (EHCI is the only device using IRQ #5).
Greetings,
Rafael
PM: Image restored successfully.
ohci_hcd 0000:00:02.0: PCI D0, from previous PCI D3
ACPI: PCI Interrupt 0000:00:02.0[A] -> Link [LUS0] -> GSI 11 (level, low) -> IRQ 11
PCI: Setting latency timer of device 0000:00:02.0 to 64
ohci_hcd 0000:00:02.1: PCI D0, from previous PCI D3
ACPI: PCI Interrupt 0000:00:02.1[B] -> Link [LUS1] -> GSI 11 (level, low) -> IRQ 11
PCI: Setting latency timer of device 0000:00:02.1 to 64
ehci_hcd 0000:00:02.2: PCI D0, from previous PCI D3
ACPI: PCI Interrupt 0000:00:02.2[C] -> Link [LUS2] -> GSI 5 (level, low) -> IRQ 5
PCI: Setting latency timer of device 0000:00:02.2 to 64
ehci_hcd 0000:00:02.2: lost power, restarting
usb usb3: root hub lost power or was reset
ehci_hcd 0000:00:02.2: reset command 080b02 park=3 ithresh=8 period=1024 Reset HALT
ehci_hcd 0000:00:02.2: debug port 1
ehci_hcd 0000:00:02.2: capability 1000001 at a0
PCI: cache line size of 64 is not supported by device 0000:00:02.2
ehci_hcd 0000:00:02.2: reset command 080b02 park=3 ithresh=8 period=1024 Reset HALT
ehci_hcd 0000:00:02.2: init command 010009 (park)=0 ithresh=1 period=256 RUN
ehci_hcd 0000:00:02.2: USB 2.0 started, EHCI 1.00, driver 10 Dec 2004
ACPI: PCI Interrupt 0000:00:06.0[A] -> Link [LAUI] -> GSI 10 (level, low) -> IRQ 10
PCI: Setting latency timer of device 0000:00:06.0 to 64
irq 5: nobody cared (try booting with the "irqpoll" option)
Call Trace: <IRQ> <ffffffff80250c3e>{add_preempt_count+94} <ffffffff8015a878>{__report_bad_irq+56}
<ffffffff8015aab4>{note_interrupt+484} <ffffffff8015a317>{__do_IRQ+199}
<ffffffff801110f7>{do_IRQ+55} <ffffffff8010f100>{ret_from_intr+0}
<ffffffff8010fb02>{call_softirq+30} <ffffffff80138714>{__do_softirq+68}
<ffffffff801386ff>{__do_softirq+47} <ffffffff8010fb02>{call_softirq+30}
<ffffffff801110b5>{do_softirq+53} <ffffffff8013849f>{irq_exit+63}
<ffffffff801110fc>{do_IRQ+60} <ffffffff8010f100>{ret_from_intr+0}
<EOI> <ffffffff802c183a>{serial8250_console_write+186}
<ffffffff80132dad>{release_console_sem+333} <ffffffff80133587>{vprintk+775}
<ffffffff80133682>{printk+162} <ffffffff80133682>{printk+162}
<ffffffff8036003d>{_spin_unlock_irqrestore+29} <ffffffff80252c31>{pci_bus_read_config_byte+113}
<ffffffff802ed6fe>{pcibios_set_master+110} <ffffffff80255415>{pci_set_master+85}
<ffffffff88180eb7>{:snd_intel8x0:intel8x0_resume+39}
<ffffffff8812a9e7>{:snd:snd_card_pci_resume+55} <ffffffff80256c74>{pci_device_resume+36}
<ffffffff802d5cdd>{resume_device+157} <ffffffff802d5e23>{dpm_resume+147}
<ffffffff802d5e90>{device_resume+32} <ffffffff80153508>{pm_suspend_disk+296}
<ffffffff80150f10>{enter_state+112} <ffffffff80151147>{state_store+119}
<ffffffff801bfdd4>{subsys_attr_store+36} <ffffffff801c025a>{sysfs_write_file+202}
<ffffffff8017fb09>{vfs_write+233} <ffffffff8017fcb0>{sys_write+80}
<ffffffff8010eb5e>{system_call+126}
---------------------------
| preempt count: 00010103 ]
| 3 level deep critical section nesting:
----------------------------------------
.. [<ffffffff801332a4>] .... vprintk+0x24/0x360
.....[<ffffffff80133682>] .. ( <= printk+0xa2/0xb0)
.. [<ffffffff80360176>] .... _spin_lock+0x16/0x30
.....[<ffffffff8015a2fc>] .. ( <= __do_IRQ+0xac/0x120)
.. [<ffffffff80360176>] .... _spin_lock+0x16/0x30
.....[<ffffffff8015a2fc>] .. ( <= __do_IRQ+0xac/0x120)
handlers:
[<ffffffff80260970>] (usb_hcd_irq+0x0/0x70)
Disabling IRQ #5
[-- Attachment #2: lspci-v.log --]
[-- Type: text/x-log, Size: 6384 bytes --]
0000:00:00.0 Host bridge: nVidia Corporation nForce3 Host Bridge (rev a4)
Subsystem: ASUSTeK Computer Inc.: Unknown device 80c5
Flags: bus master, 66Mhz, fast devsel, latency 0
Memory at e8000000 (32-bit, prefetchable) [size=128M]
Capabilities: <available only to root>
0000:00:01.0 ISA bridge: nVidia Corporation nForce3 LPC Bridge (rev f6)
Subsystem: ASUSTeK Computer Inc.: Unknown device 80c5
Flags: bus master, 66Mhz, fast devsel, latency 0
0000:00:01.1 SMBus: nVidia Corporation nForce3 SMBus (rev a4)
Subsystem: ASUSTeK Computer Inc.: Unknown device 80c5
Flags: 66Mhz, fast devsel
I/O ports at 5000 [size=64]
I/O ports at 5040 [size=64]
Capabilities: <available only to root>
0000:00:02.0 USB Controller: nVidia Corporation nForce3 USB 1.1 (rev a5) (prog-if 10 [OHCI])
Subsystem: ASUSTeK Computer Inc.: Unknown device 1858
Flags: bus master, 66Mhz, fast devsel, latency 0, IRQ 11
Memory at febfb000 (32-bit, non-prefetchable) [size=4K]
Capabilities: <available only to root>
0000:00:02.1 USB Controller: nVidia Corporation nForce3 USB 1.1 (rev a5) (prog-if 10 [OHCI])
Subsystem: ASUSTeK Computer Inc.: Unknown device 1858
Flags: bus master, 66Mhz, fast devsel, latency 0, IRQ 11
Memory at febfc000 (32-bit, non-prefetchable) [size=4K]
Capabilities: <available only to root>
0000:00:02.2 USB Controller: nVidia Corporation nForce3 USB 2.0 (rev a2) (prog-if 20 [EHCI])
Subsystem: ASUSTeK Computer Inc.: Unknown device 1859
Flags: bus master, 66Mhz, fast devsel, latency 0, IRQ 5
Memory at febfdc00 (32-bit, non-prefetchable) [size=256]
Capabilities: <available only to root>
0000:00:06.0 Multimedia audio controller: nVidia Corporation nForce3 Audio (rev a2)
Subsystem: ASUSTeK Computer Inc.: Unknown device 1853
Flags: bus master, 66Mhz, fast devsel, latency 0, IRQ 10
I/O ports at e800 [size=256]
I/O ports at ec00 [size=128]
Memory at febff000 (32-bit, non-prefetchable) [size=4K]
Capabilities: <available only to root>
0000:00:08.0 IDE interface: nVidia Corporation nForce3 IDE (rev a5) (prog-if 8a [Master SecP PriP])
Subsystem: ASUSTeK Computer Inc.: Unknown device 185a
Flags: bus master, 66Mhz, fast devsel, latency 0
I/O ports at ffa0 [size=16]
Capabilities: <available only to root>
0000:00:0a.0 PCI bridge: nVidia Corporation nForce3 PCI Bridge (rev a2) (prog-if 00 [Normal decode])
Flags: bus master, 66Mhz, fast devsel, latency 0
Bus: primary=00, secondary=02, subordinate=04, sec-latency=128
I/O behind bridge: 0000b000-0000dfff
Memory behind bridge: f8a00000-feafffff
Prefetchable memory behind bridge: 40000000-43ffffff
0000:00:0b.0 PCI bridge: nVidia Corporation nForce3 AGP Bridge (rev a4) (prog-if 00 [Normal decode])
Flags: bus master, 66Mhz, medium devsel, latency 64
Bus: primary=00, secondary=01, subordinate=01, sec-latency=64
Memory behind bridge: f6900000-f89fffff
Prefetchable memory behind bridge: c6800000-e67fffff
0000:00:18.0 Host bridge: Advanced Micro Devices [AMD] K8 [Athlon64/Opteron] HyperTransport Technology Configuration
Flags: fast devsel
Capabilities: <available only to root>
0000:00:18.1 Host bridge: Advanced Micro Devices [AMD] K8 [Athlon64/Opteron] Address Map
Flags: fast devsel
0000:00:18.2 Host bridge: Advanced Micro Devices [AMD] K8 [Athlon64/Opteron] DRAM Controller
Flags: fast devsel
0000:00:18.3 Host bridge: Advanced Micro Devices [AMD] K8 [Athlon64/Opteron] Miscellaneous Control
Flags: fast devsel
0000:01:00.0 VGA compatible controller: nVidia Corporation NV31M [GeForce FX Go5650] (rev a1) (prog-if 00 [VGA])
Subsystem: ASUSTeK Computer Inc.: Unknown device 1852
Flags: bus master, 66Mhz, medium devsel, latency 64, IRQ 11
Memory at f7000000 (32-bit, non-prefetchable) [size=16M]
Memory at d0000000 (32-bit, prefetchable) [size=256M]
Expansion ROM at f89e0000 [disabled] [size=128K]
Capabilities: <available only to root>
0000:02:00.0 Ethernet controller: Marvell Technology Group Ltd. Gigabit Ethernet Controller (rev 13)
Subsystem: ASUSTeK Computer Inc. Marvell 88E8001 Gigabit Ethernet Controller (Asus)
Flags: bus master, 66Mhz, medium devsel, latency 64, IRQ 10
Memory at feaf8000 (32-bit, non-prefetchable) [size=16K]
I/O ports at d800 [size=256]
Expansion ROM at feac0000 [disabled] [size=128K]
Capabilities: <available only to root>
0000:02:01.0 CardBus bridge: Ricoh Co Ltd RL5c476 II (rev ab)
Subsystem: ASUSTeK Computer Inc.: Unknown device 1854
Flags: bus master, medium devsel, latency 168, IRQ 11
Memory at fd200000 (32-bit, non-prefetchable) [size=4K]
Bus: primary=02, secondary=03, subordinate=06, sec-latency=176
Memory window 0: 40000000-41fff000 (prefetchable)
Memory window 1: fc600000-fd1ff000
I/O window 0: 0000b000-0000b0ff
I/O window 1: 0000b400-0000b4ff
16-bit legacy interface ports at 0001
0000:02:01.1 CardBus bridge: Ricoh Co Ltd RL5c476 II (rev ab)
Subsystem: ASUSTeK Computer Inc.: Unknown device 1854
Flags: bus master, medium devsel, latency 168, IRQ 11
Memory at fa200000 (32-bit, non-prefetchable) [size=4K]
Bus: primary=02, secondary=07, subordinate=0a, sec-latency=176
Memory window 0: 42000000-43fff000 (prefetchable)
Memory window 1: f9600000-fa1ff000
I/O window 0: 0000b800-0000b8ff
I/O window 1: 0000bc00-0000bcff
16-bit legacy interface ports at 0001
0000:02:01.2 FireWire (IEEE 1394): Ricoh Co Ltd R5C552 IEEE 1394 Controller (rev 03) (prog-if 10 [OHCI])
Subsystem: ASUSTeK Computer Inc.: Unknown device 1857
Flags: bus master, medium devsel, latency 64, IRQ 10
Memory at feafd000 (32-bit, non-prefetchable) [size=2K]
Capabilities: <available only to root>
0000:02:01.3 System peripheral: Ricoh Co Ltd: Unknown device 0576 (rev 01)
Subsystem: ASUSTeK Computer Inc.: Unknown device 185b
Flags: medium devsel, IRQ 11
Memory at feafd800 (32-bit, non-prefetchable) [size=256]
Capabilities: <available only to root>
0000:02:01.4 System peripheral: Ricoh Co Ltd: Unknown device 0592
Subsystem: ASUSTeK Computer Inc.: Unknown device 185c
Flags: medium devsel, IRQ 11
Memory at feafdc00 (32-bit, non-prefetchable) [size=256]
Capabilities: <available only to root>
0000:02:02.0 Network controller: Broadcom Corporation BCM4306 802.11b/g Wireless LAN Controller (rev 03)
Subsystem: ASUSTeK Computer Inc.: Unknown device 120f
Flags: bus master, fast devsel, latency 64, IRQ 11
Memory at feafe000 (32-bit, non-prefetchable) [size=8K]
Capabilities: <available only to root>
^ permalink raw reply
* Re: [PATCH] generate COFF zImage in arch/powerpc/boot
From: Paul Mackerras @ 2005-11-23 23:06 UTC (permalink / raw)
To: Olaf Hering; +Cc: linuxppc-dev
In-Reply-To: <20051123223827.GA20793@suse.de>
Olaf Hering writes:
> Maybe I miss the point, but if the src is unaligned, and we align it,
> dest will change as well and may be unaligned?
Yes, but in aligning the dest you will unalign the source. So with
your patch we will do something like copy 3 bytes, test, copy 1 byte,
test, go back, copy 3 bytes, test, copy 1 byte, etc., on and on until
the whole buffer is copied. With my patch we get into one loop
copying the whole buffer byte-by-byte.
The other alternative is to work out the appropriate rotate amounts
and masks so that the main loop does load word, rotate, AND, AND, OR,
store word (a bit like the 64-bit kernel memcpy does, except it works
on doublewords not words). That seems like a lot of trouble to go to
for the bootwrapper though.
Paul.
^ permalink raw reply
* Re: [PATCH] generate COFF zImage in arch/powerpc/boot
From: Olaf Hering @ 2005-11-23 22:58 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20051123223827.GA20793@suse.de>
On Wed, Nov 23, Olaf Hering wrote:
> On Thu, Nov 24, Paul Mackeras wrote:
>
> > Olaf Hering writes:
> >
> > > It just died while uncompressing vmlinux. Some unaligned load.
> > > So we either need a very simple byte by byte memcpy, or my version below.
> >
> > This should achieve the same effect and is quite a bit simpler. Your
> > version looks a bit strange - it copies 1-3 bytes to align the source
> > pointer, then copies 1-3 bytes to align the destination pointer, then
> > if the source pointer isn't aligned it goes back and tries again... :)
>
> Maybe I miss the point, but if the src is unaligned, and we align it,
> dest will change as well and may be unaligned?
Oh yes, it starts with dest. So everything is alright.
--
short story of a lazy sysadmin:
alias appserv=wotan
^ permalink raw reply
* Re: [PATCH] generate COFF zImage in arch/powerpc/boot
From: Olaf Hering @ 2005-11-23 22:38 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <17284.61088.219693.162392@cargo.ozlabs.ibm.com>
On Thu, Nov 24, Paul Mackeras wrote:
> Olaf Hering writes:
>
> > It just died while uncompressing vmlinux. Some unaligned load.
> > So we either need a very simple byte by byte memcpy, or my version below.
>
> This should achieve the same effect and is quite a bit simpler. Your
> version looks a bit strange - it copies 1-3 bytes to align the source
> pointer, then copies 1-3 bytes to align the destination pointer, then
> if the source pointer isn't aligned it goes back and tries again... :)
Maybe I miss the point, but if the src is unaligned, and we align it,
dest will change as well and may be unaligned?
--
short story of a lazy sysadmin:
alias appserv=wotan
^ permalink raw reply
* Re: [PATCH] generate COFF zImage in arch/powerpc/boot
From: Paul Mackerras @ 2005-11-23 22:35 UTC (permalink / raw)
To: Olaf Hering; +Cc: linuxppc-dev
In-Reply-To: <20051123202115.GA17320@suse.de>
Olaf Hering writes:
> It just died while uncompressing vmlinux. Some unaligned load.
> So we either need a very simple byte by byte memcpy, or my version below.
This should achieve the same effect and is quite a bit simpler. Your
version looks a bit strange - it copies 1-3 bytes to align the source
pointer, then copies 1-3 bytes to align the destination pointer, then
if the source pointer isn't aligned it goes back and tries again... :)
Regards,
Paul.
diff -urN powerpc/arch/powerpc/boot/string.S merge-hack/arch/powerpc/boot/string.S
--- powerpc/arch/powerpc/boot/string.S 2005-11-16 15:55:17.000000000 +1100
+++ merge-hack/arch/powerpc/boot/string.S 2005-11-24 09:18:47.000000000 +1100
@@ -107,7 +107,7 @@
rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */
addi r6,r3,-4
addi r4,r4,-4
- beq 2f /* if less than 8 bytes to do */
+ beq 3f /* if less than 8 bytes to do */
andi. r0,r6,3 /* get dest word aligned */
mtctr r7
bne 5f
@@ -132,6 +132,11 @@
bdnz 4b
blr
5: subfic r0,r0,4
+ cmpw cr1,r0,r5
+ add r7,r0,r4
+ andi. r7,r7,3 /* will source be word-aligned too? */
+ ble cr1,3b
+ bne 3b /* do byte-by-byte if not */
mtctr r0
6: lbz r7,4(r4)
addi r4,r4,1
@@ -149,7 +154,7 @@
rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */
add r6,r3,r5
add r4,r4,r5
- beq 2f
+ beq 3f
andi. r0,r6,3
mtctr r7
bne 5f
@@ -171,7 +176,12 @@
stbu r0,-1(r6)
bdnz 4b
blr
-5: mtctr r0
+5: cmpw cr1,r0,r5
+ subf r7,r0,r4
+ andi. r7,r7,3
+ ble cr1,3b
+ bne 3b
+ mtctr r0
6: lbzu r7,-1(r4)
stbu r7,-1(r6)
bdnz 6b
^ permalink raw reply
* Re: 2.6.14 USB vs. sleep issues
From: Gaudenz Steinlin @ 2005-11-23 21:55 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev list, debian-powerpc@lists.debian.org
In-Reply-To: <1131745946.24637.251.camel@gaston>
Hi Ben
Benjamin Herrenschmidt schrieb:
> The latest patch that is candidate for upstream is:
I have the same USB wakeup problem with my new powerbook 5,8 (oct 2005
15"). Without the patch I get a kernel oops on wakeup just like the
others. With this patch applied (and the pb 5,8 basic enablement patch)
the lcd gets distorted colors on wakeup. It looks quite insane, like a
broken lcd.
I'm useing a vanilla 2.6.14.2 kernel. CONFIG_USB_SUSPEND is set, PREEMPT
is disabled. Is there a newer version of the patch available for testing?
Gaudenz
^ permalink raw reply
* Re: 2.6.14 USB vs. sleep issues
From: Benjamin Herrenschmidt @ 2005-11-23 22:09 UTC (permalink / raw)
To: Gaudenz Steinlin; +Cc: linuxppc-dev list, debian-powerpc@lists.debian.org
In-Reply-To: <20051123215404.GB3401@soziologie.ch>
On Wed, 2005-11-23 at 22:55 +0100, Gaudenz Steinlin wrote:
> Hi Ben
>
> Benjamin Herrenschmidt schrieb:
> > The latest patch that is candidate for upstream is:
>
> I have the same USB wakeup problem with my new powerbook 5,8 (oct 2005
> 15"). Without the patch I get a kernel oops on wakeup just like the
> others. With this patch applied (and the pb 5,8 basic enablement patch)
> the lcd gets distorted colors on wakeup. It looks quite insane, like a
> broken lcd.
>
> I'm useing a vanilla 2.6.14.2 kernel. CONFIG_USB_SUSPEND is set, PREEMPT
> is disabled. Is there a newer version of the patch available for testing?
The USB patch has nothing to do with your screen problems. Does the
screen issue goes away after a couple of sleep/wakeup cycles ? i'm
waiting on the same machine model that I just ordered from Apple, so
I'll be able to fix remaining issues soon.
Ben.
^ permalink raw reply
* Re: [PATCH] ppc32: 8xx board-specific platform stuff for fs_enet
From: Marcelo Tosatti @ 2005-11-23 15:39 UTC (permalink / raw)
To: Dan Malek; +Cc: linuxppc-embedded list, Paul Mackerras
In-Reply-To: <ddea89e58026c4f55f1a05af602cba60@embeddededge.com>
Hi Dan,
On Wed, Nov 23, 2005 at 03:18:17PM -0500, Dan Malek wrote:
>
> On Nov 23, 2005, at 7:00 AM, Marcelo Tosatti wrote:
>
> >The files in arch/ppc/8xx_io/ (which is what I think you refer to as
> >candidates for drivers/), are:
>
> I don't particularly like these macros, but I'm tired of fighting
> about it.
We did not fight about it, did we??? I don't understand what you mean.
We need to agree on technical points. If you see a problem with the
macros, you need to teach us about them.
The requirement for in/out inline functions is to force the compiler
not to reorder instructions, but I suppose you are talking about the
clrbit/setbit macros? Or about both?
> If you follow the usage path, you will see it's only
> used in the CPM drivers, and I wish people would just use
> the data structure pointers to access these ports/bits with
> standard C code and then place any synchronization
> instructions properly.
The in/out inline functions unify access to conf. registers.
Jeff Garzik gave me a list of reasons for using the inline macros
which is quite educational:
* Easier reviewing. One cannot easily distinguish between writing to
normal kernel virtual memory and "magic" memory that produces magicaly
side effects such as initiating DMA of a net packet.
* Compiler safety. As the code is written now, you have no guarantees
that the compiler won't combine two stores to the same location, etc.
Accessor macros are a convenient place to add compiler barriers or
'volatile' notations that the MPC8xx code lacks.
* Maintainable. foo_read[bwl] or foo_read{8,16,32} are preferred
because that's the way other bus accessors look like -- yes even
embedded SoC buses benefit from these code patterns. You want your
driver to look like other drivers as much as possible.
* Convenience. The accessors can be a zero overhead memory read/write
at a minimum. But they can also be convenient places to use special
memory read/write instructions that specify uncached memop, compiler
barriers, memory barriers, etc.
And Paulus wrote some important points:
Generally on PowerPC you need to use at least the eieio instruction to
prevent reordering of the loads and stores to the device. It's
possible that 8xx is sufficiently in-order that you get away without
putting in barrier instructions (eieio or sync), but it's not good
practice to omit them.
You can use accessors such as in_be32 and in_le32 in this situation,
when you have a kernel virtual address that is already mapped to the
device.
> There are some cases where you have to be quite careful about how you
> read and write some control registers, and I think this opens the
> possibility to just be sloppy and make mistakes since the read/write
> is hidden within the macro.
Here you're talking about the setbit/clrbit macros which combine
read/write.
Its simply for the sake of readability, since the C text for
"out_be32(xxx, in_be32(xxx) |& zzzz)" is quite large.
Do you think that the macro is a potential for introduction
of mistakes?
We don't have any synchronization between read-modify-write
operations to conf. registers now, can you mention the cases
where read and write need some sort of synchronization?
In any way, those can just not use the macros, right?
Sincerely, I don't care very much for setbit/clrbit macros,
I just think that they make the code easier to read.
> >Does anyone have hardware to test it? Dan?
>
> Yes, I have hardware to test it. I will do that one of these days.
OK ;)
^ permalink raw reply
* Re: [PATCH] 8xx PCMCIA: support for MPC885ADS and MPC866ADS
From: Marcelo Tosatti @ 2005-11-23 15:13 UTC (permalink / raw)
To: Dan Malek; +Cc: Vitaly Bordug, linuxppc-embedded list
In-Reply-To: <24aa4090f558206fa04f9d584c590034@embeddededge.com>
On Wed, Nov 23, 2005 at 03:22:40PM -0500, Dan Malek wrote:
>
> On Nov 23, 2005, at 7:53 AM, Marcelo Tosatti wrote:
>
> >Shouldnt you handle ioremap() failure? Most 85xx code written
> >by Kumar also does not.
>
> And do what if it fails? Chances are you don't have any
> way to report an error message or panic at this point. In
> fact, there are a few silly tests like this where the
> failure tries to panic or print some message that will never
> be seen. Fortunately, the code will never fail and we will
> never take such code paths.
OK! Was talking BS then.
^ permalink raw reply
* Re: [PATCH] 8xx PCMCIA: support for MPC885ADS and MPC866ADS
From: Dan Malek @ 2005-11-23 20:22 UTC (permalink / raw)
To: Marcelo Tosatti; +Cc: Vitaly Bordug, linuxppc-embedded list
In-Reply-To: <20051123125326.GB4526@logos.cnet>
On Nov 23, 2005, at 7:53 AM, Marcelo Tosatti wrote:
> Shouldnt you handle ioremap() failure? Most 85xx code written
> by Kumar also does not.
And do what if it fails? Chances are you don't have any
way to report an error message or panic at this point. In
fact, there are a few silly tests like this where the
failure tries to panic or print some message that will never
be seen. Fortunately, the code will never fail and we will
never take such code paths.
-- Dan
^ permalink raw reply
* Re: [PATCH] generate COFF zImage in arch/powerpc/boot
From: Olaf Hering @ 2005-11-23 20:21 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20051119204742.GA17604@suse.de>
On Sat, Nov 19, Olaf Hering wrote:
> On Sat, Nov 19, Olaf Hering wrote:
>
> > On Sat, Nov 19, Olaf Hering wrote:
> >
> > > This patch on top of yours fixes it for me.
> >
> > Another Makefile fix to actually include the kernel in the zImage.coff.
It just died while uncompressing vmlinux. Some unaligned load.
So we either need a very simple byte by byte memcpy, or my version below.
0 > boot file: 1.1.1.3,coffloading XCOFF
tsize=4D84 dsize=1542B8 bsize=BC80 entry=500000
SECTIONS:
.text 00500000 00500000 00004D84 000000FC
.data 00505000 00505000 001542B8 00004E80
.bss 0065A000 0065A000 0000BC80 00000000
.note.GN 00000000 00000000 00000000 00000000
loading .text, done..
loading .data, done..
clearing .bss, done..
zImage starting: loaded at 0x00500000 (sp: 0x003fff00)
Allocating 0x4b4660 bytes for kernel ...
OF version = 'Open Firmware, 1.0.5'
old OF detected
gunzipping (0x700000 <- 0x505c44:0x6592b8)...DEFAULT CATCH!, code=FFF00600
ok
0 > .registers
Client's Fix Pt Regs:
00 00000001 003FFDF0 00000000 00662183 00629FF6 000039FC 006621C0 9D6528E2
08 7385808D 005023A0 00000002 005055C0 00000060 DEADBEEF DEADBEEF DEADBEEF
10 DEADBEEF DEADBEEF DEADBEEF DEADBEEF DEADBEEF 00662183 000039FD 00000000
18 003FFE80 0002F2FF 0065A45C 0062D9B6 00000000 00000000 0050DBC0 000039FD
Special Regs:
%IV: 00000600 %SRR0: 005001C8 %SRR1: 00003070 %MQ: 00000000
%CR: 50000055 %LR: 005023F4 %CTR: 00000737 %XER: E000BE6F
%DAR: 00629FFE %DSISR: 00004104 %SDR1: 004E0000
ok
0 > reset-all
00000000005001a8 <memcpy>:
5001a8: 54 a7 e8 ff rlinm. r7,r5,29,3,31
5001ac: 38 c3 ff fc cal r6,-4(r3)
5001b0: 38 84 ff fc cal r4,-4(r4)
5001b4: 41 82 00 28 beq 5001dc <memcpy+0x34>
5001b8: 70 c0 00 03 andil. r0,r6,3
5001bc: 7c e9 03 a6 mtctr r7
5001c0: 40 82 00 54 bne 500214 <memcpy+0x6c>
5001c4: 80 e4 00 04 l r7,4(r4)
5001c8: 85 04 00 08 lu r8,8(r4)
5001cc: 90 e6 00 04 st r7,4(r6)
5001d0: 95 06 00 08 stu r8,8(r6)
5001d4: 42 00 ff f0 bdn 5001c4 <memcpy+0x1c>
arch/powerpc/boot/string.S | 121 +++++++++++++++++++++++++---------------
Index: linux-2.6.15-rc1-olh/arch/powerpc/boot/string.S
===================================================================
--- linux-2.6.15-rc1-olh.orig/arch/powerpc/boot/string.S
+++ linux-2.6.15-rc1-olh/arch/powerpc/boot/string.S
@@ -98,88 +98,124 @@ memset:
.globl memmove
memmove:
+ cmpwi 0,r5,0
+ beqlr
cmplw 0,r3,r4
bgt backwards_memcpy
/* fall through */
.globl memcpy
memcpy:
+ cmpwi 0,r5,0
+ beqlr
+ andi. r0,r4,3 /* get src word aligned */
+ beq 20f
+10: subfic r0,r0,4
+ cmpd r0,r5
+ blt 11f
+ mr r0,r5
+11: mtctr r0
+12: lbz r7,0(r4)
+ stb r7,0(r3)
+ addi r4,r4,1
+ addi r3,r3,1
+ bdnz 12b
+ subf. r5,r0,r5
+ beqlr
+20: andi. r0,r3,3 /* get dest word aligned */
+ beq 30f
+ subfic r0,r0,4
+ cmpd r0,r5
+ blt 21f
+ mr r0,r5
+21: mtctr r0
+22: lbz r7,0(r4)
+ stb r7,0(r3)
+ addi r4,r4,1
+ addi r3,r3,1
+ bdnz 22b
+ subf. r5,r0,r5
+ beqlr
+ andi. r0,r4,3 /* get src word aligned */
+ bne 10b
+30:
rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */
addi r6,r3,-4
addi r4,r4,-4
- beq 2f /* if less than 8 bytes to do */
- andi. r0,r6,3 /* get dest word aligned */
+ beq 32f /* if less than 8 bytes to do */
mtctr r7
- bne 5f
-1: lwz r7,4(r4)
+31: lwz r7,4(r4)
lwzu r8,8(r4)
stw r7,4(r6)
stwu r8,8(r6)
- bdnz 1b
+ bdnz 31b
andi. r5,r5,7
-2: cmplwi 0,r5,4
- blt 3f
+32: cmplwi 0,r5,4
+ blt 33f
lwzu r0,4(r4)
addi r5,r5,-4
stwu r0,4(r6)
-3: cmpwi 0,r5,0
+33: cmpwi 0,r5,0
beqlr
mtctr r5
addi r4,r4,3
addi r6,r6,3
-4: lbzu r0,1(r4)
+34: lbzu r0,1(r4)
stbu r0,1(r6)
- bdnz 4b
+ bdnz 34b
blr
-5: subfic r0,r0,4
- mtctr r0
-6: lbz r7,4(r4)
- addi r4,r4,1
- stb r7,4(r6)
- addi r6,r6,1
- bdnz 6b
- subf r5,r0,r5
- rlwinm. r7,r5,32-3,3,31
- beq 2b
- mtctr r7
- b 1b
.globl backwards_memcpy
backwards_memcpy:
- rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */
add r6,r3,r5
add r4,r4,r5
- beq 2f
- andi. r0,r6,3
+
+ andi. r0,r4,3 /* get src word aligned */
+ beq 20f
+10: cmpd r0,r5
+ blt 11f
+ mr r0,r5
+11: mtctr r0
+12: lbzu r7,-1(r4)
+ stbu r7,-1(r6)
+ bdnz 12b
+ subf. r5,r0,r5
+ beqlr
+20: andi. r0,r6,3 /* get dest word aligned */
+ beq 30f
+ cmpd r0,r5
+ blt 21f
+ mr r0,r5
+21: mtctr r0
+22: lbzu r7,-1(r4)
+ stbu r7,-1(r6)
+ bdnz 22b
+ subf. r5,r0,r5
+ beqlr
+ andi. r0,r4,3 /* get src word aligned */
+ bne 10b
+30:
+ rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */
+ beq 32f
mtctr r7
- bne 5f
-1: lwz r7,-4(r4)
+31: lwz r7,-4(r4)
lwzu r8,-8(r4)
stw r7,-4(r6)
stwu r8,-8(r6)
- bdnz 1b
+ bdnz 31b
andi. r5,r5,7
-2: cmplwi 0,r5,4
- blt 3f
+32: cmplwi 0,r5,4
+ blt 33f
lwzu r0,-4(r4)
subi r5,r5,4
stwu r0,-4(r6)
-3: cmpwi 0,r5,0
+33: cmpwi 0,r5,0
beqlr
mtctr r5
-4: lbzu r0,-1(r4)
+34: lbzu r0,-1(r4)
stbu r0,-1(r6)
- bdnz 4b
+ bdnz 34b
blr
-5: mtctr r0
-6: lbzu r7,-1(r4)
- stbu r7,-1(r6)
- bdnz 6b
- subf r5,r0,r5
- rlwinm. r7,r5,32-3,3,31
- beq 2b
- mtctr r7
- b 1b
.globl memcmp
memcmp:
--
short story of a lazy sysadmin:
alias appserv=wotan
^ permalink raw reply
* Re: [PATCH] ppc32: 8xx board-specific platform stuff for fs_enet
From: Dan Malek @ 2005-11-23 20:18 UTC (permalink / raw)
To: Marcelo Tosatti; +Cc: linuxppc-embedded list, Paul Mackerras
In-Reply-To: <20051123120033.GA3551@logos.cnet>
On Nov 23, 2005, at 7:00 AM, Marcelo Tosatti wrote:
> The files in arch/ppc/8xx_io/ (which is what I think you refer to as
> candidates for drivers/), are:
I don't particularly like these macros, but I'm tired of fighting
about it. If you follow the usage path, you will see it's only
used in the CPM drivers, and I wish people would just use
the data structure pointers to access these ports/bits with
standard C code and then place any synchronization
instructions properly. There are some cases where you
have to be quite careful about how you read and write
some control registers, and I think this opens the possibility
to just be sloppy and make mistakes since the read/write
is hidden within the macro.
> Does anyone have hardware to test it? Dan?
Yes, I have hardware to test it. I will do that one of these days.
Thanks.
-- Dan
^ permalink raw reply
* Re: Freescale 8541 support
From: Wolfgang Denk @ 2005-11-23 20:14 UTC (permalink / raw)
To: Dan Wilson; +Cc: linuxppc-embedded
In-Reply-To: <200511230816400937.2B36A589@smtp.dslextreme.com>
In message <200511230816400937.2B36A589@smtp.dslextreme.com> you wrote:
>
> Thanks for the reply! Unfortunately, I am constrained to use the 2.4
> kernel by another software package that I have to use, which doesn't yet
> support 2.6. It appears to me that the 8541/8555 support was put into 2.6
> and never back-ported to 2.4. I'll take a look at the manuals today and
Yes. We will add specific board support for the 8541/8555 (in terms
of the TQM8541 and TQM8555 boards) to our 2.6 git repository in a few
days, but we don't have any intentions to support these boards in our
2.4 tree (unless you pay us for it, of course :-)
> compare the 8540 to the 8541: perhaps I can live with the 8540 support
> that does appear to be in the 2.4 kernel. If not, hopefully the porting
> job won't be very difficult.
It's just a routine job, but it takes time and resources, and you
have to decide if it makes sense to invest these in a kernel tree
that will not be developed any further.
Best regards,
Wolfgang Denk
--
Software Engineering: Embedded and Realtime Systems, Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
Our business is run on trust. We trust you will pay in advance.
^ permalink raw reply
* Re: Freescale 8541 support
From: Dan Malek @ 2005-11-23 20:07 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-embedded
In-Reply-To: <876043CF-5CC2-409D-A543-8C90C5E92097@kernel.crashing.org>
On Nov 23, 2005, at 11:19 AM, Kumar Gala wrote:
> I believe the linuxppc-dev 2.4 tree had support for the MPC8541/55.
Yes, it does. If anyone spends more than a couple of hours,
or does anything that isn't board specific, you are probably
headed down the wrong path. :-)
-- Dan
^ permalink raw reply
* Re: [PATCH] powerpc: Add support for building uImages
From: Sam Ravnborg @ 2005-11-23 18:55 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <Pine.LNX.4.44.0511231242510.4183-100000@gate.crashing.org>
On Wed, Nov 23, 2005 at 12:43:15PM -0600, Kumar Gala wrote:
> +
> +$(obj)/uImage: $(obj)/vmlinux.gz
> + $(Q)rm -f $@
> + $(call if_changed,uimage)
> + @echo -n ' Image: $@ '
> + @if [ -f $@ ]; then echo 'is ready' ; else echo 'not made'; fi
The above is suboptimal. The $(call if_changed,uimage) will execute
$(cmd_uimage) if 1) prerequisites has changed or 2) the command to execute
has changed.
In the above case 1) is always true, otherwise we would not reach the
statement. So change it to $(call cmd,uimage) is the correct way.
The 'bug' is also present in ppc/boot/images
Sam
^ permalink raw reply
* RE: [PATCH] I2C: Add I2C support for the MPC8260
From: Kumar Gala @ 2005-11-23 19:06 UTC (permalink / raw)
To: Heiko Schocher; +Cc: linuxppc-dev, lm-sensors
In-Reply-To: <AHEILKONAKAEJPHNMOPNEEMNCDAA.hs@denx.de>
On Wed, 23 Nov 2005, Heiko Schocher wrote:
* There is a bunch of code commented out in one form or another, is this
needed?
* Single line comment style
* some other comments are inline.
- kumar
> Hello
>
> On Wednesday, November 23, 2005 8:01 AM Kumar Gala wrote:
> > Can we rename the driver from mpc8260 -> cpm2. The driver should work
> > on any device that has a "CPM2" which includes a number of MPC82xx
> > and MPC85xx processors. So calling it and its config options, etc
> > MPC8260 is going to be confusing to users.
>
> [PATCH] I2C: Add I2C Bus support for MPC with CPM2.
>
> Signed-off-by: Heiko Schocher <hs@denx.de>
>
> ---
>
> drivers/i2c/busses/Kconfig | 10 +
> drivers/i2c/busses/Makefile | 1
> drivers/i2c/busses/i2c-cpm2.c | 616 +++++++++++++++++++++++++++++++++++++++++
> include/linux/i2c-algo-cpm2.h | 26 ++
> include/linux/i2c-id.h | 3
> 5 files changed, 656 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> index 4010fe9..2acb4cc 100644
> --- a/drivers/i2c/busses/Kconfig
> +++ b/drivers/i2c/busses/Kconfig
> @@ -270,6 +270,16 @@ config I2C_MPC
> This driver can also be built as a module. If so, the module
> will be called i2c-mpc.
>
> +config I2C_CPM2
> + tristate "CPM2"
> + depends on I2C && PPC32
it should really depend on CPM2 being set not PPC32.
> + help
> + If you say yes to this option, support will be included for the
> + I2C interface on PPC with CPM2
> +
> + This driver can also be built as a module. If so, the module
> + will be called i2c-cpm2.
> +
> config I2C_NFORCE2
> tristate "Nvidia nForce2, nForce3 and nForce4"
> depends on I2C && PCI
> diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
> index f1df00f..a4c1b69 100644
> --- a/drivers/i2c/busses/Makefile
> +++ b/drivers/i2c/busses/Makefile
> @@ -43,6 +43,7 @@ obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o
> obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o
> obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
> obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
> +obj-$(CONFIG_I2C_CPM2) += i2c-cpm2.o
>
> ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
> EXTRA_CFLAGS += -DDEBUG
> diff --git a/drivers/i2c/busses/i2c-cpm2.c b/drivers/i2c/busses/i2c-cpm2.c
> new file mode 100644
> index 0000000..80dc532
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-cpm2.c
> @@ -0,0 +1,616 @@
> +/*
> + * (C) Copyright 2005
> + * Heiko Schocher <hs@denx.de>
> + *
> + * This is a combined i2c adapter and algorithm driver for
> + * PPC with CPM2
> + *
> + * Release 0.1
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/config.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/sched.h>
> +#include <linux/init.h>
> +#include <linux/pci.h>
> +#include <asm/io.h>
> +#include <linux/fsl_devices.h>
> +#include <linux/i2c.h>
> +#include <linux/interrupt.h>
> +#include <linux/delay.h>
> +#include <asm/immap_cpm2.h>
> +#include <asm/mpc8260.h>
> +#include <asm/cpm2.h>
> +
> +#include <linux/i2c-algo-cpm2.h>
> +#include <linux/platform_device.h>
> +
> +#define CPM_MAX_READ 513
> +
> +static wait_queue_head_t iic_wait;
> +static ushort r_tbase, r_rbase;
> +
> +int cpm_scan = 0;
> +int cpm_debug = 0;
> +
It would be nice to rename the struct so its unique between i2c-mpc and
i2c-cpm2. Since its reasonable for both drivers to exist in a system.
> +struct mpc_i2c {
> + u32 interrupt;
> + wait_queue_head_t queue;
> + struct i2c_adapter adap;
> + int irq;
> + u32 flags;
> + struct i2c_algo_cpm2_data *data;
> +};
> +
> +static struct i2c_algo_cpm2_data cpm2_data;
> +
> +static void
> +cpm2_iic_init(struct i2c_algo_cpm2_data *data)
> +{
> + volatile cpm_cpm2_t *cp;
> + volatile cpm2_map_t *immap;
> +
> + cp = cpmp; /* Get pointer to Communication Processor */
> + immap = (cpm2_map_t *)CPM_MAP_ADDR; /* and to internal registers */
> +
> + *(ushort *)(&immap->im_dprambase[PROFF_I2C_BASE]) = PROFF_I2C;
> + data->iip = (iic_t *)&immap->im_dprambase[PROFF_I2C];
> +
> + data->i2c = (i2c_cpm2_t *)&(immap->im_i2c);
> + data->cp = cp;
> +
> + /* Initialize Port D IIC pins.
> + */
> + immap->im_ioport.iop_ppard |= 0x00030000;
> + immap->im_ioport.iop_pdird &= ~0x00030000;
> + immap->im_ioport.iop_podrd |= 0x00030000;
> + immap->im_ioport.iop_psord |= 0x00030000;
> +
> + /* Allocate space for two transmit and two receive buffer
> + * descriptors in the DP ram.
> + */
> + data->dp_addr = cpm_dpalloc(sizeof(cbd_t) * 4, 8);
> +
> + /* ptr to i2c area */
> + data->i2c = (i2c_cpm2_t *)&(((cpm2_map_t *)CPM_MAP_ADDR)->im_i2c);
> +}
> +
> +static irqreturn_t cpm2_i2c_isr(int irq, void *dev_id, struct pt_regs *regs)
> +{
> + struct mpc_i2c *mpc_i2c = dev_id;
> + struct i2c_algo_cpm2_data *cpm_adap = mpc_i2c->data;
> + volatile i2c_cpm2_t *i2c = cpm_adap->i2c;
> +
> + if (cpm_debug > 1)
> + printk(KERN_DEBUG "cpm_iic_interrupt(dev_id=%p)\n", dev_id);
> +
> + /* Clear interrupt.
> + */
> + i2c->i2c_i2cer = 0xff;
> +
> + /* Get 'me going again.
> + */
> + wake_up_interruptible(&iic_wait);
> + return IRQ_HANDLED;
> +}
> +
> +
> +static void
> +cpm_iic_init(struct i2c_algo_cpm2_data *cpm_adap)
> +{
> + volatile iic_t *iip = cpm_adap->iip;
> + volatile i2c_cpm2_t *i2c = cpm_adap->i2c;
> +
> + if (cpm_debug) printk(KERN_DEBUG "cpm_iic_init() - iip=%p\n",iip);
> +
> + /* Initialize the parameter ram.
> + * We need to make sure many things are initialized to zero,
> + * especially in the case of a microcode patch.
> + */
> + iip->iic_rstate = 0;
> + iip->iic_rdp = 0;
> + iip->iic_rbptr = 0;
> + iip->iic_rbc = 0;
> + iip->iic_rxtmp = 0;
> + iip->iic_tstate = 0;
> + iip->iic_tdp = 0;
> + iip->iic_tbptr = 0;
> + iip->iic_tbc = 0;
> + iip->iic_txtmp = 0;
> +
> + /* Set up the IIC parameters in the parameter ram.
> + */
> + iip->iic_tbase = r_tbase = cpm_adap->dp_addr;
> + iip->iic_rbase = r_rbase = cpm_adap->dp_addr + sizeof(cbd_t)*2;
> +
> + iip->iic_tfcr = CPMFCR_GBL | CPMFCR_EB;
> + iip->iic_rfcr = CPMFCR_GBL | CPMFCR_EB;
> +
> + /* Set maximum receive size.
> + */
> + iip->iic_mrblr = CPM_MAX_READ;
> +
> + /* Initialize Tx/Rx parameters.
> + */
> + {
> + volatile cpm_cpm2_t *cp = cpm_adap->cp;
> + cp->cp_cpcr =
> + mk_cr_cmd(CPM_CR_I2C_PAGE, CPM_CR_I2C_SBLOCK, 0x00, CPM_CR_INIT_TRX) | CPM_CR_FLG;
> + while (cp->cp_cpcr & CPM_CR_FLG);
> + }
> +
> + /* Select an arbitrary address. Just make sure it is unique.
> + */
> + i2c->i2c_i2add = 0x34;
> +
> + /* Divider is 2 * ( 15 + 3 )
> + */
> + i2c->i2c_i2brg = 0x0f;
> +
> + /* Pre-divider is BRGCLK/4
> + */
> + i2c->i2c_i2mod = 0x06;
> +
> + /* Disable interrupts.
> + */
> + i2c->i2c_i2cmr = 0;
> + i2c->i2c_i2cer = 0xff;
> +
> + init_waitqueue_head(&iic_wait);
> +}
> +
> +
> +#if 0
> +static int
> +cpm_iic_shutdown(struct i2c_algo_cpm2_data *cpm_adap)
> +{
> + volatile i2c_cpm2_t *i2c = cpm_adap->i2c;
> +
> + /* Shut down IIC.
> + */
> + i2c->i2c_i2mod = 0;
> + i2c->i2c_i2cmr = 0;
> + i2c->i2c_i2cer = 0xff;
> +
> + return(0);
> +}
> +#endif
> +
> +static void
> +cpm_reset_iic_params(volatile iic_t *iip)
> +{
> + iip->iic_tbase = r_tbase;
> + iip->iic_rbase = r_rbase;
> +
> + iip->iic_tfcr = CPMFCR_GBL | CPMFCR_EB;
> + iip->iic_rfcr = CPMFCR_GBL | CPMFCR_EB;
> +
> + iip->iic_mrblr = CPM_MAX_READ;
> +
> + iip->iic_rstate = 0;
> + iip->iic_rdp = 0;
> + iip->iic_rbptr = 0;
> + iip->iic_rbc = 0;
> + iip->iic_rxtmp = 0;
> + iip->iic_tstate = 0;
> + iip->iic_tdp = 0;
> + iip->iic_tbptr = 0;
> + iip->iic_tbc = 0;
> + iip->iic_txtmp = 0;
> +}
> +
> +#define BD_SC_NAK ((ushort)0x0004) /* NAK - did not respond */
> +#define CPM_CR_CLOSE_RXBD ((ushort)0x0007)
> +
> +static void force_close(struct i2c_algo_cpm2_data *cpm)
> +{
> +#if 0
> + volatile cpm_cpm2_t *cp = cpm->cp;
> +
> + if (cpm_debug) printk(KERN_DEBUG "force_close()\n");
> + cp->cp_cpcr =
> + mk_cr_cmd(CPM_CR_CH_I2C, CPM_CR_CLOSE_RXBD) |
> + CPM_CR_FLG;
> +
> + while (cp->cp_cpcr & CPM_CR_FLG);
> +#endif
> +}
> +
> +
> +/* Read from IIC...
> + * abyte = address byte, with r/w flag already set
> + */
> +static int
> +cpm_iic_read(struct i2c_algo_cpm2_data *cpm, u_char abyte, char *buf, int count)
> +{
> + volatile cpm2_map_t *immap = (cpm2_map_t *)CPM_MAP_ADDR;
> + volatile iic_t *iip = cpm->iip;
> + volatile i2c_cpm2_t *i2c = cpm->i2c;
> + volatile cbd_t *tbdf, *rbdf;
> + u_char *tb;
> + unsigned long flags;
> +
> + if (count >= CPM_MAX_READ)
> + return -EINVAL;
> +
> + tbdf = (cbd_t *)&immap->im_dprambase[iip->iic_tbase];
> + rbdf = (cbd_t *)&immap->im_dprambase[iip->iic_rbase];
> +
> + /* To read, we need an empty buffer of the proper length.
> + * All that is used is the first byte for address, the remainder
> + * is just used for timing (and doesn't really have to exist).
> + */
> + if (/*cpm->reloc*/0) {
> + cpm_reset_iic_params(iip);
> + }
> + tb = cpm->temp;
> + tb = (u_char *)(((uint)tb + 15) & ~15);
> + tb[0] = abyte; /* Device address byte w/rw flag */
> +
> + dma_cache_wback_inv (tb, 1);
> +
> + if (cpm_debug) printk(KERN_DEBUG "cpm_iic_read(abyte=0x%x)\n", abyte);
> +
> + tbdf->cbd_bufaddr = __pa(tb);
> + tbdf->cbd_datlen = count + 1;
> + tbdf->cbd_sc =
> + BD_SC_READY | BD_SC_INTRPT | BD_SC_LAST |
> + BD_SC_WRAP | BD_IIC_START;
> +
> + rbdf->cbd_datlen = 0;
> + rbdf->cbd_bufaddr = __pa(buf);
> + rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
> +
> + if (count > 0 && count < CPM_MAX_READ)
> + iip->iic_mrblr = count; /* prevent excessive read */
> +
> + dma_cache_inv (buf, count);
> +
> + /* Chip bug, set enable here */
> + local_irq_save(flags);
> + i2c->i2c_i2cmr = 0x13; /* Enable some interupts */
> + i2c->i2c_i2cer = 0xff;
> + i2c->i2c_i2mod |= 1; /* Enable */
> + i2c->i2c_i2com = 0x81; /* Start master */
> +
> + /* Wait for IIC transfer */
> + interruptible_sleep_on(&iic_wait);
> + local_irq_restore(flags);
> + if (signal_pending(current))
> + return -EIO;
> +
> + if (cpm_debug) {
> + printk(KERN_DEBUG "tx sc %04x, rx sc %04x\n",
> + tbdf->cbd_sc, rbdf->cbd_sc);
> + }
> +
> + if (tbdf->cbd_sc & BD_SC_NAK) {
> + printk(KERN_INFO "IIC read; no ack\n");
> + return 0;
> + }
> +
> + if (rbdf->cbd_sc & BD_SC_EMPTY) {
> + printk(KERN_INFO "IIC read; complete but rbuf empty\n");
> + force_close(cpm);
> + printk(KERN_INFO "tx sc %04x, rx sc %04x\n",
> + tbdf->cbd_sc, rbdf->cbd_sc);
> + }
> +
> + if (cpm_debug) printk(KERN_DEBUG "read %d bytes\n", rbdf->cbd_datlen);
> +
> + if (rbdf->cbd_datlen < count) {
> + printk(KERN_INFO "IIC read; short, wanted %d got %d\n",
> + count, rbdf->cbd_datlen);
> + return 0;
> + }
> + if (cpm_debug) {
> + int u;
> + for (u = 0; u < count; u++) {
> + printk(KERN_DEBUG "buf[%d] = 0x%x\n", u, buf[u]);
> + }
> + }
> +
> +
> + return count;
> +}
> +
> +/* Write to IIC...
> + * addr = address byte, with r/w flag already set
> + */
> +static int
> +cpm_iic_write(struct i2c_algo_cpm2_data *cpm, u_char abyte, char *buf,int count)
> +{
> + volatile cpm2_map_t *immap = (cpm2_map_t *)CPM_MAP_ADDR;
> + volatile iic_t *iip = cpm->iip;
> + volatile i2c_cpm2_t *i2c = cpm->i2c;
> + volatile cbd_t *tbdf;
> + u_char *tb;
> + unsigned long flags;
> +
> + tb = cpm->temp;
> + tb = (u_char *)(((uint)tb + 15) & ~15);
> + *tb = abyte; /* Device address byte w/rw flag */
> +
> + dma_cache_wback_inv (tb, 1);
> + dma_cache_wback_inv (buf, count);
> +
> + if (cpm_debug) printk(KERN_DEBUG "cpm_iic_write(abyte=0x%x)\n", abyte);
> + if (cpm_debug) printk(KERN_DEBUG "buf[0] = 0x%x, buf[1] = 0x%x\n", buf[0], buf[1]);
> +
> + /* set up 2 descriptors */
> + tbdf = (cbd_t *)&immap->im_dprambase[iip->iic_tbase];
> +
> + tbdf[0].cbd_bufaddr = __pa(tb);
> + tbdf[0].cbd_datlen = 1;
> + tbdf[0].cbd_sc = BD_SC_READY | BD_IIC_START;
> +
> + tbdf[1].cbd_bufaddr = __pa(buf);
> + tbdf[1].cbd_datlen = count;
> + tbdf[1].cbd_sc = BD_SC_READY | BD_SC_INTRPT | BD_SC_LAST | BD_SC_WRAP;
> +
> + /* Chip bug, set enable here */
> + local_irq_save(flags);;
> + i2c->i2c_i2cmr = 0x13; /* Enable some interupts */
> + i2c->i2c_i2cer = 0xff;
> + i2c->i2c_i2mod |= 1; /* Enable */
> + i2c->i2c_i2com = 0x81; /* Start master */
> +
> + /* Wait for IIC transfer */
> + interruptible_sleep_on(&iic_wait);
> + local_irq_restore(flags);
> + if (signal_pending(current))
> + return -EIO;
> +
> + if (cpm_debug) {
> + printk(KERN_DEBUG "tx0 sc %04x, tx1 sc %04x\n",
> + tbdf[0].cbd_sc, tbdf[1].cbd_sc);
> + }
> +
> + if (tbdf->cbd_sc & BD_SC_NAK) {
> + printk(KERN_INFO "IIC write; no ack\n");
> + return 0;
> + }
> +
> + if (tbdf->cbd_sc & BD_SC_READY) {
> + printk(KERN_INFO "IIC write; complete but tbuf ready\n");
> + return 0;
> + }
> +
> + return count;
> +}
> +
> +#if 0
> +/* See if an IIC address exists..
> + * addr = 7 bit address, unshifted
> + */
> +static int
> +cpm_iic_tryaddress(struct i2c_algo_cpm2_data *cpm, int addr)
> +{
> + volatile cpm2_map_t *immap = (cpm2_map_t *)CPM_MAP_ADDR;
> + volatile iic_t *iip = cpm->iip;
> + volatile i2c_cpm2_t *i2c = cpm->i2c;
> + volatile cbd_t *tbdf, *rbdf;
> + u_char *tb;
> + unsigned long flags, len;
> +
> + if (cpm_debug > 1)
> + printk(KERN_DEBUG "cpm_iic_tryaddress(cpm=%p,addr=%d)\n", cpm, addr);
> +
> + if (cpm_debug && addr == 0) {
> + printk(KERN_DEBUG "iip %p, dp_addr 0x%x\n", cpm->iip, cpm->dp_addr);
> + printk(KERN_DEBUG "iic_tbase %d, r_tbase %d\n", iip->iic_tbase, r_tbase);
> + }
> +
> + tbdf = (cbd_t *)&immap->im_dprambase[iip->iic_tbase];
> + rbdf = (cbd_t *)&immap->im_dprambase[iip->iic_rbase];
> +
> + tb = cpm->temp;
> + tb = (u_char *)(((uint)tb + 15) & ~15);
> +
> + /* do a simple read */
> + tb[0] = (addr << 1) | 1; /* device address (+ read) */
> + len = 2;
> +
> + dma_cache_wback_inv (tb, 1);
> +
> + tbdf->cbd_bufaddr = __pa(tb);
> + tbdf->cbd_datlen = len;
> + tbdf->cbd_sc =
> + BD_SC_READY | BD_SC_INTRPT | BD_SC_LAST |
> + BD_SC_WRAP | BD_IIC_START;
> +
> + rbdf->cbd_datlen = 0;
> + rbdf->cbd_bufaddr = __pa(tb+2);
> + rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
> +
> + local_irq_save(flags);
> + i2c->i2c_i2cmr = 0x13; /* Enable some interupts */
> + i2c->i2c_i2cer = 0xff;
> + i2c->i2c_i2mod |= 1; /* Enable */
> + i2c->i2c_i2com = 0x81; /* Start master */
> +
> + if (cpm_debug > 1) printk(KERN_DEBUG "about to sleep\n");
> +
> + /* wait for IIC transfer */
> + interruptible_sleep_on(&iic_wait);
> + local_irq_restore(flags);
> + if (signal_pending(current))
> + return -EIO;
> +
> + if (cpm_debug > 1) printk(KERN_DEBUG "back from sleep\n");
> +
> + if (tbdf->cbd_sc & BD_SC_NAK) {
> + if (cpm_debug > 1) printk(KERN_DEBUG "IIC try; no ack\n");
> + return 0;
> + }
> +
> + if (tbdf->cbd_sc & BD_SC_READY) {
> + printk(KERN_INFO "IIC try; complete but tbuf ready\n");
> + }
> +
> + return 1;
> +}
> +#endif
> +
> +static int cpm2_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
> +{
> + struct i2c_msg *pmsg;
> + int i;
> + int ret = 0;
> + struct mpc_i2c *mpc_i2c = i2c_get_adapdata(adap);
> + struct i2c_algo_cpm2_data *data = mpc_i2c->data;
> + u_char addr;
> +
> + for (i = 0; i < num; i++) {
> + pmsg = &msgs[i];
> +
> + if (cpm_debug)
> + printk(KERN_DEBUG "i2c-cpm2.o: "
> + "#%d addr=0x%x flags=0x%x len=%d\n",
> + i, pmsg->addr, pmsg->flags, pmsg->len);
> +
> + addr = pmsg->addr << 1;
> + if (pmsg->flags & I2C_M_RD )
> + addr |= 1;
> + if (pmsg->flags & I2C_M_REV_DIR_ADDR )
> + addr ^= 1;
> +
> + if (!(pmsg->flags & I2C_M_NOSTART)) {
> + }
> + if (pmsg->flags & I2C_M_RD ) {
> + /* read bytes into buffer*/
> + ret = cpm_iic_read(data, addr, pmsg->buf, pmsg->len);
> + if (cpm_debug)
> + printk(KERN_DEBUG "i2c-cpm2.o: read %d bytes\n", ret);
> + if (ret < pmsg->len ) {
> + return (ret<0)? ret : -EREMOTEIO;
> + }
> + } else {
> + /* write bytes from buffer */
> + ret = cpm_iic_write(data, addr, pmsg->buf, pmsg->len);
> + if (cpm_debug)
> + printk(KERN_DEBUG "i2c-cpm2.o: wrote %d\n", ret);
> + if (ret < pmsg->len ) {
> + return (ret<0) ? ret : -EREMOTEIO;
> + }
> + }
> + }
> + return (ret < 0) ? ret : num;
> +}
> +
> +static u32 cpm2_functionality(struct i2c_adapter *adap)
> +{
> + return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR |
> + I2C_FUNC_PROTOCOL_MANGLING;
> +}
> +
> +static struct i2c_algorithm cpm2_algo = {
> + .master_xfer = cpm2_xfer,
> + .functionality = cpm2_functionality,
> +};
> +
> +static struct i2c_adapter cpm2_ops = {
> + .owner = THIS_MODULE,
> + .name = "MPC CPM2 adapter",
> + .id = I2C_HW_MPC82xx,
> + .algo = &cpm2_algo,
> + .class = I2C_CLASS_HWMON,
> + .timeout = 1,
> + .retries = 1
> +};
> +
> +static int fsl_i2c_probe(struct device *device)
> +{
> + int result = 0;
> + struct mpc_i2c *i2c;
> + struct platform_device *pdev = to_platform_device(device);
> + struct fsl_i2c_platform_data *pdata;
> +
> + pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data;
> +
> + if (!(i2c = kmalloc(sizeof(*i2c), GFP_KERNEL))) {
> + return -ENOMEM;
> + }
> + memset(i2c, 0, sizeof(*i2c));
> +
> + i2c->data = &cpm2_data;
> + /* CPM Plattform initialisation */
> + cpm2_iic_init (i2c->data);
> + /* CPM init */
> + cpm_iic_init (i2c->data);
> + i2c->irq = platform_get_irq(pdev, 0);
> +
> + if (i2c->irq != 0) {
> + if ((result = request_irq(i2c->irq, cpm2_i2c_isr,
> + SA_SHIRQ, "i2c-mpc", i2c)) < 0) {
> + printk(KERN_ERR
> + "i2c-mpc - failed to attach interrupt\n");
> + goto fail_irq;
> + }
> + }
> + dev_set_drvdata(device, i2c);
> +
> + i2c->adap = cpm2_ops;
> + i2c_set_adapdata(&i2c->adap, i2c);
> + i2c->adap.dev.parent = &pdev->dev;
> + if ((result = i2c_add_adapter(&i2c->adap)) < 0) {
> + printk(KERN_ERR "i2c-mpc - failed to add adapter\n");
> + goto fail_add;
> + }
> +
> + return result;
> +
> + fail_add:
> + if (i2c->irq != 0)
> + free_irq(i2c->irq, NULL);
> + fail_irq:
> + kfree(i2c);
> + return result;
> +};
> +
> +static int fsl_i2c_remove(struct device *device)
> +{
> + struct mpc_i2c *i2c = dev_get_drvdata(device);
> +
> + cpm_dpfree (i2c->data->dp_addr);
> +
> + i2c_del_adapter(&i2c->adap);
> + dev_set_drvdata(device, NULL);
> +
> + if (i2c->irq != 0)
> + free_irq(i2c->irq, i2c);
> +
> + kfree(i2c);
> + return 0;
> +};
> +
> +/* Structure for a device driver */
> +static struct device_driver fsl_i2c_driver = {
> + .name = "fsl-cpm-i2c",
> + .bus = &platform_bus_type,
> + .probe = fsl_i2c_probe,
> + .remove = fsl_i2c_remove,
> +};
> +
> +static int __init fsl_i2c_init(void)
> +{
> + return driver_register(&fsl_i2c_driver);
> +}
> +
> +static void __exit fsl_i2c_exit(void)
> +{
> + driver_unregister(&fsl_i2c_driver);
> +}
> +
> +module_init(fsl_i2c_init);
> +module_exit(fsl_i2c_exit);
> +
> +MODULE_AUTHOR("Heiko Schocher <hs@denx.de>");
> +MODULE_DESCRIPTION
> + ("I2C-Bus adapter for MPC with CPM2 processors");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/i2c-algo-cpm2.h b/include/linux/i2c-algo-cpm2.h
> new file mode 100644
> index 0000000..f03277c
> --- /dev/null
> +++ b/include/linux/i2c-algo-cpm2.h
> @@ -0,0 +1,26 @@
> +/* ----------------------------------------------------------- */
> +/* i2c-algo-cpm2.h i2c driver algorithms for MPC with CPM2 */
> +/* ----------------------------------------------------------- */
> +
> +/* $Id$ */
> +
> +#ifndef I2C_ALGO_CPM2_H
> +#define I2C_ALGO_CPM2_H 1
> +
> +#include <linux/i2c.h>
> +
> +struct i2c_algo_cpm2_data {
> + uint dp_addr;
> + int reloc;
> + volatile i2c_cpm2_t *i2c;
> + volatile iic_t *iip;
> + volatile cpm_cpm2_t *cp;
> +
> + int (*setisr) (int irq,
> + void (*func)(int, void (*)(void *), void *),
> + void *data);
> +
> + u_char temp[513];
> +};
> +
> +#endif /* I2C_ALGO_CPM2_H */
> diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
> index 1543daa..e7a12cc 100644
> --- a/include/linux/i2c-id.h
> +++ b/include/linux/i2c-id.h
> @@ -223,6 +223,9 @@
> /* --- PowerPC on-chip adapters */
> #define I2C_HW_OCP 0x120000 /* IBM on-chip I2C adapter */
>
> +/* --- MPC82xx PowerPC adapters */
> +#define I2C_HW_MPC82xx 0x100002 /* MPC82xx I2C adapter */
> +
> /* --- Broadcom SiByte adapters */
> #define I2C_HW_SIBYTE 0x150000
>
>
^ permalink raw reply
* [PATCH] powerpc: Fix suboptimal uImage target
From: Kumar Gala @ 2005-11-23 19:03 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, linux-kernel
Sam Ravnborg pointed out that calling if_changed was redudant in the
rule since we a prerequisite had to have change for us to get there.
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
commit b3b2fd54eab2d87dcc29db5c537b5aee2a7732ce
tree 0eba205e3944aca7095fb2723f95e9799be5c853
parent 74dc65dbfa00bb69929c34da2ae788868aaae399
author Kumar Gala <galak@kernel.crashing.org> Wed, 23 Nov 2005 13:04:48 -0600
committer Kumar Gala <galak@kernel.crashing.org> Wed, 23 Nov 2005 13:04:48 -0600
arch/powerpc/boot/Makefile | 2 +-
arch/ppc/boot/images/Makefile | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index dfc7eac..22726ae 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -169,7 +169,7 @@ $(obj)/vmlinux.gz: $(obj)/vmlinux.bin FO
$(obj)/uImage: $(obj)/vmlinux.gz
$(Q)rm -f $@
- $(call if_changed,uimage)
+ $(call cmd,uimage)
@echo -n ' Image: $@ '
@if [ -f $@ ]; then echo 'is ready' ; else echo 'not made'; fi
diff --git a/arch/ppc/boot/images/Makefile b/arch/ppc/boot/images/Makefile
index 532e7ef..58415d5 100644
--- a/arch/ppc/boot/images/Makefile
+++ b/arch/ppc/boot/images/Makefile
@@ -26,7 +26,7 @@ quiet_cmd_uimage = UIMAGE $@
targets += uImage
$(obj)/uImage: $(obj)/vmlinux.gz
$(Q)rm -f $@
- $(call if_changed,uimage)
+ $(call cmd,uimage)
@echo -n ' Image: $@ '
@if [ -f $@ ]; then echo 'is ready' ; else echo 'not made'; fi
^ permalink raw reply related
* Re: [PATCH] powerpc: Add support for building uImages
From: Kumar Gala @ 2005-11-23 19:02 UTC (permalink / raw)
To: Sam Ravnborg; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <20051123185523.GC8336@mars.ravnborg.org>
On Wed, 23 Nov 2005, Sam Ravnborg wrote:
> On Wed, Nov 23, 2005 at 12:43:15PM -0600, Kumar Gala wrote:
> > +
> > +$(obj)/uImage: $(obj)/vmlinux.gz
> > + $(Q)rm -f $@
> > + $(call if_changed,uimage)
> > + @echo -n ' Image: $@ '
> > + @if [ -f $@ ]; then echo 'is ready' ; else echo 'not made'; fi
>
> The above is suboptimal. The $(call if_changed,uimage) will execute
> $(cmd_uimage) if 1) prerequisites has changed or 2) the command to execute
> has changed.
> In the above case 1) is always true, otherwise we would not reach the
> statement. So change it to $(call cmd,uimage) is the correct way.
>
> The 'bug' is also present in ppc/boot/images
thanks. I'll send a follow up patch to fix both cases.
- kumar
^ permalink raw reply
* Re: [PATCH] Fix USB suspend/resume crasher
From: David Brownell @ 2005-11-23 18:58 UTC (permalink / raw)
To: Greg KH; +Cc: Andrew Morton, Linux Kernel list, linuxppc-dev list, Alan Stern
In-Reply-To: <20051123171041.GC26149@kroah.com>
On Wednesday 23 November 2005 9:10 am, Greg KH wrote:
> On Wed, Nov 23, 2005 at 02:08:07PM +1100, Benjamin Herrenschmidt wrote:
> > This patch applies on top of
Ben, I'll look at this patch today.
> > the patch that moves the PowerMac specific
> > code out of ohci-pci.c to hcd-pci.c where it belongs. This patch isn't
> > upstream yet for reasons I don't fully understand (why does USB stuffs
> > has such a high latency for going upstream ?), I'm sending it as a reply
> > to this email for completeness.
>
> Sorry, I hadn't seen it, otherwise I would have sent it on.
>
> David, are you ok with the patch Ben sent on as a followup?
It should be the same as
http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/gregkh-04-usb/usb-ohci-move-ppc-asic-tweaks-nearer-pci.patch
which is already in your queue, just it's not yet upstream.
I posted it before RC1 came out, but evidently not before
your RC1-merge-to-Linus window had closed.
- Dave
^ permalink raw reply
* [PATCH] powerpc: Add support for building uImages
From: Kumar Gala @ 2005-11-23 18:43 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, linux-kernel
powerpc: Add support for building uImages
Add support to build a kernel image bootable by u-boot.
Most of the makefile foo is taken from arch/ppc/boot/images/Makefile
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
commit 74dc65dbfa00bb69929c34da2ae788868aaae399
tree 2344f27b9a84a2c3212c4dcc070f6b0cebb906ef
parent 8573cff663f4df7af110c9781ccefd6b12522a2f
author Kumar Gala <galak@kernel.crashing.org> Wed, 23 Nov 2005 12:44:01 -0600
committer Kumar Gala <galak@kernel.crashing.org> Wed, 23 Nov 2005 12:44:01 -0600
arch/powerpc/Makefile | 2 +-
arch/powerpc/boot/Makefile | 30 ++++++++++++++++++++++++++++++
2 files changed, 31 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index a13eb57..5f80e58 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -151,7 +151,7 @@ CPPFLAGS_vmlinux.lds := -Upowerpc
# All the instructions talk about "make bzImage".
bzImage: zImage
-BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm
+BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm uImage
.PHONY: $(BOOT_TARGETS)
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 9770f58..dfc7eac 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -143,6 +143,36 @@ $(obj)/zImage.initrd: $(obj)/zImage.init
@cp -f $< $@
$(call if_changed,addnote)
+#-----------------------------------------------------------
+# build u-boot images
+#-----------------------------------------------------------
+quiet_cmd_mygzip = GZIP $@
+cmd_mygzip = gzip -f -9 < $< > $@.$$$$ && mv $@.$$$$ $@
+
+quiet_cmd_objbin = OBJCOPY $@
+ cmd_objbin = $(OBJCOPY) -O binary $< $@
+
+quiet_cmd_uimage = UIMAGE $@
+ cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A ppc -O linux -T kernel \
+ -C gzip -a 00000000 -e 00000000 -n 'Linux-$(KERNELRELEASE)' \
+ -d $< $@
+
+MKIMAGE := $(srctree)/scripts/mkuboot.sh
+targets += uImage
+extra-y += vmlinux.bin vmlinux.gz
+
+$(obj)/vmlinux.bin: vmlinux FORCE
+ $(call if_changed,objbin)
+
+$(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE
+ $(call if_changed,mygzip)
+
+$(obj)/uImage: $(obj)/vmlinux.gz
+ $(Q)rm -f $@
+ $(call if_changed,uimage)
+ @echo -n ' Image: $@ '
+ @if [ -f $@ ]; then echo 'is ready' ; else echo 'not made'; fi
+
install: $(CONFIGURE) $(BOOTIMAGE)
sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" "$(BOOTIMAGE)"
^ permalink raw reply related
* Re: [PATCH] ppc32: 8xx board-specific platform stuff for fs_enet
From: 'Aristeu Sergio Rozanski Filho' @ 2005-11-23 18:25 UTC (permalink / raw)
To: Marcelo Tosatti; +Cc: linuxppc-embedded list, Paul Mackerras
In-Reply-To: <20051123120033.GA3551@logos.cnet>
> However there are some PHY descriptions in fec.c which are missing from
> fs_enet - we'd better make sure to have them all in the new driver
> before removing the old one.
>
> Aris, would you mind looking into this?
I'm on it
--
Aristeu
^ permalink raw reply
* Re: [PATCH] 8xx PCMCIA: support for MPC885ADS and MPC866ADS
From: Kumar Gala @ 2005-11-23 18:42 UTC (permalink / raw)
To: Marcelo Tosatti; +Cc: Vitaly Bordug, linuxppc-embedded list
In-Reply-To: <20051123125326.GB4526@logos.cnet>
On Nov 23, 2005, at 6:53 AM, Marcelo Tosatti wrote:
> Hi Vitaly,
>
> On Fri, Nov 18, 2005 at 07:42:51PM +0300, Vitaly Bordug wrote:
>> This adds adds PCMCIA supported for both MPC885ADS and MPC866ADS.
>>
>> This is established not together with FADS, because 885 does not have
>> io_block_mapping() for BCSR area.
>> Also, some cleanups done both for 885ADS and MBX.
>>
>> Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
>
> <snip>
>
>> + bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
>
> Shouldnt you handle ioremap() failure? Most 85xx code written
> by Kumar also does not.
Ok, I'll take a hint to go audit my code for ioremap() returns :)
- kumar
^ permalink raw reply
* RE: [PATCH] I2C: Add I2C support for the MPC8260
From: Heiko Schocher @ 2005-11-23 18:29 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, lm-sensors
In-Reply-To: <72C7A068-2C84-49BB-957A-1D1A725949D0@kernel.crashing.org>
Hello
On Wednesday, November 23, 2005 8:01 AM Kumar Gala wrote:
> Can we rename the driver from mpc8260 -> cpm2. The driver should work
> on any device that has a "CPM2" which includes a number of MPC82xx
> and MPC85xx processors. So calling it and its config options, etc
> MPC8260 is going to be confusing to users.
[PATCH] I2C: Add I2C Bus support for MPC with CPM2.
Signed-off-by: Heiko Schocher <hs@denx.de>
---
drivers/i2c/busses/Kconfig | 10 +
drivers/i2c/busses/Makefile | 1
drivers/i2c/busses/i2c-cpm2.c | 616 +++++++++++++++++++++++++++++++++++++++++
include/linux/i2c-algo-cpm2.h | 26 ++
include/linux/i2c-id.h | 3
5 files changed, 656 insertions(+), 0 deletions(-)
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 4010fe9..2acb4cc 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -270,6 +270,16 @@ config I2C_MPC
This driver can also be built as a module. If so, the module
will be called i2c-mpc.
+config I2C_CPM2
+ tristate "CPM2"
+ depends on I2C && PPC32
+ help
+ If you say yes to this option, support will be included for the
+ I2C interface on PPC with CPM2
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c-cpm2.
+
config I2C_NFORCE2
tristate "Nvidia nForce2, nForce3 and nForce4"
depends on I2C && PCI
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index f1df00f..a4c1b69 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o
obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o
obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
+obj-$(CONFIG_I2C_CPM2) += i2c-cpm2.o
ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/busses/i2c-cpm2.c b/drivers/i2c/busses/i2c-cpm2.c
new file mode 100644
index 0000000..80dc532
--- /dev/null
+++ b/drivers/i2c/busses/i2c-cpm2.c
@@ -0,0 +1,616 @@
+/*
+ * (C) Copyright 2005
+ * Heiko Schocher <hs@denx.de>
+ *
+ * This is a combined i2c adapter and algorithm driver for
+ * PPC with CPM2
+ *
+ * Release 0.1
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <linux/fsl_devices.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <asm/immap_cpm2.h>
+#include <asm/mpc8260.h>
+#include <asm/cpm2.h>
+
+#include <linux/i2c-algo-cpm2.h>
+#include <linux/platform_device.h>
+
+#define CPM_MAX_READ 513
+
+static wait_queue_head_t iic_wait;
+static ushort r_tbase, r_rbase;
+
+int cpm_scan = 0;
+int cpm_debug = 0;
+
+struct mpc_i2c {
+ u32 interrupt;
+ wait_queue_head_t queue;
+ struct i2c_adapter adap;
+ int irq;
+ u32 flags;
+ struct i2c_algo_cpm2_data *data;
+};
+
+static struct i2c_algo_cpm2_data cpm2_data;
+
+static void
+cpm2_iic_init(struct i2c_algo_cpm2_data *data)
+{
+ volatile cpm_cpm2_t *cp;
+ volatile cpm2_map_t *immap;
+
+ cp = cpmp; /* Get pointer to Communication Processor */
+ immap = (cpm2_map_t *)CPM_MAP_ADDR; /* and to internal registers */
+
+ *(ushort *)(&immap->im_dprambase[PROFF_I2C_BASE]) = PROFF_I2C;
+ data->iip = (iic_t *)&immap->im_dprambase[PROFF_I2C];
+
+ data->i2c = (i2c_cpm2_t *)&(immap->im_i2c);
+ data->cp = cp;
+
+ /* Initialize Port D IIC pins.
+ */
+ immap->im_ioport.iop_ppard |= 0x00030000;
+ immap->im_ioport.iop_pdird &= ~0x00030000;
+ immap->im_ioport.iop_podrd |= 0x00030000;
+ immap->im_ioport.iop_psord |= 0x00030000;
+
+ /* Allocate space for two transmit and two receive buffer
+ * descriptors in the DP ram.
+ */
+ data->dp_addr = cpm_dpalloc(sizeof(cbd_t) * 4, 8);
+
+ /* ptr to i2c area */
+ data->i2c = (i2c_cpm2_t *)&(((cpm2_map_t *)CPM_MAP_ADDR)->im_i2c);
+}
+
+static irqreturn_t cpm2_i2c_isr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct mpc_i2c *mpc_i2c = dev_id;
+ struct i2c_algo_cpm2_data *cpm_adap = mpc_i2c->data;
+ volatile i2c_cpm2_t *i2c = cpm_adap->i2c;
+
+ if (cpm_debug > 1)
+ printk(KERN_DEBUG "cpm_iic_interrupt(dev_id=%p)\n", dev_id);
+
+ /* Clear interrupt.
+ */
+ i2c->i2c_i2cer = 0xff;
+
+ /* Get 'me going again.
+ */
+ wake_up_interruptible(&iic_wait);
+ return IRQ_HANDLED;
+}
+
+
+static void
+cpm_iic_init(struct i2c_algo_cpm2_data *cpm_adap)
+{
+ volatile iic_t *iip = cpm_adap->iip;
+ volatile i2c_cpm2_t *i2c = cpm_adap->i2c;
+
+ if (cpm_debug) printk(KERN_DEBUG "cpm_iic_init() - iip=%p\n",iip);
+
+ /* Initialize the parameter ram.
+ * We need to make sure many things are initialized to zero,
+ * especially in the case of a microcode patch.
+ */
+ iip->iic_rstate = 0;
+ iip->iic_rdp = 0;
+ iip->iic_rbptr = 0;
+ iip->iic_rbc = 0;
+ iip->iic_rxtmp = 0;
+ iip->iic_tstate = 0;
+ iip->iic_tdp = 0;
+ iip->iic_tbptr = 0;
+ iip->iic_tbc = 0;
+ iip->iic_txtmp = 0;
+
+ /* Set up the IIC parameters in the parameter ram.
+ */
+ iip->iic_tbase = r_tbase = cpm_adap->dp_addr;
+ iip->iic_rbase = r_rbase = cpm_adap->dp_addr + sizeof(cbd_t)*2;
+
+ iip->iic_tfcr = CPMFCR_GBL | CPMFCR_EB;
+ iip->iic_rfcr = CPMFCR_GBL | CPMFCR_EB;
+
+ /* Set maximum receive size.
+ */
+ iip->iic_mrblr = CPM_MAX_READ;
+
+ /* Initialize Tx/Rx parameters.
+ */
+ {
+ volatile cpm_cpm2_t *cp = cpm_adap->cp;
+ cp->cp_cpcr =
+ mk_cr_cmd(CPM_CR_I2C_PAGE, CPM_CR_I2C_SBLOCK, 0x00, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+ }
+
+ /* Select an arbitrary address. Just make sure it is unique.
+ */
+ i2c->i2c_i2add = 0x34;
+
+ /* Divider is 2 * ( 15 + 3 )
+ */
+ i2c->i2c_i2brg = 0x0f;
+
+ /* Pre-divider is BRGCLK/4
+ */
+ i2c->i2c_i2mod = 0x06;
+
+ /* Disable interrupts.
+ */
+ i2c->i2c_i2cmr = 0;
+ i2c->i2c_i2cer = 0xff;
+
+ init_waitqueue_head(&iic_wait);
+}
+
+
+#if 0
+static int
+cpm_iic_shutdown(struct i2c_algo_cpm2_data *cpm_adap)
+{
+ volatile i2c_cpm2_t *i2c = cpm_adap->i2c;
+
+ /* Shut down IIC.
+ */
+ i2c->i2c_i2mod = 0;
+ i2c->i2c_i2cmr = 0;
+ i2c->i2c_i2cer = 0xff;
+
+ return(0);
+}
+#endif
+
+static void
+cpm_reset_iic_params(volatile iic_t *iip)
+{
+ iip->iic_tbase = r_tbase;
+ iip->iic_rbase = r_rbase;
+
+ iip->iic_tfcr = CPMFCR_GBL | CPMFCR_EB;
+ iip->iic_rfcr = CPMFCR_GBL | CPMFCR_EB;
+
+ iip->iic_mrblr = CPM_MAX_READ;
+
+ iip->iic_rstate = 0;
+ iip->iic_rdp = 0;
+ iip->iic_rbptr = 0;
+ iip->iic_rbc = 0;
+ iip->iic_rxtmp = 0;
+ iip->iic_tstate = 0;
+ iip->iic_tdp = 0;
+ iip->iic_tbptr = 0;
+ iip->iic_tbc = 0;
+ iip->iic_txtmp = 0;
+}
+
+#define BD_SC_NAK ((ushort)0x0004) /* NAK - did not respond */
+#define CPM_CR_CLOSE_RXBD ((ushort)0x0007)
+
+static void force_close(struct i2c_algo_cpm2_data *cpm)
+{
+#if 0
+ volatile cpm_cpm2_t *cp = cpm->cp;
+
+ if (cpm_debug) printk(KERN_DEBUG "force_close()\n");
+ cp->cp_cpcr =
+ mk_cr_cmd(CPM_CR_CH_I2C, CPM_CR_CLOSE_RXBD) |
+ CPM_CR_FLG;
+
+ while (cp->cp_cpcr & CPM_CR_FLG);
+#endif
+}
+
+
+/* Read from IIC...
+ * abyte = address byte, with r/w flag already set
+ */
+static int
+cpm_iic_read(struct i2c_algo_cpm2_data *cpm, u_char abyte, char *buf, int count)
+{
+ volatile cpm2_map_t *immap = (cpm2_map_t *)CPM_MAP_ADDR;
+ volatile iic_t *iip = cpm->iip;
+ volatile i2c_cpm2_t *i2c = cpm->i2c;
+ volatile cbd_t *tbdf, *rbdf;
+ u_char *tb;
+ unsigned long flags;
+
+ if (count >= CPM_MAX_READ)
+ return -EINVAL;
+
+ tbdf = (cbd_t *)&immap->im_dprambase[iip->iic_tbase];
+ rbdf = (cbd_t *)&immap->im_dprambase[iip->iic_rbase];
+
+ /* To read, we need an empty buffer of the proper length.
+ * All that is used is the first byte for address, the remainder
+ * is just used for timing (and doesn't really have to exist).
+ */
+ if (/*cpm->reloc*/0) {
+ cpm_reset_iic_params(iip);
+ }
+ tb = cpm->temp;
+ tb = (u_char *)(((uint)tb + 15) & ~15);
+ tb[0] = abyte; /* Device address byte w/rw flag */
+
+ dma_cache_wback_inv (tb, 1);
+
+ if (cpm_debug) printk(KERN_DEBUG "cpm_iic_read(abyte=0x%x)\n", abyte);
+
+ tbdf->cbd_bufaddr = __pa(tb);
+ tbdf->cbd_datlen = count + 1;
+ tbdf->cbd_sc =
+ BD_SC_READY | BD_SC_INTRPT | BD_SC_LAST |
+ BD_SC_WRAP | BD_IIC_START;
+
+ rbdf->cbd_datlen = 0;
+ rbdf->cbd_bufaddr = __pa(buf);
+ rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
+
+ if (count > 0 && count < CPM_MAX_READ)
+ iip->iic_mrblr = count; /* prevent excessive read */
+
+ dma_cache_inv (buf, count);
+
+ /* Chip bug, set enable here */
+ local_irq_save(flags);
+ i2c->i2c_i2cmr = 0x13; /* Enable some interupts */
+ i2c->i2c_i2cer = 0xff;
+ i2c->i2c_i2mod |= 1; /* Enable */
+ i2c->i2c_i2com = 0x81; /* Start master */
+
+ /* Wait for IIC transfer */
+ interruptible_sleep_on(&iic_wait);
+ local_irq_restore(flags);
+ if (signal_pending(current))
+ return -EIO;
+
+ if (cpm_debug) {
+ printk(KERN_DEBUG "tx sc %04x, rx sc %04x\n",
+ tbdf->cbd_sc, rbdf->cbd_sc);
+ }
+
+ if (tbdf->cbd_sc & BD_SC_NAK) {
+ printk(KERN_INFO "IIC read; no ack\n");
+ return 0;
+ }
+
+ if (rbdf->cbd_sc & BD_SC_EMPTY) {
+ printk(KERN_INFO "IIC read; complete but rbuf empty\n");
+ force_close(cpm);
+ printk(KERN_INFO "tx sc %04x, rx sc %04x\n",
+ tbdf->cbd_sc, rbdf->cbd_sc);
+ }
+
+ if (cpm_debug) printk(KERN_DEBUG "read %d bytes\n", rbdf->cbd_datlen);
+
+ if (rbdf->cbd_datlen < count) {
+ printk(KERN_INFO "IIC read; short, wanted %d got %d\n",
+ count, rbdf->cbd_datlen);
+ return 0;
+ }
+ if (cpm_debug) {
+ int u;
+ for (u = 0; u < count; u++) {
+ printk(KERN_DEBUG "buf[%d] = 0x%x\n", u, buf[u]);
+ }
+ }
+
+
+ return count;
+}
+
+/* Write to IIC...
+ * addr = address byte, with r/w flag already set
+ */
+static int
+cpm_iic_write(struct i2c_algo_cpm2_data *cpm, u_char abyte, char *buf,int count)
+{
+ volatile cpm2_map_t *immap = (cpm2_map_t *)CPM_MAP_ADDR;
+ volatile iic_t *iip = cpm->iip;
+ volatile i2c_cpm2_t *i2c = cpm->i2c;
+ volatile cbd_t *tbdf;
+ u_char *tb;
+ unsigned long flags;
+
+ tb = cpm->temp;
+ tb = (u_char *)(((uint)tb + 15) & ~15);
+ *tb = abyte; /* Device address byte w/rw flag */
+
+ dma_cache_wback_inv (tb, 1);
+ dma_cache_wback_inv (buf, count);
+
+ if (cpm_debug) printk(KERN_DEBUG "cpm_iic_write(abyte=0x%x)\n", abyte);
+ if (cpm_debug) printk(KERN_DEBUG "buf[0] = 0x%x, buf[1] = 0x%x\n", buf[0], buf[1]);
+
+ /* set up 2 descriptors */
+ tbdf = (cbd_t *)&immap->im_dprambase[iip->iic_tbase];
+
+ tbdf[0].cbd_bufaddr = __pa(tb);
+ tbdf[0].cbd_datlen = 1;
+ tbdf[0].cbd_sc = BD_SC_READY | BD_IIC_START;
+
+ tbdf[1].cbd_bufaddr = __pa(buf);
+ tbdf[1].cbd_datlen = count;
+ tbdf[1].cbd_sc = BD_SC_READY | BD_SC_INTRPT | BD_SC_LAST | BD_SC_WRAP;
+
+ /* Chip bug, set enable here */
+ local_irq_save(flags);;
+ i2c->i2c_i2cmr = 0x13; /* Enable some interupts */
+ i2c->i2c_i2cer = 0xff;
+ i2c->i2c_i2mod |= 1; /* Enable */
+ i2c->i2c_i2com = 0x81; /* Start master */
+
+ /* Wait for IIC transfer */
+ interruptible_sleep_on(&iic_wait);
+ local_irq_restore(flags);
+ if (signal_pending(current))
+ return -EIO;
+
+ if (cpm_debug) {
+ printk(KERN_DEBUG "tx0 sc %04x, tx1 sc %04x\n",
+ tbdf[0].cbd_sc, tbdf[1].cbd_sc);
+ }
+
+ if (tbdf->cbd_sc & BD_SC_NAK) {
+ printk(KERN_INFO "IIC write; no ack\n");
+ return 0;
+ }
+
+ if (tbdf->cbd_sc & BD_SC_READY) {
+ printk(KERN_INFO "IIC write; complete but tbuf ready\n");
+ return 0;
+ }
+
+ return count;
+}
+
+#if 0
+/* See if an IIC address exists..
+ * addr = 7 bit address, unshifted
+ */
+static int
+cpm_iic_tryaddress(struct i2c_algo_cpm2_data *cpm, int addr)
+{
+ volatile cpm2_map_t *immap = (cpm2_map_t *)CPM_MAP_ADDR;
+ volatile iic_t *iip = cpm->iip;
+ volatile i2c_cpm2_t *i2c = cpm->i2c;
+ volatile cbd_t *tbdf, *rbdf;
+ u_char *tb;
+ unsigned long flags, len;
+
+ if (cpm_debug > 1)
+ printk(KERN_DEBUG "cpm_iic_tryaddress(cpm=%p,addr=%d)\n", cpm, addr);
+
+ if (cpm_debug && addr == 0) {
+ printk(KERN_DEBUG "iip %p, dp_addr 0x%x\n", cpm->iip, cpm->dp_addr);
+ printk(KERN_DEBUG "iic_tbase %d, r_tbase %d\n", iip->iic_tbase, r_tbase);
+ }
+
+ tbdf = (cbd_t *)&immap->im_dprambase[iip->iic_tbase];
+ rbdf = (cbd_t *)&immap->im_dprambase[iip->iic_rbase];
+
+ tb = cpm->temp;
+ tb = (u_char *)(((uint)tb + 15) & ~15);
+
+ /* do a simple read */
+ tb[0] = (addr << 1) | 1; /* device address (+ read) */
+ len = 2;
+
+ dma_cache_wback_inv (tb, 1);
+
+ tbdf->cbd_bufaddr = __pa(tb);
+ tbdf->cbd_datlen = len;
+ tbdf->cbd_sc =
+ BD_SC_READY | BD_SC_INTRPT | BD_SC_LAST |
+ BD_SC_WRAP | BD_IIC_START;
+
+ rbdf->cbd_datlen = 0;
+ rbdf->cbd_bufaddr = __pa(tb+2);
+ rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
+
+ local_irq_save(flags);
+ i2c->i2c_i2cmr = 0x13; /* Enable some interupts */
+ i2c->i2c_i2cer = 0xff;
+ i2c->i2c_i2mod |= 1; /* Enable */
+ i2c->i2c_i2com = 0x81; /* Start master */
+
+ if (cpm_debug > 1) printk(KERN_DEBUG "about to sleep\n");
+
+ /* wait for IIC transfer */
+ interruptible_sleep_on(&iic_wait);
+ local_irq_restore(flags);
+ if (signal_pending(current))
+ return -EIO;
+
+ if (cpm_debug > 1) printk(KERN_DEBUG "back from sleep\n");
+
+ if (tbdf->cbd_sc & BD_SC_NAK) {
+ if (cpm_debug > 1) printk(KERN_DEBUG "IIC try; no ack\n");
+ return 0;
+ }
+
+ if (tbdf->cbd_sc & BD_SC_READY) {
+ printk(KERN_INFO "IIC try; complete but tbuf ready\n");
+ }
+
+ return 1;
+}
+#endif
+
+static int cpm2_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+ struct i2c_msg *pmsg;
+ int i;
+ int ret = 0;
+ struct mpc_i2c *mpc_i2c = i2c_get_adapdata(adap);
+ struct i2c_algo_cpm2_data *data = mpc_i2c->data;
+ u_char addr;
+
+ for (i = 0; i < num; i++) {
+ pmsg = &msgs[i];
+
+ if (cpm_debug)
+ printk(KERN_DEBUG "i2c-cpm2.o: "
+ "#%d addr=0x%x flags=0x%x len=%d\n",
+ i, pmsg->addr, pmsg->flags, pmsg->len);
+
+ addr = pmsg->addr << 1;
+ if (pmsg->flags & I2C_M_RD )
+ addr |= 1;
+ if (pmsg->flags & I2C_M_REV_DIR_ADDR )
+ addr ^= 1;
+
+ if (!(pmsg->flags & I2C_M_NOSTART)) {
+ }
+ if (pmsg->flags & I2C_M_RD ) {
+ /* read bytes into buffer*/
+ ret = cpm_iic_read(data, addr, pmsg->buf, pmsg->len);
+ if (cpm_debug)
+ printk(KERN_DEBUG "i2c-cpm2.o: read %d bytes\n", ret);
+ if (ret < pmsg->len ) {
+ return (ret<0)? ret : -EREMOTEIO;
+ }
+ } else {
+ /* write bytes from buffer */
+ ret = cpm_iic_write(data, addr, pmsg->buf, pmsg->len);
+ if (cpm_debug)
+ printk(KERN_DEBUG "i2c-cpm2.o: wrote %d\n", ret);
+ if (ret < pmsg->len ) {
+ return (ret<0) ? ret : -EREMOTEIO;
+ }
+ }
+ }
+ return (ret < 0) ? ret : num;
+}
+
+static u32 cpm2_functionality(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR |
+ I2C_FUNC_PROTOCOL_MANGLING;
+}
+
+static struct i2c_algorithm cpm2_algo = {
+ .master_xfer = cpm2_xfer,
+ .functionality = cpm2_functionality,
+};
+
+static struct i2c_adapter cpm2_ops = {
+ .owner = THIS_MODULE,
+ .name = "MPC CPM2 adapter",
+ .id = I2C_HW_MPC82xx,
+ .algo = &cpm2_algo,
+ .class = I2C_CLASS_HWMON,
+ .timeout = 1,
+ .retries = 1
+};
+
+static int fsl_i2c_probe(struct device *device)
+{
+ int result = 0;
+ struct mpc_i2c *i2c;
+ struct platform_device *pdev = to_platform_device(device);
+ struct fsl_i2c_platform_data *pdata;
+
+ pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data;
+
+ if (!(i2c = kmalloc(sizeof(*i2c), GFP_KERNEL))) {
+ return -ENOMEM;
+ }
+ memset(i2c, 0, sizeof(*i2c));
+
+ i2c->data = &cpm2_data;
+ /* CPM Plattform initialisation */
+ cpm2_iic_init (i2c->data);
+ /* CPM init */
+ cpm_iic_init (i2c->data);
+ i2c->irq = platform_get_irq(pdev, 0);
+
+ if (i2c->irq != 0) {
+ if ((result = request_irq(i2c->irq, cpm2_i2c_isr,
+ SA_SHIRQ, "i2c-mpc", i2c)) < 0) {
+ printk(KERN_ERR
+ "i2c-mpc - failed to attach interrupt\n");
+ goto fail_irq;
+ }
+ }
+ dev_set_drvdata(device, i2c);
+
+ i2c->adap = cpm2_ops;
+ i2c_set_adapdata(&i2c->adap, i2c);
+ i2c->adap.dev.parent = &pdev->dev;
+ if ((result = i2c_add_adapter(&i2c->adap)) < 0) {
+ printk(KERN_ERR "i2c-mpc - failed to add adapter\n");
+ goto fail_add;
+ }
+
+ return result;
+
+ fail_add:
+ if (i2c->irq != 0)
+ free_irq(i2c->irq, NULL);
+ fail_irq:
+ kfree(i2c);
+ return result;
+};
+
+static int fsl_i2c_remove(struct device *device)
+{
+ struct mpc_i2c *i2c = dev_get_drvdata(device);
+
+ cpm_dpfree (i2c->data->dp_addr);
+
+ i2c_del_adapter(&i2c->adap);
+ dev_set_drvdata(device, NULL);
+
+ if (i2c->irq != 0)
+ free_irq(i2c->irq, i2c);
+
+ kfree(i2c);
+ return 0;
+};
+
+/* Structure for a device driver */
+static struct device_driver fsl_i2c_driver = {
+ .name = "fsl-cpm-i2c",
+ .bus = &platform_bus_type,
+ .probe = fsl_i2c_probe,
+ .remove = fsl_i2c_remove,
+};
+
+static int __init fsl_i2c_init(void)
+{
+ return driver_register(&fsl_i2c_driver);
+}
+
+static void __exit fsl_i2c_exit(void)
+{
+ driver_unregister(&fsl_i2c_driver);
+}
+
+module_init(fsl_i2c_init);
+module_exit(fsl_i2c_exit);
+
+MODULE_AUTHOR("Heiko Schocher <hs@denx.de>");
+MODULE_DESCRIPTION
+ ("I2C-Bus adapter for MPC with CPM2 processors");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/i2c-algo-cpm2.h b/include/linux/i2c-algo-cpm2.h
new file mode 100644
index 0000000..f03277c
--- /dev/null
+++ b/include/linux/i2c-algo-cpm2.h
@@ -0,0 +1,26 @@
+/* ----------------------------------------------------------- */
+/* i2c-algo-cpm2.h i2c driver algorithms for MPC with CPM2 */
+/* ----------------------------------------------------------- */
+
+/* $Id$ */
+
+#ifndef I2C_ALGO_CPM2_H
+#define I2C_ALGO_CPM2_H 1
+
+#include <linux/i2c.h>
+
+struct i2c_algo_cpm2_data {
+ uint dp_addr;
+ int reloc;
+ volatile i2c_cpm2_t *i2c;
+ volatile iic_t *iip;
+ volatile cpm_cpm2_t *cp;
+
+ int (*setisr) (int irq,
+ void (*func)(int, void (*)(void *), void *),
+ void *data);
+
+ u_char temp[513];
+};
+
+#endif /* I2C_ALGO_CPM2_H */
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index 1543daa..e7a12cc 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -223,6 +223,9 @@
/* --- PowerPC on-chip adapters */
#define I2C_HW_OCP 0x120000 /* IBM on-chip I2C adapter */
+/* --- MPC82xx PowerPC adapters */
+#define I2C_HW_MPC82xx 0x100002 /* MPC82xx I2C adapter */
+
/* --- Broadcom SiByte adapters */
#define I2C_HW_SIBYTE 0x150000
^ permalink raw reply related
* Re: [PATCH] 8xx PCMCIA: support for MPC885ADS and MPC866ADS
From: Marcelo Tosatti @ 2005-11-23 12:53 UTC (permalink / raw)
To: Vitaly Bordug, Kumar Gala; +Cc: linuxppc-embedded list
In-Reply-To: <437E048B.2020605@dev.rtsoft.ru>
Hi Vitaly,
On Fri, Nov 18, 2005 at 07:42:51PM +0300, Vitaly Bordug wrote:
> This adds adds PCMCIA supported for both MPC885ADS and MPC866ADS.
>
> This is established not together with FADS, because 885 does not have
> io_block_mapping() for BCSR area.
> Also, some cleanups done both for 885ADS and MBX.
>
> Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
<snip>
> + bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
Shouldnt you handle ioremap() failure? Most 85xx code written
by Kumar also does not.
^ permalink raw reply
* RE: [PATCH] MTD: Add support for the PM82x Boards.
From: Heiko Schocher @ 2005-11-23 17:50 UTC (permalink / raw)
To: tglx; +Cc: linuxppc-dev, dwmw2, linux-mtd
In-Reply-To: <1132754409.32542.161.camel@tglx.tec.linutronix.de>
Hello,
i made the changes in the code you suggested to me.
Additional changes:
- I now use the CFI interface (I tested it, and it seems OK
to me)
- MB -> MiB
- Code reworked
[PATCH] MTD: Add support for the PM82x Board.
Included support for the NOR flashes on the Modul,
and for the DiskOnChip on the Board.
Signed-off-by: Heiko Schocher <hs@denx.de>
---
drivers/mtd/maps/Kconfig | 6 +
drivers/mtd/maps/Makefile | 1
drivers/mtd/maps/pm82x.c | 337 +++++++++++++++++++++++++++++++++++++++++
drivers/mtd/nand/diskonchip.c | 4
4 files changed, 348 insertions(+), 0 deletions(-)
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 846a533..237abe8 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -256,6 +256,12 @@ config MTD_SBC8240
Flash access on the SBC8240 board from Wind River. See
<http://www.windriver.com/products/sbc8240/>
+config MTD_PM82X
+ tristate "Flash device on PM82X Boards"
+ depends on PPC32 && 6xx && 8260 && MTD_COMPLEX_MAPPINGS && MTD_PARTITIONS
+ help
+ Flash access on the PM82X boards from Microsys.
+
config MTD_TQM8XXL
tristate "CFI Flash device mapped on TQM8XXL"
depends on MTD_CFI && TQM8xxL
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 7d9e940..e3733b1 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -73,3 +73,4 @@ obj-$(CONFIG_MTD_OMAP_NOR) += omap_nor.o
obj-$(CONFIG_MTD_PQ2FADS) += pq2fads.o
obj-$(CONFIG_MTD_MTX1) += mtx-1_flash.o
obj-$(CONFIG_MTD_TQM834x) += tqm834x.o
+obj-$(CONFIG_MTD_PM82X) += pm82x.o
diff --git a/drivers/mtd/maps/pm82x.c b/drivers/mtd/maps/pm82x.c
new file mode 100644
index 0000000..840fc29
--- /dev/null
+++ b/drivers/mtd/maps/pm82x.c
@@ -0,0 +1,337 @@
+/*
+ * Copyright(C) 2005
+ * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
+ *
+ * Copyright(C) 2005
+ * Josef Wagner, MicroSys GmbH <wagner@microsys.de>
+ *
+ * This code is GPLed
+ *
+ */
+
+/*
+ * PM825/PM826 uses 4 x Intel 28F160C3B (16 Mbit)
+ * 4 x Intel 28F160C3 (16 Mbit) in one bank (64 bit bankwidth)
+ * for a total of 8MiB flash
+ *
+ * PM827/PM828 uses 4 x Intel 28F640C3 (64 Mbit)
+ * in one bank (64 bit bankwidth)
+ * for a total of 32MiB flash
+
+ * Thus we have to chose:
+ * - Support 64-bit bankwidth => CONFIG_MTD_CFI_B8
+ * - Support 4-chip flash interleave => CONFIG_MTD_CFI_I4
+*/
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+#include <asm/ppcboot.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+
+#define FLASH_BANK_MAX 1
+
+/* The "residual" data board information structure the boot loader
+ * hands to us.
+ */
+extern unsigned char __res[];
+
+/* trivial struct to describe partition information */
+struct mtd_part_def
+{
+ int nums;
+ unsigned char *type;
+ struct mtd_partition* mtd_part;
+};
+
+static struct mtd_info* mtd_banks[FLASH_BANK_MAX];
+static struct map_info* map_banks[FLASH_BANK_MAX];
+static struct mtd_part_def part_banks[FLASH_BANK_MAX];
+static unsigned long num_banks;
+static __iomem void *start_scan_addr;
+
+static map_word pm82x_read64(struct map_info *map, unsigned long ofs)
+{
+ map_word val;
+ val.x[0] = *((volatile __u32 *)(map->map_priv_1 + ofs));
+ val.x[1] = *(((volatile __u32 *)(map->map_priv_1 + ofs)) + 1);
+ return val;
+}
+
+static void pm82x_copy_from(struct map_info *map,
+ void *to, unsigned long from, ssize_t len)
+{
+ memcpy_fromio(to, (void *)(map->map_priv_1 + from), len);
+}
+
+static void pm82x_write64 (struct map_info *map, map_word map_d,
+ unsigned long adr)
+{
+ ulong addr = map->map_priv_1 + adr;
+ __u64 d = ((__u64)map_d.x[0] << 32) + map_d.x[1];
+ __u64 * data = &d;
+ ulong flags;
+ volatile ulong msr;
+ ulong saved_msr;
+ volatile long saved_fr[2];
+
+ local_irq_save (flags);
+
+ __asm__ __volatile__ ("mfmsr %0" : "=r" (msr):);
+ saved_msr = msr;
+ msr |= MSR_FP;
+ msr &= ~(MSR_FE0 | MSR_FE1);
+
+ __asm__ __volatile__ (
+ "mtmsr %0\n"
+ "isync\n"
+ :
+ : "r" (msr));
+
+ __asm__ __volatile__ (
+ "stfd 1, 0(%2)\n"
+ "lfd 1, 0(%0)\n"
+ "stfd 1, 0(%1)\n"
+ "lfd 1, 0(%2)\n"
+ :
+ : "r" (data), "r" (addr), "b" (saved_fr)
+ );
+
+ __asm__ __volatile__ (
+ "mtmsr %0\n"
+ "isync\n"
+ :
+ : "r" (saved_msr));
+
+ local_irq_restore (flags);
+}
+
+static void pm82x_copy_to(struct map_info *map,
+ unsigned long to, const void *from, ssize_t len)
+{
+ memcpy_toio((void *)(map->map_priv_1 + to), from, len);
+}
+
+/*
+ * The following defines the partition layout of PM825/PM826 boards.
+ *
+ * See include/linux/mtd/partitions.h for definition of the
+ * mtd_partition structure.
+ *
+ */
+
+#ifdef CONFIG_MTD_PARTITIONS
+/* partition definition for first (and only) flash bank
+ * also ref. to "drivers/char/flash_config.c"
+ */
+static struct mtd_partition pm82x_partitions_8M[] = {
+ {
+ .name = "U-Boot", /* U-Boot image */
+ .offset = 0x00000000,
+ .size = 0x00040000, /* 256 KB */
+ },
+ {
+ .name = "kernel", /* Linux kernel image */
+ .offset = 0x00040000,
+ .size = 0x000C0000, /* 768 KB */
+ },
+ {
+ .name = "ramdisk", /* Ramdisk image */
+ .offset = 0x00100000,
+ .size = 0x00300000, /* 3 MiB */
+ },
+ {
+ .name = "user", /* User file system */
+ .offset = 0x00400000,
+ .size = 0x00400000, /* 4 MiB */
+ },
+};
+
+static struct mtd_partition pm82x_partitions_32M[] = {
+ {
+ .name = "U-Boot", /* U-Boot image */
+ .offset = 0x00000000,
+ .size = 0x00040000, /* 256 KB */
+ },
+ {
+ .name = "kernel", /* Linux kernel image */
+ .offset = 0x00040000,
+ .size = 0x000C0000, /* 768 KB */
+ },
+ {
+ .name = "ramdisk", /* Ramdisk image */
+ .offset = 0x00100000,
+ .size = 0x00300000, /* 3 MiB */
+ },
+ {
+ .name = "user", /* User file system */
+ .offset = 0x00400000,
+ .size = 0x01C00000, /* 28 MiB */
+ },
+};
+
+#endif /* CONFIG_MTD_PARTITIONS */
+
+int __init init_pm82x_mtd(void)
+{
+ int idx = 0, ret = 0;
+ unsigned long flash_addr, flash_size, mtd_size = 0;
+
+ /* pointer to PM82x board info data */
+ bd_t *bd = (bd_t *)__res;
+
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+ int n;
+ const char *part_probes[] = { "cmdlinepart", NULL };
+#endif
+
+ flash_addr = bd->bi_flashstart;
+ flash_size = bd->bi_flashsize;
+
+ /* request maximum flash size address space */
+ start_scan_addr = ioremap(flash_addr, flash_size);
+ if (!start_scan_addr) {
+ printk(KERN_ERR "%s: Failed to ioremap address: 0x%lx\n",
+ __FUNCTION__, flash_addr);
+ return -EIO;
+ }
+
+ for(idx = 0 ; idx < FLASH_BANK_MAX ; idx++) {
+ if (mtd_size >= flash_size)
+ break;
+
+ pr_debug ("%s: chip probing count %d\n", __FUNCTION__, idx);
+
+ map_banks[idx] = kmalloc(sizeof(struct map_info) + 16,
+ GFP_KERNEL);
+ if (map_banks[idx] == NULL) {
+ ret = -ENOMEM;
+ goto error_mem;
+ }
+ memset(map_banks[idx]->name, 0, 16);
+ sprintf(map_banks[idx]->name, "PM82x-%d", idx);
+ map_banks[idx]->size = flash_size;
+ map_banks[idx]->bankwidth = 8;
+ map_banks[idx]->read = pm82x_read64;
+ map_banks[idx]->copy_from = pm82x_copy_from;
+ map_banks[idx]->write = pm82x_write64;
+ map_banks[idx]->copy_to = pm82x_copy_to;
+ map_banks[idx]->map_priv_1= (unsigned long)
+ start_scan_addr + ((idx > 0) ?
+ (mtd_banks[idx-1] ? mtd_banks[idx-1]->size : 0) : 0);
+
+ /* start to probe flash chips */
+ mtd_banks[idx] = do_map_probe("cfi_probe", map_banks[idx]);
+ if (mtd_banks[idx]) {
+ mtd_banks[idx]->owner = THIS_MODULE;
+ mtd_size += mtd_banks[idx]->size;
+ num_banks++;
+ pr_debug ("%s: bank %ld, name: %s, size: %d bytes \n",
+ __FUNCTION__,
+ num_banks,
+ mtd_banks[idx]->name,
+ mtd_banks[idx]->size);
+ }
+ }
+
+ /* no supported flash chips found */
+ if (!num_banks) {
+ printk(KERN_ERR "PM82x: No supported flash chips found!\n");
+ ret = -ENXIO;
+ goto error_mem;
+ }
+
+#ifdef CONFIG_MTD_PARTITIONS
+ /*
+ * Select static partition definitions
+ */
+ if (flash_size == 0x800000) {
+ part_banks[0].mtd_part = pm82x_partitions_8M;
+ part_banks[0].nums = ARRAY_SIZE(pm82x_partitions_8M);
+ } else {
+ part_banks[0].mtd_part = pm82x_partitions_32M;
+ part_banks[0].nums = ARRAY_SIZE(pm82x_partitions_32M);
+ }
+ part_banks[0].type = "static image";
+
+ for(idx = 0; idx < num_banks ; idx++) {
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+ n = parse_mtd_partitions(mtd_banks[idx],
+ part_probes,
+ &part_banks[idx].mtd_part,
+ 0);
+ pr_debug ("%s: %d command line partitions on bank %d\n",
+ __FUNCTION__, n, idx);
+ if (n > 0) {
+ part_banks[idx].type = "command line";
+ part_banks[idx].nums = n;
+ }
+#endif /* CONFIG_MTD_CMDLINE_PARTS */
+
+ if (part_banks[idx].nums == 0) {
+ printk (KERN_NOTICE
+ "PM82x flash bank %d: no partition info "
+ "available, registering whole device\n", idx);
+ add_mtd_device(mtd_banks[idx]);
+ } else {
+ printk (KERN_NOTICE
+ "PM82x flash bank %d: Using %s partition "
+ "definition\n", idx, part_banks[idx].type);
+ add_mtd_partitions (mtd_banks[idx],
+ part_banks[idx].mtd_part,
+ part_banks[idx].nums);
+ }
+ }
+#else /* ! CONFIG_MTD_PARTITIONS */
+ printk (KERN_NOTICE "PM82x flash: registering %d flash banks "
+ "at once\n", num_banks);
+
+ for(idx = 0 ; idx < num_banks ; idx++)
+ add_mtd_device(mtd_banks[idx]);
+
+#endif /* CONFIG_MTD_PARTITIONS */
+
+ return 0;
+error_mem:
+ for (idx = 0 ; idx < FLASH_BANK_MAX ; idx++) {
+ if (map_banks[idx] != NULL) {
+ kfree(map_banks[idx]);
+ map_banks[idx] = NULL;
+ }
+ }
+ iounmap(start_scan_addr);
+
+ return ret;
+}
+
+static void __exit cleanup_pm82x_mtd(void)
+{
+ unsigned int idx = 0;
+ for(idx = 0 ; idx < num_banks ; idx++) {
+ /* destroy mtd_info previously allocated */
+ if (mtd_banks[idx]) {
+ del_mtd_partitions(mtd_banks[idx]);
+ map_destroy(mtd_banks[idx]);
+ }
+ /* release map_info not used anymore */
+ kfree(map_banks[idx]);
+ }
+ if (start_scan_addr) {
+ iounmap(start_scan_addr);
+ start_scan_addr = NULL;
+ }
+}
+
+module_init(init_pm82x_mtd);
+module_exit(cleanup_pm82x_mtd);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Wolfgang Denk <wd@denx.de>");
+MODULE_DESCRIPTION("MTD map driver for PM82x boards");
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 21d4e8f..bf7cf54 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -55,7 +55,11 @@ static unsigned long __initdata doc_loca
0xe8000, 0xea000, 0xec000, 0xee000,
#endif /* CONFIG_MTD_DOCPROBE_HIGH */
#elif defined(__PPC__)
+#if defined(CONFIG_PM82X)
+ 0xff800000,
+#else
0xe4000000,
+#endif
#elif defined(CONFIG_MOMENCO_OCELOT)
0x2f000000,
0xff000000,
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox