* SKB corruption on heavy traffic
From: Franca, Jose (NSN - PT/Portugal - MiniMD) @ 2008-04-29 18:39 UTC (permalink / raw)
To: linuxppc-dev, linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 29183 bytes --]
Hello Community!
We are developing a MPC8247 based telecom board (512MB), using
linux 2.4 with some proprietary changes on IP stack and we are facing
some problems when we have heavy traffic on our Ethernet interfaces...
Namely:
- When sending a ping flood we have skb corruption after
some variable time (looks like memory problems). Resuming what seems to
be happening: after release (dealloc) of the skb, the kernel tries to
access it again. To verify this we have implemented a list of "to be
freed" skb to have a delay between the time they are freed by the stack
and the actual dealloc. In this delay we are able to verify that the skb
is changed.
- We have reports of DMA transfers not completed in
heavy traffic.
- After a while, and skb corrupted messages appearing in
the console, we start to have a scrambled characters. So, after some
seconds we don't understand what is written. This problem solves after
the crash or reboot. Which means that uart also seems to crack in heavy
load or at least some.
Below are some of our traces that show our problem... Someone has some
hints of what could be leading to this?? HHHHEEEEEELLLPP!!!!
Huge Thanks!
Filipe.
F:bcmhal_shape_modid_phyport_to_pnum L:1046 Invalid modid received 48
port 3
Apr 25 19:59:14 system: F:bcmhal_shape_modid_phyport_to_pnum L:1046
Invalid modid received 48 port 3
Apr 25 19:59:14 system: F:bcm_enet_rx L:1788 Packet received from an
invalid port 3 modid 48
F:bcmhal_shape_modid_phyport_to_pnum L:1046 Invalid modid received 48
port 3
Apr 25 20:02:39 system: F:bcmhal_shape_modid_phyport_to_pnum L:1046
Invalid modid received 48 port 3
Apr 25 20:02:39 system: F:bcm_enet_rx L:1788 Packet received from an
invalid port 3 modid 48
F:bcmhal_shape_modid_phyport_to_pnum L:1046 Invalid modid received 48
port 3
Apr 25 20:06:57 system: F:bcmhal_shape_modid_phyport_to_pnum L:1046
Invalid modid received 48 port 3
Apr 25 20:06:57 system: F:bcm_enet_rx L:1788 Packet received from an
invalid port 3 modid 48
Apr 25 21:54:06 comd: buf = f5 43 7d 43 bb ff 80 18 36 70 6e 91 00 00
01 01 08 0a 00 0e c1 6d 00 00 41 15 6e 29 01 07 04 e6
Apr 25 21:54:08 comd: buf = 00 00 00 00 00 00 00 00 00 00 00 00 43 49
47 47 07 05 20 71 00 00 00 00 00 00 00 00 00 00 00 03
Apr 25 21:54:09 system: skbuff.c:skb_clone:647: Bingle, got a freed
skb being cloned, return NULL!!!<1> skbuff.c:skb_clone:647: Bingle, got
a freed
skb being cloned, return NULL!!!<3>tcp_write_xmit: clone failed !
Apr 25 21:54:09 comd: buf = 00 6e 29 01 07 04 e6 55 7b 00 00 ff ff 33
2d ff ff 00 00 00 0f 33 2d 00 03 00 00 00 08 00 00 00
Apr 25 21:54:09 comd: buf = 00 00 00 00 00 00 00 00 00 00 00 00 53 49
44 41 2a 00 5a f9 00 00 00 00 00 00 00 00 00 00 00 01
Apr 25 21:54:11 comd: message data field too long, max=12288 fd=82
((nil)) source: shelf=2021 slot=2223 service=2425 port=2627
destination: s
helf=1819 slot=1a1b service=1c1d port=1e1f message type: 28292a2b
length: 2c2d2e2f fd out of sync, will be closed (nil).
Oops: Exception in kernel mode, sig: 7
NIP: C0034138 XER: 20000000 LR: C011B73C SP: C04E3D20 REGS: c04e3c70
TRAP: 0600 Not tainted
MSR: 00009032 EE: 1 PR: 0 FP: 0 ME: 1 IR/DR: 11
DAR: C1611DBF, DSISR: 00010920
TASK = c04e2000[2] 'keventd' Last syscall: 120
last math cb0f8000 last altivec 00000000
GPR00: C1611DBF C04E3D20 C04E2000 C1611DAB 00000000 00000190 C1611DAB
0003CAEC
GPR08: C0F98B04 D1C8201A C0F5C018 C0230000 22002024 1031E1BC 0FFD5000
1009B000
GPR16: 00000000 00000000 00000000 00000000 003FF000 00000001 00000000
C01E0000
GPR24: C01F0000 06D01B7F C04E3E18 00000001 C01D0000 0000158E 0000AC70
C3442DA0
TESCR1 0xf0010040: 00100000 TESCR2 0xf0010044: 00000000
ESR 0xf0010884: 00000000
PCI_EACR 0xf0010890: 0000000c
PCI_EDCR 0xf0010898: 00000000
PCI_ECCR 0xf00108a0: 00000000
GFPGA regs
0xd0000000 1901200803051610 0000000000090101
0xd0000100 007f7f7f7f7f7f7f 7f7f7f7f7f7f7f7f
0xd0000200 008dd3d3d3d3d3d3 d3d3d3d3d3d3d3d3
0xd0000280 00ffffff00000000 d3d3d3d3d3d3d3d3
0xd0000300 ea19b993faff0040 0000050000001600
0xd0000380 000f0f0f00000000 0000000000000000
0xd0000400 660f01ff0100a5a5 a5a5a5a5a5a5a5a5
0xd0000480 0001010100000000 a5a5a5a5a5a5a5a5
0xd0000500 0f01010101010101 0101010101010101
0xd0000580 003f3f3f00000000 0101010101010101
0xd0000600 1f9a030a24440100 0000000000000000
0xd0000680 00ffffff00000000 0000000000000000
0xd0000690 00ffffff00000000 0000000000000000
0xd00006a0 00ffffff00000000 0000000000000000
0xd00006b0 00e727c000000000 0000000000000000
Call backtrace:
C011D8CC C011B73C C011B7D0 C011B9C8 C011BC24 C01496CC C014A054
C014D380 C0156584 C0156B70 C0137B08 C0137FD8 C0120B9C C0120C58
C001B338 C002517C C000876C
Apr 25 21:54:12 system: skbuff.c:skb_clone:647: Bingle, got a freed
skb being cloned, return NULL!!!<1> skbuff.c:skb_clone:647: Bingle, got
a freed
skb being cloned, return NULL!!!<1> skbuff.c:skb_clone:647: Bingle, got
a freed skb being cloned, return NULL!!!<1> skbuff.c:skb_clone:647:
Bingle, go
t a freed skb being cloned, return NULL!!!9C C0120C58
Apr 25 21:54:12 system: C001B338 C002517C C000876C
Apr 25 21:54:12 system: skb_release_data:400 memory ffffee84 out of
range!
Apr 25 21:54:12 system: Call backtrace:
Apr 25 21:54:12 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:12 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:12 system: C001B338 C002517C C000876C
Apr 25 21:54:12 system: skb_release_data:400 memory ffffeea0 out of
range!
Apr 25 21:54:12 system: Call backtrace:
Apr 25 21:54:12 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:12 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:12 system: C001B338 C002517C C000876C
Apr 25 21:54:12 system: skb_release_data:400 memory ffffeec4 out of
range!
Apr 25 21:54:12 system: Call backtrace:
Apr 25 21:54:12 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:12 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:12 system: C001B338 C002517C C000876C
Apr 25 21:54:12 system: skb_release_data:400 memory ffffeef8 out of
range!
Apr 25 21:54:12 system: Call backtrace:
Apr 25 21:54:12 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:12 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:12 system: C001B338 C002517C C000876C
Apr 25 21:54:12 system: skb_release_data:400 memory ffffef34 out of
range!
Apr 25 21:54:12 system: Call backtrace:
Apr 25 21:54:12 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:12 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:12 system: C001B338 C002517C C000876C
Apr 25 21:54:12 system: skb_release_data:400 memory ffffef44 out of
range!
Apr 25 21:54:12 system: Call backtrace:
Apr 25 21:54:13 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:13 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:13 system: C001B338 C002517C C000876C
Apr 25 21:54:13 system: skb_release_data:400 memory ffffef54 out of
range!
Apr 25 21:54:13 system: Call backtrace:
Apr 25 21:54:13 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:13 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:13 system: C001B338 C002517C C000876C
Apr 25 21:54:13 system: skb_release_data:400 memory ffffef64 out of
range!
Apr 25 21:54:13 system: Call backtrace:
Apr 25 21:54:13 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:13 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:13 system: C001B338 C002517C C000876C
Apr 25 21:54:13 system: skb_release_data:400 memory ffffef74 out of
range!
Apr 25 21:54:13 system: Call backtrace:
Apr 25 21:54:13 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:13 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:13 system: C001B338 C002517C C000876C
Apr 25 21:54:13 system: skb_release_data:400 memory 41646472 out of
range!
Apr 25 21:54:13 system: Call backtrace:
Apr 25 21:54:13 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:13 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
linux-bcm-core (127): soc_counter_thread: DMA did not finish
buf32=cd380000
linux-bcm-core (132): soc_counter_thread: DMA did not finish
buf32=cd389800
linux-bcm-core (130): soc_counter_thread: DMA did not finish
buf32=cd382400
Apr 25 21:54:13 system: C001B338 C002517C C000876C
Apr 25 21:54:13 system: skb_release_data:400 memory 700a0000 out of
range!
Apr 25 21:54:13 system: Call backtrace:
Apr 25 21:54:13 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:13 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:13 system: C001B338 C002517C C000876C
Apr 25 21:54:13 system: skb_release_data:400 memory 6d654164 out of
range!
Apr 25 21:54:13 system: Call backtrace:
Apr 25 21:54:13 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:13 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:13 system: C001B338 C002517C C000876C
Apr 25 21:54:13 system: skb_release_data:400 memory 2025700a out of
range!
Apr 25 21:54:13 system: Call backtrace:
Apr 25 21:54:13 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:13 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:13 system: C001B338 C002517C C000876C
Apr 25 21:54:13 system: skb_release_data:400 memory 496e2025 out of
range!
Apr 25 21:54:13 system: Call backtrace:
Apr 25 21:54:13 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:13 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:13 system: C001B338 C002517C C000876C
Apr 25 21:54:13 system: skb_release_data:400 memory 70293a0a out of
range!
Apr 25 21:54:13 system: Call backtrace:
Apr 25 21:54:13 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:13 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:13 system: C001B338 C002517C C000876C
Apr 25 21:54:13 system: skb_release_data:400 memory 726f6c42 out of
range!
Apr 25 21:54:13 system: Call backtrace:
Apr 25 21:54:14 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:14 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:14 system: C001B338 C002517C C000876C
Apr 25 21:54:14 system: skb_release_data:400 memory 72616365 out of
range!
Apr 25 21:54:14 system: Call backtrace:
Apr 25 21:54:14 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:14 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:14 system: C001B338 C002517C C000876C
Apr 25 21:54:14 system: skb_release_data:400 memory 31000000 out of
range!
Apr 25 21:54:14 system: Call backtrace:
Apr 25 21:54:14 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:14 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:14 system: C001B338 C002517C C000876C
Apr 25 21:54:14 system: skb_release_data:400 memory 73202825 out of
range!
Apr 25 21:54:14 system: Call backtrace:
Apr 25 21:54:14 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:14 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:14 system: C001B338 C002517C C000876C
Apr 25 21:54:14 system: skb_release_data:400 memory 70526574 out of
range!
Apr 25 21:54:14 system: Call backtrace:
Apr 25 21:54:14 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:14 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:14 system: C001B338 C002517C C000876C
Apr 25 21:54:14 system: skb_release_data:400 memory 203d2025 out of
range!
Apr 25 21:54:14 system: Call backtrace:
Apr 25 21:54:14 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:14 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:14 system: C001B338 C002517C C000876C
Apr 25 21:54:14 system: skb_release_data:400 memory 726f6c42 out of
range!
Apr 25 21:54:14 system: Call backtrace:
Apr 25 21:54:14 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:14 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:14 system: C001B338 C002517C C000876C
Apr 25 21:54:14 system: skb_release_data:400 memory 72616365 out of
range!
Apr 25 21:54:14 system: Call backtrace:
Apr 25 21:54:14 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:14 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:14 system: C001B338 C002517C C000876C
Apr 25 21:54:14 system: skb_release_data:400 memory 32000000 out of
range!
Apr 25 21:54:14 system: Call backtrace:
Apr 25 21:54:14 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:14 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:14 system: C001B338 C002517C C000876C
Apr 25 21:54:14 system: skb_release_data:400 memory 61636b74 out of
range!
Apr 25 21:54:14 system: Call backtrace:
Apr 25 21:54:14 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:14 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:14 system: C001B338 C002517C C000876C
Apr 25 21:54:14 system: skb_release_data:400 memory 54657374 out of
range!
Apr 25 21:54:14 system: Call backtrace:
Apr 25 21:54:14 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:14 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:14 system: C001B338 C002517C C000876C
Apr 25 21:54:15 system: skb_release_data:400 memory 68756875 out of
range!
Apr 25 21:54:15 system: Call backtrace:
Apr 25 21:54:15 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:15 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:15 system: C001B338 C002517C C000876C
Apr 25 21:54:15 system: skb_release_data:400 memory 10015ddc out of
range!
Apr 25 21:54:15 system: Call backtrace:
Apr 25 21:54:15 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:15 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:15 system: C001B338 C002517C C000876C
Apr 25 21:54:15 system: skb_release_data:400 memory 0000ffff out of
range!
Apr 25 21:54:15 system: Call backtrace:
Apr 25 21:54:15 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:15 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:15 system: C001B338 C002517C C000876C
Apr 25 21:54:15 system: skb_release_data:400 memory 64437472 out of
range!
Apr 25 21:54:15 system: Call backtrace:
Apr 25 21:54:15 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:15 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:15 system: C001B338 C002517C C000876C
Apr 25 21:54:15 system: skb_release_data:400 memory 636b0000 out of
range!
Apr 25 21:54:15 system: Call backtrace:
Apr 25 21:54:15 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:15 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
linux-bcm-core (127): soc_counter_thread: DMA did not finish
buf32=cd380000
linux-bcm-core (132): soc_counter_thread: DMA did not finish
buf32=cd389800
linux-bcm-core (130): soc_counter_thread: DMA did not finish
buf32=cd382400
Apr 25 21:54:15 system: C001B338 C002517C C000876C
Apr 25 21:54:15 system: skb_release_data:400 memory 014a5374 out of
range!
Apr 25 21:54:15 system: Call backtrace:
Apr 25 21:54:15 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:15 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:15 system: C001B338 C002517C C000876C
Apr 25 21:54:15 system: skb_release_data:400 memory 7053796e out of
range!
Apr 25 21:54:15 system: Call backtrace:
Apr 25 21:54:15 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:15 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:15 system: C001B338 C002517C C000876C
Apr 25 21:54:15 system: skb_release_data:400 memory ee0e612c out of
range!
Apr 25 21:54:15 system: Call backtrace:
Apr 25 21:54:15 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:15 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:15 system: C001B338 C002517C C000876C
Apr 25 21:54:15 system: skb_release_data:400 memory 076dc419 out of
range!
Apr 25 21:54:15 system: Call backtrace:
Apr 25 21:54:15 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:15 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:15 system: C001B338 C002517C C000876C
Apr 25 21:54:15 system: skb_release_data:400 memory e963a535 out of
range!
Apr 25 21:54:15 system: Call backtrace:
Apr 25 21:54:15 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:15 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:15 system: C001B338 C002517C C000876C
Apr 25 21:54:16 system: skb_release_data:400 memory 0edb8832 out of
range!
Apr 25 21:54:16 system: Call backtrace:
Apr 25 21:54:16 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:16 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:16 system: C001B338 C002517C C000876C
Apr 25 21:54:16 system: skb_release_data:400 memory e0d5e91e out of
range!
Apr 25 21:54:16 system: Call backtrace:
Apr 25 21:54:16 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:16 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:16 system: C001B338 C002517C C000876C
Apr 25 21:54:16 system: skb_release_data:400 memory 09b64c2b out of
range!
Apr 25 21:54:16 system: Call backtrace:
Apr 25 21:54:16 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:16 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:16 system: C001B338 C002517C C000876C
Apr 25 21:54:16 system: skb_release_data:400 memory e7b82d07 out of
range!
Apr 25 21:54:16 system: Call backtrace:
Apr 25 21:54:16 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:16 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:16 system: C001B338 C002517C C000876C
Apr 25 21:54:16 system: skb_release_data:400 memory 1db71064 out of
range!
Apr 25 21:54:16 system: Call backtrace:
Apr 25 21:54:16 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:16 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:16 system: C001B338 C002517C C000876C
Apr 25 21:54:16 system: skb_release_data:400 memory f3b97148 out of
range!
Apr 25 21:54:16 system: Call backtrace:
Apr 25 21:54:16 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:16 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:16 system: C001B338 C002517C C000876C
Apr 25 21:54:16 system: skb_release_data:400 memory 1adad47d out of
range!
Apr 25 21:54:16 system: Call backtrace:
Apr 25 21:54:16 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:16 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:16 system: C001B338 C002517C C000876C
Apr 25 21:54:16 system: skb_release_data:400 memory f4d4b551 out of
range!
Apr 25 21:54:16 system: Call backtrace:
Apr 25 21:54:16 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:16 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:16 system: C001B338 C002517C C000876C
Apr 25 21:54:16 system: skb_release_data:400 memory 136c9856 out of
range!
Apr 25 21:54:16 system: Call backtrace:
Apr 25 21:54:16 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:16 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:16 system: C001B338 C002517C C000876C
Apr 25 21:54:16 system: skb_release_data:400 memory fd62f97a out of
range!
Apr 25 21:54:16 system: Call backtrace:
Apr 25 21:54:16 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:16 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:16 system: C001B338 C002517C C000876C
Apr 25 21:54:16 system: skb_release_data:400 memory 14015c4f out of
range!
Apr 25 21:54:16 system: Call backtrace:
Apr 25 21:54:16 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:16 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:17 system: C001B338 C002517C C000876C
Apr 25 21:54:17 system: skb_release_data:400 memory fa0f3d63 out of
range!
Apr 25 21:54:17 system: Call backtrace:
Apr 25 21:54:17 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:17 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:17 system: C001B338 C002517C C000876C
Apr 25 21:54:17 system: skb_release_data:400 memory 3b6e20c8 out of
range!
Apr 25 21:54:17 system: Call backtrace:
Apr 25 21:54:17 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:17 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:17 system: C001B338 C002517C C000876C
Apr 25 21:54:17 system: skb_release_data:400 memory d56041e4 out of
range!
Apr 25 21:54:17 system: Call backtrace:
Apr 25 21:54:17 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:17 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:17 system: C001B338 C002517C C000876C
Apr 25 21:54:17 system: skb_release_data:400 memory 3c03e4d1 out of
range!
Apr 25 21:54:17 system: Call backtrace:
Apr 25 21:54:17 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:17 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:17 system: C001B338 C002517C C000876C
Apr 25 21:54:17 system: skb_release_data:400 memory d20d85fd out of
range!
Apr 25 21:54:17 system: Call backtrace:
Apr 25 21:54:17 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:17 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
linux-bcm-core (127): soc_counter_thread: DMA did not finish
buf32=cd380000
linux-bcm-core (132): soc_counter_thread: DMA did not finish
buf32=cd389800
linux-bcm-core (130): soc_counter_thread: DMA did not finish
buf32=cd382400
Apr 25 21:54:17 system: C001B338 C002517C C000876C
Apr 25 21:54:17 system: skb_release_data:400 memory 35b5a8fa out of
range!
Apr 25 21:54:17 system: Call backtrace:
Apr 25 21:54:17 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:17 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:17 system: C001B338 C002517C C000876C
Apr 25 21:54:17 system: skb_release_data:400 memory dbbbc9d6 out of
range!
Apr 25 21:54:17 system: Call backtrace:
Apr 25 21:54:17 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:17 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:17 system: C001B338 C002517C C000876C
Apr 25 21:54:17 system: skb_release_data:400 memory 32d86ce3 out of
range!
Apr 25 21:54:17 system: Call backtrace:
Apr 25 21:54:17 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:17 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:17 system: C001B338 C002517C C000876C
Apr 25 21:54:17 system: skb_release_data:400 memory dcd60dcf out of
range!
Apr 25 21:54:17 system: Call backtrace:
Apr 25 21:54:17 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:17 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:17 system: C001B338 C002517C C000876C
Apr 25 21:54:17 system: skb_release_data:400 memory 26d930ac out of
range!
Apr 25 21:54:17 system: Call backtrace:
Apr 25 21:54:17 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:17 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:18 system: C001B338 C002517C C000876C
Apr 25 21:54:18 system: skb_release_data:400 memory 21b4f4b5 out of
range!
Apr 25 21:54:18 system: Call backtrace:
Apr 25 21:54:18 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:18 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:18 system: C001B338 C002517C C000876C
Apr 25 21:54:18 system: skb_release_data:400 memory cfba9599 out of
range!
Apr 25 21:54:18 system: Call backtrace:
Apr 25 21:54:18 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:18 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:18 system: C001B338 C002517C C000876C
Apr 25 21:54:18 system: skb_release_data:400 memory 2802b89e out of
range!
Apr 25 21:54:18 system: Call backtrace:
Apr 25 21:54:18 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:18 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:18 system: C001B338 C002517C C000876C
Apr 25 21:54:18 system: skb_release_data:400 memory 2f6f7c87 out of
range!
Apr 25 21:54:18 system: Call backtrace:
Apr 25 21:54:18 system: C011D8CC C011B720 C011B7D0 C011B9C8 C011BC24
C01496CC C014A054
Apr 25 21:54:18 system: C014D380 C0156584 C0156B70 C0137B08 C0137FD8
C0120B9C C0120C58
Apr 25 21:54:18 system: C001B338 C002517C C000876C
Apr 25 21:54:18 system: Oops: Exception in kernel mode, sig: 7
Apr 25 21:54:18 system: NIP: C0034138 XER: 20000000 LR: C011B73C SP:
C04E3D20 REGS: c04e3c70 TRAP: 0600 Not tainted
Apr 25 21:54:18 system: MSR: 00009032 EE: 1 PR: 0 FP: 0 ME: 1 IR/DR: 11
Apr 25 21:54:18 system: DAR: C1611DBF, DSISR: 00010920
Apr 25 21:54:18 system: TASK = c04e2000[2] 'keventd' Last syscall: 120
Apr 25 21:54:18 system: last math cb0f8000 last altivec 00000000
Apr 25 21:54:18 system: GPR00: C1611DBF C04E3D20 C04E2000 C1611DAB
00000000 00000190 C1611DAB 0003CAEC
Apr 25 21:54:18 system: GPR08: C0F98B04 D1C8201A C0F5C018 C0230000
22002024 1031E1BC 0FFD5000 1009B000
Apr 25 21:54:18 system: GPR16: 00000000 00000000 00000000 00000000
003FF000 00000001 00000000 C01E0000
Apr 25 21:54:18 system: GPR24: C01F0000 06D01B7F C04E3E18 00000001
C01D0000 0000158E 0000AC70 C3442DA0
Apr 25 21:54:18 system: TESCR1 0xf0010040: 00100000 TESCR2 0xf0010044:
00000000
Apr 25 21:54:18 system: ESR 0xf0010884: 00000000
Apr 25 21:54:18 system: PCI_EACR 0xf0010890: 0000000c
Apr 25 21:54:18 system: PCI_EDCR 0xf0010898: 00000000
Apr 25 21:54:18 system: PCI_ECCR 0xf00108a0: 00000000
[-- Attachment #2: Type: text/html, Size: 48110 bytes --]
^ permalink raw reply
* Re: [PATCH] [POWERPC] convert transfer_to_handler into a macro
From: Scott Wood @ 2008-04-29 18:35 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <Pine.LNX.4.64.0804290856210.9230@blarg.am.freescale.net>
On Tue, Apr 29, 2008 at 08:56:56AM -0500, Kumar Gala wrote:
> +#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
> +#ifdef CONFIG_SMP
> +#define SMP_ADJUST_GLOBAL_DBCR0 \
> + rlwinm r9,r1,0,0,(31-THREAD_SHIFT); \
> + lwz r9,TI_CPU(r9); \
> + slwi r9,r9,3; \
> + add r11,r11,r9;
> +#else
> +#define SMP_ADJUST_GLOBAL_DBCR0
> +#endif
> +#define HANDLE_DBCR \
> + /* Check to see if the dbcr0 register is set up to debug. Use the \
> + internal debug mode bit to do this. */ \
> + lwz r12,THREAD_DBCR0(r12); \
> + andis. r12,r12,DBCR0_IDM@h; \
Can we use assembler macros rather than preprocessor macros to get rid of
the backslashes?
-Scott
^ permalink raw reply
* Re: [PATCH] Add fast little-endian switch system call
From: Wolfgang Denk @ 2008-04-29 18:40 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linux-arch, linuxppc-dev, Christoph Hellwig, mtk.manpages
In-Reply-To: <18454.35824.527711.355488@cargo.ozlabs.ibm.com>
In message <18454.35824.527711.355488@cargo.ozlabs.ibm.com> you wrote:
>
> > Am I missing something here or does this add a branch for every normal
> > syscall?
>
> It does, but the impact is so small as to be unmeasurable with
> lmbench, even on the null syscall measurement. The overhead of the
> easily-predicted not-taken branch is completely swamped by the amount
> of time that the sc and rfid instructions take. I had it under a
> config option at one point but then decided not to bother with that
> when I couldn't measure any difference.
This probably depends a bit on the performance of the system in
question. Did you measure it - for example - on a 50 MHz MPC850 ?
Best regards,
Wolfgang Denk
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
To get something done, a committee should consist of no more than
three men, two of them absent.
^ permalink raw reply
* Re: [PATCH] Add fast little-endian switch system call
From: Christoph Hellwig @ 2008-04-29 18:46 UTC (permalink / raw)
To: Wolfgang Denk
Cc: linux-arch, linuxppc-dev, Paul Mackerras, Christoph Hellwig,
mtk.manpages
In-Reply-To: <20080429184047.47CB7247B4@gemini.denx.de>
On Tue, Apr 29, 2008 at 08:40:47PM +0200, Wolfgang Denk wrote:
> This probably depends a bit on the performance of the system in
> question. Did you measure it - for example - on a 50 MHz MPC850 ?
You got a 64bit kernel to run on a MPC850? wow :)
Not sure what the slowest supported 64bit cpu is (RS64-II?), but Paul
might be right and in this case it really doesn't matter.
^ permalink raw reply
* [PATCH 0/6 v4] Few more patches for Kumar's powerpc.git
From: Anton Vorontsov @ 2008-04-29 18:59 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
Hi Kumar,
Here is the fourth version. Old one started to cause non trivial merge
conflicts.
Also, I re-exported the gtm_timer structure, so drivers could actually
use its irq member.
Thanks.
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply
* [PATCH 1/6] [POWERPC] sysdev: implement FSL GTM support
From: Anton Vorontsov @ 2008-04-29 19:00 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <20080429185920.GA19735@polina.dev.rtsoft.ru>
GTM stands for General-purpose Timers Module and able to generate
timer{1,2,3,4} interrupts. These timers are used by the drivers that
need time precise interrupts (like for USB transactions scheduling for
the Freescale USB Host controller as found in some QE and CPM chips),
or these timers could be used as wakeup events from the CPU deep-sleep
mode.
Things unimplemented:
1. Cascaded (32 bit) timers (1-2, 3-4).
This is straightforward to implement when needed, two timers should
be marked as "requested" and configured as appropriate.
2. Super-cascaded (64 bit) timers (1-2-3-4).
This is also straightforward to implement when needed, all timers
should be marked as "requested" and configured as appropriate.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
Documentation/powerpc/booting-without-of.txt | 37 +++-
arch/powerpc/Kconfig | 5 +
arch/powerpc/sysdev/Makefile | 1 +
arch/powerpc/sysdev/fsl_gtm.c | 424 ++++++++++++++++++++++++++
include/asm-powerpc/fsl_gtm.h | 47 +++
5 files changed, 513 insertions(+), 1 deletions(-)
create mode 100644 arch/powerpc/sysdev/fsl_gtm.c
create mode 100644 include/asm-powerpc/fsl_gtm.h
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index 1d2a772..fc7a235 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -57,7 +57,10 @@ Table of Contents
n) 4xx/Axon EMAC ethernet nodes
o) Xilinx IP cores
p) Freescale Synchronous Serial Interface
- q) USB EHCI controllers
+ q) USB EHCI controllers
+ r) Freescale Display Interface Unit
+ s) Freescale on board FPGA
+ t) Freescale General-purpose Timers Module
VII - Marvell Discovery mv64[345]6x System Controller chips
1) The /system-controller node
@@ -2870,6 +2873,38 @@ platforms are moved over to use the flattened-device-tree model.
reg = <0xe8000000 32>;
};
+ t) Freescale General-purpose Timers Module
+
+ Required properties:
+ - compatible : should be
+ "fsl,<chip>-gtm", "fsl,gtm" for SOC GTMs
+ "fsl,<chip>-qe-gtm", "fsl,qe-gtm", "fsl,gtm" for QE GTMs
+ "fsl,<chip>-cpm2-gtm", "fsl,cpm2-gtm", "fsl,gtm" for CPM2 GTMs
+ - reg : should contain gtm registers location and length (0x40).
+ - interrupts : should contain four interrupts.
+ - interrupt-parent : interrupt source phandle.
+ - clock-frequency : specifies the frequency driving the timer.
+
+ Example:
+
+ timer@500 {
+ compatible = "fsl,mpc8360-gtm", "fsl,gtm";
+ reg = <0x500 0x40>;
+ interrupts = <90 8 78 8 84 8 72 8>;
+ interrupt-parent = <&ipic>;
+ /* filled by u-boot */
+ clock-frequency = <0>;
+ };
+
+ timer@440 {
+ compatible = "fsl,mpc8360-qe-gtm", "fsl,qe-gtm", "fsl,gtm";
+ reg = <0x440 0x40>;
+ interrupts = <12 13 14 15>;
+ interrupt-parent = <&qeic>;
+ /* filled by u-boot */
+ clock-frequency = <0>;
+ };
+
VII - Marvell Discovery mv64[345]6x System Controller chips
===========================================================
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 4e40c12..4070a78 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -538,6 +538,11 @@ config FSL_LBC
help
Freescale Localbus support
+config FSL_GTM
+ bool
+ help
+ Freescale General-purpose Timers support
+
# Yes MCA RS/6000s exist but Linux-PPC does not currently support any
config MCA
bool
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 6d386d0..9d3ddd2 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
obj-$(CONFIG_FSL_SOC) += fsl_soc.o
obj-$(CONFIG_FSL_PCI) += fsl_pci.o
obj-$(CONFIG_FSL_LBC) += fsl_lbc.o
+obj-$(CONFIG_FSL_GTM) += fsl_gtm.o
obj-$(CONFIG_RAPIDIO) += fsl_rio.o
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
diff --git a/arch/powerpc/sysdev/fsl_gtm.c b/arch/powerpc/sysdev/fsl_gtm.c
new file mode 100644
index 0000000..8b35cc4
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_gtm.c
@@ -0,0 +1,424 @@
+/*
+ * Freescale General-purpose Timers Module
+ *
+ * Copyright (c) Freescale Semicondutor, Inc. 2006.
+ * Shlomi Gridish <gridish@freescale.com>
+ * Jerry Huang <Chang-Ming.Huang@freescale.com>
+ * Copyright (c) MontaVista Software, Inc. 2008.
+ * Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <asm/fsl_gtm.h>
+
+#define GTCFR_STP(x) ((x) & 1 ? 1 << 5 : 1 << 1)
+#define GTCFR_RST(x) ((x) & 1 ? 1 << 4 : 1 << 0)
+
+#define GTMDR_ICLK_MASK (3 << 1)
+#define GTMDR_ICLK_ICAS (0 << 1)
+#define GTMDR_ICLK_ICLK (1 << 1)
+#define GTMDR_ICLK_SLGO (2 << 1)
+#define GTMDR_FRR (1 << 3)
+#define GTMDR_ORI (1 << 4)
+#define GTMDR_SPS(x) ((x) << 8)
+
+struct gtm_timers_regs {
+ u8 gtcfr1; /* Timer 1, Timer 2 global config register */
+ u8 res0[0x3];
+ u8 gtcfr2; /* Timer 3, timer 4 global config register */
+ u8 res1[0xB];
+ __be16 gtmdr1; /* Timer 1 mode register */
+ __be16 gtmdr2; /* Timer 2 mode register */
+ __be16 gtrfr1; /* Timer 1 reference register */
+ __be16 gtrfr2; /* Timer 2 reference register */
+ __be16 gtcpr1; /* Timer 1 capture register */
+ __be16 gtcpr2; /* Timer 2 capture register */
+ __be16 gtcnr1; /* Timer 1 counter */
+ __be16 gtcnr2; /* Timer 2 counter */
+ __be16 gtmdr3; /* Timer 3 mode register */
+ __be16 gtmdr4; /* Timer 4 mode register */
+ __be16 gtrfr3; /* Timer 3 reference register */
+ __be16 gtrfr4; /* Timer 4 reference register */
+ __be16 gtcpr3; /* Timer 3 capture register */
+ __be16 gtcpr4; /* Timer 4 capture register */
+ __be16 gtcnr3; /* Timer 3 counter */
+ __be16 gtcnr4; /* Timer 4 counter */
+ __be16 gtevr1; /* Timer 1 event register */
+ __be16 gtevr2; /* Timer 2 event register */
+ __be16 gtevr3; /* Timer 3 event register */
+ __be16 gtevr4; /* Timer 4 event register */
+ __be16 gtpsr1; /* Timer 1 prescale register */
+ __be16 gtpsr2; /* Timer 2 prescale register */
+ __be16 gtpsr3; /* Timer 3 prescale register */
+ __be16 gtpsr4; /* Timer 4 prescale register */
+ u8 res2[0x40];
+} __attribute__ ((packed));
+
+struct gtm {
+ unsigned int clock;
+ struct gtm_timers_regs __iomem *regs;
+ struct gtm_timer timers[4];
+ spinlock_t lock;
+ struct list_head list_node;
+};
+
+static LIST_HEAD(gtms);
+
+/**
+ * gtm_get_timer - request GTM timer to use it with the rest of GTM API
+ * @width: timer width (only 16 bits wide timers implemented so far)
+ *
+ * This function reserves GTM timer for later use. It returns gtm_timer
+ * structure to use with the rest of GTM API, you should use timer->irq
+ * to manage timer interrupt.
+ */
+struct gtm_timer *gtm_get_timer(int width)
+{
+ struct gtm *gtm = NULL;
+ int i;
+
+ if (width != 16)
+ return ERR_PTR(-ENOSYS);
+
+ list_for_each_entry(gtm, >ms, list_node) {
+ spin_lock_irq(>m->lock);
+
+ for (i = 0; i < ARRAY_SIZE(gtm->timers); i++) {
+ if (!gtm->timers[i].requested) {
+ gtm->timers[i].requested = true;
+ spin_unlock_irq(>m->lock);
+ return >m->timers[i];
+ }
+ }
+
+ spin_unlock_irq(>m->lock);
+ }
+
+ if (gtm)
+ return ERR_PTR(-EBUSY);
+ return ERR_PTR(-ENODEV);
+}
+EXPORT_SYMBOL(gtm_get_timer);
+
+/**
+ * gtm_get_specific_timer - request specific GTM timer
+ * @gtm: specific GTM, pass here GTM's device_node->data
+ * @timer: specific timer number, Timer1 is 0.
+ * @width: timer width (only 16 bits wide timers implemented so far)
+ *
+ * This function reserves GTM timer for later use. It returns gtm_timer
+ * structure to use with the rest of GTM API, you should use timer->irq
+ * to manage timer interrupt.
+ */
+struct gtm_timer *gtm_get_specific_timer(struct gtm *gtm, int timer, int width)
+{
+ struct gtm_timer *ret = ERR_PTR(-EBUSY);
+
+ if (width != 16)
+ return ERR_PTR(-ENOSYS);
+
+ spin_lock_irq(>m->lock);
+
+ if (gtm->timers[timer].requested)
+ goto out;
+
+ ret = >m->timers[timer];
+ ret->requested = true;
+
+out:
+ spin_unlock_irq(>m->lock);
+ return ret;
+}
+EXPORT_SYMBOL(gtm_get_specific_timer);
+
+/**
+ * gtm_put_timer - release GTM timer
+ * @width: timer width (only 16 bits wide timers implemented so far)
+ *
+ * This function releases GTM timer so others may request it.
+ */
+void gtm_put_timer(struct gtm_timer *tmr)
+{
+ spin_lock_irq(&tmr->gtm->lock);
+
+ tmr->requested = false;
+
+ spin_unlock_irq(&tmr->gtm->lock);
+}
+EXPORT_SYMBOL(gtm_put_timer);
+
+/*
+ * This is back-end for the exported functions, it's used to reset single
+ * timer in reference mode.
+ */
+static int gtm_reset_ref_timer16(struct gtm_timer *tmr, int frequency,
+ int reference_value, bool free_run)
+{
+ struct gtm *gtm = tmr->gtm;
+ int num = tmr - >m->timers[0];
+ unsigned int prescaler;
+ u8 iclk = GTMDR_ICLK_ICLK;
+ u8 psr;
+ u8 sps;
+ unsigned long flags;
+ int max_prescaler = 256 * 256 * 16;
+
+ /* CPM2 doesn't have primary prescaler */
+ if (!tmr->gtpsr)
+ max_prescaler /= 256;
+
+ prescaler = gtm->clock / frequency;
+ /*
+ * We have two 8 bit prescalers -- primary and secondary (psr, sps),
+ * plus "slow go" mode (clk / 16). So, total prescale value is
+ * 16 * (psr + 1) * (sps + 1). Though, for CPM2 GTMs we losing psr.
+ */
+ if (prescaler > max_prescaler)
+ return -EINVAL;
+
+ if (prescaler > max_prescaler / 16) {
+ iclk = GTMDR_ICLK_SLGO;
+ prescaler /= 16;
+ }
+
+ if (prescaler <= 256) {
+ psr = 0;
+ sps = prescaler - 1;
+ } else {
+ psr = 256 - 1;
+ sps = prescaler / 256 - 1;
+ }
+
+ spin_lock_irqsave(>m->lock, flags);
+
+ /*
+ * Properly reset timers: stop, reset, set up prescalers, reference
+ * value and clear event register.
+ */
+ clrsetbits_8(tmr->gtcfr, ~(GTCFR_STP(num) | GTCFR_RST(num)),
+ GTCFR_STP(num) | GTCFR_RST(num));
+
+ setbits8(tmr->gtcfr, GTCFR_STP(num));
+
+ if (tmr->gtpsr)
+ out_be16(tmr->gtpsr, psr);
+ clrsetbits_be16(tmr->gtmdr, 0xFFFF, iclk | GTMDR_SPS(sps) |
+ GTMDR_ORI | (free_run ? GTMDR_FRR : 0));
+ out_be16(tmr->gtcnr, 0);
+ out_be16(tmr->gtrfr, reference_value);
+ out_be16(tmr->gtevr, 0xFFFF);
+
+ /* Let it be. */
+ clrbits8(tmr->gtcfr, GTCFR_STP(num));
+
+ spin_unlock_irqrestore(>m->lock, flags);
+
+ return 0;
+}
+/**
+ * gtm_reset_timer16 - reset 16 bit timer with arbitrary precision
+ * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
+ * @usec: timer interval in microseconds
+ * @reload: if set, the timer will reset upon expiry rather than
+ * continue running free.
+ *
+ * This function (re)sets the GTM timer so that it counts up to the requested
+ * interval value, and fires the interrupt when the value is reached. This
+ * function will reduce the precision of the timer as needed in order for the
+ * requested timeout to fit in a 16-bit register.
+ */
+int gtm_reset_timer16(struct gtm_timer *tmr, unsigned long usec, bool reload)
+{
+ /* quite obvious, frequency which is enough for µSec precision */
+ int freq = 1000000;
+ unsigned int bit;
+
+ bit = fls_long(usec);
+ if (bit > 15) {
+ freq >>= bit - 15;
+ usec >>= bit - 15;
+ }
+
+ if (!freq)
+ return -EINVAL;
+
+ return gtm_reset_ref_timer16(tmr, freq, usec, reload);
+}
+EXPORT_SYMBOL(gtm_reset_timer16);
+
+/**
+ * gtm_reset_utimer16 - reset 16 bits timer
+ * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
+ * @usec: timer interval in microseconds
+ * @reload: if set, the timer will reset upon expiry rather than
+ * continue running free.
+ *
+ * This function (re)sets GTM timer so that it counts up to the requested
+ * interval value, and fires the interrupt when the value is reached. If reload
+ * flag was set, timer will also reset itself upon reference value, otherwise
+ * it continues to increment.
+ */
+int gtm_reset_utimer16(struct gtm_timer *tmr, u16 usec, bool reload)
+{
+ /* quite obvious, frequency which is enough for µSec precision */
+ const int freq = 1000000;
+
+ /*
+ * We can lower the frequency (and probably power consumption) by
+ * dividing both frequency and usec by 2 until there is no remainder.
+ * But we won't bother with this unless savings are measured, so just
+ * run the timer as is.
+ */
+
+ return gtm_reset_ref_timer16(tmr, freq, usec, reload);
+}
+EXPORT_SYMBOL(gtm_reset_utimer16);
+
+/**
+ * gtm_stop_timer16 - stop single timer
+ * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
+ *
+ * This function simply stops the GTM timer.
+ */
+void gtm_stop_timer16(struct gtm_timer *tmr)
+{
+ struct gtm *gtm = tmr->gtm;
+ int num = tmr - >m->timers[0];
+ unsigned long flags;
+
+ spin_lock_irqsave(>m->lock, flags);
+
+ setbits8(tmr->gtcfr, GTCFR_STP(num));
+ out_be16(tmr->gtevr, 0xFFFF);
+
+ spin_unlock_irqrestore(>m->lock, flags);
+}
+EXPORT_SYMBOL(gtm_stop_timer16);
+
+/**
+ * gtm_ack_timer16 - acknowledge timer event (free-run timers only)
+ * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
+ * @events: events mask to ack
+ *
+ * Thus function used to acknowledge timer interrupt event, use it inside the
+ * interrupt handler.
+ */
+void gtm_ack_timer16(struct gtm_timer *tmr, u16 events)
+{
+ out_be16(tmr->gtevr, events);
+}
+EXPORT_SYMBOL(gtm_ack_timer16);
+
+static void __init gtm_set_shortcuts(struct device_node *np,
+ struct gtm_timer *timers,
+ struct gtm_timers_regs __iomem *regs)
+{
+ /*
+ * Yeah, I don't like this either, but timers' registers a bit messed,
+ * so we have to provide shortcuts to write timer independent code.
+ * Alternative option is to create gt*() accessors, but that will be
+ * even uglier and cryptic.
+ */
+ timers[0].gtcfr = ®s->gtcfr1;
+ timers[0].gtmdr = ®s->gtmdr1;
+ timers[0].gtcnr = ®s->gtcnr1;
+ timers[0].gtrfr = ®s->gtrfr1;
+ timers[0].gtevr = ®s->gtevr1;
+
+ timers[1].gtcfr = ®s->gtcfr1;
+ timers[1].gtmdr = ®s->gtmdr2;
+ timers[1].gtcnr = ®s->gtcnr2;
+ timers[1].gtrfr = ®s->gtrfr2;
+ timers[1].gtevr = ®s->gtevr2;
+
+ timers[2].gtcfr = ®s->gtcfr2;
+ timers[2].gtmdr = ®s->gtmdr3;
+ timers[2].gtcnr = ®s->gtcnr3;
+ timers[2].gtrfr = ®s->gtrfr3;
+ timers[2].gtevr = ®s->gtevr3;
+
+ timers[3].gtcfr = ®s->gtcfr2;
+ timers[3].gtmdr = ®s->gtmdr4;
+ timers[3].gtcnr = ®s->gtcnr4;
+ timers[3].gtrfr = ®s->gtrfr4;
+ timers[3].gtevr = ®s->gtevr4;
+
+ /* CPM2 doesn't have primary prescaler */
+ if (!of_device_is_compatible(np, "fsl,cpm2-gtm")) {
+ timers[0].gtpsr = ®s->gtpsr1;
+ timers[1].gtpsr = ®s->gtpsr2;
+ timers[2].gtpsr = ®s->gtpsr3;
+ timers[3].gtpsr = ®s->gtpsr4;
+ }
+}
+
+void __init fsl_gtm_init(void)
+{
+ struct device_node *np;
+
+ for_each_compatible_node(np, NULL, "fsl,gtm") {
+ int i;
+ struct gtm *gtm;
+ const u32 *clock;
+ int size;
+
+ gtm = kzalloc(sizeof(*gtm), GFP_KERNEL);
+ if (!gtm) {
+ pr_err("%s: unable to allocate memory\n",
+ np->full_name);
+ continue;
+ }
+
+ spin_lock_init(>m->lock);
+
+ clock = of_get_property(np, "clock-frequency", &size);
+ if (!clock || size != sizeof(*clock)) {
+ pr_err("%s: no clock-frequency\n", np->full_name);
+ goto err;
+ }
+ gtm->clock = *clock;
+
+ for (i = 0; i < ARRAY_SIZE(gtm->timers); i++) {
+ int ret;
+ struct resource irq;
+
+ ret = of_irq_to_resource(np, i, &irq);
+ if (ret == NO_IRQ) {
+ pr_err("%s: not enough interrupts specified\n",
+ np->full_name);
+ goto err;
+ }
+ gtm->timers[i].irq = irq.start;
+ gtm->timers[i].gtm = gtm;
+ }
+
+ gtm->regs = of_iomap(np, 0);
+ if (!gtm->regs) {
+ pr_err("%s: unable to iomap registers\n",
+ np->full_name);
+ goto err;
+ }
+
+ gtm_set_shortcuts(np, gtm->timers, gtm->regs);
+ list_add(>m->list_node, >ms);
+
+ /* We don't want to lose the node and its ->data */
+ np->data = gtm;
+ of_node_get(np);
+
+ continue;
+err:
+ kfree(gtm);
+ }
+}
diff --git a/include/asm-powerpc/fsl_gtm.h b/include/asm-powerpc/fsl_gtm.h
new file mode 100644
index 0000000..49f1240
--- /dev/null
+++ b/include/asm-powerpc/fsl_gtm.h
@@ -0,0 +1,47 @@
+/*
+ * Freescale General-purpose Timers Module
+ *
+ * Copyright (c) Freescale Semicondutor, Inc. 2006.
+ * Shlomi Gridish <gridish@freescale.com>
+ * Jerry Huang <Chang-Ming.Huang@freescale.com>
+ * Copyright (c) MontaVista Software, Inc. 2008.
+ * Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_FSL_GTM_H
+#define __ASM_FSL_GTM_H
+
+#include <linux/types.h>
+
+struct gtm;
+
+struct gtm_timer {
+ unsigned int irq;
+
+ struct gtm *gtm;
+ bool requested;
+ u8 __iomem *gtcfr;
+ __be16 __iomem *gtmdr;
+ __be16 __iomem *gtpsr;
+ __be16 __iomem *gtcnr;
+ __be16 __iomem *gtrfr;
+ __be16 __iomem *gtevr;
+};
+
+extern void __init fsl_gtm_init(void);
+extern struct gtm_timer *gtm_get_timer(int width);
+extern struct gtm_timer *gtm_get_specific_timer(struct gtm *gtm, int timer,
+ int width);
+extern void gtm_put_timer(struct gtm_timer *tmr);
+extern int gtm_reset_timer16(struct gtm_timer *tmr, unsigned long usec,
+ bool reload);
+extern int gtm_reset_utimer16(struct gtm_timer *tmr, u16 usec, bool reload);
+extern void gtm_stop_timer16(struct gtm_timer *tmr);
+extern void gtm_ack_timer16(struct gtm_timer *tmr, u16 events);
+
+#endif /* __ASM_FSL_GTM_H */
--
1.5.5.1
^ permalink raw reply related
* [PATCH 2/6] [POWERPC] QE: add support for QE USB clocks routing
From: Anton Vorontsov @ 2008-04-29 19:00 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <20080429185920.GA19735@polina.dev.rtsoft.ru>
This patch adds a function to the qe_lib to setup QE USB clocks routing.
To setup clocks safely, cmxgcr register needs locking, so I just reused
ucc_lock since it was used only to protect cmxgcr.
The idea behind placing clocks routing functions into the qe_lib is that
later we'll hopefully switch to the generic Linux Clock API, thus, for
example, FHCI driver may be used for QE and CPM chips without nasty #ifdefs.
This patch also fixes QE_USB_RESTART_TX command definition in the qe.h.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
arch/powerpc/sysdev/qe_lib/Kconfig | 4 ++
arch/powerpc/sysdev/qe_lib/Makefile | 1 +
arch/powerpc/sysdev/qe_lib/ucc.c | 7 ++--
arch/powerpc/sysdev/qe_lib/usb.c | 56 +++++++++++++++++++++++++++++++++++
include/asm-powerpc/qe.h | 23 +++++++++++++-
5 files changed, 87 insertions(+), 4 deletions(-)
create mode 100644 arch/powerpc/sysdev/qe_lib/usb.c
diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig
index adc6621..76ffbc4 100644
--- a/arch/powerpc/sysdev/qe_lib/Kconfig
+++ b/arch/powerpc/sysdev/qe_lib/Kconfig
@@ -20,3 +20,7 @@ config UCC
bool
default y if UCC_FAST || UCC_SLOW
+config QE_USB
+ bool
+ help
+ QE USB Host Controller support
diff --git a/arch/powerpc/sysdev/qe_lib/Makefile b/arch/powerpc/sysdev/qe_lib/Makefile
index 874fe1a..e9ff888 100644
--- a/arch/powerpc/sysdev/qe_lib/Makefile
+++ b/arch/powerpc/sysdev/qe_lib/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_QUICC_ENGINE)+= qe.o qe_ic.o qe_io.o
obj-$(CONFIG_UCC) += ucc.o
obj-$(CONFIG_UCC_SLOW) += ucc_slow.o
obj-$(CONFIG_UCC_FAST) += ucc_fast.o
+obj-$(CONFIG_QE_USB) += usb.o
diff --git a/arch/powerpc/sysdev/qe_lib/ucc.c b/arch/powerpc/sysdev/qe_lib/ucc.c
index 0e348d9..d3c7f5a 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc.c
@@ -26,7 +26,8 @@
#include <asm/qe.h>
#include <asm/ucc.h>
-static DEFINE_SPINLOCK(ucc_lock);
+DEFINE_SPINLOCK(cmxgcr_lock);
+EXPORT_SYMBOL(cmxgcr_lock);
int ucc_set_qe_mux_mii_mng(unsigned int ucc_num)
{
@@ -35,10 +36,10 @@ int ucc_set_qe_mux_mii_mng(unsigned int ucc_num)
if (ucc_num > UCC_MAX_NUM - 1)
return -EINVAL;
- spin_lock_irqsave(&ucc_lock, flags);
+ spin_lock_irqsave(&cmxgcr_lock, flags);
clrsetbits_be32(&qe_immr->qmx.cmxgcr, QE_CMXGCR_MII_ENET_MNG,
ucc_num << QE_CMXGCR_MII_ENET_MNG_SHIFT);
- spin_unlock_irqrestore(&ucc_lock, flags);
+ spin_unlock_irqrestore(&cmxgcr_lock, flags);
return 0;
}
diff --git a/arch/powerpc/sysdev/qe_lib/usb.c b/arch/powerpc/sysdev/qe_lib/usb.c
new file mode 100644
index 0000000..69ce78c
--- /dev/null
+++ b/arch/powerpc/sysdev/qe_lib/usb.c
@@ -0,0 +1,56 @@
+/*
+ * QE USB routines
+ *
+ * Copyright (c) Freescale Semicondutor, Inc. 2006.
+ * Shlomi Gridish <gridish@freescale.com>
+ * Jerry Huang <Chang-Ming.Huang@freescale.com>
+ * Copyright (c) MontaVista Software, Inc. 2008.
+ * Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <asm/immap_qe.h>
+#include <asm/qe.h>
+
+int qe_usb_clock_set(enum qe_clock clk, int rate)
+{
+ struct qe_mux __iomem *mux = &qe_immr->qmx;
+ unsigned long flags;
+ u32 val;
+
+ switch (clk) {
+ case QE_CLK3: val = QE_CMXGCR_USBCS_CLK3; break;
+ case QE_CLK5: val = QE_CMXGCR_USBCS_CLK5; break;
+ case QE_CLK7: val = QE_CMXGCR_USBCS_CLK7; break;
+ case QE_CLK9: val = QE_CMXGCR_USBCS_CLK9; break;
+ case QE_CLK13: val = QE_CMXGCR_USBCS_CLK13; break;
+ case QE_CLK17: val = QE_CMXGCR_USBCS_CLK17; break;
+ case QE_CLK19: val = QE_CMXGCR_USBCS_CLK19; break;
+ case QE_CLK21: val = QE_CMXGCR_USBCS_CLK21; break;
+ case QE_BRG9: val = QE_CMXGCR_USBCS_BRG9; break;
+ case QE_BRG10: val = QE_CMXGCR_USBCS_BRG10; break;
+ default:
+ pr_err("%s: requested unknown clock %d\n", __func__, clk);
+ return -EINVAL;
+ }
+
+ if (qe_clock_is_brg(clk))
+ qe_setbrg(clk, rate, 1);
+
+ spin_lock_irqsave(&cmxgcr_lock, flags);
+
+ clrsetbits_be32(&mux->cmxgcr, QE_CMXGCR_USBCS, val);
+
+ spin_unlock_irqrestore(&cmxgcr_lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(qe_usb_clock_set);
diff --git a/include/asm-powerpc/qe.h b/include/asm-powerpc/qe.h
index c3be6e2..d217288 100644
--- a/include/asm-powerpc/qe.h
+++ b/include/asm-powerpc/qe.h
@@ -16,6 +16,7 @@
#define _ASM_POWERPC_QE_H
#ifdef __KERNEL__
+#include <linux/spinlock.h>
#include <asm/immap_qe.h>
#define QE_NUM_OF_SNUM 28
@@ -74,6 +75,13 @@ enum qe_clock {
QE_CLK_DUMMY
};
+static inline bool qe_clock_is_brg(enum qe_clock clk)
+{
+ return clk >= QE_BRG1 && clk <= QE_BRG16;
+}
+
+extern spinlock_t cmxgcr_lock;
+
/* Export QE common operations */
extern void qe_reset(void);
extern int par_io_init(struct device_node *np);
@@ -156,6 +164,9 @@ int qe_upload_firmware(const struct qe_firmware *firmware);
/* Obtain information on the uploaded firmware */
struct qe_firmware_info *qe_get_firmware_info(void);
+/* QE USB */
+int qe_usb_clock_set(enum qe_clock clk, int rate);
+
/* Buffer descriptors */
struct qe_bd {
__be16 status;
@@ -254,6 +265,16 @@ enum comm_dir {
#define QE_CMXGCR_MII_ENET_MNG 0x00007000
#define QE_CMXGCR_MII_ENET_MNG_SHIFT 12
#define QE_CMXGCR_USBCS 0x0000000f
+#define QE_CMXGCR_USBCS_CLK3 0x1
+#define QE_CMXGCR_USBCS_CLK5 0x2
+#define QE_CMXGCR_USBCS_CLK7 0x3
+#define QE_CMXGCR_USBCS_CLK9 0x4
+#define QE_CMXGCR_USBCS_CLK13 0x5
+#define QE_CMXGCR_USBCS_CLK17 0x6
+#define QE_CMXGCR_USBCS_CLK19 0x7
+#define QE_CMXGCR_USBCS_CLK21 0x8
+#define QE_CMXGCR_USBCS_BRG9 0x9
+#define QE_CMXGCR_USBCS_BRG10 0xa
/* QE CECR Commands.
*/
@@ -283,7 +304,7 @@ enum comm_dir {
#define QE_HPAC_START_TX 0x0000060b
#define QE_HPAC_START_RX 0x0000070b
#define QE_USB_STOP_TX 0x0000000a
-#define QE_USB_RESTART_TX 0x0000000b
+#define QE_USB_RESTART_TX 0x0000000c
#define QE_QMC_STOP_TX 0x0000000c
#define QE_QMC_STOP_RX 0x0000000d
#define QE_SS7_SU_FIL_RESET 0x0000000e
--
1.5.5.1
^ permalink raw reply related
* [PATCH 3/6] [POWERPC] QE: prepare QE PIO code for GPIO LIB support
From: Anton Vorontsov @ 2008-04-29 19:00 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <20080429185920.GA19735@polina.dev.rtsoft.ru>
- split and export __par_io_config_pin() out of par_io_config_pin(), so we
could use the prefixed version with GPIO LIB API;
- rename struct port_regs to qe_pio_regs, and place it into qe.h;
- rename #define NUM_OF_PINS to QE_PIO_PINS, and place it into qe.h.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
arch/powerpc/sysdev/qe_lib/qe_io.c | 94 +++++++++++++++++-------------------
include/asm-powerpc/qe.h | 19 +++++++
2 files changed, 64 insertions(+), 49 deletions(-)
diff --git a/arch/powerpc/sysdev/qe_lib/qe_io.c b/arch/powerpc/sysdev/qe_lib/qe_io.c
index 93916a4..7c87460 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_io.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_io.c
@@ -28,21 +28,7 @@
#undef DEBUG
-#define NUM_OF_PINS 32
-
-struct port_regs {
- __be32 cpodr; /* Open drain register */
- __be32 cpdata; /* Data register */
- __be32 cpdir1; /* Direction register */
- __be32 cpdir2; /* Direction register */
- __be32 cppar1; /* Pin assignment register */
- __be32 cppar2; /* Pin assignment register */
-#ifdef CONFIG_PPC_85xx
- u8 pad[8];
-#endif
-};
-
-static struct port_regs __iomem *par_io;
+static struct qe_pio_regs __iomem *par_io;
static int num_par_io_ports = 0;
int par_io_init(struct device_node *np)
@@ -64,69 +50,79 @@ int par_io_init(struct device_node *np)
return 0;
}
-int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
- int assignment, int has_irq)
+void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin, int dir,
+ int open_drain, int assignment, int has_irq)
{
- u32 pin_mask1bit, pin_mask2bits, new_mask2bits, tmp_val;
-
- if (!par_io)
- return -1;
+ u32 pin_mask1bit;
+ u32 pin_mask2bits;
+ u32 new_mask2bits;
+ u32 tmp_val;
/* calculate pin location for single and 2 bits information */
- pin_mask1bit = (u32) (1 << (NUM_OF_PINS - (pin + 1)));
+ pin_mask1bit = (u32) (1 << (QE_PIO_PINS - (pin + 1)));
/* Set open drain, if required */
- tmp_val = in_be32(&par_io[port].cpodr);
+ tmp_val = in_be32(&par_io->cpodr);
if (open_drain)
- out_be32(&par_io[port].cpodr, pin_mask1bit | tmp_val);
+ out_be32(&par_io->cpodr, pin_mask1bit | tmp_val);
else
- out_be32(&par_io[port].cpodr, ~pin_mask1bit & tmp_val);
+ out_be32(&par_io->cpodr, ~pin_mask1bit & tmp_val);
/* define direction */
- tmp_val = (pin > (NUM_OF_PINS / 2) - 1) ?
- in_be32(&par_io[port].cpdir2) :
- in_be32(&par_io[port].cpdir1);
+ tmp_val = (pin > (QE_PIO_PINS / 2) - 1) ?
+ in_be32(&par_io->cpdir2) :
+ in_be32(&par_io->cpdir1);
/* get all bits mask for 2 bit per port */
- pin_mask2bits = (u32) (0x3 << (NUM_OF_PINS -
- (pin % (NUM_OF_PINS / 2) + 1) * 2));
+ pin_mask2bits = (u32) (0x3 << (QE_PIO_PINS -
+ (pin % (QE_PIO_PINS / 2) + 1) * 2));
/* Get the final mask we need for the right definition */
- new_mask2bits = (u32) (dir << (NUM_OF_PINS -
- (pin % (NUM_OF_PINS / 2) + 1) * 2));
+ new_mask2bits = (u32) (dir << (QE_PIO_PINS -
+ (pin % (QE_PIO_PINS / 2) + 1) * 2));
/* clear and set 2 bits mask */
- if (pin > (NUM_OF_PINS / 2) - 1) {
- out_be32(&par_io[port].cpdir2,
+ if (pin > (QE_PIO_PINS / 2) - 1) {
+ out_be32(&par_io->cpdir2,
~pin_mask2bits & tmp_val);
tmp_val &= ~pin_mask2bits;
- out_be32(&par_io[port].cpdir2, new_mask2bits | tmp_val);
+ out_be32(&par_io->cpdir2, new_mask2bits | tmp_val);
} else {
- out_be32(&par_io[port].cpdir1,
+ out_be32(&par_io->cpdir1,
~pin_mask2bits & tmp_val);
tmp_val &= ~pin_mask2bits;
- out_be32(&par_io[port].cpdir1, new_mask2bits | tmp_val);
+ out_be32(&par_io->cpdir1, new_mask2bits | tmp_val);
}
/* define pin assignment */
- tmp_val = (pin > (NUM_OF_PINS / 2) - 1) ?
- in_be32(&par_io[port].cppar2) :
- in_be32(&par_io[port].cppar1);
+ tmp_val = (pin > (QE_PIO_PINS / 2) - 1) ?
+ in_be32(&par_io->cppar2) :
+ in_be32(&par_io->cppar1);
- new_mask2bits = (u32) (assignment << (NUM_OF_PINS -
- (pin % (NUM_OF_PINS / 2) + 1) * 2));
+ new_mask2bits = (u32) (assignment << (QE_PIO_PINS -
+ (pin % (QE_PIO_PINS / 2) + 1) * 2));
/* clear and set 2 bits mask */
- if (pin > (NUM_OF_PINS / 2) - 1) {
- out_be32(&par_io[port].cppar2,
+ if (pin > (QE_PIO_PINS / 2) - 1) {
+ out_be32(&par_io->cppar2,
~pin_mask2bits & tmp_val);
tmp_val &= ~pin_mask2bits;
- out_be32(&par_io[port].cppar2, new_mask2bits | tmp_val);
+ out_be32(&par_io->cppar2, new_mask2bits | tmp_val);
} else {
- out_be32(&par_io[port].cppar1,
+ out_be32(&par_io->cppar1,
~pin_mask2bits & tmp_val);
tmp_val &= ~pin_mask2bits;
- out_be32(&par_io[port].cppar1, new_mask2bits | tmp_val);
+ out_be32(&par_io->cppar1, new_mask2bits | tmp_val);
}
+}
+EXPORT_SYMBOL(__par_io_config_pin);
+
+int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
+ int assignment, int has_irq)
+{
+ if (!par_io || port >= num_par_io_ports)
+ return -EINVAL;
+ __par_io_config_pin(&par_io[port], pin, dir, open_drain, assignment,
+ has_irq);
return 0;
}
EXPORT_SYMBOL(par_io_config_pin);
@@ -137,10 +133,10 @@ int par_io_data_set(u8 port, u8 pin, u8 val)
if (port >= num_par_io_ports)
return -EINVAL;
- if (pin >= NUM_OF_PINS)
+ if (pin >= QE_PIO_PINS)
return -EINVAL;
/* calculate pin location */
- pin_mask = (u32) (1 << (NUM_OF_PINS - 1 - pin));
+ pin_mask = (u32) (1 << (QE_PIO_PINS - 1 - pin));
tmp_val = in_be32(&par_io[port].cpdata);
diff --git a/include/asm-powerpc/qe.h b/include/asm-powerpc/qe.h
index d217288..c4523ac 100644
--- a/include/asm-powerpc/qe.h
+++ b/include/asm-powerpc/qe.h
@@ -84,8 +84,27 @@ extern spinlock_t cmxgcr_lock;
/* Export QE common operations */
extern void qe_reset(void);
+
+/* QE PIO */
+#define QE_PIO_PINS 32
+
+struct qe_pio_regs {
+ __be32 cpodr; /* Open drain register */
+ __be32 cpdata; /* Data register */
+ __be32 cpdir1; /* Direction register */
+ __be32 cpdir2; /* Direction register */
+ __be32 cppar1; /* Pin assignment register */
+ __be32 cppar2; /* Pin assignment register */
+#ifdef CONFIG_PPC_85xx
+ u8 pad[8];
+#endif
+};
+
extern int par_io_init(struct device_node *np);
extern int par_io_of_config(struct device_node *np);
+extern void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin,
+ int dir, int open_drain, int assignment,
+ int has_irq);
extern int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
int assignment, int has_irq);
extern int par_io_data_set(u8 port, u8 pin, u8 val);
--
1.5.5.1
^ permalink raw reply related
* [PATCH 4/6] [POWERPC] QE: implement support for the GPIO LIB API
From: Anton Vorontsov @ 2008-04-29 19:00 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <20080429185920.GA19735@polina.dev.rtsoft.ru>
This is needed to access QE GPIOs via Linux GPIO API.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
Documentation/powerpc/booting-without-of.txt | 37 ++++---
arch/powerpc/sysdev/qe_lib/Kconfig | 9 ++
arch/powerpc/sysdev/qe_lib/Makefile | 1 +
arch/powerpc/sysdev/qe_lib/gpio.c | 145 ++++++++++++++++++++++++++
include/asm-powerpc/qe.h | 1 +
5 files changed, 180 insertions(+), 13 deletions(-)
create mode 100644 arch/powerpc/sysdev/qe_lib/gpio.c
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index fc7a235..4fefc44 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -1723,24 +1723,35 @@ platforms are moved over to use the flattened-device-tree model.
information.
Required properties:
- - device_type : should be "par_io".
+ - #gpio-cells : should be "2".
+ - compatible : should be "fsl,<chip>-qe-pario-bank",
+ "fsl,mpc8323-qe-pario-bank".
- reg : offset to the register set and its length.
- - num-ports : number of Parallel I/O ports
+ - gpio-controller : node to identify gpio controllers.
- Example:
- par_io@1400 {
- reg = <1400 100>;
- #address-cells = <1>;
- #size-cells = <0>;
- device_type = "par_io";
- num-ports = <7>;
- ucc_pin@01 {
- ......
- };
+ For example, two QE Par I/O banks:
+ qe_pio_a: gpio-controller@1400 {
+ #gpio-cells = <2>;
+ compatible = "fsl,mpc8360-qe-pario-bank",
+ "fsl,mpc8323-qe-pario-bank";
+ reg = <0x1400 0x18>;
+ gpio-controller;
+ };
+ qe_pio_e: gpio-controller@1460 {
+ #gpio-cells = <2>;
+ compatible = "fsl,mpc8360-qe-pario-bank",
+ "fsl,mpc8323-qe-pario-bank";
+ reg = <0x1460 0x18>;
+ gpio-controller;
+ };
vi) Pin configuration nodes
+ NOTE: pin configuration nodes are obsolete. Usually, their existance
+ is an evidence of the firmware shortcomings. Such fixups are
+ better handled by the Linux board file, not the device tree.
+
Required properties:
- linux,phandle : phandle of this node; likely referenced by a QE
device.
diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig
index 76ffbc4..4bb18f5 100644
--- a/arch/powerpc/sysdev/qe_lib/Kconfig
+++ b/arch/powerpc/sysdev/qe_lib/Kconfig
@@ -24,3 +24,12 @@ config QE_USB
bool
help
QE USB Host Controller support
+
+config QE_GPIO
+ bool "QE GPIO support"
+ depends on QUICC_ENGINE
+ select GENERIC_GPIO
+ select HAVE_GPIO_LIB
+ help
+ Say Y here if you're going to use hardware that connects to the
+ QE GPIOs.
diff --git a/arch/powerpc/sysdev/qe_lib/Makefile b/arch/powerpc/sysdev/qe_lib/Makefile
index e9ff888..f1855c1 100644
--- a/arch/powerpc/sysdev/qe_lib/Makefile
+++ b/arch/powerpc/sysdev/qe_lib/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_UCC) += ucc.o
obj-$(CONFIG_UCC_SLOW) += ucc_slow.o
obj-$(CONFIG_UCC_FAST) += ucc_fast.o
obj-$(CONFIG_QE_USB) += usb.o
+obj-$(CONFIG_QE_GPIO) += gpio.o
diff --git a/arch/powerpc/sysdev/qe_lib/gpio.c b/arch/powerpc/sysdev/qe_lib/gpio.c
new file mode 100644
index 0000000..ae9edea
--- /dev/null
+++ b/arch/powerpc/sysdev/qe_lib/gpio.c
@@ -0,0 +1,145 @@
+/*
+ * QUICC Engine GPIOs
+ *
+ * Copyright (c) MontaVista Software, Inc. 2008.
+ *
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+#include <asm/qe.h>
+
+struct qe_gpio_chip {
+ struct of_mm_gpio_chip mm_gc;
+ spinlock_t lock;
+
+ /* shadowed data register to clear/set bits safely */
+ u32 cpdata;
+};
+
+static inline struct qe_gpio_chip *
+to_qe_gpio_chip(struct of_mm_gpio_chip *mm_gc)
+{
+ return container_of(mm_gc, struct qe_gpio_chip, mm_gc);
+}
+
+static void qe_gpio_save_regs(struct of_mm_gpio_chip *mm_gc)
+{
+ struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc);
+ struct qe_pio_regs __iomem *regs = mm_gc->regs;
+
+ qe_gc->cpdata = in_be32(®s->cpdata);
+}
+
+static int qe_gpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+ struct qe_pio_regs __iomem *regs = mm_gc->regs;
+ u32 pin_mask = 1 << (QE_PIO_PINS - 1 - gpio);
+
+ return !!(in_be32(®s->cpdata) & pin_mask);
+}
+
+static void qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+ struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc);
+ struct qe_pio_regs __iomem *regs = mm_gc->regs;
+ unsigned long flags;
+ u32 pin_mask = 1 << (QE_PIO_PINS - 1 - gpio);
+
+ spin_lock_irqsave(&qe_gc->lock, flags);
+
+ if (val)
+ qe_gc->cpdata |= pin_mask;
+ else
+ qe_gc->cpdata &= ~pin_mask;
+
+ out_be32(®s->cpdata, qe_gc->cpdata);
+
+ spin_unlock_irqrestore(&qe_gc->lock, flags);
+}
+
+static int qe_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
+{
+ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+ struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc);
+ unsigned long flags;
+
+ spin_lock_irqsave(&qe_gc->lock, flags);
+
+ __par_io_config_pin(mm_gc->regs, gpio, 2, 0, 0, 0);
+
+ spin_unlock_irqrestore(&qe_gc->lock, flags);
+
+ return 0;
+}
+
+static int qe_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+ struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc);
+ unsigned long flags;
+
+ spin_lock_irqsave(&qe_gc->lock, flags);
+
+ __par_io_config_pin(mm_gc->regs, gpio, 1, 0, 0, 0);
+
+ spin_unlock_irqrestore(&qe_gc->lock, flags);
+
+ qe_gpio_set(gc, gpio, val);
+
+ return 0;
+}
+
+void __init qe_add_gpiochips(void)
+{
+ int ret;
+ struct device_node *np;
+
+ for_each_compatible_node(np, NULL, "fsl,mpc8323-qe-pario-bank") {
+ struct qe_gpio_chip *qe_gc;
+ struct of_mm_gpio_chip *mm_gc;
+ struct of_gpio_chip *of_gc;
+ struct gpio_chip *gc;
+
+ qe_gc = kzalloc(sizeof(*qe_gc), GFP_KERNEL);
+ if (!qe_gc) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ spin_lock_init(&qe_gc->lock);
+
+ mm_gc = &qe_gc->mm_gc;
+ of_gc = &mm_gc->of_gc;
+ gc = &of_gc->gc;
+
+ mm_gc->save_regs = qe_gpio_save_regs;
+ of_gc->gpio_cells = 2;
+ gc->ngpio = QE_PIO_PINS;
+ gc->direction_input = qe_gpio_dir_in;
+ gc->direction_output = qe_gpio_dir_out;
+ gc->get = qe_gpio_get;
+ gc->set = qe_gpio_set;
+
+ ret = of_mm_gpiochip_add(np, mm_gc);
+ if (ret)
+ goto err;
+ }
+
+ return;
+err:
+ pr_err("%s: registration failed with status %d\n", np->full_name, ret);
+ of_node_put(np);
+}
diff --git a/include/asm-powerpc/qe.h b/include/asm-powerpc/qe.h
index c4523ac..42ff6dd 100644
--- a/include/asm-powerpc/qe.h
+++ b/include/asm-powerpc/qe.h
@@ -100,6 +100,7 @@ struct qe_pio_regs {
#endif
};
+extern void __init qe_add_gpiochips(void);
extern int par_io_init(struct device_node *np);
extern int par_io_of_config(struct device_node *np);
extern void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin,
--
1.5.5.1
^ permalink raw reply related
* [PATCH 5/6] [POWERPC] 83xx: new board support: MPC8360E-RDK
From: Anton Vorontsov @ 2008-04-29 19:00 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <20080429185920.GA19735@polina.dev.rtsoft.ru>
This is patch adds board file, device tree, and defconfig for the new
board, made by Freescale Semiconductor Inc. and Logic Product Development.
Currently supported:
1. UEC{1,2,7,4};
2. I2C;
3. SPI;
4. NS16550 serial;
5. PCI and miniPCI;
6. Intel NOR StrataFlash X16 64Mbit PC28F640P30T85;
7. Graphics controller, Fujitsu MB86277.
Not supported in this patch:
1. StMICRO NAND512W3A2BN6E, 512 Mbit (supported with FSL UPM NAND driver);
2. FHCI USB (supported with FHCI driver).
3. QE Serial UCCs (tested to not work with ucc_uart driver, reason
unknown, yet);
4. ADC AD7843 (tested to work, but support via device tree depends on
major SPI rework, GPIO API, etc);
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
arch/powerpc/boot/dts/mpc836x_rdk.dts | 397 +++++++++
arch/powerpc/configs/83xx/mpc836x_rdk_defconfig | 1090 +++++++++++++++++++++++
arch/powerpc/platforms/83xx/Kconfig | 11 +
arch/powerpc/platforms/83xx/Makefile | 1 +
arch/powerpc/platforms/83xx/mpc836x_rdk.c | 111 +++
5 files changed, 1610 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/boot/dts/mpc836x_rdk.dts
create mode 100644 arch/powerpc/configs/83xx/mpc836x_rdk_defconfig
create mode 100644 arch/powerpc/platforms/83xx/mpc836x_rdk.c
diff --git a/arch/powerpc/boot/dts/mpc836x_rdk.dts b/arch/powerpc/boot/dts/mpc836x_rdk.dts
new file mode 100644
index 0000000..3402d26
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc836x_rdk.dts
@@ -0,0 +1,397 @@
+/*
+ * MPC8360E RDK Device Tree Source
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ * Copyright 2007-2008 MontaVista Software, Inc.
+ *
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8360rdk";
+
+ aliases {
+ serial0 = &serial0;
+ serial1 = &serial1;
+ serial2 = &serial2;
+ serial3 = &serial3;
+ ethernet0 = &enet0;
+ ethernet1 = &enet1;
+ ethernet2 = &enet2;
+ ethernet3 = &enet3;
+ pci0 = &pci0;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ PowerPC,8360@0 {
+ device_type = "cpu";
+ reg = <0>;
+ d-cache-line-size = <32>;
+ i-cache-line-size = <32>;
+ d-cache-size = <32768>;
+ i-cache-size = <32768>;
+ /* filled by u-boot */
+ timebase-frequency = <0>;
+ bus-frequency = <0>;
+ clock-frequency = <0>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ /* filled by u-boot */
+ reg = <0 0>;
+ };
+
+ soc@e0000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+ compatible = "fsl,mpc8360-immr", "fsl,immr", "fsl,soc",
+ "simple-bus";
+ ranges = <0 0xe0000000 0x200000>;
+ reg = <0xe0000000 0x200>;
+ /* filled by u-boot */
+ bus-frequency = <0>;
+
+ wdt@200 {
+ compatible = "mpc83xx_wdt";
+ reg = <0x200 0x100>;
+ };
+
+ i2c@3000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+ reg = <0x3000 0x100>;
+ interrupts = <14 8>;
+ interrupt-parent = <&ipic>;
+ dfsrr;
+ };
+
+ i2c@3100 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <1>;
+ compatible = "fsl-i2c";
+ reg = <0x3100 0x100>;
+ interrupts = <16 8>;
+ interrupt-parent = <&ipic>;
+ dfsrr;
+ };
+
+ serial0: serial@4500 {
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x4500 0x100>;
+ interrupts = <9 8>;
+ interrupt-parent = <&ipic>;
+ /* filled by u-boot */
+ clock-frequency = <0>;
+ };
+
+ serial1: serial@4600 {
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x4600 0x100>;
+ interrupts = <10 8>;
+ interrupt-parent = <&ipic>;
+ /* filled by u-boot */
+ clock-frequency = <0>;
+ };
+
+ crypto@30000 {
+ compatible = "fsl,sec2-crypto";
+ reg = <0x30000 0x10000>;
+ interrupts = <11 8>;
+ interrupt-parent = <&ipic>;
+ num-channels = <4>;
+ channel-fifo-len = <24>;
+ exec-units-mask = <0x7e>;
+ /*
+ * desc mask is for rev1.x, we need runtime fixup
+ * for >=2.x
+ */
+ descriptor-types-mask = <0x1010ebf>;
+ };
+
+ ipic: interrupt-controller@700 {
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ compatible = "fsl,pq2pro-pic", "fsl,ipic";
+ interrupt-controller;
+ reg = <0x700 0x100>;
+ };
+
+ qe_pio_b: gpio-controller@1418 {
+ #gpio-cells = <2>;
+ compatible = "fsl,mpc8360-qe-pario-bank",
+ "fsl,mpc8323-qe-pario-bank";
+ reg = <0x1418 0x18>;
+ gpio-controller;
+ };
+
+ qe_pio_e: gpio-controller@1460 {
+ #gpio-cells = <2>;
+ compatible = "fsl,mpc8360-qe-pario-bank",
+ "fsl,mpc8323-qe-pario-bank";
+ reg = <0x1460 0x18>;
+ gpio-controller;
+ };
+
+ qe@100000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "qe";
+ compatible = "fsl,qe", "simple-bus";
+ ranges = <0 0x100000 0x100000>;
+ reg = <0x100000 0x480>;
+ /* filled by u-boot */
+ clock-frequency = <0>;
+ bus-frequency = <0>;
+ brg-frequency = <0>;
+
+ muram@10000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,qe-muram", "fsl,cpm-muram";
+ ranges = <0 0x10000 0xc000>;
+
+ data-only@0 {
+ compatible = "fsl,qe-muram-data",
+ "fsl,cpm-muram-data";
+ reg = <0 0xc000>;
+ };
+ };
+
+ timer@440 {
+ compatible = "fsl,mpc8360-qe-gtm",
+ "fsl,qe-gtm", "fsl,gtm";
+ reg = <0x440 0x40>;
+ interrupts = <12 13 14 15>;
+ interrupt-parent = <&qeic>;
+ /* filled by u-boot */
+ clock-frequency = <0>;
+ };
+
+ spi@4c0 {
+ cell-index = <0>;
+ compatible = "fsl,spi";
+ reg = <0x4c0 0x40>;
+ interrupts = <2>;
+ interrupt-parent = <&qeic>;
+ mode = "cpu-qe";
+ };
+
+ spi@500 {
+ cell-index = <1>;
+ compatible = "fsl,spi";
+ reg = <0x500 0x40>;
+ interrupts = <1>;
+ interrupt-parent = <&qeic>;
+ mode = "cpu-qe";
+ };
+
+ enet0: ucc@2000 {
+ device_type = "network";
+ compatible = "ucc_geth";
+ cell-index = <1>;
+ reg = <0x2000 0x200>;
+ interrupts = <32>;
+ interrupt-parent = <&qeic>;
+ rx-clock-name = "none";
+ tx-clock-name = "clk9";
+ phy-handle = <&phy2>;
+ phy-connection-type = "rgmii-rxid";
+ /* filled by u-boot */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+
+ enet1: ucc@3000 {
+ device_type = "network";
+ compatible = "ucc_geth";
+ cell-index = <2>;
+ reg = <0x3000 0x200>;
+ interrupts = <33>;
+ interrupt-parent = <&qeic>;
+ rx-clock-name = "none";
+ tx-clock-name = "clk4";
+ phy-handle = <&phy4>;
+ phy-connection-type = "rgmii-rxid";
+ /* filled by u-boot */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+
+ enet2: ucc@2600 {
+ device_type = "network";
+ compatible = "ucc_geth";
+ cell-index = <7>;
+ reg = <0x2600 0x200>;
+ interrupts = <42>;
+ interrupt-parent = <&qeic>;
+ rx-clock-name = "clk20";
+ tx-clock-name = "clk19";
+ phy-handle = <&phy1>;
+ phy-connection-type = "mii";
+ /* filled by u-boot */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+
+ enet3: ucc@3200 {
+ device_type = "network";
+ compatible = "ucc_geth";
+ cell-index = <4>;
+ reg = <0x3200 0x200>;
+ interrupts = <35>;
+ interrupt-parent = <&qeic>;
+ rx-clock-name = "clk8";
+ tx-clock-name = "clk7";
+ phy-handle = <&phy3>;
+ phy-connection-type = "mii";
+ /* filled by u-boot */
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+
+ mdio@2120 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,ucc-mdio";
+ reg = <0x2120 0x18>;
+
+ phy1: ethernet-phy@1 {
+ device_type = "ethernet-phy";
+ compatible = "national,DP83848VV";
+ reg = <1>;
+ };
+
+ phy2: ethernet-phy@2 {
+ device_type = "ethernet-phy";
+ compatible = "broadcom,BCM5481UA2KMLG";
+ reg = <2>;
+ };
+
+ phy3: ethernet-phy@3 {
+ device_type = "ethernet-phy";
+ compatible = "national,DP83848VV";
+ reg = <3>;
+ };
+
+ phy4: ethernet-phy@4 {
+ device_type = "ethernet-phy";
+ compatible = "broadcom,BCM5481UA2KMLG";
+ reg = <4>;
+ };
+ };
+
+ serial2: ucc@2400 {
+ device_type = "serial";
+ compatible = "ucc_uart";
+ reg = <0x2400 0x200>;
+ cell-index = <5>;
+ port-number = <0>;
+ rx-clock-name = "brg7";
+ tx-clock-name = "brg8";
+ interrupts = <40>;
+ interrupt-parent = <&qeic>;
+ soft-uart;
+ };
+
+ serial3: ucc@3400 {
+ device_type = "serial";
+ compatible = "ucc_uart";
+ reg = <0x3400 0x200>;
+ cell-index = <6>;
+ port-number = <1>;
+ rx-clock-name = "brg13";
+ tx-clock-name = "brg14";
+ interrupts = <41>;
+ interrupt-parent = <&qeic>;
+ soft-uart;
+ };
+
+ qeic: interrupt-controller@80 {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ compatible = "fsl,qe-ic";
+ interrupt-controller;
+ reg = <0x80 0x80>;
+ big-endian;
+ interrupts = <32 8 33 8>;
+ interrupt-parent = <&ipic>;
+ };
+ };
+ };
+
+ localbus@e0005000 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8360-localbus", "fsl,pq2pro-localbus",
+ "simple-bus";
+ reg = <0xe0005000 0xd8>;
+ ranges = <0 0 0xff800000 0x0800000
+ 1 0 0x60000000 0x0001000
+ 2 0 0x70000000 0x4000000>;
+
+ flash@0,0 {
+ compatible = "intel,PC28F640P30T85", "cfi-flash";
+ reg = <0 0 0x800000>;
+ bank-width = <2>;
+ device-width = <1>;
+ };
+
+ display@2,0 {
+ device_type = "display";
+ compatible = "fujitsu,MB86277", "fujitsu,mint";
+ reg = <2 0 0x4000000>;
+ fujitsu,sh3;
+ little-endian;
+ /* filled by u-boot */
+ address = <0>;
+ depth = <0>;
+ width = <0>;
+ height = <0>;
+ linebytes = <0>;
+ /* linux,opened; - added by uboot */
+ };
+ };
+
+ pci0: pci@e0008500 {
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ device_type = "pci";
+ compatible = "fsl,mpc8360-pci", "fsl,mpc8349-pci";
+ reg = <0xe0008500 0x100>;
+ ranges = <0x02000000 0 0x90000000 0x90000000 0 0x10000000
+ 0x42000000 0 0x80000000 0x80000000 0 0x10000000
+ 0x01000000 0 0xe0300000 0xe0300000 0 0x00100000>;
+ interrupts = <66 8>;
+ interrupt-parent = <&ipic>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = </* miniPCI0 IDSEL 0x14 AD20 */
+ 0xa000 0 0 1 &ipic 18 8
+ 0xa000 0 0 2 &ipic 19 8
+
+ /* PCI1 IDSEL 0x15 AD21 */
+ 0xa800 0 0 1 &ipic 19 8
+ 0xa800 0 0 2 &ipic 20 8
+ 0xa800 0 0 3 &ipic 21 8
+ 0xa800 0 0 4 &ipic 18 8>;
+ /* filled by u-boot */
+ bus-range = <0 0>;
+ clock-frequency = <0>;
+ };
+};
diff --git a/arch/powerpc/configs/83xx/mpc836x_rdk_defconfig b/arch/powerpc/configs/83xx/mpc836x_rdk_defconfig
new file mode 100644
index 0000000..06cb0a4
--- /dev/null
+++ b/arch/powerpc/configs/83xx/mpc836x_rdk_defconfig
@@ -0,0 +1,1090 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.25-rc9
+# Fri Apr 25 20:31:49 2008
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+CONFIG_6xx=y
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_PPC_FPU=y
+# CONFIG_FSL_EMB_PERFMON is not set
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_GPIO=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFAULT_UIMAGE=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+
+#
+# Platform support
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_PPC_82xx is not set
+CONFIG_PPC_83xx=y
+# CONFIG_PPC_86xx is not set
+# CONFIG_PPC_MPC512x is not set
+# CONFIG_PPC_MPC5121 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+CONFIG_MPC83xx=y
+# CONFIG_MPC831x_RDB is not set
+# CONFIG_MPC832x_MDS is not set
+# CONFIG_MPC832x_RDB is not set
+# CONFIG_MPC834x_MDS is not set
+# CONFIG_MPC834x_ITX is not set
+# CONFIG_MPC836x_MDS is not set
+CONFIG_MPC836x_RDK=y
+# CONFIG_MPC837x_MDS is not set
+# CONFIG_MPC837x_RDB is not set
+# CONFIG_SBC834x is not set
+CONFIG_IPIC=y
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_QUICC_ENGINE=y
+# CONFIG_FSL_ULI1575 is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_IOMMU_HELPER is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_FSL_LBC=y
+CONFIG_FSL_GTM=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0xc0000000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_OF_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP_OF=y
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+CONFIG_OF_DEVICE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_I2C=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+CONFIG_BROADCOM_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_NET_ETHERNET is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_E1000E_ENABLED is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_GIANFAR is not set
+CONFIG_UCC_GETH=y
+CONFIG_UGETH_NAPI=y
+# CONFIG_UGETH_MAGIC_PACKET is not set
+# CONFIG_UGETH_FILTERING is not set
+# CONFIG_UGETH_TX_ON_DEMAND is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
+CONFIG_SERIAL_QE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_MPC83xx=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+CONFIG_SPI_SPIDEV=y
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_HAVE_GPIO_LIB=y
+
+#
+# GPIO Support
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_83xx_WDT=y
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+CONFIG_FB_MACMODES=y
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+CONFIG_FB_OF=y
+# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_EDAC is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+
+#
+# Userspace I/O
+#
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+CONFIG_UCC_SLOW=y
+CONFIG_UCC_FAST=y
+CONFIG_UCC=y
+CONFIG_QE_GPIO=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_PPC_EARLY_DEBUG=y
+# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
+# CONFIG_PPC_EARLY_DEBUG_G5 is not set
+# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
+# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
+# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
+# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
+# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
+# CONFIG_PPC_EARLY_DEBUG_44x is not set
+# CONFIG_PPC_EARLY_DEBUG_40x is not set
+# CONFIG_PPC_EARLY_DEBUG_CPM is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+# CONFIG_CRYPTO_SEQIV is not set
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_ECB is not set
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_PPC_CLOCK is not set
+CONFIG_PPC_LIB_RHEAP=y
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index 13587e2..9cb9e04 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -58,6 +58,17 @@ config MPC836x_MDS
help
This option enables support for the MPC836x MDS Processor Board.
+config MPC836x_RDK
+ bool "Freescale/Logic MPC836x RDK"
+ select DEFAULT_UIMAGE
+ select QUICC_ENGINE
+ select QE_GPIO
+ select FSL_GTM
+ select FSL_LBC
+ help
+ This option enables support for the MPC836x RDK Processor Board,
+ also known as ZOOM PowerQUICC Kit.
+
config MPC837x_MDS
bool "Freescale MPC837x MDS"
select DEFAULT_UIMAGE
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile
index 7e6dd3e..1fcda8e 100644
--- a/arch/powerpc/platforms/83xx/Makefile
+++ b/arch/powerpc/platforms/83xx/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o
obj-$(CONFIG_MPC834x_MDS) += mpc834x_mds.o
obj-$(CONFIG_MPC834x_ITX) += mpc834x_itx.o
obj-$(CONFIG_MPC836x_MDS) += mpc836x_mds.o
+obj-$(CONFIG_MPC836x_RDK) += mpc836x_rdk.o
obj-$(CONFIG_MPC832x_MDS) += mpc832x_mds.o
obj-$(CONFIG_MPC837x_MDS) += mpc837x_mds.o
obj-$(CONFIG_SBC834x) += sbc834x.o
diff --git a/arch/powerpc/platforms/83xx/mpc836x_rdk.c b/arch/powerpc/platforms/83xx/mpc836x_rdk.c
new file mode 100644
index 0000000..3cb366c
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/mpc836x_rdk.c
@@ -0,0 +1,111 @@
+/*
+ * MPC8360E-RDK board file.
+ *
+ * Copyright (c) 2006 Freescale Semicondutor, Inc.
+ * Copyright (c) 2007-2008 MontaVista Software, Inc.
+ *
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/of_platform.h>
+#include <linux/io.h>
+#include <asm/prom.h>
+#include <asm/time.h>
+#include <asm/ipic.h>
+#include <asm/udbg.h>
+#include <asm/qe.h>
+#include <asm/qe_ic.h>
+#include <asm/fsl_gtm.h>
+#include <sysdev/fsl_soc.h>
+
+#include "mpc83xx.h"
+
+static struct of_device_id __initdata mpc836x_rdk_ids[] = {
+ { .compatible = "simple-bus", },
+ {},
+};
+
+static int __init mpc836x_rdk_declare_of_platform_devices(void)
+{
+ return of_platform_bus_probe(NULL, mpc836x_rdk_ids, NULL);
+}
+machine_device_initcall(mpc836x_rdk, mpc836x_rdk_declare_of_platform_devices);
+
+static int __init mpc836x_rdk_arch_initcall(void)
+{
+ fsl_gtm_init();
+ qe_add_gpiochips();
+ return 0;
+}
+machine_arch_initcall(mpc836x_rdk, mpc836x_rdk_arch_initcall);
+
+static void __init mpc836x_rdk_setup_arch(void)
+{
+#ifdef CONFIG_PCI
+ struct device_node *np;
+#endif
+
+ if (ppc_md.progress)
+ ppc_md.progress("mpc836x_rdk_setup_arch()", 0);
+
+#ifdef CONFIG_PCI
+ for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
+ mpc83xx_add_bridge(np);
+#endif
+
+ qe_reset();
+}
+
+static void __init mpc836x_rdk_init_IRQ(void)
+{
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,ipic");
+ if (!np)
+ return;
+
+ ipic_init(np, 0);
+
+ /*
+ * Initialize the default interrupt mapping priorities,
+ * in case the boot rom changed something on us.
+ */
+ ipic_set_default_priority();
+ of_node_put(np);
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
+ if (!np)
+ return;
+
+ qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic);
+ of_node_put(np);
+}
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened.
+ */
+static int __init mpc836x_rdk_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ return of_flat_dt_is_compatible(root, "fsl,mpc8360rdk");
+}
+
+define_machine(mpc836x_rdk) {
+ .name = "MPC836x RDK",
+ .probe = mpc836x_rdk_probe,
+ .setup_arch = mpc836x_rdk_setup_arch,
+ .init_IRQ = mpc836x_rdk_init_IRQ,
+ .get_irq = ipic_get_irq,
+ .restart = mpc83xx_restart,
+ .time_init = mpc83xx_time_init,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = udbg_progress,
+};
--
1.5.5.1
^ permalink raw reply related
* [PATCH 6/6] [POWERPC] booting-without-of: add FHCI USB, FSL MCU, FSL UPM and GPIO LEDs bindings
From: Anton Vorontsov @ 2008-04-29 19:00 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <20080429185920.GA19735@polina.dev.rtsoft.ru>
This patch adds few bindings for the new drivers to be submitted through
appropriate maintainers.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
Documentation/powerpc/booting-without-of.txt | 125 ++++++++++++++++++++++++++
1 files changed, 125 insertions(+), 0 deletions(-)
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index 4fefc44..6564e0a 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -61,6 +61,10 @@ Table of Contents
r) Freescale Display Interface Unit
s) Freescale on board FPGA
t) Freescale General-purpose Timers Module
+ u) Freescale QUICC Engine USB Controller
+ v) LEDs on GPIOs
+ w) Freescale MCU with MPC8349E-mITX compatible firmware
+ x) Freescale Localbus UPM programmed to work with NAND flash
VII - Marvell Discovery mv64[345]6x System Controller chips
1) The /system-controller node
@@ -2916,6 +2920,127 @@ platforms are moved over to use the flattened-device-tree model.
clock-frequency = <0>;
};
+ u) Freescale QUICC Engine USB Controller
+
+ Required properties:
+ - compatible : should be "fsl,<chip>-qe-usb", "fsl,mpc8323-qe-usb";
+ - reg : the first two cells should contain gtm registers location and
+ length, the next two two cells should contain PRAM location and
+ length.
+ - interrupts : should contain USB interrupt.
+ - interrupt-parent : interrupt source phandle.
+ - fsl,fullspeed-clock : specifies the full speed USB clock source in
+ "clk<num>" or "brg<num>" format.
+ - fsl,lowspeed-clock : specifies the low speed USB clock source in
+ "clk<num>" or "brg<num>" format.
+ - fsl,usb-mode : should be "host".
+ - linux,hub-power-budget : optional, USB power budget for the root hub
+ in mA.
+ - gpios : should specify GPIOs in this order: USBOE, USBTP, USBTN, USBRP,
+ USBRN, SPEED (optional), and POWER (optional).
+
+ Example:
+
+ usb@6c0 {
+ compatible = "fsl,mpc8360-qe-usb", "fsl,mpc8323-qe-usb";
+ reg = <0x6c0 0x40 0x8b00 0x100>;
+ interrupts = <11>;
+ interrupt-parent = <&qeic>;
+ fsl,fullspeed-clock = "clk21";
+ fsl,usb-mode = "host";
+ gpios = <&qe_pio_b 2 0 /* USBOE */
+ &qe_pio_b 3 0 /* USBTP */
+ &qe_pio_b 8 0 /* USBTN */
+ &qe_pio_b 9 0 /* USBRP */
+ &qe_pio_b 11 0 /* USBRN */
+ &qe_pio_e 20 0 /* SPEED */
+ &qe_pio_e 21 0 /* POWER */>;
+ };
+
+ v) LEDs on GPIOs
+
+ Required properties:
+ - compatible : should be "linux,gpio-led".
+ - linux,name : LED name.
+ - linux,active-low : property should be present if LED wired as
+ active-low.
+ - linux,default-trigger : Linux default trigger for this LED.
+ - linux,brightness : default brightness.
+ - gpios : should specify LED GPIO.
+
+ Example:
+
+ led@0 {
+ compatible = "linux,gpio-led";
+ linux,name = "pwr";
+ linux,brightness = <1>;
+ linux,active-low;
+ gpios = <&mcu_pio 0>;
+ };
+
+ led@1 {
+ compatible = "linux,gpio-led";
+ linux,name = "hdd";
+ linux,default-trigger = "ide-disk";
+ linux,active-low;
+ gpios = <&mcu_pio 1>;
+ };
+
+ w) Freescale MCU with MPC8349E-mITX compatible firmware
+
+ Required properties:
+ - compatible : "fsl,<mcu-chip>-<board>", "fsl,mcu-mpc8349emitx";
+ - reg : should specify I2C address (0x0a).
+ - #address-cells : should be 0.
+ - #size-cells : should be 0.
+ - #gpio-cells : should be 2.
+ - gpio-controller : should be present;
+
+ Example:
+
+ mcu_pio: mcu@0a {
+ #address-cells = <0>;
+ #size-cells = <0>;
+ #gpio-cells = <2>;
+ compatible = "fsl,mc9s08qg8-mpc8349emitx",
+ "fsl,mcu-mpc8349emitx";
+ reg = <0x0a>;
+ gpio-controller;
+ };
+
+ x) Freescale Localbus UPM programmed to work with NAND flash
+
+ Required properties:
+ - #address-cells : should be 0;
+ - #size-cells : should be 0;
+ - compatible : "fsl,upm-nand".
+ - reg : should specify localbus chip select and size used for the chip.
+ - fsl,upm-addr-offset : UPM pattern offset for the address latch.
+ - fsl,upm-cmd-offset : UPM pattern offset for the command latch.
+ - gpios : may specify optional GPIO connected to the Ready-Not-Busy pin.
+
+ Example:
+
+ upm@1,0 {
+ #address-cells = <0>;
+ #size-cells = <0>;
+ compatible = "fsl,upm-nand";
+ reg = <1 0 1>;
+ fsl,upm-addr-offset = <16>;
+ fsl,upm-cmd-offset = <8>;
+ gpios = <&qe_pio_e 18 0>;
+
+ flash {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "stmicro,NAND512W3A2BN6E";
+
+ partition@0 {
+ ...
+ };
+ };
+ };
+
VII - Marvell Discovery mv64[345]6x System Controller chips
===========================================================
--
1.5.5.1
^ permalink raw reply related
* Re: SKB corruption on heavy traffic
From: Scott Wood @ 2008-04-29 19:15 UTC (permalink / raw)
To: Franca, Jose (NSN - PT/Portugal - MiniMD); +Cc: linuxppc-dev, linuxppc-embedded
In-Reply-To: <56DEE2D3217CD946B290399093C8FA7C212D8D@PTLIEXC001.nsn-intra.net>
On Tue, Apr 29, 2008 at 07:39:07PM +0100, Franca, Jose (NSN - PT/Portugal - MiniMD) wrote:
> We are developing a MPC8247 based telecom board (512MB), using
> linux 2.4 with some proprietary changes on IP stack and we are facing
> some problems when we have heavy traffic on our Ethernet interfaces...
Do you see these problems without the proprietary changes, and with a
current kernel?
-Scott
^ permalink raw reply
* Re: 2.6.25: pmac_newworld undefined
From: Sam Ravnborg @ 2008-04-29 19:17 UTC (permalink / raw)
To: Adrian Bunk; +Cc: linuxppc-dev, LKML
In-Reply-To: <20080429133514.GA30524@cs181133002.pp.htv.fi>
On Tue, Apr 29, 2008 at 04:35:14PM +0300, Adrian Bunk wrote:
> On Mon, Apr 28, 2008 at 09:33:24PM +0200, Sam Ravnborg wrote:
> > On Mon, Apr 28, 2008 at 02:20:44PM +1000, Tony Breeds wrote:
> > > On Sun, Apr 27, 2008 at 08:03:46PM +0200, Christian Kujau wrote:
> > > > Hi,
> > > >
> > > > the build failure reported[0] by Kamalesh back in 01/2008 is still
> > > > present in today's 2.6.25-git with CONFIG_NVRAM=m (instead of =y):
> > > >
> > > > Building modules, stage 2.
> > > > MODPOST 72 modules
> > > > ERROR: "pmac_newworld" [arch/powerpc/platforms/powermac/nvram.ko] undefined!
> > > > ERROR: "__alloc_bootmem" [arch/powerpc/platforms/powermac/nvram.ko]
> > > > undefined!
> > > > make[1]: *** [__modpost] Error 1
> > >
> > > Yeah that isn't really surprising. Essentially
> > > arch/powerpc/platforms/powermac/nvram.c must be builtin (not modular)
> > > but CONFIG_NVRAM is tristate, and your .config has CONFIG_NVRAM=m.
> > >
> > > We can probably "fix" this by adding another config config symbol and
> > > "selecting" that from CONFIG_NVRAM. Then using this new symbol in
> > > arch/powerpc/platforms/powermac/*
> > >
> > > so I think with we need is:
> > > config NVRAM
> > > bool "..." if PPC32
> > > tristate "..." if !PPC32
> > > ...
> > > ...
> > >
> > > Sam is there some way to achieve that or should we just create an
> > > secondary symbol?
> >
> > In the Makefile you could just do a:
> >
> > obj-$(CONFIG_NVRAM:m=y) += nvram.o
> >
> > Then you would force nvram to be build-in.
> > That looks simpler than messing with Kconfig in this case.
>
> You miss that this is only true on powerpc.
And so is the Makefile - right?
Or is this only true for 32 bit powerpc - in that case it is the wrong fix.
> And for such issues Kconfig anyway is the right place - assume how your
> solution would break if NVRAM would some day select or depend on some
> helper code.
So something like:
config PPC32_NVRAM
bool
depends on NVRAM
obj-$(CONFIG_PPC32_NVRAM) += nvram.o
obj-$(CONFIG_NVRAM) += nvram.o
Or did you have another solution in mind?
Sam
^ permalink raw reply
* Re: [PATCH] [POWERPC] convert transfer_to_handler into a macro
From: Kumar Gala @ 2008-04-29 19:36 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20080429183559.GE6561@ld0162-tx32.am.freescale.net>
On Apr 29, 2008, at 1:35 PM, Scott Wood wrote:
> On Tue, Apr 29, 2008 at 08:56:56AM -0500, Kumar Gala wrote:
>> +#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
>> +#ifdef CONFIG_SMP
>> +#define SMP_ADJUST_GLOBAL_DBCR0 \
>> + rlwinm r9,r1,0,0,(31-THREAD_SHIFT); \
>> + lwz r9,TI_CPU(r9); \
>> + slwi r9,r9,3; \
>> + add r11,r11,r9;
>> +#else
>> +#define SMP_ADJUST_GLOBAL_DBCR0
>> +#endif
>> +#define HANDLE_DBCR \
>> + /* Check to see if the dbcr0 register is set up to debug. Use
>> the \
>> + internal debug mode bit to do this. */ \
>> + lwz r12,THREAD_DBCR0(r12); \
>> + andis. r12,r12,DBCR0_IDM@h; \
>
> Can we use assembler macros rather than preprocessor macros to get
> rid of
> the backslashes?
what's an assembler macro look like? I don't believe we use them
anywhere else.
- k
^ permalink raw reply
* Re: [PATCH] [POWERPC] convert transfer_to_handler into a macro
From: Scott Wood @ 2008-04-29 19:40 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <3BD17695-2826-43CC-98A0-16F3E33EDC43@kernel.crashing.org>
On Tue, Apr 29, 2008 at 02:36:32PM -0500, Kumar Gala wrote:
> what's an assembler macro look like?
.macro macroname arg1 arg2
do something with \arg1
do something with \arg2
.endm
> I don't believe we use them anywhere else.
arch/powerpc/boot/ps3-hvcall.S uses them, as well as lots of asm code in
other architectures.
-Scott
^ permalink raw reply
* Re: 2.6.25: pmac_newworld undefined
From: Adrian Bunk @ 2008-04-29 19:45 UTC (permalink / raw)
To: Sam Ravnborg, paulus; +Cc: linuxppc-dev, LKML
In-Reply-To: <20080429191753.GA32685@uranus.ravnborg.org>
On Tue, Apr 29, 2008 at 09:17:53PM +0200, Sam Ravnborg wrote:
>...
> So something like:
>
> config PPC32_NVRAM
> bool
> depends on NVRAM
>
> obj-$(CONFIG_PPC32_NVRAM) += nvram.o
> obj-$(CONFIG_NVRAM) += nvram.o
>
> Or did you have another solution in mind?
I start to understand the problem, and I'm currently wondering why
powerpc uses CONFIG_NVRAM although the code CONFIG_NVRAM enables on
other platforms is not enabled on powerpc.
Can we rename it and move drivers/char/generic_nvram.c under
arch/powerpc/ ?
Can some powerpc person bring some background what's going on and why
it's this way?
> Sam
cu
Adrian
--
"Is there not promise of rain?" Ling Tan asked suddenly out
of the darkness. There had been need of rain for many days.
"Only a promise," Lao Er said.
Pearl S. Buck - Dragon Seed
^ permalink raw reply
* Re: [PATCH 2/6] [POWERPC] QE: add support for QE USB clocks routing
From: Timur Tabi @ 2008-04-29 19:57 UTC (permalink / raw)
To: Anton Vorontsov; +Cc: linuxppc-dev
In-Reply-To: <20080429190031.GB21203@polina.dev.rtsoft.ru>
Anton Vorontsov wrote:
> This patch adds a function to the qe_lib to setup QE USB clocks routing.
> To setup clocks safely, cmxgcr register needs locking, so I just reused
> ucc_lock since it was used only to protect cmxgcr.
>
> The idea behind placing clocks routing functions into the qe_lib is that
> later we'll hopefully switch to the generic Linux Clock API, thus, for
> example, FHCI driver may be used for QE and CPM chips without nasty #ifdefs.
>
> This patch also fixes QE_USB_RESTART_TX command definition in the qe.h.
>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Acked-By: Timur Tabi <timur@freescale.com>
Anton, please be sure to CC: me on any QE library patches you send out.
--
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply
* Re: [PATCH 3/6] [POWERPC] QE: prepare QE PIO code for GPIO LIB support
From: Timur Tabi @ 2008-04-29 20:10 UTC (permalink / raw)
To: Anton Vorontsov; +Cc: linuxppc-dev
In-Reply-To: <20080429190035.GC21203@polina.dev.rtsoft.ru>
Anton Vorontsov wrote:
> - split and export __par_io_config_pin() out of par_io_config_pin(), so we
> could use the prefixed version with GPIO LIB API;
> - rename struct port_regs to qe_pio_regs, and place it into qe.h;
> - rename #define NUM_OF_PINS to QE_PIO_PINS, and place it into qe.h.
>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Acked-By: Timur Tabi <timur@freescale.com>
--
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply
* Re: [patch v11 1/4] USB: add Cypress c67x00 low level interface code
From: Grant Likely @ 2008-04-29 20:24 UTC (permalink / raw)
To: Peter Korsgaard; +Cc: linuxppc-dev, dbrownell, linux-usb, greg
In-Reply-To: <20080427070231.581107724@sunsite.dk>
On Sun, Apr 27, 2008 at 12:59 AM, Peter Korsgaard <jacmet@sunsite.dk> wrote:
> This patch adds the low level support code for the Cypress c67x00 family of
> OTG controllers. The low level code is responsible for register access and
> implements the software protocol for communicating with the 16bit
> microcontroller inside the c67x00 device.
>
> Communication is done over the HPI interface (16bit SRAM-like parallel bus).
>
> Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
> Acked-by: David Brownell <dbrownell@users.sourceforge.net>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
> ---
> drivers/usb/c67x00/c67x00-ll-hpi.c | 405 +++++++++++++++++++++++++++++++++++++
> drivers/usb/c67x00/c67x00.h | 285 ++++++++++++++++++++++++++
> 2 files changed, 690 insertions(+)
>
> Index: linux-2.6/drivers/usb/c67x00/c67x00.h
> ===================================================================
> --- /dev/null
> +++ linux-2.6/drivers/usb/c67x00/c67x00.h
> @@ -0,0 +1,285 @@
> +/*
> + * c67x00.h: Cypress C67X00 USB register and field definitions
> + *
> + * Copyright (C) 2006-2008 Barco N.V.
> + * Derived from the Cypress cy7c67200/300 ezusb linux driver and
> + * based on multiple host controller drivers inside the linux kernel.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
> + * MA 02110-1301 USA.
> + */
> +
> +#ifndef _USB_C67X00_H
> +#define _USB_C67X00_H
> +
> +#include <linux/spinlock.h>
> +#include <linux/platform_device.h>
> +#include <linux/completion.h>
> +#include <linux/mutex.h>
> +
> +/* ---------------------------------------------------------------------
> + * Cypress C67x00 register definitions
> + */
> +
> +/* Hardware Revision Register */
> +#define HW_REV_REG 0xC004
> +
> +/* General USB registers */
> +/* ===================== */
> +
> +/* USB Control Register */
> +#define USB_CTL_REG(x) ((x) ? 0xC0AA : 0xC08A)
> +
> +#define LOW_SPEED_PORT(x) ((x) ? 0x0800 : 0x0400)
> +#define HOST_MODE 0x0200
> +#define PORT_RES_EN(x) ((x) ? 0x0100 : 0x0080)
> +#define SOF_EOP_EN(x) ((x) ? 0x0002 : 0x0001)
> +
> +/* USB status register - Notice it has different content in hcd/udc mode */
> +#define USB_STAT_REG(x) ((x) ? 0xC0B0 : 0xC090)
> +
> +#define EP0_IRQ_FLG 0x0001
> +#define EP1_IRQ_FLG 0x0002
> +#define EP2_IRQ_FLG 0x0004
> +#define EP3_IRQ_FLG 0x0008
> +#define EP4_IRQ_FLG 0x0010
> +#define EP5_IRQ_FLG 0x0020
> +#define EP6_IRQ_FLG 0x0040
> +#define EP7_IRQ_FLG 0x0080
> +#define RESET_IRQ_FLG 0x0100
> +#define SOF_EOP_IRQ_FLG 0x0200
> +#define ID_IRQ_FLG 0x4000
> +#define VBUS_IRQ_FLG 0x8000
> +
> +/* USB Host only registers */
> +/* ======================= */
> +
> +/* Host n Control Register */
> +#define HOST_CTL_REG(x) ((x) ? 0xC0A0 : 0xC080)
> +
> +#define PREAMBLE_EN 0x0080 /* Preamble enable */
> +#define SEQ_SEL 0x0040 /* Data Toggle Sequence Bit Select */
> +#define ISO_EN 0x0010 /* Isochronous enable */
> +#define ARM_EN 0x0001 /* Arm operation */
> +
> +/* Host n Interrupt Enable Register */
> +#define HOST_IRQ_EN_REG(x) ((x) ? 0xC0AC : 0xC08C)
> +
> +#define SOF_EOP_IRQ_EN 0x0200 /* SOF/EOP Interrupt Enable */
> +#define SOF_EOP_TMOUT_IRQ_EN 0x0800 /* SOF/EOP Timeout Interrupt Enable */
> +#define ID_IRQ_EN 0x4000 /* ID interrupt enable */
> +#define VBUS_IRQ_EN 0x8000 /* VBUS interrupt enable */
> +#define DONE_IRQ_EN 0x0001 /* Done Interrupt Enable */
> +
> +/* USB status register */
> +#define HOST_STAT_MASK 0x02FD
> +#define PORT_CONNECT_CHANGE(x) ((x) ? 0x0020 : 0x0010)
> +#define PORT_SE0_STATUS(x) ((x) ? 0x0008 : 0x0004)
> +
> +/* Host Frame Register */
> +#define HOST_FRAME_REG(x) ((x) ? 0xC0B6 : 0xC096)
> +
> +#define HOST_FRAME_MASK 0x07FF
> +
> +/* USB Peripheral only registers */
> +/* ============================= */
> +
> +/* Device n Port Sel reg */
> +#define DEVICE_N_PORT_SEL(x) ((x) ? 0xC0A4 : 0xC084)
> +
> +/* Device n Interrupt Enable Register */
> +#define DEVICE_N_IRQ_EN_REG(x) ((x) ? 0xC0AC : 0xC08C)
> +
> +#define DEVICE_N_ENDPOINT_N_CTL_REG(dev, ep) ((dev) \
> + ? (0x0280 + (ep << 4)) \
> + : (0x0200 + (ep << 4)))
> +#define DEVICE_N_ENDPOINT_N_STAT_REG(dev, ep) ((dev) \
> + ? (0x0286 + (ep << 4)) \
> + : (0x0206 + (ep << 4)))
> +
> +#define DEVICE_N_ADDRESS(dev) ((dev) ? (0xC0AE) : (0xC08E))
> +
> +/* HPI registers */
> +/* ============= */
> +
> +/* HPI Status register */
> +#define SOFEOP_FLG(x) (1 << ((x) ? 12 : 10))
> +#define SIEMSG_FLG(x) (1 << (4 + (x)))
> +#define RESET_FLG(x) ((x) ? 0x0200 : 0x0002)
> +#define DONE_FLG(x) (1 << (2 + (x)))
> +#define RESUME_FLG(x) (1 << (6 + (x)))
> +#define MBX_OUT_FLG 0x0001 /* Message out available */
> +#define MBX_IN_FLG 0x0100
> +#define ID_FLG 0x4000
> +#define VBUS_FLG 0x8000
> +
> +/* Interrupt routing register */
> +#define HPI_IRQ_ROUTING_REG 0x0142
> +
> +#define HPI_SWAP_ENABLE(x) ((x) ? 0x0100 : 0x0001)
> +#define RESET_TO_HPI_ENABLE(x) ((x) ? 0x0200 : 0x0002)
> +#define DONE_TO_HPI_ENABLE(x) ((x) ? 0x0008 : 0x0004)
> +#define RESUME_TO_HPI_ENABLE(x) ((x) ? 0x0080 : 0x0040)
> +#define SOFEOP_TO_HPI_EN(x) ((x) ? 0x2000 : 0x0800)
> +#define SOFEOP_TO_CPU_EN(x) ((x) ? 0x1000 : 0x0400)
> +#define ID_TO_HPI_ENABLE 0x4000
> +#define VBUS_TO_HPI_ENABLE 0x8000
> +
> +/* SIE msg registers */
> +#define SIEMSG_REG(x) ((x) ? 0x0148 : 0x0144)
> +
> +#define HUSB_TDListDone 0x1000
> +
> +#define SUSB_EP0_MSG 0x0001
> +#define SUSB_EP1_MSG 0x0002
> +#define SUSB_EP2_MSG 0x0004
> +#define SUSB_EP3_MSG 0x0008
> +#define SUSB_EP4_MSG 0x0010
> +#define SUSB_EP5_MSG 0x0020
> +#define SUSB_EP6_MSG 0x0040
> +#define SUSB_EP7_MSG 0x0080
> +#define SUSB_RST_MSG 0x0100
> +#define SUSB_SOF_MSG 0x0200
> +#define SUSB_CFG_MSG 0x0400
> +#define SUSB_SUS_MSG 0x0800
> +#define SUSB_ID_MSG 0x4000
> +#define SUSB_VBUS_MSG 0x8000
> +
> +/* BIOS interrupt routines */
> +
> +#define SUSBx_RECEIVE_INT(x) ((x) ? 97 : 81)
> +#define SUSBx_SEND_INT(x) ((x) ? 96 : 80)
> +
> +#define SUSBx_DEV_DESC_VEC(x) ((x) ? 0x00D4 : 0x00B4)
> +#define SUSBx_CONF_DESC_VEC(x) ((x) ? 0x00D6 : 0x00B6)
> +#define SUSBx_STRING_DESC_VEC(x) ((x) ? 0x00D8 : 0x00B8)
> +
> +#define CY_HCD_BUF_ADDR 0x500 /* Base address for host */
> +#define SIE_TD_SIZE 0x200 /* size of the td list */
> +#define SIE_TD_BUF_SIZE 0x400 /* size of the data buffer */
> +
> +#define SIE_TD_OFFSET(host) ((host) ? (SIE_TD_SIZE+SIE_TD_BUF_SIZE) : 0)
> +#define SIE_BUF_OFFSET(host) (SIE_TD_OFFSET(host) + SIE_TD_SIZE)
> +
> +/* Base address of HCD + 2 x TD_SIZE + 2 x TD_BUF_SIZE */
> +#define CY_UDC_REQ_HEADER_BASE 0x1100
> +/* 8- byte request headers for IN/OUT transfers */
> +#define CY_UDC_REQ_HEADER_SIZE 8
> +
> +#define CY_UDC_REQ_HEADER_ADDR(ep_num) (CY_UDC_REQ_HEADER_BASE + \
> + ((ep_num) * CY_UDC_REQ_HEADER_SIZE))
> +#define CY_UDC_DESC_BASE_ADDRESS (CY_UDC_REQ_HEADER_ADDR(8))
> +
> +#define CY_UDC_BIOS_REPLACE_BASE 0x1800
> +#define CY_UDC_REQ_BUFFER_BASE 0x2000
> +#define CY_UDC_REQ_BUFFER_SIZE 0x0400
> +#define CY_UDC_REQ_BUFFER_ADDR(ep_num) (CY_UDC_REQ_BUFFER_BASE + \
> + ((ep_num) * CY_UDC_REQ_BUFFER_SIZE))
> +
> +/* ---------------------------------------------------------------------
> + * Driver data structures
> + */
> +
> +struct c67x00_device;
> +
> +/**
> + * struct c67x00_sie - Common data associated with a SIE
> + * @lock: lock to protect this struct and the associated chip registers
> + * @private_data: subdriver dependent data
> + * @irq: subdriver dependent irq handler, set NULL when not used
> + * @dev: link to common driver structure
> + * @sie_num: SIE number on chip, starting from 0
> + * @mode: SIE mode (host/peripheral/otg/not used)
> + */
> +struct c67x00_sie {
> + /* Entries to be used by the subdrivers */
> + spinlock_t lock; /* protect this structure */
> + void *private_data;
> + void (*irq) (struct c67x00_sie *sie, u16 int_status, u16 msg);
> +
> + /* Read only: */
> + struct c67x00_device *dev;
> + int sie_num;
> + int mode;
> +};
> +
> +#define sie_dev(s) (&(s)->dev->pdev->dev)
> +
> +/**
> + * struct c67x00_lcp
> + */
> +struct c67x00_lcp {
> + /* Internal use only */
> + struct mutex mutex;
> + struct completion msg_received;
> + u16 last_msg;
> +};
> +
> +/*
> + * struct c67x00_hpi
> + */
> +struct c67x00_hpi {
> + void __iomem *base;
> + int regstep;
> + spinlock_t lock;
> + struct c67x00_lcp lcp;
> +};
> +
> +#define C67X00_SIES 2
> +#define C67X00_PORTS 2
> +
> +/**
> + * struct c67x00_device - Common data associated with a c67x00 instance
> + * @hpi: hpi addresses
> + * @sie: array of sie's on this chip
> + * @pdev: platform device of instance
> + * @pdata: configuration provided by the platform
> + */
> +struct c67x00_device {
> + struct c67x00_hpi hpi;
> + struct c67x00_sie sie[C67X00_SIES];
> + struct platform_device *pdev;
> + struct c67x00_platform_data *pdata;
> +};
> +
> +/* ---------------------------------------------------------------------
> + * Low level interface functions
> + */
> +
> +/* Host Port Interface (HPI) functions */
> +u16 c67x00_ll_hpi_status(struct c67x00_device *dev);
> +void c67x00_ll_hpi_reg_init(struct c67x00_device *dev);
> +void c67x00_ll_hpi_enable_sofeop(struct c67x00_sie *sie);
> +void c67x00_ll_hpi_disable_sofeop(struct c67x00_sie *sie);
> +
> +/* General functions */
> +u16 c67x00_ll_fetch_siemsg(struct c67x00_device *dev, int sie_num);
> +u16 c67x00_ll_get_usb_ctl(struct c67x00_sie *sie);
> +void c67x00_ll_usb_clear_status(struct c67x00_sie *sie, u16 bits);
> +u16 c67x00_ll_usb_get_status(struct c67x00_sie *sie);
> +void c67x00_ll_write_mem_le16(struct c67x00_device *dev, u16 addr,
> + void *data, int len);
> +void c67x00_ll_read_mem_le16(struct c67x00_device *dev, u16 addr,
> + void *data, int len);
> +
> +/* Called by c67x00_irq to handle lcp interrupts */
> +void c67x00_ll_irq(struct c67x00_device *dev, u16 int_status);
> +
> +/* Setup and teardown */
> +void c67x00_ll_init(struct c67x00_device *dev);
> +void c67x00_ll_release(struct c67x00_device *dev);
> +int c67x00_ll_reset(struct c67x00_device *dev);
> +
> +#endif /* _USB_C67X00_H */
> Index: linux-2.6/drivers/usb/c67x00/c67x00-ll-hpi.c
> ===================================================================
> --- /dev/null
> +++ linux-2.6/drivers/usb/c67x00/c67x00-ll-hpi.c
> @@ -0,0 +1,405 @@
> +/*
> + * c67x00-ll-hpi.c: Cypress C67X00 USB Low level interface using HPI
> + *
> + * Copyright (C) 2006-2008 Barco N.V.
> + * Derived from the Cypress cy7c67200/300 ezusb linux driver and
> + * based on multiple host controller drivers inside the linux kernel.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
> + * MA 02110-1301 USA.
> + */
> +
> +#include <asm/byteorder.h>
> +#include <linux/io.h>
> +#include <linux/usb/c67x00.h>
> +#include "c67x00.h"
> +
> +#define COMM_REGS 14
> +
> +struct c67x00_lcp_int_data {
> + u16 regs[COMM_REGS];
> +};
> +
> +/* -------------------------------------------------------------------------- */
> +/* Interface definitions */
> +
> +#define COMM_ACK 0x0FED
> +#define COMM_NAK 0xDEAD
> +
> +#define COMM_RESET 0xFA50
> +#define COMM_EXEC_INT 0xCE01
> +#define COMM_INT_NUM 0x01C2
> +
> +/* Registers 0 to COMM_REGS-1 */
> +#define COMM_R(x) (0x01C4 + 2 * (x))
> +
> +#define HUSB_SIE_pCurrentTDPtr(x) ((x) ? 0x01B2 : 0x01B0)
> +#define HUSB_SIE_pTDListDone_Sem(x) ((x) ? 0x01B8 : 0x01B6)
> +#define HUSB_pEOT 0x01B4
> +
> +/* Software interrupts */
> +/* 114, 115: */
> +#define HUSB_SIE_INIT_INT(x) ((x) ? 0x0073 : 0x0072)
> +#define HUSB_RESET_INT 0x0074
> +
> +#define SUSB_INIT_INT 0x0071
> +#define SUSB_INIT_INT_LOC (SUSB_INIT_INT * 2)
> +
> +/* -----------------------------------------------------------------------
> + * HPI implementation
> + *
> + * The c67x00 chip also support control via SPI or HSS serial
> + * interfaces. However, this driver assumes that register access can
> + * be performed from IRQ context. While this is a safe assuption with
> + * the HPI interface, it is not true for the serial interfaces.
> + */
> +
> +/* HPI registers */
> +#define HPI_DATA 0
> +#define HPI_MAILBOX 1
> +#define HPI_ADDR 2
> +#define HPI_STATUS 3
> +
> +static inline u16 hpi_read_reg(struct c67x00_device *dev, int reg)
> +{
> + return __raw_readw(dev->hpi.base + reg * dev->hpi.regstep);
> +}
> +
> +static inline void hpi_write_reg(struct c67x00_device *dev, int reg, u16 value)
> +{
> + __raw_writew(value, dev->hpi.base + reg * dev->hpi.regstep);
> +}
> +
> +static inline u16 hpi_read_word_nolock(struct c67x00_device *dev, u16 reg)
> +{
> + hpi_write_reg(dev, HPI_ADDR, reg);
> + return hpi_read_reg(dev, HPI_DATA);
> +}
> +
> +static u16 hpi_read_word(struct c67x00_device *dev, u16 reg)
> +{
> + u16 value;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&dev->hpi.lock, flags);
> + value = hpi_read_word_nolock(dev, reg);
> + spin_unlock_irqrestore(&dev->hpi.lock, flags);
> +
> + return value;
> +}
> +
> +static void hpi_write_word_nolock(struct c67x00_device *dev, u16 reg, u16 value)
> +{
> + hpi_write_reg(dev, HPI_ADDR, reg);
> + hpi_write_reg(dev, HPI_DATA, value);
> +}
> +
> +static void hpi_write_word(struct c67x00_device *dev, u16 reg, u16 value)
> +{
> + unsigned long flags;
> +
> + spin_lock_irqsave(&dev->hpi.lock, flags);
> + hpi_write_word_nolock(dev, reg, value);
> + spin_unlock_irqrestore(&dev->hpi.lock, flags);
> +}
> +
> +/*
> + * Only data is little endian, addr has cpu endianess
> + */
> +static void hpi_write_words_le16(struct c67x00_device *dev, u16 addr,
> + u16 *data, u16 count)
> +{
> + unsigned long flags;
> + int i;
> +
> + spin_lock_irqsave(&dev->hpi.lock, flags);
> +
> + hpi_write_reg(dev, HPI_ADDR, addr);
> + for (i = 0; i < count; i++)
> + hpi_write_reg(dev, HPI_DATA, cpu_to_le16(*data++));
> +
> + spin_unlock_irqrestore(&dev->hpi.lock, flags);
> +}
> +
> +/*
> + * Only data is little endian, addr has cpu endianess
> + */
> +static void hpi_read_words_le16(struct c67x00_device *dev, u16 addr,
> + u16 *data, u16 count)
> +{
> + unsigned long flags;
> + int i;
> +
> + spin_lock_irqsave(&dev->hpi.lock, flags);
> + hpi_write_reg(dev, HPI_ADDR, addr);
> + for (i = 0; i < count; i++)
> + *data++ = le16_to_cpu(hpi_read_reg(dev, HPI_DATA));
> +
> + spin_unlock_irqrestore(&dev->hpi.lock, flags);
> +}
> +
> +static void hpi_set_bits(struct c67x00_device *dev, u16 reg, u16 mask)
> +{
> + u16 value;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&dev->hpi.lock, flags);
> + value = hpi_read_word_nolock(dev, reg);
> + hpi_write_word_nolock(dev, reg, value | mask);
> + spin_unlock_irqrestore(&dev->hpi.lock, flags);
> +}
> +
> +static void hpi_clear_bits(struct c67x00_device *dev, u16 reg, u16 mask)
> +{
> + u16 value;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&dev->hpi.lock, flags);
> + value = hpi_read_word_nolock(dev, reg);
> + hpi_write_word_nolock(dev, reg, value & ~mask);
> + spin_unlock_irqrestore(&dev->hpi.lock, flags);
> +}
> +
> +static u16 hpi_recv_mbox(struct c67x00_device *dev)
> +{
> + u16 value;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&dev->hpi.lock, flags);
> + value = hpi_read_reg(dev, HPI_MAILBOX);
> + spin_unlock_irqrestore(&dev->hpi.lock, flags);
> +
> + return value;
> +}
> +
> +static u16 hpi_send_mbox(struct c67x00_device *dev, u16 value)
> +{
> + unsigned long flags;
> +
> + spin_lock_irqsave(&dev->hpi.lock, flags);
> + hpi_write_reg(dev, HPI_MAILBOX, value);
> + spin_unlock_irqrestore(&dev->hpi.lock, flags);
> +
> + return value;
> +}
> +
> +u16 c67x00_ll_hpi_status(struct c67x00_device *dev)
> +{
> + u16 value;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&dev->hpi.lock, flags);
> + value = hpi_read_reg(dev, HPI_STATUS);
> + spin_unlock_irqrestore(&dev->hpi.lock, flags);
> +
> + return value;
> +}
> +
> +void c67x00_ll_hpi_reg_init(struct c67x00_device *dev)
> +{
> + int i;
> +
> + hpi_recv_mbox(dev);
> + c67x00_ll_hpi_status(dev);
> + hpi_write_word(dev, HPI_IRQ_ROUTING_REG, 0);
> +
> + for (i = 0; i < C67X00_SIES; i++) {
> + hpi_write_word(dev, SIEMSG_REG(i), 0);
> + hpi_read_word(dev, SIEMSG_REG(i));
> + }
> +}
> +
> +void c67x00_ll_hpi_enable_sofeop(struct c67x00_sie *sie)
> +{
> + hpi_set_bits(sie->dev, HPI_IRQ_ROUTING_REG,
> + SOFEOP_TO_HPI_EN(sie->sie_num));
> +}
> +
> +void c67x00_ll_hpi_disable_sofeop(struct c67x00_sie *sie)
> +{
> + hpi_clear_bits(sie->dev, HPI_IRQ_ROUTING_REG,
> + SOFEOP_TO_HPI_EN(sie->sie_num));
> +}
> +
> +/* -------------------------------------------------------------------------- */
> +/* Transactions */
> +
> +static inline u16 ll_recv_msg(struct c67x00_device *dev)
> +{
> + u16 res;
> +
> + res = wait_for_completion_timeout(&dev->hpi.lcp.msg_received, 5 * HZ);
> + WARN_ON(!res);
> +
> + return (res == 0) ? -EIO : 0;
> +}
> +
> +/* -------------------------------------------------------------------------- */
> +/* General functions */
> +
> +u16 c67x00_ll_fetch_siemsg(struct c67x00_device *dev, int sie_num)
> +{
> + u16 val;
> +
> + val = hpi_read_word(dev, SIEMSG_REG(sie_num));
> + /* clear register to allow next message */
> + hpi_write_word(dev, SIEMSG_REG(sie_num), 0);
> +
> + return val;
> +}
> +
> +u16 c67x00_ll_get_usb_ctl(struct c67x00_sie *sie)
> +{
> + return hpi_read_word(sie->dev, USB_CTL_REG(sie->sie_num));
> +}
> +
> +/**
> + * c67x00_ll_usb_clear_status - clear the USB status bits
> + */
> +void c67x00_ll_usb_clear_status(struct c67x00_sie *sie, u16 bits)
> +{
> + hpi_write_word(sie->dev, USB_STAT_REG(sie->sie_num), bits);
> +}
> +
> +u16 c67x00_ll_usb_get_status(struct c67x00_sie *sie)
> +{
> + return hpi_read_word(sie->dev, USB_STAT_REG(sie->sie_num));
> +}
> +
> +/* -------------------------------------------------------------------------- */
> +
> +static int c67x00_comm_exec_int(struct c67x00_device *dev, u16 nr,
> + struct c67x00_lcp_int_data *data)
> +{
> + int i, rc;
> +
> + mutex_lock(&dev->hpi.lcp.mutex);
> + hpi_write_word(dev, COMM_INT_NUM, nr);
> + for (i = 0; i < COMM_REGS; i++)
> + hpi_write_word(dev, COMM_R(i), data->regs[i]);
> + hpi_send_mbox(dev, COMM_EXEC_INT);
> + rc = ll_recv_msg(dev);
> + mutex_unlock(&dev->hpi.lcp.mutex);
> +
> + return rc;
> +}
> +
> +/* -------------------------------------------------------------------------- */
> +
> +void c67x00_ll_irq(struct c67x00_device *dev, u16 int_status)
> +{
> + if ((int_status & MBX_OUT_FLG) == 0)
> + return;
> +
> + dev->hpi.lcp.last_msg = hpi_recv_mbox(dev);
> + complete(&dev->hpi.lcp.msg_received);
> +}
> +
> +/* -------------------------------------------------------------------------- */
> +
> +int c67x00_ll_reset(struct c67x00_device *dev)
> +{
> + int rc;
> +
> + mutex_lock(&dev->hpi.lcp.mutex);
> + hpi_send_mbox(dev, COMM_RESET);
> + rc = ll_recv_msg(dev);
> + mutex_unlock(&dev->hpi.lcp.mutex);
> +
> + return rc;
> +}
> +
> +/* -------------------------------------------------------------------------- */
> +
> +/**
> + * c67x00_ll_write_mem_le16 - write into c67x00 memory
> + * Only data is little endian, addr has cpu endianess.
> + */
> +void c67x00_ll_write_mem_le16(struct c67x00_device *dev, u16 addr,
> + void *data, int len)
> +{
> + u8 *buf = data;
> +
> + /* Sanity check */
> + if (addr + len > 0xffff) {
> + dev_err(&dev->pdev->dev,
> + "Trying to write beyond writable region!\n");
> + return;
> + }
> +
> + if (addr & 0x01) {
> + /* unaligned access */
> + u16 tmp;
> + tmp = hpi_read_word(dev, addr - 1);
> + tmp = (tmp & 0x00ff) | (*buf++ << 8);
> + hpi_write_word(dev, addr - 1, tmp);
> + addr++;
> + len--;
> + }
> +
> + hpi_write_words_le16(dev, addr, (u16 *)buf, len / 2);
> + buf += len & ~0x01;
> + addr += len & ~0x01;
> + len &= 0x01;
> +
> + if (len) {
> + u16 tmp;
> + tmp = hpi_read_word(dev, addr);
> + tmp = (tmp & 0xff00) | *buf;
> + hpi_write_word(dev, addr, tmp);
> + }
> +}
> +
> +/**
> + * c67x00_ll_read_mem_le16 - read from c67x00 memory
> + * Only data is little endian, addr has cpu endianess.
> + */
> +void c67x00_ll_read_mem_le16(struct c67x00_device *dev, u16 addr,
> + void *data, int len)
> +{
> + u8 *buf = data;
> +
> + if (addr & 0x01) {
> + /* unaligned access */
> + u16 tmp;
> + tmp = hpi_read_word(dev, addr - 1);
> + *buf++ = (tmp >> 8) & 0x00ff;
> + addr++;
> + len--;
> + }
> +
> + hpi_read_words_le16(dev, addr, (u16 *)buf, len / 2);
> + buf += len & ~0x01;
> + addr += len & ~0x01;
> + len &= 0x01;
> +
> + if (len) {
> + u16 tmp;
> + tmp = hpi_read_word(dev, addr);
> + *buf = tmp & 0x00ff;
> + }
> +}
> +
> +/* -------------------------------------------------------------------------- */
> +
> +void c67x00_ll_init(struct c67x00_device *dev)
> +{
> + mutex_init(&dev->hpi.lcp.mutex);
> + init_completion(&dev->hpi.lcp.msg_received);
> +}
> +
> +void c67x00_ll_release(struct c67x00_device *dev)
> +{
> +}
>
> --
> Bye, Peter Korsgaard
>
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: [patch v11 2/4] USB: add Cypress c67x00 OTG controller core driver
From: Grant Likely @ 2008-04-29 20:25 UTC (permalink / raw)
To: Peter Korsgaard; +Cc: linuxppc-dev, dbrownell, linux-usb, greg
In-Reply-To: <20080427070231.764077242@sunsite.dk>
On Sun, Apr 27, 2008 at 12:59 AM, Peter Korsgaard <jacmet@sunsite.dk> wrote:
> This patch add the core driver for the c67x00 USB OTG controller. The core
> driver is responsible for the platform bus binding and creating either
> USB HCD or USB Gadget instances for each of the serial interface engines
> on the chip.
>
> This driver does not directly implement the HCD or gadget behaviours; it
> just controls access to the chip.
>
> Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
> Acked-by: David Brownell <dbrownell@users.sourceforge.net>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
> ---
> MAINTAINERS | 6 +
> drivers/usb/c67x00/c67x00-drv.c | 230 ++++++++++++++++++++++++++++++++++++++++
> include/linux/usb/c67x00.h | 48 ++++++++
> 3 files changed, 284 insertions(+)
>
> Index: linux-2.6/drivers/usb/c67x00/c67x00-drv.c
> ===================================================================
> --- /dev/null
> +++ linux-2.6/drivers/usb/c67x00/c67x00-drv.c
> @@ -0,0 +1,230 @@
> +/*
> + * c67x00-drv.c: Cypress C67X00 USB Common infrastructure
> + *
> + * Copyright (C) 2006-2008 Barco N.V.
> + * Derived from the Cypress cy7c67200/300 ezusb linux driver and
> + * based on multiple host controller drivers inside the linux kernel.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
> + * MA 02110-1301 USA.
> + */
> +
> +/*
> + * This file implements the common infrastructure for using the c67x00.
> + * It is both the link between the platform configuration and subdrivers and
> + * the link between the common hardware parts and the subdrivers (e.g.
> + * interrupt handling).
> + *
> + * The c67x00 has 2 SIE's (serial interface engine) wich can be configured
> + * to be host, device or OTG (with some limitations, E.G. only SIE1 can be OTG).
> + *
> + * Depending on the platform configuration, the SIE's are created and
> + * the corresponding subdriver is initialized (c67x00_probe_sie).
> + */
> +
> +#include <linux/device.h>
> +#include <linux/io.h>
> +#include <linux/list.h>
> +#include <linux/usb.h>
> +#include <linux/usb/c67x00.h>
> +
> +#include "c67x00.h"
> +
> +static void c67x00_probe_sie(struct c67x00_sie *sie,
> + struct c67x00_device *dev, int sie_num)
> +{
> + spin_lock_init(&sie->lock);
> + sie->dev = dev;
> + sie->sie_num = sie_num;
> + sie->mode = c67x00_sie_config(dev->pdata->sie_config, sie_num);
> +
> + switch (sie->mode) {
> + case C67X00_SIE_UNUSED:
> + dev_info(sie_dev(sie),
> + "Not using SIE %d as requested\n", sie->sie_num);
> + break;
> +
> + default:
> + dev_err(sie_dev(sie),
> + "Unsupported configuration: 0x%x for SIE %d\n",
> + sie->mode, sie->sie_num);
> + break;
> + }
> +}
> +
> +static void c67x00_remove_sie(struct c67x00_sie *sie)
> +{
> +}
> +
> +static irqreturn_t c67x00_irq(int irq, void *__dev)
> +{
> + struct c67x00_device *c67x00 = __dev;
> + struct c67x00_sie *sie;
> + u16 msg, int_status;
> + int i, count = 8;
> +
> + int_status = c67x00_ll_hpi_status(c67x00);
> + if (!int_status)
> + return IRQ_NONE;
> +
> + while (int_status != 0 && (count-- >= 0)) {
> + c67x00_ll_irq(c67x00, int_status);
> + for (i = 0; i < C67X00_SIES; i++) {
> + sie = &c67x00->sie[i];
> + msg = 0;
> + if (int_status & SIEMSG_FLG(i))
> + msg = c67x00_ll_fetch_siemsg(c67x00, i);
> + if (sie->irq)
> + sie->irq(sie, int_status, msg);
> + }
> + int_status = c67x00_ll_hpi_status(c67x00);
> + }
> +
> + if (int_status)
> + dev_warn(&c67x00->pdev->dev, "Not all interrupts handled! "
> + "status = 0x%04x\n", int_status);
> +
> + return IRQ_HANDLED;
> +}
> +
> +/* ------------------------------------------------------------------------- */
> +
> +static int __devinit c67x00_drv_probe(struct platform_device *pdev)
> +{
> + struct c67x00_device *c67x00;
> + struct c67x00_platform_data *pdata;
> + struct resource *res, *res2;
> + int ret, i;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!res)
> + return -ENODEV;
> +
> + res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> + if (!res2)
> + return -ENODEV;
> +
> + pdata = pdev->dev.platform_data;
> + if (!pdata)
> + return -ENODEV;
> +
> + c67x00 = kzalloc(sizeof(*c67x00), GFP_KERNEL);
> + if (!c67x00)
> + return -ENOMEM;
> +
> + if (!request_mem_region(res->start, res->end - res->start + 1,
> + pdev->name)) {
> + dev_err(&pdev->dev, "Memory region busy\n");
> + ret = -EBUSY;
> + goto request_mem_failed;
> + }
> + c67x00->hpi.base = ioremap(res->start, res->end - res->start + 1);
> + if (!c67x00->hpi.base) {
> + dev_err(&pdev->dev, "Unable to map HPI registers\n");
> + ret = -EIO;
> + goto map_failed;
> + }
> +
> + spin_lock_init(&c67x00->hpi.lock);
> + c67x00->hpi.regstep = pdata->hpi_regstep;
> + c67x00->pdata = pdev->dev.platform_data;
> + c67x00->pdev = pdev;
> +
> + c67x00_ll_init(c67x00);
> + c67x00_ll_hpi_reg_init(c67x00);
> +
> + ret = request_irq(res2->start, c67x00_irq, 0, pdev->name, c67x00);
> + if (ret) {
> + dev_err(&pdev->dev, "Cannot claim IRQ\n");
> + goto request_irq_failed;
> + }
> +
> + ret = c67x00_ll_reset(c67x00);
> + if (ret) {
> + dev_err(&pdev->dev, "Device reset failed\n");
> + goto reset_failed;
> + }
> +
> + for (i = 0; i < C67X00_SIES; i++)
> + c67x00_probe_sie(&c67x00->sie[i], c67x00, i);
> +
> + platform_set_drvdata(pdev, c67x00);
> +
> + return 0;
> +
> + reset_failed:
> + free_irq(res2->start, c67x00);
> + request_irq_failed:
> + iounmap(c67x00->hpi.base);
> + map_failed:
> + release_mem_region(res->start, res->end - res->start + 1);
> + request_mem_failed:
> + kfree(c67x00);
> +
> + return ret;
> +}
> +
> +static int __devexit c67x00_drv_remove(struct platform_device *pdev)
> +{
> + struct c67x00_device *c67x00 = platform_get_drvdata(pdev);
> + struct resource *res;
> + int i;
> +
> + for (i = 0; i < C67X00_SIES; i++)
> + c67x00_remove_sie(&c67x00->sie[i]);
> +
> + c67x00_ll_release(c67x00);
> +
> + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> + if (res)
> + free_irq(res->start, c67x00);
> +
> + iounmap(c67x00->hpi.base);
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (res)
> + release_mem_region(res->start, res->end - res->start + 1);
> +
> + kfree(c67x00);
> +
> + return 0;
> +}
> +
> +static struct platform_driver c67x00_driver = {
> + .probe = c67x00_drv_probe,
> + .remove = __devexit_p(c67x00_drv_remove),
> + .driver = {
> + .owner = THIS_MODULE,
> + .name = "c67x00",
> + },
> +};
> +MODULE_ALIAS("platform:c67x00");
> +
> +static int __init c67x00_init(void)
> +{
> + return platform_driver_register(&c67x00_driver);
> +}
> +
> +static void __exit c67x00_exit(void)
> +{
> + platform_driver_unregister(&c67x00_driver);
> +}
> +
> +module_init(c67x00_init);
> +module_exit(c67x00_exit);
> +
> +MODULE_AUTHOR("Peter Korsgaard, Jan Veldeman, Grant Likely");
> +MODULE_DESCRIPTION("Cypress C67X00 USB Controller Driver");
> +MODULE_LICENSE("GPL");
> Index: linux-2.6/include/linux/usb/c67x00.h
> ===================================================================
> --- /dev/null
> +++ linux-2.6/include/linux/usb/c67x00.h
> @@ -0,0 +1,48 @@
> +/*
> + * usb_c67x00.h: platform definitions for the Cypress C67X00 USB chip
> + *
> + * Copyright (C) 2006-2008 Barco N.V.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
> + * MA 02110-1301 USA.
> + */
> +
> +#ifndef _LINUX_USB_C67X00_H
> +#define _LINUX_USB_C67X00_H
> +
> +/* SIE configuration */
> +#define C67X00_SIE_UNUSED 0
> +#define C67X00_SIE_HOST 1
> +#define C67X00_SIE_PERIPHERAL_A 2 /* peripheral on A port */
> +#define C67X00_SIE_PERIPHERAL_B 3 /* peripheral on B port */
> +
> +#define c67x00_sie_config(config, n) (((config)>>(4*(n)))&0x3)
> +
> +#define C67X00_SIE1_UNUSED (C67X00_SIE_UNUSED << 0)
> +#define C67X00_SIE1_HOST (C67X00_SIE_HOST << 0)
> +#define C67X00_SIE1_PERIPHERAL_A (C67X00_SIE_PERIPHERAL_A << 0)
> +#define C67X00_SIE1_PERIPHERAL_B (C67X00_SIE_PERIPHERAL_B << 0)
> +
> +#define C67X00_SIE2_UNUSED (C67X00_SIE_UNUSED << 4)
> +#define C67X00_SIE2_HOST (C67X00_SIE_HOST << 4)
> +#define C67X00_SIE2_PERIPHERAL_A (C67X00_SIE_PERIPHERAL_A << 4)
> +#define C67X00_SIE2_PERIPHERAL_B (C67X00_SIE_PERIPHERAL_B << 4)
> +
> +struct c67x00_platform_data {
> + int sie_config; /* SIEs config (C67X00_SIEx_*) */
> + unsigned long hpi_regstep; /* Step between HPI registers */
> +};
> +
> +#endif /* _LINUX_USB_C67X00_H */
> Index: linux-2.6/MAINTAINERS
> ===================================================================
> --- linux-2.6.orig/MAINTAINERS
> +++ linux-2.6/MAINTAINERS
> @@ -4010,6 +4010,12 @@
> S: Maintained
> W: http://www.kroah.com/linux-usb/
>
> +USB CYPRESS C67X00 DRIVER
> +P: Peter Korsgaard
> +M: jacmet@sunsite.dk
> +L: linux-usb@vger.kernel.org
> +S: Maintained
> +
> USB DAVICOM DM9601 DRIVER
> P: Peter Korsgaard
> M: jacmet@sunsite.dk
>
> --
> Bye, Peter Korsgaard
>
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: [patch v11 3/4] USB: add Cypress c67x00 OTG controller HCD driver
From: Grant Likely @ 2008-04-29 20:26 UTC (permalink / raw)
To: Peter Korsgaard; +Cc: linuxppc-dev, dbrownell, linux-usb, greg
In-Reply-To: <20080427070231.906264382@sunsite.dk>
On Sun, Apr 27, 2008 at 12:59 AM, Peter Korsgaard <jacmet@sunsite.dk> wrote:
> This patch adds HCD support for the Cypress c67x00 family of devices.
>
> Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
> ---
> drivers/usb/Makefile | 2
> drivers/usb/c67x00/Makefile | 9
> drivers/usb/c67x00/c67x00-drv.c | 13
> drivers/usb/c67x00/c67x00-hcd.c | 412 +++++++++++++
> drivers/usb/c67x00/c67x00-hcd.h | 133 ++++
> drivers/usb/c67x00/c67x00-ll-hpi.c | 75 ++
> drivers/usb/c67x00/c67x00-sched.c | 1170 +++++++++++++++++++++++++++++++++++++
> drivers/usb/c67x00/c67x00.h | 9
> drivers/usb/host/Kconfig | 13
> 9 files changed, 1836 insertions(+)
>
> Index: linux-2.6/drivers/usb/c67x00/c67x00-hcd.c
> ===================================================================
> --- /dev/null
> +++ linux-2.6/drivers/usb/c67x00/c67x00-hcd.c
> @@ -0,0 +1,412 @@
> +/*
> + * c67x00-hcd.c: Cypress C67X00 USB Host Controller Driver
> + *
> + * Copyright (C) 2006-2008 Barco N.V.
> + * Derived from the Cypress cy7c67200/300 ezusb linux driver and
> + * based on multiple host controller drivers inside the linux kernel.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
> + * MA 02110-1301 USA.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/platform_device.h>
> +#include <linux/usb.h>
> +
> +#include "c67x00.h"
> +#include "c67x00-hcd.h"
> +
> +/* --------------------------------------------------------------------------
> + * Root Hub Support
> + */
> +
> +static __u8 c67x00_hub_des[] = {
> + 0x09, /* __u8 bLength; */
> + 0x29, /* __u8 bDescriptorType; Hub-descriptor */
> + 0x02, /* __u8 bNbrPorts; */
> + 0x00, /* __u16 wHubCharacteristics; */
> + 0x00, /* (per-port OC, no power switching) */
> + 0x32, /* __u8 bPwrOn2pwrGood; 2ms */
> + 0x00, /* __u8 bHubContrCurrent; 0 mA */
> + 0x00, /* __u8 DeviceRemovable; ** 7 Ports max ** */
> + 0xff, /* __u8 PortPwrCtrlMask; ** 7 ports max ** */
> +};
> +
> +static void c67x00_hub_reset_host_port(struct c67x00_sie *sie, int port)
> +{
> + struct c67x00_hcd *c67x00 = sie->private_data;
> + unsigned long flags;
> +
> + c67x00_ll_husb_reset(sie, port);
> +
> + spin_lock_irqsave(&c67x00->lock, flags);
> + c67x00_ll_husb_reset_port(sie, port);
> + spin_unlock_irqrestore(&c67x00->lock, flags);
> +
> + c67x00_ll_set_husb_eot(sie->dev, DEFAULT_EOT);
> +}
> +
> +static int c67x00_hub_status_data(struct usb_hcd *hcd, char *buf)
> +{
> + struct c67x00_hcd *c67x00 = hcd_to_c67x00_hcd(hcd);
> + struct c67x00_sie *sie = c67x00->sie;
> + u16 status;
> + int i;
> +
> + *buf = 0;
> + status = c67x00_ll_usb_get_status(sie);
> + for (i = 0; i < C67X00_PORTS; i++)
> + if (status & PORT_CONNECT_CHANGE(i))
> + *buf |= (1 << i);
> +
> + /* bit 0 denotes hub change, b1..n port change */
> + *buf <<= 1;
> +
> + return !!*buf;
> +}
> +
> +static int c67x00_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
> + u16 wIndex, char *buf, u16 wLength)
> +{
> + struct c67x00_hcd *c67x00 = hcd_to_c67x00_hcd(hcd);
> + struct c67x00_sie *sie = c67x00->sie;
> + u16 status, usb_status;
> + int len = 0;
> + unsigned int port = wIndex-1;
> + u16 wPortChange, wPortStatus;
> +
> + switch (typeReq) {
> +
> + case GetHubStatus:
> + *(__le32 *) buf = cpu_to_le32(0);
> + len = 4; /* hub power */
> + break;
> +
> + case GetPortStatus:
> + if (wIndex > C67X00_PORTS)
> + return -EPIPE;
> +
> + status = c67x00_ll_usb_get_status(sie);
> + usb_status = c67x00_ll_get_usb_ctl(sie);
> +
> + wPortChange = 0;
> + if (status & PORT_CONNECT_CHANGE(port))
> + wPortChange |= USB_PORT_STAT_C_CONNECTION;
> +
> + wPortStatus = USB_PORT_STAT_POWER;
> + if (!(status & PORT_SE0_STATUS(port)))
> + wPortStatus |= USB_PORT_STAT_CONNECTION;
> + if (usb_status & LOW_SPEED_PORT(port)) {
> + wPortStatus |= USB_PORT_STAT_LOW_SPEED;
> + c67x00->low_speed_ports |= (1 << port);
> + } else
> + c67x00->low_speed_ports &= ~(1 << port);
> +
> + if (usb_status & SOF_EOP_EN(port))
> + wPortStatus |= USB_PORT_STAT_ENABLE;
> +
> + *(__le16 *) buf = cpu_to_le16(wPortStatus);
> + *(__le16 *) (buf + 2) = cpu_to_le16(wPortChange);
> + len = 4;
> + break;
> +
> + case SetHubFeature: /* We don't implement these */
> + case ClearHubFeature:
> + switch (wValue) {
> + case C_HUB_OVER_CURRENT:
> + case C_HUB_LOCAL_POWER:
> + len = 0;
> + break;
> +
> + default:
> + return -EPIPE;
> + }
> + break;
> +
> + case SetPortFeature:
> + if (wIndex > C67X00_PORTS)
> + return -EPIPE;
> +
> + switch (wValue) {
> + case USB_PORT_FEAT_SUSPEND:
> + dev_dbg(c67x00_hcd_dev(c67x00),
> + "SetPortFeature %d (SUSPEND)\n", port);
> + len = 0;
> + break;
> +
> + case USB_PORT_FEAT_RESET:
> + c67x00_hub_reset_host_port(sie, port);
> + len = 0;
> + break;
> +
> + case USB_PORT_FEAT_POWER:
> + /* Power always enabled */
> + len = 0;
> + break;
> +
> + default:
> + dev_dbg(c67x00_hcd_dev(c67x00),
> + "%s: SetPortFeature %d (0x%04x) Error!\n",
> + __func__, port, wValue);
> + return -EPIPE;
> + }
> + break;
> +
> + case ClearPortFeature:
> + if (wIndex > C67X00_PORTS)
> + return -EPIPE;
> +
> + switch (wValue) {
> + case USB_PORT_FEAT_ENABLE:
> + /* Reset the port so that the c67x00 also notices the
> + * disconnect */
> + c67x00_hub_reset_host_port(sie, port);
> + len = 0;
> + break;
> +
> + case USB_PORT_FEAT_C_ENABLE:
> + dev_dbg(c67x00_hcd_dev(c67x00),
> + "ClearPortFeature (%d): C_ENABLE\n", port);
> + len = 0;
> + break;
> +
> + case USB_PORT_FEAT_SUSPEND:
> + dev_dbg(c67x00_hcd_dev(c67x00),
> + "ClearPortFeature (%d): SUSPEND\n", port);
> + len = 0;
> + break;
> +
> + case USB_PORT_FEAT_C_SUSPEND:
> + dev_dbg(c67x00_hcd_dev(c67x00),
> + "ClearPortFeature (%d): C_SUSPEND\n", port);
> + len = 0;
> + break;
> +
> + case USB_PORT_FEAT_POWER:
> + dev_dbg(c67x00_hcd_dev(c67x00),
> + "ClearPortFeature (%d): POWER\n", port);
> + return -EPIPE;
> +
> + case USB_PORT_FEAT_C_CONNECTION:
> + c67x00_ll_usb_clear_status(sie,
> + PORT_CONNECT_CHANGE(port));
> + len = 0;
> + break;
> +
> + case USB_PORT_FEAT_C_OVER_CURRENT:
> + dev_dbg(c67x00_hcd_dev(c67x00),
> + "ClearPortFeature (%d): OVER_CURRENT\n", port);
> + len = 0;
> + break;
> +
> + case USB_PORT_FEAT_C_RESET:
> + dev_dbg(c67x00_hcd_dev(c67x00),
> + "ClearPortFeature (%d): C_RESET\n", port);
> + len = 0;
> + break;
> +
> + default:
> + dev_dbg(c67x00_hcd_dev(c67x00),
> + "%s: ClearPortFeature %d (0x%04x) Error!\n",
> + __func__, port, wValue);
> + return -EPIPE;
> + }
> + break;
> +
> + case GetHubDescriptor:
> + len = min_t(unsigned int, sizeof(c67x00_hub_des), wLength);
> + memcpy(buf, c67x00_hub_des, len);
> + break;
> +
> + default:
> + dev_dbg(c67x00_hcd_dev(c67x00), "%s: unknown\n", __func__);
> + return -EPIPE;
> + }
> +
> + return 0;
> +}
> +
> +/* ---------------------------------------------------------------------
> + * Main part of host controller driver
> + */
> +
> +/**
> + * c67x00_hcd_irq
> + *
> + * This function is called from the interrupt handler in c67x00-drv.c
> + */
> +static void c67x00_hcd_irq(struct c67x00_sie *sie, u16 int_status, u16 msg)
> +{
> + struct c67x00_hcd *c67x00 = sie->private_data;
> + struct usb_hcd *hcd = c67x00_hcd_to_hcd(c67x00);
> +
> + /* Handle sie message flags */
> + if (msg) {
> + if (msg & HUSB_TDListDone)
> + c67x00_sched_kick(c67x00);
> + else
> + dev_warn(c67x00_hcd_dev(c67x00),
> + "Unknown SIE msg flag(s): 0x%04x\n", msg);
> + }
> +
> + if (unlikely(hcd->state == HC_STATE_HALT))
> + return;
> +
> + if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
> + return;
> +
> + /* Handle Start of frame events */
> + if (int_status & SOFEOP_FLG(sie->sie_num)) {
> + c67x00_ll_usb_clear_status(sie, SOF_EOP_IRQ_FLG);
> + c67x00_sched_kick(c67x00);
> + set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
> + }
> +}
> +
> +/**
> + * c67x00_hcd_start: Host controller start hook
> + */
> +static int c67x00_hcd_start(struct usb_hcd *hcd)
> +{
> + hcd->uses_new_polling = 1;
> + hcd->state = HC_STATE_RUNNING;
> + hcd->poll_rh = 1;
> +
> + return 0;
> +}
> +
> +/**
> + * c67x00_hcd_stop: Host controller stop hook
> + */
> +static void c67x00_hcd_stop(struct usb_hcd *hcd)
> +{
> + /* Nothing to do */
> +}
> +
> +static int c67x00_hcd_get_frame(struct usb_hcd *hcd)
> +{
> + struct c67x00_hcd *c67x00 = hcd_to_c67x00_hcd(hcd);
> + u16 temp_val;
> +
> + dev_dbg(c67x00_hcd_dev(c67x00), "%s\n", __func__);
> + temp_val = c67x00_ll_husb_get_frame(c67x00->sie);
> + temp_val &= HOST_FRAME_MASK;
> + return temp_val ? (temp_val - 1) : HOST_FRAME_MASK;
> +}
> +
> +static struct hc_driver c67x00_hc_driver = {
> + .description = "c67x00-hcd",
> + .product_desc = "Cypress C67X00 Host Controller",
> + .hcd_priv_size = sizeof(struct c67x00_hcd),
> + .flags = HCD_USB11 | HCD_MEMORY,
> +
> + /*
> + * basic lifecycle operations
> + */
> + .start = c67x00_hcd_start,
> + .stop = c67x00_hcd_stop,
> +
> + /*
> + * managing i/o requests and associated device resources
> + */
> + .urb_enqueue = c67x00_urb_enqueue,
> + .urb_dequeue = c67x00_urb_dequeue,
> + .endpoint_disable = c67x00_endpoint_disable,
> +
> + /*
> + * scheduling support
> + */
> + .get_frame_number = c67x00_hcd_get_frame,
> +
> + /*
> + * root hub support
> + */
> + .hub_status_data = c67x00_hub_status_data,
> + .hub_control = c67x00_hub_control,
> +};
> +
> +/* ---------------------------------------------------------------------
> + * Setup/Teardown routines
> + */
> +
> +int c67x00_hcd_probe(struct c67x00_sie *sie)
> +{
> + struct c67x00_hcd *c67x00;
> + struct usb_hcd *hcd;
> + unsigned long flags;
> + int retval;
> +
> + if (usb_disabled())
> + return -ENODEV;
> +
> + hcd = usb_create_hcd(&c67x00_hc_driver, sie_dev(sie), "c67x00_sie");
> + if (!hcd) {
> + retval = -ENOMEM;
> + goto err0;
> + }
> + c67x00 = hcd_to_c67x00_hcd(hcd);
> +
> + spin_lock_init(&c67x00->lock);
> + c67x00->sie = sie;
> +
> + INIT_LIST_HEAD(&c67x00->list[PIPE_ISOCHRONOUS]);
> + INIT_LIST_HEAD(&c67x00->list[PIPE_INTERRUPT]);
> + INIT_LIST_HEAD(&c67x00->list[PIPE_CONTROL]);
> + INIT_LIST_HEAD(&c67x00->list[PIPE_BULK]);
> + c67x00->urb_count = 0;
> + INIT_LIST_HEAD(&c67x00->td_list);
> + c67x00->td_base_addr = CY_HCD_BUF_ADDR + SIE_TD_OFFSET(sie->sie_num);
> + c67x00->buf_base_addr = CY_HCD_BUF_ADDR + SIE_BUF_OFFSET(sie->sie_num);
> + c67x00->max_frame_bw = MAX_FRAME_BW_STD;
> +
> + c67x00_ll_husb_init_host_port(sie);
> +
> + init_completion(&c67x00->endpoint_disable);
> + retval = c67x00_sched_start_scheduler(c67x00);
> + if (retval)
> + goto err1;
> +
> + retval = usb_add_hcd(hcd, 0, 0);
> + if (retval) {
> + dev_dbg(sie_dev(sie), "%s: usb_add_hcd returned %d\n",
> + __func__, retval);
> + goto err2;
> + }
> +
> + spin_lock_irqsave(&sie->lock, flags);
> + sie->private_data = c67x00;
> + sie->irq = c67x00_hcd_irq;
> + spin_unlock_irqrestore(&sie->lock, flags);
> +
> + return retval;
> +
> + err2:
> + c67x00_sched_stop_scheduler(c67x00);
> + err1:
> + usb_put_hcd(hcd);
> + err0:
> + return retval;
> +}
> +
> +/* may be called with controller, bus, and devices active */
> +void c67x00_hcd_remove(struct c67x00_sie *sie)
> +{
> + struct c67x00_hcd *c67x00 = sie->private_data;
> + struct usb_hcd *hcd = c67x00_hcd_to_hcd(c67x00);
> +
> + c67x00_sched_stop_scheduler(c67x00);
> + usb_remove_hcd(hcd);
> + usb_put_hcd(hcd);
> +}
> Index: linux-2.6/drivers/usb/c67x00/c67x00-hcd.h
> ===================================================================
> --- /dev/null
> +++ linux-2.6/drivers/usb/c67x00/c67x00-hcd.h
> @@ -0,0 +1,133 @@
> +/*
> + * c67x00-hcd.h: Cypress C67X00 USB HCD
> + *
> + * Copyright (C) 2006-2008 Barco N.V.
> + * Derived from the Cypress cy7c67200/300 ezusb linux driver and
> + * based on multiple host controller drivers inside the linux kernel.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
> + * MA 02110-1301 USA.
> + */
> +
> +#ifndef _USB_C67X00_HCD_H
> +#define _USB_C67X00_HCD_H
> +
> +#include <linux/kernel.h>
> +#include <linux/spinlock.h>
> +#include <linux/list.h>
> +#include <linux/usb.h>
> +#include "../core/hcd.h"
> +#include "c67x00.h"
> +
> +/*
> + * The following parameters depend on the CPU speed, bus speed, ...
> + * These can be tuned for specific use cases, e.g. if isochronous transfers
> + * are very important, bandwith can be sacrificed to guarantee that the
> + * 1ms deadline will be met.
> + * If bulk transfers are important, the MAX_FRAME_BW can be increased,
> + * but some (or many) isochronous deadlines might not be met.
> + *
> + * The values are specified in bittime.
> + */
> +
> +/*
> + * The current implementation switches between _STD (default) and _ISO (when
> + * isochronous transfers are scheduled), in order to optimize the throughput
> + * in normal cicrumstances, but also provide good isochronous behaviour.
> + *
> + * Bandwidth is described in bit time so with a 12MHz USB clock and 1ms
> + * frames; there are 12000 bit times per frame.
> + */
> +
> +#define TOTAL_FRAME_BW 12000
> +#define DEFAULT_EOT 2250
> +
> +#define MAX_FRAME_BW_STD (TOTAL_FRAME_BW - DEFAULT_EOT)
> +#define MAX_FRAME_BW_ISO 2400
> +
> +/*
> + * Periodic transfers may only use 90% of the full frame, but as
> + * we currently don't even use 90% of the full frame, we may
> + * use the full usable time for periodic transfers.
> + */
> +#define MAX_PERIODIC_BW(full_bw) full_bw
> +
> +/* -------------------------------------------------------------------------- */
> +
> +struct c67x00_hcd {
> + spinlock_t lock;
> + struct c67x00_sie *sie;
> + unsigned int low_speed_ports; /* bitmask of low speed ports */
> + unsigned int urb_count;
> + unsigned int urb_iso_count;
> +
> + struct list_head list[4]; /* iso, int, ctrl, bulk */
> +#if PIPE_BULK != 3
> +#error "Sanity check failed, this code presumes PIPE_... to range from 0 to 3"
> +#endif
> +
> + /* USB bandwidth allocated to td_list */
> + int bandwidth_allocated;
> + /* USB bandwidth allocated for isoc/int transfer */
> + int periodic_bw_allocated;
> + struct list_head td_list;
> + int max_frame_bw;
> +
> + u16 td_base_addr;
> + u16 buf_base_addr;
> + u16 next_td_addr;
> + u16 next_buf_addr;
> +
> + struct tasklet_struct tasklet;
> +
> + struct completion endpoint_disable;
> +
> + u16 current_frame;
> + u16 last_frame;
> +};
> +
> +static inline struct c67x00_hcd *hcd_to_c67x00_hcd(struct usb_hcd *hcd)
> +{
> + return (struct c67x00_hcd *)(hcd->hcd_priv);
> +}
> +
> +static inline struct usb_hcd *c67x00_hcd_to_hcd(struct c67x00_hcd *c67x00)
> +{
> + return container_of((void *)c67x00, struct usb_hcd, hcd_priv);
> +}
> +
> +/* ---------------------------------------------------------------------
> + * Functions used by c67x00-drv
> + */
> +
> +int c67x00_hcd_probe(struct c67x00_sie *sie);
> +void c67x00_hcd_remove(struct c67x00_sie *sie);
> +
> +/* ---------------------------------------------------------------------
> + * Transfer Descriptor scheduling functions
> + */
> +int c67x00_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags);
> +int c67x00_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status);
> +void c67x00_endpoint_disable(struct usb_hcd *hcd,
> + struct usb_host_endpoint *ep);
> +
> +void c67x00_hcd_msg_received(struct c67x00_sie *sie, u16 msg);
> +void c67x00_sched_kick(struct c67x00_hcd *c67x00);
> +int c67x00_sched_start_scheduler(struct c67x00_hcd *c67x00);
> +void c67x00_sched_stop_scheduler(struct c67x00_hcd *c67x00);
> +
> +#define c67x00_hcd_dev(x) (c67x00_hcd_to_hcd(x)->self.controller)
> +
> +#endif /* _USB_C67X00_HCD_H */
> Index: linux-2.6/drivers/usb/c67x00/c67x00-sched.c
> ===================================================================
> --- /dev/null
> +++ linux-2.6/drivers/usb/c67x00/c67x00-sched.c
> @@ -0,0 +1,1170 @@
> +/*
> + * c67x00-sched.c: Cypress C67X00 USB Host Controller Driver - TD scheduling
> + *
> + * Copyright (C) 2006-2008 Barco N.V.
> + * Derived from the Cypress cy7c67200/300 ezusb linux driver and
> + * based on multiple host controller drivers inside the linux kernel.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
> + * MA 02110-1301 USA.
> + */
> +
> +#include <linux/kthread.h>
> +
> +#include "c67x00.h"
> +#include "c67x00-hcd.h"
> +
> +/*
> + * These are the stages for a control urb, they are kept
> + * in both urb->interval and td->privdata.
> + */
> +#define SETUP_STAGE 0
> +#define DATA_STAGE 1
> +#define STATUS_STAGE 2
> +
> +/* -------------------------------------------------------------------------- */
> +
> +/**
> + * struct c67x00_ep_data: Host endpoint data structure
> + */
> +struct c67x00_ep_data {
> + struct list_head queue;
> + struct list_head node;
> + struct usb_host_endpoint *hep;
> + struct usb_device *dev;
> + u16 next_frame; /* For int/isoc transactions */
> +};
> +
> +/**
> + * struct c67x00_td
> + *
> + * Hardware parts are little endiannes, SW in CPU endianess.
> + */
> +struct c67x00_td {
> + /* HW specific part */
> + __le16 ly_base_addr; /* Bytes 0-1 */
> + __le16 port_length; /* Bytes 2-3 */
> + u8 pid_ep; /* Byte 4 */
> + u8 dev_addr; /* Byte 5 */
> + u8 ctrl_reg; /* Byte 6 */
> + u8 status; /* Byte 7 */
> + u8 retry_cnt; /* Byte 8 */
> +#define TT_OFFSET 2
> +#define TT_CONTROL 0
> +#define TT_ISOCHRONOUS 1
> +#define TT_BULK 2
> +#define TT_INTERRUPT 3
> + u8 residue; /* Byte 9 */
> + __le16 next_td_addr; /* Bytes 10-11 */
> + /* SW part */
> + struct list_head td_list;
> + u16 td_addr;
> + void *data;
> + struct urb *urb;
> + unsigned long privdata;
> +
> + /* These are needed for handling the toggle bits:
> + * an urb can be dequeued while a td is in progress
> + * after checking the td, the toggle bit might need to
> + * be fixed */
> + struct c67x00_ep_data *ep_data;
> + unsigned int pipe;
> +};
> +
> +struct c67x00_urb_priv {
> + struct list_head hep_node;
> + struct urb *urb;
> + int port;
> + int cnt; /* packet number for isoc */
> + int status;
> + struct c67x00_ep_data *ep_data;
> +};
> +
> +#define td_udev(td) ((td)->ep_data->dev)
> +
> +#define CY_TD_SIZE 12
> +
> +#define TD_PIDEP_OFFSET 0x04
> +#define TD_PIDEPMASK_PID 0xF0
> +#define TD_PIDEPMASK_EP 0x0F
> +#define TD_PORTLENMASK_DL 0x02FF
> +#define TD_PORTLENMASK_PN 0xC000
> +
> +#define TD_STATUS_OFFSET 0x07
> +#define TD_STATUSMASK_ACK 0x01
> +#define TD_STATUSMASK_ERR 0x02
> +#define TD_STATUSMASK_TMOUT 0x04
> +#define TD_STATUSMASK_SEQ 0x08
> +#define TD_STATUSMASK_SETUP 0x10
> +#define TD_STATUSMASK_OVF 0x20
> +#define TD_STATUSMASK_NAK 0x40
> +#define TD_STATUSMASK_STALL 0x80
> +
> +#define TD_ERROR_MASK (TD_STATUSMASK_ERR | TD_STATUSMASK_TMOUT | \
> + TD_STATUSMASK_STALL)
> +
> +#define TD_RETRYCNT_OFFSET 0x08
> +#define TD_RETRYCNTMASK_ACT_FLG 0x10
> +#define TD_RETRYCNTMASK_TX_TYPE 0x0C
> +#define TD_RETRYCNTMASK_RTY_CNT 0x03
> +
> +#define TD_RESIDUE_OVERFLOW 0x80
> +
> +#define TD_PID_IN 0x90
> +
> +/* Residue: signed 8bits, neg -> OVERFLOW, pos -> UNDERFLOW */
> +#define td_residue(td) ((__s8)(td->residue))
> +#define td_ly_base_addr(td) (__le16_to_cpu((td)->ly_base_addr))
> +#define td_port_length(td) (__le16_to_cpu((td)->port_length))
> +#define td_next_td_addr(td) (__le16_to_cpu((td)->next_td_addr))
> +
> +#define td_active(td) ((td)->retry_cnt & TD_RETRYCNTMASK_ACT_FLG)
> +#define td_length(td) (td_port_length(td) & TD_PORTLENMASK_DL)
> +
> +#define td_sequence_ok(td) (!td->status || \
> + (!(td->status & TD_STATUSMASK_SEQ) == \
> + !(td->ctrl_reg & SEQ_SEL)))
> +
> +#define td_acked(td) (!td->status || \
> + (td->status & TD_STATUSMASK_ACK))
> +#define td_actual_bytes(td) (td_length(td) - td_residue(td))
> +
> +/* -------------------------------------------------------------------------- */
> +
> +#ifdef DEBUG
> +
> +/**
> + * dbg_td - Dump the contents of the TD
> + */
> +static void dbg_td(struct c67x00_hcd *c67x00, struct c67x00_td *td, char *msg)
> +{
> + struct device *dev = c67x00_hcd_dev(c67x00);
> +
> + dev_dbg(dev, "### %s at 0x%04x\n", msg, td->td_addr);
> + dev_dbg(dev, "urb: 0x%p\n", td->urb);
> + dev_dbg(dev, "endpoint: %4d\n", usb_pipeendpoint(td->pipe));
> + dev_dbg(dev, "pipeout: %4d\n", usb_pipeout(td->pipe));
> + dev_dbg(dev, "ly_base_addr: 0x%04x\n", td_ly_base_addr(td));
> + dev_dbg(dev, "port_length: 0x%04x\n", td_port_length(td));
> + dev_dbg(dev, "pid_ep: 0x%02x\n", td->pid_ep);
> + dev_dbg(dev, "dev_addr: 0x%02x\n", td->dev_addr);
> + dev_dbg(dev, "ctrl_reg: 0x%02x\n", td->ctrl_reg);
> + dev_dbg(dev, "status: 0x%02x\n", td->status);
> + dev_dbg(dev, "retry_cnt: 0x%02x\n", td->retry_cnt);
> + dev_dbg(dev, "residue: 0x%02x\n", td->residue);
> + dev_dbg(dev, "next_td_addr: 0x%04x\n", td_next_td_addr(td));
> + dev_dbg(dev, "data:");
> + print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 1,
> + td->data, td_length(td), 1);
> +}
> +#else /* DEBUG */
> +
> +static inline void
> +dbg_td(struct c67x00_hcd *c67x00, struct c67x00_td *td, char *msg) { }
> +
> +#endif /* DEBUG */
> +
> +/* -------------------------------------------------------------------------- */
> +/* Helper functions */
> +
> +static inline u16 c67x00_get_current_frame_number(struct c67x00_hcd *c67x00)
> +{
> + return c67x00_ll_husb_get_frame(c67x00->sie) & HOST_FRAME_MASK;
> +}
> +
> +/**
> + * frame_add
> + * Software wraparound for framenumbers.
> + */
> +static inline u16 frame_add(u16 a, u16 b)
> +{
> + return (a + b) & HOST_FRAME_MASK;
> +}
> +
> +/**
> + * frame_after - is frame a after frame b
> + */
> +static inline int frame_after(u16 a, u16 b)
> +{
> + return ((HOST_FRAME_MASK + a - b) & HOST_FRAME_MASK) <
> + (HOST_FRAME_MASK / 2);
> +}
> +
> +/**
> + * frame_after_eq - is frame a after or equal to frame b
> + */
> +static inline int frame_after_eq(u16 a, u16 b)
> +{
> + return ((HOST_FRAME_MASK + 1 + a - b) & HOST_FRAME_MASK) <
> + (HOST_FRAME_MASK / 2);
> +}
> +
> +/* -------------------------------------------------------------------------- */
> +
> +/**
> + * c67x00_release_urb - remove link from all tds to this urb
> + * Disconnects the urb from it's tds, so that it can be given back.
> + * pre: urb->hcpriv != NULL
> + */
> +static void c67x00_release_urb(struct c67x00_hcd *c67x00, struct urb *urb)
> +{
> + struct c67x00_td *td;
> + struct c67x00_urb_priv *urbp;
> +
> + BUG_ON(!urb);
> +
> + c67x00->urb_count--;
> +
> + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
> + c67x00->urb_iso_count--;
> + if (c67x00->urb_iso_count == 0)
> + c67x00->max_frame_bw = MAX_FRAME_BW_STD;
> + }
> +
> + /* TODO this might be not so efficient when we've got many urbs!
> + * Alternatives:
> + * * only clear when needed
> + * * keep a list of tds with each urbp
> + */
> + list_for_each_entry(td, &c67x00->td_list, td_list)
> + if (urb == td->urb)
> + td->urb = NULL;
> +
> + urbp = urb->hcpriv;
> + urb->hcpriv = NULL;
> + list_del(&urbp->hep_node);
> + kfree(urbp);
> +}
> +
> +/* -------------------------------------------------------------------------- */
> +
> +static struct c67x00_ep_data *
> +c67x00_ep_data_alloc(struct c67x00_hcd *c67x00, struct urb *urb)
> +{
> + struct usb_host_endpoint *hep = urb->ep;
> + struct c67x00_ep_data *ep_data;
> + int type;
> +
> + c67x00->current_frame = c67x00_get_current_frame_number(c67x00);
> +
> + /* Check if endpoint already has a c67x00_ep_data struct allocated */
> + if (hep->hcpriv) {
> + ep_data = hep->hcpriv;
> + if (frame_after(c67x00->current_frame, ep_data->next_frame))
> + ep_data->next_frame =
> + frame_add(c67x00->current_frame, 1);
> + return hep->hcpriv;
> + }
> +
> + /* Allocate and initialize a new c67x00 endpoint data structure */
> + ep_data = kzalloc(sizeof(*ep_data), GFP_ATOMIC);
> + if (!ep_data)
> + return NULL;
> +
> + INIT_LIST_HEAD(&ep_data->queue);
> + INIT_LIST_HEAD(&ep_data->node);
> + ep_data->hep = hep;
> +
> + /* hold a reference to udev as long as this endpoint lives,
> + * this is needed to possibly fix the data toggle */
> + ep_data->dev = usb_get_dev(urb->dev);
> + hep->hcpriv = ep_data;
> +
> + /* For ISOC and INT endpoints, start ASAP: */
> + ep_data->next_frame = frame_add(c67x00->current_frame, 1);
> +
> + /* Add the endpoint data to one of the pipe lists; must be added
> + in order of endpoint address */
> + type = usb_pipetype(urb->pipe);
> + if (list_empty(&ep_data->node)) {
> + list_add(&ep_data->node, &c67x00->list[type]);
> + } else {
> + struct c67x00_ep_data *prev;
> +
> + list_for_each_entry(prev, &c67x00->list[type], node) {
> + if (prev->hep->desc.bEndpointAddress >
> + hep->desc.bEndpointAddress) {
> + list_add(&ep_data->node, prev->node.prev);
> + break;
> + }
> + }
> + }
> +
> + return ep_data;
> +}
> +
> +static int c67x00_ep_data_free(struct usb_host_endpoint *hep)
> +{
> + struct c67x00_ep_data *ep_data = hep->hcpriv;
> +
> + if (!ep_data)
> + return 0;
> +
> + if (!list_empty(&ep_data->queue))
> + return -EBUSY;
> +
> + usb_put_dev(ep_data->dev);
> + list_del(&ep_data->queue);
> + list_del(&ep_data->node);
> +
> + kfree(ep_data);
> + hep->hcpriv = NULL;
> +
> + return 0;
> +}
> +
> +void c67x00_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
> +{
> + struct c67x00_hcd *c67x00 = hcd_to_c67x00_hcd(hcd);
> + unsigned long flags;
> +
> + if (!list_empty(&ep->urb_list))
> + dev_warn(c67x00_hcd_dev(c67x00), "error: urb list not empty\n");
> +
> + spin_lock_irqsave(&c67x00->lock, flags);
> +
> + /* loop waiting for all transfers in the endpoint queue to complete */
> + while (c67x00_ep_data_free(ep)) {
> + /* Drop the lock so we can sleep waiting for the hardware */
> + spin_unlock_irqrestore(&c67x00->lock, flags);
> +
> + /* it could happen that we reinitialize this completion, while
> + * somebody was waiting for that completion. The timeout and
> + * while loop handle such cases, but this might be improved */
> + INIT_COMPLETION(c67x00->endpoint_disable);
> + c67x00_sched_kick(c67x00);
> + wait_for_completion_timeout(&c67x00->endpoint_disable, 1 * HZ);
> +
> + spin_lock_irqsave(&c67x00->lock, flags);
> + }
> +
> + spin_unlock_irqrestore(&c67x00->lock, flags);
> +}
> +
> +/* -------------------------------------------------------------------------- */
> +
> +static inline int get_root_port(struct usb_device *dev)
> +{
> + while (dev->parent->parent)
> + dev = dev->parent;
> + return dev->portnum;
> +}
> +
> +int c67x00_urb_enqueue(struct usb_hcd *hcd,
> + struct urb *urb, gfp_t mem_flags)
> +{
> + int ret;
> + unsigned long flags;
> + struct c67x00_urb_priv *urbp;
> + struct c67x00_hcd *c67x00 = hcd_to_c67x00_hcd(hcd);
> + int port = get_root_port(urb->dev)-1;
> +
> + spin_lock_irqsave(&c67x00->lock, flags);
> +
> + /* Make sure host controller is running */
> + if (!HC_IS_RUNNING(hcd->state)) {
> + ret = -ENODEV;
> + goto err_not_linked;
> + }
> +
> + ret = usb_hcd_link_urb_to_ep(hcd, urb);
> + if (ret)
> + goto err_not_linked;
> +
> + /* Allocate and initialize urb private data */
> + urbp = kzalloc(sizeof(*urbp), mem_flags);
> + if (!urbp) {
> + ret = -ENOMEM;
> + goto err_urbp;
> + }
> +
> + INIT_LIST_HEAD(&urbp->hep_node);
> + urbp->urb = urb;
> + urbp->port = port;
> +
> + urbp->ep_data = c67x00_ep_data_alloc(c67x00, urb);
> +
> + if (!urbp->ep_data) {
> + ret = -ENOMEM;
> + goto err_epdata;
> + }
> +
> + /* TODO claim bandwidth with usb_claim_bandwidth?
> + * also release it somewhere! */
> +
> + urb->hcpriv = urbp;
> +
> + urb->actual_length = 0; /* Nothing received/transmitted yet */
> +
> + switch (usb_pipetype(urb->pipe)) {
> + case PIPE_CONTROL:
> + urb->interval = SETUP_STAGE;
> + break;
> + case PIPE_INTERRUPT:
> + break;
> + case PIPE_BULK:
> + break;
> + case PIPE_ISOCHRONOUS:
> + if (c67x00->urb_iso_count == 0)
> + c67x00->max_frame_bw = MAX_FRAME_BW_ISO;
> + c67x00->urb_iso_count++;
> + /* Assume always URB_ISO_ASAP, FIXME */
> + if (list_empty(&urbp->ep_data->queue))
> + urb->start_frame = urbp->ep_data->next_frame;
> + else {
> + /* Go right after the last one */
> + struct urb *last_urb;
> +
> + last_urb = list_entry(urbp->ep_data->queue.prev,
> + struct c67x00_urb_priv,
> + hep_node)->urb;
> + urb->start_frame =
> + frame_add(last_urb->start_frame,
> + last_urb->number_of_packets *
> + last_urb->interval);
> + }
> + urbp->cnt = 0;
> + break;
> + }
> +
> + /* Add the URB to the endpoint queue */
> + list_add_tail(&urbp->hep_node, &urbp->ep_data->queue);
> +
> + /* If this is the only URB, kick start the controller */
> + if (!c67x00->urb_count++)
> + c67x00_ll_hpi_enable_sofeop(c67x00->sie);
> +
> + c67x00_sched_kick(c67x00);
> + spin_unlock_irqrestore(&c67x00->lock, flags);
> +
> + return 0;
> +
> +err_epdata:
> + kfree(urbp);
> +err_urbp:
> + usb_hcd_unlink_urb_from_ep(hcd, urb);
> +err_not_linked:
> + spin_unlock_irqrestore(&c67x00->lock, flags);
> +
> + return ret;
> +}
> +
> +int c67x00_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
> +{
> + struct c67x00_hcd *c67x00 = hcd_to_c67x00_hcd(hcd);
> + unsigned long flags;
> + int rc;
> +
> + spin_lock_irqsave(&c67x00->lock, flags);
> + rc = usb_hcd_check_unlink_urb(hcd, urb, status);
> + if (rc)
> + goto done;
> +
> + c67x00_release_urb(c67x00, urb);
> + usb_hcd_unlink_urb_from_ep(hcd, urb);
> +
> + spin_unlock(&c67x00->lock);
> + usb_hcd_giveback_urb(hcd, urb, status);
> + spin_lock(&c67x00->lock);
> +
> + spin_unlock_irqrestore(&c67x00->lock, flags);
> +
> + return 0;
> +
> + done:
> + spin_unlock_irqrestore(&c67x00->lock, flags);
> + return rc;
> +}
> +
> +/* -------------------------------------------------------------------------- */
> +
> +/*
> + * pre: c67x00 locked, urb unlocked
> + */
> +static void
> +c67x00_giveback_urb(struct c67x00_hcd *c67x00, struct urb *urb, int status)
> +{
> + struct c67x00_urb_priv *urbp;
> +
> + if (!urb)
> + return;
> +
> + urbp = urb->hcpriv;
> + urbp->status = status;
> +
> + list_del_init(&urbp->hep_node);
> +
> + c67x00_release_urb(c67x00, urb);
> + usb_hcd_unlink_urb_from_ep(c67x00_hcd_to_hcd(c67x00), urb);
> + spin_unlock(&c67x00->lock);
> + usb_hcd_giveback_urb(c67x00_hcd_to_hcd(c67x00), urb, urbp->status);
> + spin_lock(&c67x00->lock);
> +}
> +
> +/* -------------------------------------------------------------------------- */
> +
> +static int c67x00_claim_frame_bw(struct c67x00_hcd *c67x00, struct urb *urb,
> + int len, int periodic)
> +{
> + struct c67x00_urb_priv *urbp = urb->hcpriv;
> + int bit_time;
> +
> + /* According to the C67x00 BIOS user manual, page 3-18,19, the
> + * following calculations provide the full speed bit times for
> + * a transaction.
> + *
> + * FS(in) = 112.5 + 9.36*BC + HOST_DELAY
> + * FS(in,iso) = 90.5 + 9.36*BC + HOST_DELAY
> + * FS(out) = 112.5 + 9.36*BC + HOST_DELAY
> + * FS(out,iso) = 78.4 + 9.36*BC + HOST_DELAY
> + * LS(in) = 802.4 + 75.78*BC + HOST_DELAY
> + * LS(out) = 802.6 + 74.67*BC + HOST_DELAY
> + *
> + * HOST_DELAY == 106 for the c67200 and c67300.
> + */
> +
> + /* make calculations in 1/100 bit times to maintain resolution */
> + if (urbp->ep_data->dev->speed == USB_SPEED_LOW) {
> + /* Low speed pipe */
> + if (usb_pipein(urb->pipe))
> + bit_time = 80240 + 7578*len;
> + else
> + bit_time = 80260 + 7467*len;
> + } else {
> + /* FS pipes */
> + if (usb_pipeisoc(urb->pipe))
> + bit_time = usb_pipein(urb->pipe) ? 9050 : 7840;
> + else
> + bit_time = 11250;
> + bit_time += 936*len;
> + }
> +
> + /* Scale back down to integer bit times. Use a host delay of 106.
> + * (this is the only place it is used) */
> + bit_time = ((bit_time+50) / 100) + 106;
> +
> + if (unlikely(bit_time + c67x00->bandwidth_allocated >=
> + c67x00->max_frame_bw))
> + return -EMSGSIZE;
> +
> + if (unlikely(c67x00->next_td_addr + CY_TD_SIZE >=
> + c67x00->td_base_addr + SIE_TD_SIZE))
> + return -EMSGSIZE;
> +
> + if (unlikely(c67x00->next_buf_addr + len >=
> + c67x00->buf_base_addr + SIE_TD_BUF_SIZE))
> + return -EMSGSIZE;
> +
> + if (periodic) {
> + if (unlikely(bit_time + c67x00->periodic_bw_allocated >=
> + MAX_PERIODIC_BW(c67x00->max_frame_bw)))
> + return -EMSGSIZE;
> + c67x00->periodic_bw_allocated += bit_time;
> + }
> +
> + c67x00->bandwidth_allocated += bit_time;
> + return 0;
> +}
> +
> +/* -------------------------------------------------------------------------- */
> +
> +/**
> + * td_addr and buf_addr must be word aligned
> + */
> +static int c67x00_create_td(struct c67x00_hcd *c67x00, struct urb *urb,
> + void *data, int len, int pid, int toggle,
> + unsigned long privdata)
> +{
> + struct c67x00_td *td;
> + struct c67x00_urb_priv *urbp = urb->hcpriv;
> + const __u8 active_flag = 1, retry_cnt = 1;
> + __u8 cmd = 0;
> + int tt = 0;
> +
> + if (c67x00_claim_frame_bw(c67x00, urb, len, usb_pipeisoc(urb->pipe)
> + || usb_pipeint(urb->pipe)))
> + return -EMSGSIZE; /* Not really an error, but expected */
> +
> + td = kzalloc(sizeof(*td), GFP_ATOMIC);
> + if (!td)
> + return -ENOMEM;
> +
> + td->pipe = urb->pipe;
> + td->ep_data = urbp->ep_data;
> +
> + if ((td_udev(td)->speed == USB_SPEED_LOW) &&
> + !(c67x00->low_speed_ports & (1 << urbp->port)))
> + cmd |= PREAMBLE_EN;
> +
> + switch (usb_pipetype(td->pipe)) {
> + case PIPE_ISOCHRONOUS:
> + tt = TT_ISOCHRONOUS;
> + cmd |= ISO_EN;
> + break;
> + case PIPE_CONTROL:
> + tt = TT_CONTROL;
> + break;
> + case PIPE_BULK:
> + tt = TT_BULK;
> + break;
> + case PIPE_INTERRUPT:
> + tt = TT_INTERRUPT;
> + break;
> + }
> +
> + if (toggle)
> + cmd |= SEQ_SEL;
> +
> + cmd |= ARM_EN;
> +
> + /* SW part */
> + td->td_addr = c67x00->next_td_addr;
> + c67x00->next_td_addr = c67x00->next_td_addr + CY_TD_SIZE;
> +
> + /* HW part */
> + td->ly_base_addr = __cpu_to_le16(c67x00->next_buf_addr);
> + td->port_length = __cpu_to_le16((c67x00->sie->sie_num << 15) |
> + (urbp->port << 14) | (len & 0x3FF));
> + td->pid_ep = ((pid & 0xF) << TD_PIDEP_OFFSET) |
> + (usb_pipeendpoint(td->pipe) & 0xF);
> + td->dev_addr = usb_pipedevice(td->pipe) & 0x7F;
> + td->ctrl_reg = cmd;
> + td->status = 0;
> + td->retry_cnt = (tt << TT_OFFSET) | (active_flag << 4) | retry_cnt;
> + td->residue = 0;
> + td->next_td_addr = __cpu_to_le16(c67x00->next_td_addr);
> +
> + /* SW part */
> + td->data = data;
> + td->urb = urb;
> + td->privdata = privdata;
> +
> + c67x00->next_buf_addr += (len + 1) & ~0x01; /* properly align */
> +
> + list_add_tail(&td->td_list, &c67x00->td_list);
> + return 0;
> +}
> +
> +static inline void c67x00_release_td(struct c67x00_td *td)
> +{
> + list_del_init(&td->td_list);
> + kfree(td);
> +}
> +
> +/* -------------------------------------------------------------------------- */
> +
> +static int c67x00_add_data_urb(struct c67x00_hcd *c67x00, struct urb *urb)
> +{
> + int remaining;
> + int toggle;
> + int pid;
> + int ret = 0;
> + int maxps;
> + int need_empty;
> +
> + toggle = usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
> + usb_pipeout(urb->pipe));
> + remaining = urb->transfer_buffer_length - urb->actual_length;
> +
> + maxps = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
> +
> + need_empty = (urb->transfer_flags & URB_ZERO_PACKET) &&
> + usb_pipeout(urb->pipe) && !(remaining % maxps);
> +
> + while (remaining || need_empty) {
> + int len;
> + char *td_buf;
> +
> + len = (remaining > maxps) ? maxps : remaining;
> + if (!len)
> + need_empty = 0;
> +
> + pid = usb_pipeout(urb->pipe) ? USB_PID_OUT : USB_PID_IN;
> + td_buf = urb->transfer_buffer + urb->transfer_buffer_length -
> + remaining;
> + ret = c67x00_create_td(c67x00, urb, td_buf, len, pid, toggle,
> + DATA_STAGE);
> + if (ret)
> + return ret; /* td wasn't created */
> +
> + toggle ^= 1;
> + remaining -= len;
> + if (usb_pipecontrol(urb->pipe))
> + break;
> + }
> +
> + return 0;
> +}
> +
> +/**
> + * return 0 in case more bandwidth is available, else errorcode
> + */
> +static int c67x00_add_ctrl_urb(struct c67x00_hcd *c67x00, struct urb *urb)
> +{
> + int ret;
> + int pid;
> +
> + switch (urb->interval) {
> + default:
> + case SETUP_STAGE:
> + ret = c67x00_create_td(c67x00, urb, urb->setup_packet,
> + 8, USB_PID_SETUP, 0, SETUP_STAGE);
> + if (ret)
> + return ret;
> + urb->interval = SETUP_STAGE;
> + usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
> + usb_pipeout(urb->pipe), 1);
> + break;
> + case DATA_STAGE:
> + if (urb->transfer_buffer_length) {
> + ret = c67x00_add_data_urb(c67x00, urb);
> + if (ret)
> + return ret;
> + break;
> + } /* else fallthrough */
> + case STATUS_STAGE:
> + pid = !usb_pipeout(urb->pipe) ? USB_PID_OUT : USB_PID_IN;
> + ret = c67x00_create_td(c67x00, urb, NULL, 0, pid, 1,
> + STATUS_STAGE);
> + if (ret)
> + return ret;
> + break;
> + }
> +
> + return 0;
> +}
> +
> +/*
> + * return 0 in case more bandwidth is available, else errorcode
> + */
> +static int c67x00_add_int_urb(struct c67x00_hcd *c67x00, struct urb *urb)
> +{
> + struct c67x00_urb_priv *urbp = urb->hcpriv;
> +
> + if (frame_after_eq(c67x00->current_frame, urbp->ep_data->next_frame)) {
> + urbp->ep_data->next_frame =
> + frame_add(urbp->ep_data->next_frame, urb->interval);
> + return c67x00_add_data_urb(c67x00, urb);
> + }
> + return 0;
> +}
> +
> +static int c67x00_add_iso_urb(struct c67x00_hcd *c67x00, struct urb *urb)
> +{
> + struct c67x00_urb_priv *urbp = urb->hcpriv;
> +
> + if (frame_after_eq(c67x00->current_frame, urbp->ep_data->next_frame)) {
> + char *td_buf;
> + int len, pid, ret;
> +
> + BUG_ON(urbp->cnt >= urb->number_of_packets);
> +
> + td_buf = urb->transfer_buffer +
> + urb->iso_frame_desc[urbp->cnt].offset;
> + len = urb->iso_frame_desc[urbp->cnt].length;
> + pid = usb_pipeout(urb->pipe) ? USB_PID_OUT : USB_PID_IN;
> +
> + ret = c67x00_create_td(c67x00, urb, td_buf, len, pid, 0,
> + urbp->cnt);
> + if (ret) {
> + printk(KERN_DEBUG "create failed: %d\n", ret);
> + urb->iso_frame_desc[urbp->cnt].actual_length = 0;
> + urb->iso_frame_desc[urbp->cnt].status = ret;
> + if (urbp->cnt + 1 == urb->number_of_packets)
> + c67x00_giveback_urb(c67x00, urb, 0);
> + }
> +
> + urbp->ep_data->next_frame =
> + frame_add(urbp->ep_data->next_frame, urb->interval);
> + urbp->cnt++;
> + }
> + return 0;
> +}
> +
> +/* -------------------------------------------------------------------------- */
> +
> +static void c67x00_fill_from_list(struct c67x00_hcd *c67x00, int type,
> + int (*add)(struct c67x00_hcd *, struct urb *))
> +{
> + struct c67x00_ep_data *ep_data;
> + struct urb *urb;
> +
> + /* traverse every endpoint on the list */
> + list_for_each_entry(ep_data, &c67x00->list[type], node) {
> + if (!list_empty(&ep_data->queue)) {
> + /* and add the first urb */
> + /* isochronous transfer rely on this */
> + urb = list_entry(ep_data->queue.next,
> + struct c67x00_urb_priv,
> + hep_node)->urb;
> + add(c67x00, urb);
> + }
> + }
> +}
> +
> +static void c67x00_fill_frame(struct c67x00_hcd *c67x00)
> +{
> + struct c67x00_td *td, *ttd;
> +
> + /* Check if we can proceed */
> + if (!list_empty(&c67x00->td_list)) {
> + dev_warn(c67x00_hcd_dev(c67x00),
> + "TD list not empty! This should not happen!\n");
> + list_for_each_entry_safe(td, ttd, &c67x00->td_list, td_list) {
> + dbg_td(c67x00, td, "Unprocessed td");
> + c67x00_release_td(td);
> + }
> + }
> +
> + /* Reinitialize variables */
> + c67x00->bandwidth_allocated = 0;
> + c67x00->periodic_bw_allocated = 0;
> +
> + c67x00->next_td_addr = c67x00->td_base_addr;
> + c67x00->next_buf_addr = c67x00->buf_base_addr;
> +
> + /* Fill the list */
> + c67x00_fill_from_list(c67x00, PIPE_ISOCHRONOUS, c67x00_add_iso_urb);
> + c67x00_fill_from_list(c67x00, PIPE_INTERRUPT, c67x00_add_int_urb);
> + c67x00_fill_from_list(c67x00, PIPE_CONTROL, c67x00_add_ctrl_urb);
> + c67x00_fill_from_list(c67x00, PIPE_BULK, c67x00_add_data_urb);
> +}
> +
> +/* -------------------------------------------------------------------------- */
> +
> +/**
> + * Get TD from C67X00
> + */
> +static inline void
> +c67x00_parse_td(struct c67x00_hcd *c67x00, struct c67x00_td *td)
> +{
> + c67x00_ll_read_mem_le16(c67x00->sie->dev,
> + td->td_addr, td, CY_TD_SIZE);
> +
> + if (usb_pipein(td->pipe) && td_actual_bytes(td))
> + c67x00_ll_read_mem_le16(c67x00->sie->dev, td_ly_base_addr(td),
> + td->data, td_actual_bytes(td));
> +}
> +
> +static int c67x00_td_to_error(struct c67x00_hcd *c67x00, struct c67x00_td *td)
> +{
> + if (td->status & TD_STATUSMASK_ERR) {
> + dbg_td(c67x00, td, "ERROR_FLAG");
> + return -EILSEQ;
> + }
> + if (td->status & TD_STATUSMASK_STALL) {
> + /* dbg_td(c67x00, td, "STALL"); */
> + return -EPIPE;
> + }
> + if (td->status & TD_STATUSMASK_TMOUT) {
> + dbg_td(c67x00, td, "TIMEOUT");
> + return -ETIMEDOUT;
> + }
> +
> + return 0;
> +}
> +
> +static inline int c67x00_end_of_data(struct c67x00_td *td)
> +{
> + int maxps, need_empty, remaining;
> + struct urb *urb = td->urb;
> + int act_bytes;
> +
> + act_bytes = td_actual_bytes(td);
> +
> + if (unlikely(!act_bytes))
> + return 1; /* This was an empty packet */
> +
> + maxps = usb_maxpacket(td_udev(td), td->pipe, usb_pipeout(td->pipe));
> +
> + if (unlikely(act_bytes < maxps))
> + return 1; /* Smaller then full packet */
> +
> + remaining = urb->transfer_buffer_length - urb->actual_length;
> + need_empty = (urb->transfer_flags & URB_ZERO_PACKET) &&
> + usb_pipeout(urb->pipe) && !(remaining % maxps);
> +
> + if (unlikely(!remaining && !need_empty))
> + return 1;
> +
> + return 0;
> +}
> +
> +/* -------------------------------------------------------------------------- */
> +
> +/* Remove all td's from the list which come
> + * after last_td and are meant for the same pipe.
> + * This is used when a short packet has occured */
> +static inline void c67x00_clear_pipe(struct c67x00_hcd *c67x00,
> + struct c67x00_td *last_td)
> +{
> + struct c67x00_td *td, *tmp;
> + td = last_td;
> + tmp = last_td;
> + while (td->td_list.next != &c67x00->td_list) {
> + td = list_entry(td->td_list.next, struct c67x00_td, td_list);
> + if (td->pipe == last_td->pipe) {
> + c67x00_release_td(td);
> + td = tmp;
> + }
> + tmp = td;
> + }
> +}
> +
> +/* -------------------------------------------------------------------------- */
> +
> +static void c67x00_handle_successful_td(struct c67x00_hcd *c67x00,
> + struct c67x00_td *td)
> +{
> + struct urb *urb = td->urb;
> +
> + if (!urb)
> + return;
> +
> + urb->actual_length += td_actual_bytes(td);
> +
> + switch (usb_pipetype(td->pipe)) {
> + /* isochronous tds are handled separately */
> + case PIPE_CONTROL:
> + switch (td->privdata) {
> + case SETUP_STAGE:
> + urb->interval =
> + urb->transfer_buffer_length ?
> + DATA_STAGE : STATUS_STAGE;
> + /* Don't count setup_packet with normal data: */
> + urb->actual_length = 0;
> + break;
> +
> + case DATA_STAGE:
> + if (c67x00_end_of_data(td)) {
> + urb->interval = STATUS_STAGE;
> + c67x00_clear_pipe(c67x00, td);
> + }
> + break;
> +
> + case STATUS_STAGE:
> + urb->interval = 0;
> + c67x00_giveback_urb(c67x00, urb, 0);
> + break;
> + }
> + break;
> +
> + case PIPE_INTERRUPT:
> + case PIPE_BULK:
> + if (unlikely(c67x00_end_of_data(td))) {
> + c67x00_clear_pipe(c67x00, td);
> + c67x00_giveback_urb(c67x00, urb, 0);
> + }
> + break;
> + }
> +}
> +
> +static void c67x00_handle_isoc(struct c67x00_hcd *c67x00, struct c67x00_td *td)
> +{
> + struct urb *urb = td->urb;
> + struct c67x00_urb_priv *urbp;
> + int cnt;
> +
> + if (!urb)
> + return;
> +
> + urbp = urb->hcpriv;
> + cnt = td->privdata;
> +
> + if (td->status & TD_ERROR_MASK)
> + urb->error_count++;
> +
> + urb->iso_frame_desc[cnt].actual_length = td_actual_bytes(td);
> + urb->iso_frame_desc[cnt].status = c67x00_td_to_error(c67x00, td);
> + if (cnt + 1 == urb->number_of_packets) /* Last packet */
> + c67x00_giveback_urb(c67x00, urb, 0);
> +}
> +
> +/* -------------------------------------------------------------------------- */
> +
> +/**
> + * c67x00_check_td_list - handle tds which have been processed by the c67x00
> + * pre: current_td == 0
> + */
> +static inline void c67x00_check_td_list(struct c67x00_hcd *c67x00)
> +{
> + struct c67x00_td *td, *tmp;
> + struct urb *urb;
> + int ack_ok;
> + int clear_endpoint;
> +
> + list_for_each_entry_safe(td, tmp, &c67x00->td_list, td_list) {
> + /* get the TD */
> + c67x00_parse_td(c67x00, td);
> + urb = td->urb; /* urb can be NULL! */
> + ack_ok = 0;
> + clear_endpoint = 1;
> +
> + /* Handle isochronous transfers separately */
> + if (usb_pipeisoc(td->pipe)) {
> + clear_endpoint = 0;
> + c67x00_handle_isoc(c67x00, td);
> + goto cont;
> + }
> +
> + /* When an error occurs, all td's for that pipe go into an
> + * inactive state. This state matches successful transfers so
> + * we must make sure not to service them. */
> + if (td->status & TD_ERROR_MASK) {
> + c67x00_giveback_urb(c67x00, urb,
> + c67x00_td_to_error(c67x00, td));
> + goto cont;
> + }
> +
> + if ((td->status & TD_STATUSMASK_NAK) || !td_sequence_ok(td) ||
> + !td_acked(td))
> + goto cont;
> +
> + /* Sequence ok and acked, don't need to fix toggle */
> + ack_ok = 1;
> +
> + if (unlikely(td->status & TD_STATUSMASK_OVF)) {
> + if (td_residue(td) & TD_RESIDUE_OVERFLOW) {
> + /* Overflow */
> + c67x00_giveback_urb(c67x00, urb, -EOVERFLOW);
> + goto cont;
> + }
> + }
> +
> + clear_endpoint = 0;
> + c67x00_handle_successful_td(c67x00, td);
> +
> +cont:
> + if (clear_endpoint)
> + c67x00_clear_pipe(c67x00, td);
> + if (ack_ok)
> + usb_settoggle(td_udev(td), usb_pipeendpoint(td->pipe),
> + usb_pipeout(td->pipe),
> + !(td->ctrl_reg & SEQ_SEL));
> + /* next in list could have been removed, due to clear_pipe! */
> + tmp = list_entry(td->td_list.next, typeof(*td), td_list);
> + c67x00_release_td(td);
> + }
> +}
> +
> +/* -------------------------------------------------------------------------- */
> +
> +static inline int c67x00_all_tds_processed(struct c67x00_hcd *c67x00)
> +{
> + /* If all tds are processed, we can check the previous frame (if
> + * there was any) and start our next frame.
> + */
> + return !c67x00_ll_husb_get_current_td(c67x00->sie);
> +}
> +
> +/**
> + * Send td to C67X00
> + */
> +static void c67x00_send_td(struct c67x00_hcd *c67x00, struct c67x00_td *td)
> +{
> + int len = td_length(td);
> +
> + if (len && ((td->pid_ep & TD_PIDEPMASK_PID) != TD_PID_IN))
> + c67x00_ll_write_mem_le16(c67x00->sie->dev, td_ly_base_addr(td),
> + td->data, len);
> +
> + c67x00_ll_write_mem_le16(c67x00->sie->dev,
> + td->td_addr, td, CY_TD_SIZE);
> +}
> +
> +static void c67x00_send_frame(struct c67x00_hcd *c67x00)
> +{
> + struct c67x00_td *td;
> +
> + if (list_empty(&c67x00->td_list))
> + dev_warn(c67x00_hcd_dev(c67x00),
> + "%s: td list should not be empty here!\n",
> + __func__);
> +
> + list_for_each_entry(td, &c67x00->td_list, td_list) {
> + if (td->td_list.next == &c67x00->td_list)
> + td->next_td_addr = 0; /* Last td in list */
> +
> + c67x00_send_td(c67x00, td);
> + }
> +
> + c67x00_ll_husb_set_current_td(c67x00->sie, c67x00->td_base_addr);
> +}
> +
> +/* -------------------------------------------------------------------------- */
> +
> +/**
> + * c67x00_do_work - Schedulers state machine
> + */
> +static void c67x00_do_work(struct c67x00_hcd *c67x00)
> +{
> + spin_lock(&c67x00->lock);
> + /* Make sure all tds are processed */
> + if (!c67x00_all_tds_processed(c67x00))
> + goto out;
> +
> + c67x00_check_td_list(c67x00);
> +
> + /* no td's are being processed (current == 0)
> + * and all have been "checked" */
> + complete(&c67x00->endpoint_disable);
> +
> + if (!list_empty(&c67x00->td_list))
> + goto out;
> +
> + c67x00->current_frame = c67x00_get_current_frame_number(c67x00);
> + if (c67x00->current_frame == c67x00->last_frame)
> + goto out; /* Don't send tds in same frame */
> + c67x00->last_frame = c67x00->current_frame;
> +
> + /* If no urbs are scheduled, our work is done */
> + if (!c67x00->urb_count) {
> + c67x00_ll_hpi_disable_sofeop(c67x00->sie);
> + goto out;
> + }
> +
> + c67x00_fill_frame(c67x00);
> + if (!list_empty(&c67x00->td_list))
> + /* TD's have been added to the frame */
> + c67x00_send_frame(c67x00);
> +
> + out:
> + spin_unlock(&c67x00->lock);
> +}
> +
> +/* -------------------------------------------------------------------------- */
> +
> +static void c67x00_sched_tasklet(unsigned long __c67x00)
> +{
> + struct c67x00_hcd *c67x00 = (struct c67x00_hcd *)__c67x00;
> + c67x00_do_work(c67x00);
> +}
> +
> +void c67x00_sched_kick(struct c67x00_hcd *c67x00)
> +{
> + tasklet_hi_schedule(&c67x00->tasklet);
> +}
> +
> +int c67x00_sched_start_scheduler(struct c67x00_hcd *c67x00)
> +{
> + tasklet_init(&c67x00->tasklet, c67x00_sched_tasklet,
> + (unsigned long)c67x00);
> + return 0;
> +}
> +
> +void c67x00_sched_stop_scheduler(struct c67x00_hcd *c67x00)
> +{
> + tasklet_kill(&c67x00->tasklet);
> +}
> Index: linux-2.6/drivers/usb/c67x00/Makefile
> ===================================================================
> --- /dev/null
> +++ linux-2.6/drivers/usb/c67x00/Makefile
> @@ -0,0 +1,9 @@
> +#
> +# Makefile for Cypress C67X00 USB Controller
> +#
> +
> +ccflags-$(CONFIG_USB_DEBUG) += -DDEBUG
> +
> +obj-$(CONFIG_USB_C67X00_HCD) += c67x00.o
> +
> +c67x00-objs := c67x00-drv.o c67x00-ll-hpi.o c67x00-hcd.o c67x00-sched.o
> Index: linux-2.6/drivers/usb/Makefile
> ===================================================================
> --- linux-2.6.orig/drivers/usb/Makefile
> +++ linux-2.6/drivers/usb/Makefile
> @@ -17,6 +17,8 @@
> obj-$(CONFIG_USB_U132_HCD) += host/
> obj-$(CONFIG_USB_R8A66597_HCD) += host/
>
> +obj-$(CONFIG_USB_C67X00_HCD) += c67x00/
> +
> obj-$(CONFIG_USB_ACM) += class/
> obj-$(CONFIG_USB_PRINTER) += class/
>
> Index: linux-2.6/drivers/usb/c67x00/c67x00-drv.c
> ===================================================================
> --- linux-2.6.orig/drivers/usb/c67x00/c67x00-drv.c
> +++ linux-2.6/drivers/usb/c67x00/c67x00-drv.c
> @@ -41,6 +41,7 @@
> #include <linux/usb/c67x00.h>
>
> #include "c67x00.h"
> +#include "c67x00-hcd.h"
>
> static void c67x00_probe_sie(struct c67x00_sie *sie,
> struct c67x00_device *dev, int sie_num)
> @@ -51,6 +52,10 @@
> sie->mode = c67x00_sie_config(dev->pdata->sie_config, sie_num);
>
> switch (sie->mode) {
> + case C67X00_SIE_HOST:
> + c67x00_hcd_probe(sie);
> + break;
> +
> case C67X00_SIE_UNUSED:
> dev_info(sie_dev(sie),
> "Not using SIE %d as requested\n", sie->sie_num);
> @@ -66,6 +71,14 @@
>
> static void c67x00_remove_sie(struct c67x00_sie *sie)
> {
> + switch (sie->mode) {
> + case C67X00_SIE_HOST:
> + c67x00_hcd_remove(sie);
> + break;
> +
> + default:
> + break;
> + }
> }
>
> static irqreturn_t c67x00_irq(int irq, void *__dev)
> Index: linux-2.6/drivers/usb/c67x00/c67x00.h
> ===================================================================
> --- linux-2.6.orig/drivers/usb/c67x00/c67x00.h
> +++ linux-2.6/drivers/usb/c67x00/c67x00.h
> @@ -274,6 +274,15 @@
> void c67x00_ll_read_mem_le16(struct c67x00_device *dev, u16 addr,
> void *data, int len);
>
> +/* Host specific functions */
> +void c67x00_ll_set_husb_eot(struct c67x00_device *dev, u16 value);
> +void c67x00_ll_husb_reset(struct c67x00_sie *sie, int port);
> +void c67x00_ll_husb_set_current_td(struct c67x00_sie *sie, u16 addr);
> +u16 c67x00_ll_husb_get_current_td(struct c67x00_sie *sie);
> +u16 c67x00_ll_husb_get_frame(struct c67x00_sie *sie);
> +void c67x00_ll_husb_init_host_port(struct c67x00_sie *sie);
> +void c67x00_ll_husb_reset_port(struct c67x00_sie *sie, int port);
> +
> /* Called by c67x00_irq to handle lcp interrupts */
> void c67x00_ll_irq(struct c67x00_device *dev, u16 int_status);
>
> Index: linux-2.6/drivers/usb/c67x00/c67x00-ll-hpi.c
> ===================================================================
> --- linux-2.6.orig/drivers/usb/c67x00/c67x00-ll-hpi.c
> +++ linux-2.6/drivers/usb/c67x00/c67x00-ll-hpi.c
> @@ -297,6 +297,81 @@
> }
>
> /* -------------------------------------------------------------------------- */
> +/* Host specific functions */
> +
> +void c67x00_ll_set_husb_eot(struct c67x00_device *dev, u16 value)
> +{
> + mutex_lock(&dev->hpi.lcp.mutex);
> + hpi_write_word(dev, HUSB_pEOT, value);
> + mutex_unlock(&dev->hpi.lcp.mutex);
> +}
> +
> +static inline void c67x00_ll_husb_sie_init(struct c67x00_sie *sie)
> +{
> + struct c67x00_device *dev = sie->dev;
> + struct c67x00_lcp_int_data data;
> + int rc;
> +
> + rc = c67x00_comm_exec_int(dev, HUSB_SIE_INIT_INT(sie->sie_num), &data);
> + BUG_ON(rc); /* No return path for error code; crash spectacularly */
> +}
> +
> +void c67x00_ll_husb_reset(struct c67x00_sie *sie, int port)
> +{
> + struct c67x00_device *dev = sie->dev;
> + struct c67x00_lcp_int_data data;
> + int rc;
> +
> + data.regs[0] = 50; /* Reset USB port for 50ms */
> + data.regs[1] = port | (sie->sie_num << 1);
> + rc = c67x00_comm_exec_int(dev, HUSB_RESET_INT, &data);
> + BUG_ON(rc); /* No return path for error code; crash spectacularly */
> +}
> +
> +void c67x00_ll_husb_set_current_td(struct c67x00_sie *sie, u16 addr)
> +{
> + hpi_write_word(sie->dev, HUSB_SIE_pCurrentTDPtr(sie->sie_num), addr);
> +}
> +
> +u16 c67x00_ll_husb_get_current_td(struct c67x00_sie *sie)
> +{
> + return hpi_read_word(sie->dev, HUSB_SIE_pCurrentTDPtr(sie->sie_num));
> +}
> +
> +u16 c67x00_ll_husb_get_frame(struct c67x00_sie *sie)
> +{
> + return hpi_read_word(sie->dev, HOST_FRAME_REG(sie->sie_num));
> +}
> +
> +void c67x00_ll_husb_init_host_port(struct c67x00_sie *sie)
> +{
> + /* Set port into host mode */
> + hpi_set_bits(sie->dev, USB_CTL_REG(sie->sie_num), HOST_MODE);
> + c67x00_ll_husb_sie_init(sie);
> + /* Clear interrupts */
> + c67x00_ll_usb_clear_status(sie, HOST_STAT_MASK);
> + /* Check */
> + if (!(hpi_read_word(sie->dev, USB_CTL_REG(sie->sie_num)) & HOST_MODE))
> + dev_warn(sie_dev(sie),
> + "SIE %d not set to host mode\n", sie->sie_num);
> +}
> +
> +void c67x00_ll_husb_reset_port(struct c67x00_sie *sie, int port)
> +{
> + /* Clear connect change */
> + c67x00_ll_usb_clear_status(sie, PORT_CONNECT_CHANGE(port));
> +
> + /* Enable interrupts */
> + hpi_set_bits(sie->dev, HPI_IRQ_ROUTING_REG,
> + SOFEOP_TO_CPU_EN(sie->sie_num));
> + hpi_set_bits(sie->dev, HOST_IRQ_EN_REG(sie->sie_num),
> + SOF_EOP_IRQ_EN | DONE_IRQ_EN);
> +
> + /* Enable pull down transistors */
> + hpi_set_bits(sie->dev, USB_CTL_REG(sie->sie_num), PORT_RES_EN(port));
> +}
> +
> +/* -------------------------------------------------------------------------- */
>
> void c67x00_ll_irq(struct c67x00_device *dev, u16 int_status)
> {
> Index: linux-2.6/drivers/usb/host/Kconfig
> ===================================================================
> --- linux-2.6.orig/drivers/usb/host/Kconfig
> +++ linux-2.6/drivers/usb/host/Kconfig
> @@ -4,6 +4,19 @@
> comment "USB Host Controller Drivers"
> depends on USB
>
> +config USB_C67X00_HCD
> + tristate "Cypress C67x00 HCD support"
> + depends on USB
> + help
> + The Cypress C67x00 (EZ-Host/EZ-OTG) chips are dual-role
> + host/peripheral/OTG USB controllers.
> +
> + Enable this option to support this chip in host controller mode.
> + If unsure, say N.
> +
> + To compile this driver as a module, choose M here: the
> + module will be called c67x00.
> +
> config USB_EHCI_HCD
> tristate "EHCI HCD (USB 2.0) support"
> depends on USB && USB_ARCH_HAS_EHCI
>
> --
> Bye, Peter Korsgaard
>
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* [PATCH v3] sysdev,mv64x60: MV64x60 device bus
From: Remi Machet @ 2008-04-29 20:26 UTC (permalink / raw)
To: Paul Mackerras, Dale Farnsworth, Stephen Rothwell; +Cc: linuxppc-dev
Follow up of my email of 4/16/2008 titled "MV64x60 device bus".
For each mv64360 entry in the OpenFirmware database, add the
registration of an of_bus to take care of devices connected to
the MV64x60 asynchronous devices controller.
Signed-off-by: Remi Machet (rmachet@slac.stanford.edu)
---
Use the compatible field to detect devices to register (on Dale Farnsworth
suggestion).
Added __initdata to variable of_mv64x60_devices (thanks to Stephen Rothwell
for pointing that out).
arch/powerpc/sysdev/mv64x60_dev.c | 10 ++++++++++
1 files changed, 10 insertions(+)
diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c
index 41af122..c38695e 100644
--- a/arch/powerpc/sysdev/mv64x60_dev.c
+++ b/arch/powerpc/sysdev/mv64x60_dev.c
@@ -15,6 +15,7 @@
#include <linux/console.h>
#include <linux/mv643xx.h>
#include <linux/platform_device.h>
+#include <linux/of_platform.h>
#include <asm/prom.h>
@@ -25,6 +26,11 @@
* PowerPC of_platform_bus_type. They support platform_bus_type instead.
*/
+static struct of_device_id __initdata of_mv64x60_devices[] = {
+ { .compatible = "marvell,mv64306-devctrl", },
+ {}
+};
+
/*
* Create MPSC platform devices
*/
@@ -482,6 +488,10 @@ static int __init mv64x60_device_setup(void)
of_node_put(np);
}
+ /* Now add every node that is on the device bus (type is devicectrl */
+ for_each_compatible_node(np, NULL, "marvell,mv64360")
+ of_platform_bus_probe(np, of_mv64x60_devices, NULL);
+
return 0;
}
arch_initcall(mv64x60_device_setup);
^ permalink raw reply related
* Re: [PATCH 4/6] [POWERPC] QE: implement support for the GPIO LIB API
From: Timur Tabi @ 2008-04-29 20:29 UTC (permalink / raw)
To: Anton Vorontsov; +Cc: linuxppc-dev
In-Reply-To: <20080429190045.GD21203@polina.dev.rtsoft.ru>
Anton Vorontsov wrote:
> This is needed to access QE GPIOs via Linux GPIO API.
>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> ---
> Documentation/powerpc/booting-without-of.txt | 37 ++++---
> arch/powerpc/sysdev/qe_lib/Kconfig | 9 ++
> arch/powerpc/sysdev/qe_lib/Makefile | 1 +
> arch/powerpc/sysdev/qe_lib/gpio.c | 145 ++++++++++++++++++++++++++
> include/asm-powerpc/qe.h | 1 +
> 5 files changed, 180 insertions(+), 13 deletions(-)
> create mode 100644 arch/powerpc/sysdev/qe_lib/gpio.c
>
> diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
> index fc7a235..4fefc44 100644
> --- a/Documentation/powerpc/booting-without-of.txt
> +++ b/Documentation/powerpc/booting-without-of.txt
> @@ -1723,24 +1723,35 @@ platforms are moved over to use the flattened-device-tree model.
> information.
>
> Required properties:
> - - device_type : should be "par_io".
> + - #gpio-cells : should be "2".
> + - compatible : should be "fsl,<chip>-qe-pario-bank",
> + "fsl,mpc8323-qe-pario-bank".
> - reg : offset to the register set and its length.
> - - num-ports : number of Parallel I/O ports
> + - gpio-controller : node to identify gpio controllers.
>
> - Example:
> - par_io@1400 {
> - reg = <1400 100>;
> - #address-cells = <1>;
> - #size-cells = <0>;
> - device_type = "par_io";
> - num-ports = <7>;
> - ucc_pin@01 {
> - ......
> - };
> + For example, two QE Par I/O banks:
> + qe_pio_a: gpio-controller@1400 {
I think this change will break a number of boards, because a lot of them do this:
if ((np = of_find_node_by_name(NULL, "par_io")) != NULL) {
par_io_init(np);
So if you're going to change the par_io nodes, you need to change the code as well.
A patch that changes the documentation should also change the code. And if
you're code changes the device tree, it should also maintain compatibility for
older device trees.
> + #gpio-cells = <2>;
> + compatible = "fsl,mpc8360-qe-pario-bank",
> + "fsl,mpc8323-qe-pario-bank";
> + reg = <0x1400 0x18>;
> + gpio-controller;
> + };
>
> + qe_pio_e: gpio-controller@1460 {
> + #gpio-cells = <2>;
> + compatible = "fsl,mpc8360-qe-pario-bank",
> + "fsl,mpc8323-qe-pario-bank";
> + reg = <0x1460 0x18>;
> + gpio-controller;
> + };
>
> vi) Pin configuration nodes
>
> + NOTE: pin configuration nodes are obsolete. Usually, their existance
> + is an evidence of the firmware shortcomings. Such fixups are
> + better handled by the Linux board file, not the device tree.
You can't just delete the par_io documentation without updating the code and
planning for feature removal. Almost all of the existing code out there for QE
boards expects a par_io node, and the device trees still have them.
> +static int qe_gpio_get(struct gpio_chip *gc, unsigned int gpio)
> +{
> + struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
> + struct qe_pio_regs __iomem *regs = mm_gc->regs;
> + u32 pin_mask = 1 << (QE_PIO_PINS - 1 - gpio);
> +
> + return !!(in_be32(®s->cpdata) & pin_mask);
Do we need to do "!!"? I thought as long as the result was non-zero, it didn't
matter what the actual value is. "!!" converts non-zero to 1.
> +static int qe_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
> +{
> + struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
> + struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc);
> + unsigned long flags;
> +
> + spin_lock_irqsave(&qe_gc->lock, flags);
> +
> + __par_io_config_pin(mm_gc->regs, gpio, 2, 0, 0, 0);
No magic numbers, please.
> +void __init qe_add_gpiochips(void)
> +{
> + int ret;
> + struct device_node *np;
> +
> + for_each_compatible_node(np, NULL, "fsl,mpc8323-qe-pario-bank") {
> + struct qe_gpio_chip *qe_gc;
> + struct of_mm_gpio_chip *mm_gc;
> + struct of_gpio_chip *of_gc;
> + struct gpio_chip *gc;
> +
> + qe_gc = kzalloc(sizeof(*qe_gc), GFP_KERNEL);
> + if (!qe_gc) {
> + ret = -ENOMEM;
> + goto err;
> + }
> +
> + spin_lock_init(&qe_gc->lock);
> +
> + mm_gc = &qe_gc->mm_gc;
> + of_gc = &mm_gc->of_gc;
> + gc = &of_gc->gc;
> +
> + mm_gc->save_regs = qe_gpio_save_regs;
> + of_gc->gpio_cells = 2;
> + gc->ngpio = QE_PIO_PINS;
> + gc->direction_input = qe_gpio_dir_in;
> + gc->direction_output = qe_gpio_dir_out;
> + gc->get = qe_gpio_get;
> + gc->set = qe_gpio_set;
> +
> + ret = of_mm_gpiochip_add(np, mm_gc);
> + if (ret)
> + goto err;
> + }
> +
> + return;
> +err:
> + pr_err("%s: registration failed with status %d\n", np->full_name, ret);
> + of_node_put(np);
Memory leak here. If of_mm_gpiochip_add() fails or if the 2nd call to kzalloc()
fails, the already-allocated qe_gc objects won't be released.
--
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply
* MPC5200b problem configuring PSC6 as a serial port
From: Nick @ 2008-04-29 20:22 UTC (permalink / raw)
To: linuxppc-dev
Hi Everyone,
Has anyone setup and used the MPC5200b PSC6 port as a serial port? I am
having trouble getting mine to work. I am using PSC1, 2 and 3 already,
and they work fine. In my DTS file, I have PSC6 configured like this:
serial@2c00 { // PSC6
device_type = "serial";
compatible = "mpc5200b-psc-uart","mpc5200-psc-uart";
port-number = <5>;
reg = <2c00 100>;
interrupts = <2 4 0>.;
interrupt-parent = <&mpc5200_pic>;
};
Is there anything special I need to do to get this port working?
Thanks,
Nick
^ permalink raw reply
* Re: [PATCH v3] sysdev,mv64x60: MV64x60 device bus
From: Dale Farnsworth @ 2008-04-29 20:46 UTC (permalink / raw)
To: Remi Machet; +Cc: Stephen Rothwell, Paul Mackerras, linuxppc-dev
In-Reply-To: <1209500798.14407.32.camel@pcds-ts102.slac.stanford.edu>
On Tue, Apr 29, 2008 at 01:26:38PM -0700, Remi Machet wrote:
> Follow up of my email of 4/16/2008 titled "MV64x60 device bus".
> For each mv64360 entry in the OpenFirmware database, add the
> registration of an of_bus to take care of devices connected to
> the MV64x60 asynchronous devices controller.
>
> Signed-off-by: Remi Machet (rmachet@slac.stanford.edu)
Acked-by: Dale Farnsworth <dale@farnsworth.org>
^ 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